diff --git a/src/cell.rs b/src/cell.rs index 366a884..cb7d4b0 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -62,7 +62,7 @@ pub struct Cell { } impl Ctr { - pub fn to_type(&mut self) -> Type { + pub fn to_type(&self) -> Type { match self { Ctr::Symbol(_s) => Type::Symbol, Ctr::String(_s) => Type::String, @@ -76,7 +76,7 @@ impl Ctr { } impl Type { - pub fn to_str(self) -> String { + pub fn to_str(&self) -> String { let ret: &str; match self { Type::Symbol => ret = "symbol", @@ -168,9 +168,9 @@ impl Cell { * short circuits on the first false returned. * also returns false on a non standard form list */ - pub fn circuit bool>(&self, func: F) -> bool{ - if func(self.car) { - match self.cdr { + pub fn circuit bool>(&self, func: &mut F) -> bool{ + if func(&self.car) { + match &self.cdr { Ctr::None => true, Ctr::Cell(c) => c.circuit(func), _ => false @@ -211,24 +211,23 @@ impl Cell { * returns length of chain */ pub fn len(&self) -> i128 { - match self.cdr { + match &self.cdr { Ctr::Cell(c) => c.len() + 1, _ => 1 } } /* iterates through a list. - * returns a COPY of the cell at the cooresponding index - * WARNING: DESTRUCTIVE? + * returns a CLONE of the cell at the cooresponding index */ pub fn index(&self, idx: usize) -> Ctr { if idx > 0 { - match self.cdr { + match &self.cdr { Ctr::None => Ctr::None, Ctr::Cell(c) => c.index(idx-1), _ => { if idx == 1 { - self.cdr + self.cdr.clone() } else { Ctr::None } @@ -238,7 +237,7 @@ impl Cell { match self.car { Ctr::None => Ctr::None, _ => { - self.cdr + self.cdr.clone() } } } diff --git a/src/eval.rs b/src/eval.rs index 3fc355a..17a05b3 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -25,9 +25,9 @@ use crate::vars::VTable; * representing the simplest possible form of the input */ pub fn eval( - _ast: Box, - _vars: Box, - _funcs: Box, + _ast: &Box, + _vars: &Box, + _funcs: &Box, _sym_loose: bool ) -> Result, String> { Err("Unimplemented".to_string()) diff --git a/src/func.rs b/src/func.rs index 698e34a..4d54c70 100644 --- a/src/func.rs +++ b/src/func.rs @@ -25,7 +25,7 @@ use crate::eval::eval; pub type FTable = HashMap>; // Standardized function signature for stdlib functions -pub type InternalOperation = fn(Box, Box, Box) -> Box; +pub type InternalOperation = fn(&Box, &mut Box, &mut Box) -> Box; pub struct ExternalOperation { // Un-evaluated abstract syntax tree // TODO: Intermediate evaluation to simplify branches with no argument in them @@ -46,7 +46,7 @@ pub enum Operation { /* Function Args * If Lazy, is an integer denoting number of args - * If Strict, is a list of Ctrs (with no wrapped values) denoting arg type. + * If Strict, is a list of type tags denoting argument type. */ pub enum Args { // signed: -1 denotes infinite args @@ -73,14 +73,15 @@ impl Function { */ pub fn call( &self, - args: Box, - vars: Box, - funcs: Box + args: &Box, + vars: &mut Box, + funcs: &mut Box ) -> Result, String> { - let mut n_args = args; + let n_args: &Box; + let outer_owner: Box; if !self.eval_lazy { match eval(args, vars, funcs, self.loose_syms) { - Ok(box_cell) => n_args = box_cell, + Ok(box_cell) => outer_owner = box_cell, Err(s) => return Err( format!( "error evaluating args to {}: {}", @@ -89,21 +90,24 @@ impl Function { ) ) } + n_args = &outer_owner; + } else { + n_args = args; } - match self.args { + match &self.args { Args::Lazy(num) => { - if num < 0 { + if *num < 0 { } - if !(num == (n_args.len() - 1)) { + if !(*num == (n_args.len() - 1)) { return Err(format!("expected {} args in call to {}", num, self.name)) } }, Args::Strict(arg_types) => { - let idx: usize = 0; - let mut passes = args.circuit(|c: Ctr| { + let mut idx: usize = 0; + let passes = n_args.circuit(&mut |c: &Ctr| { if idx >= arg_types.len() { return false; } @@ -147,28 +151,28 @@ impl Function { } } - match self.function { - Operation::Internal(f) => Ok((f)(n_args, vars, funcs)), + match &self.function { + Operation::Internal(f) => Ok((f)(&n_args, vars, funcs)), Operation::External(f) => { // copy var table and add args - let temp = vars.clone(); + let mut temp = vars.clone(); for n in 0..f.arg_syms.len() { temp.insert( - f.arg_syms[n], + f.arg_syms[n].clone(), Box::new(n_args.index(n)) ); } - eval(f.ast, temp, funcs, self.loose_syms) + eval(&f.ast, &temp, funcs, self.loose_syms) } } } } pub fn declare( - ft: Box, + ft: &mut Box, f: Box ) -> Option { - if let Operation::External(fun) = f.function { + if let Operation::External(fun) = &f.function { if let Args::Lazy(i) = f.args { if fun.arg_syms.len() != i.try_into().unwrap() { return Some( @@ -184,17 +188,6 @@ pub fn declare( } } - ft.insert(f.name, f); + ft.insert(f.name.clone(), f); None } - -pub fn get( - ft: Box, - identifier: String -) -> Option> { - if let Some(f) = ft.get(&identifier) { - Some(*f) - } else { - None - } -} diff --git a/src/lib.rs b/src/lib.rs index 5ca14df..e0a4022 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,8 +23,10 @@ mod vars; pub mod ast { pub use crate::cell::{Cell, Ctr, cons, cell_as_string}; - pub use crate::lex::{lex}; - pub use crate::func::{Function, Operation, FTable}; + pub use crate::lex::lex; + pub use crate::func::{Function, Operation, FTable, Args, + InternalOperation, ExternalOperation, + declare}; pub use crate::vars::VTable; - pub use crate::eval::{eval}; + pub use crate::eval::eval; } diff --git a/src/vars.rs b/src/vars.rs index 24c8f87..3799123 100644 --- a/src/vars.rs +++ b/src/vars.rs @@ -21,14 +21,12 @@ use crate::cell::{Ctr}; /* Mapping between a string token and a tree of Cells * The string token can be found in any Ctr::Symbol value - * - * Considerations: should I use a structure of cells for this? - * Current thoughts: if this was a language without proper data types, yes. + * it is expected that the trees stored are already evaluated */ pub type VTable = HashMap>; pub fn define( - vt: Box, + vt: &mut Box, identifier: String, var_tree: Box ) { @@ -36,14 +34,3 @@ pub fn define( drop(boxed_cell); } } - -pub fn get( - vt: Box, - identifier: String -) -> Option> { - if let Some(c) = vt.get(&identifier) { - Some(*c) - } else { - None - } -}