mirror of
https://github.com/MorizzG/rlox.git
synced 2025-12-06 04:12:42 +00:00
updated a bunch of stuff
This commit is contained in:
parent
660464638f
commit
67bb5fe8fd
24 changed files with 683 additions and 702 deletions
|
|
@ -31,7 +31,7 @@ trait Eval {
|
|||
impl Eval for Literal {
|
||||
fn eval(&self, _env: &mut Environment) -> EvalResult<Value> {
|
||||
match self {
|
||||
Literal::String(s) => Ok(Value::String(Rc::clone(s))),
|
||||
Literal::String(s) => Ok(Value::String(s.clone())),
|
||||
Literal::Number(num) => Ok(Value::Number(*num)),
|
||||
Literal::Bool(b) => Ok(Value::Bool(*b)),
|
||||
Literal::Nil => Ok(Value::Nil),
|
||||
|
|
@ -83,10 +83,10 @@ impl Eval for Expr {
|
|||
},
|
||||
(String(left), String(right)) => match op {
|
||||
BinaryOp::Add => {
|
||||
let mut s = std::string::String::with_capacity(left.capacity() + right.capacity());
|
||||
s += &left;
|
||||
s += &right;
|
||||
Ok(String(Rc::new(s)))
|
||||
let s: Box<str> =
|
||||
itertools::chain(left.as_ref().chars(), right.chars()).collect();
|
||||
|
||||
Ok(Value::string(s))
|
||||
}
|
||||
BinaryOp::Less => Ok(Bool(left < right)),
|
||||
BinaryOp::LessEqual => Ok(Bool(left <= right)),
|
||||
|
|
@ -99,14 +99,18 @@ impl Eval for Expr {
|
|||
right: String(right),
|
||||
}),
|
||||
},
|
||||
(left, right) => Err(RuntimeError::BinaryOpInvalidArguments { left, op, right }),
|
||||
(left, right) => {
|
||||
Err(RuntimeError::BinaryOpInvalidArguments { left, op, right })
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Logical { left, op, right } => {
|
||||
let left = left.eval(env)?;
|
||||
|
||||
// shortcircuit
|
||||
if *op == LogicalOp::Or && left.is_truthy() || *op == LogicalOp::And && !left.is_truthy() {
|
||||
if *op == LogicalOp::Or && left.is_truthy()
|
||||
|| *op == LogicalOp::And && !left.is_truthy()
|
||||
{
|
||||
return Ok(left);
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +125,9 @@ impl Eval for Expr {
|
|||
let value = value.eval(env)?;
|
||||
|
||||
match target.as_ref() {
|
||||
Expr::LocalVariable { name, level } => env.assign(name, value.clone(), *level)?,
|
||||
Expr::LocalVariable { name, level } => {
|
||||
env.assign(name, value.clone(), *level)?
|
||||
}
|
||||
Expr::GlobalVariable { name } => env.assign_global(name, value.clone())?,
|
||||
_ => panic!("Invalid assigment target {target}"),
|
||||
}
|
||||
|
|
@ -159,12 +165,16 @@ impl Eval for Expr {
|
|||
Err(RuntimeError::InvalidGetTarget)
|
||||
}
|
||||
}
|
||||
Expr::Set { target, name, value } => {
|
||||
Expr::Set {
|
||||
target,
|
||||
name,
|
||||
value,
|
||||
} => {
|
||||
let target = target.eval(env)?;
|
||||
|
||||
if let Value::Object(mut object) = target {
|
||||
let value = value.eval(env)?;
|
||||
object.set(name, value);
|
||||
object.set(name.clone(), value);
|
||||
Ok(Value::Nil)
|
||||
} else {
|
||||
Err(RuntimeError::InvalidSetTarget)
|
||||
|
|
@ -176,7 +186,7 @@ impl Eval for Expr {
|
|||
closure_vars,
|
||||
body,
|
||||
} => Ok(Value::function(LoxFunction::new(
|
||||
name,
|
||||
name.clone(),
|
||||
env.collect_closure(closure_vars),
|
||||
param_names.clone(),
|
||||
body.as_ref().clone(),
|
||||
|
|
@ -208,7 +218,11 @@ impl Eval for Expr {
|
|||
|
||||
env.exit_scope();
|
||||
|
||||
Ok(Value::class(LoxClass::new(name, methods, superclass)))
|
||||
Ok(Value::class(LoxClass::new(
|
||||
name.clone(),
|
||||
methods,
|
||||
superclass,
|
||||
)))
|
||||
}
|
||||
Expr::This => panic!("Unresolved this"),
|
||||
Expr::Super {
|
||||
|
|
@ -223,7 +237,9 @@ impl Eval for Expr {
|
|||
Err(RuntimeError::InvalidGetTarget)
|
||||
}
|
||||
}
|
||||
(super_val, this_val) => panic!("super evaluated to {super_val} and this evaluated to {this_val}"),
|
||||
(super_val, this_val) => {
|
||||
panic!("super evaluated to {super_val} and this evaluated to {this_val}")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -233,11 +249,10 @@ impl Eval for Stmt {
|
|||
fn eval(&self, env: &mut Environment) -> EvalResult<Value> {
|
||||
match self {
|
||||
Stmt::Print { expr } => {
|
||||
match expr.eval(env)? {
|
||||
// special case: when printing a string, drop the surrounding ""
|
||||
Value::String(s) => println!("{s}"),
|
||||
val => println!("{val}"),
|
||||
}
|
||||
use std::io::Write;
|
||||
|
||||
let val = expr.eval(env)?;
|
||||
writeln!(env.runtime(), "{val}").unwrap();
|
||||
}
|
||||
Stmt::IfStmt {
|
||||
condition,
|
||||
|
|
@ -262,7 +277,7 @@ impl Eval for Stmt {
|
|||
}
|
||||
Stmt::VarDecl { name, initializer } => {
|
||||
let initializer = initializer.eval(env)?;
|
||||
env.define(name, initializer);
|
||||
env.define(name.clone(), initializer);
|
||||
}
|
||||
Stmt::Block { statements } => {
|
||||
env.enter_scope();
|
||||
|
|
@ -310,7 +325,7 @@ pub fn call_fun(fun: Rc<LoxFunction>, env: &mut Environment) -> EvalResult<Value
|
|||
env.insert_closure(fun.closure().clone());
|
||||
|
||||
for (name, value) in std::iter::zip(fun.param_names(), args) {
|
||||
env.define(name, value);
|
||||
env.define(name.clone(), value);
|
||||
}
|
||||
|
||||
let ret_val = match fun.body().eval(env) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue