made @argc and @argv look like ARGC and ARGV
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
hyung-hwan 2024-05-03 14:04:03 +09:00
parent 32d5a3f335
commit 114040cf68
8 changed files with 196 additions and 95 deletions

View File

@ -433,7 +433,9 @@ enum hawk_nde_type_t
HAWK_NDE_MBS, HAWK_NDE_MBS,
HAWK_NDE_REX, HAWK_NDE_REX,
HAWK_NDE_XNIL, HAWK_NDE_XNIL,
HAWK_NDE_XARG, HAWK_NDE_XARGC,
HAWK_NDE_XARGV,
HAWK_NDE_XARGVIDX,
HAWK_NDE_FUN, HAWK_NDE_FUN,
/* keep this order for the following items otherwise, you may have /* keep this order for the following items otherwise, you may have

View File

@ -1309,7 +1309,7 @@ static hawk_nde_t* parse_function (hawk_t* hawk)
hawk_fun_t* fun = HAWK_NULL; hawk_fun_t* fun = HAWK_NULL;
hawk_ooch_t* argspec = HAWK_NULL; hawk_ooch_t* argspec = HAWK_NULL;
hawk_oow_t argspeccapa = 0; hawk_oow_t argspeccapa = 0;
hawk_oow_t argspeclen; hawk_oow_t argspeclen = 0;
hawk_oow_t nargs, g; hawk_oow_t nargs, g;
int variadic = 0; int variadic = 0;
hawk_htb_pair_t* pair; hawk_htb_pair_t* pair;
@ -4086,9 +4086,9 @@ static hawk_nde_t* parse_in (hawk_t* hawk, const hawk_loc_t* xloc)
if (HAWK_UNLIKELY(!right)) goto oops; if (HAWK_UNLIKELY(!right)) goto oops;
#if defined(HAWK_ENABLE_GC) #if defined(HAWK_ENABLE_GC)
if (!is_var(right)) if (!is_var(right) && right->type != HAWK_NDE_XARGV)
#else #else
if (!is_plain_var(right)) if (!is_plain_var(right) && right->type != HAWK_NDE_XARGV)
#endif #endif
{ {
hawk_seterrnum (hawk, &rloc, HAWK_ENOTVAR); hawk_seterrnum (hawk, &rloc, HAWK_ENOTVAR);
@ -5118,55 +5118,84 @@ oops:
static hawk_nde_t* parse_primary_xarg (hawk_t* hawk, const hawk_loc_t* xloc) static hawk_nde_t* parse_primary_xarg (hawk_t* hawk, const hawk_loc_t* xloc)
{ {
hawk_nde_xarg_t* nde = HAWK_NULL; hawk_nde_t* nde = HAWK_NULL;
hawk_nde_t* pos = HAWK_NULL; hawk_nde_t* pos = HAWK_NULL;
int opcode; int nde_type;
/* @argc, @argv, @argv[] look like the standard ARGC and ARGV but form special constructs
* for function arguments. this is useful when combined with the variadic function arguments.
* it can't be used in assignment, delete, reset, in many other context, however.
* when used in the main entry point function, @argc is the number of arguments to the
* function but ARGC is the number of arguments including the program name so ARGC is greater
* than @argc by 1. */
HAWK_ASSERT (hawk->tok.type == TOK_XARGV || hawk->tok.type == TOK_XARGC); HAWK_ASSERT (hawk->tok.type == TOK_XARGV || hawk->tok.type == TOK_XARGC);
opcode = (hawk->tok.type == TOK_XARGC); /* @argv: 1 @argv: 2 */ if (hawk->tok.type == TOK_XARGV)
if (get_token(hawk) <= -1) goto oops;
if (!MATCH(hawk,TOK_LPAREN))
{
hawk_seterrfmt (hawk, &hawk->tok.loc, HAWK_ELPAREN, FMT_ELPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
goto oops;
}
if (get_token(hawk) <= -1) goto oops;
if (opcode == 0)
{ {
/* @argv */ /* @argv */
hawk_loc_t eloc; nde_type = HAWK_NDE_XARGV;
eloc = hawk->tok.loc; if (get_token(hawk) <= -1) goto oops;
pos = parse_expr_withdc(hawk, &eloc);
if (HAWK_UNLIKELY(!pos)) goto oops;
}
if (!MATCH(hawk,TOK_RPAREN)) if (MATCH(hawk,TOK_LBRACK)) /* @argv[, expecting to see @argv[expr] */
{
hawk_loc_t eloc;
if (get_token(hawk) <= -1) goto oops;
eloc = hawk->tok.loc;
pos = parse_expr_withdc(hawk, &eloc);
if (HAWK_UNLIKELY(!pos)) goto oops;
if (!MATCH(hawk,TOK_RBRACK))
{
hawk_seterrfmt (hawk, &hawk->tok.loc, HAWK_ERBRACK, FMT_ERBRACK, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
goto oops;
}
if (get_token(hawk) <= -1) goto oops;
}
}
else
{ {
hawk_seterrfmt (hawk, &hawk->tok.loc, HAWK_ERPAREN, FMT_ERPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name)); nde_type = HAWK_NDE_XARGC;
goto oops; if (get_token(hawk) <= -1) goto oops;
} }
if (get_token(hawk) <= -1) goto oops; if (pos)
nde = (hawk_nde_xarg_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde))
{ {
ADJERR_LOC (hawk, xloc); hawk_nde_xargvidx_t* xargvidx;
return HAWK_NULL;
}
nde->type = HAWK_NDE_XARG; xargvidx = (hawk_nde_xargvidx_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*xargvidx));
nde->loc = *xloc; if (HAWK_UNLIKELY(!xargvidx))
nde->opcode = opcode; {
nde->pos = pos; ADJERR_LOC (hawk, xloc);
return HAWK_NULL;
}
xargvidx->type = HAWK_NDE_XARGVIDX;
xargvidx->loc = *xloc;
xargvidx->pos = pos;
nde = (hawk_nde_t*)xargvidx;
}
else
{
nde = hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde))
{
ADJERR_LOC (hawk, xloc);
return HAWK_NULL;
}
nde->type = nde_type;
nde->loc = *xloc;
}
return (hawk_nde_t*)nde; return (hawk_nde_t*)nde;
oops: oops:
if (nde) hawk_freemem (hawk, nde); /* tricky to call hawk_clrpt() on nde due to var and pos */ if (nde) hawk_freemem (hawk, nde); /* tricky to call hawk_clrpt() on nde due to pos */
if (pos) hawk_clrpt (hawk, pos); if (pos) hawk_clrpt (hawk, pos);
return HAWK_NULL; return HAWK_NULL;
} }
@ -7343,7 +7372,11 @@ static hawk_htb_walk_t deparse_func (hawk_htb_t* map, hawk_htb_pair_t* pair, voi
PUT_S (df, HAWK_T(", ")); PUT_S (df, HAWK_T(", "));
} }
if (fun->variadic) PUT_S(df, HAWK_T(" ...")); if (fun->variadic)
{
if (fun->nargs > 0) PUT_S (df, HAWK_T(", "));
PUT_S(df, HAWK_T("..."));
}
PUT_S (df, HAWK_T(")")); PUT_S (df, HAWK_T(")"));
if (df->hawk->opt.trait & HAWK_CRLF) PUT_C (df, HAWK_T('\r')); if (df->hawk->opt.trait & HAWK_CRLF) PUT_C (df, HAWK_T('\r'));

