add fnlet
This commit is contained in:
parent
b1451a2380
commit
cc6c9ed98b
3
bltin.c
3
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},
|
||||
|
||||
1
dat.h
1
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;
|
||||
|
||||
35
eval.c
35
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;
|
||||
}
|
||||
|
||||
|
||||
2
obj.c
2
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];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user