finished circuit form

Signed-off-by: Ava Hahn <ava@aidanis.online>
This commit is contained in:
Ava Hahn 2023-03-03 14:29:53 -08:00
parent c235f9727f
commit 4b587f11ab
Signed by untrusted user who does not match committer: affine
GPG key ID: 3A4645B8CF806069
7 changed files with 144 additions and 53 deletions

View file

@ -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);

View file

@ -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))
}
}