Compare commits

...

6 Commits

9 changed files with 897 additions and 254 deletions
+7 -1
View File
@@ -358,7 +358,8 @@ BEGIN {
### Arithmetic and Comparison ### Arithmetic and Comparison
- Arithmetic: `+`, `-`, `*`, `/`, `%`, `**` (exponentiation), `++`, `--`, `<<`, `>>`. - Arithmetic: `+`, `-`, `*`, `/`, `\`(integer division), `%`(modulo), `**` or '^'(exponentiation), `++`, `--`, `<<`, `>>`.
- Compound assignment: `=`, `+=`, `-=`, `*=`, `/=`, `\=`, `%=`, `^=` or `**=`, `%%=`.
- Comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`. - Comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`.
- Type-precise compare: `===` and `!==`. - Type-precise compare: `===` and `!==`.
@@ -367,7 +368,11 @@ Example:
```awk ```awk
BEGIN { BEGIN {
x = 10 + 5 * 2 x = 10 + 5 * 2
x += 3
s = "ha"
s %%= "wk"
if (x >= 20) print x if (x >= 20) print x
print s
if ("10" === 10) print "no" if ("10" === 10) print "no"
} }
``` ```
@@ -404,6 +409,7 @@ BEGIN {
- Bitwise AND/OR/XOR: `&`, `|`, ^^ - Bitwise AND/OR/XOR: `&`, `|`, ^^
- Unary bitwise negation: ~ - Unary bitwise negation: ~
- Compound bitwise assignment: `&=`, `|=`, `^^=`, `<<=`, `>>=`
- `|` also denotes pipes, so use parentheses when you mean bitwise OR. - `|` also denotes pipes, so use parentheses when you mean bitwise OR.
- `>>` is also used for append redirection; use parentheses when you mean right shift. - `>>` is also used for append redirection; use parentheses when you mean right shift.
+492 -162
View File
@@ -218,6 +218,15 @@ struct nde_chain_t
hawk_nde_t* tail; hawk_nde_t* tail;
}; };
enum nde_hard_bool_t
{
NDE_HARD_BOOL_UNKNOWN = -1,
NDE_HARD_BOOL_FALSE = 0,
NDE_HARD_BOOL_TRUE = 1
};
typedef enum nde_hard_bool_t nde_hard_bool_t;
static int parse_progunit (hawk_t* hawk); static int parse_progunit (hawk_t* hawk);
static void adjust_static_globals (hawk_t* hawk); static void adjust_static_globals (hawk_t* hawk);
static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name); static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name);
@@ -1100,6 +1109,56 @@ static int compile_funbc_expr_bin_land (hawk_t* hawk, hawk_fbc_t* bc, hawk_nde_e
return COMPILE_FUNBC_EXPR_OK; return COMPILE_FUNBC_EXPR_OK;
} }
static int is_lowerable_funbc_fnc_argspec (const hawk_ooch_t* arg_spec)
{
if (!arg_spec) return 1;
do
{
if (*arg_spec == HAWK_T('r') || *arg_spec == HAWK_T('R') || *arg_spec == HAWK_T('x')) return 0;
}
while (*arg_spec++);
return 1;
}
static int compile_funbc_expr_fncall (hawk_t* hawk, hawk_fbc_t* bc, hawk_nde_fncall_t* call)
{
hawk_nde_t* p;
int n;
switch (call->type)
{
case HAWK_NDE_FNCALL_FNC:
if (call->u.fnc.flags & HAWK_NDE_FNCALL_FNC_DEFERRED_MODFNC) return COMPILE_FUNBC_EXPR_UNSUPPORTED;
if (!is_lowerable_funbc_fnc_argspec(call->u.fnc.spec.arg.spec)) return COMPILE_FUNBC_EXPR_UNSUPPORTED;
break;
case HAWK_NDE_FNCALL_EXPR:
HAWK_ASSERT(call->u.expr.callable != HAWK_NULL);
n = compile_funbc_expr(hawk, bc, call->u.expr.callable);
if (n <= -1) return -1;
if (n == COMPILE_FUNBC_EXPR_UNSUPPORTED) return COMPILE_FUNBC_EXPR_UNSUPPORTED;
break;
case HAWK_NDE_FNCALL_FUN:
break;
default:
return COMPILE_FUNBC_EXPR_UNSUPPORTED;
}
for (p = call->args; p; p = p->next)
{
n = compile_funbc_expr(hawk, bc, p);
if (n <= -1) return -1;
if (n == COMPILE_FUNBC_EXPR_UNSUPPORTED) return COMPILE_FUNBC_EXPR_UNSUPPORTED;
}
if (emit_funbc_ins_nde(hawk, bc, HAWK_FBC_OP_CALL, (hawk_nde_t*)call, &call->loc) <= -1) return -1;
return COMPILE_FUNBC_EXPR_OK;
}
static int compile_funbc_expr (hawk_t* hawk, hawk_fbc_t* bc, hawk_nde_t* nde) static int compile_funbc_expr (hawk_t* hawk, hawk_fbc_t* bc, hawk_nde_t* nde)
{ {
hawk_oow_t rollback; hawk_oow_t rollback;
@@ -1178,6 +1237,18 @@ static int compile_funbc_expr (hawk_t* hawk, hawk_fbc_t* bc, hawk_nde_t* nde)
return COMPILE_FUNBC_EXPR_OK; return COMPILE_FUNBC_EXPR_OK;
} }
case HAWK_NDE_FNCALL_FNC:
case HAWK_NDE_FNCALL_FUN:
case HAWK_NDE_FNCALL_EXPR:
{
int n;
n = compile_funbc_expr_fncall(hawk, bc, (hawk_nde_fncall_t*)nde);
if (n <= -1) goto oops_rollback;
if (n == COMPILE_FUNBC_EXPR_UNSUPPORTED) goto unsupported;
return COMPILE_FUNBC_EXPR_OK;
}
case HAWK_NDE_ASS: case HAWK_NDE_ASS:
{ {
hawk_nde_ass_t* ass = (hawk_nde_ass_t*)nde; hawk_nde_ass_t* ass = (hawk_nde_ass_t*)nde;
@@ -4245,6 +4316,104 @@ oops:
return HAWK_NULL; return HAWK_NULL;
} }
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 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)
{ {
hawk_nde_t* test = HAWK_NULL; hawk_nde_t* test = HAWK_NULL;
@@ -4298,6 +4467,45 @@ static hawk_nde_t* parse_if (hawk_t* hawk, const hawk_loc_t* xloc)
} }
} }
if (is_nde_hard_false(test))
{
/* fold if (0) or if (@false) or its variants */
if (else_part)
{
hawk_clrpt(hawk, test);
hawk_clrpt(hawk, then_part);
return else_part;
}
else
{
hawk_nde_t* null_nde;
null_nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*null_nde));
if (HAWK_UNLIKELY(!null_nde))
{
ADJERR_LOC(hawk, xloc);
goto oops;
}
/* [BE CAREFUL]
* Don't forget reset test and then_part to HAWK_NULL if the control
* skips the immediate return below and reaches further down */
hawk_clrpt(hawk, test);
hawk_clrpt(hawk, then_part);
null_nde->type = HAWK_NDE_NULL;
null_nde->loc = *xloc;
return null_nde;
}
}
else if (is_nde_hard_true(test))
{
/* fold the else part for if (1) or if (@true) or its variants */
hawk_clrpt(hawk, test);
if (else_part) hawk_clrpt(hawk, else_part);
return then_part;
}
nde = (hawk_nde_if_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_if_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde)) if (HAWK_UNLIKELY(!nde))
{ {
@@ -4558,6 +4766,26 @@ static hawk_nde_t* parse_while (hawk_t* hawk, const hawk_loc_t* xloc)
body = parse_statement(hawk, &ploc); body = parse_statement(hawk, &ploc);
if (HAWK_UNLIKELY(!body)) goto oops; if (HAWK_UNLIKELY(!body)) goto oops;
if (is_nde_hard_false(test))
{
/* fold while(0) and while(@false) into a null statement. */
hawk_nde_t* null_nde;
null_nde = (hawk_nde_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*null_nde));
if (HAWK_UNLIKELY(!null_nde))
{
ADJERR_LOC(hawk, xloc);
goto oops;
}
hawk_clrpt(hawk, body); body = HAWK_NULL;
hawk_clrpt(hawk, test); test = HAWK_NULL;
null_nde->type = HAWK_NDE_NULL;
null_nde->loc = *xloc;
return null_nde;
}
nde = (hawk_nde_while_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_while_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde)) if (HAWK_UNLIKELY(!nde))
{ {
@@ -5677,195 +5905,235 @@ union folded_t
}; };
typedef union folded_t folded_t; typedef union folded_t folded_t;
static int fold_constants_for_binop ( static HAWK_INLINE int is_nde_numeric_literal (hawk_nde_t* nde)
hawk_t* hawk, hawk_nde_t* left, hawk_nde_t* right,
int opcode, folded_t* folded)
{ {
int fold = -1; return nde->type == HAWK_NDE_INT || nde->type == HAWK_NDE_FLT;
}
/* TODO: can i shorten various comparisons below? static HAWK_INLINE hawk_int_t get_nde_literal_as_int (hawk_nde_t* nde)
* i hate to repeat similar code just for type difference */
if (left->type == HAWK_NDE_INT && right->type == HAWK_NDE_INT)
{ {
fold = HAWK_NDE_INT; return (nde->type == HAWK_NDE_INT)? ((hawk_nde_int_t*)nde)->val: (hawk_int_t)((hawk_nde_flt_t*)nde)->val;
}
static HAWK_INLINE hawk_flt_t get_nde_literal_as_flt (hawk_nde_t* nde)
{
return (nde->type == HAWK_NDE_INT)? (hawk_flt_t)((hawk_nde_int_t*)nde)->val: ((hawk_nde_flt_t*)nde)->val;
}
static HAWK_INLINE int is_safe_shift_count (hawk_int_t n)
{
return n >= 0 && n < HAWK_BITSOF(hawk_int_t);
}
static int fold_constants_for_binop (hawk_t* hawk, hawk_nde_t* left, hawk_nde_t* right, int opcode, folded_t* folded)
{
hawk_int_t li, ri;
hawk_flt_t lf, rf;
int both_int;
if (!is_nde_numeric_literal(left) || !is_nde_numeric_literal(right)) return -1;
li = get_nde_literal_as_int(left);
ri = get_nde_literal_as_int(right);
lf = get_nde_literal_as_flt(left);
rf = get_nde_literal_as_flt(right);
both_int = (left->type == HAWK_NDE_INT && right->type == HAWK_NDE_INT);
switch (opcode) switch (opcode)
{ {
case HAWK_BINOP_PLUS: case HAWK_BINOP_PLUS:
folded->l = INT_BINOP_INT(left,+,right); if (both_int)
break; {
folded->l = li + ri;
return HAWK_NDE_INT;
}
folded->r = lf + rf;
return HAWK_NDE_FLT;
case HAWK_BINOP_MINUS: case HAWK_BINOP_MINUS:
folded->l = INT_BINOP_INT(left,-,right); if (both_int)
break; {
folded->l = li - ri;
return HAWK_NDE_INT;
}
folded->r = lf - rf;
return HAWK_NDE_FLT;
case HAWK_BINOP_MUL: case HAWK_BINOP_MUL:
folded->l = INT_BINOP_INT(left,*,right); if (both_int)
break; {
folded->l = li * ri;
return HAWK_NDE_INT;
}
folded->r = lf * rf;
return HAWK_NDE_FLT;
case HAWK_BINOP_DIV: case HAWK_BINOP_DIV:
if (((hawk_nde_int_t*)right)->val == 0) if (both_int)
{
if (ri == 0)
{ {
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0); hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0);
fold = -2; /* error */ return -2;
} }
else if (INT_BINOP_INT(left,%,right))
if ((li % ri) == 0)
{ {
folded->r = (hawk_flt_t)((hawk_nde_int_t*)left)->val / folded->l = li / ri;
(hawk_flt_t)((hawk_nde_int_t*)right)->val; return HAWK_NDE_INT;
fold = HAWK_NDE_FLT;
} }
else
{ folded->r = (hawk_flt_t)li / (hawk_flt_t)ri;
folded->l = INT_BINOP_INT(left,/,right); return HAWK_NDE_FLT;
} }
break;
folded->r = lf / rf;
return HAWK_NDE_FLT;
case HAWK_BINOP_IDIV: case HAWK_BINOP_IDIV:
if (((hawk_nde_int_t*)right)->val == 0) if (both_int && ri == 0)
{ {
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0); hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0);
fold = -2; /* error */ return -2;
} }
else
{ folded->l = (both_int)? (li / ri): (hawk_int_t)(lf / rf);
folded->l = INT_BINOP_INT(left,/,right); return HAWK_NDE_INT;
}
break;
case HAWK_BINOP_MOD: case HAWK_BINOP_MOD:
folded->l = INT_BINOP_INT(left,%,right); if (both_int)
break; {
if (ri == 0)
{
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0);
return -2;
}
folded->l = li % ri;
return HAWK_NDE_INT;
}
folded->r = hawk->prm.math.mod(hawk, lf, rf);
return HAWK_NDE_FLT;
case HAWK_BINOP_EXP:
if (both_int)
{
if (ri >= 0)
{
hawk_int_t v = 1;
hawk_int_t n = ri;
while (n-- > 0) v *= li;
folded->l = v;
return HAWK_NDE_INT;
}
if (li == 0)
{
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0);
return -2;
}
{
hawk_flt_t v = 1.0;
hawk_int_t n = -ri;
while (n-- > 0) v /= li;
folded->r = v;
return HAWK_NDE_FLT;
}
}
if (right->type == HAWK_NDE_INT)
{
if (ri >= 0)
{
hawk_flt_t v = 1.0;
hawk_int_t n = ri;
while (n-- > 0) v *= lf;
folded->r = v;
return HAWK_NDE_FLT;
}
if (lf == 0.0)
{
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EDIVBY0);
return -2;
}
{
hawk_flt_t v = 1.0;
hawk_int_t n = -ri;
while (n-- > 0) v /= lf;
folded->r = v;
return HAWK_NDE_FLT;
}
}
folded->r = hawk->prm.math.pow(hawk, lf, rf);
return HAWK_NDE_FLT;
case HAWK_BINOP_LS:
if (!is_safe_shift_count(ri)) return -1;
folded->l = li << ri;
return HAWK_NDE_INT;
case HAWK_BINOP_RS:
if (!is_safe_shift_count(ri)) return -1;
folded->l = li >> ri;
return HAWK_NDE_INT;
case HAWK_BINOP_BAND:
folded->l = li & ri;
return HAWK_NDE_INT;
case HAWK_BINOP_BXOR:
folded->l = li ^ ri;
return HAWK_NDE_INT;
case HAWK_BINOP_BOR:
folded->l = li | ri;
return HAWK_NDE_INT;
case HAWK_BINOP_TEQ:
if (left->type != right->type) folded->l = 0;
else if (both_int) folded->l = (li == ri);
else folded->l = (lf == rf);
return HAWK_NDE_INT;
case HAWK_BINOP_TNE:
if (left->type != right->type) folded->l = 1;
else if (both_int) folded->l = (li != ri);
else folded->l = (lf != rf);
return HAWK_NDE_INT;
case HAWK_BINOP_EQ:
folded->l = (both_int)? (li == ri): (lf == rf);
return HAWK_NDE_INT;
case HAWK_BINOP_NE:
folded->l = (both_int)? (li != ri): (lf != rf);
return HAWK_NDE_INT;
case HAWK_BINOP_GT:
folded->l = (both_int)? (li > ri): (lf > rf);
return HAWK_NDE_INT;
case HAWK_BINOP_GE:
folded->l = (both_int)? (li >= ri): (lf >= rf);
return HAWK_NDE_INT;
case HAWK_BINOP_LT:
folded->l = (both_int)? (li < ri): (lf < rf);
return HAWK_NDE_INT;
case HAWK_BINOP_LE:
folded->l = (both_int)? (li <= ri): (lf <= rf);
return HAWK_NDE_INT;
default: default:
fold = -1; /* no folding */ return -1;
break;
} }
} }
else if (left->type == HAWK_NDE_FLT && right->type == HAWK_NDE_FLT)
{
fold = HAWK_NDE_FLT;
switch (opcode)
{
case HAWK_BINOP_PLUS:
folded->r = FLT_BINOP_FLT(left,+,right);
break;
case HAWK_BINOP_MINUS:
folded->r = FLT_BINOP_FLT(left,-,right);
break;
case HAWK_BINOP_MUL:
folded->r = FLT_BINOP_FLT(left,*,right);
break;
case HAWK_BINOP_DIV:
folded->r = FLT_BINOP_FLT(left,/,right);
break;
case HAWK_BINOP_IDIV:
folded->l = (hawk_int_t)FLT_BINOP_FLT(left,/,right);
fold = HAWK_NDE_INT;
break;
case HAWK_BINOP_MOD:
folded->r = hawk->prm.math.mod(
hawk,
((hawk_nde_flt_t*)left)->val,
((hawk_nde_flt_t*)right)->val
);
break;
default:
fold = -1;
break;
}
}
else if (left->type == HAWK_NDE_INT && right->type == HAWK_NDE_FLT)
{
fold = HAWK_NDE_FLT;
switch (opcode)
{
case HAWK_BINOP_PLUS:
folded->r = INT_BINOP_FLT(left,+,right);
break;
case HAWK_BINOP_MINUS:
folded->r = INT_BINOP_FLT(left,-,right);
break;
case HAWK_BINOP_MUL:
folded->r = INT_BINOP_FLT(left,*,right);
break;
case HAWK_BINOP_DIV:
folded->r = INT_BINOP_FLT(left,/,right);
break;
case HAWK_BINOP_IDIV:
folded->l = (hawk_int_t)
((hawk_flt_t)((hawk_nde_int_t*)left)->val /
((hawk_nde_flt_t*)right)->val);
fold = HAWK_NDE_INT;
break;
case HAWK_BINOP_MOD:
folded->r = hawk->prm.math.mod(
hawk,
(hawk_flt_t)((hawk_nde_int_t*)left)->val,
((hawk_nde_flt_t*)right)->val
);
break;
default:
fold = -1;
break;
}
}
else if (left->type == HAWK_NDE_FLT && right->type == HAWK_NDE_INT)
{
fold = HAWK_NDE_FLT;
switch (opcode)
{
case HAWK_BINOP_PLUS:
folded->r = FLT_BINOP_INT(left,+,right);
break;
case HAWK_BINOP_MINUS:
folded->r = FLT_BINOP_INT(left,-,right);
break;
case HAWK_BINOP_MUL:
folded->r = FLT_BINOP_INT(left,*,right);
break;
case HAWK_BINOP_DIV:
folded->r = FLT_BINOP_INT(left,/,right);
break;
case HAWK_BINOP_IDIV:
folded->l = (hawk_int_t)
(((hawk_nde_int_t*)left)->val /
(hawk_flt_t)((hawk_nde_int_t*)right)->val);
fold = HAWK_NDE_INT;
break;
case HAWK_BINOP_MOD:
folded->r = hawk->prm.math.mod(
hawk,
((hawk_nde_flt_t*)left)->val,
(hawk_flt_t)((hawk_nde_int_t*)right)->val
);
break;
default:
fold = -1;
break;
}
}
return fold;
}
static hawk_nde_t* new_exp_bin_node ( static hawk_nde_t* new_exp_bin_node (
hawk_t* hawk, const hawk_loc_t* loc, hawk_t* hawk, const hawk_loc_t* loc,
@@ -5919,6 +6187,21 @@ static hawk_nde_t* new_flt_node (hawk_t* hawk, hawk_flt_t rv, const hawk_loc_t*
return (hawk_nde_t*)tmp; return (hawk_nde_t*)tmp;
} }
static hawk_nde_t* new_xbool_node (hawk_t* hawk, int bv, const hawk_loc_t* loc)
{
hawk_nde_xnil_t* tmp;
tmp = (hawk_nde_xnil_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*tmp));
if (HAWK_LIKELY(tmp))
{
tmp->type = bv? HAWK_NDE_XTRUE: HAWK_NDE_XFALSE;
tmp->loc = *loc;
}
else ADJERR_LOC(hawk, loc);
return (hawk_nde_t*)tmp;
}
static HAWK_INLINE void update_int_node (hawk_t* hawk, hawk_nde_int_t* node, hawk_int_t lv) static HAWK_INLINE void update_int_node (hawk_t* hawk, hawk_nde_int_t* node, hawk_int_t lv)
{ {
node->val = lv; node->val = lv;
@@ -6342,6 +6625,19 @@ static hawk_nde_t* parse_unary (hawk_t* hawk, const hawk_loc_t* xloc)
hawk->parse.depth.expr--; hawk->parse.depth.expr--;
if (left == HAWK_NULL) return HAWK_NULL; if (left == HAWK_NULL) return HAWK_NULL;
if (opcode == HAWK_UNROP_LNOT)
{
/* handle the logical negation operator(!) first */
nde_hard_bool_t hb;
hb = classify_nde_hard_bool(left);
if (hb != NDE_HARD_BOOL_UNKNOWN)
{
hawk_clrpt(hawk, left);
return new_xbool_node(hawk, hb == NDE_HARD_BOOL_FALSE, xloc);
}
}
fold = -1; fold = -1;
if (left->type == HAWK_NDE_INT) if (left->type == HAWK_NDE_INT)
{ {
@@ -6356,9 +6652,11 @@ static hawk_nde_t* parse_unary (hawk_t* hawk, const hawk_loc_t* xloc)
folded.l = -((hawk_nde_int_t*)left)->val; folded.l = -((hawk_nde_int_t*)left)->val;
break; break;
#if 0
case HAWK_UNROP_LNOT: case HAWK_UNROP_LNOT:
folded.l = !((hawk_nde_int_t*)left)->val; folded.l = !((hawk_nde_int_t*)left)->val;
break; break;
#endif
case HAWK_UNROP_BNOT: case HAWK_UNROP_BNOT:
folded.l = ~((hawk_nde_int_t*)left)->val; folded.l = ~((hawk_nde_int_t*)left)->val;
@@ -6382,9 +6680,12 @@ static hawk_nde_t* parse_unary (hawk_t* hawk, const hawk_loc_t* xloc)
folded.r = -((hawk_nde_flt_t*)left)->val; folded.r = -((hawk_nde_flt_t*)left)->val;
break; break;
#if 0
case HAWK_UNROP_LNOT: case HAWK_UNROP_LNOT:
folded.r = !((hawk_nde_flt_t*)left)->val; folded.l = !((hawk_nde_flt_t*)left)->val;
fold = HAWK_NDE_INT;
break; break;
#endif
case HAWK_UNROP_BNOT: case HAWK_UNROP_BNOT:
folded.l = ~((hawk_int_t)((hawk_nde_flt_t*)left)->val); folded.l = ~((hawk_int_t)((hawk_nde_flt_t*)left)->val);
@@ -10111,11 +10412,40 @@ static int dump_funbc_ins (hawk_t* hawk, hawk_oow_t pc, const hawk_fbc_ins_t* in
case HAWK_FBC_OP_JMP: case HAWK_FBC_OP_JMP:
case HAWK_FBC_OP_JZ: case HAWK_FBC_OP_JZ:
case HAWK_FBC_OP_CALL:
if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1 || if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1 ||
put_oow_as_dec(hawk, ins->u.idx) <= -1) return -1; put_oow_as_dec(hawk, ins->u.idx) <= -1) return -1;
break; break;
case HAWK_FBC_OP_CALL:
{
hawk_nde_fncall_t* call = (hawk_nde_fncall_t*)ins->u.nde;
const hawk_ooch_t* kind = HAWK_T("?");
if (!call)
{
if (hawk_putsrcoocstr(hawk, HAWK_T(" <null-call>")) <= -1) return -1;
break;
}
switch (call->type)
{
case HAWK_NDE_FNCALL_FNC: kind = HAWK_T("fnc"); break;
case HAWK_NDE_FNCALL_FUN: kind = HAWK_T("fun"); break;
case HAWK_NDE_FNCALL_EXPR: kind = HAWK_T("expr"); break;
default: break;
}
if (hawk_putsrcoocstr(hawk, HAWK_T(" ")) <= -1 ||
hawk_putsrcoocstr(hawk, kind) <= -1 ||
hawk_putsrcoocstr(hawk, HAWK_T(" nargs=")) <= -1 ||
put_oow_as_dec(hawk, call->nargs) <= -1 ||
hawk_putsrcoocstr(hawk, HAWK_T(" @")) <= -1 ||
put_oow_as_dec(hawk, call->loc.line) <= -1 ||
hawk_putsrcoocstr(hawk, HAWK_T(":")) <= -1 ||
put_oow_as_dec(hawk, call->loc.colm) <= -1) return -1;
break;
}
case HAWK_FBC_OP_INIT_BLK: case HAWK_FBC_OP_INIT_BLK:
{ {
hawk_oow_t start, end; hawk_oow_t start, end;
+3 -3
View File
@@ -54,15 +54,15 @@ int hawk_rtx_readiobytes (
int hawk_rtx_writeioval ( int hawk_rtx_writeioval (
hawk_rtx_t* rtx, hawk_out_type_t out_type, hawk_rtx_t* rtx, hawk_out_type_t out_type,
const hawk_ooch_t* name, hawk_val_t* v); const hawk_ooch_t* name, const hawk_val_t* v);
int hawk_rtx_writeiostr ( int hawk_rtx_writeiostr (
hawk_rtx_t* rtx, hawk_out_type_t out_type, hawk_rtx_t* rtx, hawk_out_type_t out_type,
const hawk_ooch_t* name, hawk_ooch_t* str, hawk_oow_t len); const hawk_ooch_t* name, const hawk_ooch_t* str, hawk_oow_t len);
int hawk_rtx_writeiobytes ( int hawk_rtx_writeiobytes (
hawk_rtx_t* rtx, hawk_out_type_t out_type, hawk_rtx_t* rtx, hawk_out_type_t out_type,
const hawk_ooch_t* name, hawk_bch_t* str, hawk_oow_t len); const hawk_ooch_t* name, const hawk_bch_t* str, hawk_oow_t len);
int hawk_rtx_flushio ( int hawk_rtx_flushio (
hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name); hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name);
+5 -5
View File
@@ -1138,7 +1138,7 @@ int hawk_rtx_readiobytes (hawk_rtx_t* rtx, hawk_in_type_t in_type, const hawk_oo
} }
int hawk_rtx_writeioval (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, hawk_val_t* v) int hawk_rtx_writeioval (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, const hawk_val_t* v)
{ {
hawk_val_type_t vtype; hawk_val_type_t vtype;
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_RTX_GETVALTYPE(rtx, v);
@@ -1275,7 +1275,7 @@ static int prepare_for_write_io_data (hawk_rtx_t* rtx, hawk_out_type_t out_type,
return 1; return 1;
} }
int hawk_rtx_writeiostr (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, hawk_ooch_t* str, hawk_oow_t len) int hawk_rtx_writeiostr (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, const hawk_ooch_t* str, hawk_oow_t len)
{ {
int x; int x;
write_io_data_t wid; write_io_data_t wid;
@@ -1286,7 +1286,7 @@ int hawk_rtx_writeiostr (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_o
{ {
hawk_ooi_t n; hawk_ooi_t n;
n = wid.handler(rtx, HAWK_RIO_CMD_WRITE, wid.p, str, len); n = wid.handler(rtx, HAWK_RIO_CMD_WRITE, wid.p, (void*)str, len);
if (n <= -1) return -1; if (n <= -1) return -1;
if (n == 0) if (n == 0)
@@ -1302,7 +1302,7 @@ int hawk_rtx_writeiostr (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_o
return 1; return 1;
} }
int hawk_rtx_writeiobytes (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, hawk_bch_t* str, hawk_oow_t len) int hawk_rtx_writeiobytes (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_ooch_t* name, const hawk_bch_t* str, hawk_oow_t len)
{ {
int x; int x;
write_io_data_t wid; write_io_data_t wid;
@@ -1313,7 +1313,7 @@ int hawk_rtx_writeiobytes (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk
{ {
hawk_ooi_t n; hawk_ooi_t n;
n = wid.handler(rtx, HAWK_RIO_CMD_WRITE_BYTES, wid.p, str, len); n = wid.handler(rtx, HAWK_RIO_CMD_WRITE_BYTES, wid.p, (void*)str, len);
if (n <= -1) return -1; if (n <= -1) return -1;
if (n == 0) if (n == 0)
+150 -25
View File
@@ -84,6 +84,7 @@ static int init_globals (hawk_rtx_t* rtx);
static void refdown_globals (hawk_rtx_t* rtx, int pop); static void refdown_globals (hawk_rtx_t* rtx, int pop);
static void fbc_eval_stack_fini (hawk_rtx_t* rtx, hawk_fbc_eval_stack_t* stack); static void fbc_eval_stack_fini (hawk_rtx_t* rtx, hawk_fbc_eval_stack_t* stack);
static hawk_val_t* fbc_eval_stack_pop (hawk_fbc_eval_stack_t* stack);
static int run_pblocks (hawk_rtx_t* rtx); static int run_pblocks (hawk_rtx_t* rtx);
static int run_pblock_chain (hawk_rtx_t* rtx, hawk_chain_t* cha); static int run_pblock_chain (hawk_rtx_t* rtx, hawk_chain_t* cha);
@@ -1463,12 +1464,12 @@ hawk_mod_t* hawk_rtx_querymodulewithoocs (hawk_rtx_t* rtx, const hawk_oocs_t* na
/* the logic here must match hawk_querymodulewithoocs() in parse.c */ /* the logic here must match hawk_querymodulewithoocs() in parse.c */
dc = hawk_find_oochars_in_oochars(name->ptr, name->len, HAWK_T("::"), 2, 0); dc = hawk_find_oochars_in_oochars(name->ptr, name->len, HAWK_T("::"), 2, 0);
HAWK_ASSERT(dc != HAWK_NULL); HAWK_ASSERT(dc != HAWK_NULL);
if (HAWK_UNLIKELY(!dc)) goto internal_error_unrolling; if (HAWK_UNLIKELY(!dc)) goto internal_error_unrolling; /* this must not happend but .. */
len = dc - name->ptr; len = dc - name->ptr;
pair = hawk_rbt_search(rtx->modtab, name->ptr, len); pair = hawk_rbt_search(rtx->modtab, name->ptr, len);
HAWK_ASSERT(pair != HAWK_NULL); HAWK_ASSERT(pair != HAWK_NULL);
if (HAWK_UNLIKELY(!pair)) if (HAWK_UNLIKELY(!pair)) /* this must not happen but .. */
{ {
internal_error_unrolling: internal_error_unrolling:
hawk_rtx_seterrbfmt(rtx, HAWK_NULL, HAWK_EINTERN, hawk_rtx_seterrbfmt(rtx, HAWK_NULL, HAWK_EINTERN,
@@ -1480,9 +1481,9 @@ hawk_mod_t* hawk_rtx_querymodulewithoocs (hawk_rtx_t* rtx, const hawk_oocs_t* na
/* skip the fini callback because the init callback returned failure. not calling m->fini(). /* skip the fini callback because the init callback returned failure. not calling m->fini().
* invoke the unload() callback if needed and unload the module itself. */ * invoke the unload() callback if needed and unload the module itself. */
hawk_modtab_unload_module(rtx->modtab, pair, rtx->hawk); hawk_modtab_unload_module(rtx->modtab, pair, rtx->hawk);
hawk_rbt_delete(rtx->modtab, name->ptr, len);
} }
hawk_rbt_delete(rtx->modtab, name->ptr, len);
m = HAWK_NULL; /* indicate failure */ m = HAWK_NULL; /* indicate failure */
} }
} }
@@ -1493,7 +1494,7 @@ hawk_mod_t* hawk_rtx_querymodulewithoocs (hawk_rtx_t* rtx, const hawk_oocs_t* na
hawk_mod_t* hawk_rtx_querymodulewithname (hawk_rtx_t* rtx, const hawk_ooch_t* name, hawk_mod_sym_t* sym, int flags) hawk_mod_t* hawk_rtx_querymodulewithname (hawk_rtx_t* rtx, const hawk_ooch_t* name, hawk_mod_sym_t* sym, int flags)
{ {
hawk_oocs_t oocs; hawk_oocs_t oocs;
oocs.ptr = name; oocs.ptr = (hawk_ooch_t*)name;
oocs.len = hawk_count_oocstr(name); oocs.len = hawk_count_oocstr(name);
return hawk_rtx_querymodulewithoocs(rtx, &oocs, sym, flags); return hawk_rtx_querymodulewithoocs(rtx, &oocs, sym, flags);
} }
@@ -1717,7 +1718,6 @@ static int run_blocks_for_bpae_loop (hawk_rtx_t* rtx, hawk_nde_t* blk_head, int
static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx) static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx)
{ {
hawk_nde_t* nde;
hawk_oow_t nargs, i; hawk_oow_t nargs, i;
hawk_val_t* retv; hawk_val_t* retv;
int ret = 0; int ret = 0;
@@ -2668,15 +2668,10 @@ static int call_signal_handlers (hawk_rtx_t* rtx)
} \ } \
} while(0) } while(0)
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde) static HAWK_INLINE int run_pending_signal_handlers (hawk_rtx_t* rtx)
{ {
int xret; if (rtx->sig_handling) return 0;
hawk_val_t* tmp;
ON_STATEMENT(rtx, nde);
if (!rtx->sig_handling)
{
/* run singal handlers if there are raised signals */ /* run singal handlers if there are raised signals */
#if defined(HAWK_ATOMIC_LOAD) #if defined(HAWK_ATOMIC_LOAD)
if (HAWK_ATOMIC_LOAD(&rtx->sig_pending_any, HAWK_ATOMIC_RELAXED) != 0 && if (HAWK_ATOMIC_LOAD(&rtx->sig_pending_any, HAWK_ATOMIC_RELAXED) != 0 &&
@@ -2689,8 +2684,18 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
* modern compilers should support the atomic primitives. */ * modern compilers should support the atomic primitives. */
if (rtx->sig_pending_any && call_signal_handlers(rtx) <= -1) return -1; if (rtx->sig_pending_any && call_signal_handlers(rtx) <= -1) return -1;
#endif #endif
return 0;
} }
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
{
int xret;
hawk_val_t* tmp;
ON_STATEMENT(rtx, nde);
if (run_pending_signal_handlers(rtx) <= -1) return -1;
/* run the actual statement */ /* run the actual statement */
switch (nde->type) switch (nde->type)
{ {
@@ -3862,9 +3867,7 @@ static int run_reset (hawk_rtx_t* rtx, hawk_nde_reset_t* nde)
} }
} }
static int io_val_to_str ( static int io_val_to_str (hawk_rtx_t* rtx, hawk_val_t* v, const hawk_loc_t* loc, hawk_oocs_t* dst, int seterr)
hawk_rtx_t* rtx, hawk_val_t* v, const hawk_loc_t* loc,
hawk_oocs_t* dst, int seterr)
{ {
dst->ptr = hawk_rtx_getvaloocstr(rtx, v, &dst->len); dst->ptr = hawk_rtx_getvaloocstr(rtx, v, &dst->len);
if (HAWK_UNLIKELY(!dst->ptr)) return -1; if (HAWK_UNLIKELY(!dst->ptr)) return -1;
@@ -3910,9 +3913,7 @@ static hawk_val_t* io_nde_to_str(hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_oocs_t*
return v; return v;
} }
static int fbc_write_print_str ( static int fbc_write_print_str (hawk_rtx_t* rtx, hawk_nde_print_t* nde, const hawk_ooch_t* ptr, hawk_oow_t len, hawk_val_t* out_v)
hawk_rtx_t* rtx, hawk_nde_print_t* nde, const hawk_ooch_t* ptr, hawk_oow_t len,
hawk_val_t* out_v)
{ {
hawk_oocs_t out; hawk_oocs_t out;
int n; int n;
@@ -7602,10 +7603,8 @@ static hawk_val_t* eval_fncall_fnc (hawk_rtx_t* rtx, hawk_nde_t* nde)
return hawk_rtx_evalcall(rtx, call, HAWK_NULL, push_arg_from_nde, (void*)call->u.fnc.spec.arg.spec, HAWK_NULL, HAWK_NULL); return hawk_rtx_evalcall(rtx, call, HAWK_NULL, push_arg_from_nde, (void*)call->u.fnc.spec.arg.spec, HAWK_NULL, HAWK_NULL);
} }
static HAWK_INLINE hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde) static HAWK_INLINE hawk_fun_t* resolve_fncall_fun (hawk_rtx_t* rtx, hawk_nde_fncall_t* call)
{ {
/* user-defined function */
hawk_nde_fncall_t* call = (hawk_nde_fncall_t*)nde;
hawk_fun_t* fun; hawk_fun_t* fun;
#if defined(HAWK_ATOMIC_CAS_BOOL) #if defined(HAWK_ATOMIC_CAS_BOOL)
hawk_fun_t* expected; hawk_fun_t* expected;
@@ -7628,7 +7627,7 @@ static HAWK_INLINE hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde
pair = hawk_htb_search(rtx->hawk->tree.funs, call->u.fun.name.ptr, call->u.fun.name.len); pair = hawk_htb_search(rtx->hawk->tree.funs, call->u.fun.name.ptr, call->u.fun.name.len);
if (!pair) if (!pair)
{ {
hawk_rtx_seterrfmt(rtx, &nde->loc, HAWK_EFUNNF, HAWK_T("function '%.*js' not found"), call->u.fun.name.len, call->u.fun.name.ptr); hawk_rtx_seterrfmt(rtx, &call->loc, HAWK_EFUNNF, HAWK_T("function '%.*js' not found"), call->u.fun.name.len, call->u.fun.name.ptr);
return HAWK_NULL; return HAWK_NULL;
} }
@@ -7661,12 +7660,22 @@ static HAWK_INLINE hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde
if (call->nargs > fun->nargs && !fun->variadic) if (call->nargs > fun->nargs && !fun->variadic)
{ {
/* TODO: is this correct? what if i want to hawk_rtx_seterrfmt(rtx, &call->loc, HAWK_EARGTM, HAWK_T("too many arguments to '%.*js'"), fun->name.len, fun->name.ptr);
* allow arbitarary numbers of arguments? */
hawk_rtx_seterrfmt(rtx, &nde->loc, HAWK_EARGTM, HAWK_T("too many arguments to '%.*js'"), fun->name.len, fun->name.ptr);
return HAWK_NULL; return HAWK_NULL;
} }
return fun;
}
static HAWK_INLINE hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde)
{
/* user-defined function */
hawk_nde_fncall_t* call = (hawk_nde_fncall_t*)nde;
hawk_fun_t* fun;
fun = resolve_fncall_fun(rtx, call);
if (!fun) return HAWK_NULL;
/* push_arg_from_nde() has special handling for references when the function /* push_arg_from_nde() has special handling for references when the function
* argument spec contains 'r' or 'R'. * argument spec contains 'r' or 'R'.
* a reference is passed to a built-in function as a reference value * a reference is passed to a built-in function as a reference value
@@ -7747,6 +7756,114 @@ static hawk_val_t* eval_fncall_var (hawk_rtx_t* rtx, hawk_nde_t* nde)
return rv; return rv;
} }
static hawk_val_t* fbc_eval_call (hawk_rtx_t* rtx, hawk_fbc_eval_stack_t* evstk, hawk_nde_fncall_t* call)
{
hawk_val_t* args_fixed[8];
hawk_val_t** args = args_fixed;
hawk_val_t* callee_val = HAWK_NULL;
hawk_val_t* rv = HAWK_NULL;
hawk_fun_t* fun = HAWK_NULL;
struct pafv_t pafv;
hawk_oow_t i;
if (!call)
{
hawk_rtx_seterrnum(rtx, HAWK_NULL, HAWK_EINTERN);
return HAWK_NULL;
}
if (call->nargs > HAWK_COUNTOF(args_fixed))
{
args = (hawk_val_t**)hawk_rtx_allocmem(rtx, call->nargs * HAWK_SIZEOF(*args));
if (HAWK_UNLIKELY(!args)) return HAWK_NULL;
}
for (i = 0; i < call->nargs; i++) args[i] = HAWK_NULL;
for (i = call->nargs; i > 0; i--)
{
args[i - 1] = fbc_eval_stack_pop(evstk);
if (!args[i - 1])
{
hawk_rtx_seterrnum(rtx, HAWK_NULL, HAWK_EINTERN);
goto oops;
}
}
/* this function combines the subset of these three functions:
* eval_fncall_fnc(), eval_fncall_fun(), eval_fncall_var() */
switch (call->type)
{
case HAWK_NDE_FNCALL_FNC: /* builtin function */
if (call->u.fnc.flags & HAWK_NDE_FNCALL_FNC_DEFERRED_MODFNC)
{
hawk_rtx_seterrnum(rtx, &call->loc, HAWK_EINTERN);
goto oops;
}
HAWK_ASSERT(call->nargs >= call->u.fnc.spec.arg.min && call->nargs <= call->u.fnc.spec.arg.max);
break;
case HAWK_NDE_FNCALL_FUN: /* pure hawk function */
fun = resolve_fncall_fun(rtx, call);
if (!fun) goto oops;
break;
case HAWK_NDE_FNCALL_EXPR: /* function pointed to by another variable or a return value of another call, etc */
callee_val = fbc_eval_stack_pop(evstk); /* the stack top has the callee expression result */
if (!callee_val)
{
hawk_rtx_seterrnum(rtx, HAWK_NULL, HAWK_EINTERN);
goto oops;
}
fun = hawk_rtx_valtofun(rtx, callee_val);
if (!fun)
{
if (hawk_rtx_geterrnum(rtx) == HAWK_EINVAL)
{
if (nde_is_var(call->u.expr.callable))
{
hawk_nde_var_t* v = (hawk_nde_var_t*)call->u.expr.callable;
hawk_rtx_seterrfmt(rtx, &call->loc, HAWK_ENOTFUN, HAWK_T("non-function value in '%.*js'"), v->id.name.len, v->id.name.ptr);
}
else
{
hawk_rtx_seterrnum(rtx, &call->loc, HAWK_ENOTFUN);
}
}
ADJERR_LOC(rtx, &call->loc);
goto oops;
}
if (call->nargs > fun->nargs && !fun->variadic)
{
hawk_rtx_seterrfmt(rtx, &call->loc, HAWK_EARGTM, HAWK_T("too many arguments to '%.*js'"), fun->name.len, fun->name.ptr);
goto oops;
}
break;
default:
hawk_rtx_seterrnum(rtx, &call->loc, HAWK_EINTERN);
goto oops;
}
/* TODO: this implementation is extremely inefficient... we must be able to call hawk_rtx_evalcall without push_arg_from_vals... */
pafv.args = args;
pafv.nargs = call->nargs;
pafv.argspec = HAWK_NULL;
pafv.argspeclen = 0;
rv = hawk_rtx_evalcall(rtx, call, fun, push_arg_from_vals, (void*)&pafv, HAWK_NULL, HAWK_NULL);
oops:
if (callee_val) hawk_rtx_refdownval(rtx, callee_val);
for (i = 0; i < call->nargs; i++)
{
if (args[i]) hawk_rtx_refdownval(rtx, args[i]);
}
if (args != args_fixed) hawk_rtx_freemem(rtx, args);
return rv;
}
static void fbc_eval_stack_unwind (hawk_rtx_t* rtx, hawk_fbc_eval_stack_t* stack, hawk_oow_t base) static void fbc_eval_stack_unwind (hawk_rtx_t* rtx, hawk_fbc_eval_stack_t* stack, hawk_oow_t base)
{ {
while (stack->len > base) while (stack->len > base)
@@ -7882,6 +7999,8 @@ static int run_funbc (hawk_rtx_t* rtx, hawk_fun_t* fun)
hawk_fbc_ins_t* ins = &bc->code[pc]; hawk_fbc_ins_t* ins = &bc->code[pc];
hawk_val_t* val; hawk_val_t* val;
if (HAWK_UNLIKELY(run_pending_signal_handlers(rtx) <= -1)) goto oops;
/*hawk_logbfmt(rtx->hawk, HAWK_LOG_STDERR, "opcode = 0x%x [%d]\n", ins->opcode, ins->opcode);*/ /*hawk_logbfmt(rtx->hawk, HAWK_LOG_STDERR, "opcode = 0x%x [%d]\n", ins->opcode, ins->opcode);*/
switch (ins->opcode) switch (ins->opcode)
{ {
@@ -8252,6 +8371,12 @@ static int run_funbc (hawk_rtx_t* rtx, hawk_fun_t* fun)
hawk_rtx_refdownval(rtx, val); hawk_rtx_refdownval(rtx, val);
break; break;
case HAWK_FBC_OP_CALL:
val = fbc_eval_call(rtx, evstk, (hawk_nde_fncall_t*)ins->u.nde);
if (HAWK_UNLIKELY(!val)) goto oops;
if (fbc_eval_stack_push(rtx, evstk, val) <= -1) goto oops;
break;
case HAWK_FBC_OP_RET: case HAWK_FBC_OP_RET:
val = fbc_eval_stack_pop(evstk); val = fbc_eval_stack_pop(evstk);
if (!val) if (!val)
+1 -1
View File
@@ -20,7 +20,7 @@ endif
check_SCRIPTS += h-003.hawk h-004.hawk h-009.hawk h-010.hawk \ check_SCRIPTS += h-003.hawk h-004.hawk h-009.hawk h-010.hawk \
h-011.hawk h-012.hawk h-013.hawk h-014.hawk h-015.hawk \ h-011.hawk h-012.hawk h-013.hawk h-014.hawk h-015.hawk \
h-016.hawk h-017.hawk h-018.hawk h-019.hawk h-020.hawk \ h-016.hawk h-017.hawk h-018.hawk h-019.hawk h-020.hawk \
h-021.hawk h-021.hawk h-022.hawk h-023.hawk
check_SCRIPTS += regress-filename.sh check_SCRIPTS += regress-filename.sh
+1 -1
View File
@@ -650,7 +650,7 @@ LIBADD_COMMON = ../lib/libhawk.la $(LIBM)
check_SCRIPTS = $(am__append_1) h-003.hawk h-004.hawk h-009.hawk \ check_SCRIPTS = $(am__append_1) h-003.hawk h-004.hawk h-009.hawk \
h-010.hawk h-011.hawk h-012.hawk h-013.hawk h-014.hawk \ h-010.hawk h-011.hawk h-012.hawk h-013.hawk h-014.hawk \
h-015.hawk h-016.hawk h-017.hawk h-018.hawk h-019.hawk \ h-015.hawk h-016.hawk h-017.hawk h-018.hawk h-019.hawk \
h-020.hawk h-021.hawk regress-filename.sh h-020.hawk h-021.hawk h-022.hawk h-023.hawk regress-filename.sh
check_ERRORS = e-001.err check_ERRORS = e-001.err
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \ EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \ journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \
+58
View File
@@ -0,0 +1,58 @@
@pragma implicit off
@pragma pedantic on
@pragma entry main
@pragma xcall on
@include "tap.inc";
@global G = func(a, b) {
return a + b
}
@global seq;
function mark(v)
{
seq = seq sprintf("%d", v);
return v;
}
function pair(a, b)
{
return a * 10 + b;
}
function zero()
{
return 7;
}
function bump(&x)
{
x += 1;
return x;
}
function main()
{
@local v, s, f;
seq = "";
tap_ensure(pair(mark(1), mark(2)), 12, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(seq, "12", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(zero(), 7, @SCRIPTNAME, @SCRIPTLINE);
s = sprintf("%d/%d", pair(3, 4), zero());
tap_ensure(s, "34/7", @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(G(5, 6), 11, @SCRIPTNAME, @SCRIPTLINE);
f = G;
tap_ensure(f(7, 8), 15, @SCRIPTNAME, @SCRIPTLINE);
v = 9;
tap_ensure(bump(v), 10, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(v, 10, @SCRIPTNAME, @SCRIPTLINE);
tap_end();
}
+124
View File
@@ -0,0 +1,124 @@
@pragma entry main
@pragma implicit off
@include "tap.inc";
@global g_calls = 0;
function tick (v)
{
g_calls = g_calls + 1;
return v;
}
function main ()
{
@local i, j, k, l, m, n, o, p, q, r;
i = 0;
j = 0;
k = 0;
l = 0;
m = 0;
n = 0;
o = 0;
p = 0;
q = 0;
r = 0;
while (0) { i = i + 1; }
while (@false) { j = j + 1; }
while ((0)) { k = k + 1; }
while ((@false)) { l = l + 1; }
tap_ensure(i, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(j, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(k, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(l, 0, @SCRIPTNAME, @SCRIPTLINE);
if ((1, 0))
m = 1;
else
m = 2;
if (((0, "", 5)))
n = 1;
else
n = 2;
if (((1, 2, @false)))
o = 1;
else
o = 2;
if ((((1, 2), (3, 4), 0)))
p = 1;
else
p = 2;
while ((1, 0)) { q = q + 1; }
while ((((1, 2), (3, 4), 0))) { r = r + 1; }
tap_ensure(m, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(n, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(o, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(p, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(q, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 ^ 10, 1024, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 ^ -3, 0.125, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(7.5 \ 2, 3, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(8.5 / 2, 4.25, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(17 % 5, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(17.5 % 5, 2.5, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(6 & 3, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(6 ^^ 3, 5, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(6 | 3, 7, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(3 << 4, 48, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(48 >> 4, 3, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(6.9 & 3, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(8 >> 1.9, 4, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 == 2.0, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 != 2.0, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 < 2.5, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2.5 >= 2, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 === 2.0, 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(2 !== 2.0, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!@true === @false, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!@false === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!@nil === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!"" === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!"x" === @false, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!@b"" === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!@b"x" === @false, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!((1, 0)) === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(!((1, 2, "x")) === @false, 1, @SCRIPTNAME, @SCRIPTLINE);
g_calls = 0;
if ((tick(1), 0))
m = 10;
else
m = 20;
tap_ensure(m, 20, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(g_calls, 1, @SCRIPTNAME, @SCRIPTLINE);
g_calls = 0;
if ((((1, tick(0))), 1))
n = 10;
else
n = 20;
tap_ensure(n, 10, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(g_calls, 1, @SCRIPTNAME, @SCRIPTLINE);
g_calls = 0;
while ((tick(1), 0)) { o = o + 1; }
tap_ensure(o, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(g_calls, 1, @SCRIPTNAME, @SCRIPTLINE);
g_calls = 0;
tap_ensure(!(tick(1), 0) === @true, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure(g_calls, 1, @SCRIPTNAME, @SCRIPTLINE);
tap_end ();
}