test implementation for closed variable reference
This commit is contained in:
parent
ec0f0d3572
commit
f854e225c8
|
@ -12,6 +12,7 @@ typedef struct codegen_scope {
|
||||||
/* local variables are 1-indexed */
|
/* local variables are 1-indexed */
|
||||||
struct xhash *local_tbl;
|
struct xhash *local_tbl;
|
||||||
size_t argc;
|
size_t argc;
|
||||||
|
int *cv_tbl;
|
||||||
} codegen_scope;
|
} codegen_scope;
|
||||||
|
|
||||||
static codegen_scope *
|
static codegen_scope *
|
||||||
|
@ -23,6 +24,7 @@ new_global_scope(pic_state *pic)
|
||||||
scope->up = NULL;
|
scope->up = NULL;
|
||||||
scope->local_tbl = pic->global_tbl;
|
scope->local_tbl = pic->global_tbl;
|
||||||
scope->argc = -1;
|
scope->argc = -1;
|
||||||
|
scope->cv_tbl = NULL;
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ new_local_scope(pic_state *pic, pic_value args, codegen_scope *scope)
|
||||||
xh_put(x, pic_symbol_ptr(sym)->name, i++);
|
xh_put(x, pic_symbol_ptr(sym)->name, i++);
|
||||||
}
|
}
|
||||||
new_scope->argc = i;
|
new_scope->argc = i;
|
||||||
|
new_scope->cv_tbl = (int *)pic_calloc(pic, i, sizeof(int));
|
||||||
|
|
||||||
return new_scope;
|
return new_scope;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +58,7 @@ destroy_scope(pic_state *pic, codegen_scope *scope)
|
||||||
{
|
{
|
||||||
if (scope->up) {
|
if (scope->up) {
|
||||||
xh_destory(scope->local_tbl);
|
xh_destory(scope->local_tbl);
|
||||||
|
pic_free(pic, scope->cv_tbl);
|
||||||
}
|
}
|
||||||
pic_free(pic, scope);
|
pic_free(pic, scope);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +103,7 @@ destroy_codegen_state(pic_state *pic, codegen_state *state)
|
||||||
pic_free(pic, state);
|
pic_free(pic, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static codegen_scope *
|
||||||
scope_lookup(codegen_state *state, const char *key, int *depth, int *idx)
|
scope_lookup(codegen_state *state, const char *key, int *depth, int *idx)
|
||||||
{
|
{
|
||||||
codegen_scope *scope = state->scope;
|
codegen_scope *scope = state->scope;
|
||||||
|
@ -117,14 +121,14 @@ scope_lookup(codegen_state *state, const char *key, int *depth, int *idx)
|
||||||
*depth = d;
|
*depth = d;
|
||||||
}
|
}
|
||||||
*idx = e->val;
|
*idx = e->val;
|
||||||
return true;
|
return scope;
|
||||||
}
|
}
|
||||||
if (scope->up) {
|
if (scope->up) {
|
||||||
scope = scope->up;
|
scope = scope->up;
|
||||||
++d;
|
++d;
|
||||||
goto enter;
|
goto enter;
|
||||||
}
|
}
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -153,13 +157,13 @@ codegen(codegen_state *state, pic_value obj)
|
||||||
|
|
||||||
switch (pic_type(obj)) {
|
switch (pic_type(obj)) {
|
||||||
case PIC_TT_SYMBOL: {
|
case PIC_TT_SYMBOL: {
|
||||||
bool b;
|
codegen_scope *s;
|
||||||
int depth, idx;
|
int depth, idx;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
name = pic_symbol_ptr(obj)->name;
|
name = pic_symbol_ptr(obj)->name;
|
||||||
b = scope_lookup(state, name, &depth, &idx);
|
s = scope_lookup(state, name, &depth, &idx);
|
||||||
if (! b) {
|
if (! s) {
|
||||||
pic_error(pic, "unbound variable");
|
pic_error(pic, "unbound variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +178,11 @@ codegen(codegen_state *state, pic_value obj)
|
||||||
irep->clen++;
|
irep->clen++;
|
||||||
}
|
}
|
||||||
else { /* nonlocal */
|
else { /* nonlocal */
|
||||||
pic_error(pic, "reference to closed variable not supported");
|
/* dirty flag */
|
||||||
|
s->cv_tbl[idx] = 1;
|
||||||
|
/* dummy code */
|
||||||
|
irep->code[irep->clen].insn = OP_PUSHNIL;
|
||||||
|
irep->clen++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -371,6 +379,7 @@ codegen_lambda(codegen_state *state, pic_value obj)
|
||||||
codegen_scope *prev_scope;
|
codegen_scope *prev_scope;
|
||||||
struct pic_irep *prev_irep, *irep;
|
struct pic_irep *prev_irep, *irep;
|
||||||
pic_value body, v;
|
pic_value body, v;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* inner environment */
|
/* inner environment */
|
||||||
prev_irep = state->irep;
|
prev_irep = state->irep;
|
||||||
|
@ -390,6 +399,13 @@ codegen_lambda(codegen_state *state, pic_value obj)
|
||||||
irep->clen--;
|
irep->clen--;
|
||||||
irep->code[irep->clen].insn = OP_RET;
|
irep->code[irep->clen].insn = OP_RET;
|
||||||
irep->clen++;
|
irep->clen++;
|
||||||
|
|
||||||
|
printf("** dirty **\n");
|
||||||
|
for (i = 1; i < state->scope->argc; ++i) {
|
||||||
|
if (state->scope->cv_tbl[i])
|
||||||
|
printf("%d ", i);
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
}
|
}
|
||||||
destroy_scope(pic, state->scope);
|
destroy_scope(pic, state->scope);
|
||||||
|
|
||||||
|
@ -456,7 +472,8 @@ print_irep(pic_state *pic, struct pic_irep *irep)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("## irep %p [clen = %zd, ccapa = %zd]\n", irep, irep->clen, irep->ccapa);
|
printf("## irep %p\n", irep);
|
||||||
|
printf("[clen = %zd, ccapa = %zd, argc = %d]\n", irep->clen, irep->ccapa, irep->argc);
|
||||||
for (i = 0; i < irep->clen; ++i) {
|
for (i = 0; i < irep->clen; ++i) {
|
||||||
switch (irep->code[i].insn) {
|
switch (irep->code[i].insn) {
|
||||||
case OP_POP:
|
case OP_POP:
|
||||||
|
|
Loading…
Reference in New Issue