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()))