Fully fledged lambdas, along with efficiency tweaks across the ast
This commit is contained in:
parent
b0bd369c1d
commit
8efa1dbaad
10 changed files with 264 additions and 70 deletions
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
use crate::eval::eval;
|
||||
use crate::segment::{Ctr, Seg};
|
||||
use crate::sym::{Args, SymTable, Symbol, UserFn, ValueType};
|
||||
use crate::sym::{SymTable, Symbol, UserFn, ValueType};
|
||||
use std::env;
|
||||
|
||||
pub const QUOTE_DOCSTRING: &str = "takes a single unevaluated tree and returns it as it is: unevaluated.";
|
||||
|
|
@ -101,6 +101,7 @@ pub const STORE_DOCSTRING: &str = "allows user to define functions and variables
|
|||
(def useless-var)";
|
||||
|
||||
pub fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr, String> {
|
||||
println!("def: {}", ast);
|
||||
let is_var = ast.len() == 3;
|
||||
if let Ctr::Symbol(ref identifier) = *ast.car {
|
||||
match &*ast.cdr {
|
||||
|
|
@ -109,27 +110,40 @@ pub fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<C
|
|||
if let Ctr::String(ref doc) = *doc_tree.car {
|
||||
match &*doc_tree.cdr {
|
||||
// define a variable
|
||||
Ctr::Seg(data_tree) if is_var => match eval(&Box::new(data_tree), syms) {
|
||||
Ok(seg) => {
|
||||
if let Ctr::Seg(ref val) = *seg {
|
||||
Ctr::Seg(data_tree) if is_var => {
|
||||
let eval_arg: &Seg;
|
||||
let outer_maybe_eval_seg: Seg;
|
||||
let mut expand = false;
|
||||
if let Ctr::Seg(ref eval_me) = *data_tree.car {
|
||||
eval_arg = eval_me;
|
||||
} else {
|
||||
outer_maybe_eval_seg = Seg::from_mono(data_tree.car.clone());
|
||||
eval_arg = &outer_maybe_eval_seg;
|
||||
expand = true;
|
||||
}
|
||||
match eval(eval_arg, syms) {
|
||||
Ok(ctr) => {
|
||||
let mut body = ctr;
|
||||
if expand {
|
||||
if let Ctr::Seg(ref s) = *body {
|
||||
body = s.car.clone();
|
||||
} else {
|
||||
return Err("impossible expansion".to_string())
|
||||
}
|
||||
}
|
||||
syms.insert(
|
||||
identifier.clone(),
|
||||
Symbol {
|
||||
value: ValueType::VarForm(val.car.clone()),
|
||||
name: identifier.clone(),
|
||||
args: Args::None,
|
||||
docs: doc.to_owned(),
|
||||
conditional_branches: false,
|
||||
},
|
||||
Symbol::from_ast(
|
||||
identifier, doc,
|
||||
&Seg::from_mono(body.clone()), None
|
||||
),
|
||||
);
|
||||
if env_cfg {
|
||||
env::set_var(identifier.clone(), val.car.to_string());
|
||||
env::set_var(identifier.clone(), body.to_string());
|
||||
}
|
||||
} else {
|
||||
return Err("impossible args to export".to_string());
|
||||
}
|
||||
Err(e) => return Err(format!("couldnt eval symbol: {}", e)),
|
||||
}
|
||||
Err(e) => return Err(format!("couldnt eval symbol: {}", e)),
|
||||
},
|
||||
|
||||
// define a function
|
||||
|
|
@ -157,16 +171,10 @@ pub fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<C
|
|||
if let Ctr::Seg(ref bodies) = *data_tree.cdr {
|
||||
syms.insert(
|
||||
identifier.clone(),
|
||||
Symbol {
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
ast: Box::new(bodies.clone()),
|
||||
arg_syms: arg_list.clone(),
|
||||
}),
|
||||
name: identifier.clone(),
|
||||
args: Args::Lazy(arg_list.len() as u128),
|
||||
docs: doc.to_owned(),
|
||||
conditional_branches: false,
|
||||
},
|
||||
Symbol::from_ast(
|
||||
identifier, doc, bodies,
|
||||
Some(arg_list),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Err(
|
||||
|
|
@ -266,6 +274,9 @@ pub fn lambda_callback(
|
|||
if let Ctr::Symbol(ref s) = *arg {
|
||||
args.push(s.clone());
|
||||
true
|
||||
} else if let Ctr::None = *arg {
|
||||
// no args case
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
@ -273,10 +284,14 @@ pub fn lambda_callback(
|
|||
Err("all elements of first argumnets must be symbols".to_string())
|
||||
} else {
|
||||
if let Ctr::Seg(ref eval_head) = *ast.cdr {
|
||||
Ok(Ctr::Lambda(UserFn{
|
||||
ast: Box::new(eval_head.clone()),
|
||||
arg_syms: args,
|
||||
}))
|
||||
if let Ctr::Seg(_) = *eval_head.car {
|
||||
Ok(Ctr::Lambda(UserFn{
|
||||
ast: Box::new(eval_head.clone()),
|
||||
arg_syms: args,
|
||||
}))
|
||||
} else {
|
||||
Err("function body must be in list form".to_string())
|
||||
}
|
||||
} else {
|
||||
Err("not enough args".to_string())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue