diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 5fa1524..04ee0b1 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -620,7 +620,7 @@ impl Parser { fn call_expr(&mut self) -> ParseResult { let mut expr = self.index_expr()?; while let LParen = self.token_handler.peek_kind() { - let arguments = delimited!(self, LParen, expression, Comma, RParen); + let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen); let arguments = arguments.into_iter().map(|s| Meta::new(s)).collect(); expr = Expression(ExpressionKind::Call { f: bx!(expr.into()), arguments }, None); //TODO none is incorrect } @@ -629,8 +629,28 @@ impl Parser { } #[recursive_descent_method] - fn invocation_argument(&mut self) -> ParseResult { - panic!() + fn invocation_argument(&mut self) -> ParseResult { + Ok(match self.token_handler.peek_kind() { + Underscore => { + self.token_handler.next(); + InvocationArgument::Ignored + }, + Identifier(s) => { + self.token_handler.next(); + match self.token_handler.peek_kind() { + Operator(ref op) if **op == "=" => { + self.token_handler.next(); + let expr = self.expression()?; + InvocationArgument::Keyword { name: s.clone(), expr } + }, + _ => { + let expr = self.expression()?; + InvocationArgument::Positional(expr) + } + } + }, + _ => InvocationArgument::Positional(self.expression()?) + }) } #[recursive_descent_method] @@ -1159,7 +1179,7 @@ mod parse_tests { use super::tokenize; use super::ParseResult; use crate::builtin::{PrefixOp, BinOp}; - use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody}; + use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument}; use super::Statement::*; use super::Declaration::*; use super::Signature; @@ -1207,6 +1227,10 @@ mod parse_tests { }; } + macro_rules! inv { + ($expr_type:expr) => { Meta::new(InvocationArgument::Positional(ex!($expr_type))) } + } + macro_rules! binexp { ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression($lhs, None).into()), bx!(Expression($rhs, None).into())) } } @@ -1339,7 +1363,7 @@ mod parse_tests { parse_test!("oi()", AST(vec![exst!(Call { f: bx!(ex!(m val!("oi"))), arguments: vec![] })])); parse_test!("oi(a, 2 + 2)", AST(vec![exst!(Call { f: bx!(ex!(m val!("oi"))), - arguments: vec![ex!(val!("a")).into(), ex!(binexp!("+", NatLiteral(2), NatLiteral(2))).into()] + arguments: vec![inv!(val!("a")).into(), inv!(binexp!("+", NatLiteral(2), NatLiteral(2))).into()] })])); parse_error!("a(b,,c)"); @@ -1602,7 +1626,7 @@ fn a(x) { type_anno: None, body: vec![exst!(s "y")] } )), - arguments: vec![ex!(NatLiteral(1)).into()] })])); + arguments: vec![inv!(NatLiteral(1)).into()] })])); parse_test_wrap_ast! { r#"\(x: Int): String { "q" }"#, @@ -1644,7 +1668,7 @@ fn a(x) { exst! { Call { f: bx!(ex!(m Call { f: bx!(ex!(m val!("wahoo"))), arguments: vec![] })), - arguments: vec![ex!(s "3").into()], + arguments: vec![inv!(NatLiteral(3)).into()], } } ]) diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 022b15a..1ae39a2 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -118,6 +118,17 @@ fn reduce_block(block: &Block, symbol_table: &SymbolTable) -> Vec { block.iter().map(|stmt| stmt.node().reduce(symbol_table)).collect() } +impl InvocationArgument { + fn reduce(&self, symbol_table: &SymbolTable) -> Expr { + use crate::ast::InvocationArgument::*; + match self { + Positional(ex) => ex.reduce(symbol_table), + Keyword { .. } => Expr::UnimplementedSigilValue, + Ignored => Expr::UnimplementedSigilValue, + } + } +} + impl Expression { fn reduce(&self, symbol_table: &SymbolTable) -> Expr { use crate::ast::ExpressionKind::*; diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index d97898b..3f1d595 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -289,6 +289,14 @@ impl<'a> TypeContext<'a> { Ok(ty!(Unit)) } + fn invoc(&mut self, invoc: &InvocationArgument) -> InferResult { + use InvocationArgument::*; + match invoc { + Positional(expr) => self.expr(expr), + _ => Ok(ty!(Nat)) //TODO this is wrong + } + } + fn expr(&mut self, expr: &Expression) -> InferResult { match expr { Expression(expr_type, Some(anno)) => { @@ -376,9 +384,9 @@ impl<'a> TypeContext<'a> { Ok(ty!(argument_types, ret_type)) } - fn call(&mut self, f: &Expression, args: &Vec>) -> InferResult { + fn call(&mut self, f: &Expression, args: &Vec>) -> InferResult { let tf = self.expr(f)?; - let arg_types: InferResult> = args.iter().map(|ex| self.expr(ex.node())).collect(); + let arg_types: InferResult> = args.iter().map(|ex| self.invoc(ex.node())).collect(); let arg_types = arg_types?; self.handle_apply(tf, arg_types) }