Compare commits
10 Commits
f467712907
...
001eafc790
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
001eafc790 | ||
|
|
a196cec636 | ||
|
|
5b71814caf | ||
|
|
07300eff7c | ||
|
|
9a12d2ac9f | ||
|
|
023758b4a7 | ||
|
|
ba39b84914 | ||
|
|
75e2344cbe | ||
|
|
cc6c9ed98b | ||
|
|
b1451a2380 |
16
bltin.c
16
bltin.c
@ -2,6 +2,7 @@
|
|||||||
#include "fn.h"
|
#include "fn.h"
|
||||||
|
|
||||||
Object Nil = (Object){.type=OSYMBOL, .beg="nil"};
|
Object Nil = (Object){.type=OSYMBOL, .beg="nil"};
|
||||||
|
Object Top = (Object){.type=OSYMBOL, .beg="top"};
|
||||||
Object Splice= (Object){.type=OSYMBOL, .beg="@"};
|
Object Splice= (Object){.type=OSYMBOL, .beg="@"};
|
||||||
Object Comma= (Object){.type=OSYMBOL, .beg=","};
|
Object Comma= (Object){.type=OSYMBOL, .beg=","};
|
||||||
Object Minus= (Object){.type=OBLTIN, .beg="-"};
|
Object Minus= (Object){.type=OBLTIN, .beg="-"};
|
||||||
@ -20,13 +21,16 @@ Object Not = (Object){.type=OBLTIN, .beg= "not"};
|
|||||||
|
|
||||||
Object Bquote= (Object){.type=OBLTIN, .beg="`"};
|
Object Bquote= (Object){.type=OBLTIN, .beg="`"};
|
||||||
Object Lambda= (Object){.type=OBLTIN, .beg="lambda"};
|
Object Lambda= (Object){.type=OBLTIN, .beg="lambda"};
|
||||||
|
Object Block= (Object){.type=OBLTIN, .beg="block"};
|
||||||
|
Object RetFrom = (Object){.type=OBLTIN, .beg="return-from"};
|
||||||
|
Object Let= (Object){.type=OBLTIN, .beg="let"};
|
||||||
Object Progn=(Object){.type=OBLTIN, .beg="progn"};
|
Object Progn=(Object){.type=OBLTIN, .beg="progn"};
|
||||||
Object Car = (Object){.type=OBLTIN, .beg="car"};
|
Object Car = (Object){.type=OBLTIN, .beg="car"};
|
||||||
Object Cdr = (Object){.type=OBLTIN, .beg="cdr"};
|
Object Cdr = (Object){.type=OBLTIN, .beg="cdr"};
|
||||||
Object Quote= (Object){.type=OBLTIN, .beg="'"};
|
Object Quote= (Object){.type=OBLTIN, .beg="'"};
|
||||||
Object Cons = (Object){.type=OBLTIN, .beg="cons"};
|
Object Cons = (Object){.type=OBLTIN, .beg="cons"};
|
||||||
Object Define= (Object){.type=OBLTIN, .beg="define"};
|
Object Define= (Object){.type=OBLTIN, .beg="define"};
|
||||||
Object Macro= (Object){.type=OBLTIN, .beg="macro"};
|
Object Macro= (Object){.type=OBLTIN, .beg="defmacro"};
|
||||||
Object Setq = (Object){.type=OBLTIN, .beg="setq"};
|
Object Setq = (Object){.type=OBLTIN, .beg="setq"};
|
||||||
Object If = (Object){.type=OBLTIN, .beg="if"};
|
Object If = (Object){.type=OBLTIN, .beg="if"};
|
||||||
|
|
||||||
@ -35,9 +39,12 @@ extern Object* fnmul(Object *, Object *);
|
|||||||
extern Object* fndiv(Object *, Object *);
|
extern Object* fndiv(Object *, Object *);
|
||||||
extern Object* fnmod(Object *, Object *);
|
extern Object* fnmod(Object *, Object *);
|
||||||
extern Object* fnlambda(Object *, Object *);
|
extern Object* fnlambda(Object *, Object *);
|
||||||
|
extern Object* fnlet(Object *, Object *);
|
||||||
extern Object* fnprogn(Object *, Object *);
|
extern Object* fnprogn(Object *, Object *);
|
||||||
|
extern Object* fnblock(Object *, Object *);
|
||||||
|
extern Object* fnretfrom(Object *, Object *);
|
||||||
extern Object* fndefine(Object *, Object *);
|
extern Object* fndefine(Object *, Object *);
|
||||||
extern Object* fnmacro(Object *, Object *);
|
extern Object* fndefmacro(Object *, Object *);
|
||||||
extern Object* fnsetq(Object *, Object *);
|
extern Object* fnsetq(Object *, Object *);
|
||||||
extern Object* fnundef(Object *, Object *);
|
extern Object* fnundef(Object *, Object *);
|
||||||
extern Object* fnquote(Object *, Object *);
|
extern Object* fnquote(Object *, Object *);
|
||||||
@ -65,13 +72,16 @@ bltinlookup(Object *obj)
|
|||||||
}bltins[] = {
|
}bltins[] = {
|
||||||
{&Lambda , fnlambda},
|
{&Lambda , fnlambda},
|
||||||
{&Progn , fnprogn},
|
{&Progn , fnprogn},
|
||||||
|
{&Block , fnblock},
|
||||||
|
{&RetFrom ,fnretfrom},
|
||||||
{&Plus , fnplus},
|
{&Plus , fnplus},
|
||||||
{&Mul , fnmul},
|
{&Mul , fnmul},
|
||||||
{&Mod , fnmod},
|
{&Mod , fnmod},
|
||||||
{&Div , fndiv},
|
{&Div , fndiv},
|
||||||
{&Define ,fndefine},
|
{&Define ,fndefine},
|
||||||
{&Macro ,fnmacro},
|
{&Macro ,fndefmacro},
|
||||||
{&Setq ,fnsetq},
|
{&Setq ,fnsetq},
|
||||||
|
{&Let ,fnlet},
|
||||||
{&Quote ,fnquote},
|
{&Quote ,fnquote},
|
||||||
{&Bquote, fnbquote},
|
{&Bquote, fnbquote},
|
||||||
{&Car ,fncar},
|
{&Car ,fncar},
|
||||||
|
|||||||
29
dat.h
29
dat.h
@ -13,6 +13,8 @@ enum OType
|
|||||||
OINT,
|
OINT,
|
||||||
OFUNC,
|
OFUNC,
|
||||||
OMACRO,
|
OMACRO,
|
||||||
|
OBLOCK,
|
||||||
|
OFRAME,
|
||||||
OENV,
|
OENV,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,23 +37,41 @@ struct Object
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
char *end;
|
char *end;
|
||||||
};
|
};
|
||||||
|
/* Block */
|
||||||
|
struct{
|
||||||
|
Object *_tag;
|
||||||
|
Object *_up;
|
||||||
|
Object *_body;
|
||||||
|
void *jmp;
|
||||||
|
};
|
||||||
/* function */
|
/* function */
|
||||||
struct{
|
struct{
|
||||||
Object *params;
|
Object *params;
|
||||||
|
Object *frame; /* running frame */
|
||||||
Object *body;
|
Object *body;
|
||||||
Object *env;
|
Object *block;
|
||||||
};
|
};
|
||||||
/* env */
|
/* Frame */
|
||||||
struct{
|
struct{
|
||||||
Object *name;
|
Object *tag; /* Frame enter name */
|
||||||
Object *up;
|
Object *up;
|
||||||
Object *vars;
|
Object *local; /* local vars */
|
||||||
|
};
|
||||||
|
/* Env */
|
||||||
|
struct{
|
||||||
|
Object *frames;
|
||||||
|
Object *bp;
|
||||||
|
Object *sp; /* current */
|
||||||
|
Object *retval; /* for return-from */
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GC *gc;
|
extern GC *gc;
|
||||||
extern Object Nil;
|
extern Object Nil;
|
||||||
|
extern Object Top;
|
||||||
|
extern Object Block;
|
||||||
|
extern Object RetFrom;
|
||||||
extern Object Comma;
|
extern Object Comma;
|
||||||
extern Object Splice;
|
extern Object Splice;
|
||||||
extern Object Bquote;
|
extern Object Bquote;
|
||||||
@ -69,6 +89,7 @@ extern Object Define;
|
|||||||
extern Object Progn;
|
extern Object Progn;
|
||||||
extern Object Macro;
|
extern Object Macro;
|
||||||
extern Object Setq;
|
extern Object Setq;
|
||||||
|
extern Object Let;
|
||||||
extern Object Eq;
|
extern Object Eq;
|
||||||
extern Object Not;
|
extern Object Not;
|
||||||
extern Object Ne;
|
extern Object Ne;
|
||||||
|
|||||||
323
eval.c
323
eval.c
@ -1,14 +1,64 @@
|
|||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fn.h"
|
#include "fn.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define cdr(x) ((x)!= &Nil && (x)->type == OCELL ? (x)->cdr : &Nil)
|
||||||
|
#define car(x) ((x)!= &Nil && (x)->type == OCELL ? (x)->car : &Nil)
|
||||||
|
|
||||||
|
static char *typtab[] = {
|
||||||
|
[ONONE] = "error",
|
||||||
|
[OBLTIN] = "bltin",
|
||||||
|
[OSYMBOL] = "symbol",
|
||||||
|
[OCELL] = "cell",
|
||||||
|
[OIDENT] = "ident",
|
||||||
|
[OSTRING] = "string",
|
||||||
|
[OINT] = "int",
|
||||||
|
[OFUNC] = "func",
|
||||||
|
[OMACRO] = "macro",
|
||||||
|
[OENV] = "env",
|
||||||
|
};
|
||||||
|
|
||||||
static Object* evallist(Object *env, Object *list);
|
static Object* evallist(Object *env, Object *list);
|
||||||
|
|
||||||
|
static Object* curblock(Object *env) { return env->sp->car->block; }
|
||||||
|
static Object* curframe(Object *env) { return env->sp->car; }
|
||||||
|
|
||||||
|
static int
|
||||||
|
_streq(Object *a, Object *b)
|
||||||
|
{
|
||||||
|
int la = strlen(a->beg);
|
||||||
|
return la == strlen(b->beg) && memcmp(a->beg, b->beg, la) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterframe(Object *env, Object *tag, Object *local, Object *up)
|
||||||
|
{
|
||||||
|
assert(env->bp != &Nil);
|
||||||
|
Object *frame = newframe(gc, tag, local, up, curblock(env));
|
||||||
|
env->sp = env->sp->cdr = newcons(gc, frame, &Nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
leaveframe(Object *env)
|
||||||
|
{
|
||||||
|
assert(env->sp != env->bp);
|
||||||
|
Object *p = env->bp;
|
||||||
|
while(cdr(p) != env->sp)
|
||||||
|
p = p->cdr;
|
||||||
|
p->cdr = &Nil;
|
||||||
|
env->sp = p;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
exprlen(Object *expr)
|
exprlen(Object *expr)
|
||||||
{
|
{
|
||||||
int l = 0;
|
int l = 0;
|
||||||
for(;expr->type==OCELL; expr=expr->cdr)
|
while(expr != &Nil){
|
||||||
++l;
|
expr = cdr(expr);
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,14 +73,18 @@ clone(Object *p)
|
|||||||
{
|
{
|
||||||
switch(p->type){
|
switch(p->type){
|
||||||
default: panic("unreachable");
|
default: panic("unreachable");
|
||||||
|
case OFRAME:
|
||||||
|
case OENV:
|
||||||
case OSYMBOL:
|
case OSYMBOL:
|
||||||
case OBLTIN: return p;
|
case OINT:
|
||||||
case OINT: return newint(gc, p->num);
|
case OIDENT:
|
||||||
case OIDENT: return newsymbol(gc, p->beg, p->ptr - p->beg);
|
case OBLTIN:
|
||||||
case OCELL: return newcons(gc, clone(p->car), clone(p->cdr));
|
return p;
|
||||||
case OENV: return p;
|
|
||||||
case OMACRO:
|
case OMACRO:
|
||||||
case OFUNC: return newfn(gc, p->env, clone(p->params), clone(p->body), p->type);
|
case OFUNC:
|
||||||
|
return newfn(gc, p->frame, clone(p->params), clone(p->body), p->type);
|
||||||
|
case OCELL:
|
||||||
|
return newcons(gc, clone(p->car), clone(p->cdr));
|
||||||
case OSTRING:{
|
case OSTRING:{
|
||||||
Object *s = newstr(gc, p->end - p->beg);
|
Object *s = newstr(gc, p->end - p->beg);
|
||||||
strinit(s, p);
|
strinit(s, p);
|
||||||
@ -42,10 +96,10 @@ clone(Object *p)
|
|||||||
static Object*
|
static Object*
|
||||||
find(Object *env, Object *obj)
|
find(Object *env, Object *obj)
|
||||||
{
|
{
|
||||||
for(Object *cur=env; cur!=&Nil; cur=cur->up)
|
for(Object *cur=curframe(env); cur!=&Nil; cur=cur->up)
|
||||||
for(Object *p=cur->vars; p!=&Nil; p=p->cdr)
|
for(Object *p=cur->local; p!=&Nil; p=cdr(p))
|
||||||
if(strequal(obj, p->car->car))
|
if(strequal(obj, car(car(p))))
|
||||||
return clone(p->car->cdr);
|
return clone(cdr(car(p)));
|
||||||
error("not exist variable");
|
error("not exist variable");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -55,21 +109,24 @@ _newfn(Object *env, Object *l, enum OType type)
|
|||||||
{
|
{
|
||||||
if(l->type!=OCELL || islist(l->car)==0 || l->cdr->type!=OCELL)
|
if(l->type!=OCELL || islist(l->car)==0 || l->cdr->type!=OCELL)
|
||||||
error("malformed function");
|
error("malformed function");
|
||||||
for(Object *p=l->car; p->type==OCELL; p=p->cdr)
|
for(Object *p=l->car; p->type==OCELL; p=cdr(p))
|
||||||
if(p->car->type!=OIDENT)
|
if(p->car->type!=OIDENT)
|
||||||
error("parameter is not IDNET");
|
error("parameter is not IDNET");
|
||||||
Object *params = l->car;
|
Object *params = l->car;
|
||||||
Object *body = l->cdr;
|
Object *body = l->cdr;
|
||||||
return newfn(gc, env, params, body, type);
|
return newfn(gc, curframe(env), params, body, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static void
|
||||||
defvar(Object *env, Object *id, Object *val)
|
defvar(Object *env, Object *id, Object *val)
|
||||||
{
|
{
|
||||||
for(Object *p=env->vars; p!=&Nil; p=p->cdr)
|
if(id->type != OIDENT)
|
||||||
if(strequal(id, p->car->car))
|
error("can't define, already using id");
|
||||||
|
Object *frame = env->bp->car;
|
||||||
|
for(Object *p=frame->local; p!=&Nil; p=cdr(p))
|
||||||
|
if(strequal(id, car(car(p))))
|
||||||
error("already exist variable. use setq plz...");
|
error("already exist variable. use setq plz...");
|
||||||
return newacons(gc, id, val, env->vars);
|
frame->local = newacons(gc, id, val, frame->local);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -79,19 +136,21 @@ fnlambda(Object *env, Object *l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fnmacro(Object *env, Object *l)
|
fndefmacro(Object *env, Object *l)
|
||||||
{
|
{
|
||||||
|
if(l->type != OCELL)
|
||||||
|
error("Malformed macro");
|
||||||
Object *macro = _newfn(env, l->cdr, OMACRO);
|
Object *macro = _newfn(env, l->cdr, OMACRO);
|
||||||
env->vars = defvar(env, l->car, macro);
|
defvar(env, l->car, macro);
|
||||||
return macro;
|
return macro;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
progn(Object *env, Object *list)
|
progn(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
Object *r = 0;
|
Object *r = &Nil;
|
||||||
for(Object *p=list; p!=&Nil; p=p->cdr){
|
for(Object *p=list; p!=&Nil; p=cdr(p)){
|
||||||
r = eval(env, p->car);
|
r = eval(env, car(p));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -102,29 +161,86 @@ fnprogn(Object *env, Object *list)
|
|||||||
return progn(env, list);
|
return progn(env, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
fnblock(Object *env, Object *list)
|
||||||
|
{
|
||||||
|
if(list->type != OCELL|| (list->car->type != OSYMBOL&&list->car->type != OIDENT))
|
||||||
|
error("Malformed block");
|
||||||
|
Object *tag = car(list);
|
||||||
|
Object *body = cdr(list);
|
||||||
|
jmp_buf jmp;
|
||||||
|
Object *b = newblock(gc, tag, curblock(env), body, &jmp);
|
||||||
|
Object *sp = env->sp;
|
||||||
|
sp->car->block = b;
|
||||||
|
Object *res = &Nil;
|
||||||
|
|
||||||
|
if(setjmp(jmp) == 1){
|
||||||
|
env->sp->block = b->up;
|
||||||
|
env->sp = sp;
|
||||||
|
res = env->retval;
|
||||||
|
env->retval = &Nil;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = progn(env, body);
|
||||||
|
sp->car->block = b->up;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
fnretfrom(Object *env, Object *list)
|
||||||
|
{
|
||||||
|
if(list->type != OCELL)
|
||||||
|
error("Malformed return-from");
|
||||||
|
Object *tag = car(list);
|
||||||
|
Object *p = curblock(env);
|
||||||
|
for(; p!= &Top; p=p->up)
|
||||||
|
if(_streq(p->tag, tag)){
|
||||||
|
env->retval = eval(env, car(cdr(list)));
|
||||||
|
longjmp(*(jmp_buf*)p->jmp, 1);
|
||||||
|
}
|
||||||
|
error("can't excute return-from");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fnsetq(Object *env, Object *list)
|
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");
|
error("Malformed setq");
|
||||||
Object *cur = env;
|
for(Object *frame=curframe(env); frame!=&Nil; frame=frame->up)
|
||||||
Object *p = 0;
|
for(Object *p=frame->local; p!=&Nil; p=cdr(p))
|
||||||
for(; cur!=&Nil; cur=cur->up)
|
if(strequal(list->car, car(car(p))))
|
||||||
for(p=cur->vars; p!=&Nil; p=p->cdr)
|
return p->car->cdr = eval(env, car(cdr(list)));
|
||||||
if(strequal(list->car, p->car->car))
|
|
||||||
goto found;
|
|
||||||
error("setq not exist variable");
|
error("setq not exist variable");
|
||||||
found:;
|
return 0;
|
||||||
return p->car->cdr = eval(env, list->cdr->car);
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
fnlet(Object *env, Object *list)
|
||||||
|
{
|
||||||
|
if(exprlen(list) < 2)
|
||||||
|
error("let (vars) bodys");
|
||||||
|
Object *local = &Nil;
|
||||||
|
for(Object *p=car(list); p!=&Nil; p=cdr(p)){
|
||||||
|
Object *id = car(car(p));
|
||||||
|
Object *val = eval(env, car(cdr(car(p))));
|
||||||
|
local = newacons(gc, id, val, local);
|
||||||
|
}
|
||||||
|
enterframe(env, &Let, local, curframe(env));
|
||||||
|
Object *res = progn(env, cdr(list));
|
||||||
|
leaveframe(env);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fndefine(Object *env, Object *list)
|
fndefine(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
if(exprlen(list)!=2 || list->car->type!=OIDENT)
|
if(exprlen(list)!=2)
|
||||||
error("Malformed define");
|
error("Malformed define");
|
||||||
Object *val = eval(env, list->cdr->car);
|
Object *val = eval(env, car(cdr(list)));
|
||||||
env->vars = defvar(env, list->car, val);
|
defvar(env, car(list), val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,16 +258,15 @@ evalcomma(Object *env, Object *p)
|
|||||||
if(p->type != OCELL)
|
if(p->type != OCELL)
|
||||||
return p;
|
return p;
|
||||||
if(p->car == &Comma){
|
if(p->car == &Comma){
|
||||||
if(p->cdr->type == OCELL && p->cdr->car == &Splice){
|
if(car(cdr(p)) == &Splice)
|
||||||
return newcons(gc, &Splice, eval(env, p->cdr->cdr));
|
return newcons(gc, &Splice, eval(env, p->cdr->cdr));
|
||||||
}else
|
return eval(env, p->cdr);
|
||||||
return eval(env, p->cdr);
|
|
||||||
}
|
}
|
||||||
p->car = evalcomma(env, p->car);
|
p->car = evalcomma(env, p->car);
|
||||||
p->cdr = evalcomma(env, p->cdr);
|
p->cdr = evalcomma(env, p->cdr);
|
||||||
if(p->car->type == OCELL && p->car->car == &Splice){
|
if(car(car(p)) == &Splice){
|
||||||
Object *i = p->car;
|
Object *i = p->car;
|
||||||
while(i->cdr->type == OCELL && i->cdr != &Nil)
|
while(cdr(i) != &Nil)
|
||||||
i = i->cdr;
|
i = i->cdr;
|
||||||
if(i->type == OCELL){
|
if(i->type == OCELL){
|
||||||
i->cdr = p->cdr;
|
i->cdr = p->cdr;
|
||||||
@ -167,29 +282,25 @@ fnbquote(Object *env, Object *list)
|
|||||||
{
|
{
|
||||||
if(exprlen(list) != 1)
|
if(exprlen(list) != 1)
|
||||||
error("Malformed fnbquote");
|
error("Malformed fnbquote");
|
||||||
return evalcomma(env, list->car);
|
return evalcomma(env, car(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fncar(Object *env, Object *list)
|
fncar(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
list = evallist(env, list);
|
list = evallist(env, list);
|
||||||
if(list->car == &Nil)
|
if(car(list)->type != OCELL)
|
||||||
return &Nil;
|
error("expected list");
|
||||||
if(list->car->type != OCELL)
|
return car(car(list));
|
||||||
error("car: expected list");
|
|
||||||
return list->car->car;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fncdr(Object *env, Object *list)
|
fncdr(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
list = evallist(env, list);
|
list = evallist(env, list);
|
||||||
if(list->car == &Nil)
|
if(car(list)->type != OCELL)
|
||||||
return &Nil;
|
error("expected list");
|
||||||
if(list->car->type != OCELL)
|
return cdr(car(list));
|
||||||
error("cdr: expected list");
|
|
||||||
return list->car->cdr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -198,7 +309,9 @@ fncons(Object *env, Object *list)
|
|||||||
if(exprlen(list) != 2)
|
if(exprlen(list) != 2)
|
||||||
error("Malformoed cons");
|
error("Malformoed cons");
|
||||||
list = evallist(env, list);
|
list = evallist(env, list);
|
||||||
list->cdr = list->cdr->car;
|
if(list->type != OCELL)
|
||||||
|
error("cons:bad list");
|
||||||
|
list->cdr = car(list->cdr);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +320,7 @@ fnplus(Object *env, Object *list)
|
|||||||
{
|
{
|
||||||
long sum = 0;
|
long sum = 0;
|
||||||
Object *p=evallist(env, list);
|
Object *p=evallist(env, list);
|
||||||
for(;p!=&Nil; p=p->cdr){
|
for(;p!=&Nil; p=cdr(p)){
|
||||||
if(p->car->type != OINT)
|
if(p->car->type != OINT)
|
||||||
error("+ take only number");
|
error("+ take only number");
|
||||||
sum += p->car->num;
|
sum += p->car->num;
|
||||||
@ -219,11 +332,11 @@ Object*
|
|||||||
fnmul(Object *env, Object *list)
|
fnmul(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
Object *p = evallist(env, list);
|
Object *p = evallist(env, list);
|
||||||
if(p->car->type != OINT)
|
if(car(p)->type != OINT)
|
||||||
error("* take only [INT]");
|
error("* take only [INT]");
|
||||||
long sum = p->car->num;
|
long sum = p->car->num;
|
||||||
for(p=p->cdr;p!=&Nil; p=p->cdr){
|
for(p=p->cdr;p!=&Nil; p=cdr(p)){
|
||||||
if(p->car->type != OINT)
|
if(car(p)->type != OINT)
|
||||||
error("* take only [INT]");
|
error("* take only [INT]");
|
||||||
sum *= p->car->num;
|
sum *= p->car->num;
|
||||||
}
|
}
|
||||||
@ -237,8 +350,8 @@ fndiv(Object *env, Object *list)
|
|||||||
if(p->car->type != OINT)
|
if(p->car->type != OINT)
|
||||||
error("/ take only [INT]");
|
error("/ take only [INT]");
|
||||||
long sum = p->car->num;
|
long sum = p->car->num;
|
||||||
for(p=p->cdr;p!=&Nil; p=p->cdr){
|
for(p=p->cdr;p!=&Nil; p=cdr(p)){
|
||||||
if(p->car->type != OINT)
|
if(car(p)->type != OINT)
|
||||||
error("/ take only [INT]");
|
error("/ take only [INT]");
|
||||||
if(p->car->num == 0)
|
if(p->car->num == 0)
|
||||||
error("Can't div zero");
|
error("Can't div zero");
|
||||||
@ -254,8 +367,8 @@ fnmod(Object *env, Object *list)
|
|||||||
if(p->car->type != OINT)
|
if(p->car->type != OINT)
|
||||||
error("%% take only [INT]");
|
error("%% take only [INT]");
|
||||||
long sum = p->car->num;
|
long sum = p->car->num;
|
||||||
for(p=p->cdr;p!=&Nil; p=p->cdr){
|
for(p=p->cdr;p!=&Nil; p=cdr(p)){
|
||||||
if(p->car->type != OINT)
|
if(car(p)->type != OINT)
|
||||||
error("%% take only [INT]");
|
error("%% take only [INT]");
|
||||||
if(p->car->num == 0)
|
if(p->car->num == 0)
|
||||||
error("Can't mod zero");
|
error("Can't mod zero");
|
||||||
@ -267,8 +380,8 @@ fnmod(Object *env, Object *list)
|
|||||||
static long
|
static long
|
||||||
cmp(Object *env, Object *list)
|
cmp(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
Object *a = eval(env, list->car);
|
Object *a = eval(env, car(list));
|
||||||
Object *b = eval(env, list->cdr->car);
|
Object *b = eval(env, car(cdr(list)));
|
||||||
if(a->type != OINT || b->type != OINT)
|
if(a->type != OINT || b->type != OINT)
|
||||||
error("cmp only take [INT]");
|
error("cmp only take [INT]");
|
||||||
return a->num - b->num;
|
return a->num - b->num;
|
||||||
@ -285,9 +398,9 @@ _newint(int n)
|
|||||||
Object*
|
Object*
|
||||||
fnnot(Object *env, Object *list)
|
fnnot(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
if(list->type != OCELL)
|
if(exprlen(list) != 1)
|
||||||
error("Malformed not");
|
error("Malformed not");
|
||||||
return _newint(eval(env, list->car) == &Nil);
|
return _newint(eval(env, car(list)) == &Nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -329,15 +442,14 @@ fnne(Object *env, Object *list)
|
|||||||
Object*
|
Object*
|
||||||
fnif(Object *env, Object *list)
|
fnif(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
if(list->type != OCELL || list->cdr->type != OCELL)
|
if(cdr(list)->type != OCELL)
|
||||||
error("Malformed if stmt");
|
error("Malformed if stmt");
|
||||||
if(eval(env, list->car)!=&Nil)
|
Object *test = list->car;
|
||||||
return eval(env, list->cdr->car);
|
Object *then = car(cdr(list));
|
||||||
if(list->cdr->cdr == &Nil)
|
Object *else_ = car(cdr(cdr(list)));
|
||||||
return &Nil;
|
if(eval(env, test)!=&Nil)
|
||||||
if(list->cdr->cdr->type != OCELL)
|
return eval(env, then);
|
||||||
error("Malformed else stmt");
|
return eval(env, else_);
|
||||||
return eval(env, list->cdr->cdr->car);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
@ -345,73 +457,64 @@ evallist(Object *env, Object *list)
|
|||||||
{
|
{
|
||||||
if(list == &Nil)
|
if(list == &Nil)
|
||||||
return &Nil;
|
return &Nil;
|
||||||
if(list->type != OCELL)
|
Object *car = eval(env, car(list));
|
||||||
error("expected list");
|
Object *cdr = evallist(env, cdr(list));
|
||||||
Object *car = eval(env, list->car);
|
|
||||||
Object *cdr = evallist(env, list->cdr);
|
|
||||||
return newcons(gc, car, cdr);
|
return newcons(gc, car, cdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
enter(Object *env, Object *vars, Object *args)
|
applyargs(Object *fn, Object *args)
|
||||||
{
|
{
|
||||||
#define cdr(x) (x!=&Nil ? x->cdr : &Nil)
|
|
||||||
#define car(x) (x!=&Nil ? x->car : &Nil)
|
|
||||||
|
|
||||||
Object *map = &Nil;
|
Object *map = &Nil;
|
||||||
for(;vars->type==OCELL; vars=vars->cdr, args=cdr(args)){
|
Object *vars = fn->params;
|
||||||
|
for(;vars->type==OCELL; vars=cdr(vars), args=cdr(args)){
|
||||||
if(args != &Nil && args->type!=OCELL)
|
if(args != &Nil && args->type!=OCELL)
|
||||||
error("Cna't apply function argment dose not match");
|
error("Cna't apply function argment dose not match");
|
||||||
Object *id = vars->car;
|
Object *id = car(vars);
|
||||||
Object *val = car(args);
|
Object *val = car(args);
|
||||||
map = newacons(gc, id, val, map);
|
map = newacons(gc, id, val, map);
|
||||||
}
|
}
|
||||||
if(vars != &Nil)
|
if(vars != &Nil)
|
||||||
map = newacons(gc, vars, args, map);
|
map = newacons(gc, vars, args, map);
|
||||||
return newenv(gc, &Nil, map, env);
|
return map;
|
||||||
|
|
||||||
#undef car
|
|
||||||
#undef cdr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
applyfn(Object *fn, Object *args)
|
applyfn(Object *env, Object *tag, Object *fn, Object *args)
|
||||||
{
|
{
|
||||||
Object *env = enter(fn->env, fn->params, args);
|
Object *local = applyargs(fn, args);
|
||||||
return progn(env, fn->body);
|
enterframe(env, tag, local,fn->frame);
|
||||||
|
Object *res = progn(env, fn->body);
|
||||||
|
leaveframe(env);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
applymacro(Object *env, Object* fn, Object *args)
|
applymacro(Object *env, Object *tag, Object* fn, Object *args)
|
||||||
{
|
{
|
||||||
Object *nenv = enter(fn->env, fn->params, args);
|
Object *local = applyargs(fn, args);
|
||||||
Object *r = 0;
|
enterframe(env, tag, local, fn->frame);
|
||||||
for(Object *p=fn->body; p!=&Nil; p=p->cdr){
|
Object *r = progn(env, fn->body);
|
||||||
r = p->car;
|
leaveframe(env);
|
||||||
r = eval(nenv, r);
|
|
||||||
}
|
|
||||||
return eval(env, r);
|
return eval(env, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
apply(Object *env, Object *fn, Object *args)
|
apply(Object *env, Object *tag, Object *fn, Object *args)
|
||||||
{
|
{
|
||||||
if(islist(args) == 0)
|
|
||||||
error("args is not list type");
|
|
||||||
switch(fn->type){
|
switch(fn->type){
|
||||||
default:
|
default:
|
||||||
error("apply only tabke [MACRO BLTIN FUNC]");
|
error("apply:can't eval type");
|
||||||
case OMACRO:
|
return 0;
|
||||||
return applymacro(env, fn, args);
|
|
||||||
case OBLTIN:{
|
case OBLTIN:{
|
||||||
Bltinfn blt = bltinlookup(fn);
|
Bltinfn blt = bltinlookup(fn);
|
||||||
if(blt==0)
|
|
||||||
error("not builtin type!");
|
|
||||||
return blt(env, args);
|
return blt(env, args);
|
||||||
}
|
}
|
||||||
|
case OMACRO:
|
||||||
|
return applymacro(env, tag, fn, args);
|
||||||
case OFUNC:{
|
case OFUNC:{
|
||||||
Object *elist = evallist(env, args);
|
Object *elist = evallist(env, args);
|
||||||
Object*res = applyfn(fn, elist);
|
Object*res = applyfn(env, tag, fn, elist);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,20 +525,18 @@ eval(Object *env, Object *obj)
|
|||||||
{
|
{
|
||||||
switch(obj->type){
|
switch(obj->type){
|
||||||
default:
|
default:
|
||||||
error("can't eval");
|
error("eval: can't eval type");
|
||||||
|
return 0;
|
||||||
case OSTRING:
|
case OSTRING:
|
||||||
case OINT:
|
case OINT:
|
||||||
case OBLTIN:
|
case OBLTIN:
|
||||||
case OSYMBOL:
|
case OSYMBOL:
|
||||||
return obj;
|
return obj;
|
||||||
case OIDENT:{
|
case OIDENT:
|
||||||
return find(env, obj);
|
return find(env, obj);
|
||||||
}
|
|
||||||
case OCELL:{
|
case OCELL:{
|
||||||
Object *fn = eval(env, obj->car);
|
Object *fn = eval(env, obj->car);
|
||||||
if(fn == &Nil)
|
Object *res = apply(env, obj->car, fn, obj->cdr);
|
||||||
return &Nil;
|
|
||||||
Object *res = apply(env, fn, obj->cdr);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
fn.h
6
fn.h
@ -12,11 +12,13 @@ Object* eval(Object *env, Object *expr);
|
|||||||
/* new */
|
/* new */
|
||||||
Object* newint(GC *,long);
|
Object* newint(GC *,long);
|
||||||
Object* newcons(GC *,Object*,Object*);
|
Object* newcons(GC *,Object*,Object*);
|
||||||
Object* newenv(GC *,Object*name, Object *vars, Object *up);
|
Object* newenv(GC *gc, Object *frames, Object *bp, Object *sp);
|
||||||
|
Object* newblock(GC *gc, Object* tag, Object *up, Object *body, void *jmp);
|
||||||
|
Object* newframe(GC *gc, Object* tag, Object *local, Object *up, Object *block);
|
||||||
Object* newacons(GC *,Object*, Object*, Object*);
|
Object* newacons(GC *,Object*, Object*, Object*);
|
||||||
Object* newsymbol(GC *,char*, int);
|
Object* newsymbol(GC *,char*, int);
|
||||||
Object* newstr(GC *,int);
|
Object* newstr(GC *,int);
|
||||||
Object* newfn(GC *,Object *env, Object *params, Object *body, enum OType type);
|
Object* newfn(GC *,Object *frame, Object *params, Object *body, enum OType type);
|
||||||
|
|
||||||
/* gc.c */
|
/* gc.c */
|
||||||
GC* newgc(void *top, int cap);
|
GC* newgc(void *top, int cap);
|
||||||
|
|||||||
41
gc.c
41
gc.c
@ -65,17 +65,32 @@ cloneobj(GC *dst, GC *src, Object *obj)
|
|||||||
p->cdr = cloneobj(dst, src, obj->cdr);
|
p->cdr = cloneobj(dst, src, obj->cdr);
|
||||||
break;
|
break;
|
||||||
case OENV:
|
case OENV:
|
||||||
obj->forward = p = newenv(dst, &Nil, &Nil, &Nil);
|
obj->forward = p = newenv(dst,&Nil, &Nil, &Nil);
|
||||||
p->name = cloneobj(dst, src, obj->name);
|
p->frames = cloneobj(dst, src, obj->frames);
|
||||||
p->vars = cloneobj(dst, src, obj->vars);
|
p->bp = cloneobj(dst, src, obj->bp);
|
||||||
|
p->sp = cloneobj(dst, src, obj->sp);
|
||||||
|
p->retval = cloneobj(dst, src, obj->retval);
|
||||||
|
break;
|
||||||
|
case OBLOCK:
|
||||||
|
obj->forward = p = newblock(dst, &Nil, &Nil, &Nil, obj->jmp);
|
||||||
|
p->tag = cloneobj(dst, src, obj->tag);
|
||||||
p->up = cloneobj(dst, src, obj->up);
|
p->up = cloneobj(dst, src, obj->up);
|
||||||
|
p->body = cloneobj(dst, src, obj->body);
|
||||||
|
p->jmp = obj->jmp;
|
||||||
|
break;
|
||||||
|
case OFRAME:
|
||||||
|
obj->forward = p = newframe(dst, &Nil, &Nil, &Nil, &Nil);
|
||||||
|
p->tag = cloneobj(dst, src, obj->tag);
|
||||||
|
p->local = cloneobj(dst, src, obj->local);
|
||||||
|
p->up = cloneobj(dst, src, obj->up);
|
||||||
|
p->block = cloneobj(dst, src, obj->block);
|
||||||
break;
|
break;
|
||||||
case OMACRO:
|
case OMACRO:
|
||||||
case OFUNC:
|
case OFUNC:
|
||||||
obj->forward = p = newfn(dst, &Nil, &Nil, &Nil, obj->type);
|
obj->forward = p = newfn(dst, &Nil, &Nil, &Nil, obj->type);
|
||||||
p->params = cloneobj(dst, src, obj->params);
|
p->params = cloneobj(dst, src, obj->params);
|
||||||
p->body = cloneobj(dst, src, obj->body);
|
p->body = cloneobj(dst, src, obj->body);
|
||||||
p->env = cloneobj(dst, src, obj->env);
|
p->frame = cloneobj(dst, src, obj->frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
@ -128,15 +143,27 @@ mark(GC *gc, Object *obj)
|
|||||||
mark(gc, obj->cdr);
|
mark(gc, obj->cdr);
|
||||||
break;
|
break;
|
||||||
case OENV:
|
case OENV:
|
||||||
mark(gc, obj->name);
|
mark(gc, obj->frames);
|
||||||
mark(gc, obj->vars);
|
mark(gc, obj->bp);
|
||||||
|
mark(gc, obj->sp);
|
||||||
|
mark(gc, obj->retval);
|
||||||
|
break;
|
||||||
|
case OBLOCK:
|
||||||
|
mark(gc, obj->tag);
|
||||||
mark(gc, obj->up);
|
mark(gc, obj->up);
|
||||||
|
mark(gc, obj->body);
|
||||||
|
break;
|
||||||
|
case OFRAME:
|
||||||
|
mark(gc, obj->tag);
|
||||||
|
mark(gc, obj->local);
|
||||||
|
mark(gc, obj->up);
|
||||||
|
mark(gc, obj->block);
|
||||||
break;
|
break;
|
||||||
case OMACRO:
|
case OMACRO:
|
||||||
case OFUNC:
|
case OFUNC:
|
||||||
mark(gc, obj->params);
|
mark(gc, obj->params);
|
||||||
mark(gc, obj->body);
|
mark(gc, obj->body);
|
||||||
mark(gc, obj->env);
|
mark(gc, obj->frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
lib/lib.lisp
38
lib/lib.lisp
@ -1,8 +1,36 @@
|
|||||||
(macro defun (name args body)
|
(defmacro defun (name args body)
|
||||||
`(define ,name (lambda ,args ,body)))
|
`(define ,name (lambda ,args (block ,name ,body))))
|
||||||
|
|
||||||
|
(defmacro cond (expr . rest)
|
||||||
|
(if (not expr)
|
||||||
|
nil
|
||||||
|
(let ((test (car expr)))
|
||||||
|
`(if ,test
|
||||||
|
(progn ,test ,@(cdr expr))
|
||||||
|
(cond ,@rest)))))
|
||||||
|
|
||||||
|
(defmacro and (expr . rest)
|
||||||
|
(if (not rest)
|
||||||
|
expr
|
||||||
|
(if (cond (not expr) nil)
|
||||||
|
`(and ,@rest))))
|
||||||
|
|
||||||
|
(defmacro or (expr . rest)
|
||||||
|
(if rest
|
||||||
|
(cond (expr) (`(or ,@rest)))
|
||||||
|
expr))
|
||||||
|
|
||||||
|
(defmacro when (test . rest)
|
||||||
|
`(if ,test
|
||||||
|
(progn ,@rest)))
|
||||||
|
|
||||||
|
(defmacro unless (test . rest)
|
||||||
|
`(if (not ,test)
|
||||||
|
(progn ,@rest)))
|
||||||
|
|
||||||
|
(defmacro return (res)
|
||||||
|
(return-from nil `,res))
|
||||||
|
|
||||||
(defun list (x . y) (cons x y))
|
(defun list (x . y) (cons x y))
|
||||||
|
|
||||||
(macro cond (expr . rest)
|
|
||||||
(if (not expr) nil
|
|
||||||
`(if ,(car expr) (progn ,@expr) (cond ,@rest))))
|
|
||||||
|
|||||||
12
main.c
12
main.c
@ -31,9 +31,17 @@ SExprint(Object *obj)
|
|||||||
case OSYMBOL:
|
case OSYMBOL:
|
||||||
printf("%s", obj->beg);
|
printf("%s", obj->beg);
|
||||||
break;
|
break;
|
||||||
|
case OBLOCK:
|
||||||
|
printf("\n<block-%s>\n", obj->tag->beg);
|
||||||
|
break;
|
||||||
|
case OFRAME:
|
||||||
|
printf("\n<frame-%s>\n", obj->tag->beg);
|
||||||
|
printexpr(obj->local);
|
||||||
|
printexpr(obj->block);
|
||||||
|
break;
|
||||||
case OENV:
|
case OENV:
|
||||||
printf("<env>");
|
printf("<env>");
|
||||||
SExprint(obj->vars);
|
printexpr(obj->frames);
|
||||||
break;
|
break;
|
||||||
case OMACRO:
|
case OMACRO:
|
||||||
printf("<macro>");
|
printf("<macro>");
|
||||||
@ -60,7 +68,7 @@ int
|
|||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
*argv = "lib/lib.lisp";
|
*argv = "lib/lib.lisp";
|
||||||
gc = newgc(&argc, 400);
|
gc = newgc(&argc, 24000);
|
||||||
lispmain(argv);
|
lispmain(argv);
|
||||||
panic("unreachable");
|
panic("unreachable");
|
||||||
}
|
}
|
||||||
|
|||||||
37
obj.c
37
obj.c
@ -29,15 +29,38 @@ newcons(GC *gc, Object *car, Object *cdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
newenv(GC *gc, Object* name, Object *vars, Object *up)
|
newblock(GC *gc, Object* tag, Object *up, Object *body, void *jmp)
|
||||||
{
|
{
|
||||||
Object *obj = newobj(gc, OENV, 0);
|
Object *obj = newobj(gc, OBLOCK, 0);
|
||||||
obj->name = name;
|
obj->tag = tag;
|
||||||
obj->up = up;
|
obj->up = up;
|
||||||
obj->vars = vars;
|
obj->body = body;
|
||||||
|
obj->jmp = jmp;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
newframe(GC *gc, Object* tag, Object *local, Object *up, Object *block)
|
||||||
|
{
|
||||||
|
Object *obj = newobj(gc, OFRAME, 0);
|
||||||
|
obj->tag = tag;
|
||||||
|
obj->local = local;
|
||||||
|
obj->up = up;
|
||||||
|
obj->block = block;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
newenv(GC *gc, Object *frames, Object *bp, Object *sp)
|
||||||
|
{
|
||||||
|
Object *env = newobj(gc, OENV, 0);
|
||||||
|
env->frames = frames;
|
||||||
|
env->bp = bp;
|
||||||
|
env->sp = sp;
|
||||||
|
env->retval = &Nil;
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
newacons(GC *gc, Object *x, Object *y, Object *z)
|
newacons(GC *gc, Object *x, Object *y, Object *z)
|
||||||
{
|
{
|
||||||
@ -46,13 +69,13 @@ newacons(GC *gc, Object *x, Object *y, Object *z)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
newfn(GC *gc, Object *env, Object *params, Object *body, enum OType type)
|
newfn(GC *gc, Object *frame, Object *params, Object *body, enum OType type)
|
||||||
{
|
{
|
||||||
Object *fn = newobj(gc, type, 0);
|
Object *fn = newobj(gc, type, 0);
|
||||||
fn->type = type;
|
fn->type = type;
|
||||||
fn->params = params;
|
fn->params = params;
|
||||||
fn->body = body;
|
fn->body = body;
|
||||||
fn->env = env;
|
fn->frame = frame;
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +86,7 @@ newsymbol(GC *gc, char *str, int len)
|
|||||||
&Nil, &Minus, &Plus, &Mul, &Mod, &Div, &Ge, &Le,
|
&Nil, &Minus, &Plus, &Mul, &Mod, &Div, &Ge, &Le,
|
||||||
&Lt, &Gt, &Ne, &Lambda, &Car, &Cdr, &Quote, &Cons,
|
&Lt, &Gt, &Ne, &Lambda, &Car, &Cdr, &Quote, &Cons,
|
||||||
&Define, &Setq, &Eq, &If, &Macro, &Progn, &Bquote,
|
&Define, &Setq, &Eq, &If, &Macro, &Progn, &Bquote,
|
||||||
&Comma, &Not, &Splice,
|
&Comma, &Not, &Splice, &Let, &Block, &RetFrom,
|
||||||
};
|
};
|
||||||
for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){
|
for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){
|
||||||
Object *c = syms[i];
|
Object *c = syms[i];
|
||||||
|
|||||||
16
repl.c
16
repl.c
@ -31,6 +31,16 @@ error(char *fmt, ...)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove all frames except Top */
|
||||||
|
static void
|
||||||
|
clearenv(Object *env)
|
||||||
|
{
|
||||||
|
env->bp->cdr = &Nil;
|
||||||
|
env->bp->car->block = &Top;
|
||||||
|
env->sp = env->bp;
|
||||||
|
env->retval = &Nil;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
repl(Object *env, FILE *f, char *pre)
|
repl(Object *env, FILE *f, char *pre)
|
||||||
{
|
{
|
||||||
@ -39,6 +49,7 @@ repl(Object *env, FILE *f, char *pre)
|
|||||||
if(setjmp(err) == 1){
|
if(setjmp(err) == 1){
|
||||||
if(feof(f))
|
if(feof(f))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
clearenv(env);
|
||||||
skipline(f);
|
skipline(f);
|
||||||
}
|
}
|
||||||
while(1){
|
while(1){
|
||||||
@ -46,7 +57,6 @@ repl(Object *env, FILE *f, char *pre)
|
|||||||
Object *res = nextexpr(f);
|
Object *res = nextexpr(f);
|
||||||
res = eval(env, res);
|
res = eval(env, res);
|
||||||
printexpr(res);
|
printexpr(res);
|
||||||
printgc("status", gc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +77,9 @@ readlib(FILE *f, Object *env)
|
|||||||
void
|
void
|
||||||
lispmain(char *argv[])
|
lispmain(char *argv[])
|
||||||
{
|
{
|
||||||
Object *env = newenv(gc , &Nil, &Nil, &Nil);
|
Object *frame = newframe(gc, &Top, &Nil, &Nil, &Top);
|
||||||
|
Object *cons = newcons(gc, frame, &Nil);
|
||||||
|
Object *env = newenv(gc, cons, cons, cons);
|
||||||
for(; *argv; ++argv){
|
for(; *argv; ++argv){
|
||||||
FILE *f = fopen(*argv, "r");
|
FILE *f = fopen(*argv, "r");
|
||||||
if(f == 0)
|
if(f == 0)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user