touched up stack management code
added hawk::call()
This commit is contained in:
parent
9eb3c4fc42
commit
e4de922f7d
@ -129,7 +129,7 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
|
||||
HAWK_T("word after @ not recognized"),
|
||||
HAWK_T("@ not followed by a valid word"),
|
||||
|
||||
HAWK_T("stack error"),
|
||||
HAWK_T("stack full"),
|
||||
HAWK_T("divide by zero"),
|
||||
HAWK_T("invalid operand"),
|
||||
HAWK_T("wrong position index"),
|
||||
|
@ -362,14 +362,6 @@ struct hawk_chain_t
|
||||
hawk_chain_t* next;
|
||||
};
|
||||
|
||||
#define HAWK_RTX_STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)])
|
||||
#define HAWK_RTX_STACK_NARGS(rtx) HAWK_RTX_STACK_AT(rtx,3)
|
||||
#define HAWK_RTX_STACK_ARG(rtx,n) HAWK_RTX_STACK_AT(rtx,3+1+(n))
|
||||
#define HAWK_RTX_STACK_LCL(rtx,n) HAWK_RTX_STACK_AT(rtx,3+(hawk_oow_t)HAWK_RTX_STACK_NARGS(rtx)+1+(n))
|
||||
#define HAWK_RTX_STACK_RETVAL(rtx) HAWK_RTX_STACK_AT(rtx,2)
|
||||
#define HAWK_RTX_STACK_GBL(rtx,n) ((rtx)->stack[(n)])
|
||||
#define HAWK_RTX_STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->hawk->tree.ngbls+2])
|
||||
|
||||
struct hawk_rtx_t
|
||||
{
|
||||
HAWK_RTX_HDR;
|
||||
@ -536,6 +528,35 @@ struct hawk_mod_data_t
|
||||
hawk_mod_t mod;
|
||||
};
|
||||
|
||||
|
||||
#define HAWK_RTX_STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)])
|
||||
#define HAWK_RTX_STACK_NARGS(rtx) HAWK_RTX_STACK_AT(rtx,3)
|
||||
#define HAWK_RTX_STACK_ARG(rtx,n) HAWK_RTX_STACK_AT(rtx,3+1+(n))
|
||||
#define HAWK_RTX_STACK_LCL(rtx,n) HAWK_RTX_STACK_AT(rtx,3+(hawk_oow_t)HAWK_RTX_STACK_NARGS(rtx)+1+(n))
|
||||
#define HAWK_RTX_STACK_RETVAL(rtx) HAWK_RTX_STACK_AT(rtx,2)
|
||||
#define HAWK_RTX_STACK_GBL(rtx,n) ((rtx)->stack[(n)])
|
||||
#define HAWK_RTX_STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->hawk->tree.ngbls+2])
|
||||
|
||||
#define HAWK_RTX_STACK_AVAIL(rtx) ((rtx)->stack_limit - (rtx)->stack_top)
|
||||
|
||||
#if defined(HAWK_HAVE_INLINE)
|
||||
static HAWK_INLINE void HAWK_RTX_STACK_PUSH (hawk_rtx_t* rtx, hawk_val_t* val)
|
||||
{
|
||||
/*HAWK_ASSERT (rtx->stack_top < rtx->stack_limit);*/
|
||||
rtx->stack[rtx->stack_top++] = val;
|
||||
}
|
||||
|
||||
static HAWK_INLINE void HAWK_RTX_STACK_POP (hawk_rtx_t* rtx)
|
||||
{
|
||||
/*HAWK_ASSERT (rtx->stack_top > rtx->stack_base);*/
|
||||
rtx->stack_top--;
|
||||
}
|
||||
#else
|
||||
#define HAWK_RTX_STACK_PUSH(rtx,val) ((rtx)->stack[(rtx)->stack_top++] = val)
|
||||
#define HAWK_RTX_STACK_POP(rtx) ((rtx)->stack_top--)
|
||||
#endif
|
||||
|
||||
|
||||
#define HAWK_RTX_INIT_REF_VAL(refval, _id, _adr, _nrefs) \
|
||||
do { \
|
||||
(refval)->v_type = HAWK_VAL_REF; \
|
||||
|
@ -27,10 +27,91 @@
|
||||
#include "mod-hawk.h"
|
||||
#include "hawk-prv.h"
|
||||
|
||||
struct pafs_t
|
||||
{
|
||||
hawk_oow_t stack_base;
|
||||
hawk_oow_t start_index;
|
||||
hawk_oow_t end_index;
|
||||
};
|
||||
|
||||
static hawk_oow_t push_args_from_stack (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, void* data)
|
||||
{
|
||||
struct pafs_t* pasf = (struct pafs_t*)data;
|
||||
hawk_oow_t org_stack_base, i;
|
||||
hawk_val_t* v;
|
||||
|
||||
if (HAWK_RTX_STACK_AVAIL(rtx) < pasf->end_index - pasf->start_index + 1)
|
||||
{
|
||||
hawk_rtx_seterrnum (rtx, &call->loc, HAWK_ESTACK);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
org_stack_base = rtx->stack_base;
|
||||
for (i = pasf->start_index; i <= pasf->end_index; i++)
|
||||
{
|
||||
rtx->stack_base = pasf->stack_base;
|
||||
v = HAWK_RTX_STACK_ARG(rtx, i);
|
||||
rtx->stack_base = org_stack_base;
|
||||
|
||||
HAWK_RTX_STACK_PUSH (rtx, v);
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
}
|
||||
|
||||
return pasf->end_index - pasf->start_index + 1;
|
||||
}
|
||||
|
||||
static int fnc_call (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
||||
{
|
||||
hawk_fun_t* fun;
|
||||
hawk_oow_t nargs;
|
||||
hawk_nde_fncall_t call;
|
||||
struct pafs_t pafs;
|
||||
hawk_val_t* v, * a0;
|
||||
int rx = -1;
|
||||
|
||||
/* this function is similar to hawk_rtx_callfun() but it is more simplified */
|
||||
|
||||
a0 = hawk_rtx_getarg(rtx, 0);
|
||||
|
||||
fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 1));
|
||||
if (!fun) goto done;
|
||||
|
||||
nargs = hawk_rtx_getnargs(rtx);
|
||||
if (nargs - 2 > fun->nargs)
|
||||
{
|
||||
/*hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EARGTM);
|
||||
return HAWK_NULL;*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
HAWK_MEMSET (&call, 0, HAWK_SIZEOF(call));
|
||||
call.type = HAWK_NDE_FNCALL_FUN;
|
||||
call.u.fun.name = fun->name;
|
||||
call.nargs = nargs - 2;
|
||||
/* keep HAWK_NULL in call.args so that hawk_rtx_evalcall() knows it's a fake call structure */
|
||||
call.arg_base = rtx->stack_base + 6; /* 6 = 4(stack frame prologue) + 2(the first two arguments to hawk::call()) */
|
||||
|
||||
pafs.stack_base = rtx->stack_base;
|
||||
pafs.start_index = 2;
|
||||
pafs.end_index = nargs - 1;
|
||||
|
||||
v = hawk_rtx_evalcall(rtx, &call, fun, push_args_from_stack, (void*)&pafs, HAWK_NULL, HAWK_NULL);
|
||||
if (HAWK_LIKELY(v))
|
||||
{
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
rx = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)a0, v);
|
||||
hawk_rtx_refdownval (rtx, v);
|
||||
}
|
||||
|
||||
done:
|
||||
hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, rx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
hawk::gc();
|
||||
hawk::gc_set_threshold(gen)
|
||||
hawk::gc_get_threshold(gen)
|
||||
hawk::gc_set_threshold(gen, threshold)
|
||||
hawk::GC_NUM_GENS
|
||||
*/
|
||||
|
||||
@ -107,6 +188,7 @@ struct inttab_t
|
||||
static fnctab_t fnctab[] =
|
||||
{
|
||||
/* keep this table sorted for binary search in query(). */
|
||||
{ HAWK_T("call"), { { 2, A_MAX, HAWK_T("rvR") }, fnc_call, 0 } },
|
||||
{ HAWK_T("gc"), { { 0, 1, HAWK_NULL }, fnc_gc, 0 } },
|
||||
{ HAWK_T("gc_get_threshold"), { { 1, 1, HAWK_NULL }, fnc_gc_get_threshold, 0 } },
|
||||
{ HAWK_T("gc_set_threshold"), { { 2, 2, HAWK_NULL }, fnc_gc_set_threshold, 0 } }
|
||||
|
@ -350,7 +350,6 @@ static int fnc_tocharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fnc_frommbs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
||||
{
|
||||
/* str::frommbs(B"byte-string" [, "encoding-name"])
|
||||
|
@ -1460,7 +1460,8 @@ static hawk_nde_t* parse_function (hawk_t* awk)
|
||||
for (i = argspeccapa; i < newcapa; i++) argspec[i] = HAWK_T(' ');
|
||||
argspeccapa = newcapa;
|
||||
}
|
||||
argspec[nargs] = HAWK_T('r');
|
||||
argspec[nargs] = 'r';
|
||||
argspec[nargs + 1] = '\0';
|
||||
if (get_token(awk) <= -1) goto oops;
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,17 @@ int hawk_rtx_cmpval (
|
||||
int* ret
|
||||
);
|
||||
|
||||
|
||||
hawk_val_t* hawk_rtx_evalcall (
|
||||
hawk_rtx_t* rtx,
|
||||
hawk_nde_fncall_t* call,
|
||||
hawk_fun_t* fun,
|
||||
hawk_oow_t(*argpusher)(hawk_rtx_t*,hawk_nde_fncall_t*,void*),
|
||||
void* apdata, /* data to argpusher */
|
||||
void(*errhandler)(void*),
|
||||
void* eharg
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
490
hawk/lib/run.c
490
hawk/lib/run.c
@ -174,14 +174,6 @@ static hawk_val_t* eval_fncall_fnc (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||
static hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||
static hawk_val_t* eval_fncall_var (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||
|
||||
static hawk_val_t* __eval_call (
|
||||
hawk_rtx_t* rtx,
|
||||
hawk_nde_t* nde,
|
||||
hawk_fun_t* fun,
|
||||
hawk_oow_t(*argpusher)(hawk_rtx_t*,hawk_nde_fncall_t*,void*),
|
||||
void* apdata, /* data to argpusher */
|
||||
void(*errhandler)(void*),
|
||||
void* eharg);
|
||||
|
||||
static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref);
|
||||
static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var);
|
||||
@ -1336,36 +1328,6 @@ oops:
|
||||
return n;
|
||||
}
|
||||
|
||||
static HAWK_INLINE int __raw_push (hawk_rtx_t* rtx, void* val)
|
||||
{
|
||||
if (rtx->stack_top >= rtx->stack_limit)
|
||||
{
|
||||
/*
|
||||
void** tmp;
|
||||
hawk_oow_t n;
|
||||
|
||||
n = rtx->stack_limit + HAWK_RTX_STACK_INCREMENT;
|
||||
|
||||
tmp = (void**)hawk_rtx_reallocmem(rtx, rtx->stack, n * HAWK_SIZEOF(void*));
|
||||
if (!tmp) return -1;
|
||||
|
||||
rtx->stack = tmp;
|
||||
rtx->stack_limit = n;
|
||||
*/
|
||||
hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_ESTACK, HAWK_T("runtime stack full"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtx->stack[rtx->stack_top++] = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __raw_pop(rtx) \
|
||||
do { \
|
||||
HAWK_ASSERT ((rtx)->stack_top > (rtx)->stack_base); \
|
||||
(rtx)->stack_top--; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* create global variables into the runtime stack
|
||||
* each variable is initialized to nil or zero.
|
||||
@ -1375,31 +1337,38 @@ static int prepare_globals (hawk_rtx_t* rtx)
|
||||
hawk_oow_t saved_stack_top;
|
||||
hawk_oow_t ngbls;
|
||||
|
||||
saved_stack_top = rtx->stack_top;
|
||||
ngbls = rtx->hawk->tree.ngbls;
|
||||
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < ngbls))
|
||||
{
|
||||
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ESTACK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
saved_stack_top = rtx->stack_top;
|
||||
|
||||
/* initialize all global variables to nil by push nils to the stack */
|
||||
while (ngbls > 0)
|
||||
{
|
||||
--ngbls;
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1)) goto oops;
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil);
|
||||
}
|
||||
|
||||
/* override NF to zero */
|
||||
if (hawk_rtx_setgbl(rtx, HAWK_GBL_NF, HAWK_VAL_ZERO) <= -1) goto oops;
|
||||
|
||||
/* return success */
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* restore the stack_top this way instead of calling __raw_pop()
|
||||
* as many times as successful __raw_push(). it is ok because
|
||||
if (hawk_rtx_setgbl(rtx, HAWK_GBL_NF, HAWK_VAL_ZERO) <= -1)
|
||||
{
|
||||
/* restore the stack_top this way instead of calling HAWK_RTX_STACK_POP()
|
||||
* as many times as successful HAWK_RTX_STACK_PUSH(). it is ok because
|
||||
* the values pushed so far are hawk_val_nils and HAWK_VAL_ZEROs.
|
||||
*/
|
||||
rtx->stack_top = saved_stack_top;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign initial values to the global variables whose desired initial
|
||||
* values are not nil or zero. some are handled in prepare_globals () and
|
||||
@ -1472,7 +1441,7 @@ static void refdown_globals (hawk_rtx_t* rtx, int pop)
|
||||
{
|
||||
--ngbls;
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_GBL(rtx,ngbls));
|
||||
if (pop) __raw_pop (rtx);
|
||||
if (pop) HAWK_RTX_STACK_POP (rtx);
|
||||
else HAWK_RTX_STACK_GBL(rtx,ngbls) = hawk_val_nil;
|
||||
}
|
||||
}
|
||||
@ -1507,47 +1476,6 @@ static void capture_retval_on_exit (void* arg)
|
||||
hawk_rtx_refupval (data->rtx, data->val);
|
||||
}
|
||||
|
||||
static int enter_stack_frame (hawk_rtx_t* rtx)
|
||||
{
|
||||
hawk_oow_t saved_stack_top;
|
||||
|
||||
/* remember the current stack top */
|
||||
saved_stack_top = rtx->stack_top;
|
||||
|
||||
/* push the current stack base */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,(void*)rtx->stack_base) <= -1)) goto oops;
|
||||
|
||||
/* push the current stack top before push the current stack base */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,(void*)saved_stack_top) <= -1)) goto oops;
|
||||
|
||||
/* secure space for a return value */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1)) goto oops;
|
||||
|
||||
/* secure space for HAWK_RTX_STACK_NARGS */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1)) goto oops;
|
||||
|
||||
/* let the stack top remembered be the base of a new stack frame */
|
||||
rtx->stack_base = saved_stack_top;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* restore the stack top in a cheesy(?) way.
|
||||
* it is ok to do so as the values pushed are
|
||||
* nils and binary numbers. */
|
||||
rtx->stack_top = saved_stack_top;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void exit_stack_frame (hawk_rtx_t* run)
|
||||
{
|
||||
/* At this point, the current stack frame should have
|
||||
* the 4 entries pushed in enter_stack_frame(). */
|
||||
HAWK_ASSERT ((run->stack_top-run->stack_base) == 4);
|
||||
|
||||
run->stack_top = (hawk_oow_t)run->stack[run->stack_base + 1];
|
||||
run->stack_base = (hawk_oow_t)run->stack[run->stack_base + 0];
|
||||
}
|
||||
|
||||
static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx)
|
||||
{
|
||||
hawk_nde_t* nde;
|
||||
@ -1660,15 +1588,38 @@ static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx)
|
||||
hawk_val_t* hawk_rtx_loop (hawk_rtx_t* rtx)
|
||||
{
|
||||
hawk_val_t* retv = HAWK_NULL;
|
||||
hawk_oow_t saved_stack_top;
|
||||
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
|
||||
if (enter_stack_frame(rtx) == 0)
|
||||
/* make a new stack frame */
|
||||
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < 4))
|
||||
{
|
||||
retv = run_bpae_loop(rtx);
|
||||
exit_stack_frame (rtx);
|
||||
/* restore the stack top in a cheesy(?) way.
|
||||
* it is ok to do so as the values pushed are
|
||||
* nils and binary numbers. */
|
||||
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ESTACK);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
saved_stack_top = rtx->stack_top; /* remember the current stack top */
|
||||
HAWK_RTX_STACK_PUSH (rtx, (void*)rtx->stack_base); /* push the current stack base */
|
||||
HAWK_RTX_STACK_PUSH (rtx, (void*)saved_stack_top); /* push the current stack top before push the current stack base */
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); /* secure space for a return value */
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); /* secure space for HAWK_RTX_STACK_NARGS */
|
||||
|
||||
/* enter the new stack frame */
|
||||
rtx->stack_base = saved_stack_top; /* let the stack top remembered be the base of a new stack frame */
|
||||
|
||||
/* run the BEGIN/pattern-action/END loop */
|
||||
retv = run_bpae_loop(rtx);
|
||||
|
||||
/* exit the stack frame */
|
||||
HAWK_ASSERT ((rtx->stack_top - rtx->stack_base) == 4); /* at this point, the current stack frame should have the 4 entries pushed above */
|
||||
rtx->stack_top = (hawk_oow_t)rtx->stack[rtx->stack_base + 1];
|
||||
rtx->stack_base = (hawk_oow_t)rtx->stack[rtx->stack_base + 0];
|
||||
|
||||
/* reset the exit level */
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
|
||||
@ -1771,7 +1722,7 @@ hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args
|
||||
pafv.nargs = nargs;
|
||||
pafv.argspec = fun->argspec;
|
||||
|
||||
if (rtx->exit_level >= EXIT_GLOBAL)
|
||||
if (HAWK_UNLIKELY(rtx->exit_level >= EXIT_GLOBAL))
|
||||
{
|
||||
/* cannot call the function again when exit() is called
|
||||
* in an AWK program or hawk_rtx_halt() is invoked */
|
||||
@ -1795,7 +1746,7 @@ hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args
|
||||
call.type = HAWK_NDE_FNCALL_FUN;
|
||||
call.u.fun.name = fun->name;
|
||||
call.nargs = nargs;
|
||||
/* keep HAWK_NULL in call.args so that __eval_call() knows it's a fake call structure */
|
||||
/* keep HAWK_NULL in call.args so that hawk_rtx_evalcall() knows it's a fake call structure */
|
||||
|
||||
/* check if the number of arguments given is more than expected */
|
||||
if (nargs > fun->nargs)
|
||||
@ -1811,7 +1762,7 @@ hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args
|
||||
crdata.rtx = rtx;
|
||||
crdata.val = HAWK_NULL;
|
||||
|
||||
v = __eval_call(rtx, (hawk_nde_t*)&call, fun, push_arg_from_vals, (void*)&pafv, capture_retval_on_exit, &crdata);
|
||||
v = hawk_rtx_evalcall(rtx, &call, fun, push_arg_from_vals, (void*)&pafv, capture_retval_on_exit, &crdata);
|
||||
|
||||
if (HAWK_UNLIKELY(!v))
|
||||
{
|
||||
@ -2159,24 +2110,22 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
||||
nlcls = nde->nlcls;
|
||||
|
||||
#if defined(DEBUG_RUN)
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx),
|
||||
HAWK_T("securing space for local variables nlcls = %d\n"),
|
||||
(int)nlcls);
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("securing space for local variables nlcls = %d\n"), (int)nlcls);
|
||||
#endif
|
||||
|
||||
saved_stack_top = rtx->stack_top;
|
||||
|
||||
/* secure space for local variables */
|
||||
while (nlcls > 0)
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < nlcls))
|
||||
{
|
||||
--nlcls;
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1))
|
||||
{
|
||||
/* restore stack top */
|
||||
rtx->stack_top = saved_stack_top;
|
||||
hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ESTACK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
saved_stack_top = rtx->stack_top;
|
||||
|
||||
while (nlcls > 0)
|
||||
{
|
||||
--nlcls;
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil);
|
||||
/* refupval is not required for hawk_val_nil */
|
||||
}
|
||||
|
||||
@ -2186,7 +2135,7 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
||||
|
||||
while (p != HAWK_NULL && rtx->exit_level == EXIT_NONE)
|
||||
{
|
||||
if (run_statement(rtx, p) <= -1)
|
||||
if (HAWK_UNLIKELY(run_statement(rtx, p) <= -1))
|
||||
{
|
||||
n = -1;
|
||||
break;
|
||||
@ -2203,7 +2152,7 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
||||
{
|
||||
--nlcls;
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_LCL(rtx, nlcls));
|
||||
__raw_pop (rtx);
|
||||
HAWK_RTX_STACK_POP (rtx);
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -2687,7 +2636,7 @@ static int run_return (hawk_rtx_t* rtx, hawk_nde_return_t* nde)
|
||||
|
||||
static int run_exit (hawk_rtx_t* rtx, hawk_nde_exit_t* nde)
|
||||
{
|
||||
if (nde->val != HAWK_NULL)
|
||||
if (nde->val)
|
||||
{
|
||||
hawk_val_t* val;
|
||||
|
||||
@ -5938,7 +5887,7 @@ static hawk_val_t* eval_fncall_fnc (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
hawk_nde_fncall_t* call = (hawk_nde_fncall_t*)nde;
|
||||
/* the parser must make sure that the number of arguments is proper */
|
||||
HAWK_ASSERT (call->nargs >= call->u.fnc.spec.arg.min && call->nargs <= call->u.fnc.spec.arg.max);
|
||||
return __eval_call(rtx, nde, 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_ex (hawk_rtx_t* rtx, hawk_nde_t* nde, void(*errhandler)(void*), void* eharg)
|
||||
@ -5982,7 +5931,7 @@ static HAWK_INLINE hawk_val_t* eval_fncall_fun_ex (hawk_rtx_t* rtx, hawk_nde_t*
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
return __eval_call(rtx, nde, fun, push_arg_from_nde, HAWK_NULL, errhandler, eharg);
|
||||
return hawk_rtx_evalcall(rtx, call, fun, push_arg_from_nde, fun->argspec, errhandler, eharg);
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_fncall_fun (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
@ -5997,11 +5946,11 @@ static hawk_val_t* eval_fncall_var (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
hawk_fun_t* fun;
|
||||
|
||||
fv = eval_expression(rtx, (hawk_nde_t*)call->u.var.var);
|
||||
if (!fv) return HAWK_NULL;
|
||||
if (HAWK_UNLIKELY(!fv)) return HAWK_NULL;
|
||||
|
||||
hawk_rtx_refupval (rtx, fv);
|
||||
fun = hawk_rtx_valtofun(rtx, fv);
|
||||
if (!fun)
|
||||
if (HAWK_UNLIKELY(!fun))
|
||||
{
|
||||
if (hawk_rtx_geterrnum(rtx) == HAWK_EINVAL)
|
||||
hawk_rtx_seterrfmt (rtx, &nde->loc, HAWK_ENOTFUN, HAWK_T("non-function value in %.*js"), call->u.var.var->id.name.len, call->u.var.var->id.name.ptr);
|
||||
@ -6010,48 +5959,20 @@ static hawk_val_t* eval_fncall_var (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = __eval_call(rtx, nde, fun, push_arg_from_nde, HAWK_NULL, HAWK_NULL, HAWK_NULL);
|
||||
rv = hawk_rtx_evalcall(rtx, call, fun, push_arg_from_nde, fun->argspec, HAWK_NULL, HAWK_NULL);
|
||||
}
|
||||
hawk_rtx_refdownval (rtx, fv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* run->stack_base has not been set for this
|
||||
* stack frame. so the HAWK_RTX_STACK_ARG macro cannot be used as in
|
||||
* hawk_rtx_refdownval (run, HAWK_RTX_STACK_ARG(run,nargs));*/
|
||||
#define UNWIND_HAWK_RTX_STACK_ARG(rtx,nargs) \
|
||||
do { \
|
||||
while ((nargs) > 0) \
|
||||
{ \
|
||||
--(nargs); \
|
||||
hawk_rtx_refdownval ((rtx), (rtx)->stack[(rtx)->stack_top-1]); \
|
||||
__raw_pop (rtx); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define UNWIND_HAWK_RTX_STACK_BASE(rtx) \
|
||||
do { \
|
||||
__raw_pop (rtx); /* nargs */ \
|
||||
__raw_pop (rtx); /* return */ \
|
||||
__raw_pop (rtx); /* prev stack top */ \
|
||||
__raw_pop (rtx); /* prev stack back */ \
|
||||
} while (0)
|
||||
|
||||
#define UNWIND_RTX_STACK(rtx,nargs) \
|
||||
do { \
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx,nargs); \
|
||||
UNWIND_HAWK_RTX_STACK_BASE (rtx); \
|
||||
} while (0)
|
||||
|
||||
static hawk_val_t* __eval_call (
|
||||
hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_fun_t* fun,
|
||||
hawk_val_t* hawk_rtx_evalcall (
|
||||
hawk_rtx_t* rtx, hawk_nde_fncall_t* call, hawk_fun_t* fun,
|
||||
hawk_oow_t(*argpusher)(hawk_rtx_t*,hawk_nde_fncall_t*,void*), void* apdata,
|
||||
void(*errhandler)(void*), void* eharg)
|
||||
{
|
||||
hawk_nde_fncall_t* call = (hawk_nde_fncall_t*)nde;
|
||||
hawk_oow_t saved_stack_top;
|
||||
hawk_oow_t nargs, i;
|
||||
hawk_oow_t saved_stack_top, saved_arg_stack_top;
|
||||
hawk_oow_t nargs, i, stack_req;
|
||||
hawk_val_t* v;
|
||||
int n;
|
||||
|
||||
@ -6104,88 +6025,47 @@ static hawk_val_t* __eval_call (
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("setting up function stack frame top=%zd base=%zd\n"), (hawk_oow_t)rtx->stack_top, (hawk_oow_t)rtx->stack_base);
|
||||
#endif
|
||||
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,(void*)rtx->stack_base) <= -1))
|
||||
/* make a new stack frame */
|
||||
stack_req = 4 + call->nargs;
|
||||
if (fun)
|
||||
{
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
HAWK_ASSERT (fun->nargs >= call->nargs); /* the compiler must guarantee this */
|
||||
stack_req += fun->nargs - call->nargs;
|
||||
}
|
||||
/* if fun is HAWK_NULL, there is no way for this function to know expected argument numbers.
|
||||
* the argument pusher must ensure the stack availality before pushing arguments */
|
||||
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < stack_req))
|
||||
{
|
||||
hawk_rtx_seterrnum (rtx, &call->loc, HAWK_ESTACK);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,(void*)saved_stack_top) <= -1))
|
||||
{
|
||||
__raw_pop (rtx);
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
HAWK_RTX_STACK_PUSH (rtx, (void*)rtx->stack_base);
|
||||
HAWK_RTX_STACK_PUSH (rtx, (void*)saved_stack_top);
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); /* space for return value */
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil); /* space for number of arguments */
|
||||
|
||||
/* secure space for a return value. */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1))
|
||||
{
|
||||
__raw_pop (rtx);
|
||||
__raw_pop (rtx);
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
/* secure space for nargs */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,hawk_val_nil) <= -1))
|
||||
{
|
||||
__raw_pop (rtx);
|
||||
__raw_pop (rtx);
|
||||
__raw_pop (rtx);
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
saved_arg_stack_top = rtx->stack_top;
|
||||
|
||||
/* push all arguments onto the stack */
|
||||
nargs = argpusher(rtx, call, apdata);
|
||||
if (nargs == (hawk_oow_t)-1)
|
||||
{
|
||||
UNWIND_HAWK_RTX_STACK_BASE (rtx);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
if (nargs == (hawk_oow_t)-1) goto oops_making_stack_frame;
|
||||
|
||||
HAWK_ASSERT (nargs == call->nargs);
|
||||
|
||||
if (fun)
|
||||
{
|
||||
/* extra step for normal awk functions */
|
||||
|
||||
if (fun->argspec && call->args) /* hawk_rtx_callfun() sets up a fake call structure with nargs > 0 but args == HAWK_NULL */
|
||||
{
|
||||
/* sanity check for pass-by-reference parameters of a normal awk function.
|
||||
* it tests if each pass-by-reference argument is referenceable. */
|
||||
|
||||
hawk_nde_t* p = call->args;
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if (fun->argspec[i] == HAWK_T('r'))
|
||||
{
|
||||
hawk_val_t** ref;
|
||||
|
||||
if (get_reference(rtx, p, &ref) <= -1)
|
||||
{
|
||||
UNWIND_RTX_STACK (rtx, nargs);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
while (nargs < fun->nargs)
|
||||
{
|
||||
/* push as many nils as the number of missing actual arguments */
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx, hawk_val_nil) <= -1))
|
||||
{
|
||||
UNWIND_RTX_STACK (rtx, nargs);
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
HAWK_RTX_STACK_PUSH (rtx, hawk_val_nil);
|
||||
nargs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* entering a new stack frame */
|
||||
rtx->stack_base = saved_stack_top;
|
||||
HAWK_RTX_STACK_NARGS(rtx) = (void*)nargs;
|
||||
|
||||
@ -6209,7 +6089,7 @@ static hawk_val_t* __eval_call (
|
||||
if (call->u.fnc.spec.impl)
|
||||
{
|
||||
n = call->u.fnc.spec.impl(rtx, &call->u.fnc.info);
|
||||
if (HAWK_UNLIKELY(n <= -1)) ADJERR_LOC (rtx, &nde->loc);
|
||||
if (HAWK_UNLIKELY(n <= -1)) ADJERR_LOC (rtx, &call->loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6219,7 +6099,8 @@ static hawk_val_t* __eval_call (
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("block rtx complete nargs = %d\n"), (int)nargs);
|
||||
#endif
|
||||
|
||||
if (fun && fun->argspec && call->args && call->nargs > 0) /* hawk_rtx_callfun() sets up a fake call structure with nargs > 0 but args == HAWK_NULL */
|
||||
i = 0;
|
||||
if (fun && fun->argspec && call->nargs > 0) /* hawk_rtx_callfun() sets up a fake call structure with call->nargs > 0 but call->args == HAWK_NULL */
|
||||
{
|
||||
/* set back the values for pass-by-reference parameters of normal functions.
|
||||
* the intrinsic functions are not handled here but their implementation would
|
||||
@ -6231,51 +6112,87 @@ static hawk_val_t* __eval_call (
|
||||
* all parameters are nils in this case. nargs and fun->nargs are 2 but call->nargs is 0.
|
||||
*/
|
||||
|
||||
if (call->args)
|
||||
{
|
||||
hawk_oow_t cur_stack_base = rtx->stack_base;
|
||||
hawk_oow_t prev_stack_base = (hawk_oow_t)rtx->stack[rtx->stack_base + 0];
|
||||
|
||||
hawk_nde_t* p = call->args;
|
||||
for (i = 0; i < call->nargs; i++)
|
||||
|
||||
for (; i < call->nargs; i++)
|
||||
{
|
||||
if (n >= 0 && fun->argspec[i] == HAWK_T('r'))
|
||||
if (n >= 0 && (fun->argspec[i] == 'r' || fun->argspec[i] == 'R'))
|
||||
{
|
||||
hawk_val_t** ref;
|
||||
hawk_val_ref_t refv;
|
||||
int r;
|
||||
|
||||
/* if an argument passed is a local variable or a parameter to the previous caller,
|
||||
* the argument node information stored is relative to the previous stack frame.
|
||||
* i revert rtx->stack_base to the previous stack frame base before calling
|
||||
* get_reference() and restors it back to the current base. this tactic
|
||||
* is very ugly because the assumptions for this is dependent on get_reference()
|
||||
* is very ugly because the assumptions for this is depecallnt on get_reference()
|
||||
* implementation */
|
||||
rtx->stack_base = prev_stack_base; /* UGLY */
|
||||
get_reference (rtx, p, &ref); /* no failure check as it must succeed here for the check done above */
|
||||
r = get_reference(rtx, p, &ref);
|
||||
rtx->stack_base = cur_stack_base; /* UGLY */
|
||||
|
||||
/* if argspec is 'r', get_reference() must succeed all the time.
|
||||
* if argspec is 'R', it may fail. if it happens, don't copy the value */
|
||||
if (HAWK_LIKELY(r >= 0))
|
||||
{
|
||||
HAWK_RTX_INIT_REF_VAL (&refv, p->type - HAWK_NDE_NAMED, ref, 9); /* initialize a fake reference variable. 9 chosen randomly */
|
||||
if (HAWK_UNLIKELY(hawk_rtx_setrefval(rtx, &refv, HAWK_RTX_STACK_ARG(rtx, i)) <= -1))
|
||||
{
|
||||
n = -1;
|
||||
ADJERR_LOC (rtx, &nde->loc);
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i));
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else if (call->arg_base > 0) /* special case. set by hawk::call() */
|
||||
{
|
||||
/*
|
||||
* function f1(a,&b) { b *= 20; }
|
||||
* BEGIN { q = 4; hawk::call(r, "f1", 20, q); print q;
|
||||
* }
|
||||
* the fourth argument to hawk::call() must map to the second argument to f1().
|
||||
* hawk::call() accepts the third to the last arguments as reference if possible.
|
||||
* this function attempts to copy back the pass-by-reference values to
|
||||
* one stack frame up.
|
||||
*
|
||||
* f1(1, 2) is an error as 2 is not referenceable.
|
||||
* hakw::call(r, "f1", 1, 2) is not an error but can't capture changes made inside f1.
|
||||
*/
|
||||
for (; i < call->nargs; i++)
|
||||
{
|
||||
if (n >= 0 && (fun->argspec[i] == 'r' || fun->argspec[i] == 'R'))
|
||||
{
|
||||
hawk_val_t* v;
|
||||
|
||||
v = rtx->stack[call->arg_base + i]; /* UGLY */
|
||||
if (HAWK_RTX_GETVALTYPE(rtx, v) == HAWK_VAL_REF)
|
||||
{
|
||||
if (HAWK_UNLIKELY(hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)v, HAWK_RTX_STACK_ARG(rtx, i)) <= -1))
|
||||
{
|
||||
n = -1;
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < nargs; i++)
|
||||
{
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG_RUN)
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("got return value\n"));
|
||||
@ -6286,13 +6203,13 @@ static hawk_val_t* __eval_call (
|
||||
{
|
||||
if (hawk_rtx_geterrnum(rtx) == HAWK_ENOERR && errhandler != HAWK_NULL)
|
||||
{
|
||||
/* errhandler is passed only when __eval_call() is
|
||||
* invoked from hawk_rtx_call(). Under this
|
||||
/* errhandler is passed only when hawk_rtx_evalcall() is
|
||||
* invoked from hawk_rtx_call(). Ucallr this
|
||||
* circumstance, this stack frame is the first
|
||||
* activated and the stack base is the first element
|
||||
* after the global variables. so HAWK_RTX_STACK_RETVAL(rtx)
|
||||
* effectively becomes HAWK_RTX_STACK_RETVAL_GBL(rtx).
|
||||
* As __eval_call() returns HAWK_NULL on error and
|
||||
* As hawk_rtx_evalcall() returns HAWK_NULL on error and
|
||||
* the reference count of HAWK_RTX_STACK_RETVAL(rtx) should be
|
||||
* decremented, it can't get the return value
|
||||
* if it turns out to be terminated by exit().
|
||||
@ -6336,6 +6253,27 @@ static hawk_val_t* __eval_call (
|
||||
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("returning from function top=%zd, base=%zd\n"), (hawk_oow_t)rtx->stack_top, (hawk_oow_t)rtx->stack_base);
|
||||
#endif
|
||||
return (n <= -1)? HAWK_NULL: v;
|
||||
|
||||
oops_making_stack_frame:
|
||||
while (rtx->stack_top > saved_arg_stack_top)
|
||||
{
|
||||
/* call hawk_rtx_refdownval() for all arguments.
|
||||
* it is safe because nil or quickint is immune to excessive hawk_rtx_refdownval() calls */
|
||||
hawk_rtx_refdownval(rtx, rtx->stack[rtx->stack_top - 1]);
|
||||
HAWK_RTX_STACK_POP (rtx);
|
||||
}
|
||||
HAWK_ASSERT (rtx->stack_top - saved_stack_top == 4);
|
||||
while (rtx->stack_top > saved_stack_top)
|
||||
{
|
||||
/* the stack frame prologue does not have a reference-counted value
|
||||
* before being entered. so no hawk_rtx_refdownval().
|
||||
* three slots contains raw integers for internal use.. only one
|
||||
* slot that contains the return value would be reference counted
|
||||
* after it is set to a reference counted value. here, it never happens */
|
||||
HAWK_RTX_STACK_POP (rtx);
|
||||
}
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_oow_t push_arg_from_vals (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, void* data)
|
||||
@ -6343,51 +6281,33 @@ static hawk_oow_t push_arg_from_vals (hawk_rtx_t* rtx, hawk_nde_fncall_t* call,
|
||||
struct pafv_t* pafv = (struct pafv_t*)data;
|
||||
hawk_oow_t nargs = 0;
|
||||
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < pafv->nargs))
|
||||
{
|
||||
hawk_rtx_seterrnum (rtx, &call->loc, HAWK_ESTACK);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
for (nargs = 0; nargs < pafv->nargs; nargs++)
|
||||
{
|
||||
if (pafv->argspec && pafv->argspec[nargs] == HAWK_T('r'))
|
||||
if (pafv->argspec && (pafv->argspec[nargs] == 'r' || pafv->argspec[nargs] == 'R'))
|
||||
{
|
||||
hawk_val_t** ref;
|
||||
hawk_val_t* v;
|
||||
|
||||
ref = (hawk_val_t**)&pafv->args[nargs];
|
||||
v = hawk_rtx_makerefval(rtx, HAWK_VAL_REF_LCL, ref); /* this type(HAWK_VAL_REF_LCL) is fake */
|
||||
if (!v)
|
||||
if (HAWK_UNLIKELY(!v))
|
||||
{
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx, v) <= -1))
|
||||
{
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
hawk_rtx_refdownval (rtx, v);
|
||||
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
HAWK_RTX_STACK_PUSH (rtx, v);
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx, pafv->args[nargs]) <= -1))
|
||||
{
|
||||
/* ugly - arg needs to be freed if it doesn't have
|
||||
* any reference. but its reference has not been
|
||||
* updated yet as it is carried out after successful
|
||||
* stack push. so it adds up a reference and
|
||||
* dereferences it */
|
||||
hawk_rtx_refupval (rtx, pafv->args[nargs]);
|
||||
hawk_rtx_refdownval (rtx, pafv->args[nargs]);
|
||||
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
HAWK_RTX_STACK_PUSH (rtx, pafv->args[nargs]);
|
||||
hawk_rtx_refupval (rtx, pafv->args[nargs]);
|
||||
}
|
||||
}
|
||||
@ -6400,11 +6320,17 @@ static hawk_oow_t push_arg_from_nde (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, v
|
||||
hawk_nde_t* p;
|
||||
hawk_val_t* v;
|
||||
hawk_oow_t nargs;
|
||||
const hawk_ooch_t* fnc_arg_spec = (const hawk_ooch_t*)data;
|
||||
const hawk_ooch_t* arg_spec = (const hawk_ooch_t*)data;
|
||||
hawk_oow_t spec_len;
|
||||
|
||||
spec_len = fnc_arg_spec? hawk_count_oocstr(fnc_arg_spec): 0;
|
||||
for (p = call->args, nargs = 0; p != HAWK_NULL; p = p->next, nargs++)
|
||||
if (HAWK_UNLIKELY(HAWK_RTX_STACK_AVAIL(rtx) < call->nargs))
|
||||
{
|
||||
hawk_rtx_seterrnum (rtx, &call->loc, HAWK_ESTACK);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
spec_len = arg_spec? hawk_count_oocstr(arg_spec): 0;
|
||||
for (p = call->args, nargs = 0; p; p = p->next, nargs++)
|
||||
{
|
||||
hawk_ooch_t spec;
|
||||
|
||||
@ -6414,59 +6340,47 @@ static hawk_oow_t push_arg_from_nde (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, v
|
||||
{
|
||||
/* not sufficient number of spec characters given.
|
||||
* take the last value and use it */
|
||||
spec = fnc_arg_spec[spec_len - 1];
|
||||
spec = arg_spec[spec_len - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
spec = fnc_arg_spec[nargs];
|
||||
spec = arg_spec[nargs];
|
||||
}
|
||||
}
|
||||
else spec = '\0';
|
||||
|
||||
if (spec == 'r')
|
||||
switch (spec)
|
||||
{
|
||||
case 'R': /* make reference if a referenceable is given. otherwise accept a normal value - useful for hawk::call() */
|
||||
case 'r': /* make reference. a non-referenceable value is rejected */
|
||||
{
|
||||
hawk_val_t** ref;
|
||||
|
||||
if (get_reference(rtx, p, &ref) <= -1)
|
||||
{
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
return (hawk_oow_t)-1;
|
||||
if (spec == 'R') goto normal_arg;
|
||||
return (hawk_oow_t)-1; /* return -1 without unwinding stack as hawk_rtx_evalcall() does it */
|
||||
}
|
||||
|
||||
/* 'p->type - HAWK_NDE_NAMED' must produce a relevant HAWK_VAL_REF_XXX value. */
|
||||
v = hawk_rtx_makerefval(rtx, p->type - HAWK_NDE_NAMED, ref);
|
||||
break;
|
||||
}
|
||||
else if (spec == 'x')
|
||||
{
|
||||
|
||||
case 'x':
|
||||
/* a regular expression is passed to the function as it is */
|
||||
v = eval_expression0(rtx, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
default:
|
||||
normal_arg:
|
||||
v = eval_expression(rtx, p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (HAWK_UNLIKELY(!v))
|
||||
{
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
|
||||
if (HAWK_UNLIKELY(__raw_push(rtx,v) <= -1))
|
||||
{
|
||||
/* ugly - v needs to be freed if it doesn't have
|
||||
* any reference. but its reference has not been
|
||||
* updated yet as it is carried out after the
|
||||
* successful stack push. so it adds up a reference
|
||||
* and dereferences it */
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
hawk_rtx_refdownval (rtx, v);
|
||||
|
||||
UNWIND_HAWK_RTX_STACK_ARG (rtx, nargs);
|
||||
ADJERR_LOC (rtx, &call->loc);
|
||||
return (hawk_oow_t)-1;
|
||||
}
|
||||
if (HAWK_UNLIKELY(!v)) return (hawk_oow_t)-1; /* return -1 without unwinding stack as hawk_rtx_evalcall() does it */
|
||||
|
||||
HAWK_RTX_STACK_PUSH (rtx, v);
|
||||
hawk_rtx_refupval (rtx, v);
|
||||
}
|
||||
|
||||
|
@ -224,6 +224,7 @@ struct hawk_nde_fncall_t
|
||||
} u;
|
||||
hawk_nde_t* args;
|
||||
hawk_oow_t nargs;
|
||||
hawk_oow_t arg_base; /* special field set by hawk::call() and handled by hawk_rtx_evalcall() */
|
||||
};
|
||||
|
||||
/* HAWK_NDE_GETLINE */
|
||||
|
Loading…
x
Reference in New Issue
Block a user