Commits

knarf committed cf3222a

implemented lexically scoped let form.

  • Participants
  • Parent commits 375685e

Comments (0)

Files changed (2)

File lisp

Binary file modified.
 typedef char sym_t[SYM_NAME_SIZE];
 
 obj_t *fn_begin(obj_t *arg, env_t *env);
+obj_t *fn_let(obj_t *arg, env_t *env);
 obj_t *fn_lambda(obj_t *arg, env_t *env);
 obj_t *fn_quote(obj_t *arg, env_t *env);
 obj_t *fn_plus(obj_t *arg, env_t *env);
 int eof(void);
 
 /*
-   notes:
-   - implement let
+   TODO:
+   - expose macros definition
+   - make parser more robust
+   - implement more type (string, char, double, ...)
 */
 
 enum {
     } while(0)
 
 
+/* convert let form into lambda */
+obj_t* fn_let (obj_t* arg, env_t* env)
+{
+    obj_t *p, *parg, *pval, *varlist, *arglist, *vallist, *body;
+
+    varlist = CAR(arg);
+    body = CDR(arg);
+    arglist = Onil;
+    vallist = Onil;
+
+    if(varlist->t != CONS)
+        goto err;
+
+    /* take care of the args */
+    for(p = varlist; p != Onil; p = CDR(p)) {
+        obj_t* c = CAR(p);
+
+        if(c->t != CONS || CDR(c) == Onil)
+            goto err;
+
+        obj_t* sym = CAR(c);
+        obj_t* val = CAR(CDR(c));
+
+        if(sym->t != SYM)
+            goto err;
+
+        if(arglist == Onil) {
+            arglist = mk_cons(sym, Onil);
+            parg = arglist;
+            vallist = mk_cons(val, Onil);
+            pval = vallist;
+        } else {
+            CDR(parg) = mk_cons(sym, Onil);
+            parg = CDR(parg);
+            CDR(pval) = mk_cons(val, Onil);
+            pval = CDR(pval);
+        }
+    }
+
+    obj_t* la = mk_obj(LAMBDA);
+    la->lambda.env = env;
+    la->lambda.arg = arglist;
+    la->lambda.body = body;
+
+    return eval_lambda(la, vallist, env);
+
+ err:
+    ERR("bad let form. correct ex: (let ((a 1)) a)");
+}
+
 obj_t* fn_begin (obj_t* arg, env_t* env)
 {
     obj_t* p;
     EXPORT("quote",  mk_fun(fn_quote,  ARG_QUOTE));
     EXPORT("if",     mk_fun(fn_if,     ARG_QUOTE));
     EXPORT("lambda", mk_fun(fn_lambda, ARG_QUOTE));
+    EXPORT("let",    mk_fun(fn_let,    ARG_QUOTE));
     EXPORT("and",    mk_fun(fn_and,    ARG_QUOTE));
     EXPORT("or",     mk_fun(fn_or,     ARG_QUOTE));
     EXPORT("not",    mk_fun(fn_not,    ARG_QUOTE));