add macro support
This commit is contained in:
parent
c63c1eaf6e
commit
2e7d05f783
6 changed files with 95 additions and 20 deletions
|
|
@ -177,7 +177,7 @@ static int nested_p(Cm *c, O body) {
|
|||
}
|
||||
|
||||
// Compile a closure with `args` and `body`.
|
||||
static V compile_fn(Cm *c, O args, O body) {
|
||||
static V compile_fn(Cm *c, O args, O body, I macro) {
|
||||
// Create an inner compiler context for compiling the closure's body.
|
||||
Cm ic;
|
||||
memset(&ic, 0, sizeof(Cm));
|
||||
|
|
@ -204,14 +204,14 @@ static V compile_fn(Cm *c, O args, O body) {
|
|||
if (rest == NIL && !nested) {
|
||||
// If the function has no rest argument, and has no nested closures inside
|
||||
// it, compile using stack locals as an optimization for tail-calls
|
||||
ic.use_stack_locals = 1;
|
||||
ic.use_locals = 1;
|
||||
curr = args;
|
||||
for (O next = list_next(c->in, &curr); next != NIL;
|
||||
next = list_next(c->in, &curr))
|
||||
add_local(&ic, next);
|
||||
} else {
|
||||
// Otherwise, fallback to using environment bindings for locals
|
||||
ic.use_stack_locals = 0;
|
||||
ic.use_locals = 0;
|
||||
if (rest != NIL) {
|
||||
emit(&ic, OP_BIND_REST);
|
||||
emit16(&ic, add_constant(&ic, rest));
|
||||
|
|
@ -231,7 +231,7 @@ static V compile_fn(Cm *c, O args, O body) {
|
|||
Z args_idx = add_constant(c, args);
|
||||
|
||||
// Compile pushing the closure to the stack.
|
||||
emit(c, OP_CLOS);
|
||||
emit(c, macro ? OP_MAC : OP_CLOS);
|
||||
emit16(c, code_idx);
|
||||
emit16(c, args_idx);
|
||||
|
||||
|
|
@ -256,6 +256,8 @@ static V compile_def(Cm *c, O args, I tail) {
|
|||
emit(c, OP_RET);
|
||||
}
|
||||
|
||||
O vm_apply(In *in, O macro, O args);
|
||||
|
||||
// Compile a function application/special form
|
||||
static V compile_apply(Cm *co, O expr, I tail) {
|
||||
Pa *p = pair_unwrap(co->in, expr);
|
||||
|
|
@ -278,7 +280,13 @@ static V compile_apply(Cm *co, O expr, I tail) {
|
|||
return;
|
||||
} else if (head == co->specials.fn) {
|
||||
Pa *args = pair_unwrap(co->in, p->tail);
|
||||
compile_fn(co, args->head, args->tail);
|
||||
compile_fn(co, args->head, args->tail, 0);
|
||||
if (tail)
|
||||
emit(co, OP_RET);
|
||||
return;
|
||||
} else if (head == co->specials.mac) {
|
||||
Pa *args = pair_unwrap(co->in, p->tail);
|
||||
compile_fn(co, args->head, args->tail, 1);
|
||||
if (tail)
|
||||
emit(co, OP_RET);
|
||||
return;
|
||||
|
|
@ -286,6 +294,17 @@ static V compile_apply(Cm *co, O expr, I tail) {
|
|||
compile_def(co, p->tail, tail);
|
||||
return;
|
||||
}
|
||||
if (find_local(co, head) == -1) {
|
||||
O obj = list_assoc(co->in, head, co->in->env);
|
||||
if (obj != NIL) {
|
||||
obj = pair_unwrap(co->in, obj)->tail;
|
||||
if (type(obj) == TYPE_MAC) {
|
||||
O exp = vm_apply(co->in, obj, p->tail);
|
||||
compile(co, exp, tail);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
compile_call(co, head, p->tail, tail);
|
||||
}
|
||||
|
|
@ -303,6 +322,8 @@ V compile(Cm *co, O expr, I tail) {
|
|||
co->specials.fn = symbol_make(co->in, "fn");
|
||||
if (co->specials.def == NIL)
|
||||
co->specials.def = symbol_make(co->in, "def");
|
||||
if (co->specials.mac == NIL)
|
||||
co->specials.mac = symbol_make(co->in, "mac");
|
||||
|
||||
switch (ty) {
|
||||
case TYPE_NIL:
|
||||
|
|
@ -314,7 +335,7 @@ V compile(Cm *co, O expr, I tail) {
|
|||
emit(co, OP_RET);
|
||||
break;
|
||||
case TYPE_SYM:
|
||||
if (co->use_stack_locals) {
|
||||
if (co->use_locals) {
|
||||
int idx = find_local(co, expr);
|
||||
if (idx >= 0) {
|
||||
emit(co, OP_GET_LOCAL);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue