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: `+`, `-`, `*`, `/`, `%`, `**` (exponentiation), `++`, `--`, `<<`, `>>`.
- Arithmetic: `+`, `-`, `*`, `/`, `\`(integer division), `%`(modulo), `**` or '^'(exponentiation), `++`, `--`, `<<`, `>>`.
- Compound assignment: `=`, `+=`, `-=`, `*=`, `/=`, `\=`, `%=`, `^=` or `**=`, `%%=`.
- Comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`.
- Type-precise compare: `===` and `!==`.
@@ -367,7 +368,11 @@ Example:
```awk
BEGIN {
x = 10 + 5 * 2
x += 3
s = "ha"
s %%= "wk"
if (x >= 20) print x
print s
if ("10" === 10) print "no"
}
```
@@ -404,6 +409,7 @@ BEGIN {
- Bitwise AND/OR/XOR: `&`, `|`, ^^
- Unary bitwise negation: ~
- Compound bitwise assignment: `&=`, `|=`, `^^=`, `<<=`, `>>=`
- `|` also denotes pipes, so use parentheses when you mean bitwise OR.
- `>>` is also used for append redirection; use parentheses when you mean right shift.
+538 -208
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -54,15 +54,15 @@ int hawk_rtx_readiobytes (
int hawk_rtx_writeioval (
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 (
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 (
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 (
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;
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;
}
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;
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;
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 == 0)
@@ -1302,7 +1302,7 @@ int hawk_rtx_writeiostr (hawk_rtx_t* rtx, hawk_out_type_t out_type, const hawk_o
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;
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;
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 == 0)
+160 -35
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 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_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 */
dc = hawk_find_oochars_in_oochars(name->ptr, name->len, HAWK_T("::"), 2, 0);
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;
pair = hawk_rbt_search(rtx->modtab, name->ptr, len);
HAWK_ASSERT(pair != HAWK_NULL);
if (HAWK_UNLIKELY(!pair))
if (HAWK_UNLIKELY(!pair)) /* this must not happen but .. */
{
internal_error_unrolling:
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().
* invoke the unload() callback if needed and unload the module itself. */
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 */
}
}
@@ -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_oocs_t oocs;
oocs.ptr = name;
oocs.ptr = (hawk_ooch_t*)name;
oocs.len = hawk_count_oocstr(name);
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)
{
hawk_nde_t* nde;
hawk_oow_t nargs, i;
hawk_val_t* retv;
int ret = 0;
@@ -2668,28 +2668,33 @@ static int call_signal_handlers (hawk_rtx_t* rtx)
} \
} 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)
{
int xret;
hawk_val_t* tmp;
ON_STATEMENT(rtx, nde);
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
}
if (run_pending_signal_handlers(rtx) <= -1) return -1;
/* run the actual statement */
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 (
hawk_rtx_t* rtx, hawk_val_t* v, const hawk_loc_t* loc,
hawk_oocs_t* dst, int seterr)
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)
{
dst->ptr = hawk_rtx_getvaloocstr(rtx, v, &dst->len);
if (HAWK_UNLIKELY(!dst->ptr)) return -1;
@@ -3893,7 +3896,7 @@ static int io_val_to_str (
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;
@@ -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;
}
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)
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_oocs_t out;
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);
}
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;
#if defined(HAWK_ATOMIC_CAS_BOOL)
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);
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;
}
@@ -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)
{
/* TODO: is this correct? what if i want to
* 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);
hawk_rtx_seterrfmt(rtx, &call->loc, HAWK_EARGTM, HAWK_T("too many arguments to '%.*js'"), fun->name.len, fun->name.ptr);
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
* argument spec contains 'r' or 'R'.
* 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;
}
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)
{
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_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);*/
switch (ins->opcode)
{
@@ -8252,6 +8371,12 @@ static int run_funbc (hawk_rtx_t* rtx, hawk_fun_t* fun)
hawk_rtx_refdownval(rtx, val);
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:
val = fbc_eval_stack_pop(evstk);
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 \
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-021.hawk
h-021.hawk h-022.hawk h-023.hawk
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 \
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-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
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
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 ();
}