From b9fce69c6107f61cbd320b454b5128af8dc17c94 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 13 Nov 2013 18:08:22 +0900 Subject: [PATCH] support internal definitions --- src/codegen.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- src/vm.c | 9 +++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 5468d713..008601ad 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -166,6 +166,22 @@ scope_global_define(pic_state *pic, const char *name) return e->val; } +static int +scope_local_define(pic_state *pic, const char *name, codegen_scope *scope) +{ + struct xh_entry *e; + + e = xh_put(scope->local_tbl, name, scope->argc + scope->localc++); + scope->dirty_flags = (int *)pic_realloc(pic, scope->dirty_flags, (e->val) * sizeof(int)); + return e->val; +} + +static bool +scope_is_global(codegen_scope *scope) +{ + return scope->up == NULL; +} + static void codegen_call(codegen_state *, pic_value, bool); static struct pic_irep *codegen_lambda(codegen_state *, pic_value); @@ -220,6 +236,7 @@ codegen(codegen_state *state, pic_value obj, bool tailpos) if (sym == pic->sDEFINE) { int idx; pic_value var, val; + codegen_scope *s; if (pic_length(pic, obj) < 2) { pic_error(pic, "syntax error"); @@ -242,15 +259,27 @@ codegen(codegen_state *state, pic_value obj, bool tailpos) pic_error(pic, "syntax error"); } - idx = scope_global_define(pic, pic_symbol_name(pic, pic_sym(var))); - - codegen(state, val, false); - irep->code[irep->clen].insn = OP_GSET; - irep->code[irep->clen].u.i = idx; - irep->clen++; - irep->code[irep->clen].insn = OP_PUSHFALSE; - irep->clen++; - break; + s = state->scope; + if (scope_is_global(s)) { + idx = scope_global_define(pic, pic_symbol_name(pic, pic_sym(var))); + codegen(state, val, false); + irep->code[irep->clen].insn = OP_GSET; + irep->code[irep->clen].u.i = idx; + irep->clen++; + irep->code[irep->clen].insn = OP_PUSHFALSE; + irep->clen++; + break; + } + else { + idx = scope_local_define(pic, pic_symbol_name(pic, pic_sym(var)), s); + codegen(state, val, false); + irep->code[irep->clen].insn = OP_LSET; + irep->code[irep->clen].u.i = idx; + irep->clen++; + irep->code[irep->clen].insn = OP_PUSHFALSE; + irep->clen++; + break; + } } else if (sym == pic->sLAMBDA) { int k = pic->ilen++; @@ -738,7 +767,6 @@ codegen_lambda(codegen_state *state, pic_value obj) state->scope = new_local_scope(pic, args, state->scope); state->irep = irep = new_irep(pic); irep->argc = state->scope->argc; - irep->localc = state->scope->localc; irep->varg = state->scope->varg; { /* body */ @@ -756,6 +784,8 @@ codegen_lambda(codegen_state *state, pic_value obj) irep->code[irep->clen].insn = OP_RET; irep->clen++; + irep->localc = state->scope->localc; + /* fixup local references */ for (i = 0; i < irep->clen; ++i) { struct pic_code c = irep->code[i]; diff --git a/src/vm.c b/src/vm.c index 9f607f9a..4ef3c429 100644 --- a/src/vm.c +++ b/src/vm.c @@ -484,6 +484,15 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv) } } + /* prepare local variable area */ + if (proc->u.irep->localc > 0) { + int l = proc->u.irep->localc; + if (proc->u.irep->varg) { + --l; + } + pic->sp += l; + } + pc = proc->u.irep->code; pic_gc_arena_restore(pic, ai); JUMP;