feat(prelude): add define/defun
This commit is contained in:
parent
5275bc33a8
commit
fd98aa4a96
@ -13,6 +13,8 @@ fn main() {
|
|||||||
"(pow 2 10)",
|
"(pow 2 10)",
|
||||||
"(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))",
|
"(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))",
|
||||||
"(let '((a . (vec3 1 2 3)) (b . (vec3 4 5 6))) (vec3-dot (vec3-norm (vec3-add a b)) a))",
|
"(let '((a . (vec3 1 2 3)) (b . (vec3 4 5 6))) (vec3-dot (vec3-norm (vec3-add a b)) a))",
|
||||||
|
"(defun do-n-times (f n) (if (= n 0) '() (cons (f) (do-n-times f (- n 1)))))",
|
||||||
|
"(do-n-times (lambda () (print 'hello)) 5)",
|
||||||
];
|
];
|
||||||
|
|
||||||
let environment = Environment::default();
|
let environment = Environment::default();
|
||||||
|
|||||||
@ -94,6 +94,40 @@ pub fn prelude_lambda(_env: &Environment, expr: Expression) -> Result<Expression
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prelude_defun(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [name, args, body]: [Expression; 3] = expr.try_into()?;
|
||||||
|
let name = match name {
|
||||||
|
Expression::Symbol(s) => s,
|
||||||
|
x => return Err(EvalError::NotASymbol(x)),
|
||||||
|
};
|
||||||
|
let mut arg_exprs: Vec<Expression> = args.try_into()?;
|
||||||
|
let argument_symbols: Vec<String> = arg_exprs
|
||||||
|
.iter_mut()
|
||||||
|
.map(|a| match a.to_owned() {
|
||||||
|
Expression::Symbol(s) => Ok(s),
|
||||||
|
x => Err(EvalError::NotASymbol(x)),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<String>, EvalError>>()?;
|
||||||
|
|
||||||
|
let f = Expression::AnonymousFunction {
|
||||||
|
argument_symbols,
|
||||||
|
body: Box::new(body),
|
||||||
|
};
|
||||||
|
env.shared_set(name, f.clone());
|
||||||
|
Ok(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prelude_define(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [name, value] = expr.try_into()?;
|
||||||
|
let name = match name {
|
||||||
|
Expression::Symbol(s) => s,
|
||||||
|
x => return Err(EvalError::NotASymbol(x)),
|
||||||
|
};
|
||||||
|
let value = eval(env, value)?;
|
||||||
|
env.shared_set(name, value.clone());
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
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()?;
|
||||||
|
|
||||||
@ -160,7 +194,7 @@ pub fn prelude_gt(env: &Environment, expr: Expression) -> Result<Expression, Eva
|
|||||||
|
|
||||||
pub fn prelude_not(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
pub fn prelude_not(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
let [a] = expr.try_into()?;
|
let [a] = expr.try_into()?;
|
||||||
match a {
|
match eval(env, a)? {
|
||||||
Expression::Nil => Ok(Expression::True),
|
Expression::Nil => Ok(Expression::True),
|
||||||
_ => Ok(Expression::Nil),
|
_ => Ok(Expression::Nil),
|
||||||
}
|
}
|
||||||
@ -217,6 +251,8 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
|||||||
layer.set("*".to_string(), Expression::Function(prelude_mul));
|
layer.set("*".to_string(), Expression::Function(prelude_mul));
|
||||||
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("defun".to_string(), Expression::Function(prelude_defun));
|
||||||
|
layer.set("define".to_string(), Expression::Function(prelude_define));
|
||||||
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));
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use as_any::AsAny;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
environment::{Environment, EnvironmentLayer},
|
environment::{Environment, EnvironmentLayer},
|
||||||
eval::{eval, EvalError},
|
eval::{eval, EvalError},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user