From 08ca48b2ba268c88d4b03b3ba37d9ecb0cd70a53 Mon Sep 17 00:00:00 2001 From: greg Date: Sun, 4 Mar 2018 02:11:22 -0800 Subject: [PATCH] lambdas --- source_files/test.schala | 7 ++++++ src/schala_lang/parsing.rs | 48 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/source_files/test.schala b/source_files/test.schala index d223eff..d9ab285 100644 --- a/source_files/test.schala +++ b/source_files/test.schala @@ -96,3 +96,10 @@ fn main() { } } + + +# lambdas +# +|x,y| { }() #is probably fine +const a = |x: Type, y|: RetType { } +const a: X -> Y -> Z = |x,y| { } diff --git a/src/schala_lang/parsing.rs b/src/schala_lang/parsing.rs index b5b713d..36192ef 100644 --- a/src/schala_lang/parsing.rs +++ b/src/schala_lang/parsing.rs @@ -54,7 +54,9 @@ expression := precedence_expr type_anno+ precedence_expr := prefix_expr prefix_expr := prefix_op primary prefix_op := '+' | '-' | '!' | '~' -primary := literal | paren_expr | if_expr | match_expr | for_expr | identifier_expr +primary := literal | paren_expr | if_expr | match_expr | for_expr | identifier_expr | curly_brace_expr +curly_brace_expr := lambda_expr | anonymous_struct //TODO +lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement)* '}' paren_expr := LParen paren_inner RParen paren_inner := (expression ',')* identifier_expr := named_struct | call_expr | index_expr | IDENTIFIER @@ -63,6 +65,7 @@ literal := 'true' | 'false' | number_literal | STR_LITERAL named_struct := IDENTIFIER record_block record_block := '{' (record_entry, ',')* | '}' //TODO support anonymus structs, update syntax record_entry := IDENTIFIER ':' expression +anonymous_struct := TODO if_expr := 'if' expression block else_clause else_clause := ε | 'else' block @@ -246,7 +249,11 @@ pub enum ExpressionType { }, IfExpression(Box, Vec, Option>), MatchExpression(Box, Vec), - ForExpression + ForExpression, + Lambda { + params: Vec, + body: Vec, + }, } #[derive(Debug, PartialEq, Clone)] @@ -578,6 +585,7 @@ impl Parser { parse_method!(primary(&mut self) -> ParseResult { match self.peek() { + LCurlyBrace => self.curly_brace_expr(), LParen => self.paren_expr(), Keyword(Kw::If) => self.if_expr(), Keyword(Kw::Match) => self.match_expr(), @@ -587,6 +595,28 @@ impl Parser { } }); + parse_method!(curly_brace_expr(&mut self) -> ParseResult { + self.lambda_expr() + }); + + parse_method!(lambda_expr(&mut self) -> ParseResult { + expect!(self, LCurlyBrace, "{"); + let params = delimited!(self, Pipe, '|', formal_param, Comma, Pipe, '|'); + 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 + }); + parse_method!(paren_expr(&mut self) -> ParseResult { use self::ExpressionType::*; let old_struct_value = self.restrictions.no_struct_literal; @@ -1149,4 +1179,18 @@ fn a(x) { name: rc!(Yolo), params: vec![ty!("a")] })]))])); } + + #[test] + fn parsing_lambdas() { + parse_test!("{|x| x + 1}", AST(vec![ + exprstatement!(Lambda { params: vec![(rc!(x), None)], body: vec![exprstatement!(binexp!("+", val!("x"), IntLiteral(1)))]}) + ])); + + parse_test!("{ |x: Int, y| a;b;c;}", AST(vec![ + exprstatement!(Lambda { + params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)], + body: vec![exprstatement!(val!("a")), exprstatement!(val!("b")), exprstatement!(val!("c"))] + }) + ])); + } }