add splice for `(,@var)
This commit is contained in:
parent
67788893b3
commit
2ddcc7578c
1
bltin.c
1
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 Splice= (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="*"};
|
||||||
|
|||||||
1
dat.h
1
dat.h
@ -53,6 +53,7 @@ struct Object
|
|||||||
extern GC *gc;
|
extern GC *gc;
|
||||||
extern Object Nil;
|
extern Object Nil;
|
||||||
extern Object Comma;
|
extern Object Comma;
|
||||||
|
extern Object Splice;
|
||||||
extern Object Bquote;
|
extern Object Bquote;
|
||||||
extern Object Minus;
|
extern Object Minus;
|
||||||
extern Object Plus;
|
extern Object Plus;
|
||||||
|
|||||||
36
eval.c
36
eval.c
@ -118,15 +118,26 @@ fnquote(Object *env, Object *list)
|
|||||||
static Object*
|
static Object*
|
||||||
evalcomma(Object *env, Object *p)
|
evalcomma(Object *env, Object *p)
|
||||||
{
|
{
|
||||||
if(p->type == OCELL){
|
if(p->type != OCELL)
|
||||||
if(p->car == &Comma)
|
return p;
|
||||||
|
if(p->car == &Comma){
|
||||||
|
if(p->cdr->type == OCELL && p->cdr->car == &Splice){
|
||||||
|
Object *obj = eval(env, p->cdr->cdr);
|
||||||
|
return newcons(gc, &Splice, obj);
|
||||||
|
}else
|
||||||
return eval(env, p->cdr);
|
return eval(env, p->cdr);
|
||||||
Object *dst = newcons(gc, p->car, p->cdr);
|
|
||||||
dst->car = evalcomma(env, p->car);
|
|
||||||
dst->cdr = evalcomma(env, p->cdr);
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
return p;
|
Object *car = evalcomma(env, p->car);
|
||||||
|
Object *cdr = evalcomma(env, p->cdr);
|
||||||
|
if(cdr->type == OCELL && cdr->car == &Splice){
|
||||||
|
cdr = cdr->cdr;
|
||||||
|
}
|
||||||
|
if(car->type == OCELL && car->car == &Splice){
|
||||||
|
car = car->cdr;
|
||||||
|
if(cdr == &Nil)
|
||||||
|
return car;
|
||||||
|
}
|
||||||
|
return newcons(gc, car, cdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
@ -141,7 +152,9 @@ Object*
|
|||||||
fncar(Object *env, Object *list)
|
fncar(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
list = evallist(env, list);
|
list = evallist(env, list);
|
||||||
if(list->car->type != OCELL || list->cdr != &Nil)
|
if(list->car == &Nil)
|
||||||
|
return &Nil;
|
||||||
|
if(list->car->type != OCELL)
|
||||||
error("Malformed Car");
|
error("Malformed Car");
|
||||||
return list->car->car;
|
return list->car->car;
|
||||||
}
|
}
|
||||||
@ -150,7 +163,9 @@ Object*
|
|||||||
fncdr(Object *env, Object *list)
|
fncdr(Object *env, Object *list)
|
||||||
{
|
{
|
||||||
list = evallist(env, list);
|
list = evallist(env, list);
|
||||||
if(list->car->type != OCELL || list->cdr != &Nil)
|
if(list->car == &Nil)
|
||||||
|
return &Nil;
|
||||||
|
if(list->car->type != OCELL)
|
||||||
error("Malformed Car");
|
error("Malformed Car");
|
||||||
return list->car->cdr;
|
return list->car->cdr;
|
||||||
}
|
}
|
||||||
@ -378,7 +393,8 @@ apply(Object *env, Object *fn, Object *args)
|
|||||||
if(islist(args) == 0)
|
if(islist(args) == 0)
|
||||||
error("args is not list type");
|
error("args is not list type");
|
||||||
switch(fn->type){
|
switch(fn->type){
|
||||||
default: error("apply only tabke [MACRO BLTIN FUNC]");
|
default:
|
||||||
|
error("apply only tabke [MACRO BLTIN FUNC]");
|
||||||
case OMACRO:
|
case OMACRO:
|
||||||
return applymacro(env, fn, args);
|
return applymacro(env, fn, args);
|
||||||
case OBLTIN:{
|
case OBLTIN:{
|
||||||
|
|||||||
2
main.c
2
main.c
@ -60,7 +60,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, 12000);
|
||||||
lispmain(argv);
|
lispmain(argv);
|
||||||
panic("unreachable");
|
panic("unreachable");
|
||||||
}
|
}
|
||||||
|
|||||||
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,
|
&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,
|
&Comma, &Not, &Splice,
|
||||||
};
|
};
|
||||||
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
parser.c
16
parser.c
@ -140,6 +140,12 @@ lparlist(FILE *f, int *bq)
|
|||||||
if(*bq <= 0)
|
if(*bq <= 0)
|
||||||
error("comma is illegal outside of backquote");
|
error("comma is illegal outside of backquote");
|
||||||
get(f);
|
get(f);
|
||||||
|
if(lookup(f) == '@'){
|
||||||
|
get(f);
|
||||||
|
res = newcons(gc, &Comma, &Nil);
|
||||||
|
res->cdr = newcons(gc, &Splice, list(f, bq));
|
||||||
|
return newcons(gc, res, lparlist(f, bq));
|
||||||
|
}
|
||||||
car = newcons(gc, &Comma, list(f, bq));
|
car = newcons(gc, &Comma, list(f, bq));
|
||||||
cdr = lparlist(f, bq);
|
cdr = lparlist(f, bq);
|
||||||
return newcons(gc, car, cdr);
|
return newcons(gc, car, cdr);
|
||||||
@ -180,9 +186,15 @@ redo:
|
|||||||
if(*bq <= 0)
|
if(*bq <= 0)
|
||||||
error("comma is illegal outside of backquote");
|
error("comma is illegal outside of backquote");
|
||||||
get(f);
|
get(f);
|
||||||
return newcons(gc, &Comma, list(f, bq));
|
if(lookup(f) == '@'){
|
||||||
|
get(f);
|
||||||
|
res = newcons(gc, &Comma, &Nil);
|
||||||
|
res->cdr = newcons(gc, &Splice, list(f, bq));
|
||||||
|
}else
|
||||||
|
res = newcons(gc, &Comma, list(f, bq));
|
||||||
|
return res;
|
||||||
case '\'':
|
case '\'':
|
||||||
get(f);
|
get(f);
|
||||||
return quote(f, &Quote, bq);
|
return quote(f, &Quote, bq);
|
||||||
case '(':{
|
case '(':{
|
||||||
get(f);
|
get(f);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user