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:
parent
d2f60314f9
commit
76b12a8214
5 changed files with 44 additions and 63 deletions
21
src/cell.rs
21
src/cell.rs
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
55
src/func.rs
55
src/func.rs
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/vars.rs
17
src/vars.rs
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue