[fine] Split environment and type fully

Environment and type are now fully split, so that neither directly
depends on each other, to remove another class of circular dependency.
This commit is contained in:
John Doty 2024-01-29 06:42:51 -08:00
parent 019d780f85
commit 15548afc38

View file

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