Interpreter - Lookups and assignment based on resolver results

* Does not work. Using pointers was a bad idea.
This commit is contained in:
Emmanuel BENOîT 2023-01-07 08:24:27 +01:00
parent bd156e619f
commit 3117dfeac5
2 changed files with 41 additions and 18 deletions

View file

@ -82,21 +82,11 @@ impl Environment {
}
/// Access a variable at a specified distance in a parent environment.
pub fn get_at(&self, distance: usize, name: &Token) -> Value {
self.ancestor(distance)
.values
.get(&name.lexeme as &str)
.unwrap()
.unwrap()
.clone()
}
/// Access the ancestor environment at a specified distance from the current one.
fn ancestor(&self, distance: usize) -> &Self {
pub fn get_at(&self, distance: usize, name: &Token) -> SloxResult<Value> {
if distance == 0 {
&self
self.get(name)
} else {
self.enclosing.unwrap().borrow().ancestor(distance - 1)
self.ancestor(distance).borrow().get(name)
}
}
@ -116,4 +106,27 @@ impl Environment {
}
}
}
/// Set a variable at a specified distance in a parent environment.
pub fn assign_at(&mut self, distance: usize, name: &Token, value: Value) -> SloxResult<()> {
if distance == 0 {
self.assign(name, value)
} else {
self.ancestor(distance).borrow_mut().assign(name, value)
}
}
/// Read an ancestor from the chain of enclosing environments.
fn ancestor(&self, distance: usize) -> EnvironmentRef {
let mut ancestor = self.enclosing.clone().expect("ancestor() called at root");
for _ in 1..distance {
let ap = ancestor
.borrow()
.enclosing
.clone()
.expect("ancestor() called with too high a distance");
ancestor = ap;
}
ancestor
}
}

View file

@ -51,8 +51,18 @@ impl<'a> InterpreterState<'a> {
fn lookup_var(&self, name: &Token, expr: &ast::ExprNode) -> SloxResult<Value> {
match self.variables.get(&(expr as *const ast::ExprNode)) {
Some(distance) => Ok(self.environment.borrow().get_at(*distance, name)),
None => self.environment.borrow().get(name),
Some(distance) => self.environment.borrow().get_at(*distance, name),
None => self.globals.borrow().get(name),
}
}
fn assign_var(&self, name: &Token, expr: &ast::ExprNode, value: Value) -> SloxResult<()> {
match self.variables.get(&(expr as *const ast::ExprNode)) {
Some(distance) => self
.environment
.borrow_mut()
.assign_at(*distance, name, value),
None => self.globals.borrow_mut().assign(name, value),
}
}
}
@ -303,7 +313,7 @@ impl Interpretable for ast::ExprNode {
match self {
ast::ExprNode::Assignment { name, value } => {
let value = value.interpret(es)?.result();
es.environment.borrow_mut().assign(name, value)?;
es.assign_var(name, &self, value)?;
Ok(InterpreterFlowControl::default())
}
ast::ExprNode::Logical {
@ -319,7 +329,7 @@ impl Interpretable for ast::ExprNode {
ast::ExprNode::Unary { operator, right } => self.on_unary(es, operator, right),
ast::ExprNode::Grouping { expression } => expression.interpret(es),
ast::ExprNode::Litteral { value } => self.on_litteral(value),
ast::ExprNode::Variable { name } => Ok(es.environment.borrow().get(name)?.into()),
ast::ExprNode::Variable { name } => Ok(es.lookup_var(name, &self)?.into()),
ast::ExprNode::Call {
callee,
right_paren,