initial closure support

This commit is contained in:
Yuichi Nishiwaki 2013-10-24 02:51:02 +09:00
parent 4b31901bce
commit 337b54dc40
2 changed files with 30 additions and 18 deletions

View File

@ -6,6 +6,8 @@
#include "picrin/proc.h" #include "picrin/proc.h"
#include "xhash/xhash.h" #include "xhash/xhash.h"
#define FALLTHROUGH ((void)0)
typedef struct codegen_scope { typedef struct codegen_scope {
struct codegen_scope *up; struct codegen_scope *up;
@ -167,22 +169,23 @@ codegen(codegen_state *state, pic_value obj)
pic_error(pic, "unbound variable"); pic_error(pic, "unbound variable");
} }
if (depth == -1) { /* global */ switch (depth) {
case -1: /* global */
irep->code[irep->clen].insn = OP_GREF; irep->code[irep->clen].insn = OP_GREF;
irep->code[irep->clen].u.i = idx; irep->code[irep->clen].u.i = idx;
irep->clen++; irep->clen++;
} break;
else if (depth == 0) { /* local */ default: /* nonlocal */
irep->code[irep->clen].insn = OP_LREF;
irep->code[irep->clen].u.i = idx;
irep->clen++;
}
else { /* nonlocal */
/* dirty flag */ /* dirty flag */
s->cv_tbl[idx] = 1; s->cv_tbl[idx] = 1;
/* dummy code */ /* at this stage, lref and cref are not distinguished */
irep->code[irep->clen].insn = OP_PUSHNIL; FALLTHROUGH;
case 0: /* local */
irep->code[irep->clen].insn = OP_CREF;
irep->code[irep->clen].u.c.depth = depth;
irep->code[irep->clen].u.c.idx = idx;
irep->clen++; irep->clen++;
break;
} }
break; break;
} }
@ -207,11 +210,12 @@ codegen(codegen_state *state, pic_value obj)
break; break;
} }
else if (pic_eq_p(pic, proc, pic->sLAMBDA)) { else if (pic_eq_p(pic, proc, pic->sLAMBDA)) {
int k = pic->ilen++;
irep->code[irep->clen].insn = OP_LAMBDA; irep->code[irep->clen].insn = OP_LAMBDA;
irep->code[irep->clen].u.i = pic->ilen; irep->code[irep->clen].u.i = k;
irep->clen++; irep->clen++;
pic->irep[pic->ilen++] = codegen_lambda(state, obj); pic->irep[k] = codegen_lambda(state, obj);
break; break;
} }
else if (pic_eq_p(pic, proc, pic->sIF)) { else if (pic_eq_p(pic, proc, pic->sIF)) {
@ -401,12 +405,14 @@ codegen_lambda(codegen_state *state, pic_value obj)
irep->code[irep->clen].insn = OP_RET; irep->code[irep->clen].insn = OP_RET;
irep->clen++; irep->clen++;
printf("** dirty **\n"); /* fixup */
for (i = 1; i < state->scope->argc; ++i) { for (i = 0; i < irep->clen; ++i) {
if (state->scope->cv_tbl[i]) struct pic_code c = irep->code[i];
printf("%d ", i); if (c.insn == OP_CREF && c.u.c.depth == 0 && ! state->scope->cv_tbl[c.u.c.idx]) {
irep->code[i].insn = OP_LREF;
irep->code[i].u.i = irep->code[i].u.c.idx;
}
} }
puts("");
} }
destroy_scope(pic, state->scope); destroy_scope(pic, state->scope);
@ -414,7 +420,6 @@ codegen_lambda(codegen_state *state, pic_value obj)
state->scope = prev_scope; state->scope = prev_scope;
#if VM_DEBUG #if VM_DEBUG
printf("LAMBDA_%zd:\n", pic->ilen);
print_irep(pic, irep); print_irep(pic, irep);
puts(""); puts("");
#endif #endif

View File

@ -224,10 +224,15 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args)
NEXT; NEXT;
} }
else { else {
int i;
if (ci->argc != proc->u.irep->argc) { if (ci->argc != proc->u.irep->argc) {
pic->errmsg = "wrong number of arguments"; pic->errmsg = "wrong number of arguments";
goto L_RAISE; goto L_RAISE;
} }
for (i = 0; i < proc->u.irep->argc; ++i) {
proc->env->values[i] = ci->fp[i];
}
pc = proc->u.irep->code; pc = proc->u.irep->code;
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
JUMP; JUMP;
@ -256,6 +261,8 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args)
struct pic_env *env; struct pic_env *env;
env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV); env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV);
env->numcv = pic->irep[pc->u.i]->argc;
env->values = (pic_value *)pic_alloc(pic, sizeof(pic_value) * env->numcv);
env->up = pic_proc_ptr(*pic->ci->fp)->env; env->up = pic_proc_ptr(*pic->ci->fp)->env;
proc = pic_proc_new(pic, pic->irep[pc->u.i], env); proc = pic_proc_new(pic, pic->irep[pc->u.i], env);