enhanced array manipulation code

This commit is contained in:
hyung-hwan 2020-04-26 15:28:44 +00:00
parent d497e51b62
commit 881dfd2ce0
10 changed files with 286 additions and 284 deletions

View File

@ -244,7 +244,7 @@ To know the current type of a value, call typename().
BEGIN { BEGIN {
a="hello"; a="hello";
b=12345; b=12345;
print typename(a), typename(b), typename(c), typename(f), typename(1.23), typename(B"world"); print hawk::typename(a), hawk::typename(b), hawk::typename(c), hawk::typename(f), hawk::typename(1.23), hawk::typename(B"world");
} }
A regular expression literal is special in that it never appears as an indendent value and still entails a match operation against $0 without an match operator. A regular expression literal is special in that it never appears as an indendent value and still entails a match operation against $0 without an match operator.

View File

@ -141,6 +141,8 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
HAWK_T("value not a map"), HAWK_T("value not a map"),
HAWK_T("right-hand side of the 'in' operator not a map"), HAWK_T("right-hand side of the 'in' operator not a map"),
HAWK_T("right-hand side of the 'in' operator not a map nor nil"), HAWK_T("right-hand side of the 'in' operator not a map nor nil"),
HAWK_T("value not an array"),
HAWK_T("value not accessible with index"),
HAWK_T("value not referenceable"), HAWK_T("value not referenceable"),
HAWK_T("cannot return a nonscalar value"), /* ENONSCARET */ HAWK_T("cannot return a nonscalar value"), /* ENONSCARET */
HAWK_T("cannot assign a nonscalar value to a positional"), /* ENONSCATOPOS */ HAWK_T("cannot assign a nonscalar value to a positional"), /* ENONSCATOPOS */

View File

