Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b7873b230 | |||
| 5a563d7c15 | |||
| 6dc0dec3e8 |
@@ -701,7 +701,7 @@ func (rtx *Rtx) Exec(args []string) (*Val, error) {
|
|||||||
// hawk_rtx_exec...() returns a value with the reference count incremented.
|
// hawk_rtx_exec...() returns a value with the reference count incremented.
|
||||||
// create a value without going through rtx.make_val()
|
// create a value without going through rtx.make_val()
|
||||||
return rtx.fix_val_with_raw(val), nil
|
return rtx.fix_val_with_raw(val), nil
|
||||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
//return rtx.make_val(func() *C.hawk_val_t { return val })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rtx *Rtx) Loop() (*Val, error) {
|
func (rtx *Rtx) Loop() (*Val, error) {
|
||||||
@@ -711,7 +711,7 @@ func (rtx *Rtx) Loop() (*Val, error) {
|
|||||||
// hawk_rtx_loop() returns a value with the reference count incremented.
|
// hawk_rtx_loop() returns a value with the reference count incremented.
|
||||||
// create a value without going through rtx.make_val()
|
// create a value without going through rtx.make_val()
|
||||||
return rtx.fix_val_with_raw(val), nil
|
return rtx.fix_val_with_raw(val), nil
|
||||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
//return rtx.make_val(func() *C.hawk_val_t { return val })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
|
func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
|
||||||
@@ -1053,7 +1053,8 @@ func (rtx* Rtx) fix_val_with_raw(val *C.hawk_val_t) *Val {
|
|||||||
// this function assumes val has the non-zero reference count
|
// this function assumes val has the non-zero reference count
|
||||||
// the caller must ensure that the reference count has been incremented properly
|
// the caller must ensure that the reference count has been incremented properly
|
||||||
var vv *Val
|
var vv *Val
|
||||||
if val.v_refs <= 0 && C.hawk_rtx_isstaticval(rtx.c, val) == 0 { panic("invalid reference count") }
|
// immediate values or static pointer values must no check the reference count.
|
||||||
|
if C.hawk_rtx_isimmorstaticval(rtx.c, val) == 0 && val.v_refs <= 0 { panic("invalid reference count") }
|
||||||
vv = &Val{rtx: rtx, c: val}
|
vv = &Val{rtx: rtx, c: val}
|
||||||
rtx.chain_val(vv)
|
rtx.chain_val(vv)
|
||||||
return vv
|
return vv
|
||||||
|
|||||||
+14
@@ -3653,6 +3653,20 @@ HAWK_EXPORT int hawk_rtx_isstaticval (
|
|||||||
const hawk_val_t* val /**< value to check */
|
const hawk_val_t* val /**< value to check */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hawk_rtx_isimmval() function determines if a value is a immediate value
|
||||||
|
* encoded using pointer tagging.
|
||||||
|
*/
|
||||||
|
HAWK_EXPORT int hawk_rtx_isimmval (
|
||||||
|
hawk_rtx_t* rtx, /**< runtime context */
|
||||||
|
const hawk_val_t* val /**< value to check */
|
||||||
|
);
|
||||||
|
|
||||||
|
HAWK_EXPORT int hawk_rtx_isimmorstaticval (
|
||||||
|
hawk_rtx_t* rtx, /**< runtime context */
|
||||||
|
const hawk_val_t* val /**< value to check */
|
||||||
|
);
|
||||||
|
|
||||||
HAWK_EXPORT int hawk_rtx_getvaltype (
|
HAWK_EXPORT int hawk_rtx_getvaltype (
|
||||||
hawk_rtx_t* rtx,
|
hawk_rtx_t* rtx,
|
||||||
const hawk_val_t* val
|
const hawk_val_t* val
|
||||||
|
|||||||
@@ -2958,13 +2958,17 @@ static int push_exec_stack (hawk_rtx_t* rtx, int state, hawk_nde_t* nde)
|
|||||||
{
|
{
|
||||||
hawk_oow_t new_limit;
|
hawk_oow_t new_limit;
|
||||||
hawk_exec_stack_t* tmp;
|
hawk_exec_stack_t* tmp;
|
||||||
|
|
||||||
new_limit = rtx->exec_stack_limit + 1;
|
new_limit = rtx->exec_stack_limit + 1;
|
||||||
new_limit = HAWK_ALIGN_POW2(new_limit, 64); /* TODO: change align factor */
|
new_limit = HAWK_ALIGN_POW2(new_limit, 64); /* TODO: change align factor */
|
||||||
|
|
||||||
tmp = hawk_rtx_reallocmem(rtx, rtx->exec_stack, HAWK_SIZEOF(*tmp) * new_limit);
|
tmp = hawk_rtx_reallocmem(rtx, rtx->exec_stack, HAWK_SIZEOF(*tmp) * new_limit);
|
||||||
if (HAWK_UNLIKELY(!tmp)) return -1;
|
if (HAWK_UNLIKELY(!tmp)) return -1;
|
||||||
|
|
||||||
rtx->exec_stack = tmp;
|
rtx->exec_stack = tmp;
|
||||||
rtx->exec_stack_limit = new_limit;
|
rtx->exec_stack_limit = new_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtx->exec_stack[rtx->exec_stack_size].state = state;
|
rtx->exec_stack[rtx->exec_stack_size].state = state;
|
||||||
rtx->exec_stack[rtx->exec_stack_size].nde = nde;
|
rtx->exec_stack[rtx->exec_stack_size].nde = nde;
|
||||||
rtx->exec_stack[rtx->exec_stack_size].ptr = HAWK_NULL;
|
rtx->exec_stack[rtx->exec_stack_size].ptr = HAWK_NULL;
|
||||||
@@ -2979,7 +2983,7 @@ static int push_exec_stack2 (hawk_rtx_t* rtx, int state, hawk_nde_t* nde, hawk_n
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = push_exec_stack(rtx, state, nde);
|
n = push_exec_stack(rtx, state, nde);
|
||||||
if (n <= -1) return -1;
|
if (HAWK_UNLIKELY(n <= -1)) return -1;
|
||||||
rtx->exec_stack[rtx->exec_stack_size - 1].ptr = ptr;
|
rtx->exec_stack[rtx->exec_stack_size - 1].ptr = ptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2989,13 +2993,15 @@ static int push_exec_stack3 (hawk_rtx_t* rtx, int state, hawk_nde_t* nde, hawk_o
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = push_exec_stack(rtx, state, nde);
|
n = push_exec_stack(rtx, state, nde);
|
||||||
if (n <= -1) return -1;
|
if (HAWK_UNLIKELY(n <= -1)) return -1;
|
||||||
rtx->exec_stack[rtx->exec_stack_size - 1].iv = iv;
|
rtx->exec_stack[rtx->exec_stack_size - 1].iv = iv;
|
||||||
rtx->exec_stack[rtx->exec_stack_size - 1].base = base;
|
rtx->exec_stack[rtx->exec_stack_size - 1].base = base;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: return the item pointer? */
|
/* TODO: return the item pointer? */
|
||||||
|
#define pop_exec_stack_unchecked(rtx) ((rtx)->exec_stack_size = (rtx)->exec_stack_size - 1)
|
||||||
|
|
||||||
static hawk_exec_stack_t* pop_exec_stack (hawk_rtx_t* rtx, hawk_exec_stack_t* es)
|
static hawk_exec_stack_t* pop_exec_stack (hawk_rtx_t* rtx, hawk_exec_stack_t* es)
|
||||||
{
|
{
|
||||||
if (rtx->exec_stack_size <= 0) return HAWK_NULL;
|
if (rtx->exec_stack_size <= 0) return HAWK_NULL;
|
||||||
@@ -3093,16 +3099,18 @@ static int enter_block_iterative (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* what needs to be done upon entering a block has been done.
|
||||||
|
* rollback(i.e. leave_block_iterative) must undo them from here on. */
|
||||||
|
|
||||||
if (push_exec_stack(rtx, EXEC_STATE_BLK_LEAVE, (hawk_nde_t*)nde) <= -1)
|
if (push_exec_stack(rtx, EXEC_STATE_BLK_LEAVE, (hawk_nde_t*)nde) <= -1)
|
||||||
{
|
{
|
||||||
leave_block_iterative(rtx, nde);
|
leave_block_iterative(rtx, nde);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nde->body &&
|
if (nde->body && push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, (hawk_nde_t*)nde, nde->body) <= -1)
|
||||||
push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, (hawk_nde_t*)nde, nde->body) <= -1)
|
|
||||||
{
|
{
|
||||||
rtx->exec_stack_size--;
|
pop_exec_stack_unchecked(rtx);
|
||||||
leave_block_iterative(rtx, nde);
|
leave_block_iterative(rtx, nde);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -3153,13 +3161,18 @@ static int run_statement0 (hawk_rtx_t* rtx, const hawk_exec_stack_t* es)
|
|||||||
stmt = es->ptr;
|
stmt = es->ptr;
|
||||||
HAWK_ASSERT(stmt != HAWK_NULL);
|
HAWK_ASSERT(stmt != HAWK_NULL);
|
||||||
|
|
||||||
if (stmt->next &&
|
/* For example, consider:
|
||||||
push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, nde, stmt->next) <= -1) return -1;
|
* { print "hello"; print "world" }
|
||||||
|
* nde->body is pushed to the stack in enter_block_interactive().
|
||||||
|
* the body is a chain of other statements. each statement needs
|
||||||
|
* to be executed. */
|
||||||
|
if (stmt->next && push_exec_stack2(rtx, EXEC_STATE_BLK_STEP, nde, stmt->next) <= -1) return -1;
|
||||||
if (push_exec_stack(rtx, EXEC_STATE_ENTER, stmt) <= -1) return -1;
|
if (push_exec_stack(rtx, EXEC_STATE_ENTER, stmt) <= -1) return -1;
|
||||||
xret = 0;
|
xret = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* entering the block */
|
||||||
xret = enter_block_iterative(rtx, (hawk_nde_blk_t*)nde);
|
xret = enter_block_iterative(rtx, (hawk_nde_blk_t*)nde);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+29
-27
@@ -231,7 +231,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||||
PRINT_EXPR(hawk, px->right);
|
PRINT_EXPR(hawk, px->right);
|
||||||
|
|
||||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||||
PRINT_EXPR(hawk, px->left);
|
PRINT_EXPR(hawk, px->left);
|
||||||
HAWK_ASSERT (px->left->next == HAWK_NULL);
|
HAWK_ASSERT(px->left->next == HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||||
PUT_SRCSTR(hawk, binop_str[px->opcode][(hawk->opt.trait & HAWK_BLANKCONCAT)? 0: 1]);
|
PUT_SRCSTR(hawk, binop_str[px->opcode][(hawk->opt.trait & HAWK_BLANKCONCAT)? 0: 1]);
|
||||||
@@ -252,7 +252,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
PRINT_EXPR(hawk, px->right);
|
PRINT_EXPR(hawk, px->right);
|
||||||
if (px->right->type == HAWK_NDE_ASS)
|
if (px->right->type == HAWK_NDE_ASS)
|
||||||
PUT_SRCSTR(hawk, HAWK_T(")"));
|
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(")"));
|
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
case HAWK_NDE_EXP_UNR:
|
case HAWK_NDE_EXP_UNR:
|
||||||
{
|
{
|
||||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||||
PUT_SRCSTR(hawk, unrop_str[px->opcode]);
|
PUT_SRCSTR(hawk, unrop_str[px->opcode]);
|
||||||
@@ -274,7 +274,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
case HAWK_NDE_EXP_INCPRE:
|
case HAWK_NDE_EXP_INCPRE:
|
||||||
{
|
{
|
||||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, incop_str[px->opcode]);
|
PUT_SRCSTR(hawk, incop_str[px->opcode]);
|
||||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||||
@@ -286,7 +286,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
case HAWK_NDE_EXP_INCPST:
|
case HAWK_NDE_EXP_INCPST:
|
||||||
{
|
{
|
||||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
hawk_nde_exp_t* px = (hawk_nde_exp_t*)nde;
|
||||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T("("));
|
PUT_SRCSTR(hawk, HAWK_T("("));
|
||||||
PRINT_EXPR(hawk, px->left);
|
PRINT_EXPR(hawk, px->left);
|
||||||
@@ -659,14 +659,14 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
hawk_ooch_t tmp[HAWK_SIZEOF(hawk_int_t)*8+2];
|
hawk_ooch_t tmp[HAWK_SIZEOF(hawk_int_t)*8+2];
|
||||||
hawk_oow_t n;
|
hawk_oow_t n;
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||||
HAWK_ASSERT (px->id.idxa != (hawk_oow_t)-1);
|
HAWK_ASSERT(px->id.idxa != (hawk_oow_t)-1);
|
||||||
|
|
||||||
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, tmp, HAWK_COUNTOF(tmp));
|
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, tmp, HAWK_COUNTOF(tmp));
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
||||||
PUT_SRCSTRN(hawk, tmp, n);
|
PUT_SRCSTRN(hawk, tmp, n);
|
||||||
|
|
||||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,8 +674,8 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
{
|
{
|
||||||
hawk_oow_t n;
|
hawk_oow_t n;
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||||
HAWK_ASSERT (px->id.idxa != (hawk_oow_t)-1);
|
HAWK_ASSERT(px->id.idxa != (hawk_oow_t)-1);
|
||||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
PUT_SRCSTR(hawk, HAWK_T("__p"));
|
||||||
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt));
|
n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, hawk->tmp.fmt, HAWK_COUNTOF(hawk->tmp.fmt));
|
||||||
@@ -687,10 +687,10 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
case HAWK_NDE_NAMED:
|
case HAWK_NDE_NAMED:
|
||||||
{
|
{
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||||
/*HAWK_ASSERT (px->id.idxa == (hawk_oow_t)-1);
|
/*HAWK_ASSERT(px->id.idxa == (hawk_oow_t)-1);
|
||||||
* commented out the above assertion because
|
* commented out the above assertion because
|
||||||
* id.idxa field holds an index to the rtx->named_slots. */
|
* id.idxa field holds an index to the rtx->named_slots. */
|
||||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
break;
|
break;
|
||||||
@@ -699,8 +699,10 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
case HAWK_NDE_NAMEDIDX:
|
case HAWK_NDE_NAMEDIDX:
|
||||||
{
|
{
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)nde;
|
||||||
HAWK_ASSERT (px->id.idxa == (hawk_oow_t)-1);
|
/*HAWK_ASSERT(px->id.idxa == (hawk_oow_t)-1);
|
||||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
* commented out the above assertion because
|
||||||
|
* id.idxa field holds an index to the rtx->named_slots. */
|
||||||
|
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||||
|
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||||
@@ -740,7 +742,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
{
|
{
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
}
|
}
|
||||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +779,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
{
|
{
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
}
|
}
|
||||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -798,7 +800,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
{
|
{
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
}
|
}
|
||||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,7 +819,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde, int depth)
|
|||||||
{
|
{
|
||||||
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
PUT_SRCSTRN(hawk, px->id.name.ptr, px->id.name.len);
|
||||||
}
|
}
|
||||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||||
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
PRINT_EXPR_LIST_FOR_IDX(hawk, px->idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1027,7 +1029,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
|||||||
PRINT_EXPR(hawk, px->test);
|
PRINT_EXPR(hawk, px->test);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(") "));
|
PUT_SRCSTR(hawk, HAWK_T(") "));
|
||||||
|
|
||||||
HAWK_ASSERT (px->then_part != HAWK_NULL);
|
HAWK_ASSERT(px->then_part != HAWK_NULL);
|
||||||
xflags = STMT_FLAG_NO_LEAD_INDENT;
|
xflags = STMT_FLAG_NO_LEAD_INDENT;
|
||||||
if (!px->else_part) xflags |= STMT_FLAG_NO_ENDING_NL;
|
if (!px->else_part) xflags |= STMT_FLAG_NO_ENDING_NL;
|
||||||
xdepth = depth + (px->then_part->type != HAWK_NDE_BLK);
|
xdepth = depth + (px->then_part->type != HAWK_NDE_BLK);
|
||||||
@@ -1202,7 +1204,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
|||||||
hawk_getkwname(hawk, HAWK_KWID_RETURN, &kw);
|
hawk_getkwname(hawk, HAWK_KWID_RETURN, &kw);
|
||||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||||
HAWK_ASSERT (((hawk_nde_return_t*)p)->val->next == HAWK_NULL);
|
HAWK_ASSERT(((hawk_nde_return_t*)p)->val->next == HAWK_NULL);
|
||||||
|
|
||||||
PRINT_EXPR(hawk, ((hawk_nde_return_t*)p)->val);
|
PRINT_EXPR(hawk, ((hawk_nde_return_t*)p)->val);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(";"));
|
PUT_SRCSTR(hawk, HAWK_T(";"));
|
||||||
@@ -1225,7 +1227,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth, int flags)
|
|||||||
hawk_getkwname(hawk, (px->abort? HAWK_KWID_XABORT: HAWK_KWID_EXIT), &kw);
|
hawk_getkwname(hawk, (px->abort? HAWK_KWID_XABORT: HAWK_KWID_EXIT), &kw);
|
||||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||||
HAWK_ASSERT (px->val->next == HAWK_NULL);
|
HAWK_ASSERT(px->val->next == HAWK_NULL);
|
||||||
PRINT_EXPR(hawk, px->val);
|
PRINT_EXPR(hawk, px->val);
|
||||||
PUT_SRCSTR(hawk, HAWK_T(";"));
|
PUT_SRCSTR(hawk, HAWK_T(";"));
|
||||||
}
|
}
|
||||||
@@ -1494,8 +1496,8 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
case HAWK_NDE_EXP_BIN:
|
case HAWK_NDE_EXP_BIN:
|
||||||
{
|
{
|
||||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
||||||
HAWK_ASSERT (px->left->next == HAWK_NULL);
|
HAWK_ASSERT(px->left->next == HAWK_NULL);
|
||||||
HAWK_ASSERT (px->right->next == HAWK_NULL);
|
HAWK_ASSERT(px->right->next == HAWK_NULL);
|
||||||
|
|
||||||
hawk_clrpt(hawk, px->left);
|
hawk_clrpt(hawk, px->left);
|
||||||
hawk_clrpt(hawk, px->right);
|
hawk_clrpt(hawk, px->right);
|
||||||
@@ -1508,7 +1510,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
case HAWK_NDE_EXP_INCPST:
|
case HAWK_NDE_EXP_INCPST:
|
||||||
{
|
{
|
||||||
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
hawk_nde_exp_t* px = (hawk_nde_exp_t*)p;
|
||||||
HAWK_ASSERT (px->right == HAWK_NULL);
|
HAWK_ASSERT(px->right == HAWK_NULL);
|
||||||
hawk_clrpt(hawk, px->left);
|
hawk_clrpt(hawk, px->left);
|
||||||
hawk_freemem(hawk, p);
|
hawk_freemem(hawk, p);
|
||||||
break;
|
break;
|
||||||
@@ -1605,7 +1607,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
case HAWK_NDE_ARG:
|
case HAWK_NDE_ARG:
|
||||||
{
|
{
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
||||||
HAWK_ASSERT (px->idx == HAWK_NULL);
|
HAWK_ASSERT(px->idx == HAWK_NULL);
|
||||||
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
||||||
hawk_freemem(hawk, p);
|
hawk_freemem(hawk, p);
|
||||||
break;
|
break;
|
||||||
@@ -1617,7 +1619,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
case HAWK_NDE_ARGIDX:
|
case HAWK_NDE_ARGIDX:
|
||||||
{
|
{
|
||||||
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
hawk_nde_var_t* px = (hawk_nde_var_t*)p;
|
||||||
HAWK_ASSERT (px->idx != HAWK_NULL);
|
HAWK_ASSERT(px->idx != HAWK_NULL);
|
||||||
hawk_clrpt(hawk, px->idx);
|
hawk_clrpt(hawk, px->idx);
|
||||||
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
if (px->id.name.ptr) hawk_freemem(hawk, px->id.name.ptr);
|
||||||
hawk_freemem(hawk, p);
|
hawk_freemem(hawk, p);
|
||||||
@@ -1678,7 +1680,7 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
HAWK_ASSERT (!"should never happen - invalid node type");
|
HAWK_ASSERT(!"should never happen - invalid node type");
|
||||||
hawk_freemem(hawk, p);
|
hawk_freemem(hawk, p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1572,11 +1572,21 @@ hawk_val_t* hawk_rtx_makebobval (hawk_rtx_t* rtx, const void* ptr, hawk_oow_t le
|
|||||||
return (hawk_val_t*)val;
|
return (hawk_val_t*)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HAWK_INLINE hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
int hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||||
{
|
{
|
||||||
return HAWK_VTR_IS_POINTER(val) && HAWK_IS_STATICVAL(val);
|
return HAWK_VTR_IS_POINTER(val) && HAWK_IS_STATICVAL(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hawk_rtx_isimmval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||||
|
{
|
||||||
|
return !HAWK_VTR_IS_POINTER(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hawk_rtx_isimmorstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||||
|
{
|
||||||
|
return !HAWK_VTR_IS_POINTER(val) || HAWK_IS_STATICVAL(val);
|
||||||
|
}
|
||||||
|
|
||||||
int hawk_rtx_getvaltype (hawk_rtx_t* rtx, const hawk_val_t* val)
|
int hawk_rtx_getvaltype (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||||
{
|
{
|
||||||
return HAWK_RTX_GETVALTYPE(rtx, val);
|
return HAWK_RTX_GETVALTYPE(rtx, 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-022.hawk h-023.hawk h-024.hawk
|
h-021.hawk h-022.hawk h-023.hawk h-024.hawk h-025.hawk
|
||||||
|
|
||||||
check_SCRIPTS += regress-filename.sh regress-extra-info.sh regress-environ.sh
|
check_SCRIPTS += regress-filename.sh regress-extra-info.sh regress-environ.sh
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -659,7 +659,8 @@ 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 h-022.hawk h-023.hawk h-024.hawk \
|
h-020.hawk h-021.hawk h-022.hawk h-023.hawk h-024.hawk \
|
||||||
regress-filename.sh regress-extra-info.sh regress-environ.sh
|
h-025.hawk regress-filename.sh regress-extra-info.sh \
|
||||||
|
regress-environ.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 \
|
||||||
|
|||||||
+574
@@ -0,0 +1,574 @@
|
|||||||
|
## xstack expression evaluator tests
|
||||||
|
## Covers every eframe state in eval_expression0_xstack:
|
||||||
|
## HAWK_EF_BIN_LEFT/RIGHT - binary operators
|
||||||
|
## HAWK_EF_LAND_LEFT/RIGHT - logical && with short-circuit
|
||||||
|
## HAWK_EF_LOR_LEFT/RIGHT - logical || with short-circuit
|
||||||
|
## HAWK_EF_UNARY - unary operators
|
||||||
|
## HAWK_EF_CND - ternary conditional
|
||||||
|
## HAWK_EF_ASS_RHS - simple assignment
|
||||||
|
## HAWK_EF_ASS_LHS - compound assignment (read-modify-write)
|
||||||
|
|
||||||
|
@pragma entry main
|
||||||
|
@pragma implicit off
|
||||||
|
|
||||||
|
@include "tap.inc";
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## binary arithmetic operators
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_binary_arith( x)
|
||||||
|
{
|
||||||
|
tap_ensure(2 + 3, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(10 - 4, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(3 * 7, 21, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(15 / 4, 3.75, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(17 % 5, 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(2 ^ 10, 1024, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(17 \ 5, 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(-17 \ 5, -3, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## string concatenation (binary)
|
||||||
|
tap_ensure("hello" " " "world", "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure("a" "b" "c", "abc", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## binary comparison operators
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_binary_cmp()
|
||||||
|
{
|
||||||
|
tap_ensure((3 < 5), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((5 < 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 <= 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((4 <= 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((5 > 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 > 5), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 >= 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((2 >= 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 == 3), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 == 4), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 != 4), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((3 != 3), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## bitwise binary operators
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_binary_bitwise()
|
||||||
|
{
|
||||||
|
tap_ensure((0xF0 & 0xFF), 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((0x0F & 0xFF), 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((0xF0 | 0x0F), 255, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((0xFF ^^ 0x0F), 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((1 << 4), 16, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((256 >> 3), 32, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((0 << 10), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## deeply chained binary expressions (stress eframe stack growth)
|
||||||
|
## The eframe stack starts at 0 and grows 64 at a time; these chains
|
||||||
|
## push many BIN_LEFT frames before resolving any BIN_RIGHT frames.
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_binary_chain( x)
|
||||||
|
{
|
||||||
|
## left-associative chain (parser produces left-leaning tree)
|
||||||
|
x = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
|
||||||
|
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = 1 * 2 * 3 * 4 * 5;
|
||||||
|
tap_ensure(x, 120, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## deeply parenthesised right-associative nesting
|
||||||
|
x = (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + 10)))))))));
|
||||||
|
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## mix of operators
|
||||||
|
x = 2 * 3 + 4 * 5 - 6 / 2;
|
||||||
|
tap_ensure(x, 23, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## 20-term sum (forces eframe realloc path)
|
||||||
|
x = 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20;
|
||||||
|
tap_ensure(x, 210, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## logical AND -- HAWK_EF_LAND_LEFT / HAWK_EF_LAND_RIGHT
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_logical_and( r, se)
|
||||||
|
{
|
||||||
|
## short-circuit: right never evaluated when left is false
|
||||||
|
se = 0;
|
||||||
|
r = 0 && (se = 1);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## right NOT evaluated
|
||||||
|
|
||||||
|
## both sides evaluated when left is true
|
||||||
|
se = 0;
|
||||||
|
r = 1 && (se = 99);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 99, @SCRIPTNAME, @SCRIPTLINE); ## right WAS evaluated
|
||||||
|
|
||||||
|
## false right side
|
||||||
|
r = 1 && 0;
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## chained AND
|
||||||
|
r = 1 && 1 && 1;
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = 1 && 1 && 0;
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## AND with complex subexpressions
|
||||||
|
r = (2 + 3 == 5) && (10 / 2 == 5);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = (2 + 3 == 5) && (10 / 2 == 4);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## logical OR -- HAWK_EF_LOR_LEFT / HAWK_EF_LOR_RIGHT
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_logical_or( r, se)
|
||||||
|
{
|
||||||
|
## short-circuit: right never evaluated when left is true
|
||||||
|
se = 0;
|
||||||
|
r = 1 || (se = 1);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## right NOT evaluated
|
||||||
|
|
||||||
|
## both sides evaluated when left is false
|
||||||
|
se = 0;
|
||||||
|
r = 0 || (se = 77);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 77, @SCRIPTNAME, @SCRIPTLINE); ## right WAS evaluated
|
||||||
|
|
||||||
|
## false || false
|
||||||
|
r = 0 || 0;
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## chained OR
|
||||||
|
r = 0 || 0 || 1;
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = 0 || 0 || 0;
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## OR with complex subexpressions
|
||||||
|
r = (1 == 2) || (3 * 3 == 9);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = (1 == 2) || (2 + 2 == 5);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## mixed AND/OR with nested short-circuit
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_logical_mixed( r, se)
|
||||||
|
{
|
||||||
|
r = (1 && 1) || (0 && 1);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = (0 || 0) && (1 || 0);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = (0 || 1) && (1 && 1) && (0 || 1);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## right side of AND is never reached because left is short-circuit false
|
||||||
|
se = 0;
|
||||||
|
r = (0 && 1) || (se = 5);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 5, @SCRIPTNAME, @SCRIPTLINE); ## OR's right WAS evaluated
|
||||||
|
|
||||||
|
## right side of OR never reached
|
||||||
|
se = 0;
|
||||||
|
r = (1 || (se = 3)) && 1;
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(se, 0, @SCRIPTNAME, @SCRIPTLINE); ## OR's right NOT evaluated
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## unary operators -- HAWK_EF_UNARY
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_unary( x)
|
||||||
|
{
|
||||||
|
x = 5;
|
||||||
|
tap_ensure(-x, -5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(+x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!x, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!0, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(~0, -1, @SCRIPTNAME, @SCRIPTLINE); ## bitwise NOT
|
||||||
|
|
||||||
|
## nested unary operators (each adds a UNARY frame)
|
||||||
|
tap_ensure(-(-x), 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!!x, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!!!x, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(~(~0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## unary applied to binary subexpression
|
||||||
|
tap_ensure(-(2 + 3), -5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!(3 < 2), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(-(2 * 3), -6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(~(0xF0 & 0xFF), -241, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## conditional (ternary) -- HAWK_EF_CND
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_conditional( a, b, x)
|
||||||
|
{
|
||||||
|
a = 10; b = 20;
|
||||||
|
|
||||||
|
## basic true/false branch selection
|
||||||
|
tap_ensure((a < b ? "lt" : "ge"), "lt", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((a > b ? "gt" : "le"), "le", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((a == 10 ? a : b), 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((a == 99 ? a : b), 20, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## nested ternary (each level adds a CND frame)
|
||||||
|
x = (a < b) ? (b < 30 ? "lt30" : "ge30") : "no";
|
||||||
|
tap_ensure(x, "lt30", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = (a > b) ? "no" : (b > 15 ? "gt15" : "le15");
|
||||||
|
tap_ensure(x, "gt15", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## ternary with binary expressions in all three positions
|
||||||
|
x = (a + b == 30) ? (a * b) : (a - b);
|
||||||
|
tap_ensure(x, 200, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = (a + b == 99) ? (a * b) : (a - b);
|
||||||
|
tap_ensure(x, -10, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## ternary result used in larger expression
|
||||||
|
tap_ensure((a < b ? a : b) + (a > b ? a : b), 30, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## ternary inside AND/OR
|
||||||
|
tap_ensure((1 && (a < b ? 1 : 0)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((0 || (a > b ? 1 : 0)), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## simple assignment -- HAWK_EF_ASS_RHS (opcode == NONE path)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_simple_assign( x, y, z)
|
||||||
|
{
|
||||||
|
x = 42;
|
||||||
|
tap_ensure(x, 42, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## assignment with complex RHS (exercises BIN/UNARY/CND inside ASS_RHS)
|
||||||
|
x = 3 * 4 + 5;
|
||||||
|
tap_ensure(x, 17, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = (2 < 3 ? 10 : 20) + 5;
|
||||||
|
tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = !(1 == 2);
|
||||||
|
tap_ensure(x, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## chained assignment (right-to-left: z=7, y=7, x=7)
|
||||||
|
x = y = z = 7;
|
||||||
|
tap_ensure(x, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(y, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(z, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## assignment used as expression in larger context
|
||||||
|
tap_ensure((x = 5) + 3, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## compound assignment -- HAWK_EF_ASS_LHS (opcode != NONE path)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_compound_assign( x)
|
||||||
|
{
|
||||||
|
x = 10;
|
||||||
|
x += 5; tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x -= 3; tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x *= 4; tap_ensure(x, 48, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x /= 6; tap_ensure(x, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x %= 3; tap_ensure(x, 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x ^= 8; tap_ensure(x, 256, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x \= 10; tap_ensure(x, 25, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## compound with complex RHS (BIN evaluator inside ASS_RHS)
|
||||||
|
x = 5;
|
||||||
|
x += 2 * 3; tap_ensure(x, 11, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = 100;
|
||||||
|
x -= (3 + 7); tap_ensure(x, 90, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
x = 4;
|
||||||
|
x *= (1 + 1); tap_ensure(x, 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## bitwise compound assignments
|
||||||
|
x = 0xFF;
|
||||||
|
x &= 0x0F; tap_ensure(x, 15, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x = 0xF0;
|
||||||
|
x |= 0x0F; tap_ensure(x, 255, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x = 0xFF;
|
||||||
|
x ^^= 0x0F; tap_ensure(x, 240, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x = 1;
|
||||||
|
x <<= 4; tap_ensure(x, 16, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
x >>= 2; tap_ensure(x, 4, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## string concatenation compound assignment
|
||||||
|
x = "hello";
|
||||||
|
x = x " " "world";
|
||||||
|
tap_ensure(x, "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## function calls with complex argument expressions
|
||||||
|
## (exercises push_arg_from_nde_xstack for each argument)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function add3(a, b, c) { return a + b + c; }
|
||||||
|
function mul_add(a, b, c) { return a * b + c; }
|
||||||
|
function identity(x) { return x; }
|
||||||
|
function choose(flag, a, b){ return flag ? a : b; }
|
||||||
|
function noop() { return 0; }
|
||||||
|
|
||||||
|
function test_fncall_args( r, tmp)
|
||||||
|
{
|
||||||
|
## args are binary expressions
|
||||||
|
r = add3(1 + 2, 3 * 4, 5 - 1);
|
||||||
|
tap_ensure(r, 19, @SCRIPTNAME, @SCRIPTLINE); ## 3 + 12 + 4
|
||||||
|
|
||||||
|
## arg is a conditional
|
||||||
|
r = choose(1 > 0, "yes", "no");
|
||||||
|
tap_ensure(r, "yes", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = choose(0 > 1, "yes", "no");
|
||||||
|
tap_ensure(r, "no", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## arg is a unary expression
|
||||||
|
r = identity(-(3 + 4));
|
||||||
|
tap_ensure(r, -7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## arg is itself a function call with complex args
|
||||||
|
r = identity(add3(1, 2, 3));
|
||||||
|
tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## arg mixing AND with function call
|
||||||
|
r = choose(1 && 1, add3(1, 2, 3), 0);
|
||||||
|
tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = choose(1 && 0, add3(1, 2, 3), 99);
|
||||||
|
tap_ensure(r, 99, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## arg that is an assignment expression (side-effect)
|
||||||
|
tmp = 0;
|
||||||
|
r = add3((tmp = 10), tmp + 1, tmp + 2);
|
||||||
|
tap_ensure(r, 33, @SCRIPTNAME, @SCRIPTLINE); ## 10 + 11 + 12
|
||||||
|
tap_ensure(tmp, 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## deeply nested call in arg
|
||||||
|
r = mul_add(add3(1, 1, 1), identity(4), noop() + 2);
|
||||||
|
tap_ensure(r, 14, @SCRIPTNAME, @SCRIPTLINE); ## 3*4 + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## recursive user-defined functions
|
||||||
|
## (each call goes through evalcall/evalcall_xstack)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function fib(n) { return n <= 1 ? n : fib(n - 1) + fib(n - 2); }
|
||||||
|
function fact(n) { return n <= 1 ? 1 : n * fact(n - 1); }
|
||||||
|
function sum_to(n) { return n <= 0 ? 0 : n + sum_to(n - 1); }
|
||||||
|
function ack(m, n)
|
||||||
|
{
|
||||||
|
if (m == 0) return n + 1;
|
||||||
|
if (n == 0) return ack(m - 1, 1);
|
||||||
|
return ack(m - 1, ack(m, n - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_recursive()
|
||||||
|
{
|
||||||
|
@local r;
|
||||||
|
|
||||||
|
tap_ensure(fib(0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(fib(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(fib(10), 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(fib(15), 610, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
tap_ensure(fact(0), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(fact(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(fact(10), 3628800, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
tap_ensure(sum_to(0), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(sum_to(100), 5050, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## Ackermann: moderate values to avoid stack overflow
|
||||||
|
tap_ensure(ack(0, 0), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(ack(1, 1), 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(ack(2, 2), 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(ack(3, 3), 61, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## deeply nested mixed expressions
|
||||||
|
## (combines BIN, UNARY, CND, ASS — many eframe levels at once)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_deep_mixed()
|
||||||
|
{
|
||||||
|
@local t, a, b, c, x;
|
||||||
|
|
||||||
|
a = 3; b = 4; c = 5;
|
||||||
|
|
||||||
|
## Pythagorean triple check
|
||||||
|
x = (a*a + b*b == c*c) ? "right" : "wrong";
|
||||||
|
tap_ensure(x, "right", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## deeply nested: binary inside conditional inside assignment
|
||||||
|
x = (a < b) ? (b < c ? a + b + c : a * b) : (a - b) * c;
|
||||||
|
tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE); ## a+b+c = 12
|
||||||
|
|
||||||
|
## right-associated depth 10
|
||||||
|
x = (1+(2+(3+(4+(5+(6+(7+(8+(9+10)))))))));
|
||||||
|
tap_ensure(x, 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## logical chains mixed with arithmetic
|
||||||
|
x = (a > 0 && b > 0 && c > 0) ? a * b * c : 0;
|
||||||
|
tap_ensure(x, 60, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## unary inside conditional inside AND
|
||||||
|
x = (!(a > b)) && (-(a - b) > 0);
|
||||||
|
tap_ensure(x, 1, @SCRIPTNAME, @SCRIPTLINE); ## !(3>4)=1, -(3-4)=1 > 0
|
||||||
|
|
||||||
|
## assignment inside binary
|
||||||
|
x = (t = a + b) * (t - a);
|
||||||
|
tap_ensure(x, 28, @SCRIPTNAME, @SCRIPTLINE); ## t=7, 7*4=28
|
||||||
|
tap_ensure(t, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## in operator (delegated to eval_binop_in, not iterative)
|
||||||
|
## Verify the default-case delegation path in eval_expression0_xstack.
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_in_operator()
|
||||||
|
{
|
||||||
|
@local m, r;
|
||||||
|
|
||||||
|
m["x"] = 1; m["y"] = 2;
|
||||||
|
|
||||||
|
tap_ensure(("x" in m), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(("z" in m), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## 'in' inside AND/OR (both iterative and delegated evaluators)
|
||||||
|
tap_ensure((("x" in m) && ("y" in m)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((("x" in m) && ("z" in m)), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure((("z" in m) || ("x" in m)), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## 'in' inside conditional
|
||||||
|
r = ("x" in m) ? m["x"] : -1;
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = ("z" in m) ? m["z"] : -1;
|
||||||
|
tap_ensure(r, -1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## 'in' inside unary
|
||||||
|
tap_ensure(!("z" in m), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(!("x" in m), 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## pre/post increment and decrement
|
||||||
|
## (delegated to original eval_expression0 via default: branch)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_incr_decr( x, r)
|
||||||
|
{
|
||||||
|
x = 5;
|
||||||
|
r = ++x; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(x, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = x++; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE); ## returns old value
|
||||||
|
tap_ensure(x, 7, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = --x; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(x, 6, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = x--; tap_ensure(r, 6, @SCRIPTNAME, @SCRIPTLINE); ## returns old value
|
||||||
|
tap_ensure(x, 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## incr/decr result used in binary expression
|
||||||
|
x = 10;
|
||||||
|
r = (++x) + (++x);
|
||||||
|
tap_ensure(r, 23, @SCRIPTNAME, @SCRIPTLINE); ## 11 + 12
|
||||||
|
tap_ensure(x, 12, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## positional variable ($n) — delegated path
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_positional()
|
||||||
|
{
|
||||||
|
@local r;
|
||||||
|
|
||||||
|
$1 = "hello";
|
||||||
|
$2 = "world";
|
||||||
|
r = $1 " " $2;
|
||||||
|
tap_ensure(r, "hello world", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## positional in conditional (force numeric comparison with +0)
|
||||||
|
$1 = 10;
|
||||||
|
r = ($1 + 0 > 5 ? $1 * 2 : $1 / 2);
|
||||||
|
tap_ensure(r, 20, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## positional in compound assignment
|
||||||
|
$1 = 3;
|
||||||
|
$1 += 7;
|
||||||
|
tap_ensure($1, 10, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
## match/no-match operators (delegated to eval_binop_ma / eval_binop_nm)
|
||||||
|
## -----------------------------------------------------------------------
|
||||||
|
function test_match_ops()
|
||||||
|
{
|
||||||
|
@local r;
|
||||||
|
|
||||||
|
r = ("hello" ~ /ell/);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = ("hello" ~ /xyz/);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = ("hello" !~ /xyz/);
|
||||||
|
tap_ensure(r, 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
r = ("hello" !~ /ell/);
|
||||||
|
tap_ensure(r, 0, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## match result in AND/OR
|
||||||
|
tap_ensure(("abc" ~ /a/) && ("xyz" ~ /x/), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
tap_ensure(("abc" ~ /z/) || ("xyz" ~ /x/), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
|
||||||
|
## match result in conditional
|
||||||
|
r = ("hawk" ~ /awk/) ? "yes" : "no";
|
||||||
|
tap_ensure(r, "yes", @SCRIPTNAME, @SCRIPTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main()
|
||||||
|
{
|
||||||
|
test_binary_arith();
|
||||||
|
test_binary_cmp();
|
||||||
|
test_binary_bitwise();
|
||||||
|
test_binary_chain();
|
||||||
|
test_logical_and();
|
||||||
|
test_logical_or();
|
||||||
|
test_logical_mixed();
|
||||||
|
test_unary();
|
||||||
|
test_conditional();
|
||||||
|
test_simple_assign();
|
||||||
|
test_compound_assign();
|
||||||
|
test_fncall_args();
|
||||||
|
test_recursive();
|
||||||
|
test_deep_mixed();
|
||||||
|
test_in_operator();
|
||||||
|
test_incr_decr();
|
||||||
|
test_positional();
|
||||||
|
test_match_ops();
|
||||||
|
tap_end();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user