This MR finishes up all remaining Pre V1 goals

* add a posix exit() builtin
* improve separation of concerns regarding standard library structure
This commit is contained in:
Ava Apples Affine 2023-05-25 23:08:44 +00:00
parent b3c0b80ee6
commit 3bbea6bea0
9 changed files with 753 additions and 752 deletions

View file

@ -18,9 +18,10 @@
use crate::eval::eval;
use crate::error::{Traceback, start_trace};
use crate::segment::{Ctr, Seg};
use crate::sym::{SymTable, Symbol};
use crate::sym::{SymTable, Symbol, ValueType, Args};
use std::rc::Rc;
pub const IF_DOCSTRING: &str =
const IF_DOCSTRING: &str =
"accepts three bodies, a condition, an unevaluated consequence, and an alternative consequence.
If the condition is evaluated to true, the first consequence is evaluated.
If the condition is evaluated to false, the second consequence is evaluated.
@ -29,8 +30,7 @@ Otherwise, an error is thrown.
example: (if my-state-switch
(do-my-thing)
(else-an-other-thing))";
pub fn if_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
fn if_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let cond: bool;
match *ast.car {
Ctr::Seg(ref cond_form) => {
@ -119,7 +119,7 @@ pub fn if_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
}
}
pub const LET_DOCSTRING: &str = "creates a stack of local variables for a sequence of operations.
const LET_DOCSTRING: &str = "creates a stack of local variables for a sequence of operations.
returns the result of the final operation.
example: (let ((step1 'hello')
@ -132,8 +132,7 @@ In this example step1, step2, and step3 are created sequentially.
Then, the echo form is evaluated, printing 'hello-world'.
Finally, the some-func form is evaluated.
Since the call to some-func is the final form, its value is returned.";
pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let mut localsyms = syms.clone();
let mut locals = vec![];
let locals_form: &Seg;
@ -250,15 +249,14 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
Ok((*result).clone())
}
pub const WHILE_DOCSTRING: &str = "traverses a list of N un-evaluated forms.
const WHILE_DOCSTRING: &str = "traverses a list of N un-evaluated forms.
the first form is expected to evaluate to a boolean. if it evaluates to false, while will stop and return. Otherwise, while will evaluate each form in a loop.
example: (while (check-my-state)
(do-thing-1 args)
(do-thing-2 args)
(edit-state my-state))";
pub fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let eval_cond: &Seg;
let outer_maybe: Seg;
let eval_bodies_head: &Seg;
@ -319,7 +317,7 @@ pub fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback>
Ok(*(result.unwrap()).clone())
}
pub const CIRCUIT_DOCSTRING: &str = "traverses a list of N un-evaluated forms.
const CIRCUIT_DOCSTRING: &str = "traverses a list of N un-evaluated forms.
evaluates each one until it stops. Circuit will stop when a form errors during evaluation.
Circuit will also stop when a form does not evaluate to a boolean, or evaluates to false.
@ -329,8 +327,7 @@ example: (circuit (eq? (do-operation) myresult)
(do-another-operation))
in this example, do-another-operation will not be called";
pub fn circuit_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
fn circuit_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let mut cursor = 0;
let mut err_trace = Traceback::new();
let result = ast.circuit(&mut |form: &Ctr| -> bool {
@ -383,3 +380,53 @@ pub fn circuit_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback
Ok(Ctr::Bool(result))
}
}
pub fn add_control_lib(syms: &mut SymTable) {
syms.insert(
"if".to_string(),
Symbol {
name: String::from("if"),
args: Args::Lazy(3),
conditional_branches: true,
docs: IF_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(if_callback)),
..Default::default()
},
);
syms.insert(
"let".to_string(),
Symbol {
name: String::from("let"),
args: Args::Infinite,
conditional_branches: true,
docs: LET_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(let_callback)),
..Default::default()
},
);
syms.insert(
"while".to_string(),
Symbol {
name: String::from("while"),
args: Args::Infinite,
conditional_branches: true,
docs: WHILE_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(while_callback)),
..Default::default()
},
);
syms.insert(
"circuit".to_string(),
Symbol {
name: String::from("circuit"),
args: Args::Infinite,
conditional_branches: true,
docs: CIRCUIT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(circuit_callback)),
..Default::default()
},
);
}