diff --git a/build.soft b/build.soft new file mode 100644 index 0000000..d76521c --- /dev/null +++ b/build.soft @@ -0,0 +1,4 @@ +(require '[stdlib.soft]) + +(println (-> stdlib/args + (map (fun [x] (str "Hello " x))))) diff --git a/src/eval.rs b/src/eval.rs index 407a815..a57fa2c 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -47,9 +47,7 @@ pub enum Value { String(String), Float(u64), Fun(Fun), - List { - elements: Vec, - }, + List(Vec), Apply { callee: Box, arguments: Vec, @@ -208,13 +206,12 @@ impl Expr { // Base cases for expansion when it will just walk the tree. These // are the cases where the expansion is recursive. - Expr::List(list) => Ok(Value::List { - elements: list - .elements()? + Expr::List(list) => Ok(Value::List( + list.elements()? .into_iter() .map(|expr| expr.expand(environment)) .collect::, _>>()?, - }), + )), Expr::Def(def) => Ok(Value::Def { name: def.name()?.expand(environment)?.try_into()?, value: def.value()?.expand(environment)?.into(), @@ -261,10 +258,12 @@ impl Expr { Expr::Literal(_) => Err(keyword!("eval.error/invalid-literal")), } } +} +impl Value { /// Evaluate the expression into a value. pub fn eval(self, environment: &Environment) -> Trampoline { - match self.expand(environment)? { + match self { Value::Deref { box value, .. } => { let Value::Atomic(atomic) = value else { bail!(keyword!("eval.error/atomic-expected")) @@ -273,7 +272,20 @@ impl Expr { Done(guard.clone()) } + Value::Apply { callee, arguments } => { + todo!() + } + Value::List(old_elements) => { + let mut new_elements = Vec::new(); + for element in old_elements { + new_elements.push(element.eval(environment)?); + } + + Done(Value::List(new_elements)) + } + // Base cases for evaluation when it will just walk the tree. These + // are the cases where the evaluation is recursive. value => Done(value), } } diff --git a/stdlib.soft b/stdlib.soft new file mode 100644 index 0000000..7ebcf7a --- /dev/null +++ b/stdlib.soft @@ -0,0 +1,15 @@ +(defmacro* map* (fun* [f coll] + (if (cons? coll) + (cons (f (car coll)) (map* f (cdr coll))) + coll))) + +(defmacro* quasi-quote (fun* [form] + (if (cons? form) + (if (= 'unquote (car form)) + (cdr form) + (cons 'list (map* quasi-quote form))) + (list 'quote form)))) + +(defmacro* defmacro [name args & body] + (let [body (cons 'block body)] + `(defmacro* ,name (fun* ,args ,body))))