introduce codegen_state structure

This commit is contained in:
Yuichi Nishiwaki 2013-10-23 17:25:39 +09:00
parent 035de0016b
commit 79ee6f6ae4
1 changed files with 105 additions and 72 deletions

View File

@ -51,7 +51,7 @@ new_local_scope(pic_state *pic, pic_value args, codegen_scope *scope)
} }
static void static void
destory_scope(pic_state *pic, codegen_scope *scope) destroy_scope(pic_state *pic, codegen_scope *scope)
{ {
if (scope->up) { if (scope->up) {
xh_destory(scope->local_tbl); xh_destory(scope->local_tbl);
@ -59,9 +59,50 @@ destory_scope(pic_state *pic, codegen_scope *scope)
pic_free(pic, scope); pic_free(pic, scope);
} }
static bool static struct pic_irep *
scope_lookup(pic_state *pic, codegen_scope *scope, const char *key, int *depth, int *idx) new_irep(pic_state *pic)
{ {
struct pic_irep *irep;
irep = (struct pic_irep *)pic_alloc(pic, sizeof(struct pic_irep));
irep->code = (struct pic_code *)pic_alloc(pic, sizeof(struct pic_code) * 1024);
irep->clen = 0;
irep->ccapa = 1024;
return irep;
}
static void print_irep(pic_state *, struct pic_irep *);
typedef struct codegen_state {
pic_state *pic;
codegen_scope *scope;
struct pic_irep *irep;
} codegen_state;
static codegen_state *
new_codegen_state(pic_state *pic)
{
codegen_state *state;
state = (codegen_state *)pic_alloc(pic, sizeof(codegen_state));
state->pic = pic;
state->scope = new_global_scope(pic);
state->irep = new_irep(pic);
return state;
}
static void
destroy_codegen_state(pic_state *pic, codegen_state *state)
{
destroy_scope(pic, state->scope);
pic_free(pic, state);
}
static bool
scope_lookup(codegen_state *state, const char *key, int *depth, int *idx)
{
codegen_scope *scope = state->scope;
struct xh_entry *e; struct xh_entry *e;
int d = 0; int d = 0;
@ -101,26 +142,14 @@ scope_global_define(pic_state *pic, const char *name)
return e->val; return e->val;
} }
static struct pic_irep * static void pic_gen_call(codegen_state *, pic_value);
new_irep(pic_state *pic) static struct pic_irep *pic_gen_lambda(codegen_state *, pic_value);
{
struct pic_irep *irep;
irep = (struct pic_irep *)pic_alloc(pic, sizeof(struct pic_irep));
irep->code = (struct pic_code *)pic_alloc(pic, sizeof(struct pic_code) * 1024);
irep->clen = 0;
irep->ccapa = 1024;
return irep;
}
static void print_irep(pic_state *, struct pic_irep *);
static void pic_gen_call(pic_state *, struct pic_irep *, pic_value, codegen_scope *);
static struct pic_irep *pic_gen_lambda(pic_state *, pic_value, codegen_scope *);
static void static void
pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *scope) pic_gen(codegen_state *state, pic_value obj)
{ {
pic_state *pic = state->pic;
struct pic_irep *irep = state->irep;
pic_value sDEFINE, sLAMBDA, sIF, sBEGIN, sQUOTE; pic_value sDEFINE, sLAMBDA, sIF, sBEGIN, sQUOTE;
pic_value sCONS, sCAR, sCDR, sNILP; pic_value sCONS, sCAR, sCDR, sNILP;
pic_value sADD, sSUB, sMUL, sDIV; pic_value sADD, sSUB, sMUL, sDIV;
@ -146,7 +175,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
const char *name; const char *name;
name = pic_symbol_ptr(obj)->name; name = pic_symbol_ptr(obj)->name;
b = scope_lookup(pic, scope, name, &depth, &idx); b = scope_lookup(state, name, &depth, &idx);
if (! b) { if (! b) {
pic_error(pic, "unbound variable"); pic_error(pic, "unbound variable");
} }
@ -177,7 +206,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
name = pic_symbol_ptr(pic_car(pic, pic_cdr(pic, obj)))->name; name = pic_symbol_ptr(pic_car(pic, pic_cdr(pic, obj)))->name;
idx = scope_global_define(pic, name); idx = scope_global_define(pic, name);
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_GSET; irep->code[irep->clen].insn = OP_GSET;
irep->code[irep->clen].u.i = idx; irep->code[irep->clen].u.i = idx;
@ -191,26 +220,26 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
irep->code[irep->clen].u.i = pic->ilen; irep->code[irep->clen].u.i = pic->ilen;
irep->clen++; irep->clen++;
pic->irep[pic->ilen++] = pic_gen_lambda(pic, obj, scope); pic->irep[pic->ilen++] = pic_gen_lambda(state, obj);
break; break;
} }
else if (pic_eq_p(pic, proc, sIF)) { else if (pic_eq_p(pic, proc, sIF)) {
int s,t; int s,t;
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
irep->code[irep->clen].insn = OP_JMPIF; irep->code[irep->clen].insn = OP_JMPIF;
s = irep->clen++; s = irep->clen++;
/* if false branch */ /* if false branch */
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, pic_cdr(pic, obj)))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, pic_cdr(pic, obj)))));
irep->code[irep->clen].insn = OP_JMP; irep->code[irep->clen].insn = OP_JMP;
t = irep->clen++; t = irep->clen++;
irep->code[s].u.i = irep->clen - s; irep->code[s].u.i = irep->clen - s;
/* if true branch */ /* if true branch */
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[t].u.i = irep->clen - t; irep->code[t].u.i = irep->clen - t;
break; break;
} }
@ -219,7 +248,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
seq = pic_cdr(pic, obj); seq = pic_cdr(pic, obj);
for (v = seq; ! pic_nil_p(v); v = pic_cdr(pic, v)) { for (v = seq; ! pic_nil_p(v); v = pic_cdr(pic, v)) {
pic_gen(pic, irep, pic_car(pic, v), scope); pic_gen(state, pic_car(pic, v));
irep->code[irep->clen].insn = OP_POP; irep->code[irep->clen].insn = OP_POP;
irep->clen++; irep->clen++;
} }
@ -236,60 +265,60 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
break; break;
} }
else if (pic_eq_p(pic, proc, sCONS)) { else if (pic_eq_p(pic, proc, sCONS)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_CONS; irep->code[irep->clen].insn = OP_CONS;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sCAR)) { else if (pic_eq_p(pic, proc, sCAR)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
irep->code[irep->clen].insn = OP_CAR; irep->code[irep->clen].insn = OP_CAR;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sCDR)) { else if (pic_eq_p(pic, proc, sCDR)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
irep->code[irep->clen].insn = OP_CDR; irep->code[irep->clen].insn = OP_CDR;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sNILP)) { else if (pic_eq_p(pic, proc, sNILP)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
irep->code[irep->clen].insn = OP_NILP; irep->code[irep->clen].insn = OP_NILP;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sADD)) { else if (pic_eq_p(pic, proc, sADD)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_ADD; irep->code[irep->clen].insn = OP_ADD;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sSUB)) { else if (pic_eq_p(pic, proc, sSUB)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_SUB; irep->code[irep->clen].insn = OP_SUB;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sMUL)) { else if (pic_eq_p(pic, proc, sMUL)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_MUL; irep->code[irep->clen].insn = OP_MUL;
irep->clen++; irep->clen++;
break; break;
} }
else if (pic_eq_p(pic, proc, sDIV)) { else if (pic_eq_p(pic, proc, sDIV)) {
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, obj)), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), scope); pic_gen(state, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))));
irep->code[irep->clen].insn = OP_DIV; irep->code[irep->clen].insn = OP_DIV;
irep->clen++; irep->clen++;
break; break;
} }
else { else {
pic_gen_call(pic, irep, obj, scope); pic_gen_call(state, obj);
break; break;
} }
} }
@ -333,8 +362,10 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *sco
} }
static void static void
pic_gen_call(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope *scope) pic_gen_call(codegen_state *state, pic_value obj)
{ {
pic_state *pic = state->pic;
struct pic_irep *irep = state->irep;
pic_value seq; pic_value seq;
int i = 0; int i = 0;
@ -342,7 +373,7 @@ pic_gen_call(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope
pic_value v; pic_value v;
v = pic_car(pic, seq); v = pic_car(pic, seq);
pic_gen(pic, irep, v, scope); pic_gen(state, v);
++i; ++i;
} }
irep->code[irep->clen].insn = OP_CALL; irep->code[irep->clen].insn = OP_CALL;
@ -351,30 +382,35 @@ pic_gen_call(pic_state *pic, struct pic_irep *irep, pic_value obj, codegen_scope
} }
static struct pic_irep * static struct pic_irep *
pic_gen_lambda(pic_state *pic, pic_value obj, codegen_scope *scope) pic_gen_lambda(codegen_state *state, pic_value obj)
{ {
codegen_scope *new_scope; pic_state *pic = state->pic;
pic_value args, body, v; codegen_scope *prev_scope;
struct pic_irep *irep; struct pic_irep *prev_irep, *irep;
pic_value body, v;
irep = new_irep(pic); /* inner environment */
prev_irep = state->irep;
prev_scope = state->scope;
/* arguments */ state->irep = irep = new_irep(pic);
args = pic_car(pic, pic_cdr(pic, obj)); state->scope = new_local_scope(pic, pic_car(pic, pic_cdr(pic, obj)), state->scope);
new_scope = new_local_scope(pic, args, scope); {
/* body */
/* body */ body = pic_cdr(pic, pic_cdr(pic, obj));
body = pic_cdr(pic, pic_cdr(pic, obj)); for (v = body; ! pic_nil_p(v); v = pic_cdr(pic, v)) {
for (v = body; ! pic_nil_p(v); v = pic_cdr(pic, v)) { pic_gen(state, pic_car(pic, v));
pic_gen(pic, irep, pic_car(pic, v), new_scope); irep->code[irep->clen].insn = OP_POP;
irep->code[irep->clen].insn = OP_POP; irep->clen++;
}
irep->clen--;
irep->code[irep->clen].insn = OP_RET;
irep->clen++; irep->clen++;
} }
irep->clen--; destroy_scope(pic, state->scope);
irep->code[irep->clen].insn = OP_RET;
irep->clen++;
destory_scope(pic, new_scope); state->irep = prev_irep;
state->scope = prev_scope;
#if VM_DEBUG #if VM_DEBUG
printf("LAMBDA_%zd:\n", pic->ilen); printf("LAMBDA_%zd:\n", pic->ilen);
@ -388,14 +424,10 @@ pic_gen_lambda(pic_state *pic, pic_value obj, codegen_scope *scope)
struct pic_proc * struct pic_proc *
pic_codegen(pic_state *pic, pic_value obj) pic_codegen(pic_state *pic, pic_value obj)
{ {
codegen_scope *global_scope;
struct pic_proc *proc; struct pic_proc *proc;
struct pic_irep *irep; codegen_state *state;
global_scope = new_global_scope(pic); state = new_codegen_state(pic);
irep = new_irep(pic);
proc = pic_proc_new(pic, irep);
if (! pic->jmp) { if (! pic->jmp) {
jmp_buf jmp; jmp_buf jmp;
@ -409,14 +441,15 @@ pic_codegen(pic_state *pic, pic_value obj)
return NULL; return NULL;
} }
} }
pic_gen(pic, irep, obj, global_scope); pic_gen(state, obj);
irep->code[irep->clen].insn = OP_STOP; state->irep->code[state->irep->clen].insn = OP_STOP;
irep->clen++; state->irep->clen++;
proc = pic_proc_new(pic, state->irep);
destory_scope(pic, global_scope); destroy_codegen_state(pic, state);
#if VM_DEBUG #if VM_DEBUG
print_irep(pic, irep); print_irep(pic, proc->u.irep);
#endif #endif
return proc; return proc;