diff --git a/fine/src/semantics.rs b/fine/src/semantics.rs index 561fb9fe..a9aa72cc 100644 --- a/fine/src/semantics.rs +++ b/fine/src/semantics.rs @@ -60,6 +60,7 @@ impl fmt::Display for Error { pub struct FieldDecl { pub name: Rc, pub field_type: Type, + pub declaration: TreeRef, } pub struct MethodDecl { @@ -228,12 +229,11 @@ impl ExternalFunctionId { pub enum Declaration { Variable { - declaration_type: Type, + declaration: TreeRef, location: Location, index: usize, }, Function { - declaration_type: Type, declaration: TreeRef, //? }, ExternFunction { @@ -241,7 +241,6 @@ pub enum Declaration { id: ExternalFunctionId, }, Class { - declaration_type: Type, declaration: TreeRef, //? }, } @@ -292,15 +291,15 @@ impl Environment { }) } - pub fn insert(&mut self, token: &Token, t: Type) -> Option { + pub fn insert(&mut self, token: &Token, t: TreeRef) -> Option { self.insert_name(token.as_str().into(), t) } - pub fn insert_name(&mut self, name: Box, t: Type) -> Option { + pub fn insert_name(&mut self, name: Box, t: TreeRef) -> Option { let result = self.declarations.insert( name, Declaration::Variable { - declaration_type: t, + declaration: t, location: self.location, index: self.next_index, }, @@ -593,7 +592,7 @@ impl<'a> Semantics<'a> { } let tree = &self.syntax_tree[t]; - //eprintln!(">>> environment_of => {tree:?}"); + eprintln!(">>> environment_of => {tree:?}"); let parent = match self.logical_parents[t.index()] { Some(t) => self.environment_of(t), @@ -614,7 +613,7 @@ impl<'a> Semantics<'a> { }; self.environments.borrow_mut()[t.index()] = Incremental::Complete(result.clone()); - //eprintln!("<<< environment_of => {tree:?}"); + eprintln!("<<< environment_of => {tree:?}"); result } @@ -631,10 +630,7 @@ impl<'a> Semantics<'a> { let existing = environment.declarations.insert( name.as_str().into(), - Declaration::Function { - declaration_type: self.type_of(*t), - declaration: *t, - }, + Declaration::Function { declaration: *t }, ); if existing.is_some() { self.report_error_tree( @@ -663,10 +659,7 @@ impl<'a> Semantics<'a> { continue; }; - let declaration = Declaration::Function { - declaration_type: self.type_of(*t), - declaration: *t, - }; + let declaration = Declaration::Function { declaration: *t }; Some(("function", name, declaration)) } TreeKind::ClassDecl => { @@ -674,10 +667,7 @@ impl<'a> Semantics<'a> { continue; }; - let declaration = Declaration::Class { - declaration_type: self.type_of(*t), - declaration: *t, - }; + let declaration = Declaration::Class { declaration: *t }; Some(("class", name, declaration)) } _ => None, @@ -707,26 +697,11 @@ impl<'a> Semantics<'a> { return parent; // Error is already reported? }; - let declaration_type = match tree.nth_tree(3) { - Some(expr) => self.type_of(expr), - - // The syntax error should already have been reported, so we'll - // stick with error type here. (But bind the name, because we see - // it!) - None => Type::Error, + let Some(declaration) = tree.nth_tree(3) else { + return parent; }; - let declaration_type = match declaration_type { - Type::Method(..) => { - let start = name.start; - let end = name.start + name.as_str().len(); - self.report_error_span(start, end, "methods cannot be assigned to variables"); - Type::Error - } - _ => declaration_type, - }; - - eprintln!("{} => {}", name, declaration_type); + // eprintln!("{} => {}", name, declaration_type); let location = match parent.location { Location::Local => Location::Local, @@ -736,7 +711,7 @@ impl<'a> Semantics<'a> { }; let mut environment = Environment::new(Some(parent), location); - environment.insert(name, declaration_type); + environment.insert(name, declaration); EnvironmentRef::new(environment) } @@ -753,8 +728,7 @@ impl<'a> Semantics<'a> { match param.kind { TreeKind::SelfParameter => { let param_name = param.nth_token(0).unwrap(); - let declaration_type = self.type_of(*ct); - if environment.insert(param_name, declaration_type).is_some() { + if environment.insert(param_name, *ct).is_some() { self.report_error_tree( param, format!("duplicate definition of self parameter"), @@ -771,8 +745,7 @@ impl<'a> Semantics<'a> { continue; }; - let declaration_type = self.type_of(*ct); - if environment.insert(param_name, declaration_type).is_some() { + if environment.insert(param_name, *ct).is_some() { self.report_error_tree( param, format!("duplicate definition of parameter '{param_name}'"), @@ -786,27 +759,31 @@ impl<'a> Semantics<'a> { EnvironmentRef::new(environment) } - fn environment_of_for(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef { - let Some(id) = tree.nth_token(1) else { - return parent; - }; + fn environment_of_for(&self, parent: EnvironmentRef, _tree: &Tree) -> EnvironmentRef { + // let Some(id) = tree.nth_token(1) else { + // return parent; + // }; - let Some(enumerable) = tree.nth_tree(3) else { - return parent; - }; + // let Some(enumerable) = tree.nth_tree(3) else { + // return parent; + // }; - let item_type = match self.type_of(enumerable) { - Type::Error => Type::Error, - Type::List(x) => (&*x).clone(), - _ => { - self.report_error_tree_ref(enumerable, "this expression is not enumerable"); - Type::Error - } - }; + // let item_type = match self.type_of(enumerable) { + // Type::Error => Type::Error, + // Type::List(x) => (&*x).clone(), + // _ => { + // self.report_error_tree_ref(enumerable, "this expression is not enumerable"); + // Type::Error + // } + // }; - let mut environment = Environment::new(Some(parent), Location::Local); - environment.insert(id, item_type); - EnvironmentRef::new(environment) + // TODO: This is broken, need a sub-tree to point the decl at that + // has the right type. + // + // let mut environment = Environment::new(Some(parent), Location::Local); + // environment.insert(id, item_type); + // EnvironmentRef::new(environment) + parent } fn environment_of_member_access(&self, tree: &Tree) -> EnvironmentRef { @@ -871,6 +848,7 @@ impl<'a> Semantics<'a> { .unwrap_or(Type::Error); fields.push(FieldDecl { name: field_name.as_str().into(), + declaration: field, field_type, }); } @@ -913,7 +891,7 @@ impl<'a> Semantics<'a> { (&*field.name).into(), Declaration::Variable { index, - declaration_type: field.field_type.clone(), + declaration: field.declaration, location: Location::Slot, }, ); @@ -923,7 +901,6 @@ impl<'a> Semantics<'a> { static_env.declarations.insert( (&*method.name).into(), Declaration::Function { - declaration_type: method.decl_type.clone(), declaration: method.declaration, }, ) @@ -931,7 +908,6 @@ impl<'a> Semantics<'a> { env.declarations.insert( (&*method.name).into(), Declaration::Function { - declaration_type: method.decl_type.clone(), declaration: method.declaration, }, ) @@ -1010,7 +986,7 @@ impl<'a> Semantics<'a> { } let tree = &self.syntax_tree[t]; - // eprintln!("type_of => {tree:?}"); + eprintln!(">>> type_of => {tree:?}"); let result = match tree.kind { TreeKind::Error => Some(Type::Error), @@ -1020,6 +996,7 @@ impl<'a> Semantics<'a> { TreeKind::Block => self.type_of_block(tree), TreeKind::CallExpression => self.type_of_call(tree), TreeKind::ClassDecl => self.type_of_class_decl(t, tree), + TreeKind::FieldDecl => self.type_of_field_decl(tree), TreeKind::ConditionalExpression => self.type_of_conditional(tree), TreeKind::ExpressionStatement => self.type_of_expression_statement(tree), TreeKind::FieldValue => self.type_of_field_value(t, tree), @@ -1049,6 +1026,8 @@ impl<'a> Semantics<'a> { // NOTE: These return `None` if they encounter some problem. let result = result.unwrap_or(Type::Error); self.types.borrow_mut()[t.index()] = Incremental::Complete(result.clone()); + eprintln!("<<< type_of => {tree:?}"); + result } @@ -1236,9 +1215,9 @@ impl<'a> Semantics<'a> { _ => { let environment = self.environment_of(t); match environment.bind(token) { - Some(Declaration::Class { - declaration_type, .. - }) => Some(declaration_type.clone()), + Some(Declaration::Class { declaration, .. }) => { + Some(self.type_of(*declaration)) + } Some(Declaration::Variable { .. }) => { self.report_error_tree( tree, @@ -1523,19 +1502,13 @@ impl<'a> Semantics<'a> { let environment = self.environment_of(t); if let Some(declaration) = environment.bind(id) { return Some(match declaration { - Declaration::Variable { - declaration_type, .. - } => declaration_type.clone(), - Declaration::Function { - declaration_type, .. - } => declaration_type.clone(), + Declaration::Variable { declaration, .. } => self.type_of(*declaration), + Declaration::Function { declaration, .. } => self.type_of(*declaration), Declaration::ExternFunction { declaration_type, .. } => declaration_type.clone(), - Declaration::Class { - declaration_type, .. - } => match declaration_type { - Type::Object(cd, name) => Type::Class(*cd, name.clone()), + Declaration::Class { declaration, .. } => match self.type_of(*declaration) { + Type::Object(cd, name) => Type::Class(cd, name.clone()), _ => self.internal_compiler_error(Some(t), "bound to a class not understood"), }, }); @@ -1572,9 +1545,7 @@ impl<'a> Semantics<'a> { let environment = self.environment_of(t); if let Some(declaration) = environment.bind(id) { return Some(match declaration { - Declaration::Variable { - declaration_type, .. - } => declaration_type.clone(), + Declaration::Variable { declaration, .. } => self.type_of(*declaration), _ => self.internal_compiler_error( Some(t), "how did I bind something other than a variable to self?", @@ -1679,6 +1650,13 @@ impl<'a> Semantics<'a> { Some(Type::Object(t, name.as_str().into())) } + fn type_of_field_decl(&self, tree: &Tree) -> Option { + assert_eq!(tree.kind, TreeKind::FieldDecl); + + // Type of a field declaration is the type of the type expression. + Some(self.type_of(tree.nth_tree(2)?)) + } + fn type_of_field_value(&self, t: TreeRef, tree: &Tree) -> Option { assert_eq!(tree.kind, TreeKind::FieldValue); @@ -1702,13 +1680,10 @@ impl<'a> Semantics<'a> { } }; match declaration { - Declaration::Variable { - declaration_type, .. - } - | Declaration::Function { - declaration_type, .. - } - | Declaration::ExternFunction { + Declaration::Variable { declaration, .. } + | Declaration::Function { declaration, .. } => Some(self.type_of(*declaration)), + + Declaration::ExternFunction { declaration_type, .. } => Some(declaration_type.clone()), @@ -1773,29 +1748,18 @@ impl<'a> Semantics<'a> { eprint!(" {k}: "); match v { Declaration::Variable { - declaration_type, - location, - index, + location, index, .. } => { - eprintln!("{declaration_type:?} (variable {location:?} {index})"); + eprintln!("(variable {location:?} {index})"); } - Declaration::Function { - declaration_type, - declaration, - } => { - eprintln!("{declaration_type:?} (function {declaration:?})"); + Declaration::Function { declaration, .. } => { + eprintln!(" (function {declaration:?})"); } - Declaration::ExternFunction { - declaration_type, - id, - } => { - eprintln!("{declaration_type:?} (extern {id:?})"); + Declaration::ExternFunction { id, .. } => { + eprintln!(" (extern {id:?})"); } - Declaration::Class { - declaration_type, - declaration, - } => { - eprintln!("{declaration_type:?} (class {declaration:?})"); + Declaration::Class { declaration, .. } => { + eprintln!(" (class {declaration:?})"); } }; } @@ -1831,9 +1795,7 @@ pub fn check(s: &Semantics) { TreeKind::Block => { let _ = s.type_of(t); } - TreeKind::LetStatement => { - let _ = s.environment_of(t); - } + TreeKind::LetStatement => check_let(s, tree), TreeKind::ReturnStatement => check_return_statement(s, tree), TreeKind::ExpressionStatement | TreeKind::LiteralExpression @@ -1910,6 +1872,19 @@ fn check_function_decl(s: &Semantics, t: TreeRef, tree: &Tree) { } } +fn check_let(s: &Semantics, tree: &Tree) { + let Some(name) = tree.nth_token(1) else { + return; + }; + let Some(expr) = tree.nth_tree(3) else { return }; + + if let Type::Method(..) = s.type_of(expr) { + let start = name.start; + let end = name.start + name.as_str().len(); + s.report_error_span(start, end, "methods cannot be assigned to variables"); + } +} + fn check_return_statement(s: &Semantics, tree: &Tree) { assert_eq!(tree.kind, TreeKind::ReturnStatement);