Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 479b74d1a3 | |||
| f444cc92fe | |||
| b5464605d8 | |||
| 9e5804a15b | |||
| ecc1c4bfb3 | |||
| 1428e7dc2f |
@@ -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.
|
||||||
|
|
||||||
|
|||||||
+538
-208
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,28 +2668,33 @@ static int call_signal_handlers (hawk_rtx_t* rtx)
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
static HAWK_INLINE int run_pending_signal_handlers (hawk_rtx_t* rtx)
|
||||||
|
{
|
||||||
|
if (rtx->sig_handling) return 0;
|
||||||
|
|
||||||
|
/* run singal handlers if there are raised signals */
|
||||||
|
#if defined(HAWK_ATOMIC_LOAD)
|
||||||
|
if (HAWK_ATOMIC_LOAD(&rtx->sig_pending_any, HAWK_ATOMIC_RELAXED) != 0 &&
|
||||||
|
call_signal_handlers(rtx) <= -1) return -1;
|
||||||
|
#else
|
||||||
|
/* NOTE:
|
||||||
|
* rtx->sig_pending_any accessed non-atomically without mutex concurrently
|
||||||
|
* from multiple threads(e.g. hawk_rtx_raisesig() called from a different
|
||||||
|
* thread) is undefined behavior. but ignore this path as i believe most
|
||||||
|
* modern compilers should support the atomic primitives. */
|
||||||
|
if (rtx->sig_pending_any && call_signal_handlers(rtx) <= -1) return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||||
{
|
{
|
||||||
int xret;
|
int xret;
|
||||||
hawk_val_t* tmp;
|
hawk_val_t* tmp;
|
||||||
|
|
||||||
ON_STATEMENT(rtx, nde);
|
ON_STATEMENT(rtx, nde);
|
||||||
|
if (run_pending_signal_handlers(rtx) <= -1) return -1;
|
||||||
if (!rtx->sig_handling)
|
|
||||||
{
|
|
||||||
/* run singal handlers if there are raised signals */
|
|
||||||
#if defined(HAWK_ATOMIC_LOAD)
|
|
||||||
if (HAWK_ATOMIC_LOAD(&rtx->sig_pending_any, HAWK_ATOMIC_RELAXED) != 0 &&
|
|
||||||
call_signal_handlers(rtx) <= -1) return -1;
|
|
||||||
#else
|
|
||||||
/* NOTE:
|
|
||||||
* rtx->sig_pending_any accessed non-atomically without mutex concurrently
|
|
||||||
* from multiple threads(e.g. hawk_rtx_raisesig() called from a different
|
|
||||||
* thread) is undefined behavior. but ignore this path as i believe most
|
|
||||||
* modern compilers should support the atomic primitives. */
|
|
||||||
if (rtx->sig_pending_any && call_signal_handlers(rtx) <= -1) return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
||||||
@@ -3893,7 +3896,7 @@ static int io_val_to_str (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_val_t* io_nde_to_str(hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_oocs_t* dst, int seterr)
|
static hawk_val_t* io_nde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_oocs_t* dst, int seterr)
|
||||||
{
|
{
|
||||||
hawk_val_t* v;
|
hawk_val_t* v;
|
||||||
|
|
||||||
@@ -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
@@ -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
@@ -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 \
|
||||||
|
|||||||
@@ -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
@@ -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 ();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user