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:
parent
7ab601303c
commit
afe27f4eec
@ -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 ();
|
||||
|
||||
/*
|
||||
|
@ -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? */
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user