split codegen function

This commit is contained in:
Yuichi Nishiwaki 2015-07-02 05:07:16 +09:00
parent 43f385760d
commit 28b180ac3f
1 changed files with 263 additions and 231 deletions

View File

@ -679,6 +679,8 @@ codegen_context_destroy(pic_state *pic, codegen_context *cxt)
cxt->clen++; \ cxt->clen++; \
} while (0) \ } while (0) \
#define emit_ret(pic, cxt, tailpos) if (tailpos) emit_i(pic, cxt, OP_RET, 1)
static void static void
create_activation(pic_state *pic, codegen_context *cxt) create_activation(pic_state *pic, codegen_context *cxt)
{ {
@ -762,36 +764,8 @@ index_symbol(pic_state *pic, codegen_context *cxt, pic_sym *sym)
static void codegen(pic_state *, codegen_context *, pic_value, bool); static void codegen(pic_state *, codegen_context *, pic_value, bool);
static struct pic_irep *
codegen_lambda(pic_state *pic, codegen_context *up, pic_value obj)
{
codegen_context c, *cxt = &c;
pic_value rest_opt, body;
pic_sym *rest = NULL;
pic_vec *args, *locals, *captures;
rest_opt = pic_list_ref(pic, obj, 1);
if (pic_sym_p(rest_opt)) {
rest = pic_sym_ptr(rest_opt);
}
args = pic_vec_ptr(pic_list_ref(pic, obj, 2));
locals = pic_vec_ptr(pic_list_ref(pic, obj, 3));
captures = pic_vec_ptr(pic_list_ref(pic, obj, 4));
body = pic_list_ref(pic, obj, 5);
/* inner environment */
codegen_context_init(pic, cxt, up, rest, args, locals, captures);
{
/* body */
codegen(pic, cxt, body, true);
}
return codegen_context_destroy(pic, cxt);
}
#define emit_ret(pic, cxt, tailpos) if (tailpos) emit_i(pic, cxt, OP_RET, 1)
static void static void
codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos) codegen_ref(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{ {
pic_sym *sym; pic_sym *sym;
@ -799,7 +773,6 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
if (sym == pic->sGREF) { if (sym == pic->sGREF) {
emit_i(pic, cxt, OP_GREF, index_symbol(pic, cxt, pic_sym_ptr(pic_list_ref(pic, obj, 1)))); emit_i(pic, cxt, OP_GREF, index_symbol(pic, cxt, pic_sym_ptr(pic_list_ref(pic, obj, 1))));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
else if (sym == pic->sCREF) { else if (sym == pic->sCREF) {
pic_sym *name; pic_sym *name;
@ -809,7 +782,6 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
name = pic_sym_ptr(pic_list_ref(pic, obj, 2)); name = pic_sym_ptr(pic_list_ref(pic, obj, 2));
emit_r(pic, cxt, OP_CREF, depth, index_capture(cxt, name, depth)); emit_r(pic, cxt, OP_CREF, depth, index_capture(cxt, name, depth));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
else if (sym == pic->sLREF) { else if (sym == pic->sLREF) {
pic_sym *name; pic_sym *name;
@ -819,13 +791,16 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
if ((i = index_capture(cxt, name, 0)) != -1) { if ((i = index_capture(cxt, name, 0)) != -1) {
emit_i(pic, cxt, OP_LREF, i + (int)cxt->args->len + (int)cxt->locals->len + 1); emit_i(pic, cxt, OP_LREF, i + (int)cxt->args->len + (int)cxt->locals->len + 1);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; } else {
}
emit_i(pic, cxt, OP_LREF, index_local(cxt, name)); emit_i(pic, cxt, OP_LREF, index_local(cxt, name));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
else if (sym == pic->uSETBANG || sym == pic->uDEFINE) { }
}
static void
codegen_set(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
pic_value var, val; pic_value var, val;
pic_sym *type; pic_sym *type;
@ -838,7 +813,6 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
emit_i(pic, cxt, OP_GSET, index_symbol(pic, cxt, pic_sym_ptr(pic_list_ref(pic, var, 1)))); emit_i(pic, cxt, OP_GSET, index_symbol(pic, cxt, pic_sym_ptr(pic_list_ref(pic, var, 1))));
emit_n(pic, cxt, OP_PUSHUNDEF); emit_n(pic, cxt, OP_PUSHUNDEF);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
else if (type == pic->sCREF) { else if (type == pic->sCREF) {
pic_sym *name; pic_sym *name;
@ -849,7 +823,6 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
emit_r(pic, cxt, OP_CSET, depth, index_capture(cxt, name, depth)); emit_r(pic, cxt, OP_CSET, depth, index_capture(cxt, name, depth));
emit_n(pic, cxt, OP_PUSHUNDEF); emit_n(pic, cxt, OP_PUSHUNDEF);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
else if (type == pic->sLREF) { else if (type == pic->sLREF) {
pic_sym *name; pic_sym *name;
@ -860,26 +833,47 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
emit_i(pic, cxt, OP_LSET, i + (int)cxt->args->len + (int)cxt->locals->len + 1); emit_i(pic, cxt, OP_LSET, i + (int)cxt->args->len + (int)cxt->locals->len + 1);
emit_n(pic, cxt, OP_PUSHUNDEF); emit_n(pic, cxt, OP_PUSHUNDEF);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; } else {
}
emit_i(pic, cxt, OP_LSET, index_local(cxt, name)); emit_i(pic, cxt, OP_LSET, index_local(cxt, name));
emit_n(pic, cxt, OP_PUSHUNDEF); emit_n(pic, cxt, OP_PUSHUNDEF);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return;
} }
} }
else if (sym == pic->uLAMBDA) { }
int k;
static void
codegen_lambda(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
codegen_context c, *inner_cxt = &c;
pic_value rest_opt, body;
pic_sym *rest = NULL;
pic_vec *args, *locals, *captures;
check_irep_size(pic, cxt); check_irep_size(pic, cxt);
k = (int)cxt->ilen++;
emit_i(pic, cxt, OP_LAMBDA, k);
emit_ret(pic, cxt, tailpos);
cxt->irep[k] = codegen_lambda(pic, cxt, obj); /* extract arguments */
return; rest_opt = pic_list_ref(pic, obj, 1);
if (pic_sym_p(rest_opt)) {
rest = pic_sym_ptr(rest_opt);
} }
else if (sym == pic->uIF) { args = pic_vec_ptr(pic_list_ref(pic, obj, 2));
locals = pic_vec_ptr(pic_list_ref(pic, obj, 3));
captures = pic_vec_ptr(pic_list_ref(pic, obj, 4));
body = pic_list_ref(pic, obj, 5);
/* emit irep */
codegen_context_init(pic, inner_cxt, cxt, rest, args, locals, captures);
codegen(pic, inner_cxt, body, true);
cxt->irep[cxt->ilen] = codegen_context_destroy(pic, inner_cxt);
/* emit OP_LAMBDA */
emit_i(pic, cxt, OP_LAMBDA, cxt->ilen++);
emit_ret(pic, cxt, tailpos);
}
static void
codegen_if(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
int s, t; int s, t;
codegen(pic, cxt, pic_list_ref(pic, obj, 1), false); codegen(pic, cxt, pic_list_ref(pic, obj, 1), false);
@ -900,15 +894,19 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
/* if true branch */ /* if true branch */
codegen(pic, cxt, pic_list_ref(pic, obj, 2), tailpos); codegen(pic, cxt, pic_list_ref(pic, obj, 2), tailpos);
cxt->code[t].u.i = (int)cxt->clen - t; cxt->code[t].u.i = (int)cxt->clen - t;
return;
} }
else if (sym == pic->uBEGIN) {
static void
codegen_begin(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
codegen(pic, cxt, pic_list_ref(pic, obj, 1), false); codegen(pic, cxt, pic_list_ref(pic, obj, 1), false);
emit_n(pic, cxt, OP_POP); emit_n(pic, cxt, OP_POP);
codegen(pic, cxt, pic_list_ref(pic, obj, 2), tailpos); codegen(pic, cxt, pic_list_ref(pic, obj, 2), tailpos);
return;
} }
else if (sym == pic->uQUOTE) {
static void
codegen_quote(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
int pidx; int pidx;
obj = pic_list_ref(pic, obj, 1); obj = pic_list_ref(pic, obj, 1);
@ -916,29 +914,32 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
case PIC_TT_BOOL: case PIC_TT_BOOL:
emit_n(pic, cxt, (pic_true_p(obj) ? OP_PUSHTRUE : OP_PUSHFALSE)); emit_n(pic, cxt, (pic_true_p(obj) ? OP_PUSHTRUE : OP_PUSHFALSE));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; break;
case PIC_TT_INT: case PIC_TT_INT:
emit_i(pic, cxt, OP_PUSHINT, pic_int(obj)); emit_i(pic, cxt, OP_PUSHINT, pic_int(obj));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; break;
case PIC_TT_NIL: case PIC_TT_NIL:
emit_n(pic, cxt, OP_PUSHNIL); emit_n(pic, cxt, OP_PUSHNIL);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; break;
case PIC_TT_CHAR: case PIC_TT_CHAR:
emit_c(pic, cxt, OP_PUSHCHAR, pic_char(obj)); emit_c(pic, cxt, OP_PUSHCHAR, pic_char(obj));
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; break;
default: default:
check_pool_size(pic, cxt); check_pool_size(pic, cxt);
pidx = (int)cxt->plen++; pidx = (int)cxt->plen++;
cxt->pool[pidx] = obj; cxt->pool[pidx] = obj;
emit_i(pic, cxt, OP_PUSHCONST, pidx); emit_i(pic, cxt, OP_PUSHCONST, pidx);
emit_ret(pic, cxt, tailpos); emit_ret(pic, cxt, tailpos);
return; break;
} }
} }
else if (sym == pic->sCALL) {
static void
codegen_call(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
int len = (int)pic_length(pic, obj); int len = (int)pic_length(pic, obj);
pic_value elt, it; pic_value elt, it;
@ -947,7 +948,7 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
} }
if (pic_sym_ptr(pic_list_ref(pic, pic_list_ref(pic, obj, 1), 0)) == pic->sGREF) { if (pic_sym_ptr(pic_list_ref(pic, pic_list_ref(pic, obj, 1), 0)) == pic->sGREF) {
sym = pic_sym_ptr(pic_list_ref(pic, pic_list_ref(pic, obj, 1), 1)); pic_sym *sym;
/* /*
TODO: TODO:
@ -955,6 +956,8 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
- more than 2 arguments for add, sub, mul, ... - more than 2 arguments for add, sub, mul, ...
*/ */
sym = pic_sym_ptr(pic_list_ref(pic, pic_list_ref(pic, obj, 1), 1));
if (len == 4) { /* binary operator */ if (len == 4) { /* binary operator */
if (sym == pic->uCONS) { if (sym == pic->uCONS) {
emit_n(pic, cxt, OP_CONS); emit_n(pic, cxt, OP_CONS);
@ -1037,10 +1040,39 @@ codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
} }
emit_i(pic, cxt, (tailpos ? OP_TAILCALL : OP_CALL), len - 1); emit_i(pic, cxt, (tailpos ? OP_TAILCALL : OP_CALL), len - 1);
return;
} }
static void
codegen(pic_state *pic, codegen_context *cxt, pic_value obj, bool tailpos)
{
pic_sym *sym;
sym = pic_sym_ptr(pic_car(pic, obj));
if (sym == pic->sGREF || sym == pic->sCREF || sym == pic->sLREF) {
codegen_ref(pic, cxt, obj, tailpos);
}
else if (sym == pic->uSETBANG || sym == pic->uDEFINE) {
codegen_set(pic, cxt, obj, tailpos);
}
else if (sym == pic->uLAMBDA) {
codegen_lambda(pic, cxt, obj, tailpos);
}
else if (sym == pic->uIF) {
codegen_if(pic, cxt, obj, tailpos);
}
else if (sym == pic->uBEGIN) {
codegen_begin(pic, cxt, obj, tailpos);
}
else if (sym == pic->uQUOTE) {
codegen_quote(pic, cxt, obj, tailpos);
}
else if (sym == pic->sCALL) {
codegen_call(pic, cxt, obj, tailpos);
}
else {
pic_errorf(pic, "codegen: unknown AST type ~s", obj); pic_errorf(pic, "codegen: unknown AST type ~s", obj);
} }
}
struct pic_irep * struct pic_irep *
pic_codegen(pic_state *pic, pic_value obj) pic_codegen(pic_state *pic, pic_value obj)