@ -1788,7 +1788,7 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
a0_type = HAWK_RTX_GETVALTYPE(rtx, a0); a0_type = HAWK_RTX_GETVALTYPE(rtx, a0);
HAWK_ASSERT (a0_type == HAWK_VAL_REF); HAWK_ASSERT (a0_type == HAWK_VAL_REF);
/* TODO: handel HAWK_VAL_ARR */ /* TODO: handle HAWK_VAL_ARR as input */
v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0); v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0);
if (v_type != HAWK_VAL_MAP) if (v_type != HAWK_VAL_MAP)
{ {

View File

@ -328,8 +328,8 @@ HAWK_EXPORT hawk_oow_t hawk_arr_update (
*/ */
HAWK_EXPORT hawk_oow_t hawk_arr_delete ( HAWK_EXPORT hawk_oow_t hawk_arr_delete (
hawk_arr_t* arr, hawk_arr_t* arr,
hawk_oow_t index, hawk_oow_t index,
hawk_oow_t count hawk_oow_t count
); );
/** /**
@ -338,8 +338,8 @@ HAWK_EXPORT hawk_oow_t hawk_arr_delete (
*/ */
HAWK_EXPORT hawk_oow_t hawk_arr_uplete ( HAWK_EXPORT hawk_oow_t hawk_arr_uplete (
hawk_arr_t* arr, hawk_arr_t* arr,
hawk_oow_t index, hawk_oow_t index,
hawk_oow_t count hawk_oow_t count
); );
HAWK_EXPORT void hawk_arr_clear ( HAWK_EXPORT void hawk_arr_clear (

View File

@ -976,6 +976,8 @@ enum hawk_errnum_t
HAWK_ENOTMAP, /**< value not a map */ HAWK_ENOTMAP, /**< value not a map */
HAWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */ HAWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */
HAWK_ENOTMAPNILIN, /**< right-hand side of 'in' not a map nor nil */ HAWK_ENOTMAPNILIN, /**< right-hand side of 'in' not a map nor nil */
HAWK_ENOTARR, /**< value not an array */
HAWK_ENOTIDXACC, /**< value not accessible with index */
HAWK_ENOTREF, /**< value not referenceable */ HAWK_ENOTREF, /**< value not referenceable */
HAWK_ENONSCARET, /**< nonscalar value cannot be returned */ HAWK_ENONSCARET, /**< nonscalar value cannot be returned */
HAWK_ENONSCATOPOS, /**< nonscalar value cannot be assigned to a positional */ HAWK_ENONSCATOPOS, /**< nonscalar value cannot be assigned to a positional */

View File

@ -2887,7 +2887,7 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_makerexval (
*/ */
HAWK_EXPORT hawk_val_t* hawk_rtx_makearrval ( HAWK_EXPORT hawk_val_t* hawk_rtx_makearrval (
hawk_rtx_t* rtx, hawk_rtx_t* rtx,
hawk_oow_t init_capa hawk_ooi_t init_capa
); );
/** /**

View File

@ -225,7 +225,7 @@ static int fnc_array (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
hawk_val_t* tmp; hawk_val_t* tmp;
tmp = hawk_rtx_makearrval(rtx, 0); tmp = hawk_rtx_makearrval(rtx, -1);
if (HAWK_UNLIKELY(!tmp)) return -1; /* hard failure */ if (HAWK_UNLIKELY(!tmp)) return -1; /* hard failure */
/* TODO: take arguments and put them to the map */ /* TODO: take arguments and put them to the map */

View File

@ -126,9 +126,9 @@ static hawk_val_t* eval_group (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_assignment (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_assignment (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t* val); static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t* val);
static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val); static hawk_val_t* do_assignment_nonindexed (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val);
static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val); static hawk_val_t* do_assignment_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val);
static hawk_val_t* do_assignment_pos (hawk_rtx_t* rtx, hawk_nde_pos_t* pos, hawk_val_t* val); static hawk_val_t* do_assignment_positional (hawk_rtx_t* rtx, hawk_nde_pos_t* pos, hawk_val_t* val);
static hawk_val_t* eval_binary (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_binary (hawk_rtx_t* rtx, hawk_nde_t* nde);
static hawk_val_t* eval_binop_lor (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right); static hawk_val_t* eval_binop_lor (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right);
@ -685,7 +685,7 @@ int hawk_rtx_setgbltostrbyname (hawk_rtx_t* rtx, const hawk_ooch_t* name, const
var.id.idxa = (hawk_oow_t)-1; var.id.idxa = (hawk_oow_t)-1;
var.idx = HAWK_NULL; var.idx = HAWK_NULL;
n = do_assignment_nonidx(rtx, &var, v)? 0: -1; n = do_assignment_nonindexed(rtx, &var, v)? 0: -1;
} }
else else
{ {
@ -2849,8 +2849,7 @@ static hawk_val_t* assign_newmapval_in_map (hawk_rtx_t* rtx, hawk_map_t* contain
tmp = hawk_rtx_makemapval(rtx); tmp = hawk_rtx_makemapval(rtx);
if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL; if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL;
/* as this is the assignment, it needs to update /* as this is the assignment, it needs to update the reference count of the target value. */
* the reference count of the target value. */
hawk_rtx_refupval (rtx, tmp); hawk_rtx_refupval (rtx, tmp);
pair = hawk_map_upsert(container, idxptr, idxlen, tmp, 0); pair = hawk_map_upsert(container, idxptr, idxlen, tmp, 0);
if (HAWK_UNLIKELY(!pair)) if (HAWK_UNLIKELY(!pair))
@ -2863,23 +2862,20 @@ static hawk_val_t* assign_newmapval_in_map (hawk_rtx_t* rtx, hawk_map_t* contain
return tmp; return tmp;
} }
static hawk_val_t* assign_newmapval_in_arr (hawk_rtx_t* rtx, hawk_arr_t* container, hawk_ooi_t idx) static hawk_val_t* assign_newarrval_in_arr (hawk_rtx_t* rtx, hawk_arr_t* container, hawk_ooi_t idx)
{ {
hawk_val_t* tmp; hawk_val_t* tmp;
hawk_map_pair_t* pair;
tmp = hawk_rtx_makemapval(rtx); tmp = hawk_rtx_makearrval(rtx, -1);
if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL; if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL;
/* as this is the assignment, it needs to update /* as this is the assignment, it needs to update the reference count of the target value. */
* the reference count of the target value. */
hawk_rtx_refupval (rtx, tmp); hawk_rtx_refupval (rtx, tmp);
if (HAWK_UNLIKELY(hawk_arr_upsert(container, idx, tmp, 0) == HAWK_VAL_NIL)) if (HAWK_UNLIKELY(hawk_arr_upsert(container, idx, tmp, 0) == HAWK_ARR_NIL))
{ {
hawk_rtx_refdownval (rtx, tmp); /* decrement upon upsert() failure */ hawk_rtx_refdownval (rtx, tmp); /* decrement upon upsert() failure */
return HAWK_NULL; return HAWK_NULL;
} }
return tmp; return tmp;
} }
@ -3049,26 +3045,39 @@ static HAWK_INLINE int delete_indexed (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_NIL:
remidx_nil_to_map:
vv = container_vtype == HAWK_VAL_MAP? assign_newmapval_in_map(rtx, map, str, len): assign_newmapval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!vv)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_RTX_GETVALTYPE(rtx, vv);
map = ((hawk_val_map_t*)vv)->map;
break;
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
val_map:
if (str && 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;
map = ((hawk_val_map_t*)vv)->map; map = ((hawk_val_map_t*)vv)->map;
break; break;
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
val_arr:
idx = idxnde_to_int(rtx, remidx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
arr = ((hawk_val_arr_t*)vv)->arr; arr = ((hawk_val_arr_t*)vv)->arr;
break; break;
default: default:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP) if (vtype == HAWK_VAL_NIL || (rtx->hawk->opt.trait & HAWK_FLEXMAP))
{ {
goto remidx_nil_to_map; if (container_vtype == HAWK_VAL_MAP)
{
vv = assign_newmapval_in_map(rtx, map, str, len);
if (HAWK_UNLIKELY(!vv)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_MAP;
goto val_map;
}
else
{
vv = assign_newarrval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!vv)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_ARR;
goto val_arr;
}
} }
else else
{ {
@ -3076,27 +3085,13 @@ static HAWK_INLINE int delete_indexed (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde
goto oops; goto oops;
} }
} }
if (str && str != idxbuf) { hawk_rtx_freemem (rtx, str); str = HAWK_NULL; }
if (vtype == HAWK_VAL_MAP)
{
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
}
else
{
idx = idxnde_to_int(rtx, remidx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
arr = ((hawk_val_arr_t*)vv)->arr;
}
} }
#endif #endif
if (vtype == HAWK_VAL_MAP) if (vtype == HAWK_VAL_MAP)
hawk_map_delete (map, str, len); hawk_map_delete (map, str, len);
else else
hawk_arr_delete (arr, idx, 1); hawk_arr_uplete (arr, idx, 1); /* no reindexing by compaction. keep the place unset */
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
return 0; return 0;
@ -3799,13 +3794,14 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t*
case HAWK_NDE_GBL: case HAWK_NDE_GBL:
case HAWK_NDE_LCL: case HAWK_NDE_LCL:
case HAWK_NDE_ARG: case HAWK_NDE_ARG:
ret = do_assignment_nonidx(rtx, (hawk_nde_var_t*)var, val); ret = do_assignment_nonindexed(rtx, (hawk_nde_var_t*)var, val);
break; break;
case HAWK_NDE_NAMEDIDX: case HAWK_NDE_NAMEDIDX:
case HAWK_NDE_GBLIDX: case HAWK_NDE_GBLIDX:
case HAWK_NDE_LCLIDX: case HAWK_NDE_LCLIDX:
case HAWK_NDE_ARGIDX: case HAWK_NDE_ARGIDX:
{
#if !defined(HAWK_ENABLE_GC) #if !defined(HAWK_ENABLE_GC)
hawk_val_type_t vtype = HAWK_RTX_GETVALTYPE(rtx, val); hawk_val_type_t vtype = HAWK_RTX_GETVALTYPE(rtx, val);
if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR)
@ -3816,8 +3812,9 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t*
} }
#endif #endif
ret = do_assignment_idx(rtx, (hawk_nde_var_t*)var, val); ret = do_assignment_indexed(rtx, (hawk_nde_var_t*)var, val);
break; break;
}
case HAWK_NDE_POS: case HAWK_NDE_POS:
{ {
@ -3829,7 +3826,7 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t*
goto exit_on_error; goto exit_on_error;
} }
ret = do_assignment_pos(rtx, (hawk_nde_pos_t*)var, val); ret = do_assignment_positional(rtx, (hawk_nde_pos_t*)var, val);
break; break;
} }
@ -3846,7 +3843,7 @@ exit_on_error:
return HAWK_NULL; return HAWK_NULL;
} }
static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val) static hawk_val_t* do_assignment_nonindexed (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val)
{ {
hawk_val_type_t vtype; hawk_val_type_t vtype;
@ -3973,14 +3970,25 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
break; break;
} }
default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_EINTERN);
return HAWK_NULL;
} }
return val; return val;
} }
static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val) static hawk_val_t* do_assignment_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val)
{ {
hawk_map_t* map;
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_ooi_t idx;
hawk_arr_t* arr;
hawk_nde_t* remidx;
hawk_val_t* vv; /* existing value pointed to by var */ hawk_val_t* vv; /* existing value pointed to by var */
hawk_val_type_t vtype; hawk_val_type_t vtype;
@ -3999,37 +4007,21 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
vtype = HAWK_RTX_GETVALTYPE(rtx, vv); vtype = HAWK_RTX_GETVALTYPE(rtx, vv);
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_NIL:
nil_to_map:
vv = assign_newmapval_to_var(rtx, var);
if (HAWK_UNLIKELY(!vv)) return HAWK_NULL;
vtype = HAWK_RTX_GETVALTYPE(rtx, vv); /* it must be HAWK_VAL_MAP */
/* fall thru */
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
{ {
hawk_map_t* map; val_map_or_arr:
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_ooi_t idx;
hawk_arr_t* arr;
hawk_nde_t* remidx;
if (vtype == HAWK_VAL_MAP) if (vtype == HAWK_VAL_MAP)
{ {
len = HAWK_COUNTOF(idxbuf); len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx); str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops_map; if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)vv)->map; map = ((hawk_val_map_t*)vv)->map;
} }
else else
{ {
idx = idxnde_to_int(rtx, var->idx, &remidx); idx = idxnde_to_int(rtx, var->idx, &remidx);
if (idx <= -1) return HAWK_NULL; if (idx <= -1) goto oops;
arr = ((hawk_val_arr_t*)vv)->arr; arr = ((hawk_val_arr_t*)vv)->arr;
} }
@ -4048,30 +4040,29 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
{ {
vv = (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil; vv = (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil;
} }
container_vtype = vtype; container_vtype = vtype;
vtype = HAWK_RTX_GETVALTYPE(rtx, vv); vtype = HAWK_RTX_GETVALTYPE(rtx, vv);
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_NIL:
remidx_nil_to_map:
vv = container_vtype == HAWK_VAL_MAP? assign_newmapval_in_map(rtx, map, str, len): assign_newmapval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!vv)) goto oops_map;
vtype = HAWK_RTX_GETVALTYPE(rtx, vv); /* it must be HAWK_VAL_MAP */
map = ((hawk_val_map_t*)vv)->map;
break;
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
val_map:
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;
map = ((hawk_val_map_t*)vv)->map; map = ((hawk_val_map_t*)vv)->map;
break; break;
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
val_arr:
idx = idxnde_to_int(rtx, remidx, &remidx);
if (idx <= -1) goto oops;
arr = ((hawk_val_arr_t*)vv)->arr; arr = ((hawk_val_arr_t*)vv)->arr;
break; break;
default: default:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP) if (vtype == HAWK_VAL_NIL || (rtx->hawk->opt.trait & HAWK_FLEXMAP))
{ {
/* BEGIN { @local a, b; b="hello"; a[1]=b; a[1][2]=20; print a[1][2];} */ /* BEGIN { @local a, b; b="hello"; a[1]=b; a[1][2]=20; print a[1][2];} */
/* BEGIN { a[1]="hello"; a[1][2]=20; print a[1][2]; } */ /* BEGIN { a[1]="hello"; a[1][2]=20; print a[1][2]; } */
@ -4080,28 +4071,27 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
/* well, this is not the first level index. /* well, this is not the first level index.
* the logic is different from the first level where reset_variable is called. * the logic is different from the first level where reset_variable is called.
* here it simply creates a new map. */ * here it simply creates a new map. */
goto remidx_nil_to_map; if (container_vtype == HAWK_VAL_MAP)
{
vv = assign_newmapval_in_map(rtx, map, str, len);
if (HAWK_UNLIKELY(!vv)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_MAP;
goto val_map;
}
else
{
vv = assign_newarrval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!vv)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_ARR;
goto val_arr;
}
} }
else else
{ {
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTONONSCA, HAWK_T("not allowed to change a nested scalar value under '%.*js' to a nonscalar value"), var->id.name.len, var->id.name.ptr); hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTONONSCA, HAWK_T("not allowed to change a nested scalar value under '%.*js' to a nonscalar value"), var->id.name.len, var->id.name.ptr);
goto oops_map; goto oops;
} }
} }
if (vtype == HAWK_VAL_MAP)
{
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_map;
}
else
{
idx = idxnde_to_int(rtx, remidx, &remidx);
if (idx <= -1) return HAWK_NULL;
arr = ((hawk_val_arr_t*)vv)->arr;
}
} }
#endif #endif
@ -4111,40 +4101,51 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
if (vtype == HAWK_VAL_MAP) if (vtype == HAWK_VAL_MAP)
{ {
if (HAWK_UNLIKELY(hawk_map_upsert(map, str, len, val, 0) == HAWK_NULL)) goto oops_map; if (HAWK_UNLIKELY(hawk_map_upsert(map, str, len, val, 0) == HAWK_NULL))
{
ADJERR_LOC (rtx, &var->loc);
goto oops;
}
} }
else else
{ {
if (HAWK_UNLIKELY(hawk_arr_upsert(arr, idx, val, 0) == HAWK_ARR_NIL)) goto oops_map; if (HAWK_UNLIKELY(hawk_arr_upsert(arr, idx, val, 0) == HAWK_ARR_NIL))
{
ADJERR_LOC (rtx, &var->loc);
goto oops;
}
} }
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
hawk_rtx_refupval (rtx, val); hawk_rtx_refupval (rtx, val);
return val;
oops_map:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
ADJERR_LOC (rtx, &var->loc); return val;
return HAWK_NULL;
} }
default: default:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP) if (vtype == HAWK_VAL_NIL || (rtx->hawk->opt.trait & HAWK_FLEXMAP))
{ {
/* if FLEXMAP is on, you can switch a scalar value to a map */ /* 1. switch a nil value to a map value at the first level */
goto nil_to_map; /* switch a scalar value to a map */ /* 2. if FLEXMAP is on, you can switch a scalar value to a map value */
vv = assign_newmapval_to_var(rtx, var);
if (HAWK_UNLIKELY(!vv)) return HAWK_NULL;
vtype = HAWK_VAL_MAP;
goto val_map_or_arr;
} }
else else
{ {
/* you can't manipulate a variable pointing to /* you can't manipulate a variable pointing to
* a scalar value with an index if FLEXMAP is off. */ * a scalar value with an index if FLEXMAP is off. */
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTONONSCA, HAWK_T("not allowed to change a scalar value in '%.*js' to a nonscalar value"), var->id.name.len, var->id.name.ptr); hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTONONSCA, HAWK_T("not allowed to change a scalar value in '%.*js' to a nonscalar value"), var->id.name.len, var->id.name.ptr);
return HAWK_NULL; goto oops;
} }
} }
oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
return HAWK_NULL;
} }
static hawk_val_t* do_assignment_pos (hawk_rtx_t* rtx, hawk_nde_pos_t* pos, hawk_val_t* val) static hawk_val_t* do_assignment_positional (hawk_rtx_t* rtx, hawk_nde_pos_t* pos, hawk_val_t* val)
{ {
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype; hawk_val_type_t vtype;
@ -6749,33 +6750,28 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
case HAWK_VAL_NIL: case HAWK_VAL_NIL:
v = assign_newmapval_to_var(rtx, var); v = assign_newmapval_to_var(rtx, var);
if (HAWK_UNLIKELY(!v)) goto oops; if (HAWK_UNLIKELY(!v)) goto oops;
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_VAL_MAP;
break; goto val_map_init;
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
val_map_init:
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
/* do nothing */ idx = idxnde_to_int(rtx, var->idx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
arr = ((hawk_val_arr_t*)v)->arr;
break; break;
default: default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP); hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC);
goto oops; goto oops;
} }
if (vtype == HAWK_VAL_MAP)
{
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)v)->map;
}
else
{
idx = idxnde_to_int(rtx, var->idx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
arr = ((hawk_val_arr_t*)v)->arr;
}
#if defined(HAWK_ENABLE_GC) #if defined(HAWK_ENABLE_GC)
while (remidx) while (remidx)
{ {
@ -6796,39 +6792,44 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_NIL:
v = container_vtype == HAWK_VAL_MAP? assign_newmapval_in_map(rtx, map, str, len): assign_newmapval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!v)) goto oops;
vtype = HAWK_RTX_GETVALTYPE(rtx, v);
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
val_map:
if (str && 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;
map = ((hawk_val_map_t*)v)->map; map = ((hawk_val_map_t*)v)->map;
break; break;
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
val_arr:
idx = idxnde_to_int(rtx, remidx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
arr = ((hawk_val_arr_t*)v)->arr; arr = ((hawk_val_arr_t*)v)->arr;
break; break;
default: default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP); if (vtype == HAWK_VAL_NIL /* || (rtx->hawk->opt.trait & HAWK_FLEXMAP) no flexmap because this is in a 'get' context. */)
{
if (container_vtype == HAWK_VAL_MAP)
{
v = assign_newmapval_in_map(rtx, map, str, len);
if (HAWK_UNLIKELY(!v)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_MAP;
goto val_map;
}
else
{
v = assign_newarrval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!v)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_ARR;
goto val_arr;
}
}
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC);
goto oops; goto oops;
} }
if (str && str != idxbuf) { hawk_rtx_freemem (rtx, str); str = HAWK_NULL; }
if (vtype == HAWK_VAL_MAP)
{
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
}
else
{
idx = idxnde_to_int(rtx, remidx, &remidx);
if (HAWK_UNLIKELY(idx <= -1)) goto oops;
}
} }
#endif #endif
@ -6840,7 +6841,7 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
{ {
/* if the value doesn't exist for the given key, insert a nil for it to create a placeholder for the reference */ /* if the value doesn't exist for the given key, insert a nil for it to create a placeholder for the reference */
pair = hawk_map_upsert(map, str, len, hawk_val_nil, 0); pair = hawk_map_upsert(map, str, len, hawk_val_nil, 0);
if (HAWK_UNLIKELY(!pair)) goto oops; if (HAWK_UNLIKELY(!pair)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
HAWK_ASSERT (HAWK_MAP_VPTR(pair) == hawk_val_nil); HAWK_ASSERT (HAWK_MAP_VPTR(pair) == hawk_val_nil);
/* no reference count increment as hawk_val_nil is upserted /* no reference count increment as hawk_val_nil is upserted
hawk_rtx_refupval (rtx, HAWK_MAP_VPTR(pair)); */ hawk_rtx_refupval (rtx, HAWK_MAP_VPTR(pair)); */
@ -6855,14 +6856,13 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
if (idx >= HAWK_ARR_SIZE(arr) || !HAWK_ARR_SLOT(arr, idx)) if (idx >= HAWK_ARR_SIZE(arr) || !HAWK_ARR_SLOT(arr, idx))
{ {
/* if the value doesn't exist for the given index, insert a nil at that position to create a placeholder for the reference */ /* if the value doesn't exist for the given index, insert a nil at that position to create a placeholder for the reference */
if (HAWK_UNLIKELY(hawk_arr_upsert (arr, idx, hawk_val_nil, 0) == HAWK_ARR_NIL)) goto oops; if (HAWK_UNLIKELY(hawk_arr_upsert (arr, idx, hawk_val_nil, 0) == HAWK_ARR_NIL)) { ADJERR_LOC(rtx, &var->loc); goto oops; }
} }
return (hawk_val_t**)&HAWK_ARR_DPTR(arr, idx); return (hawk_val_t**)&HAWK_ARR_DPTR(arr, idx);
} }
oops: oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
ADJERR_LOC (rtx, &var->loc);
return HAWK_NULL; return HAWK_NULL;
} }
@ -6964,148 +6964,134 @@ static hawk_val_t* eval_arg (hawk_rtx_t* rtx, hawk_nde_t* nde)
static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
{ {
hawk_map_t* map; /* containing map */
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_arr_t* arr; /* containing array */
hawk_ooi_t idx;
hawk_nde_t* remidx;
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype; hawk_val_type_t vtype;
v = fetch_topval_from_var(rtx, var); v = fetch_topval_from_var(rtx, var);
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_RTX_GETVALTYPE(rtx, v);
HAWK_ASSERT (var->idx != HAWK_NULL);
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_NIL: case HAWK_VAL_NIL:
v = assign_newmapval_to_var(rtx, var); v = assign_newmapval_to_var(rtx, var);
if (HAWK_UNLIKELY(!v)) return HAWK_NULL; if (HAWK_UNLIKELY(!v)) return HAWK_NULL;
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_VAL_MAP;
/* fall thru */ goto init_val_map;
case HAWK_VAL_MAP: case HAWK_VAL_MAP:
init_val_map:
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
{ idx = idxnde_to_int(rtx, var->idx, &remidx);
hawk_map_t* map; /* containing map */ if (idx <= -1) goto oops;
hawk_map_pair_t* pair; arr = ((hawk_val_arr_t*)v)->arr;
break;
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_arr_t* arr; /* containing array */
hawk_ooi_t idx;
hawk_nde_t* remidx;
HAWK_ASSERT (var->idx != HAWK_NULL);
if (vtype == HAWK_VAL_MAP)
{
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)v)->map;
pair = hawk_map_search(map, str, len);
}
else
{
idx = idxnde_to_int(rtx, var->idx, &remidx);
if (idx <= -1) goto oops;
arr = ((hawk_val_arr_t*)v)->arr;
}
#if defined(HAWK_ENABLE_GC)
while (remidx)
{
hawk_val_type_t container_vtype;
if (vtype == HAWK_VAL_MAP)
{
v = pair? (hawk_val_t*)HAWK_MAP_VPTR(pair): hawk_val_nil;
}
else
{
v = (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil;
}
container_vtype = vtype;
vtype = HAWK_RTX_GETVALTYPE(rtx, v);
/*
a[10] = hawk::array();
print typename(a[10][40][50]);
print typename(a[10][40]);
*
*
a[10] = hawk::array();
a[10][40] = hawk::array();
a[10][40][5] = hawk::array();
*
*
a = hawk::array(
hawk::array(10, 20, 30),
hawk::array(99, 99, 99, 88, 77)
);
*/
switch (vtype)
{
case HAWK_VAL_NIL:
v = container_vtype == HAWK_VAL_MAP? assign_newmapval_in_map(rtx, map, str, len): assign_newmapval_in_arr(rtx, arr, idx); /* TODO: should i do assign_newarrval_in_arr(rtx, arr, idx)? instead??? */
if (HAWK_UNLIKELY(!v)) goto oops;
vtype = HAWK_RTX_GETVALTYPE(rtx, v); /* it must be HAWK_VAL_MAP */
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_MAP:
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_ARR:
arr = ((hawk_val_arr_t*)v)->arr;
break;
default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP);
goto oops;
}
if (str && str != idxbuf) { hawk_rtx_freemem (rtx, str); str = HAWK_NULL; }
if (vtype == HAWK_VAL_MAP)
{
len = HAWK_COUNTOF(idxbuf);
str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx);
if (HAWK_UNLIKELY(!str)) goto oops;
pair = hawk_map_search(map, str, len);
}
else
{
idx = idxnde_to_int(rtx, remidx, &remidx);
if (idx <= -1) goto oops;
arr = ((hawk_val_arr_t*)v)->arr;
}
}
#endif
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
if (vtype == HAWK_VAL_MAP)
{
return pair? (hawk_val_t*)HAWK_MAP_VPTR(pair): hawk_val_nil;
}
else
{
/* return nil if the index is out of range or the element at the index is not set.
* no check for a negative index as it's guaranteed to be positive by idxnde_to_int() */
return (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil;
}
oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
ADJERR_LOC (rtx, &var->loc);
return HAWK_NULL;
}
default: default:
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP); /* TODO: change error code... ENOTINDEXABLE, not map or not array */ hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC);
return HAWK_NULL; return HAWK_NULL;
} }
#if defined(HAWK_ENABLE_GC)
while (remidx)
{
hawk_val_type_t container_vtype;
if (vtype == HAWK_VAL_MAP)
{
hawk_map_pair_t* pair;
pair = hawk_map_search(map, str, len);
v = pair? (hawk_val_t*)HAWK_MAP_VPTR(pair): hawk_val_nil;
}
else
{
v = (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil;
}
container_vtype = vtype;
vtype = HAWK_RTX_GETVALTYPE(rtx, v);
switch (vtype)
{
case HAWK_VAL_MAP:
val_map:
if (str && 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;
map = ((hawk_val_map_t*)v)->map;
break;
case HAWK_VAL_ARR:
val_arr:
idx = idxnde_to_int(rtx, remidx, &remidx);
if (idx <= -1) goto oops;
arr = ((hawk_val_arr_t*)v)->arr;
break;
default:
if (vtype == HAWK_VAL_NIL /* || (rtx->hawk->opt.trait & HAWK_FLEXMAP) no flexmap because this is in a 'get' context */)
{
if (container_vtype == HAWK_VAL_MAP)
{
v = assign_newmapval_in_map(rtx, map, str, len);
if (HAWK_UNLIKELY(!v)) { ADJERR_LOC (rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_MAP;
goto val_map;
}
else
{
v = assign_newarrval_in_arr(rtx, arr, idx);
if (HAWK_UNLIKELY(!v)) { ADJERR_LOC (rtx, &var->loc); goto oops; }
vtype = HAWK_VAL_ARR;
goto val_arr;
}
}
else
{
hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC);
goto oops;
}
}
}
#endif
if (vtype == HAWK_VAL_MAP)
{
hawk_map_pair_t* pair;
pair = hawk_map_search(map, str, len);
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
return pair? (hawk_val_t*)HAWK_MAP_VPTR(pair): hawk_val_nil;
}
else
{
/* return nil if the index is out of range or the element at the index is not set.
* no check for a negative index as it's guaranteed to be positive by idxnde_to_int() */
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
return (idx < HAWK_ARR_SIZE(arr) && HAWK_ARR_SLOT(arr, idx))? ((hawk_val_t*)HAWK_ARR_DPTR(arr, idx)): hawk_val_nil;
}
oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
return HAWK_NULL;
} }
static hawk_val_t* eval_namedidx (hawk_rtx_t* rtx, hawk_nde_t* nde) static hawk_val_t* eval_namedidx (hawk_rtx_t* rtx, hawk_nde_t* nde)

View File

@ -980,7 +980,7 @@ static void same_arrayval (hawk_arr_t* map, void* dptr, hawk_oow_t dlen)
} }
hawk_val_t* hawk_rtx_makearrval (hawk_rtx_t* rtx, hawk_oow_t init_capa) hawk_val_t* hawk_rtx_makearrval (hawk_rtx_t* rtx, hawk_ooi_t init_capa)
{ {
static hawk_arr_style_t style = static hawk_arr_style_t style =
{ {
@ -1015,7 +1015,7 @@ retry:
val->v_gc = 0; val->v_gc = 0;
val->arr = (hawk_arr_t*)(val + 1); val->arr = (hawk_arr_t*)(val + 1);
if (init_capa <= 0) init_capa = 64; /* TODO: what is the best initial value? */ if (init_capa < 0) init_capa = 64; /* TODO: what is the best initial value? */
if (HAWK_UNLIKELY(hawk_arr_init(val->arr, hawk_rtx_getgem(rtx), init_capa) <= -1)) if (HAWK_UNLIKELY(hawk_arr_init(val->arr, hawk_rtx_getgem(rtx), init_capa) <= -1))
{ {
#if defined(HAWK_ENABLE_GC) #if defined(HAWK_ENABLE_GC)
@ -1344,7 +1344,7 @@ const hawk_ooch_t* hawk_rtx_getvaltypename(hawk_rtx_t* rtx, hawk_val_t* val)
HAWK_T("mbs"), HAWK_T("mbs"),
HAWK_T("fun"), HAWK_T("fun"),
HAWK_T("map"), HAWK_T("map"),
HAWK_T("arr"), HAWK_T("array"),
HAWK_T("rex"), HAWK_T("rex"),
HAWK_T("ref") HAWK_T("ref")
}; };
@ -2073,7 +2073,7 @@ int hawk_rtx_valtostr (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_rtx_valtostr_o
case HAWK_VAL_ARR: case HAWK_VAL_ARR:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP) if (rtx->hawk->opt.trait & HAWK_FLEXMAP)
{ {
return str_to_str(rtx, HAWK_T("#ARR"), 4, out); return str_to_str(rtx, HAWK_T("#ARRAY"), 4, out);
} }
goto invalid; goto invalid;

View File

@ -78,18 +78,30 @@ function main()
} }
{ {
@local a; @local a, nil;
a = hawk::array(); a = hawk::array();
a[10] = "good"; a[10] = "good";
a[0][40] = "bye"
a[0][0] = "farewell"
ensure (hawk::typename(a), "array", SCRIPTNAME);
ensure (hawk::typename(a[0]), "array", SCRIPTNAME);
call_by_ref_3(a[9]); call_by_ref_3(a[9]);
ensure (a[10], "good", SCRIPTNAME); ensure (a[10], "good", SCRIPTNAME);
ensure (a[9], "hello world", SCRIPTNAME); ensure (a[9], "hello world", SCRIPTNAME);
call_by_ref_3(a[10]); call_by_ref_3(a[10]);
ensure (a[10], "hello world", SCRIPTNAME); ensure (a[10], "hello world", SCRIPTNAME);
ensure (a[9], "hello world", SCRIPTNAME); ensure (a[9], "hello world", SCRIPTNAME);
ensure (a[0][40], "bye", SCRIPTNAME);
call_by_ref_3(a[0][40]);
ensure (a[0][40], "hello world", SCRIPTNAME);
ensure (length(a[0]), 41);
delete a[0][40];
ensure (length(a[0]), 41);
ensure (a[0][0], "farewell", SCRIPTNAME);
ensure (a[0][40], nil, SCRIPTNAME);
#hawk::splice (a[0], 40, 1);
#ensure (length(a[0]), 40);
} }
print "SUCCESS" print "SUCCESS"
} }