feat(prelude): add more std functions
This commit is contained in:
parent
efe1a7877b
commit
eb2cda854f
@ -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> {
|
||||
let [bindings, body] = expr.try_into()?;
|
||||
|
||||
let bindings = CellIterator::new(bindings)
|
||||
let bindings = CellIterator::new(eval(env, bindings)?)
|
||||
.map(|e| {
|
||||
let (s, e) = e?.try_into()?;
|
||||
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> {
|
||||
let [s, e] = expr.try_into()?;
|
||||
|
||||
@ -178,6 +186,31 @@ pub fn prelude_print(env: &Environment, expr: Expression) -> Result<Expression,
|
||||
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) {
|
||||
layer.set("+".to_string(), Expression::Function(prelude_add));
|
||||
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("lambda".to_string(), Expression::Function(prelude_lambda));
|
||||
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_gt));
|
||||
layer.set("not".to_string(), Expression::Function(prelude_not));
|
||||
layer.set("let".to_string(), Expression::Function(prelude_let));
|
||||
layer.set("set".to_string(), Expression::Function(prelude_set));
|
||||
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));
|
||||
}
|
||||
|
||||
27
src/main.rs
27
src/main.rs
@ -5,20 +5,26 @@ use parser::ExpressionStream;
|
||||
use crate::lisp::{eval, Environment};
|
||||
|
||||
fn main() {
|
||||
let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)";
|
||||
let program2 = "(set 'myvar \"hello world!\")";
|
||||
let program3 = "(print myvar) (print 'myvar)";
|
||||
let programs = [
|
||||
"((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)",
|
||||
"(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();
|
||||
|
||||
for r in ExpressionStream::from_char_stream(
|
||||
program1
|
||||
.chars()
|
||||
.chain(program2.chars())
|
||||
.chain(program3.chars()),
|
||||
) {
|
||||
for r in ExpressionStream::from_char_stream(programs.iter().map(|p| p.chars()).flatten()) {
|
||||
match r {
|
||||
Err(err) => println!("ParserError: {:?}", err),
|
||||
Err(err) => {
|
||||
println!("ParserError: {:?}", err);
|
||||
break;
|
||||
}
|
||||
Ok(expr) => {
|
||||
println!("Evaluating: {}", expr.clone());
|
||||
match eval(&environment, expr) {
|
||||
@ -30,5 +36,4 @@ fn main() {
|
||||
}
|
||||
|
||||
println!("Interpreter Done!");
|
||||
println!("Environment: {:?}", environment);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user