mirror of
https://github.com/MorizzG/rlox.git
synced 2025-12-06 04:12:42 +00:00
Interpreter finish
This commit is contained in:
parent
719a014977
commit
647a095a05
5 changed files with 29 additions and 21 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 },
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue