[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 name: Rc<str>,
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<Declaration> {
pub fn insert(&mut self, token: &Token, t: TreeRef) -> Option<Declaration> {
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(
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<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> {
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);