From 380b7b26a37399e47d814bfaffba7b3b9169e68a Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 11 Apr 2025 20:44:52 +0300 Subject: [PATCH] side effects? --- src/run.rs | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/run.rs b/src/run.rs index d271b7c..33283f6 100644 --- a/src/run.rs +++ b/src/run.rs @@ -6,22 +6,9 @@ use crate::{ }; #[derive(Clone)] -pub struct Function { - name: String, - inner: Rc) -> Value>, -} - -impl Function { - pub fn new(name: String, func: impl Fn(Vec) -> Value + 'static) -> Self { - Self { - name, - inner: Rc::new(func), - } - } - - pub fn call(&self, args: Vec) -> Value { - (self.inner)(args) - } +struct Function { + name: &'static str, + inner: Rc) -> Value>, } impl Debug for Function { @@ -33,7 +20,7 @@ impl Debug for Function { #[derive(Debug, Clone, Default)] pub struct Scope { variables: HashMap, - functions: HashMap, + functions: HashMap<&'static str, Function>, } impl Scope { @@ -49,9 +36,18 @@ impl Scope { } } - pub fn add_fn(&mut self, name: &'static str, f: impl Fn(Vec) -> Value + 'static) { - self.functions - .insert(name.into(), Function::new(name.into(), f)); + pub fn add_fn( + &mut self, + name: &'static str, + f: impl Fn(&mut Scope, Vec) -> Value + 'static, + ) { + self.functions.insert( + name, + Function { + name: name, + inner: Rc::new(f), + }, + ); } } @@ -95,10 +91,11 @@ impl Eval for Expression { Expression::Constant(inner) => inner.eval(scope), Expression::Variable(inner) => inner.eval(scope), Expression::Call { callee, args } => { - let Some(function) = scope.functions.get(callee).cloned() else { + let Some(function) = scope.functions.get(callee.as_str()).cloned() else { panic!("attempt to call non-existent function {callee}") }; - function.call(args.into_iter().map(|arg| arg.eval(scope)).collect()) + let args = args.into_iter().map(|arg| arg.eval(scope)).collect(); + (function.inner)(scope, args) } } } @@ -197,7 +194,7 @@ mod tests { #[test] fn test_call() { let mut scope = Scope::default(); - scope.add_fn("sqr", |args| { + scope.add_fn("sqr", |_, args| { let [arg] = args.as_slice() else { panic!("exactly one argument expected"); };