From cc6c9ed98b37967fe03319b6e2974896312888b8 Mon Sep 17 00:00:00 2001 From: yoyo Date: Wed, 11 Sep 2024 13:44:56 +0900 Subject: [PATCH] add fnlet --- bltin.c | 3 +++ dat.h | 1 + eval.c | 35 +++++++++++++++++++++++++---------- obj.c | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/bltin.c b/bltin.c index 09c7e95..1d3a086 100644 --- a/bltin.c +++ b/bltin.c @@ -20,6 +20,7 @@ Object Not = (Object){.type=OBLTIN, .beg= "not"}; Object Bquote= (Object){.type=OBLTIN, .beg="`"}; Object Lambda= (Object){.type=OBLTIN, .beg="lambda"}; +Object Let= (Object){.type=OBLTIN, .beg="let"}; Object Progn=(Object){.type=OBLTIN, .beg="progn"}; Object Car = (Object){.type=OBLTIN, .beg="car"}; Object Cdr = (Object){.type=OBLTIN, .beg="cdr"}; @@ -35,6 +36,7 @@ extern Object* fnmul(Object *, Object *); extern Object* fndiv(Object *, Object *); extern Object* fnmod(Object *, Object *); extern Object* fnlambda(Object *, Object *); +extern Object* fnlet(Object *, Object *); extern Object* fnprogn(Object *, Object *); extern Object* fndefine(Object *, Object *); extern Object* fnmacro(Object *, Object *); @@ -72,6 +74,7 @@ bltinlookup(Object *obj) {&Define ,fndefine}, {&Macro ,fnmacro}, {&Setq ,fnsetq}, + {&Let ,fnlet}, {&Quote ,fnquote}, {&Bquote, fnbquote}, {&Car ,fncar}, diff --git a/dat.h b/dat.h index c661949..cfd3dc2 100644 --- a/dat.h +++ b/dat.h @@ -69,6 +69,7 @@ extern Object Define; extern Object Progn; extern Object Macro; extern Object Setq; +extern Object Let; extern Object Eq; extern Object Not; extern Object Ne; diff --git a/eval.c b/eval.c index 5ebb5ba..8a819f6 100644 --- a/eval.c +++ b/eval.c @@ -130,26 +130,41 @@ fnprogn(Object *env, Object *list) Object* fnsetq(Object *env, Object *list) { - if(exprlen(list)!=2 || list->car->type!=OIDENT) + if(list->type != OCELL || exprlen(list)!=2 || list->car->type!=OIDENT) error("Malformed setq"); Object *cur = env; - Object *p = 0; + Object *p = &Nil; for(; cur!=&Nil; cur=cur->up) - for(p=cur->vars; p!=&Nil; p=p->cdr) - if(strequal(list->car, p->car->car)) - goto found; + for(p=cur->vars; p!=&Nil; p=cdr(p)) + if(strequal(list->car, car(car(p)))) + return p->car->cdr = eval(env, car(cdr(list))); error("setq not exist variable"); -found:; - return p->car->cdr = eval(env, list->cdr->car); + return 0; +} + +Object* +fnlet(Object *env, Object *list) +{ + if(exprlen(list) < 2) + error("let (vars) bodys"); + Object *nenv = newenv(gc, &Nil, &Nil, env) ; + for(Object *p=list->car; p!=&Nil; p=cdr(p)){ + Object *var = car(car(p)); + if(var->type != OIDENT) + error("expected ident"); + Object *val = eval(env, car(cdr(car(p)))); + nenv->vars = newacons(gc, var, val, nenv->vars); + } + return progn(nenv, cdr(list)); } Object* fndefine(Object *env, Object *list) { - if(exprlen(list)!=2 || list->car->type!=OIDENT) + if(exprlen(list)!=2 || car(list)->type!=OIDENT) error("Malformed define"); - Object *val = eval(env, list->cdr->car); - env->vars = defvar(env, list->car, val); + Object *val = eval(env, car(cdr(list))); + env->vars = defvar(env, car(list), val); return val; } diff --git a/obj.c b/obj.c index 15e1627..8e1213e 100644 --- a/obj.c +++ b/obj.c @@ -63,7 +63,7 @@ newsymbol(GC *gc, char *str, int len) &Nil, &Minus, &Plus, &Mul, &Mod, &Div, &Ge, &Le, &Lt, &Gt, &Ne, &Lambda, &Car, &Cdr, &Quote, &Cons, &Define, &Setq, &Eq, &If, &Macro, &Progn, &Bquote, - &Comma, &Not, &Splice, + &Comma, &Not, &Splice, &Let, }; for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){ Object *c = syms[i];