diff --git a/fine/src/parser.rs b/fine/src/parser.rs index 802657ad..13cdd620 100644 --- a/fine/src/parser.rs +++ b/fine/src/parser.rs @@ -120,7 +120,7 @@ impl<'a> std::ops::IndexMut for SyntaxTree<'a> { pub enum TreeKind { Error, File, - FunDecl, + FunctionDecl, ParamList, Parameter, TypeExpression, @@ -488,7 +488,7 @@ fn function(p: &mut CParser) { block(p); } - p.end(m, TreeKind::FunDecl); + p.end(m, TreeKind::FunctionDecl); } fn param_list(p: &mut CParser) { diff --git a/fine/src/semantics.rs b/fine/src/semantics.rs index 40138628..af3a4598 100644 --- a/fine/src/semantics.rs +++ b/fine/src/semantics.rs @@ -369,6 +369,7 @@ impl<'a> Semantics<'a> { let result = match tree.kind { TreeKind::LetStatement => self.environment_of_let(parent, tree), + TreeKind::FunctionDecl => self.environment_of_func(parent, tree), // TODO: MORE Things that introduce an environment! _ => parent, @@ -404,6 +405,44 @@ impl<'a> Semantics<'a> { EnvironmentRef::new(environment) } + fn environment_of_func(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef { + let Some(param_list) = tree.nth_tree(2) else { + return parent; // SE + }; + let param_list = &self.syntax_tree[param_list]; + if param_list.kind != TreeKind::ParamList { + return parent; // SE + } + + let mut environment = Environment::new(Some(parent)); + for child in param_list.children.iter() { + let Child::Tree(ct) = child else { + continue; + }; + let param = &self.syntax_tree[*ct]; + if param.kind != TreeKind::Parameter { + continue; + } + + let Some(param_name) = param.nth_token(0) else { + continue; + }; + + let declaration_type = if let Some(type_expression) = param.nth_tree(2) { + self.type_of(type_expression) + .expect("the type expression should yield *some* type here") + } else { + Type::Error + }; + + environment + .declarations + .insert(param_name.as_str().into(), Declaration { declaration_type }); + } + + EnvironmentRef::new(environment) + } + pub fn type_of(&self, t: TreeRef) -> Option { match self.types.borrow().get(&t) { None => (), @@ -553,7 +592,16 @@ impl<'a> Semantics<'a> { fn type_of_type_expr(&self, tree: &Tree) -> Option { assert_eq!(tree.kind, TreeKind::TypeExpression); - Some(Type::Error) + + // TODO: This will *clearly* need to get better. + let token = tree.nth_token(0)?; + match token.as_str() { + "f64" => Some(Type::F64), + "string" => Some(Type::String), + "bool" => Some(Type::Bool), + "()" => Some(Type::Nothing), + _ => Some(Type::Error), + } } fn type_of_block(&self, tree: &Tree) -> Option { diff --git a/fine/tests/expression/argument.fine b/fine/tests/expression/argument.fine new file mode 100644 index 00000000..bf9de0b8 --- /dev/null +++ b/fine/tests/expression/argument.fine @@ -0,0 +1,30 @@ +// @concrete: +// | File +// | FunctionDecl +// | Fun:'"fun"' +// | Identifier:'"foo"' +// | ParamList +// | LeftParen:'"("' +// | Parameter +// | Identifier:'"x"' +// | Colon:'":"' +// | TypeExpression +// | Identifier:'"f64"' +// | RightParen:'")"' +// | Block +// | LeftBrace:'"{"' +// | ExpressionStatement +// | BinaryExpression +// | Identifier +// | Identifier:'"x"' +// | Plus:'"+"' +// | LiteralExpression +// | Number:'"7"' +// | RightBrace:'"}"' +// | + +fun foo(x: f64) { + x + 7 +} + +// @type: 613 f64