[fine] Let binding
This commit is contained in:
parent
e5ac1b2718
commit
f9c7591154
2 changed files with 86 additions and 21 deletions
|
|
@ -122,12 +122,12 @@ impl fmt::Display for Type {
|
|||
}
|
||||
|
||||
pub struct Declaration {
|
||||
declaration_type: Type,
|
||||
pub declaration_type: Type,
|
||||
}
|
||||
|
||||
pub struct Environment {
|
||||
parent: Option<EnvironmentRef>,
|
||||
declarations: HashMap<Box<str>, Declaration>,
|
||||
pub parent: Option<EnvironmentRef>,
|
||||
pub declarations: HashMap<Box<str>, Declaration>,
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
|
|
@ -178,8 +178,8 @@ fn set_logical_parents(parents: &mut Vec<Option<TreeRef>>, syntax_tree: &SyntaxT
|
|||
// The default logical parent is the physical parent.
|
||||
if parents.len() <= t.index() {
|
||||
parents.resize(t.index() + 1, None);
|
||||
parents[t.index()] = tree.parent.clone();
|
||||
}
|
||||
parents[t.index()] = tree.parent.clone();
|
||||
|
||||
for child in &tree.children {
|
||||
match child {
|
||||
|
|
@ -189,17 +189,17 @@ fn set_logical_parents(parents: &mut Vec<Option<TreeRef>>, syntax_tree: &SyntaxT
|
|||
}
|
||||
|
||||
match tree.kind {
|
||||
TreeKind::Block => {
|
||||
// In a block, each child actually points to the previous child
|
||||
// as the logical parent, so that variable declarations that
|
||||
// occur as part of statements in the block are available to
|
||||
// statements later in the block.
|
||||
TreeKind::Block | TreeKind::File => {
|
||||
// In a block (or at the top level), each child actually points
|
||||
// to the previous child as the logical parent, so that variable
|
||||
// declarations that occur as part of statements in the block are
|
||||
// available to statements later in the block.
|
||||
let mut parent = Some(t);
|
||||
for child in &tree.children {
|
||||
match child {
|
||||
Child::Token(_) => (),
|
||||
Child::Tree(ct) => {
|
||||
parents[t.index()] = parent;
|
||||
parents[ct.index()] = parent;
|
||||
parent = Some(*ct);
|
||||
}
|
||||
}
|
||||
|
|
@ -261,6 +261,14 @@ impl<'a> Semantics<'a> {
|
|||
(*self.errors.borrow()).clone()
|
||||
}
|
||||
|
||||
pub fn logical_parent(&self, tr: TreeRef) -> Option<TreeRef> {
|
||||
if tr.index() < self.logical_parents.len() {
|
||||
self.logical_parents[tr.index()]
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn report_error<T>(&self, position: usize, error: T)
|
||||
where
|
||||
T: ToString,
|
||||
|
|
@ -326,7 +334,9 @@ impl<'a> Semantics<'a> {
|
|||
};
|
||||
|
||||
let result = match tree.kind {
|
||||
// TODO: Things that introduce an environment!
|
||||
TreeKind::LetStatement => self.environment_of_let(parent, tree),
|
||||
|
||||
// TODO: MORE Things that introduce an environment!
|
||||
_ => parent,
|
||||
};
|
||||
|
||||
|
|
@ -334,6 +344,31 @@ impl<'a> Semantics<'a> {
|
|||
result
|
||||
}
|
||||
|
||||
fn environment_of_let(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||
// 0 is the ... let keyword
|
||||
let Some(name) = tree.nth_token(1) else {
|
||||
return parent; // Error is already reported?
|
||||
};
|
||||
|
||||
let declaration_type = match tree.nth_tree(3) {
|
||||
Some(expr) => self
|
||||
.type_of(expr)
|
||||
.expect("the tree in the expression should yield a type"),
|
||||
|
||||
// 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 mut environment = Environment::new(Some(parent));
|
||||
environment
|
||||
.declarations
|
||||
.insert(name.as_str().into(), Declaration { declaration_type });
|
||||
|
||||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
||||
pub fn type_of(&self, t: TreeRef) -> Option<Type> {
|
||||
if let Some(existing) = self.types.borrow().get(&t) {
|
||||
return Some(existing.clone());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue