From a9a530c9bdf957a0d9b5edc4a3057d1dca82972d Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 21 Mar 2014 12:34:45 +0900 Subject: [PATCH 1/3] memorize only list of captured symbols --- src/codegen.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 45018f0f..a5d5ed8e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -15,15 +15,9 @@ # error enable PIC_NONE_IS_FALSE #endif -enum { - LOCAL, - CAPTURED, -}; - typedef struct analyze_scope { bool varg; - xvect args, locals; /* rest args variable is counted as a local */ - xhash *captures; + xvect args, locals, captures; /* rest args variable is counted as a local */ struct analyze_scope *up; } analyze_scope; @@ -97,7 +91,6 @@ new_analyze_state(pic_state *pic) global_tbl = pic->global_tbl; for (xh_begin(global_tbl, &it); ! xh_isend(&it); xh_next(&it)) { xv_push(&state->scope->locals, &it.e->key); - xh_put_int(state->scope->captures, (long)&it.e->key, LOCAL); } return state; @@ -142,12 +135,11 @@ push_scope(analyze_state *state, pic_value formals) pic_state *pic = state->pic; analyze_scope *scope; bool varg; - xvect args, locals; - size_t i; - pic_sym *var; + xvect args, locals, captures; xv_init(&args, sizeof(pic_sym)); xv_init(&locals, sizeof(pic_sym)); + xv_init(&captures, sizeof(pic_sym)); if (analyze_args(pic, formals, &varg, &args, &locals)) { scope = (analyze_scope *)pic_alloc(pic, sizeof(analyze_scope)); @@ -155,17 +147,7 @@ push_scope(analyze_state *state, pic_value formals) scope->varg = varg; scope->args = args; scope->locals = locals; - scope->captures = xh_new_int(); - - for (i = 0; i < scope->args.size; ++i) { - var = xv_get(&scope->args, i); - xh_put_int(scope->captures, *var, LOCAL); - } - - for (i = 0; i < scope->locals.size; ++i) { - var = xv_get(&scope->locals, i); - xh_put_int(scope->captures, *var, LOCAL); - } + scope->captures = captures; state->scope = scope; @@ -186,7 +168,7 @@ pop_scope(analyze_state *state) scope = state->scope; xv_destroy(&scope->args); xv_destroy(&scope->locals); - xh_destroy(scope->captures); + xv_destroy(&scope->captures); scope = scope->up; pic_free(state->pic, state->scope); @@ -223,7 +205,7 @@ find_var(analyze_state *state, pic_sym sym) while (scope) { if (lookup_scope(scope, sym)) { if (depth > 0) { - xh_put_int(scope->captures, sym, CAPTURED); /* mark dirty */ + xv_push(&scope->captures, &sym); } return depth; } @@ -245,7 +227,6 @@ define_var(analyze_state *state, pic_sym sym) } xv_push(&scope->locals, &sym); - xh_put_int(scope->captures, sym, LOCAL); } static pic_value @@ -437,7 +418,6 @@ analyze_lambda(analyze_state *state, pic_value obj) analyze_scope *scope = state->scope; pic_sym *var; size_t i; - xh_iter it; args = pic_nil_value(); for (i = scope->args.size; i > 0; --i) { @@ -459,10 +439,9 @@ analyze_lambda(analyze_state *state, pic_value obj) } captures = pic_nil_value(); - for (xh_begin(scope->captures, &it); ! xh_isend(&it); xh_next(&it)) { - if (it.e->val == CAPTURED) { - pic_push(pic, pic_sym_value((long)it.e->key), captures); - } + for (i = scope->captures.size; i > 0; --i) { + var = xv_get(&scope->captures, i - 1); + pic_push(pic, pic_sym_value(*var), captures); } pop_scope(state); From 9a3ff987af9b7556e5053b28dbe3199bbc8d0230 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 21 Mar 2014 12:36:46 +0900 Subject: [PATCH 2/3] define pic_push/pic_pop macro in pair.h --- include/picrin/pair.h | 3 +++ src/codegen.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/picrin/pair.h b/include/picrin/pair.h index dab97571..b6673a2a 100644 --- a/include/picrin/pair.h +++ b/include/picrin/pair.h @@ -39,6 +39,9 @@ pic_value pic_make_list(pic_state *, int, pic_value); pic_nil_p(tmp) ? false : ((var = pic_car(pic, tmp)), true); \ tmp = pic_cdr(pic, tmp)) +#define pic_push(pic, item, place) (place = pic_cons(pic, item, place)) +#define pic_pop(pic, place) (place = pic_cdr(pic, place)) + int pic_length(pic_state *, pic_value); pic_value pic_reverse(pic_state *, pic_value); pic_value pic_append(pic_state *, pic_value, pic_value); diff --git a/src/codegen.c b/src/codegen.c index a5d5ed8e..63ae63e3 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -400,8 +400,6 @@ analyze_quote(analyze_state *state, pic_value obj) return obj; } -#define pic_push(pic, item, place) (place = pic_cons(pic, item, place)) - static pic_value analyze_lambda(analyze_state *state, pic_value obj) { From 189487b0263d47d1e52f4dfd9629039058a12da9 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 21 Mar 2014 12:51:57 +0900 Subject: [PATCH 3/3] [bugfix] don't push symbols doubly to captured variable list --- src/codegen.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/codegen.c b/src/codegen.c index 63ae63e3..b498fc1c 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -196,6 +196,23 @@ lookup_scope(analyze_scope *scope, pic_sym sym) return false; } +static void +capture_var(analyze_scope *scope, pic_sym sym) +{ + pic_sym *var; + size_t i; + + for (i = 0; i < scope->captures.size; ++i) { + var = xv_get(&scope->captures, i); + if (*var == sym) { + break; + } + } + if (i == scope->captures.size) { + xv_push(&scope->captures, &sym); + } +} + static int find_var(analyze_state *state, pic_sym sym) { @@ -205,7 +222,7 @@ find_var(analyze_state *state, pic_sym sym) while (scope) { if (lookup_scope(scope, sym)) { if (depth > 0) { - xv_push(&scope->captures, &sym); + capture_var(scope, sym); } return depth; }