add fnlet

This commit is contained in:
yoyo 2024-09-11 13:44:56 +09:00
parent b1451a2380
commit cc6c9ed98b
4 changed files with 30 additions and 11 deletions

View File

@ -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},

1
dat.h
View File

@ -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;

35
eval.c
View File

@ -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;
}

2
obj.c
View File

@ -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];