[fine] Environments for functions

Fun times.
This commit is contained in:
John Doty 2024-01-07 08:09:43 -08:00
parent 308114f8cf
commit efd0685f41
3 changed files with 81 additions and 3 deletions

View file

@ -120,7 +120,7 @@ impl<'a> std::ops::IndexMut<TreeRef> 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) {

View file

@ -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<Type> {
match self.types.borrow().get(&t) {
None => (),
@ -553,7 +592,16 @@ impl<'a> Semantics<'a> {
fn type_of_type_expr(&self, tree: &Tree) -> Option<Type> {
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<Type> {

View file

@ -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