Compare commits
2 Commits
e8b613576f
...
0a0db012a3
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a0db012a3 | |||
| 21b22e28c4 |
+261
-133
@@ -994,6 +994,223 @@ oops:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_nde_bool_literal_atom (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
switch (nde->type)
|
||||||
|
{
|
||||||
|
case HAWK_NDE_XFALSE:
|
||||||
|
case HAWK_NDE_XTRUE:
|
||||||
|
case HAWK_NDE_XNIL:
|
||||||
|
case HAWK_NDE_INT:
|
||||||
|
case HAWK_NDE_FLT:
|
||||||
|
case HAWK_NDE_STR:
|
||||||
|
case HAWK_NDE_MBS:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the effective literal node for boolean decision.
|
||||||
|
* if nde is a grouped node, every grouped element must be literal.
|
||||||
|
* the returned node is the last literal element in the group.
|
||||||
|
*
|
||||||
|
* examples:
|
||||||
|
* (1, 0) -> INT(0)
|
||||||
|
* ((1, 0)) -> INT(0)
|
||||||
|
* ("x", @false) -> XFALSE
|
||||||
|
* (abc(), 0) -> HAWK_NULL
|
||||||
|
*/
|
||||||
|
static hawk_nde_t* get_nde_bool_literal_tail (hawk_nde_t* nde, int depth)
|
||||||
|
{
|
||||||
|
if (depth >= 256) return HAWK_NULL; /* i don't wawnt to support to deep recursion. TODO: remove hard-coded value or remove recursion? */
|
||||||
|
|
||||||
|
if (nde->type == HAWK_NDE_GRP)
|
||||||
|
{
|
||||||
|
hawk_nde_t* cur, * last;
|
||||||
|
|
||||||
|
cur = ((hawk_nde_grp_t*)nde)->body;
|
||||||
|
HAWK_ASSERT(cur != HAWK_NULL);
|
||||||
|
|
||||||
|
last = HAWK_NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
last = get_nde_bool_literal_tail(cur, depth + 1);
|
||||||
|
if (!last) return HAWK_NULL;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
while (cur);
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_nde_bool_literal_atom(nde)? nde: HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nde_hard_bool_t classify_nde_hard_bool (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
nde = get_nde_bool_literal_tail(nde, 0);
|
||||||
|
if (!nde) return NDE_HARD_BOOL_UNKNOWN;
|
||||||
|
|
||||||
|
switch (nde->type)
|
||||||
|
{
|
||||||
|
case HAWK_NDE_XFALSE:
|
||||||
|
case HAWK_NDE_XNIL:
|
||||||
|
return NDE_HARD_BOOL_FALSE;
|
||||||
|
|
||||||
|
case HAWK_NDE_XTRUE:
|
||||||
|
return NDE_HARD_BOOL_TRUE;
|
||||||
|
|
||||||
|
case HAWK_NDE_INT:
|
||||||
|
return (((hawk_nde_int_t*)nde)->val == 0)?
|
||||||
|
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
||||||
|
|
||||||
|
case HAWK_NDE_FLT:
|
||||||
|
return (((hawk_nde_flt_t*)nde)->val == 0.0)?
|
||||||
|
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
||||||
|
|
||||||
|
case HAWK_NDE_STR:
|
||||||
|
return (((hawk_nde_str_t*)nde)->len == 0)?
|
||||||
|
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
||||||
|
|
||||||
|
case HAWK_NDE_MBS:
|
||||||
|
return (((hawk_nde_mbs_t*)nde)->len == 0)?
|
||||||
|
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NDE_HARD_BOOL_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HAWK_INLINE int is_nde_hard_false (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
return classify_nde_hard_bool(nde) == NDE_HARD_BOOL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HAWK_INLINE int is_nde_hard_true (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
return classify_nde_hard_bool(nde) == NDE_HARD_BOOL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_nde_unconditional_terminator (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
switch (nde->type)
|
||||||
|
{
|
||||||
|
case HAWK_NDE_EXIT: /* exit or @abort */
|
||||||
|
case HAWK_NDE_RETURN: /* return */
|
||||||
|
case HAWK_NDE_NEXT:
|
||||||
|
case HAWK_NDE_NEXTFILE:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* TODO: recursion depth check? */
|
||||||
|
case HAWK_NDE_BLK:
|
||||||
|
{
|
||||||
|
hawk_nde_t* p;
|
||||||
|
for (p = ((hawk_nde_blk_t*)nde)->body; p; p = p->next)
|
||||||
|
{
|
||||||
|
if (is_nde_unconditional_terminator(p)) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_IF:
|
||||||
|
{
|
||||||
|
hawk_nde_if_t* p = (hawk_nde_if_t*)nde;
|
||||||
|
return p->else_part &&
|
||||||
|
is_nde_unconditional_terminator(p->else_part) &&
|
||||||
|
is_nde_unconditional_terminator(p->then_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int does_nde_have_side_effect (hawk_nde_t* nde)
|
||||||
|
{
|
||||||
|
HAWK_ASSERT(nde != HAWK_NULL);
|
||||||
|
|
||||||
|
switch (nde->type)
|
||||||
|
{
|
||||||
|
case HAWK_NDE_NULL:
|
||||||
|
case HAWK_NDE_CHAR:
|
||||||
|
case HAWK_NDE_BCHR:
|
||||||
|
case HAWK_NDE_INT:
|
||||||
|
case HAWK_NDE_FLT:
|
||||||
|
case HAWK_NDE_STR:
|
||||||
|
case HAWK_NDE_MBS:
|
||||||
|
case HAWK_NDE_REX:
|
||||||
|
case HAWK_NDE_XNIL:
|
||||||
|
case HAWK_NDE_XTRUE:
|
||||||
|
case HAWK_NDE_XFALSE:
|
||||||
|
case HAWK_NDE_XARGC:
|
||||||
|
case HAWK_NDE_XARGV:
|
||||||
|
case HAWK_NDE_FUN:
|
||||||
|
case HAWK_NDE_MODSYM:
|
||||||
|
case HAWK_NDE_NAMED:
|
||||||
|
case HAWK_NDE_GBL:
|
||||||
|
case HAWK_NDE_LCL:
|
||||||
|
case HAWK_NDE_ARG:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case HAWK_NDE_NAMEDIDX:
|
||||||
|
case HAWK_NDE_GBLIDX:
|
||||||
|
case HAWK_NDE_LCLIDX:
|
||||||
|
case HAWK_NDE_ARGIDX:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_var_t*)nde)->idx);
|
||||||
|
|
||||||
|
case HAWK_NDE_XARGVIDX:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_xargvidx_t*)nde)->pos);
|
||||||
|
|
||||||
|
case HAWK_NDE_POS:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_pos_t*)nde)->val);
|
||||||
|
|
||||||
|
case HAWK_NDE_GRP:
|
||||||
|
{
|
||||||
|
hawk_nde_t* p;
|
||||||
|
for (p = ((hawk_nde_grp_t*)nde)->body; p; p = p->next)
|
||||||
|
{
|
||||||
|
if (does_nde_have_side_effect(p)) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_EXP_BIN:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_exp_t*)nde)->left) ||
|
||||||
|
does_nde_have_side_effect(((hawk_nde_exp_t*)nde)->right);
|
||||||
|
|
||||||
|
case HAWK_NDE_EXP_UNR:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_exp_t*)nde)->left);
|
||||||
|
|
||||||
|
case HAWK_NDE_BLK:
|
||||||
|
{
|
||||||
|
hawk_nde_t* p;
|
||||||
|
for (p = ((hawk_nde_blk_t*)nde)->body; p; p = p->next)
|
||||||
|
{
|
||||||
|
if (does_nde_have_side_effect(p)) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HAWK_NDE_CND:
|
||||||
|
return does_nde_have_side_effect(((hawk_nde_cnd_t*)nde)->test) ||
|
||||||
|
does_nde_have_side_effect(((hawk_nde_cnd_t*)nde)->left) ||
|
||||||
|
does_nde_have_side_effect(((hawk_nde_cnd_t*)nde)->right);
|
||||||
|
|
||||||
|
case HAWK_NDE_IF:
|
||||||
|
{
|
||||||
|
hawk_nde_if_t* p = (hawk_nde_if_t*)nde;
|
||||||
|
return does_nde_have_side_effect(p->test) ||
|
||||||
|
does_nde_have_side_effect(p->then_part) ||
|
||||||
|
(p->else_part && does_nde_have_side_effect(p->else_part));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all other nodes */
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_progunit (hawk_t* hawk)
|
static int parse_progunit (hawk_t* hawk)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -2024,6 +2241,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
|||||||
hawk_nde_blk_t* block;
|
hawk_nde_blk_t* block;
|
||||||
hawk_oow_t nlcls_outer, nlcls_max, tmp;
|
hawk_oow_t nlcls_outer, nlcls_max, tmp;
|
||||||
nde_chain_t local_inits = { HAWK_NULL, HAWK_NULL };
|
nde_chain_t local_inits = { HAWK_NULL, HAWK_NULL };
|
||||||
|
int dead_code;
|
||||||
|
|
||||||
nlcls_outer = 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;
|
||||||
@@ -2034,6 +2252,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
|||||||
/* block body */
|
/* block body */
|
||||||
head = local_inits.head;
|
head = local_inits.head;
|
||||||
curr = local_inits.tail;
|
curr = local_inits.tail;
|
||||||
|
dead_code = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -2100,9 +2319,17 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dead_code)
|
||||||
|
{
|
||||||
|
hawk_clrpt(hawk, nde);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (curr == HAWK_NULL) head = nde;
|
if (curr == HAWK_NULL) head = nde;
|
||||||
else curr->next = nde;
|
else curr->next = nde;
|
||||||
curr = nde;
|
curr = nde;
|
||||||
|
|
||||||
|
if (is_nde_unconditional_terminator(nde)) dead_code = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3025,102 +3252,22 @@ oops:
|
|||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_nde_bool_literal_atom (hawk_nde_t* nde)
|
static hawk_nde_t* make_null_nde (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
{
|
{
|
||||||
switch (nde->type)
|
hawk_nde_t* null_nde;
|
||||||
|
|
||||||
|
null_nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*null_nde));
|
||||||
|
if (HAWK_UNLIKELY(!null_nde))
|
||||||
{
|
{
|
||||||
case HAWK_NDE_XFALSE:
|
ADJERR_LOC(hawk, xloc);
|
||||||
case HAWK_NDE_XTRUE:
|
return HAWK_NULL;
|
||||||
case HAWK_NDE_XNIL:
|
|
||||||
case HAWK_NDE_INT:
|
|
||||||
case HAWK_NDE_FLT:
|
|
||||||
case HAWK_NDE_STR:
|
|
||||||
case HAWK_NDE_MBS:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return the effective literal node for boolean decision.
|
|
||||||
* if nde is a grouped node, every grouped element must be literal.
|
|
||||||
* the returned node is the last literal element in the group.
|
|
||||||
*
|
|
||||||
* examples:
|
|
||||||
* (1, 0) -> INT(0)
|
|
||||||
* ((1, 0)) -> INT(0)
|
|
||||||
* ("x", @false) -> XFALSE
|
|
||||||
* (abc(), 0) -> HAWK_NULL
|
|
||||||
*/
|
|
||||||
static hawk_nde_t* get_nde_bool_literal_tail (hawk_nde_t* nde, int depth)
|
|
||||||
{
|
|
||||||
if (depth >= 256) return HAWK_NULL; /* i don't wawnt to support to deep recursion. TODO: remove hard-coded value or remove recursion? */
|
|
||||||
|
|
||||||
if (nde->type == HAWK_NDE_GRP)
|
|
||||||
{
|
|
||||||
hawk_nde_t* cur, * last;
|
|
||||||
|
|
||||||
cur = ((hawk_nde_grp_t*)nde)->body;
|
|
||||||
HAWK_ASSERT(cur != HAWK_NULL);
|
|
||||||
|
|
||||||
last = HAWK_NULL;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
last = get_nde_bool_literal_tail(cur, depth + 1);
|
|
||||||
if (!last) return HAWK_NULL;
|
|
||||||
cur = cur->next;
|
|
||||||
}
|
|
||||||
while (cur);
|
|
||||||
|
|
||||||
return last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_nde_bool_literal_atom(nde)? nde: HAWK_NULL;
|
null_nde->type = HAWK_NDE_NULL;
|
||||||
}
|
if (xloc) null_nde->loc = *xloc;
|
||||||
|
null_nde->next = HAWK_NULL;
|
||||||
|
|
||||||
static nde_hard_bool_t classify_nde_hard_bool (hawk_nde_t* nde)
|
return null_nde;
|
||||||
{
|
|
||||||
nde = get_nde_bool_literal_tail(nde, 0);
|
|
||||||
if (!nde) return NDE_HARD_BOOL_UNKNOWN;
|
|
||||||
|
|
||||||
switch (nde->type)
|
|
||||||
{
|
|
||||||
case HAWK_NDE_XFALSE:
|
|
||||||
case HAWK_NDE_XNIL:
|
|
||||||
return NDE_HARD_BOOL_FALSE;
|
|
||||||
|
|
||||||
case HAWK_NDE_XTRUE:
|
|
||||||
return NDE_HARD_BOOL_TRUE;
|
|
||||||
|
|
||||||
case HAWK_NDE_INT:
|
|
||||||
return (((hawk_nde_int_t*)nde)->val == 0)?
|
|
||||||
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
|
||||||
|
|
||||||
case HAWK_NDE_FLT:
|
|
||||||
return (((hawk_nde_flt_t*)nde)->val == 0.0)?
|
|
||||||
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
|
||||||
|
|
||||||
case HAWK_NDE_STR:
|
|
||||||
return (((hawk_nde_str_t*)nde)->len == 0)?
|
|
||||||
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
|
||||||
|
|
||||||
case HAWK_NDE_MBS:
|
|
||||||
return (((hawk_nde_mbs_t*)nde)->len == 0)?
|
|
||||||
NDE_HARD_BOOL_FALSE: NDE_HARD_BOOL_TRUE;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NDE_HARD_BOOL_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static HAWK_INLINE int is_nde_hard_false (hawk_nde_t* nde)
|
|
||||||
{
|
|
||||||
return classify_nde_hard_bool(nde) == NDE_HARD_BOOL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HAWK_INLINE int is_nde_hard_true (hawk_nde_t* nde)
|
|
||||||
{
|
|
||||||
return classify_nde_hard_bool(nde) == NDE_HARD_BOOL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
|
static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||||
@@ -3148,10 +3295,6 @@ static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: optimization. if you know 'test' evaluates to true or false,
|
|
||||||
* you can drop the 'if' statement and take either the 'then_part'
|
|
||||||
* or 'else_part'. */
|
|
||||||
|
|
||||||
if (get_token(hawk) <= -1) goto oops;
|
if (get_token(hawk) <= -1) goto oops;
|
||||||
|
|
||||||
tloc = hawk->tok.loc;
|
tloc = hawk->tok.loc;
|
||||||
@@ -3189,12 +3332,8 @@ static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
{
|
{
|
||||||
hawk_nde_t* null_nde;
|
hawk_nde_t* null_nde;
|
||||||
|
|
||||||
null_nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*null_nde));
|
null_nde = make_null_nde(hawk, xloc);
|
||||||
if (HAWK_UNLIKELY(!null_nde))
|
if (HAWK_UNLIKELY(!null_nde)) goto oops;
|
||||||
{
|
|
||||||
ADJERR_LOC(hawk, xloc);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [BE CAREFUL]
|
/* [BE CAREFUL]
|
||||||
* Don't forget reset test and then_part to HAWK_NULL if the control
|
* Don't forget reset test and then_part to HAWK_NULL if the control
|
||||||
@@ -3202,8 +3341,6 @@ static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
hawk_clrpt(hawk, test);
|
hawk_clrpt(hawk, test);
|
||||||
hawk_clrpt(hawk, then_part);
|
hawk_clrpt(hawk, then_part);
|
||||||
|
|
||||||
null_nde->type = HAWK_NDE_NULL;
|
|
||||||
null_nde->loc = *xloc;
|
|
||||||
return null_nde;
|
return null_nde;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3480,18 +3617,12 @@ static hawk_nde_t* parse_while (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
/* fold while(0) and while(@false) into a null statement. */
|
/* fold while(0) and while(@false) into a null statement. */
|
||||||
hawk_nde_t* null_nde;
|
hawk_nde_t* null_nde;
|
||||||
|
|
||||||
null_nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*null_nde));
|
null_nde = make_null_nde(hawk, xloc);
|
||||||
if (HAWK_UNLIKELY(!null_nde))
|
if (HAWK_UNLIKELY(!null_nde)) goto oops;
|
||||||
{
|
|
||||||
ADJERR_LOC(hawk, xloc);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
hawk_clrpt(hawk, body); body = HAWK_NULL;
|
hawk_clrpt(hawk, body); body = HAWK_NULL;
|
||||||
hawk_clrpt(hawk, test); test = HAWK_NULL;
|
hawk_clrpt(hawk, test); test = HAWK_NULL;
|
||||||
|
|
||||||
null_nde->type = HAWK_NDE_NULL;
|
|
||||||
null_nde->loc = *xloc;
|
|
||||||
return null_nde;
|
return null_nde;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4342,20 +4473,12 @@ static hawk_nde_t* parse_statement (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
if (MATCH(hawk,TOK_SEMICOLON))
|
if (MATCH(hawk,TOK_SEMICOLON))
|
||||||
{
|
{
|
||||||
/* null statement */
|
/* null statement */
|
||||||
nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
|
nde = make_null_nde(hawk, xloc);
|
||||||
if (HAWK_UNLIKELY(!nde))
|
if (HAWK_UNLIKELY(!nde)) return HAWK_NULL;
|
||||||
{
|
|
||||||
ADJERR_LOC(hawk, xloc);
|
|
||||||
return HAWK_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nde->type = HAWK_NDE_NULL;
|
|
||||||
nde->loc = *xloc;
|
|
||||||
nde->next = HAWK_NULL;
|
|
||||||
|
|
||||||
if (get_token(hawk) <= -1)
|
if (get_token(hawk) <= -1)
|
||||||
{
|
{
|
||||||
hawk_freemem(hawk, nde);
|
hawk_clrpt(hawk, nde);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4392,6 +4515,15 @@ static hawk_nde_t* parse_statement (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
hawk->parse.id.stmt = old_id;
|
hawk->parse.id.stmt = old_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nde && !does_nde_have_side_effect(nde))
|
||||||
|
{
|
||||||
|
hawk_nde_t* tmp;
|
||||||
|
tmp = make_null_nde(hawk, &nde->loc);
|
||||||
|
hawk_clrpt(hawk, nde);
|
||||||
|
if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL;
|
||||||
|
nde = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return nde;
|
return nde;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4430,7 +4562,7 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
hawk_nde_t* nde, * n1, * n2;
|
hawk_nde_t* nde, * n1, * n2;
|
||||||
|
|
||||||
nde = parse_logical_or(hawk, xloc);
|
nde = parse_logical_or(hawk, xloc);
|
||||||
if (nde == HAWK_NULL) return HAWK_NULL;
|
if (!nde) return HAWK_NULL;
|
||||||
|
|
||||||
if (MATCH(hawk,TOK_QUEST))
|
if (MATCH(hawk,TOK_QUEST))
|
||||||
{
|
{
|
||||||
@@ -4445,7 +4577,7 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
|
|
||||||
eloc = hawk->tok.loc;
|
eloc = hawk->tok.loc;
|
||||||
n1 = parse_expr_withdc(hawk, &eloc);
|
n1 = parse_expr_withdc(hawk, &eloc);
|
||||||
if (n1 == HAWK_NULL)
|
if (!n1)
|
||||||
{
|
{
|
||||||
hawk_clrpt(hawk, nde);
|
hawk_clrpt(hawk, nde);
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@@ -4467,7 +4599,7 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
|
|
||||||
eloc = hawk->tok.loc;
|
eloc = hawk->tok.loc;
|
||||||
n2 = parse_expr_withdc(hawk, &eloc);
|
n2 = parse_expr_withdc(hawk, &eloc);
|
||||||
if (n2 == HAWK_NULL)
|
if (!n2)
|
||||||
{
|
{
|
||||||
hawk_clrpt(hawk, nde);
|
hawk_clrpt(hawk, nde);
|
||||||
hawk_clrpt(hawk, n1);
|
hawk_clrpt(hawk, n1);
|
||||||
@@ -4475,7 +4607,7 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cnd = (hawk_nde_cnd_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*cnd));
|
cnd = (hawk_nde_cnd_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*cnd));
|
||||||
if (cnd == HAWK_NULL)
|
if (HAWK_UNLIKELY(!cnd))
|
||||||
{
|
{
|
||||||
hawk_clrpt(hawk, nde);
|
hawk_clrpt(hawk, nde);
|
||||||
hawk_clrpt(hawk, n1);
|
hawk_clrpt(hawk, n1);
|
||||||
@@ -7403,18 +7535,14 @@ static hawk_nde_t* parse_idx_chain (hawk_t* hawk, const hawk_loc_t* xloc)
|
|||||||
|
|
||||||
/* additional index - a[10][20] or a.b.c ...
|
/* additional index - a[10][20] or a.b.c ...
|
||||||
* use the NULL node as a splitter */
|
* use the NULL node as a splitter */
|
||||||
splitter = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*splitter));
|
|
||||||
if (HAWK_UNLIKELY(!splitter))
|
|
||||||
{
|
|
||||||
ADJERR_LOC(hawk, xloc);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
splitter->type = HAWK_NDE_NULL;
|
splitter = make_null_nde(hawk, xloc);
|
||||||
|
if (HAWK_UNLIKELY(!splitter)) goto oops;
|
||||||
|
|
||||||
HAWK_ASSERT(idx.tail != HAWK_NULL);
|
HAWK_ASSERT(idx.tail != HAWK_NULL);
|
||||||
idx.tail->next = splitter;
|
idx.tail->next = splitter;
|
||||||
idx.tail = splitter;
|
idx.tail = splitter;
|
||||||
|
/* splitter is already chained. no need seperate clearing upon failure */
|
||||||
|
|
||||||
if (parse_single_idx(hawk, &idx) <= -1) goto oops;
|
if (parse_single_idx(hawk, &idx) <= -1) goto oops;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user