store constructing iseq in scope object, not pic_irep

This commit is contained in:
Yuichi Nishiwaki 2014-01-18 20:49:01 +09:00
parent 05a69d10dd
commit 801d92e0a4
1 changed files with 144 additions and 130 deletions

View File

@ -27,9 +27,9 @@ new_irep(pic_state *pic)
struct pic_irep *irep; struct pic_irep *irep;
irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP); irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP);
irep->code = (struct pic_code *)pic_alloc(pic, sizeof(struct pic_code) * 1024); irep->code = NULL;
irep->clen = 0; irep->clen = 0;
irep->ccapa = 1024; irep->ccapa = 0;
irep->argc = -1; irep->argc = -1;
irep->localc = -1; irep->localc = -1;
irep->varg = false; irep->varg = false;
@ -41,15 +41,18 @@ new_irep(pic_state *pic)
*/ */
typedef struct codegen_scope { typedef struct codegen_scope {
struct codegen_scope *up; bool varg;
/* local variables are 1-indexed, 0 is reserved for the callee */ /* local variables are 1-indexed, 0 is reserved for the callee */
struct xhash *local_tbl; struct xhash *local_tbl;
/* rest args variable is counted at localc */ /* rest args variable is counted at localc */
size_t argc, localc; size_t argc, localc;
/* if local var i is captured, then dirty_flags[i] == 1 */ /* if local var i is captured, then dirty_flags[i] == 1 */
int *dirty_flags; int *dirty_flags;
bool varg; /* actual bit code sequence */
struct pic_code *code;
size_t clen, ccapa;
struct codegen_scope *up;
} codegen_scope; } codegen_scope;
static codegen_scope * static codegen_scope *
@ -64,6 +67,10 @@ new_global_scope(pic_state *pic)
scope->localc = -1; scope->localc = -1;
scope->dirty_flags = NULL; scope->dirty_flags = NULL;
scope->varg = false; scope->varg = false;
scope->code = (struct pic_code *)pic_alloc(pic, sizeof(struct pic_code) * 1024);
scope->clen = 0;
scope->ccapa = 1024;
return scope; return scope;
} }
@ -101,6 +108,10 @@ new_local_scope(pic_state *pic, pic_value args, codegen_scope *scope)
new_scope->localc = l; new_scope->localc = l;
new_scope->dirty_flags = (int *)pic_calloc(pic, i + l, sizeof(int)); new_scope->dirty_flags = (int *)pic_calloc(pic, i + l, sizeof(int));
new_scope->code = (struct pic_code *)pic_alloc(pic, sizeof(struct pic_code) * 1024);
new_scope->clen = 0;
new_scope->ccapa = 1024;
return new_scope; return new_scope;
} }
@ -121,7 +132,6 @@ destroy_scope(pic_state *pic, codegen_scope *scope)
typedef struct codegen_state { typedef struct codegen_state {
pic_state *pic; pic_state *pic;
codegen_scope *scope; codegen_scope *scope;
struct pic_irep *irep;
} codegen_state; } codegen_state;
static codegen_state * static codegen_state *
@ -211,7 +221,7 @@ static void
codegen(codegen_state *state, pic_value obj, bool tailpos) codegen(codegen_state *state, pic_value obj, bool tailpos)
{ {
pic_state *pic = state->pic; pic_state *pic = state->pic;
struct pic_irep *irep = state->irep; codegen_scope *scope = state->scope;
switch (pic_type(obj)) { switch (pic_type(obj)) {
case PIC_TT_SYMBOL: { case PIC_TT_SYMBOL: {
@ -230,19 +240,19 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
switch (depth) { switch (depth) {
case -1: /* global */ case -1: /* global */
irep->code[irep->clen].insn = OP_GREF; scope->code[scope->clen].insn = OP_GREF;
irep->code[irep->clen].u.i = idx; scope->code[scope->clen].u.i = idx;
irep->clen++; scope->clen++;
break; break;
default: /* nonlocal */ default: /* nonlocal */
s->dirty_flags[idx] = 1; s->dirty_flags[idx] = 1;
/* at this stage, lref and cref are not distinguished */ /* at this stage, lref and cref are not distinguished */
FALLTHROUGH; FALLTHROUGH;
case 0: /* local */ case 0: /* local */
irep->code[irep->clen].insn = OP_CREF; scope->code[scope->clen].insn = OP_CREF;
irep->code[irep->clen].u.r.depth = depth; scope->code[scope->clen].u.r.depth = depth;
irep->code[irep->clen].u.r.idx = idx; scope->code[scope->clen].u.r.idx = idx;
irep->clen++; scope->clen++;
break; break;
} }
break; break;
@ -288,22 +298,22 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
if (scope_is_global(s)) { if (scope_is_global(s)) {
idx = scope_global_define(pic, pic_symbol_name(pic, pic_sym(var))); idx = scope_global_define(pic, pic_symbol_name(pic, pic_sym(var)));
codegen(state, val, false); codegen(state, val, false);
irep->code[irep->clen].insn = OP_GSET; scope->code[scope->clen].insn = OP_GSET;
irep->code[irep->clen].u.i = idx; scope->code[scope->clen].u.i = idx;
irep->clen++; scope->clen++;
irep->code[irep->clen].insn = OP_PUSHNONE; scope->code[scope->clen].insn = OP_PUSHNONE;
irep->clen++; scope->clen++;
break; break;
} }
else { else {
idx = scope_local_define(pic, pic_symbol_name(pic, pic_sym(var)), s); idx = scope_local_define(pic, pic_symbol_name(pic, pic_sym(var)), s);
codegen(state, val, false); codegen(state, val, false);
irep->code[irep->clen].insn = OP_CSET; scope->code[scope->clen].insn = OP_CSET;
irep->code[irep->clen].u.r.depth = 0; scope->code[scope->clen].u.r.depth = 0;
irep->code[irep->clen].u.r.idx = idx; scope->code[scope->clen].u.r.idx = idx;
irep->clen++; scope->clen++;
irep->code[irep->clen].insn = OP_PUSHNONE; scope->code[scope->clen].insn = OP_PUSHNONE;
irep->clen++; scope->clen++;
break; break;
} }
} }
@ -320,9 +330,9 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
pic->icapa *= 2; pic->icapa *= 2;
} }
k = pic->ilen++; k = pic->ilen++;
irep->code[irep->clen].insn = OP_LAMBDA; scope->code[scope->clen].insn = OP_LAMBDA;
irep->code[irep->clen].u.i = k; scope->code[scope->clen].u.i = k;
irep->clen++; scope->clen++;
/* prevent GC from hanging */ /* prevent GC from hanging */
pic->irep[k] = NULL; pic->irep[k] = NULL;
@ -348,19 +358,19 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_JMPIF; scope->code[scope->clen].insn = OP_JMPIF;
s = irep->clen++; s = scope->clen++;
/* if false branch */ /* if false branch */
codegen(state, if_false, tailpos); codegen(state, if_false, tailpos);
irep->code[irep->clen].insn = OP_JMP; scope->code[scope->clen].insn = OP_JMP;
t = irep->clen++; t = scope->clen++;
irep->code[s].u.i = irep->clen - s; scope->code[s].u.i = scope->clen - s;
/* if true branch */ /* if true branch */
codegen(state, if_true, tailpos); codegen(state, if_true, tailpos);
irep->code[t].u.i = irep->clen - t; scope->code[t].u.i = scope->clen - t;
break; break;
} }
else if (sym == pic->sBEGIN) { else if (sym == pic->sBEGIN) {
@ -376,8 +386,8 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
} }
else { else {
codegen(state, v, false); codegen(state, v, false);
irep->code[irep->clen].insn = OP_POP; scope->code[scope->clen].insn = OP_POP;
irep->clen++; scope->clen++;
} }
seq = pic_cdr(pic, seq); seq = pic_cdr(pic, seq);
} }
@ -406,24 +416,24 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
switch (depth) { switch (depth) {
case -1: /* global */ case -1: /* global */
irep->code[irep->clen].insn = OP_GSET; scope->code[scope->clen].insn = OP_GSET;
irep->code[irep->clen].u.i = idx; scope->code[scope->clen].u.i = idx;
irep->clen++; scope->clen++;
break; break;
default: /* nonlocal */ default: /* nonlocal */
s->dirty_flags[idx] = 1; s->dirty_flags[idx] = 1;
/* at this stage, lset and cset are not distinguished */ /* at this stage, lset and cset are not distinguished */
FALLTHROUGH; FALLTHROUGH;
case 0: /* local */ case 0: /* local */
irep->code[irep->clen].insn = OP_CSET; scope->code[scope->clen].insn = OP_CSET;
irep->code[irep->clen].u.r.depth = depth; scope->code[scope->clen].u.r.depth = depth;
irep->code[irep->clen].u.r.idx = idx; scope->code[scope->clen].u.r.idx = idx;
irep->clen++; scope->clen++;
break; break;
} }
irep->code[irep->clen].insn = OP_PUSHNONE; scope->code[scope->clen].insn = OP_PUSHNONE;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->sQUOTE) { else if (sym == pic->sQUOTE) {
@ -438,9 +448,9 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
pic_abort(pic, "constant pool overflow"); pic_abort(pic, "constant pool overflow");
} }
pic->pool[pidx] = pic_car(pic, pic_cdr(pic, obj)); pic->pool[pidx] = pic_car(pic, pic_cdr(pic, obj));
irep->code[irep->clen].insn = OP_PUSHCONST; scope->code[scope->clen].insn = OP_PUSHCONST;
irep->code[irep->clen].u.i = pidx; scope->code[scope->clen].u.i = pidx;
irep->clen++; scope->clen++;
break; break;
} }
@ -454,29 +464,29 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
irep->code[irep->clen].insn = OP_CONS; scope->code[scope->clen].insn = OP_CONS;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rCAR) { else if (sym == pic->rCAR) {
ARGC_ASSERT(1); ARGC_ASSERT(1);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_CAR; scope->code[scope->clen].insn = OP_CAR;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rCDR) { else if (sym == pic->rCDR) {
ARGC_ASSERT(1); ARGC_ASSERT(1);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_CDR; scope->code[scope->clen].insn = OP_CDR;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rNILP) { else if (sym == pic->rNILP) {
ARGC_ASSERT(1); ARGC_ASSERT(1);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_NILP; scope->code[scope->clen].insn = OP_NILP;
irep->clen++; scope->clen++;
break; break;
} }
@ -492,9 +502,9 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
ARGC_ASSERT_GE(0); ARGC_ASSERT_GE(0);
switch (pic_length(pic, obj)) { switch (pic_length(pic, obj)) {
case 1: case 1:
irep->code[irep->clen].insn = OP_PUSHINT; scope->code[scope->clen].insn = OP_PUSHINT;
irep->code[irep->clen].u.i = 0; scope->code[scope->clen].u.i = 0;
irep->clen++; scope->clen++;
break; break;
case 2: case 2:
codegen(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); codegen(state, pic_car(pic, pic_cdr(pic, obj)), tailpos);
@ -504,8 +514,8 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
codegen(state, pic_car(pic, args), false); codegen(state, pic_car(pic, args), false);
while (pic_length(pic, args) >= 2) { while (pic_length(pic, args) >= 2) {
codegen(state, pic_car(pic, pic_cdr(pic, args)), false); codegen(state, pic_car(pic, pic_cdr(pic, args)), false);
irep->code[irep->clen].insn = OP_ADD; scope->code[scope->clen].insn = OP_ADD;
irep->clen++; scope->clen++;
args = pic_cdr(pic, args); args = pic_cdr(pic, args);
} }
break; break;
@ -519,16 +529,16 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
switch (pic_length(pic, obj)) { switch (pic_length(pic, obj)) {
case 2: case 2:
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_MINUS; scope->code[scope->clen].insn = OP_MINUS;
irep->clen++; scope->clen++;
break; break;
default: default:
args = pic_cdr(pic, obj); args = pic_cdr(pic, obj);
codegen(state, pic_car(pic, args), false); codegen(state, pic_car(pic, args), false);
while (pic_length(pic, args) >= 2) { while (pic_length(pic, args) >= 2) {
codegen(state, pic_car(pic, pic_cdr(pic, args)), false); codegen(state, pic_car(pic, pic_cdr(pic, args)), false);
irep->code[irep->clen].insn = OP_SUB; scope->code[scope->clen].insn = OP_SUB;
irep->clen++; scope->clen++;
args = pic_cdr(pic, args); args = pic_cdr(pic, args);
} }
break; break;
@ -541,9 +551,9 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
ARGC_ASSERT_GE(0); ARGC_ASSERT_GE(0);
switch (pic_length(pic, obj)) { switch (pic_length(pic, obj)) {
case 1: case 1:
irep->code[irep->clen].insn = OP_PUSHINT; scope->code[scope->clen].insn = OP_PUSHINT;
irep->code[irep->clen].u.i = 1; scope->code[scope->clen].u.i = 1;
irep->clen++; scope->clen++;
break; break;
case 2: case 2:
codegen(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); codegen(state, pic_car(pic, pic_cdr(pic, obj)), tailpos);
@ -553,8 +563,8 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
codegen(state, pic_car(pic, args), false); codegen(state, pic_car(pic, args), false);
while (pic_length(pic, args) >= 2) { while (pic_length(pic, args) >= 2) {
codegen(state, pic_car(pic, pic_cdr(pic, args)), false); codegen(state, pic_car(pic, pic_cdr(pic, args)), false);
irep->code[irep->clen].insn = OP_MUL; scope->code[scope->clen].insn = OP_MUL;
irep->clen++; scope->clen++;
args = pic_cdr(pic, args); args = pic_cdr(pic, args);
} }
break; break;
@ -567,20 +577,20 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
ARGC_ASSERT_GE(1); ARGC_ASSERT_GE(1);
switch (pic_length(pic, obj)) { switch (pic_length(pic, obj)) {
case 2: case 2:
irep->code[irep->clen].insn = OP_PUSHINT; scope->code[scope->clen].insn = OP_PUSHINT;
irep->code[irep->clen].u.i = 1; scope->code[scope->clen].u.i = 1;
irep->clen++; scope->clen++;
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_DIV; scope->code[scope->clen].insn = OP_DIV;
irep->clen++; scope->clen++;
break; break;
default: default:
args = pic_cdr(pic, obj); args = pic_cdr(pic, obj);
codegen(state, pic_car(pic, args), false); codegen(state, pic_car(pic, args), false);
while (pic_length(pic, args) >= 2) { while (pic_length(pic, args) >= 2) {
codegen(state, pic_car(pic, pic_cdr(pic, args)), false); codegen(state, pic_car(pic, pic_cdr(pic, args)), false);
irep->code[irep->clen].insn = OP_DIV; scope->code[scope->clen].insn = OP_DIV;
irep->clen++; scope->clen++;
args = pic_cdr(pic, args); args = pic_cdr(pic, args);
} }
break; break;
@ -591,40 +601,40 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
irep->code[irep->clen].insn = OP_EQ; scope->code[scope->clen].insn = OP_EQ;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rLT) { else if (sym == pic->rLT) {
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
irep->code[irep->clen].insn = OP_LT; scope->code[scope->clen].insn = OP_LT;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rLE) { else if (sym == pic->rLE) {
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
irep->code[irep->clen].insn = OP_LE; scope->code[scope->clen].insn = OP_LE;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rGT) { else if (sym == pic->rGT) {
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_LT; scope->code[scope->clen].insn = OP_LT;
irep->clen++; scope->clen++;
break; break;
} }
else if (sym == pic->rGE) { else if (sym == pic->rGE) {
ARGC_ASSERT(2); ARGC_ASSERT(2);
codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false); codegen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), false);
codegen(state, pic_car(pic, pic_cdr(pic, obj)), false); codegen(state, pic_car(pic, pic_cdr(pic, obj)), false);
irep->code[irep->clen].insn = OP_LE; scope->code[scope->clen].insn = OP_LE;
irep->clen++; scope->clen++;
break; break;
} }
} }
@ -634,35 +644,35 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
} }
case PIC_TT_BOOL: { case PIC_TT_BOOL: {
if (pic_true_p(obj)) { if (pic_true_p(obj)) {
irep->code[irep->clen].insn = OP_PUSHTRUE; scope->code[scope->clen].insn = OP_PUSHTRUE;
} }
else { else {
irep->code[irep->clen].insn = OP_PUSHFALSE; scope->code[scope->clen].insn = OP_PUSHFALSE;
} }
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_FLOAT: { case PIC_TT_FLOAT: {
irep->code[irep->clen].insn = OP_PUSHFLOAT; scope->code[scope->clen].insn = OP_PUSHFLOAT;
irep->code[irep->clen].u.f = pic_float(obj); scope->code[scope->clen].u.f = pic_float(obj);
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_INT: { case PIC_TT_INT: {
irep->code[irep->clen].insn = OP_PUSHINT; scope->code[scope->clen].insn = OP_PUSHINT;
irep->code[irep->clen].u.i = pic_int(obj); scope->code[scope->clen].u.i = pic_int(obj);
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_NIL: { case PIC_TT_NIL: {
irep->code[irep->clen].insn = OP_PUSHNIL; scope->code[scope->clen].insn = OP_PUSHNIL;
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_CHAR: { case PIC_TT_CHAR: {
irep->code[irep->clen].insn = OP_PUSHCHAR; scope->code[scope->clen].insn = OP_PUSHCHAR;
irep->code[irep->clen].u.c = pic_char(obj); scope->code[scope->clen].u.c = pic_char(obj);
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_STRING: case PIC_TT_STRING:
@ -674,9 +684,9 @@ codegen(codegen_state *state, pic_value obj, bool tailpos)
pic_abort(pic, "constant pool overflow"); pic_abort(pic, "constant pool overflow");
} }
pic->pool[pidx] = obj; pic->pool[pidx] = obj;
irep->code[irep->clen].insn = OP_PUSHCONST; scope->code[scope->clen].insn = OP_PUSHCONST;
irep->code[irep->clen].u.i = pidx; scope->code[scope->clen].u.i = pidx;
irep->clen++; scope->clen++;
break; break;
} }
case PIC_TT_CONT: case PIC_TT_CONT:
@ -700,7 +710,7 @@ static void
codegen_call(codegen_state *state, pic_value obj, bool tailpos) codegen_call(codegen_state *state, pic_value obj, bool tailpos)
{ {
pic_state *pic = state->pic; pic_state *pic = state->pic;
struct pic_irep *irep = state->irep; codegen_scope *scope = state->scope;
pic_value seq; pic_value seq;
int i = 0; int i = 0;
@ -711,9 +721,9 @@ codegen_call(codegen_state *state, pic_value obj, bool tailpos)
codegen(state, v, false); codegen(state, v, false);
++i; ++i;
} }
irep->code[irep->clen].insn = tailpos ? OP_TAILCALL : OP_CALL; scope->code[scope->clen].insn = tailpos ? OP_TAILCALL : OP_CALL;
irep->code[irep->clen].u.i = i; scope->code[scope->clen].u.i = i;
irep->clen++; scope->clen++;
} }
static bool static bool
@ -802,8 +812,7 @@ static struct pic_irep *
codegen_lambda(codegen_state *state, pic_value obj) codegen_lambda(codegen_state *state, pic_value obj)
{ {
pic_state *pic = state->pic; pic_state *pic = state->pic;
codegen_scope *prev_scope; struct pic_irep *irep;
struct pic_irep *prev_irep, *irep;
pic_value args, body, v; pic_value args, body, v;
int i, c, k; int i, c, k;
@ -817,13 +826,7 @@ codegen_lambda(codegen_state *state, pic_value obj)
} }
/* inner environment */ /* inner environment */
prev_irep = state->irep;
prev_scope = state->scope;
state->scope = new_local_scope(pic, args, state->scope); state->scope = new_local_scope(pic, args, state->scope);
state->irep = irep = new_irep(pic);
irep->argc = state->scope->argc;
irep->varg = state->scope->varg;
{ {
/* body */ /* body */
body = pic_cdr(pic, pic_cdr(pic, obj)); body = pic_cdr(pic, pic_cdr(pic, obj));
@ -833,14 +836,21 @@ codegen_lambda(codegen_state *state, pic_value obj)
} }
else { else {
codegen(state, pic_car(pic, v), false); codegen(state, pic_car(pic, v), false);
irep->code[irep->clen].insn = OP_POP; state->scope->code[state->scope->clen].insn = OP_POP;
irep->clen++; state->scope->clen++;
} }
} }
irep->code[irep->clen].insn = OP_RET; state->scope->code[state->scope->clen].insn = OP_RET;
irep->clen++; state->scope->clen++;
/* create irep */
irep = new_irep(pic);
irep->varg = state->scope->varg;
irep->argc = state->scope->argc;
irep->localc = state->scope->localc; irep->localc = state->scope->localc;
irep->code = state->scope->code;
irep->clen = state->scope->clen;
irep->ccapa = state->scope->ccapa;
/* fixup local references */ /* fixup local references */
for (i = 0; i < irep->clen; ++i) { for (i = 0; i < irep->clen; ++i) {
@ -890,8 +900,7 @@ codegen_lambda(codegen_state *state, pic_value obj)
} }
destroy_scope(pic, state->scope); destroy_scope(pic, state->scope);
state->irep = prev_irep; state->scope = state->scope->up;
state->scope = prev_scope;
#if VM_DEBUG #if VM_DEBUG
printf("* generated lambda:\n"); printf("* generated lambda:\n");
@ -907,6 +916,7 @@ pic_codegen(pic_state *pic, pic_value obj)
{ {
struct pic_proc *proc; struct pic_proc *proc;
codegen_state *state; codegen_state *state;
struct pic_irep *irep;
jmp_buf jmp, *prev_jmp = pic->jmp; jmp_buf jmp, *prev_jmp = pic->jmp;
int ai = pic_gc_arena_preserve(pic); int ai = pic_gc_arena_preserve(pic);
@ -921,16 +931,20 @@ pic_codegen(pic_state *pic, pic_value obj)
goto exit; goto exit;
} }
state->irep = new_irep(pic);
state->irep->argc = 1;
state->irep->localc = 0;
codegen(state, pic_macroexpand(pic, obj), false); codegen(state, pic_macroexpand(pic, obj), false);
state->irep->code[state->irep->clen].insn = OP_RET; state->scope->code[state->scope->clen].insn = OP_RET;
state->irep->clen++; state->scope->clen++;
state->irep->cv_num = 0;
state->irep->cv_tbl = NULL;
proc = pic_proc_new_irep(pic, state->irep, NULL); irep = new_irep(pic);
irep->varg = false;
irep->argc = 1;
irep->localc = 0;
irep->code = state->scope->code;
irep->clen = state->scope->clen;
irep->cv_num = 0;
irep->cv_tbl = NULL;
proc = pic_proc_new_irep(pic, irep, NULL);
destroy_codegen_state(pic, state); destroy_codegen_state(pic, state);