diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 4d04560..973389d 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -111,6 +111,7 @@ pub enum ExpressionType { }, Lambda { params: Vec, + type_anno: Option, body: Block, }, ListLiteral(Vec), diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 7bce092..8e2eba8 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -188,7 +188,7 @@ typed_identifier := IDENTIFIER type_anno func_declaration := func_signature func_body func_body := ε | nonempty_func_body nonempty_func_body := '{' (statement delimiter)* '}' -func_signature := 'fn' func_name formal_param_list func_body +func_signature := 'fn' func_name formal_param_list type_anno+ func_name := IDENTIFIER | operator formal_param_list := '(' (formal_param ',')* ')' formal_param := IDENTIFIER type_anno+ @@ -227,7 +227,7 @@ primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_e /* Primary Expressions */ list_expr := '[' (expression, ',')* ']' -lambda_expr := '\' formal_param_list nonempty_func_body +lambda_expr := '\' formal_param_list type_anno+ nonempty_func_body paren_expr := LParen paren_inner RParen paren_inner := (expression ',')* identifier_expr := named_struct | IDENTIFIER @@ -639,22 +639,12 @@ impl Parser { fn lambda_expr(&mut self) -> ParseResult { expect!(self, Backslash); let params = self.formal_param_list()?; //TODO make this allow some more concise syntaxes + let type_anno = match self.peek() { + Colon => Some(self.type_anno()?), + _ => None, + }; let body = self.nonempty_func_body()?; - /* - let mut body = Vec::new(); - loop { - match self.peek() { - EOF | RCurlyBrace => break, - Newline | Semicolon => { - self.next(); - continue; - }, - _ => body.push(self.statement()?), - } - } - expect!(self, RCurlyBrace); - */ - Ok(Expression(ExpressionType::Lambda { params, body }, None)) //TODO need to handle types somehow + Ok(Expression(ExpressionType::Lambda { params, type_anno, body }, None)) //TODO need to handle types somehow } #[recursive_descent_method] @@ -1483,20 +1473,36 @@ fn a(x) { #[test] fn parsing_lambdas() { parse_test! { r#"\(x) { x + 1}"#, single_expr!( - Lambda { params: vec![(rc!(x), None)], body: vec![exst!("+", val!("x"), NatLiteral(1))] } + Lambda { params: vec![(rc!(x), None)], type_anno: None, body: vec![exst!("+", val!("x"), NatLiteral(1))] } ) } parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![ exprstatement!(Lambda { params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)], + type_anno: None, body: vec![exst!(val!("a")), exst!(val!("b")), exst!(val!("c"))] }) ])); parse_test!(r#"\(x){y}(1)"#, AST(vec![ exprstatement!(Call { f: bx!(ex!( - Lambda { params: vec![(rc!(x), None)], body: vec![exprstatement!(val!("y"))] })), + Lambda { + params: vec![(rc!(x), None)], + type_anno: None, + body: vec![exprstatement!(val!("y"))] } + )), arguments: vec![ex!(NatLiteral(1))] })])); + + parse_test! { + r#"\(x: Int): String { "q" }"#, + AST(vec![ + exprstatement!(Lambda { + params: vec![(rc!(x), Some(ty!("Int")))], + type_anno: Some(ty!("String")), + body: vec![exprstatement!(StringLiteral(rc!(q)))] + }) + ]) + } } #[test]