updated a bunch of stuff

This commit is contained in:
Moritz Gmeiner 2024-09-01 19:16:30 +02:00
commit 67bb5fe8fd
24 changed files with 683 additions and 702 deletions

View file

@ -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) {