finished circuit form
Signed-off-by: Ava Hahn <ava@aidanis.online>
This commit is contained in:
parent
c235f9727f
commit
4b587f11ab
7 changed files with 144 additions and 53 deletions
|
|
@ -65,28 +65,32 @@ pub fn bool_not_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String>
|
|||
|
||||
pub fn bool_iseq_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
let head_ctr_ref = &*ast.car;
|
||||
Ok(Ctr::Bool(ast.circuit(&mut |arg: &Ctr| -> bool {arg == head_ctr_ref})))
|
||||
Ok(Ctr::Bool(
|
||||
ast.circuit(&mut |arg: &Ctr| -> bool { arg == head_ctr_ref }),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn bool_toggle_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
let var_name: String;
|
||||
if let Ctr::Symbol(ref s) = *ast.car {
|
||||
var_name = s.clone();
|
||||
if let Ctr::Symbol(ref s) = *ast.car {
|
||||
var_name = s.clone();
|
||||
} else {
|
||||
return Err("argument to toggle should be a symbol".to_string())
|
||||
return Err("argument to toggle should be a symbol".to_string());
|
||||
}
|
||||
|
||||
let mut sym = syms.remove(&var_name).expect(&format!("symbol {var_name} is not defined"));
|
||||
let mut sym = syms
|
||||
.remove(&var_name)
|
||||
.expect(&format!("symbol {var_name} is not defined"));
|
||||
if let ValueType::VarForm(ref var) = sym.value {
|
||||
if let Ctr::Bool(ref b) = **var {
|
||||
sym.value = ValueType::VarForm(Box::new(Ctr::Bool(!b)));
|
||||
} else {
|
||||
syms.insert(var_name, sym);
|
||||
return Err("can only toggle a boolean".to_string())
|
||||
return Err("can only toggle a boolean".to_string());
|
||||
}
|
||||
} else {
|
||||
syms.insert(var_name, sym);
|
||||
return Err("cannot toggle a function".to_string())
|
||||
return Err("cannot toggle a function".to_string());
|
||||
}
|
||||
|
||||
syms.insert(var_name, sym);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
use crate::eval::eval;
|
||||
use crate::segment::{Ctr, Seg};
|
||||
use crate::sym::{SymTable, Symbol, ValueType, Args};
|
||||
use crate::sym::{Args, SymTable, Symbol, ValueType};
|
||||
|
||||
pub fn if_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
let cond: bool;
|
||||
|
|
@ -32,10 +32,7 @@ pub fn if_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
}
|
||||
|
||||
Ctr::Symbol(ref cond_name) => {
|
||||
if let Ctr::Bool(cond_from_eval) = *syms.call_symbol(
|
||||
cond_name,
|
||||
&Seg::new(), false
|
||||
)? {
|
||||
if let Ctr::Bool(cond_from_eval) = *syms.call_symbol(cond_name, &Seg::new(), false)? {
|
||||
cond = cond_from_eval;
|
||||
} else {
|
||||
return Err("first argument to if must evaluate to be a boolean".to_string());
|
||||
|
|
@ -95,13 +92,13 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
if let Ctr::Seg(ref locals_form_list) = *ast.car {
|
||||
locals_form = locals_form_list;
|
||||
} else {
|
||||
return Err("first element of let form must contain local variables".to_string())
|
||||
return Err("first element of let form must contain local variables".to_string());
|
||||
}
|
||||
|
||||
if let Ctr::Seg(ref eval_forms_head) = *ast.cdr {
|
||||
eval_forms = eval_forms_head;
|
||||
} else {
|
||||
return Err("let form should contain one or more elements to evaluate".to_string())
|
||||
return Err("let form should contain one or more elements to evaluate".to_string());
|
||||
}
|
||||
|
||||
// process locals forms
|
||||
|
|
@ -125,27 +122,30 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
}
|
||||
if let Err(e) = var_val_res {
|
||||
eprintln!("failed to evaluate definition of {}: {}", name, e);
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
localsyms.insert(name.clone(), Symbol {
|
||||
name: name.clone(),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
value: ValueType::VarForm(Box::new(*var_val_res.unwrap().clone())),
|
||||
});
|
||||
localsyms.insert(
|
||||
name.clone(),
|
||||
Symbol {
|
||||
name: name.clone(),
|
||||
args: Args::None,
|
||||
conditional_branches: false,
|
||||
value: ValueType::VarForm(Box::new(*var_val_res.unwrap().clone())),
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
eprintln!("improper declaration of {}: not a list", var_decl);
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
eprintln!("improper declaration form: {}", var_decl);
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}) {
|
||||
return Err("local variable declaration failure".to_string())
|
||||
return Err("local variable declaration failure".to_string());
|
||||
}
|
||||
|
||||
let mut result: Box<Ctr> = Box::new(Ctr::None);
|
||||
|
|
@ -167,13 +167,13 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
|
||||
if let Err(e) = res {
|
||||
eprintln!("error evaluating let form: {}", e);
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
result = res.unwrap().clone();
|
||||
true
|
||||
}) {
|
||||
return Err("evaluation failure".to_string())
|
||||
return Err("evaluation failure".to_string());
|
||||
}
|
||||
|
||||
Ok((*result).clone())
|
||||
|
|
@ -200,7 +200,7 @@ pub fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
if let Ctr::Seg(ref eval) = *ast.cdr {
|
||||
eval_bodies_head = eval;
|
||||
} else {
|
||||
return Err("expected N more bodies in while form".to_string())
|
||||
return Err("expected N more bodies in while form".to_string());
|
||||
}
|
||||
|
||||
loop {
|
||||
|
|
@ -208,15 +208,19 @@ pub fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
if unwrap {
|
||||
if let Ctr::Seg(ref cond_res_inner) = cond_res {
|
||||
if let Ctr::Bool(ref b) = *cond_res_inner.car {
|
||||
if !b {break}
|
||||
if !b {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else if let Ctr::Bool(b) = cond_res {
|
||||
if !b {break}
|
||||
if !b {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return Err("first body of while form should evaluate to a bool".to_string())
|
||||
return Err("first body of while form should evaluate to a bool".to_string());
|
||||
}
|
||||
|
||||
if !eval_bodies_head.circuit(&mut |body: &Ctr| -> bool {
|
||||
|
|
@ -242,7 +246,49 @@ pub fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
|||
/*
|
||||
(circuit makes_a_bool makes_a_bool makes_a_bool makes_a_bool ... )
|
||||
*/
|
||||
pub fn circuit_callback(_ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
todo!()
|
||||
}
|
||||
pub fn circuit_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
let mut cursor = 0;
|
||||
let mut error: String = String::new();
|
||||
let result = ast.circuit(&mut |form: &Ctr| -> bool {
|
||||
cursor += 1;
|
||||
let operand: &Seg;
|
||||
let mut expand_eval_res = false;
|
||||
let outer_scope_seg: Seg;
|
||||
if let Ctr::Seg(ref s) = form {
|
||||
operand = s;
|
||||
} else {
|
||||
outer_scope_seg = Seg::from_mono(Box::new(form.clone()));
|
||||
operand = &outer_scope_seg;
|
||||
expand_eval_res = true;
|
||||
}
|
||||
|
||||
let eval_result = eval(operand, syms);
|
||||
match eval_result {
|
||||
Err(s) => error = format!("eval failed at form {cursor}: {s}"),
|
||||
Ok(s) => match *s {
|
||||
Ctr::Bool(b) => return b,
|
||||
|
||||
Ctr::Seg(s) if expand_eval_res => {
|
||||
if let Ctr::Bool(b) = *s.car {
|
||||
return b;
|
||||
} else {
|
||||
error = "impossible condition in circuit form".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
_ => error = format!("{cursor} form did not evaluate to a boolean"),
|
||||
},
|
||||
}
|
||||
|
||||
false
|
||||
});
|
||||
|
||||
if !result && !error.is_empty() {
|
||||
Err(format!("circuit stopped at form {cursor}: {error}"))
|
||||
} else {
|
||||
if !result {
|
||||
eprintln!("circuit stopped at form {cursor}");
|
||||
}
|
||||
Ok(Ctr::Bool(result))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue