Assert, Exit builtins

* Builtins for assert and exit are added
* Tests for assert are added
* file operations from previous MR are added to documents
* assert and exit are added to documents
This commit is contained in:
Ava Apples Affine 2023-06-20 01:25:19 +00:00
parent 270cc32572
commit 2cd5016c1d
6 changed files with 119 additions and 34 deletions

View file

@ -17,9 +17,10 @@
use crate::eval::eval;
use crate::error::{Traceback, start_trace};
use crate::segment::{Ctr, Seg};
use crate::segment::{Ctr, Seg, Type};
use crate::sym::{SymTable, Symbol, ValueType, Args};
use std::rc::Rc;
use std::process;
const IF_DOCSTRING: &str =
"accepts three bodies, a condition, an unevaluated consequence, and an alternative consequence.
@ -381,7 +382,60 @@ fn circuit_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
}
}
const ASSERT_DOCSTRING: &str = "Takes one input: a boolean (or form that evaluates to a boolean).
If input is false, a traceback is started and code throws an error.
Otherwise, if input is true, returns None.";
fn assert_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::Bool(b) = *ast.car {
if b {
Ok(Ctr::None)
} else {
Err(start_trace(("assert", "assertion failed").into()))
}
} else {
Err(start_trace(("assert", "impossible arg").into()))
}
}
const EXIT_DOCSTRING: &str = "Takes on input: an integer used as an exit code.
Entire REPL process quits with exit code.";
fn exit_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::Integer(i) = *ast.car {
if i > 2 ^ 32 {
panic!("argument to exit too large!")
} else {
process::exit(i as i32);
}
} else {
panic!("impossible argument to exit")
}
}
pub fn add_control_lib(syms: &mut SymTable) {
syms.insert(
"exit".to_string(),
Symbol {
name: String::from("exit"),
args: Args::Strict(vec![Type::Integer]),
conditional_branches: false,
docs: EXIT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(exit_callback)),
..Default::default()
},
);
syms.insert(
"assert".to_string(),
Symbol {
name: String::from("assert"),
args: Args::Strict(vec![Type::Bool]),
conditional_branches: false,
docs: ASSERT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(assert_callback)),
..Default::default()
},
);
syms.insert(
"if".to_string(),
Symbol {