Skip to content

Commit

Permalink
Use RC to avoid cloning functions and strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Quaqqer committed Jan 7, 2024
1 parent 62b6298 commit 35103f5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 16 deletions.
25 changes: 17 additions & 8 deletions crates/saft-eval/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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())?;
Expand All @@ -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!(
Expand Down Expand Up @@ -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 {
Expand All @@ -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)?
}
_ => {
Expand All @@ -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",
Expand Down
4 changes: 3 additions & 1 deletion crates/saft-eval/src/natives.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::rc::Rc;

use crate::interpreter::{ControlFlow, Interpreter};
use crate::{cast_error, exotic};
use saft_common::span::{Span, Spanned};
Expand Down Expand Up @@ -69,6 +71,6 @@ fn add_native<N: NativeFunc>(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))),
);
}
16 changes: 9 additions & 7 deletions crates/saft-eval/src/value.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -8,8 +8,8 @@ use saft_common::span::{Span, Spanned};
pub enum Value {
Nil,
Num(Num),
Function(Function),
String(String),
Function(Rc<Function>),
String(Rc<String>),
Vec(Vec<Value>),
}

Expand All @@ -18,8 +18,10 @@ impl Value {
match self {
Value::Nil => "nil".into(),
Value::Num(num) => num.repr(),
Value::Function(Function::SaftFunction(..)) => "<function>".into(),
Value::Function(Function::NativeFunction(..)) => "<builtin function>".into(),
Value::Function(fun) => match fun.as_ref() {
Function::SaftFunction(_) => "<function>".into(),
Function::NativeFunction(_) => "<builtin function>".into(),
},
Value::String(s) => format!("\"{}\"", s),
Value::Vec(vals) => {
let mut buf = String::new();
Expand Down Expand Up @@ -281,7 +283,7 @@ impl From<Num> for Value {

impl From<String> for Value {
fn from(value: String) -> Self {
Value::String(value)
Value::String(Rc::new(value))
}
}

Expand Down Expand Up @@ -434,7 +436,7 @@ impl CastFrom<Value> for String {

fn cast_from(value: Value) -> Option<Self> {
match value {
Value::String(s) => Some(s.clone()),
Value::String(s) => Some(s.as_ref().clone()),
_ => None,
}
}
Expand Down

0 comments on commit 35103f5

Please sign in to comment.