initial closure support
This commit is contained in:
parent
4b31901bce
commit
337b54dc40
|
@ -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
|
||||||
|
|
7
src/vm.c
7
src/vm.c
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue