Interpreter - Special case for initializer methods

This commit is contained in:
Emmanuel BENOîT 2023-01-11 07:46:13 +01:00
parent 98eef78583
commit 783a2e3dd0
3 changed files with 26 additions and 4 deletions

View file

@ -122,6 +122,15 @@ impl Environment {
self.values.insert(name.to_owned(), Some(value));
}
/// Read a variable from an environment directly. Panics if the symbol
/// does not exist.
pub fn read(&self, name: &str) -> Value {
match self.values.get(name) {
Some(Some(v)) => v.clone(),
_ => panic!("Symbol {name} does not exist"),
}
}
/// 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");

View file

@ -1,4 +1,4 @@
use std::{fmt::Display, cell::RefMut};
use std::{cell::RefMut, fmt::Display};
use itertools::izip;
@ -15,6 +15,7 @@ pub struct Function {
params: Vec<Token>,
body: Vec<ast::StmtNode>,
env: EnvironmentRef,
is_initializer: bool,
}
impl Function {
@ -23,12 +24,14 @@ impl Function {
params: &[Token],
body: &[ast::StmtNode],
environment: EnvironmentRef,
is_initializer: bool,
) -> Self {
Self {
name: name.cloned(),
params: params.to_owned(),
body: body.to_owned(),
env: environment,
is_initializer,
}
}
@ -38,6 +41,7 @@ impl Function {
params: self.params.clone(),
body: self.body.clone(),
env: Environment::create_child(&self.env),
is_initializer: self.is_initializer,
}
}
@ -71,11 +75,18 @@ impl Callable for Function {
let result = stmt.interpret(&mut child)?;
match result {
InterpreterFlowControl::Result(_) => (),
InterpreterFlowControl::Return(v) => return Ok(v),
InterpreterFlowControl::Return(v) if !self.is_initializer => return Ok(v),
InterpreterFlowControl::Return(_) => {
return Ok(itpr_state.environment.borrow().read("this"))
}
_ => panic!("unexpected flow control {:?}", result),
}
}
Ok(Value::Nil)
if self.is_initializer {
Ok(itpr_state.environment.borrow().read("this"))
} else {
Ok(Value::Nil)
}
}
}

View file

@ -208,6 +208,7 @@ impl StmtNode {
&method.params,
&method.body,
es.environment.clone(),
method.name.lexeme == "init",
),
)
})
@ -226,6 +227,7 @@ impl StmtNode {
&decl.params,
&decl.body,
es.environment.clone(),
false,
);
es.environment
.borrow_mut()
@ -357,7 +359,7 @@ impl Interpretable for ExprNode {
arguments,
} => self.on_call(es, callee, right_paren, arguments),
ExprNode::Lambda { params, body } => {
let lambda = Function::new(None, params, body, es.environment.clone());
let lambda = Function::new(None, params, body, es.environment.clone(), false);
Ok(Value::from(lambda).into())
}
ExprNode::Get(get_expr) => self.on_get_expression(es, get_expr),