View File

@ -163,7 +163,9 @@ static hawk_val_t* eval_str (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_mbs (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_mbs (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_rex (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_rex (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_xnil (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_xnil (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_xarg (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_xargc (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_xargv (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_xargvidx (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_fun (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_fun (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_named (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_named (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_gbl (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_gbl (hawk_rtx_t* rtx, hawk_nde_t* nde);
@ -3708,7 +3710,9 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde)
eval_mbs, eval_mbs,
eval_rex, eval_rex,
eval_xnil, eval_xnil,
eval_xarg, eval_xargc,
eval_xargv,
eval_xargvidx,
eval_fun, eval_fun,
eval_named, eval_named,
eval_gbl, eval_gbl,
@ -4496,6 +4500,8 @@ static hawk_val_t* eval_binop_in (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t*
hawk_nde_t* remidx; hawk_nde_t* remidx;
hawk_int_t idxint; hawk_int_t idxint;
if (right->type == HAWK_NDE_XARGV) goto rvalue_ok;
#if defined(HAWK_ENABLE_GC) #if defined(HAWK_ENABLE_GC)
if (right->type < HAWK_NDE_NAMED || right->type > HAWK_NDE_ARGIDX) if (right->type < HAWK_NDE_NAMED || right->type > HAWK_NDE_ARGIDX)
#else #else
@ -4508,6 +4514,7 @@ static hawk_val_t* eval_binop_in (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t*
return HAWK_NULL; return HAWK_NULL;
} }
rvalue_ok:
/* evaluate the left-hand side of the operator */ /* evaluate the left-hand side of the operator */
len = HAWK_COUNTOF(idxbuf); len = HAWK_COUNTOF(idxbuf);
str = (left->type == HAWK_NDE_GRP)? /* it is inefficinet to call idxnde_to_str() for an array. but i don't know if the right hand side is a map or an array yet */ str = (left->type == HAWK_NDE_GRP)? /* it is inefficinet to call idxnde_to_str() for an array. but i don't know if the right hand side is a map or an array yet */
@ -7473,38 +7480,59 @@ static hawk_val_t* eval_xnil (hawk_rtx_t* rtx, hawk_nde_t* nde)
return hawk_rtx_makenilval(rtx); /* this never fails */ return hawk_rtx_makenilval(rtx); /* this never fails */
} }
static hawk_val_t* eval_xarg (hawk_rtx_t* rtx, hawk_nde_t* nde) static hawk_val_t* eval_xargc (hawk_rtx_t* rtx, hawk_nde_t* nde)
{ {
hawk_nde_xarg_t* xarg; hawk_int_t nargs = (hawk_int_t)hawk_rtx_getnargs(rtx);
return hawk_rtx_makeintval(rtx, nargs);
}
xarg = (hawk_nde_xarg_t*)nde; static hawk_val_t* eval_xargv (hawk_rtx_t* rtx, hawk_nde_t* nde)
if (xarg->opcode == 0) {
/* this create a new array. referencing @argv without a subscript
* slows hawk. TODO: fix this issue */
hawk_oow_t nargs, i;
hawk_val_t* v;
nargs = hawk_rtx_getnargs(rtx);
v = hawk_rtx_makearrval(rtx, nargs);
if (HAWK_UNLIKELY(!v)) return HAWK_NULL;
hawk_rtx_refupval (rtx,v);
for (i = 0; i < nargs; i++)
{ {
/* @argv */ if (HAWK_UNLIKELY(!hawk_rtx_setarrvalfld(rtx, v, i, hawk_rtx_getarg(rtx, i))))
hawk_val_t* v;
hawk_int_t pos;
int n;
v = eval_expression(rtx, xarg->pos);
if (HAWK_UNLIKELY(!v)) return HAWK_NULL;
hawk_rtx_refupval (rtx, v);
n = hawk_rtx_valtoint(rtx, v, &pos);
hawk_rtx_refdownval (rtx, v);
if (n <= -1)
{ {
hawk_rtx_seterrnum (rtx, &xarg->pos->loc, HAWK_EPOSIDX); hawk_rtx_refdownval (rtx, v);
return HAWK_NULL; return HAWK_NULL;
} }
}
return (pos < 0 || pos >= hawk_rtx_getnargs(rtx))? hawk_rtx_makenilval(rtx): hawk_rtx_getarg(rtx, pos); hawk_rtx_refdownval_nofree (rtx,v);
} return v;
else }
static hawk_val_t* eval_xargvidx (hawk_rtx_t* rtx, hawk_nde_t* nde)
{
hawk_nde_xargvidx_t* xarg;
hawk_val_t* v;
hawk_int_t pos;
int n;
xarg = (hawk_nde_xargvidx_t*)nde;
v = eval_expression(rtx, xarg->pos);
if (HAWK_UNLIKELY(!v)) return HAWK_NULL;
hawk_rtx_refupval (rtx, v);
n = hawk_rtx_valtoint(rtx, v, &pos);
hawk_rtx_refdownval (rtx, v);
if (n <= -1)
{ {
/* @argc */ hawk_rtx_seterrnum (rtx, &xarg->pos->loc, HAWK_EPOSIDX);
hawk_int_t nargs = (hawk_int_t)hawk_rtx_getnargs(rtx); return HAWK_NULL;
return hawk_rtx_makeintval(rtx, nargs);
} }
return (pos < 0 || pos >= hawk_rtx_getnargs(rtx))? hawk_rtx_makenilval(rtx): hawk_rtx_getarg(rtx, pos);
} }
static hawk_val_t* eval_fun (hawk_rtx_t* rtx, hawk_nde_t* nde) static hawk_val_t* eval_fun (hawk_rtx_t* rtx, hawk_nde_t* nde)

View File

@ -68,7 +68,7 @@ typedef struct hawk_nde_mbs_t hawk_nde_mbs_t;
typedef struct hawk_nde_rex_t hawk_nde_rex_t; typedef struct hawk_nde_rex_t hawk_nde_rex_t;
typedef struct hawk_nde_fun_t hawk_nde_fun_t; typedef struct hawk_nde_fun_t hawk_nde_fun_t;
typedef struct hawk_nde_xnil_t hawk_nde_xnil_t; typedef struct hawk_nde_xnil_t hawk_nde_xnil_t;
typedef struct hawk_nde_xarg_t hawk_nde_xarg_t; typedef struct hawk_nde_xargvidx_t hawk_nde_xargvidx_t;
typedef struct hawk_nde_var_t hawk_nde_var_t; typedef struct hawk_nde_var_t hawk_nde_var_t;
typedef struct hawk_nde_fncall_t hawk_nde_fncall_t; typedef struct hawk_nde_fncall_t hawk_nde_fncall_t;
@ -178,7 +178,7 @@ struct hawk_nde_str_t
{ {
HAWK_NDE_HDR; HAWK_NDE_HDR;
hawk_ooch_t* ptr; hawk_ooch_t* ptr;
hawk_oow_t len; hawk_oow_t len;
}; };
/* HAWK_NDE_MBS */ /* HAWK_NDE_MBS */
@ -186,15 +186,15 @@ struct hawk_nde_mbs_t
{ {
HAWK_NDE_HDR; HAWK_NDE_HDR;
hawk_bch_t* ptr; hawk_bch_t* ptr;
hawk_oow_t len; hawk_oow_t len;
}; };
/* HAWK_NDE_REX */ /* HAWK_NDE_REX */
struct hawk_nde_rex_t struct hawk_nde_rex_t
{ {
HAWK_NDE_HDR; HAWK_NDE_HDR;
hawk_oocs_t str; hawk_oocs_t str;
hawk_tre_t* code[2]; /* [0]: case sensitive, [1]: case insensitive */ hawk_tre_t* code[2]; /* [0]: case sensitive, [1]: case insensitive */
}; };
struct hawk_nde_xnil_t struct hawk_nde_xnil_t
@ -202,10 +202,9 @@ struct hawk_nde_xnil_t
HAWK_NDE_HDR; HAWK_NDE_HDR;
}; };
struct hawk_nde_xarg_t struct hawk_nde_xargvidx_t
{ {
HAWK_NDE_HDR; HAWK_NDE_HDR;
int opcode; /* 0: @argc, 1: @argv */
hawk_nde_t* pos; hawk_nde_t* pos;
}; };

View File

@ -554,16 +554,23 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
break; break;
} }
case HAWK_NDE_XARG: case HAWK_NDE_XARGC:
{ {
static hawk_ooch_t* xarg_str[] = PUT_SRCSTR (hawk, HAWK_T("@argc"));
{ break;
HAWK_T("@argv("), }
HAWK_T("@argc("),
}; case HAWK_NDE_XARGV:
PUT_SRCSTR (hawk, xarg_str[((hawk_nde_xarg_t*)nde)->opcode % 2]); {
if (((hawk_nde_xarg_t*)nde)->pos) PRINT_EXPR (hawk, ((hawk_nde_xarg_t*)nde)->pos); PUT_SRCSTR (hawk, HAWK_T("@argv"));
PUT_SRCSTR (hawk, HAWK_T(")")); break;
}
case HAWK_NDE_XARGVIDX:
{
PUT_SRCSTR (hawk, HAWK_T("@argv["));
PRINT_EXPR (hawk, ((hawk_nde_xargvidx_t*)nde)->pos);
PUT_SRCSTR (hawk, HAWK_T("]"));
break; break;
} }
@ -1467,10 +1474,16 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
break; break;
} }
case HAWK_NDE_XARG: case HAWK_NDE_XARGC:
case HAWK_NDE_XARGV:
{ {
if (((hawk_nde_xarg_t*)p)->pos) /* pos is null for @argc */ hawk_freemem (hawk, p);
hawk_clrpt (hawk, ((hawk_nde_xarg_t*)p)->pos); break;
}
case HAWK_NDE_XARGVIDX:
{
hawk_clrpt (hawk, ((hawk_nde_xargvidx_t*)p)->pos);
hawk_freemem (hawk, p); hawk_freemem (hawk, p);
break; break;
} }

View File

@ -1069,7 +1069,7 @@ hawk_val_t* hawk_rtx_makerexval (hawk_rtx_t* rtx, const hawk_oocs_t* str, hawk_t
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static void free_arrayval (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) static void free_arrval (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen)
{ {
hawk_rtx_t* rtx = *(hawk_rtx_t**)hawk_arr_getxtn(arr); hawk_rtx_t* rtx = *(hawk_rtx_t**)hawk_arr_getxtn(arr);
hawk_val_t* v = (hawk_val_t*)dptr; hawk_val_t* v = (hawk_val_t*)dptr;
@ -1091,7 +1091,7 @@ static void free_arrayval (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen)
hawk_rtx_refdownval (rtx, v); hawk_rtx_refdownval (rtx, v);
} }
static void same_arrayval (hawk_arr_t* map, void* dptr, hawk_oow_t dlen) static void same_arrval (hawk_arr_t* map, void* dptr, hawk_oow_t dlen)
{ {
hawk_rtx_t* rtx = *(hawk_rtx_t**)hawk_arr_getxtn(map); hawk_rtx_t* rtx = *(hawk_rtx_t**)hawk_arr_getxtn(map);
#if defined(DEBUG_VAL) #if defined(DEBUG_VAL)
@ -1111,9 +1111,9 @@ hawk_val_t* hawk_rtx_makearrval (hawk_rtx_t* rtx, hawk_ooi_t init_capa)
* freeing the actual value is handled by free_arrval and same_arrval */ * freeing the actual value is handled by free_arrval and same_arrval */
HAWK_ARR_COPIER_DEFAULT, HAWK_ARR_COPIER_DEFAULT,
free_arrayval, free_arrval,
HAWK_ARR_COMPER_DEFAULT, HAWK_ARR_COMPER_DEFAULT,
same_arrayval, same_arrval,
HAWK_ARR_SIZER_DEFAULT HAWK_ARR_SIZER_DEFAULT
}; };
#if defined(HAWK_ENABLE_GC) #if defined(HAWK_ENABLE_GC)

View File

@ -530,7 +530,7 @@ static int getoption_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, ha
{ {
int n; int n;
hawk_rtx_refupval (rtx, map); hawk_rtx_refupval (rtx, map);
n = hawk_rtx_setrefval (rtx, ref, map); n = hawk_rtx_setrefval(rtx, ref, map);
hawk_rtx_refdownval (rtx, map); hawk_rtx_refdownval (rtx, map);
if (n <= -1) if (n <= -1)
{ {

View File

@ -643,8 +643,15 @@ function main()
tap_ensure (RLENGTH, 2, @SCRIPTNAME, @SCRIPTLINE); tap_ensure (RLENGTH, 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test5(10, 20, 30), 10, @SCRIPTNAME, @SCRIPTLINE); tap_ensure (test5(10, 20, 30), 10, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test6(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 54, @SCRIPTNAME, @SCRIPTLINE); tap_ensure (test6(), 2, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test7(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE); tap_ensure (test6(11, 11, 11), 3, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test7(), 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test7(11, 11, 11), 3, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 54, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test9(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test11("aa", "bb", "cc"), 0, @SCRIPTNAME, @SCRIPTLINE);
tap_ensure (test11("aa", "bb", "cc", "dd"), 1, @SCRIPTNAME, @SCRIPTLINE);
} }
tap_end (); tap_end ();
} }
@ -658,16 +665,35 @@ function test5(a, b, ...) {
return a; return a;
} }
function test6(a, ...) { function test6(a, b, ...) {
@local i, x return @argc;
x = 0
for (i = 0; i < @argc(); i++) x += @argv(i);
return x - a;
} }
function test7(...) { function test7(...) {
return @argc;
}
function test8(a, ...) {
@local i, x @local i, x
x = 0 x = 0
for (i = 0; i < @argc(); i++) x += @argv(i); for (i = 0; i < @argc; i++) x += @argv[i];
return x - a;
}
function test9(...) {
@local i, x
x = 0
for (i = 0; i < @argc; i++) x += @argv[i];
return x; return x;
} }
function test10(...) {
@local i, x
x = 0
for (i in @argv) x += @argv[i];
return x;
}
function test11(...) {
return (3 in @argv);
}