call-by-reference handling with a true multidimensional map

This commit is contained in:
hyung-hwan 2020-04-04 17:40:56 +00:00
parent 82eac76de4
commit ca1877d412
2 changed files with 74 additions and 71 deletions

View File

@ -184,7 +184,7 @@ static hawk_val_t* __eval_call (
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* nde, hawk_val_t** val);
static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var);
static hawk_val_t* eval_int (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_flt (hawk_rtx_t* rtx, hawk_nde_t* nde);
@ -3604,7 +3604,7 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde)
v = __evaluator[nde->type-HAWK_NDE_GRP](rtx, nde);
if (v != HAWK_NULL && rtx->exit_level >= EXIT_GLOBAL)
if (HAWK_UNLIKELY(v && rtx->exit_level >= EXIT_GLOBAL))
{
hawk_rtx_refupval (rtx, v);
hawk_rtx_refdownval (rtx, v);
@ -3649,7 +3649,7 @@ static hawk_val_t* eval_group (hawk_rtx_t* rtx, hawk_nde_t* nde)
loop:
val = eval_expression (rtx, np);
if (val == HAWK_NULL) return HAWK_NULL;
if (HAWK_UNLIKELY(!val)) return HAWK_NULL;
np = np->next;
if (np)
@ -6267,12 +6267,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 (n <= -1)
{
ADJERR_LOC (rtx, &nde->loc);
/* correct the return code just in case */
if (n < -1) n = -1;
}
if (HAWK_UNLIKELY(n <= -1)) ADJERR_LOC (rtx, &nde->loc);
}
}
@ -6300,7 +6295,7 @@ static hawk_val_t* __eval_call (
hawk_nde_t* p = call->args;
for (i = 0; i < call->nargs; i++)
{
if (fun->argspec[i] == HAWK_T('r'))
if (n >= 0 && fun->argspec[i] == HAWK_T('r'))
{
hawk_val_t** ref;
hawk_val_ref_t refv;
@ -6316,7 +6311,11 @@ static hawk_val_t* __eval_call (
rtx->stack_base = cur_stack_base; /* UGLY */
HAWK_RTX_INIT_REF_VAL (&refv, p->type - HAWK_NDE_NAMED, ref, 9); /* initialize a fake reference variable. 9 chosen randomly */
hawk_rtx_setrefval (rtx, &refv, HAWK_RTX_STACK_ARG(rtx, i));
if (HAWK_UNLIKELY(hawk_rtx_setrefval(rtx, &refv, HAWK_RTX_STACK_ARG(rtx, i)) <= -1))
{
n = -1;
ADJERR_LOC (rtx, &nde->loc);
}
}
hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i));
@ -6341,7 +6340,7 @@ static hawk_val_t* __eval_call (
#endif
v = HAWK_RTX_STACK_RETVAL(rtx);
if (n == -1)
if (HAWK_UNLIKELY(n <= -1))
{
if (hawk_rtx_geterrnum(rtx) == HAWK_ENOERR && errhandler != HAWK_NULL)
{
@ -6394,7 +6393,7 @@ static hawk_val_t* __eval_call (
#if defined(DEBUG_RUN)
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;
return (n <= -1)? HAWK_NULL: v;
}
static hawk_oow_t push_arg_from_vals (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, void* data)
@ -6577,41 +6576,11 @@ static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref)
return 0;
case HAWK_NDE_NAMEDIDX:
{
hawk_htb_pair_t* pair;
pair = hawk_htb_search(rtx->named, tgt->id.name.ptr, tgt->id.name.len);
if (pair == HAWK_NULL)
{
pair = hawk_htb_upsert(rtx->named, tgt->id.name.ptr, tgt->id.name.len, hawk_val_nil, 0);
if (pair == HAWK_NULL)
{
ADJERR_LOC (rtx, &nde->loc);
return -1;
}
}
tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_HTB_VPTR(pair));
if (tmp == HAWK_NULL) return -1;
*ref = tmp;
return 0;
}
case HAWK_NDE_GBLIDX:
tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_GBL(rtx,tgt->id.idxa));
if (tmp == HAWK_NULL) return -1;
*ref = tmp;
return 0;
case HAWK_NDE_LCLIDX:
tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_LCL(rtx,tgt->id.idxa));
if (tmp == HAWK_NULL) return -1;
*ref = tmp;
return 0;
case HAWK_NDE_ARGIDX:
tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_ARG(rtx,tgt->id.idxa));
if (tmp == HAWK_NULL) return -1;
tmp = get_reference_indexed(rtx, tgt);
if (HAWK_UNLIKELY(!tmp)) return -1;
*ref = tmp;
return 0;
@ -6624,13 +6593,13 @@ static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref)
/* the position number is returned for the positional
* variable unlike other reference types. */
v = eval_expression(rtx, ((hawk_nde_pos_t*)nde)->val);
if (v == HAWK_NULL) return -1;
if (HAWK_UNLIKELY(!v)) return -1;
hawk_rtx_refupval (rtx, v);
n = hawk_rtx_valtoint(rtx, v, &lv);
hawk_rtx_refdownval (rtx, v);
if (n <= -1)
if (HAWK_UNLIKELY(n <= -1))
{
hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_EPOSIDX);
return -1;
@ -6652,51 +6621,83 @@ 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* nde, hawk_val_t** val)
static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
{
hawk_map_t* map;
hawk_map_pair_t* pair;
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_val_t* v;
hawk_val_type_t vtype;
hawk_nde_t* remidx;
HAWK_ASSERT (val != HAWK_NULL);
HAWK_ASSERT (var->idx != HAWK_NULL);
vtype = HAWK_RTX_GETVALTYPE(rtx, *val);
if (vtype == HAWK_VAL_NIL)
v = fetch_topval_from_var(rtx, var);
vtype = HAWK_RTX_GETVALTYPE(rtx, v);
switch (vtype)
{
hawk_val_t* tmp;
case HAWK_VAL_NIL:
v = assign_newmapval_to_var(rtx, var);
if (HAWK_UNLIKELY(!v)) goto oops;
break;
case HAWK_VAL_MAP:
/* do nothing */
break;
tmp = hawk_rtx_makemapval(rtx);
if (HAWK_UNLIKELY(!tmp)) goto oops;
hawk_rtx_refdownval (rtx, *val);
*val = tmp;
hawk_rtx_refupval (rtx, (hawk_val_t*)*val);
default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP);
goto oops;
}
else if (vtype != HAWK_VAL_MAP)
{
hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENOTMAP);
goto oops;
}
HAWK_ASSERT (nde->idx != HAWK_NULL);
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, nde->idx, idxbuf, &len, &remidx);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)v)->map;
#if defined(HAWK_ENABLE_GC)
/* TODO: true-multidimensional map support */
while (remidx)
{
pair = hawk_map_search(map, str, len);
v = pair? (hawk_val_t*)HAWK_HTB_VPTR(pair): hawk_val_nil;
vtype = HAWK_RTX_GETVALTYPE(rtx, v);
switch (vtype)
{
case HAWK_VAL_NIL:
v = assign_newmapval_in_map(rtx, map, str, len);
if (HAWK_UNLIKELY(!v)) goto oops;
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_MAP:
map = ((hawk_val_map_t*)v)->map;
break;
default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP);
goto oops;
}
if (str != idxbuf) hawk_rtx_freemem (rtx, str);
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
}
#endif
pair = hawk_map_search((*(hawk_val_map_t**)val)->map, str, len);
pair = hawk_map_search(map, str, len);
if (!pair)
{
pair = hawk_map_upsert((*(hawk_val_map_t**)val)->map, str, len, hawk_val_nil, 0);
pair = hawk_map_upsert(map, str, len, hawk_val_nil, 0);
if (HAWK_UNLIKELY(!pair)) goto oops;
hawk_rtx_refupval (rtx, HAWK_HTB_VPTR(pair));
HAWK_ASSERT (HAWK_HTB_VPTR(pair) == hawk_val_nil);
/* no reference count increment as hawk_val_nil is upserted
hawk_rtx_refupval (rtx, HAWK_HTB_VPTR(pair)); */
}
if (str != idxbuf) hawk_rtx_freemem (rtx, str);
@ -6704,7 +6705,7 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde,
oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
ADJERR_LOC (rtx, &nde->loc);
ADJERR_LOC (rtx, &var->loc);
return HAWK_NULL;
}

View File

@ -2503,6 +2503,7 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val)
case HAWK_VAL_REF_GBLIDX:
case HAWK_VAL_REF_LCLIDX:
case HAWK_VAL_REF_ARGIDX:
#if !defined(HAWK_ENABLE_GC)
if (vtype == HAWK_VAL_MAP)
{
/* an indexed variable cannot be assigned a map.
@ -2510,6 +2511,7 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val)
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOIDX);
return -1;
}
#endif
/* fall through */
default: