From 2ddcc7578c967867904269dc1567fd03c4414449 Mon Sep 17 00:00:00 2001 From: yoyo Date: Mon, 9 Sep 2024 20:42:20 +0900 Subject: [PATCH] add splice for `(,@var) --- bltin.c | 1 + dat.h | 1 + eval.c | 36 ++++++++++++++++++++++++++---------- main.c | 2 +- obj.c | 2 +- parser.c | 16 ++++++++++++++-- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/bltin.c b/bltin.c index 87f0ca2..8fa0ecc 100644 --- a/bltin.c +++ b/bltin.c @@ -2,6 +2,7 @@ #include "fn.h" Object Nil = (Object){.type=OSYMBOL, .beg="nil"}; +Object Splice= (Object){.type=OSYMBOL, .beg="@"}; Object Minus= (Object){.type=OBLTIN, .beg="-"}; Object Plus = (Object){.type=OBLTIN, .beg="+"}; Object Mul = (Object){.type=OBLTIN, .beg="*"}; diff --git a/dat.h b/dat.h index eed8344..c661949 100644 --- a/dat.h +++ b/dat.h @@ -53,6 +53,7 @@ struct Object extern GC *gc; extern Object Nil; extern Object Comma; +extern Object Splice; extern Object Bquote; extern Object Minus; extern Object Plus; diff --git a/eval.c b/eval.c index 5e0a5ea..70ad46d 100644 --- a/eval.c +++ b/eval.c @@ -118,15 +118,26 @@ fnquote(Object *env, Object *list) static Object* evalcomma(Object *env, Object *p) { - if(p->type == OCELL){ - if(p->car == &Comma) + if(p->type != OCELL) + 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); - 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* @@ -141,7 +152,9 @@ Object* fncar(Object *env, Object *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"); return list->car->car; } @@ -150,7 +163,9 @@ Object* fncdr(Object *env, Object *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"); return list->car->cdr; } @@ -378,7 +393,8 @@ apply(Object *env, Object *fn, Object *args) if(islist(args) == 0) error("args is not list type"); switch(fn->type){ - default: error("apply only tabke [MACRO BLTIN FUNC]"); + default: + error("apply only tabke [MACRO BLTIN FUNC]"); case OMACRO: return applymacro(env, fn, args); case OBLTIN:{ diff --git a/main.c b/main.c index e943d04..2f37c66 100644 --- a/main.c +++ b/main.c @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) { *argv = "lib/lib.lisp"; - gc = newgc(&argc, 400); + gc = newgc(&argc, 12000); lispmain(argv); panic("unreachable"); } diff --git a/obj.c b/obj.c index ce51c90..15e1627 100644 --- a/obj.c +++ b/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, + &Comma, &Not, &Splice, }; for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){ Object *c = syms[i]; diff --git a/parser.c b/parser.c index c0bc64c..ac8e344 100644 --- a/parser.c +++ b/parser.c @@ -140,6 +140,12 @@ lparlist(FILE *f, int *bq) if(*bq <= 0) error("comma is illegal outside of backquote"); 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)); cdr = lparlist(f, bq); return newcons(gc, car, cdr); @@ -180,9 +186,15 @@ redo: if(*bq <= 0) error("comma is illegal outside of backquote"); 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 '\'': - get(f); + get(f); return quote(f, &Quote, bq); case '(':{ get(f);