Interpreter - Special case for initializer methods
This commit is contained in:
parent
98eef78583
commit
783a2e3dd0
3 changed files with 26 additions and 4 deletions
|
@ -122,6 +122,15 @@ impl Environment {
|
||||||
self.values.insert(name.to_owned(), Some(value));
|
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.
|
/// Read an ancestor from the chain of enclosing environments.
|
||||||
fn ancestor(&self, distance: usize) -> EnvironmentRef {
|
fn ancestor(&self, distance: usize) -> EnvironmentRef {
|
||||||
let mut ancestor = self.enclosing.clone().expect("ancestor() called at root");
|
let mut ancestor = self.enclosing.clone().expect("ancestor() called at root");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{fmt::Display, cell::RefMut};
|
use std::{cell::RefMut, fmt::Display};
|
||||||
|
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ pub struct Function {
|
||||||
params: Vec<Token>,
|
params: Vec<Token>,
|
||||||
body: Vec<ast::StmtNode>,
|
body: Vec<ast::StmtNode>,
|
||||||
env: EnvironmentRef,
|
env: EnvironmentRef,
|
||||||
|
is_initializer: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
|
@ -23,12 +24,14 @@ impl Function {
|
||||||
params: &[Token],
|
params: &[Token],
|
||||||
body: &[ast::StmtNode],
|
body: &[ast::StmtNode],
|
||||||
environment: EnvironmentRef,
|
environment: EnvironmentRef,
|
||||||
|
is_initializer: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.cloned(),
|
name: name.cloned(),
|
||||||
params: params.to_owned(),
|
params: params.to_owned(),
|
||||||
body: body.to_owned(),
|
body: body.to_owned(),
|
||||||
env: environment,
|
env: environment,
|
||||||
|
is_initializer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +41,7 @@ impl Function {
|
||||||
params: self.params.clone(),
|
params: self.params.clone(),
|
||||||
body: self.body.clone(),
|
body: self.body.clone(),
|
||||||
env: Environment::create_child(&self.env),
|
env: Environment::create_child(&self.env),
|
||||||
|
is_initializer: self.is_initializer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +75,20 @@ impl Callable for Function {
|
||||||
let result = stmt.interpret(&mut child)?;
|
let result = stmt.interpret(&mut child)?;
|
||||||
match result {
|
match result {
|
||||||
InterpreterFlowControl::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),
|
_ => panic!("unexpected flow control {:?}", result),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.is_initializer {
|
||||||
|
Ok(itpr_state.environment.borrow().read("this"))
|
||||||
|
} else {
|
||||||
Ok(Value::Nil)
|
Ok(Value::Nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
impl Display for Function {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|
|
@ -208,6 +208,7 @@ impl StmtNode {
|
||||||
&method.params,
|
&method.params,
|
||||||
&method.body,
|
&method.body,
|
||||||
es.environment.clone(),
|
es.environment.clone(),
|
||||||
|
method.name.lexeme == "init",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -226,6 +227,7 @@ impl StmtNode {
|
||||||
&decl.params,
|
&decl.params,
|
||||||
&decl.body,
|
&decl.body,
|
||||||
es.environment.clone(),
|
es.environment.clone(),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
es.environment
|
es.environment
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -357,7 +359,7 @@ impl Interpretable for ExprNode {
|
||||||
arguments,
|
arguments,
|
||||||
} => self.on_call(es, callee, right_paren, arguments),
|
} => self.on_call(es, callee, right_paren, arguments),
|
||||||
ExprNode::Lambda { params, body } => {
|
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())
|
Ok(Value::from(lambda).into())
|
||||||
}
|
}
|
||||||
ExprNode::Get(get_expr) => self.on_get_expression(es, get_expr),
|
ExprNode::Get(get_expr) => self.on_get_expression(es, get_expr),
|
||||||
|
|
Loading…
Reference in a new issue