diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index d440a82..0934c49 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -43,7 +43,13 @@ pub enum Statement { pub type Block = Vec>; pub type ParamName = Rc; -pub type FormalParam = (ParamName, Option); + +#[derive(Debug, PartialEq, Clone)] +pub struct FormalParam { + pub name: ParamName, + pub default: Option, + pub anno: Option +} #[derive(Debug, PartialEq, Clone)] pub enum Declaration { diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 1706ef5..2c4d790 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -461,14 +461,16 @@ impl Parser { Ok(delimited!(self, LParen, formal_param, Comma, RParen)) } + //TODO needs to support default values #[recursive_descent_method] fn formal_param(&mut self) -> ParseResult { let name = self.identifier()?; - let ty = match self.token_handler.peek_kind() { + let anno = match self.token_handler.peek_kind() { Colon => Some(self.type_anno()?), _ => None }; - Ok((name, ty)) + let default = None; + Ok(FormalParam { name, anno, default }) } #[recursive_descent_method] @@ -1185,7 +1187,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, InvocationArgument}; + use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam}; use super::Statement::*; use super::Declaration::*; use super::Signature; @@ -1375,15 +1377,16 @@ mod parse_tests { parse_test!("fn a(b, c: Int): Int", AST(vec![Meta::new(Declaration( FuncSig(Signature { name: rc!(a), operator: false, params: vec![ - (rc!(b), None), (rc!(c), Some(ty!("Int"))) + FormalParam { name: rc!(b), anno: None, default: None }, + FormalParam { name: rc!(c), anno: Some(ty!("Int")), default: None } ], type_anno: Some(ty!("Int")) })))])); parse_test!("fn a(x) { x() }", AST(vec![Meta::new(Declaration( - FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, + FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))])); parse_test!("fn a(x) {\n x() }", AST(vec![Meta::new(Declaration( - FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, + FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))])); let multiline = r#" @@ -1392,7 +1395,7 @@ fn a(x) { } "#; parse_test!(multiline, AST(vec![Meta::new(Declaration( - FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, + FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))])); let multiline2 = r#" fn a(x) { @@ -1402,7 +1405,7 @@ fn a(x) { } "#; parse_test!(multiline2, AST(vec![Meta::new(Declaration( - FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, + FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None }, vec![exst!(s "x()")])))])); } @@ -1535,7 +1538,14 @@ fn a(x) { Meta::new(Declaration(Interface { name: rc!(Unglueable), signatures: vec![ - Signature { name: rc!(unglue), operator: false, params: vec![(rc!(a), Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })))], type_anno: None }, + Signature { + name: rc!(unglue), + operator: false, + params: vec![ + FormalParam { name: rc!(a), anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })), default: None } + ], + type_anno: None + }, Signature { name: rc!(mar), operator: false, params: vec![], type_anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })) }, ] })) @@ -1613,13 +1623,16 @@ fn a(x) { #[test] fn parsing_lambdas() { parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!( - Lambda { params: vec![(rc!(x), None)], type_anno: None, body: vec![exst!(s "x + 1")] } - ) + Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: vec![exst!(s "x + 1")] } + ) } parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![ exst!(Lambda { - params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)], + params: vec![ + FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None }, + FormalParam { name: rc!(y), anno: None, default: None } + ], type_anno: None, body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")] }) @@ -1627,8 +1640,10 @@ fn a(x) { parse_test!(r#"\(x){y}(1)"#, AST(vec![ exst!(Call { f: bx!(ex!(m - Lambda { - params: vec![(rc!(x), None)], + Lambda { + params: vec![ + FormalParam { name: rc!(x), anno: None, default: None } + ], type_anno: None, body: vec![exst!(s "y")] } )), @@ -1637,7 +1652,9 @@ fn a(x) { parse_test_wrap_ast! { r#"\(x: Int): String { "q" }"#, exst!(Lambda { - params: vec![(rc!(x), Some(ty!("Int")))], + params: vec![ + FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None }, + ], type_anno: Some(ty!("String")), body: vec![exst!(s r#""q""#)] }) @@ -1647,18 +1664,18 @@ fn a(x) { #[test] fn single_param_lambda() { parse_test_wrap_ast! { - r"\x { x + 10 }", + r"\x { x + 10 }", exst!(Lambda { - params: vec![(rc!(x), None)], + params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None, body: vec![exst!(s r"x + 10")] }) } parse_test_wrap_ast! { - r"\x: Nat { x + 10 }", + r"\x: Nat { x + 10 }", exst!(Lambda { - params: vec![(rc!(x), Some(ty!("Nat")))], + params: vec![FormalParam { name: rc!(x), anno: Some(ty!("Nat")), default: None }], type_anno: None, body: vec![exst!(s r"x + 10")] }) diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 4aff5be..03e8300 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -165,7 +165,7 @@ impl Expression { fn reduce_lambda(params: &Vec, body: &Block, symbol_table: &SymbolTable) -> Expr { Expr::Func(Func::UserDefined { name: None, - params: params.iter().map(|param| param.0.clone()).collect(), + params: params.iter().map(|param| param.name.clone()).collect(), body: reduce_block(body, symbol_table), }) } @@ -377,7 +377,7 @@ impl Declaration { name: name.clone(), func: Func::UserDefined { name: Some(name.clone()), - params: params.iter().map(|param| param.0.clone()).collect(), + params: params.iter().map(|param| param.name.clone()).collect(), body: reduce_block(&statements, symbol_table), } }, diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index 1c0e28b..b06edf0 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -169,9 +169,9 @@ impl SymbolTable { fn add_function_signature(&mut self, signature: &Signature, scope_name_stack: &mut Vec) -> Result<(), String> { let mut local_type_context = LocalTypeContext::new(); - let types = signature.params.iter().map(|param| match param { - (_, Some(type_identifier)) => Rc::new(format!("{:?}", type_identifier)), - (_, None) => local_type_context.new_universal_type() + let types = signature.params.iter().map(|param| match param.anno { + Some(ref type_identifier) => Rc::new(format!("{:?}", type_identifier)), + None => local_type_context.new_universal_type() }).collect(); self.add_new_symbol(&signature.name, scope_name_stack, SymbolSpec::Func(types)); Ok(()) diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 3f1d595..43e81ec 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -369,7 +369,7 @@ impl<'a> TypeContext<'a> { fn lambda(&mut self, params: &Vec, type_anno: &Option, _body: &Block) -> InferResult { let argument_types: InferResult> = params.iter().map(|param: &FormalParam| { - if let (_, Some(type_identifier)) = param { + if let FormalParam { anno: Some(type_identifier), .. } = param { self.get_type_from_name(type_identifier) } else { Ok(Type::Var(self.fresh_type_variable()))