Interpreter finish

This commit is contained in:
Moritz Gmeiner 2023-01-28 21:11:01 +01:00
commit 647a095a05
5 changed files with 29 additions and 21 deletions

View file

@ -82,7 +82,7 @@ impl Stmt {
impl Display for Stmt { impl Display for Stmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Stmt::Print { expr } => write!(f, "print {expr};"), Stmt::Print { expr } => write!(f, "(print {expr});"),
Stmt::IfStmt { Stmt::IfStmt {
condition, condition,
then_branch, then_branch,

View file

@ -36,22 +36,27 @@ impl<'a> Environment<'a> {
self.local_scopes.push(Scope::new()); self.local_scopes.push(Scope::new());
} }
pub fn push_scope(&mut self, scope: Scope) {
self.local_scopes.push(scope);
}
pub fn exit_scope(&mut self) { pub fn exit_scope(&mut self) {
// self.current_frame_mut().exit_scope(); // self.current_frame_mut().exit_scope();
self.local_scopes.pop().expect("Tried to pop global scope"); self.local_scopes.pop().expect("Tried to pop global scope");
} }
pub fn insert_closure(&mut self, closure: Scope) {
let scope = self.local_scopes.last_mut().unwrap();
for (name, value) in closure {
scope.insert(name, value);
}
}
pub fn get_global(&self, name: &str) -> Result<Value, RuntimeError> { pub fn get_global(&self, name: &str) -> Result<Value, RuntimeError> {
self.runtime.get_global(name) self.runtime.get_global(name)
} }
pub fn get_local(&self, name: &str, level: usize) -> Result<Value, RuntimeError> { pub fn get_local(&self, name: &str, level: usize) -> Result<Value, RuntimeError> {
if let Some(scope) = self.local_scopes.iter().rev().nth(level) { let len = self.local_scopes.len();
if let Some(heap_value) = scope.get(name) { if level < len {
if let Some(heap_value) = self.local_scopes[len - level - 1].get(name) {
return Ok(heap_value.get_clone()); return Ok(heap_value.get_clone());
} }
} }

View file

@ -16,7 +16,7 @@ pub enum RuntimeError {
BinaryOpInvalidArguments { left: Value, op: BinaryOp, right: Value }, BinaryOpInvalidArguments { left: Value, op: BinaryOp, right: Value },
#[error("Division by zero")] #[error("Division by zero")]
DivisionByZero, DivisionByZero,
#[error("Name {name} is not defined")] #[error("Local {name} is not defined")]
NameNotDefined { name: String }, NameNotDefined { name: String },
#[error("Global {name} is not defined")] #[error("Global {name} is not defined")]
GlobalNotDefined { name: String }, GlobalNotDefined { name: String },

View file

@ -133,7 +133,7 @@ impl Eval for Expr {
.collect::<EvalResult<Vec<Value>>>()?; .collect::<EvalResult<Vec<Value>>>()?;
match callee { match callee {
Value::Function(fun) => fun.call(args, env), Value::Function(fun) => LoxFunction::call(fun, args, env),
Value::ExternFunction(ext_fun) => ext_fun.call(args, env), Value::ExternFunction(ext_fun) => ext_fun.call(args, env),
Value::Class(class) => LoxClass::call(class, args, env), Value::Class(class) => LoxClass::call(class, args, env),
_ => Err(RuntimeError::NotCallable { callee }), _ => Err(RuntimeError::NotCallable { callee }),
@ -286,22 +286,26 @@ impl Eval for Stmt {
/*====================================================================================================================*/ /*====================================================================================================================*/
impl LoxFunction { impl LoxFunction {
pub fn call(&self, args: Vec<Value>, env: &mut Environment) -> EvalResult<Value> { pub fn call(fun: Rc<LoxFunction>, args: Vec<Value>, env: &mut Environment) -> EvalResult<Value> {
if args.len() != self.arity() { if args.len() != fun.arity() {
return Err(RuntimeError::WrongArity { return Err(RuntimeError::WrongArity {
name: self.name().to_owned(), name: fun.name().to_owned(),
arity: self.arity(), arity: fun.arity(),
given: args.len(), given: args.len(),
}); });
} }
env.push_scope(self.closure().clone()); env.enter_scope();
for (name, value) in std::iter::zip(self.param_names(), args) { env.define(fun.name(), Value::Function(fun.clone()));
env.insert_closure(fun.closure().clone());
for (name, value) in std::iter::zip(fun.param_names(), args) {
env.define(name, value); env.define(name, value);
} }
let ret_val = match self.body().eval(env) { let ret_val = match fun.body().eval(env) {
Ok(_) => Ok(Value::Nil), Ok(_) => Ok(Value::Nil),
Err(RuntimeError::Return { value }) => Ok(value), Err(RuntimeError::Return { value }) => Ok(value),
Err(err) => Err(err), Err(err) => Err(err),
@ -343,7 +347,7 @@ impl LoxClass {
// object.init(args, env)?; // object.init(args, env)?;
if let Some(Value::Function(method)) = object.get("init") { if let Some(Value::Function(method)) = object.get("init") {
method.call(args, env)?; LoxFunction::call(method, args, env)?;
} }
Ok(Value::Object(object)) Ok(Value::Object(object))

View file

@ -103,12 +103,11 @@ fn run(code_string: &str, runtime: &mut Runtime) -> Result<(), LoxError> {
println!("{statement}"); println!("{statement}");
} */ } */
/* for statement in statements.iter() {
println!("{statement}");
} */
for mut statement in statements { for mut statement in statements {
resolve(&mut statement, runtime)?; resolve(&mut statement, runtime)?;
// println!("{statement}");
execute(statement, runtime)?; execute(statement, runtime)?;
} }