diff --git a/hawk/lib/err.c b/hawk/lib/err.c index 4c725cc3..f65f233f 100644 --- a/hawk/lib/err.c +++ b/hawk/lib/err.c @@ -142,20 +142,17 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum) 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("value not referenceable"), - HAWK_T("cannot return a map"), /* EMAPRET */ - HAWK_T("cannot assign a map to a positional"), /* EMAPTOPOS */ - HAWK_T("cannot assign a map to an indexed variable"),/* EMAPTOIDX */ - HAWK_T("cannot assign a map to a variable"), /* EMAPTOVAR */ - HAWK_T("cannot change a map to a scalar"), /* EMAPTOSCALAR */ - HAWK_T("cannot change a map to another map"), /* EMAPTOMAP */ - HAWK_T("cannot change a scalar to a map"), /* ESCALARTOMAP */ + HAWK_T("cannot return a non-scalar value"), /* ENONSCARET */ + HAWK_T("cannot assign a non-scalar value to a positional"), /* ENONSCATOPOS */ + HAWK_T("cannot assign a non-scalar value to an indexed variable"),/* ENONSCATOIDX */ + HAWK_T("cannot assign a non-scalar value to a variable"), /* ENONSCATOVAR */ + HAWK_T("cannot change a non-scalar value to a scalar value"), /* ENONSCATOSCALAR */ + HAWK_T("cannot change a non-scalar value to another non-scalar value"), /* ENONSCATONONSCA */ + HAWK_T("cannot change a scalar value to a non-scalar value"), /* ESCALARTONONSCA */ HAWK_T("invalid value to convert to a string"), HAWK_T("invalid value to convert to a number"), HAWK_T("invalid value to a character"), HAWK_T("invalid value for hashing"), - HAWK_T("cannot return an array"), /* EARRRET */ - HAWK_T("cannot assign an array to a positional"), /* EARRTOPOS */ - HAWK_T("cannot assign an array to an indexed variable"),/* EARRTOIDX */ HAWK_T("array index out of allowed range"), HAWK_T("single-bracketed multidimensional array indices not allowed"), HAWK_T("'next' called from BEGIN block"), diff --git a/hawk/lib/fnc.c b/hawk/lib/fnc.c index 6a2733d1..2bf8102e 100644 --- a/hawk/lib/fnc.c +++ b/hawk/lib/fnc.c @@ -29,11 +29,6 @@ static int fnc_close (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_fflush (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_int (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); -static int fnc_typename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); -static int fnc_gcrefs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); -static int fnc_isnil (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); -static int fnc_ismap (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); -static int fnc_isarr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_asorti (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); @@ -59,11 +54,6 @@ static hawk_fnc_t sysfnctab[] = /* type info/conversion */ { {HAWK_T("int"), 3}, 0, { {1, 1, HAWK_NULL}, fnc_int, 0 }, HAWK_NULL}, - { {HAWK_T("isarray"), 7}, 0, { {1, 1, HAWK_NULL}, fnc_isarr, 0 }, HAWK_NULL}, - { {HAWK_T("isnil"), 5}, 0, { {1, 1, HAWK_NULL}, fnc_isnil, 0 }, HAWK_NULL}, - { {HAWK_T("ismap"), 5}, 0, { {1, 1, HAWK_NULL}, fnc_ismap, 0 }, HAWK_NULL}, - { {HAWK_T("typename"), 8}, 0, { {1, 1, HAWK_NULL}, fnc_typename, 0 }, HAWK_NULL}, - { {HAWK_T("gcrefs"), 6}, 0, { {1, 1, HAWK_NULL}, fnc_gcrefs, 0 }, HAWK_NULL}, /* map(array) sort */ { {HAWK_T("asort"), 5}, 0, { {1, 3, HAWK_T("rrv")}, fnc_asort, 0 }, HAWK_NULL}, @@ -1733,73 +1723,6 @@ static int fnc_int (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) return 0; } -static int fnc_typename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) -{ - hawk_val_t* a0; - hawk_val_t* r; - const hawk_ooch_t* name; - - a0 = hawk_rtx_getarg(rtx, 0); - name = hawk_rtx_getvaltypename(rtx, a0); - - r = hawk_rtx_makestrvalwithoocstr(rtx, name); - if (r == HAWK_NULL) return -1; - - hawk_rtx_setretval (rtx, r); - return 0; -} - -static int fnc_gcrefs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) -{ - hawk_val_t* a0; - a0 = hawk_rtx_getarg(rtx, 0); - hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, HAWK_VTR_IS_POINTER(a0)? a0->v_refs: 0)); - return 0; -} - - -static int fnc_isnil (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) -{ - hawk_val_t* a0; - hawk_val_t* r; - - a0 = hawk_rtx_getarg(rtx, 0); - - r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_NIL); - if (r == HAWK_NULL) return -1; - - hawk_rtx_setretval (rtx, r); - return 0; -} - -static int fnc_ismap (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) -{ - hawk_val_t* a0; - hawk_val_t* r; - - a0 = hawk_rtx_getarg(rtx, 0); - - r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MAP); - if (HAWK_UNLIKELY(!r)) return -1; - - hawk_rtx_setretval (rtx, r); - return 0; -} - -static int fnc_isarr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) -{ - hawk_val_t* a0; - hawk_val_t* r; - - a0 = hawk_rtx_getarg(rtx, 0); - - r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_ARR); - if (HAWK_UNLIKELY(!r)) return -1; - - hawk_rtx_setretval (rtx, r); - return 0; -} - static HAWK_INLINE int asort_compare (const void* x1, const void* x2, void* ctx, int* cv) { int n; @@ -1865,6 +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); HAWK_ASSERT (a0_type == HAWK_VAL_REF); +/* TODO: handel HAWK_VAL_ARR */ v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0); if (v_type != HAWK_VAL_MAP) { diff --git a/hawk/lib/hawk-cmn.h b/hawk/lib/hawk-cmn.h index efebc40f..f93c6c5f 100644 --- a/hawk/lib/hawk-cmn.h +++ b/hawk/lib/hawk-cmn.h @@ -977,20 +977,19 @@ enum hawk_errnum_t HAWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */ HAWK_ENOTMAPNILIN, /**< right-hand side of 'in' not a map nor nil */ HAWK_ENOTREF, /**< value not referenceable */ - HAWK_EMAPRET, /**< map cannot be returned */ - HAWK_EMAPTOPOS, /**< map cannot be assigned to a positional */ - HAWK_EMAPTOIDX, /**< map cannot be assigned to an indexed variable */ - HAWK_EMAPTOVAR, /**< map cannot be assigned to a variable */ - HAWK_EMAPTOSCALAR, /**< cannot change a map to a scalar value */ - HAWK_EMAPTOMAP, /**< cannot change a map to another map */ - HAWK_ESCALARTOMAP, /**< cannot change a scalar to a map */ + HAWK_ENONSCARET, /**< non-scalar value cannot be returned */ + HAWK_ENONSCATOPOS, /**< non-scalar value cannot be assigned to a positional */ + HAWK_ENONSCATOIDX, /**< non-scalar value cannot be assigned to an indexed variable */ + HAWK_ENONSCATOVAR, /**< non-scalar cannot be assigned to a variable */ + HAWK_ENONSCATOSCALAR, /**< cannot change a non-scalar value to a scalar value */ + HAWK_ENONSCATONONSCA, /**< cannot change a non-scalar value to another non-scalar value */ + HAWK_ESCALARTONONSCA, /**< cannot change a scalar value to to a non-scalar value */ HAWK_EVALTOSTR, /**< invalid value to convert to a string */ HAWK_EVALTONUM, /**< invalid value to convert to a number */ HAWK_EVALTOCHR, /**< invalid value to convert to a character */ HAWK_EHASHVAL, /**< invalid value to hash */ - HAWK_EARRRET, /**< array cannot be returned */ - HAWK_EARRTOPOS, /**< array cannot be assigned to a positional */ - HAWK_EARRTOIDX, /**< array cannot be assigned to an indexed variable */ + + HAWK_EARRIDXRANGE, /**< disallowed array index range */ HAWK_EARRIDXMULTI, /**< single-bracketed multidimensional array indices not allowed */ HAWK_ERNEXTBEG, /**< 'next' called from BEGIN block */ diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index e55a51fe..a20782a0 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -211,6 +211,14 @@ static int fnc_gc_set_threshold (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) return 0; } +static int fnc_gcrefs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + a0 = hawk_rtx_getarg(rtx, 0); + hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, HAWK_VTR_IS_POINTER(a0)? a0->v_refs: 0)); + return 0; +} + /* -------------------------------------------------------------------------- */ static int fnc_array (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) @@ -239,6 +247,66 @@ static int fnc_map (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) /* -------------------------------------------------------------------------- */ +static int fnc_isnil (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_val_t* r; + + a0 = hawk_rtx_getarg(rtx, 0); + + r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_NIL); + if (r == HAWK_NULL) return -1; + + hawk_rtx_setretval (rtx, r); + return 0; +} + +static int fnc_ismap (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_val_t* r; + + a0 = hawk_rtx_getarg(rtx, 0); + + r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MAP); + if (HAWK_UNLIKELY(!r)) return -1; + + hawk_rtx_setretval (rtx, r); + return 0; +} + +static int fnc_isarr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_val_t* r; + + a0 = hawk_rtx_getarg(rtx, 0); + + r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_ARR); + if (HAWK_UNLIKELY(!r)) return -1; + + hawk_rtx_setretval (rtx, r); + return 0; +} + +static int fnc_typename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_val_t* r; + const hawk_ooch_t* name; + + a0 = hawk_rtx_getarg(rtx, 0); + name = hawk_rtx_getvaltypename(rtx, a0); + + r = hawk_rtx_makestrvalwithoocstr(rtx, name); + if (r == HAWK_NULL) return -1; + + hawk_rtx_setretval (rtx, r); + return 0; +} + +/* -------------------------------------------------------------------------- */ + typedef struct fnctab_t fnctab_t; struct fnctab_t { @@ -262,9 +330,14 @@ static fnctab_t fnctab[] = { HAWK_T("call"), { { 1, A_MAX, HAWK_T("vR") }, fnc_call, 0 } }, { HAWK_T("function_exists"), { { 1, 1, HAWK_NULL }, fnc_function_exists, 0 } }, { HAWK_T("gc"), { { 0, 1, HAWK_NULL }, fnc_gc, 0 } }, + { HAWK_T("gcrefs"), { { 1, 1, HAWK_NULL }, fnc_gcrefs, 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 } }, - { HAWK_T("map"), { { 0, A_MAX }, fnc_map, 0 } } + { HAWK_T("isarray"), { { 1, 1, HAWK_NULL }, fnc_isarr, 0 } }, + { HAWK_T("ismap"), { { 1, 1, HAWK_NULL }, fnc_ismap, 0 } }, + { HAWK_T("isnil"), { { 1, 1, HAWK_NULL }, fnc_isnil, 0 } }, + { HAWK_T("map"), { { 0, A_MAX, HAWK_NULL }, fnc_map, 0 } }, + { HAWK_T("typename"), { { 1, 1, HAWK_NULL }, fnc_typename, 0 } } }; static inttab_t inttab[] = diff --git a/hawk/lib/run.c b/hawk/lib/run.c index fe22cd3e..678f0157 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -168,8 +168,6 @@ static hawk_val_t* eval_incpre (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_incpst (hawk_rtx_t* rtx, hawk_nde_t* nde); static hawk_val_t* eval_cnd (hawk_rtx_t* rtx, hawk_nde_t* nde); -static hawk_val_t* eval_fncall_fun_ex (hawk_rtx_t* rtx, hawk_nde_t* nde, void(*errhandler)(void*), void* eharg); - 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); @@ -250,14 +248,14 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t hawk_errnum_t errnum = HAWK_ENOERR; const hawk_ooch_t* errfmt; - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { if (old_vtype == HAWK_VAL_NIL) { /* a nil valul can be overridden with any values */ /* ok. no error */ } - else if (!assign && old_vtype == HAWK_VAL_MAP) + else if (!assign && old_vtype == vtype) { /* when both are maps, how should this operation be * interpreted? @@ -277,16 +275,16 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t } else { - errnum = HAWK_ESCALARTOMAP; - errfmt = HAWK_T("not allowed to change a scalar '%.*js' to a map"); + errnum = HAWK_ESCALARTONONSCA; + errfmt = HAWK_T("not allowed to change a scalar value in '%.*js' to a non-scalar value"); } } else { - if (old_vtype == HAWK_VAL_MAP) + if (old_vtype == HAWK_VAL_MAP || old_vtype == HAWK_VAL_ARR) { - errnum = HAWK_EMAPTOSCALAR; - errfmt = HAWK_T("not allowed to change a map '%.*js' to a scalar"); + errnum = HAWK_ENONSCATOSCALAR; + errfmt = HAWK_T("not allowed to change a non-scalar value in '%.*js' to a scalar value"); } } @@ -312,7 +310,7 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t } } - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { if (idx >= HAWK_MIN_GBL_ID && idx <= HAWK_MAX_GBL_ID) { @@ -325,7 +323,7 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t hawk_oocs_t ea; ea.ptr = (hawk_ooch_t*)hawk_getgblname(hawk_rtx_gethawk(rtx), idx, &ea.len); - hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_ESCALARTOMAP, HAWK_T("not allowed to change a scalar '%.*js' to a map"), ea.len, ea.ptr); + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_ESCALARTONONSCA, HAWK_T("not allowed to change a scalar value in '%.*js' to a non-scalar value"), ea.len, ea.ptr); return -1; } } @@ -2709,19 +2707,12 @@ static int run_return (hawk_rtx_t* rtx, hawk_nde_return_t* nde) { hawk_val_type_t vtype = HAWK_RTX_GETVALTYPE(rtx, val); - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* cannot return a map */ hawk_rtx_refupval (rtx, val); hawk_rtx_refdownval (rtx, val); - hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_EMAPRET); - return -1; - } - else if (vtype == HAWK_VAL_ARR) - { - hawk_rtx_refupval (rtx, val); - hawk_rtx_refdownval (rtx, val); - hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_EARRRET); + hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENONSCARET); return -1; } } @@ -2989,7 +2980,7 @@ static hawk_val_t* assign_newmapval_to_var (hawk_rtx_t* rtx, hawk_nde_var_t* var } -static int delete_indexed (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde_var_t* var) +static int delete_indexed_in_map (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde_var_t* var) { hawk_map_t* map; hawk_ooch_t* str = HAWK_NULL; @@ -3039,7 +3030,7 @@ static int delete_indexed (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde_var_t* var) } else { - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENOTDEL, HAWK_T("nested scalar under '%.*js' not deletable"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENOTDEL, HAWK_T("nested scalar value under '%.*js' not deletable"), var->id.name.len, var->id.name.ptr); goto oops; } } @@ -3064,6 +3055,24 @@ oops: return -1; } +static int delete_indexed_in_arr (hawk_rtx_t* rtx, hawk_val_t* vv, hawk_nde_var_t* var) +{ + hawk_arr_t* arr; + hawk_ooi_t idx; + + HAWK_ASSERT (var->idx != HAWK_NULL); + HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, vv) == HAWK_VAL_ARR); + + idx = idxnde_to_int(rtx, var->idx); + if (HAWK_UNLIKELY(idx <= -1)) return -1; + + arr = ((hawk_val_arr_t*)vv)->arr; + + /* no bound check because hawk_arr_delete() performs sanity check */ + hawk_arr_delete (arr, idx, 1); + return 0; +} + static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde) { hawk_nde_var_t* var; @@ -3087,7 +3096,7 @@ static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde) if (var->type == HAWK_NDE_NAMEDIDX || var->type == HAWK_NDE_GBLIDX || var->type == HAWK_NDE_LCLIDX || var->type == HAWK_NDE_ARGIDX) { - if (delete_indexed(rtx, val, var) <= -1) goto oops; + if (delete_indexed_in_map(rtx, val, var) <= -1) goto oops; } else { @@ -3104,6 +3113,17 @@ static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde) } break; + case HAWK_VAL_ARR: + if (var->type == HAWK_NDE_NAMEDIDX || var->type == HAWK_NDE_GBLIDX || + var->type == HAWK_NDE_LCLIDX || var->type == HAWK_NDE_ARGIDX) + { + if (delete_indexed_in_arr(rtx, val, var) <= -1) goto oops; + } + else + { + hawk_arr_clear (((hawk_val_arr_t*)val)->arr); + } + break; default: hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENOTDEL, HAWK_T("'%.*js' not deletable"), var->id.name.len, var->id.name.ptr); goto oops; @@ -3754,15 +3774,10 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t* case HAWK_NDE_ARGIDX: #if !defined(HAWK_ENABLE_GC) hawk_val_type_t vtype = HAWK_RTX_GETVALTYPE(rtx, val); - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* a map cannot become a member of a map */ - errnum = HAWK_EMAPTOIDX; - goto exit_on_error; - } - else if (vtype == HAWK_VAL_ARR) - { - errnum = HAWK_EARRTOIDX; + errnum = HAWK_ENONSCATOIDX; goto exit_on_error; } #endif @@ -3773,15 +3788,10 @@ static hawk_val_t* do_assignment (hawk_rtx_t* rtx, hawk_nde_t* var, hawk_val_t* case HAWK_NDE_POS: { hawk_val_type_t vtype = HAWK_RTX_GETVALTYPE(rtx, val); - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* a map cannot be assigned to a positional */ - errnum = HAWK_EMAPTOPOS; - goto exit_on_error; - } - else if (vtype == HAWK_VAL_ARR) - { - errnum = HAWK_EARRTOPOS; + errnum = HAWK_ENONSCATOPOS; goto exit_on_error; } @@ -3826,20 +3836,21 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP)) { - if (pair && HAWK_RTX_GETVALTYPE(rtx, (hawk_val_t*)HAWK_HTB_VPTR(pair)) == HAWK_VAL_MAP) + hawk_val_type_t old_vtype; + if (pair && ((old_vtype = HAWK_RTX_GETVALTYPE(rtx, (hawk_val_t*)HAWK_HTB_VPTR(pair))) == HAWK_VAL_MAP || old_vtype == HAWK_VAL_ARR)) { /* old value is a map - it can only be accessed through indexing. */ - if (vtype == HAWK_VAL_MAP) - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOMAP, HAWK_T("not allowed to change a map '%.*js' to another map"), var->id.name.len, var->id.name.ptr); + if (vtype == old_vtype) + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATONONSCA, HAWK_T("not allowed to change a non-scalar value in '%.*js' to another non-scalar value"), var->id.name.len, var->id.name.ptr); else - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOSCALAR, HAWK_T("not allowed to change a non-scalar value in '%.*js' to a scalar value"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } - else if (vtype == HAWK_VAL_MAP) + else if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* old value is not a map but a new value is a map. * a map cannot be assigned to a variable if FLEXMAP is off. */ - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOVAR, HAWK_T("not allowed to assign a non-scalar value to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } } @@ -3870,20 +3881,22 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP)) { - if (HAWK_RTX_GETVALTYPE(rtx, old) == HAWK_VAL_MAP) + hawk_val_type_t old_type; + + if ((old_type = HAWK_RTX_GETVALTYPE(rtx, old)) == HAWK_VAL_MAP || old_type == HAWK_VAL_ARR) { /* old value is a map - it can only be accessed through indexing. */ - if (vtype == HAWK_VAL_MAP) - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOMAP, HAWK_T("not allowed to change a map '%.*js' to another map"), var->id.name.len, var->id.name.ptr); + if (vtype == old_type) + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATONONSCA, HAWK_T("not allowed to change a non-scalar value in '%.*js' to another non-scalar value"), var->id.name.len, var->id.name.ptr); else - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOSCALAR, HAWK_T("not allowed to change a non-scalar value in '%.*js' to a scalar value"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } - else if (vtype == HAWK_VAL_MAP) + else if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* old value is not a map but a new value is a map. * a map cannot be assigned to a variable if FLEXMAP is off. */ - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOVAR, HAWK_T("not allowed to assign a non-scalar value to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } } @@ -3900,20 +3913,22 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP)) { - if (HAWK_RTX_GETVALTYPE(rtx, old) == HAWK_VAL_MAP) + hawk_val_type_t old_type; + + if ((old_type = HAWK_RTX_GETVALTYPE(rtx, old) == HAWK_VAL_MAP) || old_type == HAWK_VAL_ARR) { /* old value is a map - it can only be accessed through indexing. */ - if (vtype == HAWK_VAL_MAP) - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOMAP, HAWK_T("not allowed to change a map '%.*js' to another map"), var->id.name.len, var->id.name.ptr); + if (vtype == old_type) + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATONONSCA, HAWK_T("not allowed to change a non-scalar value in '%.*js' to another non-scalar value"), var->id.name.len, var->id.name.ptr); else - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOSCALAR, HAWK_T("not allowed to change a map '%.*js' to a scalar"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOSCALAR, HAWK_T("not allowed to change a non-scalar value in '%.*js' to a scalar value"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } - else if (vtype == HAWK_VAL_MAP) + else if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* old value is not a map but a new value is a map. * a map cannot be assigned to a variable if FLEXMAP is off. */ - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_EMAPTOVAR, HAWK_T("not allowed to assign a map to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); + hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENONSCATOVAR, HAWK_T("not allowed to assign a non-scalar value to a variable '%.*js'"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } } @@ -4007,7 +4022,7 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk } else { - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTOMAP, HAWK_T("not allowed to change a nested scalar under '%.*js' to a map"), 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 non-scalar value"), var->id.name.len, var->id.name.ptr); goto oops_map; } } @@ -4064,7 +4079,7 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk { /* you can't manipulate a variable pointing to * a scalar value with an index if FLEXMAP is off. */ - hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ESCALARTOMAP, HAWK_T("not allowed to change a scalar '%.*js' to a map"), 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 non-scalar value"), var->id.name.len, var->id.name.ptr); return HAWK_NULL; } } @@ -6918,7 +6933,8 @@ static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) if (idx <= -1) return HAWK_NULL; arr = ((hawk_val_arr_t*)v)->arr; - /* return nil if the index is out of range or the element at the index is not set */ + /* 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; } diff --git a/hawk/lib/val.c b/hawk/lib/val.c index fcee6f67..9efb57de 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -1238,7 +1238,7 @@ hawk_val_t* hawk_rtx_makemapvalwithdata (hawk_rtx_t* rtx, hawk_val_map_data_t da hawk_val_t* hawk_rtx_setmapvalfld (hawk_rtx_t* rtx, hawk_val_t* map, const hawk_ooch_t* kptr, hawk_oow_t klen, hawk_val_t* v) { - HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, map) == HAWK_VAL_MAP); + HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, map) == HAWK_VAL_MAP); if (hawk_map_upsert(((hawk_val_map_t*)map)->map, (hawk_ooch_t*)kptr, klen, v, 0) == HAWK_NULL) return HAWK_NULL; @@ -1344,6 +1344,7 @@ const hawk_ooch_t* hawk_rtx_getvaltypename(hawk_rtx_t* rtx, hawk_val_t* val) HAWK_T("mbs"), HAWK_T("fun"), HAWK_T("map"), + HAWK_T("arr"), HAWK_T("rex"), HAWK_T("ref") }; @@ -1351,7 +1352,6 @@ const hawk_ooch_t* hawk_rtx_getvaltypename(hawk_rtx_t* rtx, hawk_val_t* val) return __val_type_name[HAWK_RTX_GETVALTYPE(rtx, val)]; } - int hawk_rtx_getintfromval (hawk_rtx_t* rtx, hawk_val_t* val) { return HAWK_RTX_GETINTFROMVAL(rtx, val); @@ -1636,6 +1636,8 @@ int hawk_rtx_valtobool (hawk_rtx_t* rtx, const hawk_val_t* val) case HAWK_VAL_MAP: /* true if the map size is greater than 0. false if not */ return HAWK_MAP_SIZE(((hawk_val_map_t*)val)->map) > 0; + case HAWK_VAL_ARR: + return HAWK_ARR_SIZE(((hawk_val_arr_t*)val)->arr) > 0; case HAWK_VAL_REF: return val_ref_to_bool(rtx, (hawk_val_ref_t*)val); } @@ -2068,6 +2070,13 @@ int hawk_rtx_valtostr (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_rtx_valtostr_o } goto invalid; + case HAWK_VAL_ARR: + if (rtx->hawk->opt.trait & HAWK_FLEXMAP) + { + return str_to_str(rtx, HAWK_T("#ARR"), 4, out); + } + goto invalid; + case HAWK_VAL_REF: return val_ref_to_str(rtx, (hawk_val_ref_t*)v, out); @@ -2412,6 +2421,14 @@ int hawk_rtx_valtonum (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_int_t* l, hawk } goto invalid; + case HAWK_VAL_ARR: + if (rtx->hawk->opt.trait & HAWK_FLEXMAP) + { + *l = HAWK_ARR_SIZE(((hawk_val_arr_t*)v)->arr); + return 0; /* long */ + } + goto invalid; + case HAWK_VAL_REF: return val_ref_to_num(rtx, (hawk_val_ref_t*)v, l, r); @@ -2665,8 +2682,9 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) switch (vtype) { case HAWK_VAL_MAP: + case HAWK_VAL_ARR: /* a map is assigned to a positional. this is disallowed. */ - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOPOS); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENONSCATOPOS); return -1; case HAWK_VAL_STR: @@ -2718,11 +2736,11 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) case HAWK_VAL_REF_LCLIDX: case HAWK_VAL_REF_ARGIDX: #if !defined(HAWK_ENABLE_GC) - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* an indexed variable cannot be assigned a map. * in other cases, it falls down to the default case. */ - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOIDX); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENONSCATOIDX); return -1; } #endif @@ -2735,15 +2753,15 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) rref = (hawk_val_t**)ref->adr; /* old value pointer */ rref_vtype = HAWK_RTX_GETVALTYPE(rtx, *rref); /* old value type */ - if (vtype == HAWK_VAL_MAP) + if (vtype == HAWK_VAL_MAP || vtype == HAWK_VAL_ARR) { /* new value: map, old value: nil or map => ok */ - if (rref_vtype != HAWK_VAL_NIL && rref_vtype != HAWK_VAL_MAP) + if (rref_vtype != HAWK_VAL_NIL && rref_vtype != vtype) { if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP)) { /* cannot change a scalar value to a map */ - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ESCALARTOMAP); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ESCALARTONONSCA); return -1; } } @@ -2751,11 +2769,11 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) else { /* new value: scalar, old value: nil or scalar => ok */ - if (rref_vtype == HAWK_VAL_MAP) + if (rref_vtype == HAWK_VAL_MAP || rref_vtype == HAWK_VAL_ARR) { if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP)) { - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOSCALAR); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENONSCATOSCALAR); return -1; } } @@ -2779,9 +2797,9 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) static hawk_map_walk_t print_pair (hawk_map_t* map, hawk_map_pair_t* pair, void* arg) { - hawk_rtx_t* run = (hawk_rtx_t*)arg; + hawk_rtx_t* rtx = (hawk_rtx_t*)arg; - HAWK_ASSERT (run == *(hawk_rtx_t**)hawk_map_getxtn(map)); + HAWK_ASSERT (rtx == *(hawk_rtx_t**)hawk_map_getxtn(map)); hawk_errputstrf (HAWK_T(" %.*s=>"), HAWK_MAP_KLEN(pair), HAWK_MAP_KPTR(pair)); hawk_dprintval ((hawk_rtx_t*)arg, HAWK_MAP_VPTR(pair)); @@ -2790,6 +2808,21 @@ static hawk_map_walk_t print_pair (hawk_map_t* map, hawk_map_pair_t* pair, void* return HAWK_MAP_WALK_FORWARD; } + +static hawk_arr_walk_t print_pair (hawk_arr_t* arr, hawk_oow_t index, void* arg) +{ + hawk_rtx_t* rtx = (hawk_rtx_t*)arg; + + HAWK_ASSERT (rtx == *(hawk_rtx_t**)hawk_arr_getxtn(arr)); + + hawk_errputstrf (HAWK_T(" %lu=>"), (unsigned long int)index); + hawk_dprintval ((hawk_rtx_t*)arg, (HAWK_ARR_SLOT(arr,index)? HAWK_ARR_DPTR(arr, index): hawk_val_nil)); + hawk_errputstrf (HAWK_T(" ")); + + return HAWK_ARR_WALK_FORWARD; +} + + void hawk_dprintval (hawk_rtx_t* run, hawk_val_t* val) { /* TODO: better value printing ... */ @@ -2832,6 +2865,12 @@ void hawk_dprintval (hawk_rtx_t* run, hawk_val_t* val) hawk_errputstrf (HAWK_T("]")); break; + case HAWK_VAL_ARR: + hawk_errputstrf (HAWK_T("ARR[")); + hawk_arr_walk (((hawk_val_arr_t*)val)->arr, print_elem, run); + hawk_errputstrf (HAWK_T("]")); + break; + case HAWK_VAL_REF: hawk_errputstrf (HAWK_T("REF[id=%d,val="), ((hawk_val_ref_t*)val)->id); hawk_dprintval (run, *((hawk_val_ref_t*)val)->adr); diff --git a/hawk/t/h-001.hawk b/hawk/t/h-001.hawk index 7aeabb16..8c635621 100644 --- a/hawk/t/h-001.hawk +++ b/hawk/t/h-001.hawk @@ -61,5 +61,17 @@ function main() ensure (b[2], "perfect", SCRIPTNAME); } + + { + @local a; + a[1] = hawk::array(); + a[1][2]=20; + ensure (a[1][2], 20, SCRIPTNAME); + a[1][2]++; + ensure (a[1][2], 21, SCRIPTNAME); + --a[1][2]; + ensure (a[1][2], 20, SCRIPTNAME); + } + print "SUCCESS" }