implement macros and dotted pairs

This commit is contained in:
Lobo 2026-01-11 22:17:36 -03:00
parent 44237a650d
commit a7295cba7e
8 changed files with 68 additions and 13 deletions

View file

@ -69,13 +69,13 @@ enum {
enum { enum {
TYPE_NIL = 0, TYPE_NIL = 0,
TYPE_NUM = 1, TYPE_NUM = 1, // These three are the same as their tags.
TYPE_SYM = 2, TYPE_SYM = 2,
TYPE_PRIM = 4, TYPE_PRIM = 4,
TYPE_PAIR, // = 5, TYPE_PAIR,
TYPE_CLOS, // = 6, TYPE_CLOS,
TYPE_CODE, // = 7, TYPE_MAC,
TYPE_FWD, // = 8, TYPE_FWD,
TYPE__MAX, TYPE__MAX,
}; };

View file

@ -10,6 +10,8 @@ V interp_init(In *in) {
gc_addroot(&in->gc, &in->env); gc_addroot(&in->gc, &in->env);
in->t = symbol_make(in, "t"); in->t = symbol_make(in, "t");
in->env = NIL; in->env = NIL;
// Add T symbol
in->env = pair_make(in, pair_make(in, in->t, in->t), in->env); in->env = pair_make(in, pair_make(in, in->t, in->t), in->env);
#define PRIM(name, prim) \ #define PRIM(name, prim) \
@ -35,6 +37,7 @@ V interp_init(In *in) {
PRIM("=", prim_equal); PRIM("=", prim_equal);
PRIM("fn", prim_fn); PRIM("fn", prim_fn);
PRIM("mac", prim_mac);
PRIM("gc", prim_gc); PRIM("gc", prim_gc);
#undef PRIM #undef PRIM
} }
@ -135,8 +138,20 @@ static O apply(In *in, O fn, O args, O env) {
O nenv = bind(in, cl->args, args, cl->env); O nenv = bind(in, cl->args, args, cl->env);
// `bind' may have moved the closure if a GC was triggered // `bind' may have moved the closure if a GC was triggered
cl = (Cl *)(UNBOX(fn) + 1); cl = (Cl *)(UNBOX(fn) + 1);
O res = eval(in, cl->body, nenv);
gc_rootreset(&in->gc, mark); gc_rootreset(&in->gc, mark);
return eval(in, cl->body, nenv); return res;
}
case TYPE_MAC: {
Gh *hdr = UNBOX(fn);
Cl *cl = (Cl *)(hdr + 1);
O nenv = bind(in, cl->args, args, cl->env);
cl = (Cl *)(UNBOX(fn) + 1);
O exp = eval(in, cl->body, nenv);
gc_addroot(&in->gc, &exp);
O res = eval(in, exp, env);
gc_rootreset(&in->gc, mark);
return res;
} }
default: default:
error_throw(in, "tried to call non-function value"); error_throw(in, "tried to call non-function value");

View file

@ -1,3 +1,5 @@
/* List utilities. */
#include <wolflisp.h> #include <wolflisp.h>
O list_assoc(O key, O alist) { O list_assoc(O key, O alist) {

View file

@ -223,6 +223,30 @@ O prim_fn(In *in, O args, O env) {
return BOX(hdr); return BOX(hdr);
} }
O prim_mac(In *in, O args, O env) {
O params = nextarg(&args);
O body = args;
I mark = gc_rootmark(&in->gc);
gc_addroot(&in->gc, &params);
gc_addroot(&in->gc, &env);
gc_addroot(&in->gc, &body);
O progn = symbol_make(in, "progn");
O body_form = pair_make(in, progn, body);
gc_addroot(&in->gc, &body_form);
Gh *hdr = gc_alloc(&in->gc, sizeof(Gh) + sizeof(Cl));
hdr->type = TYPE_MAC;
Cl *cl = (Cl *)(hdr + 1);
cl->args = params;
cl->env = env;
cl->body = body_form;
gc_rootreset(&in->gc, mark);
return BOX(hdr);
}
O prim_gc(In *in, O args, O env) { O prim_gc(In *in, O args, O env) {
(void)in; (void)in;
(void)args; (void)args;

View file

@ -17,6 +17,7 @@ O prim_equal(In *in, O args, O env);
O prim_lt(In *in, O args, O env); O prim_lt(In *in, O args, O env);
O prim_gt(In *in, O args, O env); O prim_gt(In *in, O args, O env);
O prim_fn(In *in, O args, O env); O prim_fn(In *in, O args, O env);
O prim_mac(In *in, O args, O env);
O prim_gc(In *in, O args, O env); O prim_gc(In *in, O args, O env);
O prim_def(In *in, O args, O env); O prim_def(In *in, O args, O env);
O prim_defn(In *in, O args, O env); O prim_defn(In *in, O args, O env);

View file

@ -30,7 +30,23 @@ int read_expr(In *in, Lx *lex, O *result) {
gc_addroot(&in->gc, &tail); gc_addroot(&in->gc, &tail);
while (lex->kind != TOK_RPAREN && lex->kind != TOK_EOF) { while (lex->kind != TOK_RPAREN && lex->kind != TOK_EOF) {
O elem; if (lex->kind == TOK_DOT) {
if (list == NIL)
error_throw(in, "unexpected .");
nexttoken(lex);
O last = NIL;
read_expr(in, lex, &last);
nexttoken(lex);
pair_unwrap(tail)->tail = last;
if (lex->kind != TOK_RPAREN)
error_throw(in, "expected closing parenthesis");
break;
}
O elem = NIL;
read_expr(in, lex, &elem); read_expr(in, lex, &elem);
nexttoken(lex); nexttoken(lex);

View file

@ -11,7 +11,7 @@ static const char *typenames[] = {
[TYPE_PRIM] = "primitive", [TYPE_PRIM] = "primitive",
[TYPE_PAIR] = "pair", [TYPE_PAIR] = "pair",
[TYPE_CLOS] = "closure", [TYPE_CLOS] = "closure",
[TYPE_CODE] = "code", [TYPE_MAC] = "macro",
}; };
// clang-format on // clang-format on

View file

@ -1,3 +0,0 @@
(defn fib (n)
(if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
(println (fib 10))