aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2024-01-17 23:54:52 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2024-01-17 23:54:52 +0100
commit95ba627a9c5e4e6e1d79f7aaff1854eb831511b4 (patch)
tree177d58d387143d644ce7ad2c97eb30032e226533 /src
parent9cc61497ed8a2336f33407d3262181e4ac3b46cb (diff)
hand context on to Function trait
Diffstat (limited to 'src')
-rw-r--r--src/commonsense.rs15
-rw-r--r--src/context.rs20
-rw-r--r--src/expression.rs2
-rw-r--r--src/expression_function.rs18
-rw-r--r--src/function.rs19
-rw-r--r--src/main.rs2
-rw-r--r--src/operation.rs7
7 files changed, 45 insertions, 38 deletions
diff --git a/src/commonsense.rs b/src/commonsense.rs
index df688fb..4570109 100644
--- a/src/commonsense.rs
+++ b/src/commonsense.rs
@@ -40,7 +40,8 @@ pub fn tan(a: Complex) -> Complex {
macro_rules! commonsense_functions {
{$($x:expr => $y:expr), *} => {
{
- let mut h : HashMap<String, Box<dyn Function>> = HashMap::new();
+ use std::sync::Arc;
+ let mut h : HashMap<String, Arc<dyn Function>> = HashMap::new();
h.extend(functions!{
"sqrt" => &crate::commonsense::sqrt,
"sin" => &crate::commonsense::sin,
@@ -48,7 +49,7 @@ macro_rules! commonsense_functions {
"tan" => &crate::commonsense::tan
});
$(
- h.insert($x.to_string(), Box::new($y));
+ h.insert($x.to_string(), Arc::new($y));
)*
h
}
@@ -59,11 +60,11 @@ macro_rules! commonsense_functions {
macro_rules! commonsense_operations {
{$($x:expr => $y:expr), *} => {
vec![
- Operation::new('+', Box::new(&crate::commonsense::add)),
- Operation::new('-', Box::new(&crate::commonsense::sub)),
- Operation::new('*', Box::new(&crate::commonsense::mul)),
- Operation::new('/', Box::new(&crate::commonsense::div)),
- Operation::new('^', Box::new(&crate::commonsense::pow))
+ Operation::new('+', crate::commonsense::add),
+ Operation::new('-', crate::commonsense::sub),
+ Operation::new('*', crate::commonsense::mul),
+ Operation::new('/', crate::commonsense::div),
+ Operation::new('^', crate::commonsense::pow)
$(
Operation::new($x, Box::new($y)),
)*]
diff --git a/src/context.rs b/src/context.rs
index de1d09d..04e27f7 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -1,13 +1,14 @@
+use crate::complex::Complex;
use crate::function::Function;
use crate::operation::Operation;
-use crate::complex::Complex;
+use std::sync::Arc;
use std::collections::HashMap;
-#[derive(Default)]
+#[derive(Default, Clone)]
pub struct Context {
ops: Vec<Operation>,
vars: HashMap<String, Complex>,
- funcs: HashMap<String, Box<dyn Function>>,
+ funcs: HashMap<String, Arc<dyn Function>>,
}
impl Context {
@@ -25,7 +26,7 @@ impl Context {
self
}
- pub fn with_functions(mut self, funcs: HashMap<String, Box<dyn Function>>) -> Self {
+ pub fn with_functions(mut self, funcs: HashMap<String, Arc<dyn Function>>) -> Self {
self.funcs = funcs;
self
}
@@ -34,12 +35,12 @@ impl Context {
&self.ops
}
- pub fn variable_mut(&mut self, name: &str) -> Option<&mut Complex> {
- self.vars.get_mut(name)
+ pub fn set_variable(&mut self, name: &str, value: Complex) {
+ self.vars.insert(name.to_string(), value);
}
- pub fn function_mut(&mut self, name: &str) -> Option<&mut Box<dyn Function>> {
- self.funcs.get_mut(name)
+ pub fn set_function(&mut self, name: &str, func: Arc<dyn Function>) {
+ self.funcs.insert(name.to_string(), func);
}
pub fn variable(&self, name: &str) -> Option<&Complex> {
@@ -47,7 +48,7 @@ impl Context {
}
#[allow(clippy::borrowed_box)]
- pub fn function(&self, name: &str) -> Option<&Box<dyn Function>> {
+ pub fn function(&self, name: &str) -> Option<&Arc<dyn Function>> {
self.funcs.get(name)
}
}
@@ -64,4 +65,3 @@ macro_rules! variables {
}
};
}
-
diff --git a/src/expression.rs b/src/expression.rs
index 4029f93..c7574a9 100644
--- a/src/expression.rs
+++ b/src/expression.rs
@@ -55,7 +55,7 @@ impl Expression {
}
if let Some(func) = context.function(func) {
- Ok(func.eval(FunctionArgument::new(argv))?)
+ Ok(func.eval(FunctionArgument::new(argv), context)?)
} else {
Err(format!("function '{func}' not found"))
}
diff --git a/src/expression_function.rs b/src/expression_function.rs
index 35eba5f..138891f 100644
--- a/src/expression_function.rs
+++ b/src/expression_function.rs
@@ -1,12 +1,11 @@
use std::{collections::HashMap, iter::zip};
+use std::sync::Arc;
use crate::{
- commonsense_functions, commonsense_operations, functions,
complex::Complex,
context::Context,
expression::Expression,
- operation::Operation,
- function::{Function, FunctionArgument}
+ function::{Function, FunctionArgument, EmptyFunction}
};
pub struct ExpressionFunction {
@@ -38,17 +37,14 @@ impl ExpressionFunction {
}
impl Function for ExpressionFunction {
- fn eval(&self, args: FunctionArgument) -> Result<Complex, String> {
+ fn eval(&self, args: FunctionArgument, ctx: &Context) -> Result<Complex, String> {
if args.len() == self.args.len() {
- let mut vars = HashMap::new();
+ let mut nctx = ctx.clone();
for (n, v) in zip(self.args.iter(), args.data().iter()) {
- vars.insert(n.to_string(), v.clone());
+ nctx.set_variable(n, *v)
}
- let ctx = Context::new()
- .with_variables(vars)
- .with_functions(commonsense_functions! {})
- .with_operations(commonsense_operations! {});
- self.expr.evaluate(&ctx)
+ nctx.set_function(self.name(), Arc::new(EmptyFunction {}));
+ self.expr.evaluate(&nctx)
} else {
Err(format!(
"{} takes {} parameters",
diff --git a/src/function.rs b/src/function.rs
index 0da4574..126477c 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -1,4 +1,4 @@
-use crate::complex::Complex;
+use crate::{complex::Complex, context::Context};
pub struct FunctionArgument {
args : Vec<Complex>,
@@ -23,16 +23,16 @@ impl FunctionArgument {
}
pub trait Function {
- fn eval(&self, args: FunctionArgument) -> Result<Complex, String>;
+ fn eval(&self, args: FunctionArgument, ctx: &Context) -> Result<Complex, String>;
}
#[macro_export]
macro_rules! functions {
{$($x:expr => $y:expr), *} => {
{
- let mut h : HashMap<String, Box<dyn Function>> = HashMap::new();
+ let mut h : HashMap<String, Arc<dyn Function>> = HashMap::new();
$(
- h.insert($x.to_string(), Box::new($y));
+ h.insert($x.to_string(), Arc::new($y));
)*
h
}
@@ -45,7 +45,7 @@ impl<T> Function for T
where
T: Fn(Complex) -> Complex,
{
- fn eval(&self, args: FunctionArgument) -> Result<Complex, String> {
+ fn eval(&self, args: FunctionArgument, _ctx: &Context) -> Result<Complex, String> {
if args.len() == 1 {
Ok(self(args.get(0)))
} else {
@@ -53,3 +53,12 @@ where
}
}
}
+
+
+pub struct EmptyFunction {}
+
+impl Function for EmptyFunction {
+ fn eval(&self, _args: FunctionArgument, _ctx: &Context) -> Result<Complex, String> {
+ Err("function not implemented in this scope".to_string())
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 466ad09..614eba6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,7 +19,7 @@ use expression_function::ExpressionFunction;
fn main() {
let func = ExpressionFunction::from_string("f(x) = x^2".to_string());
- let expr = "f(3)";
+ let expr = "f(5)";
let ctx: Context = Context::new()
.with_operations(commonsense_operations!{})
diff --git a/src/operation.rs b/src/operation.rs
index a61ae1f..7eca774 100644
--- a/src/operation.rs
+++ b/src/operation.rs
@@ -1,14 +1,15 @@
use crate::complex::Complex;
-pub type Operator = dyn Fn(Complex, Complex) -> Complex;
+pub type Operator = fn(Complex, Complex) -> Complex;
+#[derive(Clone)]
pub struct Operation {
sign: char,
- func: Box<Operator>
+ func: Operator
}
impl Operation {
- pub fn new(sign: char, func: Box<Operator>) -> Self {
+ pub fn new(sign: char, func: Operator) -> Self {
Self { sign, func }
}