From afe27f4eecf58c6ab11e1962fc3729a3de19b349 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 12 Nov 2020 08:02:36 +0000 Subject: [PATCH] hawk initializes block-local variables upon block entry regardless of migration to the outermost block by the parser. it emits the local variable declaration in the original nested block regardless of migration by the parser. --- hawk/lib/parse.c | 42 ++++++++++++++--------- hawk/lib/run.c | 83 +++++++++++++++++++++++++++++++-------------- hawk/lib/std.c | 5 ++- hawk/lib/tree-prv.h | 2 ++ hawk/lib/tree.c | 17 ++++++---- hawk/t/h-002.hawk | 3 +- 6 files changed, 101 insertions(+), 51 deletions(-) diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index 158bdfe6..bb65321b 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -1708,9 +1708,9 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) { hawk_nde_t* head, * curr, * nde; hawk_nde_blk_t* block; - hawk_oow_t nlcls, nlcls_max, tmp; + hawk_oow_t nlcls_outer, nlcls_max, tmp; - nlcls = HAWK_ARR_SIZE(hawk->parse.lcls); + nlcls_outer = HAWK_ARR_SIZE(hawk->parse.lcls); nlcls_max = hawk->parse.nlcls_max; /* local variable declarations */ @@ -1750,13 +1750,13 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) /* @local ... */ if (get_token(hawk) <= -1) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); return HAWK_NULL; } - if (collect_locals(hawk, nlcls, istop) == HAWK_NULL) + if (collect_locals(hawk, nlcls_outer, istop) == HAWK_NULL) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); return HAWK_NULL; } } @@ -1777,7 +1777,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) /* if EOF is met before the right brace, this is an error */ if (MATCH(hawk,TOK_EOF)) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); if (head) hawk_clrpt (hawk, head); hawk_seterrnum (hawk, &hawk->tok.loc, HAWK_EEOF); return HAWK_NULL; @@ -1788,7 +1788,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) { if (get_token(hawk) <= -1) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls)-nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); if (head) hawk_clrpt (hawk, head); return HAWK_NULL; } @@ -1829,7 +1829,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) if (HAWK_UNLIKELY(!nde)) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls)-nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); if (head) hawk_clrpt (hawk, head); return HAWK_NULL; } @@ -1856,7 +1856,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) block = (hawk_nde_blk_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*block)); if (HAWK_UNLIKELY(!block)) { - hawk_arr_delete (hawk->parse.lcls, nlcls, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer); hawk_clrpt (hawk, head); ADJERR_LOC (hawk, xloc); return HAWK_NULL; @@ -1866,7 +1866,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) if (tmp > hawk->parse.nlcls_max) hawk->parse.nlcls_max = tmp; /* remove all lcls to move them up to the top level */ - hawk_arr_delete (hawk->parse.lcls, nlcls, tmp - nlcls); + hawk_arr_delete (hawk->parse.lcls, nlcls_outer, tmp - nlcls_outer); /* adjust the number of lcls for a block without any statements */ /* if (head == HAWK_NULL) tmp = 0; */ @@ -1875,21 +1875,29 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop) block->loc = *xloc; block->body = head; + block->org_nlcls = tmp - nlcls_outer; /* number of locals defined in this block */ + block->outer_nlcls = nlcls_outer; /* number of locals defined in outer blocks */ + +#if 1 /* TODO: not only local variables but also nested blocks, unless it is part of other constructs such as if, can be promoted and merged to top-level block */ - /* migrate all block-local variables to a top-level block */ + /* migrate all block-local variables to the outermost block */ if (istop) { - block->nlcls = hawk->parse.nlcls_max - nlcls; - hawk->parse.nlcls_max = nlcls_max; + HAWK_ASSERT (nlcls_outer == 0 && nlcls_max == 0); + block->nlcls = hawk->parse.nlcls_max - nlcls_outer; + hawk->parse.nlcls_max = nlcls_max; /* restore */ } else { - /*block->nlcls = tmp - nlcls;*/ block->nlcls = 0; } +#else + /* no migration */ + block->nlcls = block->org_nlcls; +#endif return (hawk_nde_t*)block; } @@ -7113,6 +7121,7 @@ static int deparse (hawk_t* hawk) if (hawk_putsrcoochars(hawk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE (); if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE (); + if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE (); if (hawk->opt.trait & HAWK_CRLF) @@ -7124,7 +7133,7 @@ static int deparse (hawk_t* hawk) } chain = hawk->tree.chain; - while (chain != HAWK_NULL) + while (chain) { if (chain->pattern != HAWK_NULL) { @@ -7143,7 +7152,7 @@ static int deparse (hawk_t* hawk) } else { - if (chain->pattern != HAWK_NULL) + if (chain->pattern) { if (put_char(hawk, HAWK_T(' ')) <= -1) EXIT_DEPARSE (); } @@ -7168,6 +7177,7 @@ static int deparse (hawk_t* hawk) if (hawk_putsrcoochars(hawk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE (); if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE (); + if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE (); /* diff --git a/hawk/lib/run.c b/hawk/lib/run.c index 6317c06c..9634e94a 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -2093,35 +2093,60 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde) } HAWK_ASSERT (nde->type == HAWK_NDE_BLK); - - p = nde->body; - nlcls = nde->nlcls; - -#if defined(DEBUG_RUN) - hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("securing space for local variables nlcls = %d\n"), (int)nlcls); -#endif - - /* secure space for local variables */ - if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < nlcls)) - { - hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ESTACK); - return -1; - } - saved_stack_top = rtx->stack_top; - while (nlcls > 0) +#if defined(DEBUG_RUN) + hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("securing space for local variables nlcls = %d\n"), (int)nde->nlcls); +#endif + + if (nde->nlcls > 0) { - --nlcls; - HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); - /* refupval is not required for hawk_val_nil */ + hawk_oow_t tmp = nde->nlcls; + + /* ensure sufficient space for local variables */ + if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < tmp)) + { + hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ESTACK); + return -1; + } + + do + { + --tmp; + HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); + /* refupval is not required for hawk_val_nil */ + } + while (tmp > 0); + } + else if (nde->nlcls != nde->org_nlcls) + { + /* this part can be reached if: + * - the block is nested + * - the block declares local variables + * - the local variables have been migrated to the outer-most block by the parser. + * + * if the parser skips migrations, this part isn't reached but the normal push/pop + * will take place for a nested block with local variable declaration. + */ + hawk_oow_t tmp, end; + + /* when the outer-most block has been entered, the space large enough for all local + * variables defined has been secured. nullify part of the stack to initialze local + * variables defined for a nested block */ + end = nde->outer_nlcls + nde->org_nlcls; + for (tmp = nde->outer_nlcls; tmp < end; tmp++) + { + hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, tmp)); + HAWK_RTX_STACK_LCL(rtx, tmp) = hawk_val_nil; + } } #if defined(DEBUG_RUN) hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("executing block statements\n")); #endif - while (p != HAWK_NULL && rtx->exit_level == EXIT_NONE) + p = nde->body; + while (p && rtx->exit_level == EXIT_NONE) { if (HAWK_UNLIKELY(run_statement(rtx, p) <= -1)) { @@ -2135,12 +2160,18 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde) #if defined(DEBUG_RUN) hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("popping off local variables\n")); #endif - nlcls = nde->nlcls; - while (nlcls > 0) + + if (nde->nlcls > 0) { - --nlcls; - hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, nlcls)); - HAWK_RTX_STACK_POP (rtx); + hawk_oow_t tmp = nde->nlcls; + + do + { + --tmp; + hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, tmp)); + HAWK_RTX_STACK_POP (rtx); + } + while (tmp > 0); } return n; @@ -6206,7 +6237,7 @@ static hawk_val_t* eval_fncall_var (hawk_rtx_t* rtx, hawk_nde_t* nde) ADJERR_LOC (rtx, &nde->loc); rv = HAWK_NULL; } - else if (call->nargs > fun->nargs) + else if (call->nargs > fun->nargs) { /* TODO: is this correct? what if i want to * allow arbitarary numbers of arguments? */ diff --git a/hawk/lib/std.c b/hawk/lib/std.c index 35d566ae..8614389e 100644 --- a/hawk/lib/std.c +++ b/hawk/lib/std.c @@ -729,7 +729,10 @@ static void log_write (hawk_t* hawk, hawk_bitmask_t mask, const hawk_ooch_t* msg { logfd = xtn->log.fd; #if !defined(EMSCRIPTEN) - if (logfd <= -1) return; + if (logfd <= -1) + { + return; + } #endif } diff --git a/hawk/lib/tree-prv.h b/hawk/lib/tree-prv.h index 4335a530..ac8d5cf6 100644 --- a/hawk/lib/tree-prv.h +++ b/hawk/lib/tree-prv.h @@ -88,6 +88,8 @@ struct hawk_nde_blk_t { HAWK_NDE_HDR; hawk_oow_t nlcls; /* number of local variables */ + hawk_oow_t org_nlcls; /* the original number of local variables before pushing to the top-level block */ + hawk_oow_t outer_nlcls; /* the number of local variables in the outer blocks accumulated */ hawk_nde_t* body; }; diff --git a/hawk/lib/tree.c b/hawk/lib/tree.c index ac21bc40..af28f73e 100644 --- a/hawk/lib/tree.c +++ b/hawk/lib/tree.c @@ -638,6 +638,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde) break; } + case HAWK_NDE_LCL: { hawk_oow_t n; @@ -834,7 +835,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth) PUT_SRCSTR (hawk, HAWK_T("{")); PUT_NL (hawk); - if (px->nlcls > 0) + if (px->org_nlcls > 0) { PRINT_TABS (hawk, depth + 1); @@ -842,16 +843,18 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth) PUT_SRCSTRN (hawk, kw.ptr, kw.len); PUT_SRCSTR (hawk, HAWK_T(" ")); - for (i = 0; i < px->nlcls - 1; i++) + /* though the parser pushed up all local variables to the outer-most level, + * the code here restores the original declarations with org_nlcls and prv_nlcls */ + for (i = 0; i < px->org_nlcls - 1; i++) { PUT_SRCSTR (hawk, HAWK_T("__l")); - n = hawk_int_to_oocstr(i, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt)); + n = hawk_int_to_oocstr(px->outer_nlcls + i, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt)); PUT_SRCSTRN (hawk, hawk->tmp.fmt, n); PUT_SRCSTR (hawk, HAWK_T(", ")); } PUT_SRCSTR (hawk, HAWK_T("__l")); - n = hawk_int_to_oocstr(i, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt)); + n = hawk_int_to_oocstr(px->outer_nlcls + i, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt)); PUT_SRCSTRN (hawk, hawk->tmp.fmt, n); PUT_SRCSTR (hawk, HAWK_T(";")); PUT_NL (hawk); @@ -1148,7 +1151,7 @@ static int print_stmts (hawk_t* hawk, hawk_nde_t* tree, int depth) while (p) { - if (print_stmt(hawk, p, depth) == -1) return -1; + if (print_stmt(hawk, p, depth) <= -1) return -1; p = p->next; } @@ -1171,8 +1174,8 @@ int hawk_prnptnpt (hawk_t* hawk, hawk_nde_t* tree) while (nde) { - if (print_expr (hawk, nde) == -1) return -1; - if (nde->next == HAWK_NULL) break; + if (print_expr(hawk, nde) <= -1) return -1; + if (!nde->next) break; PUT_SRCSTR (hawk, HAWK_T(",")); nde = nde->next; diff --git a/hawk/t/h-002.hawk b/hawk/t/h-002.hawk index 9fd737ed..f016715a 100644 --- a/hawk/t/h-002.hawk +++ b/hawk/t/h-002.hawk @@ -244,7 +244,8 @@ function main() { @local bool, b, c; - c = @nil; + ensure ((c === @nil), 1, @SCRIPTNAME, @SCRIPTLINE); ## ensure local variable initialization + bool = ((b = 1) in c); ensure (bool, 0, @SCRIPTNAME, @SCRIPTLINE); ensure (b, 1, @SCRIPTNAME, @SCRIPTLINE);