diff --git a/crates/saft-eval/src/interpreter.rs b/crates/saft-eval/src/interpreter.rs index 099908c..a838bd1 100644 --- a/crates/saft-eval/src/interpreter.rs +++ b/crates/saft-eval/src/interpreter.rs @@ -5,6 +5,7 @@ use saft_ast::{Block, Expr, Ident, Item, Module, Statement}; use saft_common::span::{Span, Spanned}; use std::borrow::Borrow; use std::collections::HashMap; +use std::rc::Rc; #[macro_export] macro_rules! exotic { @@ -141,10 +142,10 @@ impl Interpreter { params, body, }) => { - let fun = Value::Function(Function::SaftFunction(SaftFunction { + let fun = Value::Function(Rc::new(Function::SaftFunction(SaftFunction { params: params.clone(), body: body.clone(), - })); + }))); self.env.declare(ident, fun); Ok(()) } @@ -179,7 +180,7 @@ impl Interpreter { Expr::Integer(i) => (*i).into(), Expr::Float(f) => (*f).into(), Expr::Nil => Value::Nil, - Expr::String(s) => Value::String(s.clone()), + Expr::String(s) => Value::String(Rc::new(s.clone())), Expr::Assign(lhs, rhs) => { if let Expr::Var(ident) = &lhs.v { let res = self.eval_expr(rhs.as_ref())?; @@ -199,7 +200,9 @@ impl Interpreter { match (&lhs.v, &rhs.v) { (Value::Num(a), Value::Num(b)) => Value::Num(a.add(b)), - (Value::String(a), Value::String(b)) => Value::String(a.to_owned() + b), + (Value::String(a), Value::String(b)) => { + Value::String(Rc::new(a.as_ref().clone() + b)) + } _ => { return Err(type_error!( format!( @@ -316,8 +319,11 @@ impl Interpreter { arg_vals.push(self.eval_expr(arg)?); } - match fun.v { - Value::Function(Function::SaftFunction(SaftFunction { params, body })) => { + match &fun.v { + Value::Function(fun) + if let Function::SaftFunction(SaftFunction { params, body }) = + fun.as_ref() => + { match self.scoped(|interpreter| { if arg_vals.len() != params.len() { return Err(Exception::ArgMismatch { @@ -339,7 +345,10 @@ impl Interpreter { Err(e) => return Err(e), } } - Value::Function(Function::NativeFunction(NativeFuncData { f, .. })) => { + Value::Function(fun) + if let Function::NativeFunction(NativeFuncData { f, .. }) = + fun.as_ref() => + { f(self, &s, arg_vals)? } _ => { @@ -366,7 +375,7 @@ impl Interpreter { match expr.v { Value::String(str) => match index.v { Value::Num(Num::Int(i)) => match str.get(i as usize..i as usize + 1) { - Some(c) => Value::String(c.to_string()), + Some(c) => Value::String(Rc::new(c.to_string())), None => { return Err(exotic!( "Indexed out of bounds", diff --git a/crates/saft-eval/src/natives.rs b/crates/saft-eval/src/natives.rs index beffafd..e7a56b1 100644 --- a/crates/saft-eval/src/natives.rs +++ b/crates/saft-eval/src/natives.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::interpreter::{ControlFlow, Interpreter}; use crate::{cast_error, exotic}; use saft_common::span::{Span, Spanned}; @@ -69,6 +71,6 @@ fn add_native(env: &mut Env) { let data = N::data(); env.declare_unspanned( &data.name.into(), - Value::Function(Function::NativeFunction(data)), + Value::Function(Rc::new(Function::NativeFunction(data))), ); } diff --git a/crates/saft-eval/src/value.rs b/crates/saft-eval/src/value.rs index ef2e61d..110e4a1 100644 --- a/crates/saft-eval/src/value.rs +++ b/crates/saft-eval/src/value.rs @@ -1,5 +1,5 @@ use crate::interpreter::{ControlFlow, Interpreter}; -use std::borrow::Borrow; +use std::{borrow::Borrow, rc::Rc}; use saft_ast::Block; use saft_common::span::{Span, Spanned}; @@ -8,8 +8,8 @@ use saft_common::span::{Span, Spanned}; pub enum Value { Nil, Num(Num), - Function(Function), - String(String), + Function(Rc), + String(Rc), Vec(Vec), } @@ -18,8 +18,10 @@ impl Value { match self { Value::Nil => "nil".into(), Value::Num(num) => num.repr(), - Value::Function(Function::SaftFunction(..)) => "".into(), - Value::Function(Function::NativeFunction(..)) => "".into(), + Value::Function(fun) => match fun.as_ref() { + Function::SaftFunction(_) => "".into(), + Function::NativeFunction(_) => "".into(), + }, Value::String(s) => format!("\"{}\"", s), Value::Vec(vals) => { let mut buf = String::new(); @@ -281,7 +283,7 @@ impl From for Value { impl From for Value { fn from(value: String) -> Self { - Value::String(value) + Value::String(Rc::new(value)) } } @@ -434,7 +436,7 @@ impl CastFrom for String { fn cast_from(value: Value) -> Option { match value { - Value::String(s) => Some(s.clone()), + Value::String(s) => Some(s.as_ref().clone()), _ => None, } }