From 0cb89202765a73a5dd7634c4b86a2fb9ff4552fb Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 19 Mar 2014 21:45:02 +0900 Subject: [PATCH 01/11] refactor analyzer --- src/codegen.c | 732 ++++++++++++++++++++++++++++---------------------- 1 file changed, 406 insertions(+), 326 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 7916e16b..1ca26003 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -255,8 +255,6 @@ new_ref(analyze_state *state, int depth, pic_sym sym) } static pic_value analyze_node(analyze_state *, pic_value, bool); -static pic_value analyze_call(analyze_state *, pic_value, bool); -static pic_value analyze_lambda(analyze_state *, pic_value); static pic_value analyze(analyze_state *state, pic_value obj, bool tailpos) @@ -284,345 +282,124 @@ analyze(analyze_state *state, pic_value obj, bool tailpos) } static pic_value -analyze_node(analyze_state *state, pic_value obj, bool tailpos) +analyze_define(analyze_state *state, pic_value obj) { pic_state *pic = state->pic; + pic_value var, val; - switch (pic_type(obj)) { - case PIC_TT_SYMBOL: { - pic_sym sym = pic_sym(obj); - int depth; + if (pic_length(pic, obj) < 2) { + pic_error(pic, "syntax error"); + } - depth = lookup_var(state, sym); - if (depth == -1) { - pic_errorf(pic, "unbound variable %s", pic_symbol_name(pic, sym)); + var = pic_list_ref(pic, obj, 1); + if (pic_pair_p(var)) { + val = pic_cons(pic, pic_symbol_value(pic->sLAMBDA), + pic_cons(pic, pic_list_tail(pic, var, 1), + pic_list_tail(pic, obj, 2))); + var = pic_list_ref(pic, var, 0); + } + else { + if (pic_length(pic, obj) != 3) { + pic_error(pic, "syntax error"); } - /* at this stage, lref/cref/gref are not distinguished */ - return new_ref(state, depth, sym); + val = pic_list_ref(pic, obj, 2); } - case PIC_TT_PAIR: { - pic_value proc; - - if (! pic_list_p(obj)) { - pic_errorf(pic, "invalid expression given: ~s", obj); - } - - proc = pic_list_ref(pic, obj, 0); - if (pic_sym_p(proc)) { - pic_sym sym = pic_sym(proc); - - if (sym == pic->sDEFINE) { - pic_value var, val; - - if (pic_length(pic, obj) < 2) { - pic_error(pic, "syntax error"); - } - - var = pic_list_ref(pic, obj, 1); - if (pic_pair_p(var)) { - val = pic_cons(pic, pic_symbol_value(pic->sLAMBDA), - pic_cons(pic, pic_list_tail(pic, var, 1), - pic_list_tail(pic, obj, 2))); - var = pic_list_ref(pic, var, 0); - } - else { - if (pic_length(pic, obj) != 3) { - pic_error(pic, "syntax error"); - } - val = pic_list_ref(pic, obj, 2); - } - if (! pic_sym_p(var)) { - pic_error(pic, "syntax error"); - } - - define_var(state, pic_sym(var)); - return pic_list3(pic, - pic_symbol_value(pic->sSETBANG), - analyze(state, var, false), - analyze(state, val, false)); - } - else if (sym == pic->sLAMBDA) { - return analyze_lambda(state, obj); - } - else if (sym == pic->sIF) { - pic_value cond, if_true, if_false; - - if_false = pic_none_value(); - switch (pic_length(pic, obj)) { - default: - pic_error(pic, "syntax error"); - break; - case 4: - if_false = pic_list_ref(pic, obj, 3); - FALLTHROUGH; - case 3: - if_true = pic_list_ref(pic, obj, 2); - } - - /* analyze in order */ - cond = analyze(state, pic_list_ref(pic, obj, 1), false); - if_true = analyze(state, if_true, tailpos); - if_false = analyze(state, if_false, tailpos); - - return pic_list4(pic, pic_symbol_value(pic->sIF), cond, if_true, if_false); - } - else if (sym == pic->sBEGIN) { - pic_value seq; - bool tail; - - switch (pic_length(pic, obj)) { - case 1: - return analyze(state, pic_none_value(), tailpos); - case 2: - return analyze(state, pic_list_ref(pic, obj, 1), tailpos); - default: - seq = pic_list1(pic, pic_symbol_value(pic->sBEGIN)); - for (obj = pic_cdr(pic, obj); ! pic_nil_p(obj); obj = pic_cdr(pic, obj)) { - if (pic_nil_p(pic_cdr(pic, obj))) { - tail = tailpos; - } else { - tail = false; - } - seq = pic_cons(pic, analyze(state, pic_car(pic, obj), tail), seq); - } - return pic_reverse(pic, seq); - } - } - else if (sym == pic->sSETBANG) { - pic_value var, val; - - if (pic_length(pic, obj) != 3) { - pic_error(pic, "syntax error"); - } - - var = pic_list_ref(pic, obj, 1); - if (! pic_sym_p(var)) { - pic_error(pic, "syntax error"); - } - - val = pic_list_ref(pic, obj, 2); - - return pic_list3(pic, - pic_symbol_value(pic->sSETBANG), - analyze(state, var, false), - analyze(state, val, false)); - } - else if (sym == pic->sQUOTE) { - if (pic_length(pic, obj) != 2) { - pic_error(pic, "syntax error"); - } - return obj; - } - -#define ARGC_ASSERT(n) do { \ - if (pic_length(pic, obj) != (n) + 1) { \ - pic_error(pic, "wrong number of arguments"); \ - } \ - } while (0) - -#define CONSTRUCT_OP1(op) \ - pic_list2(pic, \ - pic_symbol_value(op), \ - analyze(state, pic_list_ref(pic, obj, 1), false)) - -#define CONSTRUCT_OP2(op) \ - pic_list3(pic, \ - pic_symbol_value(op), \ - analyze(state, pic_list_ref(pic, obj, 1), false), \ - analyze(state, pic_list_ref(pic, obj, 2), false)) - - else if (sym == state->rCONS) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sCONS); - } - else if (sym == state->rCAR) { - ARGC_ASSERT(1); - return CONSTRUCT_OP1(pic->sCAR); - } - else if (sym == state->rCDR) { - ARGC_ASSERT(1); - return CONSTRUCT_OP1(pic->sCDR); - } - else if (sym == state->rNILP) { - ARGC_ASSERT(1); - return CONSTRUCT_OP1(pic->sNILP); - } - -#define ARGC_ASSERT_GE(n) do { \ - if (pic_length(pic, obj) < (n) + 1) { \ - pic_error(pic, "wrong number of arguments"); \ - } \ - } while (0) - -#define FOLD_ARGS(sym) do { \ - obj = analyze(state, pic_car(pic, args), false); \ - pic_for_each (arg, pic_cdr(pic, args)) { \ - obj = pic_list3(pic, pic_symbol_value(sym), obj, \ - analyze(state, arg, false)); \ - } \ - } while (0) - - else if (sym == state->rADD) { - pic_value args, arg; - - ARGC_ASSERT_GE(0); - switch (pic_length(pic, obj)) { - case 1: - return pic_int_value(0); - case 2: - return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); - default: - args = pic_cdr(pic, obj); - FOLD_ARGS(pic->sADD); - return obj; - } - } - else if (sym == state->rSUB) { - pic_value args, arg; - - ARGC_ASSERT_GE(1); - switch (pic_length(pic, obj)) { - case 2: - return pic_list2(pic, pic_symbol_value(pic->sMINUS), - analyze(state, pic_car(pic, pic_cdr(pic, obj)), false)); - default: - args = pic_cdr(pic, obj); - FOLD_ARGS(pic->sSUB); - return obj; - } - } - else if (sym == state->rMUL) { - pic_value args, arg; - - ARGC_ASSERT_GE(0); - switch (pic_length(pic, obj)) { - case 1: - return pic_int_value(1); - case 2: - return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); - default: - args = pic_cdr(pic, obj); - FOLD_ARGS(pic->sMUL); - return obj; - } - } - else if (sym == state->rDIV) { - pic_value args, arg; - - ARGC_ASSERT_GE(1); - switch (pic_length(pic, obj)) { - case 2: - args = pic_cdr(pic, obj); - obj = pic_list3(pic, proc, pic_float_value(1), pic_car(pic, args)); - return analyze(state, obj, tailpos); - default: - args = pic_cdr(pic, obj); - FOLD_ARGS(pic->sDIV); - return obj; - } - break; - } - else if (sym == state->rEQ) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sEQ); - } - else if (sym == state->rLT) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sLT); - } - else if (sym == state->rLE) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sLE); - } - else if (sym == state->rGT) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sGT); - } - else if (sym == state->rGE) { - ARGC_ASSERT(2); - return CONSTRUCT_OP2(pic->sGE); - } - else if (sym == state->rNOT) { - ARGC_ASSERT(1); - return CONSTRUCT_OP1(pic->sNOT); - } - else if (sym == state->rVALUES && tailpos) { - pic_value v, seq; - - seq = pic_list1(pic, pic_symbol_value(state->sRETURN)); - pic_for_each (v, pic_cdr(pic, obj)) { - seq = pic_cons(pic, analyze(state, v, false), seq); - } - return pic_reverse(pic, seq); - } - else if (sym == state->rCALL_WITH_VALUES) { - pic_value prod, cnsm; - pic_sym call; - - ARGC_ASSERT(2); - - if (! tailpos) { - call = state->sCALL_WITH_VALUES; - } else { - call = state->sTAILCALL_WITH_VALUES; - } - prod = analyze(state, pic_list_ref(pic, obj, 1), false); - cnsm = analyze(state, pic_list_ref(pic, obj, 2), false); - return pic_list3(pic, pic_symbol_value(call), prod, cnsm); - } - } - return analyze_call(state, obj, tailpos); + if (! pic_sym_p(var)) { + pic_error(pic, "syntax error"); } - case PIC_TT_BOOL: - case PIC_TT_FLOAT: - case PIC_TT_INT: - case PIC_TT_NIL: - case PIC_TT_CHAR: - case PIC_TT_STRING: - case PIC_TT_VECTOR: - case PIC_TT_BLOB: { - return pic_list2(pic, pic_symbol_value(pic->sQUOTE), obj); - } - case PIC_TT_CONT: - case PIC_TT_ENV: - case PIC_TT_PROC: - case PIC_TT_UNDEF: - case PIC_TT_EOF: - case PIC_TT_PORT: - case PIC_TT_ERROR: - case PIC_TT_SENV: - case PIC_TT_MACRO: - case PIC_TT_SC: - case PIC_TT_LIB: - case PIC_TT_VAR: - case PIC_TT_IREP: - pic_error(pic, "invalid expression given"); - } - pic_abort(pic, "logic flaw"); + + define_var(state, pic_sym(var)); + + var = analyze(state, var, false); + val = analyze(state, val, false); + + return pic_list3(pic, pic_symbol_value(pic->sSETBANG), var, val); } static pic_value -analyze_call(analyze_state *state, pic_value obj, bool tailpos) +analyze_if(analyze_state *state, pic_value obj, bool tailpos) { pic_state *pic = state->pic; - int ai = pic_gc_arena_preserve(pic); - pic_value seq, elt; - pic_sym call; + pic_value cond, if_true, if_false; - if (! tailpos) { - call = state->sCALL; - } else { - call = state->sTAILCALL; + if_false = pic_none_value(); + switch (pic_length(pic, obj)) { + default: + pic_error(pic, "syntax error"); + break; + case 4: + if_false = pic_list_ref(pic, obj, 3); + FALLTHROUGH; + case 3: + if_true = pic_list_ref(pic, obj, 2); } - seq = pic_list1(pic, pic_symbol_value(call)); - pic_for_each (elt, obj) { - seq = pic_cons(pic, analyze(state, elt, false), seq); - } - seq = pic_reverse(pic, seq); - pic_gc_arena_restore(pic, ai); - pic_gc_protect(pic, seq); - return seq; + /* analyze in order */ + cond = analyze(state, pic_list_ref(pic, obj, 1), false); + if_true = analyze(state, if_true, tailpos); + if_false = analyze(state, if_false, tailpos); + + return pic_list4(pic, pic_symbol_value(pic->sIF), cond, if_true, if_false); +} + +static pic_value +analyze_begin(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + pic_value seq; + bool tail; + + switch (pic_length(pic, obj)) { + case 1: + return analyze(state, pic_none_value(), tailpos); + case 2: + return analyze(state, pic_list_ref(pic, obj, 1), tailpos); + default: + seq = pic_list1(pic, pic_symbol_value(pic->sBEGIN)); + for (obj = pic_cdr(pic, obj); ! pic_nil_p(obj); obj = pic_cdr(pic, obj)) { + if (pic_nil_p(pic_cdr(pic, obj))) { + tail = tailpos; + } else { + tail = false; + } + seq = pic_cons(pic, analyze(state, pic_car(pic, obj), tail), seq); + } + return pic_reverse(pic, seq); + } +} + +static pic_value +analyze_set(analyze_state *state, pic_value obj) +{ + pic_state *pic = state->pic; + pic_value var, val; + + if (pic_length(pic, obj) != 3) { + pic_error(pic, "syntax error"); + } + + var = pic_list_ref(pic, obj, 1); + if (! pic_sym_p(var)) { + pic_error(pic, "syntax error"); + } + + val = pic_list_ref(pic, obj, 2); + + var = analyze(state, var, false); + val = analyze(state, val, false); + + return pic_list3(pic, pic_symbol_value(pic->sSETBANG), var, val); +} + +static pic_value +analyze_quote(analyze_state *state, pic_value obj) +{ + pic_state *pic = state->pic; + + if (pic_length(pic, obj) != 2) { + pic_error(pic, "syntax error"); + } + return obj; } static pic_value @@ -683,6 +460,309 @@ analyze_lambda(analyze_state *state, pic_value obj) return obj; } +#define ARGC_ASSERT_GE(n) do { \ + if (pic_length(pic, obj) < (n) + 1) { \ + pic_error(pic, "wrong number of arguments"); \ + } \ + } while (0) + +#define FOLD_ARGS(sym) do { \ + obj = analyze(state, pic_car(pic, args), false); \ + pic_for_each (arg, pic_cdr(pic, args)) { \ + obj = pic_list3(pic, pic_symbol_value(sym), obj, \ + analyze(state, arg, false)); \ + } \ + } while (0) + +static pic_value +analyze_add(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + pic_value args, arg; + + ARGC_ASSERT_GE(0); + switch (pic_length(pic, obj)) { + case 1: + return pic_int_value(0); + case 2: + return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); + default: + args = pic_cdr(pic, obj); + FOLD_ARGS(pic->sADD); + return obj; + } +} + +static pic_value +analyze_sub(analyze_state *state, pic_value obj) +{ + pic_state *pic = state->pic; + pic_value args, arg; + + ARGC_ASSERT_GE(1); + switch (pic_length(pic, obj)) { + case 2: + return pic_list2(pic, pic_symbol_value(pic->sMINUS), + analyze(state, pic_car(pic, pic_cdr(pic, obj)), false)); + default: + args = pic_cdr(pic, obj); + FOLD_ARGS(pic->sSUB); + return obj; + } +} + +static pic_value +analyze_mul(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + pic_value args, arg; + + ARGC_ASSERT_GE(0); + switch (pic_length(pic, obj)) { + case 1: + return pic_int_value(1); + case 2: + return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); + default: + args = pic_cdr(pic, obj); + FOLD_ARGS(pic->sMUL); + return obj; + } +} + +static pic_value +analyze_div(analyze_state *state, pic_value obj) +{ + pic_state *pic = state->pic; + pic_value args, arg; + + ARGC_ASSERT_GE(1); + switch (pic_length(pic, obj)) { + case 2: + args = pic_cdr(pic, obj); + obj = pic_list3(pic, pic_car(pic, obj), pic_float_value(1), pic_car(pic, args)); + return analyze(state, obj, false); + default: + args = pic_cdr(pic, obj); + FOLD_ARGS(pic->sDIV); + return obj; + } +} + +static pic_value +analyze_call(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + int ai = pic_gc_arena_preserve(pic); + pic_value seq, elt; + pic_sym call; + + if (! tailpos) { + call = state->sCALL; + } else { + call = state->sTAILCALL; + } + seq = pic_list1(pic, pic_symbol_value(call)); + pic_for_each (elt, obj) { + seq = pic_cons(pic, analyze(state, elt, false), seq); + } + seq = pic_reverse(pic, seq); + + pic_gc_arena_restore(pic, ai); + pic_gc_protect(pic, seq); + return seq; +} + +static pic_value +analyze_values(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + pic_value v, seq; + + if (! tailpos) { + return analyze_call(state, obj, false); + } + + seq = pic_list1(pic, pic_symbol_value(state->sRETURN)); + pic_for_each (v, pic_cdr(pic, obj)) { + seq = pic_cons(pic, analyze(state, v, false), seq); + } + return pic_reverse(pic, seq); +} + +static pic_value +analyze_call_with_values(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + pic_value prod, cnsm; + pic_sym call; + + if (pic_length(pic, obj) != 3) { + pic_error(pic, "wrong number of arguments"); + } + + if (! tailpos) { + call = state->sCALL_WITH_VALUES; + } else { + call = state->sTAILCALL_WITH_VALUES; + } + prod = analyze(state, pic_list_ref(pic, obj, 1), false); + cnsm = analyze(state, pic_list_ref(pic, obj, 2), false); + return pic_list3(pic, pic_symbol_value(call), prod, cnsm); +} + +#define ARGC_ASSERT(n) do { \ + if (pic_length(pic, obj) != (n) + 1) { \ + pic_error(pic, "wrong number of arguments"); \ + } \ + } while (0) + +#define CONSTRUCT_OP1(op) \ + pic_list2(pic, \ + pic_symbol_value(op), \ + analyze(state, pic_list_ref(pic, obj, 1), false)) + +#define CONSTRUCT_OP2(op) \ + pic_list3(pic, \ + pic_symbol_value(op), \ + analyze(state, pic_list_ref(pic, obj, 1), false), \ + analyze(state, pic_list_ref(pic, obj, 2), false)) + +static pic_value +analyze_node(analyze_state *state, pic_value obj, bool tailpos) +{ + pic_state *pic = state->pic; + + switch (pic_type(obj)) { + case PIC_TT_SYMBOL: { + pic_sym sym = pic_sym(obj); + int depth; + + depth = lookup_var(state, sym); + if (depth == -1) { + pic_errorf(pic, "unbound variable %s", pic_symbol_name(pic, sym)); + } + /* at this stage, lref/cref/gref are not distinguished */ + return new_ref(state, depth, sym); + } + case PIC_TT_PAIR: { + pic_value proc; + + if (! pic_list_p(obj)) { + pic_errorf(pic, "invalid expression given: ~s", obj); + } + + proc = pic_list_ref(pic, obj, 0); + if (pic_sym_p(proc)) { + pic_sym sym = pic_sym(proc); + + if (sym == pic->sDEFINE) { + return analyze_define(state, obj); + } + else if (sym == pic->sLAMBDA) { + return analyze_lambda(state, obj); + } + else if (sym == pic->sIF) { + return analyze_if(state, obj, tailpos); + } + else if (sym == pic->sBEGIN) { + return analyze_begin(state, obj, tailpos); + } + else if (sym == pic->sSETBANG) { + return analyze_set(state, obj); + } + else if (sym == pic->sQUOTE) { + return analyze_quote(state, obj); + } + else if (sym == state->rCONS) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sCONS); + } + else if (sym == state->rCAR) { + ARGC_ASSERT(1); + return CONSTRUCT_OP1(pic->sCAR); + } + else if (sym == state->rCDR) { + ARGC_ASSERT(1); + return CONSTRUCT_OP1(pic->sCDR); + } + else if (sym == state->rNILP) { + ARGC_ASSERT(1); + return CONSTRUCT_OP1(pic->sNILP); + } + else if (sym == state->rADD) { + return analyze_add(state, obj, tailpos); + } + else if (sym == state->rSUB) { + return analyze_sub(state, obj); + } + else if (sym == state->rMUL) { + return analyze_mul(state, obj, tailpos); + } + else if (sym == state->rDIV) { + return analyze_div(state, obj); + } + else if (sym == state->rEQ) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sEQ); + } + else if (sym == state->rLT) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sLT); + } + else if (sym == state->rLE) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sLE); + } + else if (sym == state->rGT) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sGT); + } + else if (sym == state->rGE) { + ARGC_ASSERT(2); + return CONSTRUCT_OP2(pic->sGE); + } + else if (sym == state->rNOT) { + ARGC_ASSERT(1); + return CONSTRUCT_OP1(pic->sNOT); + } + else if (sym == state->rVALUES) { + return analyze_values(state, obj, tailpos); + } + else if (sym == state->rCALL_WITH_VALUES) { + return analyze_call_with_values(state, obj, tailpos); + } + } + return analyze_call(state, obj, tailpos); + } + case PIC_TT_BOOL: + case PIC_TT_FLOAT: + case PIC_TT_INT: + case PIC_TT_NIL: + case PIC_TT_CHAR: + case PIC_TT_STRING: + case PIC_TT_VECTOR: + case PIC_TT_BLOB: { + return pic_list2(pic, pic_symbol_value(pic->sQUOTE), obj); + } + case PIC_TT_CONT: + case PIC_TT_ENV: + case PIC_TT_PROC: + case PIC_TT_UNDEF: + case PIC_TT_EOF: + case PIC_TT_PORT: + case PIC_TT_ERROR: + case PIC_TT_SENV: + case PIC_TT_MACRO: + case PIC_TT_SC: + case PIC_TT_LIB: + case PIC_TT_VAR: + case PIC_TT_IREP: + pic_errorf(pic, "invalid expression given: ~s", obj); + } + UNREACHABLE(); +} + pic_value pic_analyze(pic_state *pic, pic_value obj) { From 6d6420f2b99bc1a2d730fc1d09ee5f36e2298d9b Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 11:43:55 +0900 Subject: [PATCH 02/11] refactor analyze_var --- src/codegen.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 1ca26003..17ad75ce 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -281,6 +281,20 @@ analyze(analyze_state *state, pic_value obj, bool tailpos) return res; } +static pic_value +analyze_var(analyze_state *state, pic_value obj) +{ + pic_state *pic = state->pic; + pic_sym sym; + int depth; + + sym = pic_sym(obj); + if ((depth = lookup_var(state, sym)) == -1) { + pic_errorf(pic, "unbound variable %s", pic_symbol_name(pic, sym)); + } + return new_ref(state, depth, sym); /* at this stage, lref/cref/gref are not distinguished */ +} + static pic_value analyze_define(analyze_state *state, pic_value obj) { @@ -635,15 +649,7 @@ analyze_node(analyze_state *state, pic_value obj, bool tailpos) switch (pic_type(obj)) { case PIC_TT_SYMBOL: { - pic_sym sym = pic_sym(obj); - int depth; - - depth = lookup_var(state, sym); - if (depth == -1) { - pic_errorf(pic, "unbound variable %s", pic_symbol_name(pic, sym)); - } - /* at this stage, lref/cref/gref are not distinguished */ - return new_ref(state, depth, sym); + return analyze_var(state, obj); } case PIC_TT_PAIR: { pic_value proc; From 3158a41772d42f6949acfc747b6e8b41d8940d87 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 13:41:47 +0900 Subject: [PATCH 03/11] refactor analyze_args --- src/codegen.c | 54 ++++++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 17ad75ce..40e69126 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -54,23 +54,6 @@ analyze_args(pic_state *pic, pic_value args, bool *varg, int *argc, int *localc) return syms; } -static bool -valid_formal(pic_state *pic, pic_value formal) -{ - bool varg; - int argc, localc; - pic_sym *syms; - - syms = analyze_args(pic, formal, &varg, &argc, &localc); - if (syms == NULL) { - return false; - } - else { - pic_free(pic, syms); - return true; - } -} - typedef struct analyze_scope { /* rest args variable is counted by localc */ bool varg; @@ -93,7 +76,7 @@ typedef struct analyze_state { pic_sym sREF, sRETURN; } analyze_state; -static void push_scope(analyze_state *, pic_value); +static bool push_scope(analyze_state *, pic_value); static void pop_scope(analyze_state *); #define register_symbol(pic, state, slot, name) do { \ @@ -164,28 +147,34 @@ destroy_analyze_state(analyze_state *state) pic_free(state->pic, state); } -static void +static bool push_scope(analyze_state *state, pic_value args) { pic_state *pic = state->pic; analyze_scope *scope; - int i; + bool varg = false; + int argc, localc, i; + pic_sym *vars; + + if ((vars = analyze_args(pic, args, &varg, &argc, &localc)) == NULL) { + return false; + } scope = (analyze_scope *)pic_alloc(pic, sizeof(analyze_scope)); scope->up = state->scope; scope->var_tbl = xh_new_int(); - scope->varg = false; - scope->vars = analyze_args(pic, args, &scope->varg, &scope->argc, &scope->localc); - - if (scope->vars == NULL) { - pic_error(pic, "logic flaw"); - } + scope->varg = varg; + scope->argc = argc; + scope->localc = localc; + scope->vars = vars; for (i = 1; i < scope->argc + scope->localc; ++i) { xh_put_int(scope->var_tbl, scope->vars[i], 0); } state->scope = scope; + + return true; } static void @@ -427,14 +416,9 @@ analyze_lambda(analyze_state *state, pic_value obj) pic_error(pic, "syntax error"); } - /* formal arguments */ args = pic_car(pic, pic_cdr(pic, obj)); - if (! valid_formal(pic, args)) { - pic_error(pic, "syntax error"); - } - push_scope(state, args); - { + if (push_scope(state, args)) { analyze_scope *scope = state->scope; int i; @@ -465,8 +449,12 @@ analyze_lambda(analyze_state *state, pic_value obj) } } closes = pic_reverse(pic, closes); + + pop_scope(state); + } + else { + pic_errorf(pic, "invalid formal syntax: ~s", args); } - pop_scope(state); obj = pic_list6(pic, pic_symbol_value(pic->sLAMBDA), args, locals, varg, closes, body); pic_gc_arena_restore(pic, ai); From 37a87046b75edc77738c169765a99776fff55623 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 13:44:35 +0900 Subject: [PATCH 04/11] remove redundant arena management --- src/codegen.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 40e69126..b3c1678a 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -409,7 +409,6 @@ static pic_value analyze_lambda(analyze_state *state, pic_value obj) { pic_state *pic = state->pic; - int ai = pic_gc_arena_preserve(pic); pic_value args, body, locals, varg, closes; if (pic_length(pic, obj) < 2) { @@ -456,10 +455,7 @@ analyze_lambda(analyze_state *state, pic_value obj) pic_errorf(pic, "invalid formal syntax: ~s", args); } - obj = pic_list6(pic, pic_symbol_value(pic->sLAMBDA), args, locals, varg, closes, body); - pic_gc_arena_restore(pic, ai); - pic_gc_protect(pic, obj); - return obj; + return pic_list6(pic, pic_sym_value(pic->sLAMBDA), args, locals, varg, closes, body); } #define ARGC_ASSERT_GE(n) do { \ @@ -555,7 +551,6 @@ static pic_value analyze_call(analyze_state *state, pic_value obj, bool tailpos) { pic_state *pic = state->pic; - int ai = pic_gc_arena_preserve(pic); pic_value seq, elt; pic_sym call; @@ -568,11 +563,7 @@ analyze_call(analyze_state *state, pic_value obj, bool tailpos) pic_for_each (elt, obj) { seq = pic_cons(pic, analyze(state, elt, false), seq); } - seq = pic_reverse(pic, seq); - - pic_gc_arena_restore(pic, ai); - pic_gc_protect(pic, seq); - return seq; + return pic_reverse(pic, seq); } static pic_value From 1548a17b3552603f7a2864fa84c0c7285fce21b6 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 13:48:51 +0900 Subject: [PATCH 05/11] cleanup --- src/codegen.c | 97 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index b3c1678a..09b59856 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -15,45 +15,6 @@ # error enable PIC_NONE_IS_FALSE #endif -static pic_sym * -analyze_args(pic_state *pic, pic_value args, bool *varg, int *argc, int *localc) -{ - pic_sym *syms = (pic_sym *)pic_alloc(pic, sizeof(pic_sym)); - int i = 1, l = 0; - pic_value v; - - *varg = false; - for (v = args; pic_pair_p(v); v = pic_cdr(pic, v)) { - pic_value sym; - - sym = pic_car(pic, v); - if (! pic_sym_p(sym)) { - pic_free(pic, syms); - return NULL; - } - syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); - syms[i] = pic_sym(sym); - i++; - } - if (pic_nil_p(v)) { - /* pass */ - } - else if (pic_sym_p(v)) { - *varg = true; - syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); - syms[i] = pic_sym(v); - l++; - } - else { - pic_free(pic, syms); - return NULL; - } - *argc = i; - *localc = l; - - return syms; -} - typedef struct analyze_scope { /* rest args variable is counted by localc */ bool varg; @@ -147,6 +108,45 @@ destroy_analyze_state(analyze_state *state) pic_free(state->pic, state); } +static pic_sym * +analyze_args(pic_state *pic, pic_value args, bool *varg, int *argc, int *localc) +{ + pic_sym *syms = (pic_sym *)pic_alloc(pic, sizeof(pic_sym)); + int i = 1, l = 0; + pic_value v; + + *varg = false; + for (v = args; pic_pair_p(v); v = pic_cdr(pic, v)) { + pic_value sym; + + sym = pic_car(pic, v); + if (! pic_sym_p(sym)) { + pic_free(pic, syms); + return NULL; + } + syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); + syms[i] = pic_sym(sym); + i++; + } + if (pic_nil_p(v)) { + /* pass */ + } + else if (pic_sym_p(v)) { + *varg = true; + syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); + syms[i] = pic_sym(v); + l++; + } + else { + pic_free(pic, syms); + return NULL; + } + *argc = i; + *localc = l; + + return syms; +} + static bool push_scope(analyze_state *state, pic_value args) { @@ -198,19 +198,16 @@ lookup_var(analyze_state *state, pic_sym sym) xh_entry *e; int depth = 0; - enter: - - e = xh_get_int(scope->var_tbl, sym); - if (e) { - if (depth > 0) { /* mark dirty */ - xh_put_int(scope->var_tbl, sym, 1); + while (scope) { + e = xh_get_int(scope->var_tbl, sym); + if (e) { + if (depth > 0) { /* mark dirty */ + xh_put_int(scope->var_tbl, sym, 1); + } + return depth; } - return depth; - } - if (scope->up) { + depth++; scope = scope->up; - ++depth; - goto enter; } return -1; } From 0b4cb7683439c6a08538dc46fa9237c427184340 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 20:06:59 +0900 Subject: [PATCH 06/11] add xvect --- src/codegen.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/codegen.c b/src/codegen.c index 09b59856..adc75f58 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -15,6 +15,78 @@ # error enable PIC_NONE_IS_FALSE #endif +typedef struct xvect { + char *data; + size_t size, capa, width; +} xvect; + +static inline void xv_init(xvect *, size_t); +static inline void xv_destroy(xvect *); + +static inline void xv_reserve(xvect *, size_t); + +static inline void xv_get(xvect *, size_t, void *); +static inline void xv_set(xvect *, size_t, void *); + +static inline void xv_push(xvect *, void *); +static inline void xv_peek(xvect *, void *); +static inline void xv_pop(xvect *, void *); + +static inline void +xv_init(xvect *x, size_t width) +{ + x->data = NULL; + x->size = 0; + x->capa = 0; + x->width = width; +} + +static inline void +xv_destroy(xvect *x) +{ + free(x->data); +} + +static inline void +xv_reserve(xvect *x, size_t newcapa) +{ + x->data = realloc(x->data, newcapa * x->width); + x->capa = newcapa; +} + +static inline void +xv_get(xvect *x, size_t i, void *dst) +{ + memcpy(dst, x->data + i * x->width, x->width); +} + +static inline void +xv_set(xvect *x, size_t i, void *src) +{ + memcpy(x->data + i * x->width, src, x->width); +} + +static inline void +xv_push(xvect *x, void *src) +{ + if (x->capa <= x->size + 1) { + xv_reserve(x, x->size * 2 + 1); + } + xv_set(x, x->size++, src); +} + +static inline void +xv_peek(xvect *x, void *dst) +{ + xv_get(x, x->size, dst); +} + +static inline void +xv_pop(xvect *x, void *dst) +{ + xv_get(x, --x->size, dst); +} + typedef struct analyze_scope { /* rest args variable is counted by localc */ bool varg; From 0c12784da527dd81f8500eeafd415d7cf823eef7 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 21:56:49 +0900 Subject: [PATCH 07/11] use xvect --- src/codegen.c | 207 +++++++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 97 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index adc75f58..4953ef47 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -88,13 +88,9 @@ xv_pop(xvect *x, void *dst) } typedef struct analyze_scope { - /* rest args variable is counted by localc */ bool varg; - int argc, localc; - /* if variable v is captured, then xh_get(var_tbl, v) == 1 */ - xhash *var_tbl; - pic_sym *vars; - + xvect args, locals; /* rest args variable is counted as a local */ + xhash *captures; struct analyze_scope *up; } analyze_scope; @@ -167,7 +163,8 @@ new_analyze_state(pic_state *pic) global_tbl = pic->global_tbl; for (xh_begin(global_tbl, &it); ! xh_isend(&it); xh_next(&it)) { - xh_put_int(state->scope->var_tbl, (long)it.e->key, 0); + xv_push(&state->scope->locals, &it.e->key); + xh_put_int(state->scope->captures, (long)&it.e->key, 0); } return state; @@ -180,101 +177,120 @@ destroy_analyze_state(analyze_state *state) pic_free(state->pic, state); } -static pic_sym * -analyze_args(pic_state *pic, pic_value args, bool *varg, int *argc, int *localc) +static bool +analyze_args(pic_state *pic, pic_value formals, bool *varg, xvect *args, xvect *locals) { - pic_sym *syms = (pic_sym *)pic_alloc(pic, sizeof(pic_sym)); - int i = 1, l = 0; - pic_value v; - - *varg = false; - for (v = args; pic_pair_p(v); v = pic_cdr(pic, v)) { - pic_value sym; + pic_value v, sym; + for (v = formals; pic_pair_p(v); v = pic_cdr(pic, v)) { sym = pic_car(pic, v); if (! pic_sym_p(sym)) { - pic_free(pic, syms); - return NULL; + return false; } - syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); - syms[i] = pic_sym(sym); - i++; + xv_push(args, &pic_sym(sym)); } if (pic_nil_p(v)) { - /* pass */ + *varg = false; } else if (pic_sym_p(v)) { *varg = true; - syms = (pic_sym *)pic_realloc(pic, syms, sizeof(pic_sym) * (i + 1)); - syms[i] = pic_sym(v); - l++; + xv_push(locals, &pic_sym(v)); } else { - pic_free(pic, syms); - return NULL; - } - *argc = i; - *localc = l; - - return syms; -} - -static bool -push_scope(analyze_state *state, pic_value args) -{ - pic_state *pic = state->pic; - analyze_scope *scope; - bool varg = false; - int argc, localc, i; - pic_sym *vars; - - if ((vars = analyze_args(pic, args, &varg, &argc, &localc)) == NULL) { return false; } - scope = (analyze_scope *)pic_alloc(pic, sizeof(analyze_scope)); - scope->up = state->scope; - scope->var_tbl = xh_new_int(); - scope->varg = varg; - scope->argc = argc; - scope->localc = localc; - scope->vars = vars; - - for (i = 1; i < scope->argc + scope->localc; ++i) { - xh_put_int(scope->var_tbl, scope->vars[i], 0); - } - - state->scope = scope; - return true; } +static bool +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; + + xv_init(&args, sizeof(pic_sym)); + xv_init(&locals, sizeof(pic_sym)); + + if (analyze_args(pic, formals, &varg, &args, &locals)) { + scope = (analyze_scope *)pic_alloc(pic, sizeof(analyze_scope)); + scope->up = state->scope; + scope->varg = varg; + scope->args = args; + scope->locals = locals; + scope->captures = xh_new_int(); + + for (i = 0; i < scope->args.size; ++i) { + xv_get(&scope->args, i, &var); + xh_put_int(scope->captures, var, 0); + } + + for (i = 0; i < scope->locals.size; ++i) { + xv_get(&scope->locals, i, &var); + xh_put_int(scope->captures, var, 0); + } + + state->scope = scope; + + return true; + } + else { + xv_destroy(&args); + xv_destroy(&locals); + return false; + } +} + static void pop_scope(analyze_state *state) { analyze_scope *scope; scope = state->scope; - xh_destroy(scope->var_tbl); - pic_free(state->pic, scope->vars); + xv_destroy(&scope->args); + xv_destroy(&scope->locals); + xh_destroy(scope->captures); scope = scope->up; pic_free(state->pic, state->scope); state->scope = scope; } +static bool +lookup_scope(analyze_scope *scope, pic_sym sym) +{ + pic_sym arg, local; + size_t i; + + /* args */ + for (i = 0; i < scope->args.size; ++i) { + xv_get(&scope->args, i, &arg); + if (arg == sym) + return true; + } + /* locals */ + for (i = 0; i < scope->locals.size; ++i) { + xv_get(&scope->locals, i, &local); + if (local == sym) + return true; + } + return false; +} + static int -lookup_var(analyze_state *state, pic_sym sym) +find_var(analyze_state *state, pic_sym sym) { analyze_scope *scope = state->scope; - xh_entry *e; int depth = 0; while (scope) { - e = xh_get_int(scope->var_tbl, sym); - if (e) { - if (depth > 0) { /* mark dirty */ - xh_put_int(scope->var_tbl, sym, 1); + if (lookup_scope(scope, sym)) { + if (depth > 0) { + xh_put_int(scope->captures, sym, 1); /* mark dirty */ } return depth; } @@ -289,18 +305,14 @@ define_var(analyze_state *state, pic_sym sym) { pic_state *pic = state->pic; analyze_scope *scope = state->scope; - xh_entry *e; - if ((e = xh_get_int(scope->var_tbl, sym))) { + if (lookup_scope(scope, sym)) { pic_warn(pic, "redefining variable"); return; } - xh_put_int(scope->var_tbl, sym, 0); - - scope->localc++; - scope->vars = (pic_sym *)pic_realloc(pic, scope->vars, sizeof(pic_sym) * (scope->argc + scope->localc)); - scope->vars[scope->argc + scope->localc - 1] = sym; + xv_push(&scope->locals, &sym); + xh_put_int(scope->captures, sym, 0); } static pic_value @@ -347,10 +359,10 @@ analyze_var(analyze_state *state, pic_value obj) int depth; sym = pic_sym(obj); - if ((depth = lookup_var(state, sym)) == -1) { + if ((depth = find_var(state, sym)) == -1) { pic_errorf(pic, "unbound variable %s", pic_symbol_name(pic, sym)); } - return new_ref(state, depth, sym); /* at this stage, lref/cref/gref are not distinguished */ + return new_ref(state, depth, sym); } static pic_value @@ -474,49 +486,50 @@ 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) { pic_state *pic = state->pic; - pic_value args, body, locals, varg, closes; + pic_value formals, args, locals, varg, captures, body; if (pic_length(pic, obj) < 2) { pic_error(pic, "syntax error"); } - args = pic_car(pic, pic_cdr(pic, obj)); + formals = pic_car(pic, pic_cdr(pic, obj)); - if (push_scope(state, args)) { + if (push_scope(state, formals)) { analyze_scope *scope = state->scope; - int i; + pic_sym sym; + size_t i; + xh_iter it; - /* analyze body in inner environment */ - body = pic_cdr(pic, pic_cdr(pic, obj)); - body = pic_cons(pic, pic_symbol_value(pic->sBEGIN), body); - body = analyze(state, body, true); + body = analyze(state, pic_cons(pic, pic_sym_value(pic->sBEGIN), pic_list_tail(pic, obj, 2)), true); args = pic_nil_value(); - for (i = 1; i < scope->argc; ++i) { - args = pic_cons(pic, pic_symbol_value(scope->vars[i]), args); + for (i = scope->args.size; i > 0; --i) { + xv_get(&scope->args, i - 1, &sym); + pic_push(pic, pic_sym_value(sym), args); } - args = pic_reverse(pic, args); locals = pic_nil_value(); - for (i = 0; i < scope->localc; ++i) { - locals = pic_cons(pic, pic_symbol_value(scope->vars[scope->argc + i]), locals); + for (i = scope->locals.size; i > 0; --i) { + xv_get(&scope->locals, i - 1, &sym); + pic_push(pic, pic_sym_value(sym), locals); } - locals = pic_reverse(pic, locals); - varg = scope->varg ? pic_true_value() : pic_false_value(); + varg = scope->varg + ? pic_true_value() + : pic_false_value(); - closes = pic_nil_value(); - for (i = 1; i < scope->argc + scope->localc; ++i) { - pic_sym var = scope->vars[i]; - if (xh_get_int(scope->var_tbl, var)->val == 1) { - closes = pic_cons(pic, pic_symbol_value(var), closes); + captures = pic_nil_value(); + for (xh_begin(scope->captures, &it); ! xh_isend(&it); xh_next(&it)) { + if (it.e->val == 1) { + pic_push(pic, pic_sym_value((long)it.e->key), captures); } } - closes = pic_reverse(pic, closes); pop_scope(state); } @@ -524,7 +537,7 @@ analyze_lambda(analyze_state *state, pic_value obj) pic_errorf(pic, "invalid formal syntax: ~s", args); } - return pic_list6(pic, pic_sym_value(pic->sLAMBDA), args, locals, varg, closes, body); + return pic_list6(pic, pic_sym_value(pic->sLAMBDA), args, locals, varg, captures, body); } #define ARGC_ASSERT_GE(n) do { \ From 53cd2942d1aae284aee3ee83bced02f27a7c4412 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 22:12:20 +0900 Subject: [PATCH 08/11] change xvect API --- src/codegen.c | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 4953ef47..8632a028 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -25,12 +25,12 @@ static inline void xv_destroy(xvect *); static inline void xv_reserve(xvect *, size_t); -static inline void xv_get(xvect *, size_t, void *); +static inline void *xv_get(xvect *, size_t); static inline void xv_set(xvect *, size_t, void *); static inline void xv_push(xvect *, void *); -static inline void xv_peek(xvect *, void *); -static inline void xv_pop(xvect *, void *); +static inline void *xv_peek(xvect *); +static inline void *xv_pop(xvect *); static inline void xv_init(xvect *x, size_t width) @@ -54,10 +54,10 @@ xv_reserve(xvect *x, size_t newcapa) x->capa = newcapa; } -static inline void -xv_get(xvect *x, size_t i, void *dst) +static inline void * +xv_get(xvect *x, size_t i) { - memcpy(dst, x->data + i * x->width, x->width); + return x->data + i * x->width; } static inline void @@ -75,16 +75,16 @@ xv_push(xvect *x, void *src) xv_set(x, x->size++, src); } -static inline void -xv_peek(xvect *x, void *dst) +static inline void * +xv_peek(xvect *x) { - xv_get(x, x->size, dst); + return xv_get(x, x->size); } -static inline void -xv_pop(xvect *x, void *dst) +static inline void * +xv_pop(xvect *x) { - xv_get(x, --x->size, dst); + return xv_get(x, --x->size); } typedef struct analyze_scope { @@ -211,7 +211,7 @@ push_scope(analyze_state *state, pic_value formals) bool varg; xvect args, locals; size_t i; - pic_sym var; + pic_sym *var; xv_init(&args, sizeof(pic_sym)); xv_init(&locals, sizeof(pic_sym)); @@ -225,13 +225,13 @@ push_scope(analyze_state *state, pic_value formals) scope->captures = xh_new_int(); for (i = 0; i < scope->args.size; ++i) { - xv_get(&scope->args, i, &var); - xh_put_int(scope->captures, var, 0); + var = xv_get(&scope->args, i); + xh_put_int(scope->captures, *var, 0); } for (i = 0; i < scope->locals.size; ++i) { - xv_get(&scope->locals, i, &var); - xh_put_int(scope->captures, var, 0); + var = xv_get(&scope->locals, i); + xh_put_int(scope->captures, *var, 0); } state->scope = scope; @@ -263,19 +263,19 @@ pop_scope(analyze_state *state) static bool lookup_scope(analyze_scope *scope, pic_sym sym) { - pic_sym arg, local; + pic_sym *arg, *local; size_t i; /* args */ for (i = 0; i < scope->args.size; ++i) { - xv_get(&scope->args, i, &arg); - if (arg == sym) + arg = xv_get(&scope->args, i); + if (*arg == sym) return true; } /* locals */ for (i = 0; i < scope->locals.size; ++i) { - xv_get(&scope->locals, i, &local); - if (local == sym) + local = xv_get(&scope->locals, i); + if (*local == sym) return true; } return false; @@ -502,7 +502,7 @@ analyze_lambda(analyze_state *state, pic_value obj) if (push_scope(state, formals)) { analyze_scope *scope = state->scope; - pic_sym sym; + pic_sym *var; size_t i; xh_iter it; @@ -510,14 +510,14 @@ analyze_lambda(analyze_state *state, pic_value obj) args = pic_nil_value(); for (i = scope->args.size; i > 0; --i) { - xv_get(&scope->args, i - 1, &sym); - pic_push(pic, pic_sym_value(sym), args); + var = xv_get(&scope->args, i - 1); + pic_push(pic, pic_sym_value(*var), args); } locals = pic_nil_value(); for (i = scope->locals.size; i > 0; --i) { - xv_get(&scope->locals, i - 1, &sym); - pic_push(pic, pic_sym_value(sym), locals); + var = xv_get(&scope->locals, i - 1); + pic_push(pic, pic_sym_value(*var), locals); } varg = scope->varg From cfde253f260961772a2ebd73d81d18d250b573e9 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 20 Mar 2014 23:09:45 +0900 Subject: [PATCH 09/11] split xvect module --- .gitmodules | 3 ++ extlib/xvect | 1 + include/picrin.h | 1 + src/codegen.c | 72 ------------------------------------------------ 4 files changed, 5 insertions(+), 72 deletions(-) create mode 160000 extlib/xvect diff --git a/.gitmodules b/.gitmodules index 578e58a1..e676f24f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "extlib/xrope"] path = extlib/xrope url = git://github.com/wasabiz/xrope.git +[submodule "extlib/xvect"] + path = extlib/xvect + url = git://github.com/wasabiz/xvect.git diff --git a/extlib/xvect b/extlib/xvect new file mode 160000 index 00000000..973b9f3d --- /dev/null +++ b/extlib/xvect @@ -0,0 +1 @@ +Subproject commit 973b9f3d89ff4669d08f1bc28e205bd9834bef10 diff --git a/include/picrin.h b/include/picrin.h index 8ae0be90..e2fa4212 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -35,6 +35,7 @@ extern "C" { #include #include +#include "xvect/xvect.h" #include "xhash/xhash.h" #include "xfile/xfile.h" #include "xrope/xrope.h" diff --git a/src/codegen.c b/src/codegen.c index 8632a028..f6a877fc 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -15,78 +15,6 @@ # error enable PIC_NONE_IS_FALSE #endif -typedef struct xvect { - char *data; - size_t size, capa, width; -} xvect; - -static inline void xv_init(xvect *, size_t); -static inline void xv_destroy(xvect *); - -static inline void xv_reserve(xvect *, size_t); - -static inline void *xv_get(xvect *, size_t); -static inline void xv_set(xvect *, size_t, void *); - -static inline void xv_push(xvect *, void *); -static inline void *xv_peek(xvect *); -static inline void *xv_pop(xvect *); - -static inline void -xv_init(xvect *x, size_t width) -{ - x->data = NULL; - x->size = 0; - x->capa = 0; - x->width = width; -} - -static inline void -xv_destroy(xvect *x) -{ - free(x->data); -} - -static inline void -xv_reserve(xvect *x, size_t newcapa) -{ - x->data = realloc(x->data, newcapa * x->width); - x->capa = newcapa; -} - -static inline void * -xv_get(xvect *x, size_t i) -{ - return x->data + i * x->width; -} - -static inline void -xv_set(xvect *x, size_t i, void *src) -{ - memcpy(x->data + i * x->width, src, x->width); -} - -static inline void -xv_push(xvect *x, void *src) -{ - if (x->capa <= x->size + 1) { - xv_reserve(x, x->size * 2 + 1); - } - xv_set(x, x->size++, src); -} - -static inline void * -xv_peek(xvect *x) -{ - return xv_get(x, x->size); -} - -static inline void * -xv_pop(xvect *x) -{ - return xv_get(x, --x->size); -} - typedef struct analyze_scope { bool varg; xvect args, locals; /* rest args variable is counted as a local */ From b6b47943bb7bb3b1e3479de210bcfc0aee57f192 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 21 Mar 2014 08:17:52 +0900 Subject: [PATCH 10/11] use enum value for variable marking --- src/codegen.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index f6a877fc..6e396185 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -15,6 +15,11 @@ # 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 */ @@ -92,7 +97,7 @@ 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, 0); + xh_put_int(state->scope->captures, (long)&it.e->key, LOCAL); } return state; @@ -154,12 +159,12 @@ push_scope(analyze_state *state, pic_value formals) for (i = 0; i < scope->args.size; ++i) { var = xv_get(&scope->args, i); - xh_put_int(scope->captures, *var, 0); + 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, 0); + xh_put_int(scope->captures, *var, LOCAL); } state->scope = scope; @@ -218,7 +223,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, 1); /* mark dirty */ + xh_put_int(scope->captures, sym, CAPTURED); /* mark dirty */ } return depth; } @@ -240,7 +245,7 @@ define_var(analyze_state *state, pic_sym sym) } xv_push(&scope->locals, &sym); - xh_put_int(scope->captures, sym, 0); + xh_put_int(scope->captures, sym, LOCAL); } static pic_value @@ -454,7 +459,7 @@ 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 == 1) { + if (it.e->val == CAPTURED) { pic_push(pic, pic_sym_value((long)it.e->key), captures); } } From 91065a7c25e6363e68898dde59c3c7b66f4514ec Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 21 Mar 2014 08:20:33 +0900 Subject: [PATCH 11/11] add commentary to lambda analyzer to avoid regression --- src/codegen.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 6e396185..45018f0f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -439,24 +439,25 @@ analyze_lambda(analyze_state *state, pic_value obj) size_t i; xh_iter it; - body = analyze(state, pic_cons(pic, pic_sym_value(pic->sBEGIN), pic_list_tail(pic, obj, 2)), true); - args = pic_nil_value(); for (i = scope->args.size; i > 0; --i) { var = xv_get(&scope->args, i - 1); pic_push(pic, pic_sym_value(*var), args); } + varg = scope->varg + ? pic_true_value() + : pic_false_value(); + + /* To know what kind of local variables are defined, analyze body at first. */ + body = analyze(state, pic_cons(pic, pic_sym_value(pic->sBEGIN), pic_list_tail(pic, obj, 2)), true); + locals = pic_nil_value(); for (i = scope->locals.size; i > 0; --i) { var = xv_get(&scope->locals, i - 1); pic_push(pic, pic_sym_value(*var), locals); } - varg = scope->varg - ? pic_true_value() - : pic_false_value(); - captures = pic_nil_value(); for (xh_begin(scope->captures, &it); ! xh_isend(&it); xh_next(&it)) { if (it.e->val == CAPTURED) {