fix macro
This commit is contained in:
parent
2ddcc7578c
commit
f467712907
@ -1,3 +1,5 @@
|
|||||||
|
* see lib/lib.lisp
|
||||||
|
|
||||||
* (define fac (lambda (n) (if (== n 0) 1 (* n (fac (+ n -1))))))
|
* (define fac (lambda (n) (if (== n 0) 1 (* n (fac (+ n -1))))))
|
||||||
|
|
||||||
* macro
|
* macro
|
||||||
|
|||||||
2
bltin.c
2
bltin.c
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
Object Nil = (Object){.type=OSYMBOL, .beg="nil"};
|
Object Nil = (Object){.type=OSYMBOL, .beg="nil"};
|
||||||
Object Splice= (Object){.type=OSYMBOL, .beg="@"};
|
Object Splice= (Object){.type=OSYMBOL, .beg="@"};
|
||||||
|
Object Comma= (Object){.type=OSYMBOL, .beg=","};
|
||||||
Object Minus= (Object){.type=OBLTIN, .beg="-"};
|
Object Minus= (Object){.type=OBLTIN, .beg="-"};
|
||||||
Object Plus = (Object){.type=OBLTIN, .beg="+"};
|
Object Plus = (Object){.type=OBLTIN, .beg="+"};
|
||||||
Object Mul = (Object){.type=OBLTIN, .beg="*"};
|
Object Mul = (Object){.type=OBLTIN, .beg="*"};
|
||||||
@ -17,7 +18,6 @@ Object Ne = (Object){.type=OBLTIN, .beg= "!="};
|
|||||||
Object Eq = (Object){.type=OBLTIN, .beg= "=="};
|
Object Eq = (Object){.type=OBLTIN, .beg= "=="};
|
||||||
Object Not = (Object){.type=OBLTIN, .beg= "not"};
|
Object Not = (Object){.type=OBLTIN, .beg= "not"};
|
||||||
|
|
||||||
Object Comma= (Object){.type=OBLTIN, .beg=","};
|
|
||||||
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 Progn=(Object){.type=OBLTIN, .beg="progn"};
|
Object Progn=(Object){.type=OBLTIN, .beg="progn"};
|
||||||
|
|||||||
139
eval.c
139
eval.c
@ -9,8 +9,6 @@ exprlen(Object *expr)
|
|||||||
int l = 0;
|
int l = 0;
|
||||||
for(;expr->type==OCELL; expr=expr->cdr)
|
for(;expr->type==OCELL; expr=expr->cdr)
|
||||||
++l;
|
++l;
|
||||||
if(expr != &Nil)
|
|
||||||
error("Not list type");
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,14 +18,35 @@ islist(Object *obj)
|
|||||||
return obj == &Nil || obj->type == OCELL;
|
return obj == &Nil || obj->type == OCELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Object*
|
||||||
|
clone(Object *p)
|
||||||
|
{
|
||||||
|
switch(p->type){
|
||||||
|
default: panic("unreachable");
|
||||||
|
case OSYMBOL:
|
||||||
|
case OBLTIN: return p;
|
||||||
|
case OINT: return newint(gc, p->num);
|
||||||
|
case OIDENT: return newsymbol(gc, p->beg, p->ptr - p->beg);
|
||||||
|
case OCELL: return newcons(gc, clone(p->car), clone(p->cdr));
|
||||||
|
case OENV: return p;
|
||||||
|
case OMACRO:
|
||||||
|
case OFUNC: return newfn(gc, p->env, clone(p->params), clone(p->body), p->type);
|
||||||
|
case OSTRING:{
|
||||||
|
Object *s = newstr(gc, p->end - p->beg);
|
||||||
|
strinit(s, p);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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=env; cur!=&Nil; cur=cur->up)
|
||||||
for(Object *p=cur->vars; p!=&Nil; p=p->cdr)
|
for(Object *p=cur->vars; p!=&Nil; p=p->cdr)
|
||||||
if(strequal(obj, p->car->car))
|
if(strequal(obj, p->car->car))
|
||||||
return p->car;
|
return clone(p->car->cdr);
|
||||||
}
|
error("not exist variable");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +55,9 @@ _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=p->cdr)
|
||||||
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, env, params, body, type);
|
||||||
@ -48,10 +66,9 @@ _newfn(Object *env, Object *l, enum OType type)
|
|||||||
static Object*
|
static Object*
|
||||||
defvar(Object *env, Object *id, Object *val)
|
defvar(Object *env, Object *id, Object *val)
|
||||||
{
|
{
|
||||||
for(Object *p=env->vars; p!=&Nil; p=p->cdr){
|
for(Object *p=env->vars; p!=&Nil; p=p->cdr)
|
||||||
if(strequal(id, p->car->car))
|
if(strequal(id, p->car->car))
|
||||||
error("already exist variable. use setq plz...");
|
error("already exist variable. use setq plz...");
|
||||||
}
|
|
||||||
return newacons(gc, id, val, env->vars);
|
return newacons(gc, id, val, env->vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,8 +91,7 @@ progn(Object *env, Object *list)
|
|||||||
{
|
{
|
||||||
Object *r = 0;
|
Object *r = 0;
|
||||||
for(Object *p=list; p!=&Nil; p=p->cdr){
|
for(Object *p=list; p!=&Nil; p=p->cdr){
|
||||||
r = p->car;
|
r = eval(env, p->car);
|
||||||
r = eval(env, r);
|
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -91,10 +107,15 @@ fnsetq(Object *env, Object *list)
|
|||||||
{
|
{
|
||||||
if(exprlen(list)!=2 || list->car->type!=OIDENT)
|
if(exprlen(list)!=2 || list->car->type!=OIDENT)
|
||||||
error("Malformed setq");
|
error("Malformed setq");
|
||||||
Object *obj = find(env, list->car);
|
Object *cur = env;
|
||||||
if(obj == 0)
|
Object *p = 0;
|
||||||
error("Not exist variable");
|
for(; cur!=&Nil; cur=cur->up)
|
||||||
return obj->cdr = eval(env, list->cdr->car);
|
for(p=cur->vars; p!=&Nil; p=p->cdr)
|
||||||
|
if(strequal(list->car, p->car->car))
|
||||||
|
goto found;
|
||||||
|
error("setq not exist variable");
|
||||||
|
found:;
|
||||||
|
return p->car->cdr = eval(env, list->cdr->car);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -115,29 +136,30 @@ fnquote(Object *env, Object *list)
|
|||||||
return list->car;
|
return list->car;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
evalcomma(Object *env, Object *p)
|
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(p->cdr->type == OCELL && p->cdr->car == &Splice){
|
||||||
Object *obj = eval(env, p->cdr->cdr);
|
return newcons(gc, &Splice, eval(env, p->cdr->cdr));
|
||||||
return newcons(gc, &Splice, obj);
|
|
||||||
}else
|
}else
|
||||||
return eval(env, p->cdr);
|
return eval(env, p->cdr);
|
||||||
}
|
}
|
||||||
Object *car = evalcomma(env, p->car);
|
p->car = evalcomma(env, p->car);
|
||||||
Object *cdr = evalcomma(env, p->cdr);
|
p->cdr = evalcomma(env, p->cdr);
|
||||||
if(cdr->type == OCELL && cdr->car == &Splice){
|
if(p->car->type == OCELL && p->car->car == &Splice){
|
||||||
cdr = cdr->cdr;
|
Object *i = p->car;
|
||||||
|
while(i->cdr->type == OCELL && i->cdr != &Nil)
|
||||||
|
i = i->cdr;
|
||||||
|
if(i->type == OCELL){
|
||||||
|
i->cdr = p->cdr;
|
||||||
|
return p->car->cdr;
|
||||||
|
}
|
||||||
|
p->car = i;
|
||||||
}
|
}
|
||||||
if(car->type == OCELL && car->car == &Splice){
|
return p;
|
||||||
car = car->cdr;
|
|
||||||
if(cdr == &Nil)
|
|
||||||
return car;
|
|
||||||
}
|
|
||||||
return newcons(gc, car, cdr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -155,7 +177,7 @@ fncar(Object *env, Object *list)
|
|||||||
if(list->car == &Nil)
|
if(list->car == &Nil)
|
||||||
return &Nil;
|
return &Nil;
|
||||||
if(list->car->type != OCELL)
|
if(list->car->type != OCELL)
|
||||||
error("Malformed Car");
|
error("car: expected list");
|
||||||
return list->car->car;
|
return list->car->car;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +188,7 @@ fncdr(Object *env, Object *list)
|
|||||||
if(list->car == &Nil)
|
if(list->car == &Nil)
|
||||||
return &Nil;
|
return &Nil;
|
||||||
if(list->car->type != OCELL)
|
if(list->car->type != OCELL)
|
||||||
error("Malformed Car");
|
error("cdr: expected list");
|
||||||
return list->car->cdr;
|
return list->car->cdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,10 +202,11 @@ fncons(Object *env, Object *list)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
Object*
|
||||||
plusint(Object *env, Object *p)
|
fnplus(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
long sum = 0;
|
long sum = 0;
|
||||||
|
Object *p=evallist(env, list);
|
||||||
for(;p!=&Nil; p=p->cdr){
|
for(;p!=&Nil; p=p->cdr){
|
||||||
if(p->car->type != OINT)
|
if(p->car->type != OINT)
|
||||||
error("+ take only number");
|
error("+ take only number");
|
||||||
@ -192,29 +215,6 @@ plusint(Object *env, Object *p)
|
|||||||
return newint(gc, sum);
|
return newint(gc, sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
|
||||||
plusstr(Object *env, Object *p)
|
|
||||||
{
|
|
||||||
Object *str = newstr(gc, 16);
|
|
||||||
for(;p!=&Nil; p=p->cdr){
|
|
||||||
if(p->car->type != OSTRING)
|
|
||||||
error("+ take only number");
|
|
||||||
str = strputs(str, p->car);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object*
|
|
||||||
fnplus(Object *env, Object *list)
|
|
||||||
{
|
|
||||||
Object *p=evallist(env, list);
|
|
||||||
switch(p->car->type){
|
|
||||||
default: error("+ take only [STRING, INT]");
|
|
||||||
case OSTRING: return plusstr(env ,p);
|
|
||||||
case OINT: return plusint(env, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
fnmul(Object *env, Object *list)
|
fnmul(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
@ -285,9 +285,9 @@ _newint(int n)
|
|||||||
Object*
|
Object*
|
||||||
fnnot(Object *env, Object *list)
|
fnnot(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
if(list->type != OCELL || exprlen(list)!= 1)
|
if(list->type != OCELL)
|
||||||
error("Malformed not");
|
error("Malformed not");
|
||||||
return _newint(list->car == &Nil);
|
return _newint(eval(env, list->car) == &Nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -346,7 +346,7 @@ evallist(Object *env, Object *list)
|
|||||||
if(list == &Nil)
|
if(list == &Nil)
|
||||||
return &Nil;
|
return &Nil;
|
||||||
if(list->type != OCELL)
|
if(list->type != OCELL)
|
||||||
error("type is not list");
|
error("expected list");
|
||||||
Object *car = eval(env, list->car);
|
Object *car = eval(env, list->car);
|
||||||
Object *cdr = evallist(env, list->cdr);
|
Object *cdr = evallist(env, list->cdr);
|
||||||
return newcons(gc, car, cdr);
|
return newcons(gc, car, cdr);
|
||||||
@ -355,17 +355,23 @@ evallist(Object *env, Object *list)
|
|||||||
static Object*
|
static Object*
|
||||||
enter(Object *env, Object *vars, Object *args)
|
enter(Object *env, Object *vars, 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=args->cdr){
|
for(;vars->type==OCELL; vars=vars->cdr, args=cdr(args)){
|
||||||
if(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 = vars->car;
|
||||||
Object *val = args->car;
|
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 newenv(gc, &Nil, map, env);
|
||||||
|
|
||||||
|
#undef car
|
||||||
|
#undef cdr
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object*
|
static Object*
|
||||||
@ -423,13 +429,12 @@ eval(Object *env, Object *obj)
|
|||||||
case OSYMBOL:
|
case OSYMBOL:
|
||||||
return obj;
|
return obj;
|
||||||
case OIDENT:{
|
case OIDENT:{
|
||||||
Object* val = find(env, obj);
|
return find(env, obj);
|
||||||
if(val == 0)
|
|
||||||
error("not exist '%s'", obj->beg);
|
|
||||||
return val->cdr;
|
|
||||||
}
|
}
|
||||||
case OCELL:{
|
case OCELL:{
|
||||||
Object *fn = eval(env, obj->car);
|
Object *fn = eval(env, obj->car);
|
||||||
|
if(fn == &Nil)
|
||||||
|
return &Nil;
|
||||||
Object *res = apply(env, fn, obj->cdr);
|
Object *res = apply(env, fn, obj->cdr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
12
lib/lib.lisp
12
lib/lib.lisp
@ -3,12 +3,6 @@
|
|||||||
|
|
||||||
(defun list (x . y) (cons x y))
|
(defun list (x . y) (cons x y))
|
||||||
|
|
||||||
(macro and (expr . rest)
|
(macro cond (expr . rest)
|
||||||
(if rest (list 'if expr (cons 'and rest)) expr))
|
(if (not expr) nil
|
||||||
|
`(if ,(car expr) (progn ,@expr) (cond ,@rest))))
|
||||||
(macro cond (expr. rest)
|
|
||||||
(if rest (list 'if (car expr) (car (cdr expr)) (cons 'cond rest))
|
|
||||||
expr))
|
|
||||||
|
|
||||||
;exampe (cond ((== 1 0) 0) ((== 1 1) -1) (+ 100000000))
|
|
||||||
;exampe (cond ((== 1 0) 0) ((== 1 0) -1) (+ 100000000))
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user