implementing assignment with true multi-dimensional map

This commit is contained in:
hyung-hwan 2020-04-03 02:05:12 +00:00
parent 76d295365a
commit 164d91661b

View File

@ -2977,49 +2977,44 @@ static int run_delete_unnamed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
vtype = HAWK_RTX_GETVALTYPE(rtx, val); vtype = HAWK_RTX_GETVALTYPE(rtx, val);
if (vtype == HAWK_VAL_NIL) if (vtype == HAWK_VAL_NIL)
{ {
hawk_val_t* tmp; if (!(rtx->hawk->opt.trait & HAWK_FLEXMAP))
/* value not set.
* create a map and assign it to the variable */
tmp = hawk_rtx_makemapval(rtx);
if (HAWK_UNLIKELY(!tmp))
{ {
ADJERR_LOC (rtx, &var->loc); hawk_val_t* tmp;
return -1;
}
/* no need to reduce the reference count of /* value not set.
* the previous value because it was nil. */ * create a map and assign it to the variable */
switch (var->type)
{ tmp = hawk_rtx_makemapval(rtx);
case HAWK_NDE_GBL: if (HAWK_UNLIKELY(!tmp)) goto oops;
case HAWK_NDE_GBLIDX:
/* no need to reduce the reference count of
* the previous value because it was nil. */
switch (var->type)
{ {
int x; case HAWK_NDE_GBL:
case HAWK_NDE_GBLIDX:
hawk_rtx_refupval (rtx, tmp);
x = hawk_rtx_setgbl(rtx, (int)var->id.idxa, tmp);
hawk_rtx_refdownval (rtx, tmp);
if (HAWK_UNLIKELY(x <= -1))
{ {
ADJERR_LOC (rtx, &var->loc); int x;
return -1;
hawk_rtx_refupval (rtx, tmp);
x = hawk_rtx_setgbl(rtx, (int)var->id.idxa, tmp);
hawk_rtx_refdownval (rtx, tmp);
if (HAWK_UNLIKELY(x <= -1)) goto oops;
break;
} }
break;
case HAWK_NDE_LCL:
case HAWK_NDE_LCLIDX:
HAWK_RTX_STACK_LCL(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
default:
HAWK_RTX_STACK_ARG(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
} }
case HAWK_NDE_LCL:
case HAWK_NDE_LCLIDX:
HAWK_RTX_STACK_LCL(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
default:
HAWK_RTX_STACK_ARG(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
} }
} }
else else
@ -3029,7 +3024,7 @@ static int run_delete_unnamed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
if (vtype != HAWK_VAL_MAP) if (vtype != HAWK_VAL_MAP)
{ {
hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENOTDEL, HAWK_T("'%.*js' not deletable"), var->id.name.len, var->id.name.ptr); hawk_rtx_seterrfmt (rtx, &var->loc, HAWK_ENOTDEL, HAWK_T("'%.*js' not deletable"), var->id.name.len, var->id.name.ptr);
return -1; goto oops;
} }
map = ((hawk_val_map_t*)val)->map; map = ((hawk_val_map_t*)val)->map;
@ -3037,15 +3032,28 @@ static int run_delete_unnamed (hawk_rtx_t* rtx, hawk_nde_var_t* var)
var->type == HAWK_NDE_LCLIDX || var->type == HAWK_NDE_LCLIDX ||
var->type == HAWK_NDE_ARGIDX) var->type == HAWK_NDE_ARGIDX)
{ {
if (delete_indexed(rtx, map, var) <= -1) return -1; if (delete_indexed(rtx, map, var) <= -1) goto oops;
} }
else else
{ {
/*
BEGIN {
@local a;
a[1] = 20; a[2] = "hello"; a[3][4][5]="ttt";
print typename(a), length(a);
delete a;
print typename(a), length(a);
}
*/
hawk_map_clear (map); hawk_map_clear (map);
} }
} }
return 0; return 0;
oops:
ADJERR_LOC (rtx, &var->loc);
return -1;
} }
static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde) static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde)
@ -3059,7 +3067,7 @@ static int run_delete (hawk_rtx_t* rtx, hawk_nde_delete_t* nde)
case HAWK_NDE_NAMED: case HAWK_NDE_NAMED:
case HAWK_NDE_NAMEDIDX: case HAWK_NDE_NAMEDIDX:
return run_delete_named(rtx, var); return run_delete_named(rtx, var);
case HAWK_NDE_GBL: case HAWK_NDE_GBL:
case HAWK_NDE_LCL: case HAWK_NDE_LCL:
case HAWK_NDE_ARG: case HAWK_NDE_ARG:
@ -3904,9 +3912,10 @@ static hawk_val_t* do_assignment_nonidx (hawk_rtx_t* rtx, hawk_nde_var_t* var, h
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_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk_val_t* val)
{ {
hawk_val_map_t* map; hawk_map_t* map;
hawk_val_type_t mvtype; hawk_val_t* vv; /* existing value pointed to by var */
hawk_ooch_t* str; hawk_val_type_t vtype;
hawk_ooch_t* str = HAWK_NULL;
hawk_oow_t len; hawk_oow_t len;
hawk_ooch_t idxbuf[IDXBUFSIZE]; hawk_ooch_t idxbuf[IDXBUFSIZE];
hawk_nde_t* remidx; hawk_nde_t* remidx;
@ -3917,7 +3926,7 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk
var->type == HAWK_NDE_LCLIDX || var->type == HAWK_NDE_LCLIDX ||
var->type == HAWK_NDE_ARGIDX) && var->idx != HAWK_NULL); var->type == HAWK_NDE_ARGIDX) && var->idx != HAWK_NULL);
#if !defined(HAWK_ENABLE_GC) #if !defined(HAWK_ENABLE_GC)
HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, val) != HAWK_VAL_MAP); HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, val) != HAWK_VAL_MAP);
#endif #endif
retry: retry:
@ -3927,130 +3936,189 @@ retry:
{ {
hawk_htb_pair_t* pair; hawk_htb_pair_t* pair;
pair = hawk_htb_search(rtx->named, var->id.name.ptr, var->id.name.len); pair = hawk_htb_search(rtx->named, var->id.name.ptr, var->id.name.len);
map = (pair == HAWK_NULL)? (hawk_val_map_t*)hawk_val_nil: (hawk_val_map_t*)HAWK_HTB_VPTR(pair); vv = (pair == HAWK_NULL)? hawk_val_nil: HAWK_HTB_VPTR(pair);
break; break;
} }
case HAWK_NDE_GBLIDX: case HAWK_NDE_GBLIDX:
map = (hawk_val_map_t*)HAWK_RTX_STACK_GBL(rtx,var->id.idxa); vv = HAWK_RTX_STACK_GBL(rtx,var->id.idxa);
break; break;
case HAWK_NDE_LCLIDX: case HAWK_NDE_LCLIDX:
map = (hawk_val_map_t*)HAWK_RTX_STACK_LCL(rtx,var->id.idxa); vv = HAWK_RTX_STACK_LCL(rtx,var->id.idxa);
break; break;
default: /* HAWK_NDE_ARGIDX */ default: /* HAWK_NDE_ARGIDX */
map = (hawk_val_map_t*)HAWK_RTX_STACK_ARG(rtx,var->id.idxa); vv = HAWK_RTX_STACK_ARG(rtx,var->id.idxa);
break; break;
} }
mvtype = HAWK_RTX_GETVALTYPE(rtx, map); /* check the value that the assigned variable points to */
if (mvtype == HAWK_VAL_NIL) vtype = HAWK_RTX_GETVALTYPE(rtx, vv);
switch (vtype)
{ {
hawk_val_t* tmp; case HAWK_VAL_NIL:
/* the map is not initialized yet */
tmp = hawk_rtx_makemapval(rtx);
if (HAWK_UNLIKELY(!tmp))
{ {
ADJERR_LOC (rtx, &var->loc); hawk_val_t* tmp;
return HAWK_NULL;
}
switch (var->type) /* the map is not initialized yet */
{ tmp = hawk_rtx_makemapval(rtx);
case HAWK_NDE_NAMEDIDX: if (HAWK_UNLIKELY(!tmp)) goto oops;
switch (var->type)
{ {
/* doesn't have to decrease the reference count case HAWK_NDE_NAMEDIDX:
* of the previous value here as it is done by
* hawk_htb_upsert */
hawk_rtx_refupval (rtx, tmp);
if (hawk_htb_upsert(rtx->named, var->id.name.ptr, var->id.name.len, tmp, 0) == HAWK_NULL)
{ {
/* doesn't have to decrease the reference count
* of the previous value here as it is done by
* hawk_htb_upsert */
hawk_rtx_refupval (rtx, tmp);
if (HAWK_UNLIKELY(hawk_htb_upsert(rtx->named, var->id.name.ptr, var->id.name.len, tmp, 0) == HAWK_NULL))
{
hawk_rtx_refdownval (rtx, tmp);
goto oops;
}
break;
}
case HAWK_NDE_GBLIDX:
{
int x;
hawk_rtx_refupval (rtx, tmp);
x = hawk_rtx_setgbl(rtx, (int)var->id.idxa, tmp);
hawk_rtx_refdownval (rtx, tmp); hawk_rtx_refdownval (rtx, tmp);
ADJERR_LOC (rtx, &var->loc); if (HAWK_UNLIKELY(x <= -1)) goto oops;
return HAWK_NULL; break;
} }
break; case HAWK_NDE_LCLIDX:
hawk_rtx_refdownval (rtx, vv);
HAWK_RTX_STACK_LCL(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
default: /* HAWK_NDE_ARGIDX */
hawk_rtx_refdownval (rtx, vv);
HAWK_RTX_STACK_ARG(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
} }
case HAWK_NDE_GBLIDX: vv = tmp;
break;
}
case HAWK_VAL_MAP:
/* nothing to do */
break;
default:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP)
{ {
int x; /* if FLEXMAP is on, you can switch a scalar value to a map */
hawk_nde_var_t fake;
hawk_rtx_refupval (rtx, tmp); /* create a fake non-indexed variable node */
x = hawk_rtx_setgbl(rtx, (int)var->id.idxa, tmp); fake = *var;
hawk_rtx_refdownval (rtx, tmp); /* NOTE: type conversion by decrementing by 4 is
if (HAWK_UNLIKELY(x <= -1)) * dependent on the hawk_nde_type_t
{ * enumerators defined in <hawk.h> */
ADJERR_LOC (rtx, &var->loc); fake.type = var->type - 4;
return HAWK_NULL; fake.idx = HAWK_NULL;
}
break; reset_variable (rtx, &fake);
goto retry;
} }
else
case HAWK_NDE_LCLIDX: {
hawk_rtx_refdownval (rtx, (hawk_val_t*)map); /* you can't manipulate a variable pointing to
HAWK_RTX_STACK_LCL(rtx,var->id.idxa) = tmp; * a scalar value with an index if FLEXMAP is off. */
hawk_rtx_refupval (rtx, tmp); 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);
break; goto oops;
}
default: /* HAWK_NDE_ARGIDX */ break;
hawk_rtx_refdownval (rtx, (hawk_val_t*)map);
HAWK_RTX_STACK_ARG(rtx,var->id.idxa) = tmp;
hawk_rtx_refupval (rtx, tmp);
break;
}
map = (hawk_val_map_t*)tmp;
}
else if (mvtype != HAWK_VAL_MAP)
{
if (rtx->hawk->opt.trait & HAWK_FLEXMAP)
{
/* if FLEXMAP is on, you can switch a scalar value to a map */
hawk_nde_var_t fake;
/* create a fake non-indexed variable node */
fake = *var;
/* NOTE: type conversion by decrementing by 4 is
* dependent on the hawk_nde_type_t
* enumerators defined in <hawk.h> */
fake.type = var->type - 4;
fake.idx = HAWK_NULL;
reset_variable (rtx, &fake);
goto retry;
}
else
{
/* 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);
return HAWK_NULL;
}
} }
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)) return HAWK_NULL; if (HAWK_UNLIKELY(!str)) goto oops;
map = ((hawk_val_map_t*)vv)->map;
#if defined(DEBUG_RUN) #if defined(HAWK_ENABLE_GC)
hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("**** index str=>%s, map->ref=%d, map->type=%d\n"), str, (int)map->ref, (int)map->type); while (remidx)
{
hawk_map_pair_t* pair;
pair = hawk_map_search(map, str, len);
vv = pair? (hawk_val_t*)HAWK_HTB_VPTR(pair): hawk_val_nil;
vtype = HAWK_RTX_GETVALTYPE(rtx, vv);
switch (vtype)
{
case HAWK_VAL_NIL:
remidx_nil_to_map:
vv = hawk_rtx_makemapval(rtx);
if (HAWK_UNLIKELY(!vv)) goto oops;
hawk_rtx_refupval (rtx, vv);
pair = hawk_map_upsert(map, str, len, vv, 0);
if (HAWK_UNLIKELY(!pair))
{
hawk_rtx_refdownval (rtx, vv);
goto oops;
}
map = ((hawk_val_map_t*)vv)->map;
break;
case HAWK_VAL_MAP:
map = ((hawk_val_map_t*)vv)->map;
break;
default:
if (rtx->hawk->opt.trait & HAWK_FLEXMAP)
{
/* 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 { b="hello"; a[1]=b; a[1][2]=20; print a[1][2]; } */
goto remidx_nil_to_map;
}
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);
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;
pair = hawk_map_search(map, str, len);
}
#endif #endif
if (hawk_map_upsert(map->map, str, len, val, 0) == HAWK_NULL) #if defined(DEBUG_RUN)
{ hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("**** index str=>%s, map->ref=%d, map->type=%d\n"), str, (int)v->ref, (int)v->type);
if (str != idxbuf) hawk_rtx_freemem (rtx, str); #endif
ADJERR_LOC (rtx, &var->loc);
return HAWK_NULL;
}
if (str != idxbuf) hawk_rtx_freemem (rtx, str); if (HAWK_UNLIKELY(hawk_map_upsert(map, str, len, val, 0) == HAWK_NULL)) goto oops;
if (str != idxbuf) hawk_rtx_freemem (rtx, str);
hawk_rtx_refupval (rtx, val); hawk_rtx_refupval (rtx, val);
return val; return val;
oops:
if (str && str != idxbuf) hawk_rtx_freemem (rtx, str);
ADJERR_LOC (rtx, &var->loc);
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_pos (hawk_rtx_t* rtx, hawk_nde_pos_t* pos, hawk_val_t* val)
@ -7360,6 +7428,7 @@ static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t
{ {
hawk_rtx_refdownval (rtx, idx); hawk_rtx_refdownval (rtx, idx);
hawk_ooecs_fini (&idxstr); hawk_ooecs_fini (&idxstr);
ADJERR_LOC (rtx, &nde->loc);
return HAWK_NULL; return HAWK_NULL;
} }