diff --git a/examples/ackermann.sb b/examples/ackermann.sb index 64ffc09..c07a96f 100644 --- a/examples/ackermann.sb +++ b/examples/ackermann.sb @@ -4,7 +4,7 @@ fn main() { println(ackermann(m, n)) } -fn ackermann(m, n) { +fn ackermann(m int, n int) { if m == 0 { return n + 1 } else if n == 0 { diff --git a/examples/fib.sb b/examples/fib.sb index 683b902..7f7011a 100644 --- a/examples/fib.sb +++ b/examples/fib.sb @@ -3,7 +3,7 @@ fn main() { println(fib(num)) } -fn fib(n) { +fn fib(n int) { if 1 >= n { return n } diff --git a/examples/greeter.sb b/examples/greeter.sb index c27bb4e..c2597b8 100644 --- a/examples/greeter.sb +++ b/examples/greeter.sb @@ -2,6 +2,6 @@ fn main() { println(greet("World")) } -fn greet(name) { +fn greet(name string) { return "Hello " + name } diff --git a/lib/stdio.sb b/lib/stdio.sb index d135d76..25fa46e 100644 --- a/lib/stdio.sb +++ b/lib/stdio.sb @@ -1,16 +1,16 @@ // Raw wrapper around _printf builtin function. // Writes the given content to stdout -fn print(msg) { +fn print(msg string) { _printf(msg) } // Like print(), but with an extra newline ('\n') character -fn println(msg) { +fn println(msg string) { print(msg + "\n") } // Prints the size of an array -fn len(arr) { +fn len(arr int[]) { let c = 0 while arr[c] { c = c + 1 @@ -21,7 +21,7 @@ fn len(arr) { // Reverses an array // TODO: fix me! -fn rev(arr) { +fn rev(arr int[]) { let l = len(arr) let new_arr = [] diff --git a/src/main.rs b/src/main.rs index 03f0b03..b44b359 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,6 +67,7 @@ fn main() -> Result<(), String> { let tokens = lexer::tokenize(&contents); let program = parser::parse(tokens, Some(contents))?; + dbg!(&program); let output = generator::js::JsGenerator::generate(program); let mut file = std::fs::File::create(out_file).expect("create failed"); diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index fcf1179..507b1d6 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -32,6 +32,27 @@ pub struct Function { #[derive(Debug, Eq, PartialEq)] pub struct Variable { pub name: String, + pub ty: Option, +} + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + Int, + Str, + Bool, + Array(Box), +} + +impl TryFrom for Type { + type Error = String; + fn try_from(s: String) -> Result { + match s.as_ref() { + "int" => Ok(Self::Int), + "string" => Ok(Self::Str), + "bool" => Ok(Self::Bool), + _ => Err("Expected Type".into()), + } + } } #[derive(Debug, Eq, PartialEq)] diff --git a/src/parser/rules.rs b/src/parser/rules.rs index 3f0998a..4fce8ed 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -58,9 +58,7 @@ impl Parser { let arguments: Vec = match self.peek()? { t if t.kind == TokenKind::BraceClose => Vec::new(), - _ => self - .parse_arguments() - .expect("Failed to parse function arguments"), + _ => self.parse_arguments()?, }; self.match_token(TokenKind::BraceClose)?; @@ -82,7 +80,10 @@ impl Parser { TokenKind::Comma => { continue; } - TokenKind::Identifier(name) => args.push(Variable { name: name }), + TokenKind::Identifier(name) => args.push(Variable { + name: name, + ty: Some(self.parse_type()?), + }), _ => return Err(self.make_error(TokenKind::Identifier("Argument".into()), next)), } } @@ -90,6 +91,21 @@ impl Parser { Ok(args) } + fn parse_type(&mut self) -> Result { + let next = self.next()?; + let typ = match next.kind { + TokenKind::Identifier(t) => Type::try_from(t), + _ => Err("Expected type".into()), + }?; + if let Ok(_) = self.peek_token(TokenKind::SquareBraceOpen) { + self.drop(1); + self.match_token(TokenKind::SquareBraceClose)?; + Ok(Type::Array(Box::new(typ))) + } else { + Ok(typ) + } + } + fn parse_statement(&mut self) -> Result { let token = self.peek()?; let state = match &token.kind { @@ -333,12 +349,12 @@ impl Parser { self.match_keyword(Keyword::Let)?; match (self.next()?.kind, self.peek()?.kind) { (TokenKind::Identifier(name), TokenKind::SemiColon) => { - Ok(Statement::Declare(Variable { name }, None)) + Ok(Statement::Declare(Variable { name, ty: None }, None)) } (TokenKind::Identifier(name), TokenKind::Assign) => { self.drop(1); let exp = self.parse_expression().ok(); - Ok(Statement::Declare(Variable { name }, exp)) + Ok(Statement::Declare(Variable { name, ty: None }, exp)) } other => Err(format!("Expected identifier, found {:?}", other)), } diff --git a/src/parser/tests.rs b/src/parser/tests.rs index c2b099c..74c0c53 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -120,7 +120,7 @@ fn test_parse_variable_declaration_added() { #[test] fn test_parse_function_with_args() { let raw = " - fn main(foo) { + fn main(foo int) { return foo } "; @@ -132,7 +132,7 @@ fn test_parse_function_with_args() { #[test] fn test_parse_function_call() { let raw = " - fn main(foo) { + fn main(foo int) { foo() } @@ -184,7 +184,7 @@ fn test_parse_nexted_function_call() { fib(fib(2), 2) } - fn fib(n) { + fn fib(n int) { return 2 } "; @@ -244,7 +244,7 @@ fn test_parse_compound_ops_with_strings() { #[test] fn test_parse_compound_ops_with_identifier() { let raw = " - fn main(n) { + fn main(n int) { return 2 * n } "; @@ -256,7 +256,7 @@ fn test_parse_compound_ops_with_identifier() { #[test] fn test_parse_compound_ops_with_identifier_first() { let raw = " - fn main(n) { + fn main(n int) { return n * 2 } "; @@ -268,7 +268,7 @@ fn test_parse_compound_ops_with_identifier_first() { #[test] fn test_parse_compound_ops_return() { let raw = " - fn main(n) { + fn main(n int) { return 2 * n } "; @@ -280,7 +280,7 @@ fn test_parse_compound_ops_return() { #[test] fn test_parse_basic_conditional() { let raw = " - fn main(n) { + fn main(n int) { if n { return n } @@ -294,7 +294,7 @@ fn test_parse_basic_conditional() { #[test] fn test_parse_basic_conditional_with_multiple_statements() { let raw = " - fn main(n) { + fn main(n int) { if n { let x = 2 * n return x @@ -309,7 +309,7 @@ fn test_parse_basic_conditional_with_multiple_statements() { #[test] fn test_parse_conditional_else_if_branch() { let raw = " - fn main(n) { + fn main(n int) { if n > 10 { let x = 2 * n return x @@ -326,7 +326,7 @@ fn test_parse_conditional_else_if_branch() { #[test] fn test_parse_conditional_multiple_else_if_branch_branches() { let raw = " - fn main(n) { + fn main(n int) { if n > 10 { let x = 2 * n return x @@ -345,7 +345,7 @@ fn test_parse_conditional_multiple_else_if_branch_branches() { #[test] fn test_parse_conditional_else_branch() { let raw = " - fn main(n) { + fn main(n int) { if n > 10 { let x = 2 * n return x @@ -362,7 +362,7 @@ fn test_parse_conditional_else_branch() { #[test] fn test_parse_conditional_elseif_else_branch() { let raw = " - fn main(n) { + fn main(n int) { if n > 10 { let x = 2 * n return x @@ -383,7 +383,7 @@ fn test_parse_conditional_elseif_else_branch() { #[test] fn test_int_array() { let raw = " - fn main(n) { + fn main(n int) { let arr = [1, 2, 3] return arr } @@ -396,7 +396,7 @@ fn test_int_array() { #[test] fn test_string_array() { let raw = " - fn main(n) { + fn main(n int) { return [\"Foo\", \"Bar\", \"Baz\"] } "; @@ -533,7 +533,7 @@ fn test_uninitialized_variables() { #[test] fn test_function_call_math() { let raw = " - fn main(m) { + fn main(m int) { main(m - 1) } "; @@ -545,7 +545,7 @@ fn test_function_call_math() { #[test] fn test_function_multiple_args() { let raw = " - fn main(m, n) { + fn main(m int, n int) { main(m, n) } ";