in progress commit

- fixed errors in func and vars blocking testing
- use box references in call and eval
Still need to fix the tests themselves....
This commit is contained in:
Aidan 2021-03-07 19:24:38 -08:00
parent d2f60314f9
commit 76b12a8214
No known key found for this signature in database
GPG key ID: 327711E983899316
5 changed files with 44 additions and 63 deletions

View file

@ -62,7 +62,7 @@ pub struct Cell {
} }
impl Ctr { impl Ctr {
pub fn to_type(&mut self) -> Type { pub fn to_type(&self) -> Type {
match self { match self {
Ctr::Symbol(_s) => Type::Symbol, Ctr::Symbol(_s) => Type::Symbol,
Ctr::String(_s) => Type::String, Ctr::String(_s) => Type::String,
@ -76,7 +76,7 @@ impl Ctr {
} }
impl Type { impl Type {
pub fn to_str(self) -> String { pub fn to_str(&self) -> String {
let ret: &str; let ret: &str;
match self { match self {
Type::Symbol => ret = "symbol", Type::Symbol => ret = "symbol",
@ -168,9 +168,9 @@ impl Cell {
* short circuits on the first false returned. * short circuits on the first false returned.
* also returns false on a non standard form list * also returns false on a non standard form list
*/ */
pub fn circuit<F: FnOnce(Ctr)-> bool>(&self, func: F) -> bool{ pub fn circuit<F: FnMut(&Ctr)-> bool>(&self, func: &mut F) -> bool{
if func(self.car) { if func(&self.car) {
match self.cdr { match &self.cdr {
Ctr::None => true, Ctr::None => true,
Ctr::Cell(c) => c.circuit(func), Ctr::Cell(c) => c.circuit(func),
_ => false _ => false
@ -211,24 +211,23 @@ impl Cell {
* returns length of chain * returns length of chain
*/ */
pub fn len(&self) -> i128 { pub fn len(&self) -> i128 {
match self.cdr { match &self.cdr {
Ctr::Cell(c) => c.len() + 1, Ctr::Cell(c) => c.len() + 1,
_ => 1 _ => 1
} }
} }
/* iterates through a list. /* iterates through a list.
* returns a COPY of the cell at the cooresponding index * returns a CLONE of the cell at the cooresponding index
* WARNING: DESTRUCTIVE?
*/ */
pub fn index(&self, idx: usize) -> Ctr { pub fn index(&self, idx: usize) -> Ctr {
if idx > 0 { if idx > 0 {
match self.cdr { match &self.cdr {
Ctr::None => Ctr::None, Ctr::None => Ctr::None,
Ctr::Cell(c) => c.index(idx-1), Ctr::Cell(c) => c.index(idx-1),
_ => { _ => {
if idx == 1 { if idx == 1 {
self.cdr self.cdr.clone()
} else { } else {
Ctr::None Ctr::None
} }
@ -238,7 +237,7 @@ impl Cell {
match self.car { match self.car {
Ctr::None => Ctr::None, Ctr::None => Ctr::None,
_ => { _ => {
self.cdr self.cdr.clone()
} }
} }
} }

View file

@ -25,9 +25,9 @@ use crate::vars::VTable;
* representing the simplest possible form of the input * representing the simplest possible form of the input
*/ */
pub fn eval( pub fn eval(
_ast: Box<Cell>, _ast: &Box<Cell>,
_vars: Box<VTable>, _vars: &Box<VTable>,
_funcs: Box<FTable>, _funcs: &Box<FTable>,
_sym_loose: bool _sym_loose: bool
) -> Result<Box<Cell>, String> { ) -> Result<Box<Cell>, String> {
Err("Unimplemented".to_string()) Err("Unimplemented".to_string())

View file

@ -25,7 +25,7 @@ use crate::eval::eval;
pub type FTable = HashMap<String, Box<Function>>; pub type FTable = HashMap<String, Box<Function>>;
// Standardized function signature for stdlib functions // Standardized function signature for stdlib functions
pub type InternalOperation = fn(Box<Cell>, Box<VTable>, Box<FTable>) -> Box<Cell>; pub type InternalOperation = fn(&Box<Cell>, &mut Box<VTable>, &mut Box<FTable>) -> Box<Cell>;
pub struct ExternalOperation { pub struct ExternalOperation {
// Un-evaluated abstract syntax tree // Un-evaluated abstract syntax tree
// TODO: Intermediate evaluation to simplify branches with no argument in them // TODO: Intermediate evaluation to simplify branches with no argument in them
@ -46,7 +46,7 @@ pub enum Operation {
/* Function Args /* Function Args
* If Lazy, is an integer denoting number of 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 { pub enum Args {
// signed: -1 denotes infinite args // signed: -1 denotes infinite args
@ -73,14 +73,15 @@ impl Function {
*/ */
pub fn call( pub fn call(
&self, &self,
args: Box<Cell>, args: &Box<Cell>,
vars: Box<VTable>, vars: &mut Box<VTable>,
funcs: Box<FTable> funcs: &mut Box<FTable>
) -> Result<Box<Cell>, String> { ) -> Result<Box<Cell>, String> {
let mut n_args = args; let n_args: &Box<Cell>;
let outer_owner: Box<Cell>;
if !self.eval_lazy { if !self.eval_lazy {
match eval(args, vars, funcs, self.loose_syms) { 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( Err(s) => return Err(
format!( format!(
"error evaluating args to {}: {}", "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) => { 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)) return Err(format!("expected {} args in call to {}", num, self.name))
} }
}, },
Args::Strict(arg_types) => { Args::Strict(arg_types) => {
let idx: usize = 0; let mut idx: usize = 0;
let mut passes = args.circuit(|c: Ctr| { let passes = n_args.circuit(&mut |c: &Ctr| {
if idx >= arg_types.len() { if idx >= arg_types.len() {
return false; return false;
} }
@ -147,28 +151,28 @@ impl Function {
} }
} }
match self.function { match &self.function {
Operation::Internal(f) => Ok((f)(n_args, vars, funcs)), Operation::Internal(f) => Ok((f)(&n_args, vars, funcs)),
Operation::External(f) => { Operation::External(f) => {
// copy var table and add args // copy var table and add args
let temp = vars.clone(); let mut temp = vars.clone();
for n in 0..f.arg_syms.len() { for n in 0..f.arg_syms.len() {
temp.insert( temp.insert(
f.arg_syms[n], f.arg_syms[n].clone(),
Box::new(n_args.index(n)) 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( pub fn declare(
ft: Box<FTable>, ft: &mut Box<FTable>,
f: Box<Function> f: Box<Function>
) -> Option<String> { ) -> Option<String> {
if let Operation::External(fun) = f.function { if let Operation::External(fun) = &f.function {
if let Args::Lazy(i) = f.args { if let Args::Lazy(i) = f.args {
if fun.arg_syms.len() != i.try_into().unwrap() { if fun.arg_syms.len() != i.try_into().unwrap() {
return Some( return Some(
@ -184,17 +188,6 @@ pub fn declare(
} }
} }
ft.insert(f.name, f); ft.insert(f.name.clone(), f);
None None
} }
pub fn get(
ft: Box<FTable>,
identifier: String
) -> Option<Box<Function>> {
if let Some(f) = ft.get(&identifier) {
Some(*f)
} else {
None
}
}

View file

@ -23,8 +23,10 @@ mod vars;
pub mod ast { pub mod ast {
pub use crate::cell::{Cell, Ctr, cons, cell_as_string}; pub use crate::cell::{Cell, Ctr, cons, cell_as_string};
pub use crate::lex::{lex}; pub use crate::lex::lex;
pub use crate::func::{Function, Operation, FTable}; pub use crate::func::{Function, Operation, FTable, Args,
InternalOperation, ExternalOperation,
declare};
pub use crate::vars::VTable; pub use crate::vars::VTable;
pub use crate::eval::{eval}; pub use crate::eval::eval;
} }

View file

@ -21,14 +21,12 @@ use crate::cell::{Ctr};
/* Mapping between a string token and a tree of Cells /* Mapping between a string token and a tree of Cells
* The string token can be found in any Ctr::Symbol value * The string token can be found in any Ctr::Symbol value
* * it is expected that the trees stored are already evaluated
* Considerations: should I use a structure of cells for this?
* Current thoughts: if this was a language without proper data types, yes.
*/ */
pub type VTable = HashMap<String, Box<Ctr>>; pub type VTable = HashMap<String, Box<Ctr>>;
pub fn define( pub fn define(
vt: Box<VTable>, vt: &mut Box<VTable>,
identifier: String, identifier: String,
var_tree: Box<Ctr> var_tree: Box<Ctr>
) { ) {
@ -36,14 +34,3 @@ pub fn define(
drop(boxed_cell); drop(boxed_cell);
} }
} }
pub fn get(
vt: Box<VTable>,
identifier: String
) -> Option<Box<Ctr>> {
if let Some(c) = vt.get(&identifier) {
Some(*c)
} else {
None
}
}