feat(prelude): add more std functions

This commit is contained in:
Jonas Röger 2024-11-06 13:43:18 +01:00
parent efe1a7877b
commit eb2cda854f
Signed by: jonas
GPG Key ID: 4000EB35E1AE0F07
2 changed files with 56 additions and 13 deletions

View File

@ -97,7 +97,7 @@ pub fn prelude_lambda(_env: &Environment, expr: Expression) -> Result<Expression
pub fn prelude_let(env: &Environment, expr: Expression) -> Result<Expression, EvalError> { pub fn prelude_let(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [bindings, body] = expr.try_into()?; let [bindings, body] = expr.try_into()?;
let bindings = CellIterator::new(bindings) let bindings = CellIterator::new(eval(env, bindings)?)
.map(|e| { .map(|e| {
let (s, e) = e?.try_into()?; let (s, e) = e?.try_into()?;
if let Expression::Symbol(s) = s { if let Expression::Symbol(s) = s {
@ -158,6 +158,14 @@ pub fn prelude_gt(env: &Environment, expr: Expression) -> Result<Expression, Eva
} }
} }
pub fn prelude_not(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [a] = expr.try_into()?;
match a {
Expression::Nil => Ok(Expression::True),
_ => Ok(Expression::Nil),
}
}
pub fn prelude_set(env: &Environment, expr: Expression) -> Result<Expression, EvalError> { pub fn prelude_set(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [s, e] = expr.try_into()?; let [s, e] = expr.try_into()?;
@ -178,6 +186,31 @@ pub fn prelude_print(env: &Environment, expr: Expression) -> Result<Expression,
Ok(e) Ok(e)
} }
pub fn prelude_cons(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [a, b] = expr.try_into()?;
Ok(Expression::Cell(
Box::new(eval(env, a)?),
Box::new(eval(env, b)?),
))
}
pub fn prelude_car(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [arg] = expr.try_into()?;
let (a, _) = eval(env, arg)?.try_into()?;
Ok(a)
}
pub fn prelude_cdr(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [arg] = expr.try_into()?;
let (_, b) = eval(env, arg)?.try_into()?;
Ok(b)
}
pub fn prelude_eval(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [e] = expr.try_into()?;
eval(env, eval(env, e)?)
}
pub fn mk_prelude(layer: &mut EnvironmentLayer) { pub fn mk_prelude(layer: &mut EnvironmentLayer) {
layer.set("+".to_string(), Expression::Function(prelude_add)); layer.set("+".to_string(), Expression::Function(prelude_add));
layer.set("-".to_string(), Expression::Function(prelude_sub)); layer.set("-".to_string(), Expression::Function(prelude_sub));
@ -185,10 +218,15 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) {
layer.set("/".to_string(), Expression::Function(prelude_div)); layer.set("/".to_string(), Expression::Function(prelude_div));
layer.set("lambda".to_string(), Expression::Function(prelude_lambda)); layer.set("lambda".to_string(), Expression::Function(prelude_lambda));
layer.set("if".to_string(), Expression::Function(prelude_if)); layer.set("if".to_string(), Expression::Function(prelude_if));
layer.set("==".to_string(), Expression::Function(prelude_eq)); layer.set("=".to_string(), Expression::Function(prelude_eq));
layer.set("<".to_string(), Expression::Function(prelude_lt)); layer.set("<".to_string(), Expression::Function(prelude_lt));
layer.set(">".to_string(), Expression::Function(prelude_gt)); layer.set(">".to_string(), Expression::Function(prelude_gt));
layer.set("not".to_string(), Expression::Function(prelude_not));
layer.set("let".to_string(), Expression::Function(prelude_let)); layer.set("let".to_string(), Expression::Function(prelude_let));
layer.set("set".to_string(), Expression::Function(prelude_set)); layer.set("set".to_string(), Expression::Function(prelude_set));
layer.set("print".to_string(), Expression::Function(prelude_print)); layer.set("print".to_string(), Expression::Function(prelude_print));
layer.set("cons".to_string(), Expression::Function(prelude_cons));
layer.set("car".to_string(), Expression::Function(prelude_car));
layer.set("cdr".to_string(), Expression::Function(prelude_cdr));
layer.set("eval".to_string(), Expression::Function(prelude_eval));
} }

View File

@ -5,20 +5,26 @@ use parser::ExpressionStream;
use crate::lisp::{eval, Environment}; use crate::lisp::{eval, Environment};
fn main() { fn main() {
let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)"; let programs = [
let program2 = "(set 'myvar \"hello world!\")"; "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)",
let program3 = "(print myvar) (print 'myvar)"; "(set 'myvar \"hello world!\")",
"(print myvar) (print 'myvar)",
"(car (cons 'a 'b)) (cdr (cons 'c 'd)) (cons 'a 'b)",
"(eval (car (cons 'myvar 'b)))",
"(set 'pow (lambda (a b) (if (= b 0) 1 (* a (pow a (- b 1))))))",
"pow",
"(pow 2 10)",
"(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))",
];
let environment = Environment::default(); let environment = Environment::default();
for r in ExpressionStream::from_char_stream( for r in ExpressionStream::from_char_stream(programs.iter().map(|p| p.chars()).flatten()) {
program1
.chars()
.chain(program2.chars())
.chain(program3.chars()),
) {
match r { match r {
Err(err) => println!("ParserError: {:?}", err), Err(err) => {
println!("ParserError: {:?}", err);
break;
}
Ok(expr) => { Ok(expr) => {
println!("Evaluating: {}", expr.clone()); println!("Evaluating: {}", expr.clone());
match eval(&environment, expr) { match eval(&environment, expr) {
@ -30,5 +36,4 @@ fn main() {
} }
println!("Interpreter Done!"); println!("Interpreter Done!");
println!("Environment: {:?}", environment);
} }