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.
This commit is contained in:
hyung-hwan 2020-11-12 08:02:36 +00:00
parent 7ab601303c
commit afe27f4eec
6 changed files with 101 additions and 51 deletions

View File

@ -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_t* head, * curr, * nde;
hawk_nde_blk_t* block; 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; nlcls_max = hawk->parse.nlcls_max;
/* local variable declarations */ /* local variable declarations */
@ -1750,13 +1750,13 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
/* @local ... */ /* @local ... */
if (get_token(hawk) <= -1) 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; 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; 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 EOF is met before the right brace, this is an error */
if (MATCH(hawk,TOK_EOF)) 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); if (head) hawk_clrpt (hawk, head);
hawk_seterrnum (hawk, &hawk->tok.loc, HAWK_EEOF); hawk_seterrnum (hawk, &hawk->tok.loc, HAWK_EEOF);
return HAWK_NULL; 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) 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); if (head) hawk_clrpt (hawk, head);
return HAWK_NULL; 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)) 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); if (head) hawk_clrpt (hawk, head);
return HAWK_NULL; 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)); block = (hawk_nde_blk_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*block));
if (HAWK_UNLIKELY(!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); hawk_clrpt (hawk, head);
ADJERR_LOC (hawk, xloc); ADJERR_LOC (hawk, xloc);
return HAWK_NULL; 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; if (tmp > hawk->parse.nlcls_max) hawk->parse.nlcls_max = tmp;
/* remove all lcls to move them up to the top level */ /* 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 */ /* adjust the number of lcls for a block without any statements */
/* if (head == HAWK_NULL) tmp = 0; */ /* 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->loc = *xloc;
block->body = head; 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, /* TODO: not only local variables but also nested blocks,
unless it is part of other constructs such as if, can be promoted unless it is part of other constructs such as if, can be promoted
and merged to top-level block */ 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) if (istop)
{ {
block->nlcls = hawk->parse.nlcls_max - nlcls; HAWK_ASSERT (nlcls_outer == 0 && nlcls_max == 0);
hawk->parse.nlcls_max = nlcls_max; block->nlcls = hawk->parse.nlcls_max - nlcls_outer;
hawk->parse.nlcls_max = nlcls_max; /* restore */
} }
else else
{ {
/*block->nlcls = tmp - nlcls;*/
block->nlcls = 0; block->nlcls = 0;
} }
#else
/* no migration */
block->nlcls = block->org_nlcls;
#endif
return (hawk_nde_t*)block; 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_putsrcoochars(hawk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE ();
if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE (); if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE ();
if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE (); if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE ();
if (hawk->opt.trait & HAWK_CRLF) if (hawk->opt.trait & HAWK_CRLF)
@ -7124,7 +7133,7 @@ static int deparse (hawk_t* hawk)
} }
chain = hawk->tree.chain; chain = hawk->tree.chain;
while (chain != HAWK_NULL) while (chain)
{ {
if (chain->pattern != HAWK_NULL) if (chain->pattern != HAWK_NULL)
{ {
@ -7143,7 +7152,7 @@ static int deparse (hawk_t* hawk)
} }
else else
{ {
if (chain->pattern != HAWK_NULL) if (chain->pattern)
{ {
if (put_char(hawk, HAWK_T(' ')) <= -1) EXIT_DEPARSE (); 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_putsrcoochars(hawk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE ();
if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE (); if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1) EXIT_DEPARSE ();
if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE (); if (hawk_prnnde(hawk, nde) <= -1) EXIT_DEPARSE ();
/* /*

View File

@ -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); 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; 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_oow_t tmp = nde->nlcls;
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil);
/* refupval is not required for hawk_val_nil */ /* 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) #if defined(DEBUG_RUN)
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("executing block statements\n")); hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("executing block statements\n"));
#endif #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)) 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) #if defined(DEBUG_RUN)
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("popping off local variables\n")); hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("popping off local variables\n"));
#endif #endif
nlcls = nde->nlcls;
while (nlcls > 0) if (nde->nlcls > 0)
{ {
--nlcls; hawk_oow_t tmp = nde->nlcls;
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, nlcls));
HAWK_RTX_STACK_POP (rtx); do
{
--tmp;
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, tmp));
HAWK_RTX_STACK_POP (rtx);
}
while (tmp > 0);
} }
return n; 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); ADJERR_LOC (rtx, &nde->loc);
rv = HAWK_NULL; rv = HAWK_NULL;
} }
else if (call->nargs > fun->nargs) else if (call->nargs > fun->nargs)
{ {
/* TODO: is this correct? what if i want to /* TODO: is this correct? what if i want to
* allow arbitarary numbers of arguments? */ * allow arbitarary numbers of arguments? */

View File

@ -729,7 +729,10 @@ static void log_write (hawk_t* hawk, hawk_bitmask_t mask, const hawk_ooch_t* msg
{ {
logfd = xtn->log.fd; logfd = xtn->log.fd;
#if !defined(EMSCRIPTEN) #if !defined(EMSCRIPTEN)
if (logfd <= -1) return; if (logfd <= -1)
{
return;
}
#endif #endif
} }

View File

@ -88,6 +88,8 @@ struct hawk_nde_blk_t
{ {
HAWK_NDE_HDR; HAWK_NDE_HDR;
hawk_oow_t nlcls; /* number of local variables */ 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; hawk_nde_t* body;
}; };

View File

@ -638,6 +638,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
break; break;
} }
case HAWK_NDE_LCL: case HAWK_NDE_LCL:
{ {
hawk_oow_t n; 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_SRCSTR (hawk, HAWK_T("{"));
PUT_NL (hawk); PUT_NL (hawk);
if (px->nlcls > 0) if (px->org_nlcls > 0)
{ {
PRINT_TABS (hawk, depth + 1); 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_SRCSTRN (hawk, kw.ptr, kw.len);
PUT_SRCSTR (hawk, HAWK_T(" ")); 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")); 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_SRCSTRN (hawk, hawk->tmp.fmt, n);
PUT_SRCSTR (hawk, HAWK_T(", ")); PUT_SRCSTR (hawk, HAWK_T(", "));
} }
PUT_SRCSTR (hawk, HAWK_T("__l")); 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_SRCSTRN (hawk, hawk->tmp.fmt, n);
PUT_SRCSTR (hawk, HAWK_T(";")); PUT_SRCSTR (hawk, HAWK_T(";"));
PUT_NL (hawk); PUT_NL (hawk);
@ -1148,7 +1151,7 @@ static int print_stmts (hawk_t* hawk, hawk_nde_t* tree, int depth)
while (p) while (p)
{ {
if (print_stmt(hawk, p, depth) == -1) return -1; if (print_stmt(hawk, p, depth) <= -1) return -1;
p = p->next; p = p->next;
} }
@ -1171,8 +1174,8 @@ int hawk_prnptnpt (hawk_t* hawk, hawk_nde_t* tree)
while (nde) while (nde)
{ {
if (print_expr (hawk, nde) == -1) return -1; if (print_expr(hawk, nde) <= -1) return -1;
if (nde->next == HAWK_NULL) break; if (!nde->next) break;
PUT_SRCSTR (hawk, HAWK_T(",")); PUT_SRCSTR (hawk, HAWK_T(","));
nde = nde->next; nde = nde->next;

View File

@ -244,7 +244,8 @@ function main()
{ {
@local bool, b, c; @local bool, b, c;
c = @nil; ensure ((c === @nil), 1, @SCRIPTNAME, @SCRIPTLINE); ## ensure local variable initialization
bool = ((b = 1) in c); bool = ((b = 1) in c);
ensure (bool, 0, @SCRIPTNAME, @SCRIPTLINE); ensure (bool, 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (b, 1, @SCRIPTNAME, @SCRIPTLINE); ensure (b, 1, @SCRIPTNAME, @SCRIPTLINE);