changed the behavior of for(x in y) loop - it now takes a snapshot of keys before running body
This commit is contained in:
parent
66d461e664
commit
6502a2e388
@ -45,7 +45,7 @@
|
||||
#endif
|
||||
|
||||
/// \file
|
||||
/// AWK Interpreter
|
||||
/// Hawk Interpreter
|
||||
|
||||
/////////////////////////////////
|
||||
HAWK_BEGIN_NAMESPACE(HAWK)
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <Hawk.hpp>
|
||||
|
||||
/// \file
|
||||
/// Standard AWK Interpreter
|
||||
/// Standard Hawk Interpreter
|
||||
|
||||
/////////////////////////////////
|
||||
HAWK_BEGIN_NAMESPACE(HAWK)
|
||||
|
@ -491,6 +491,13 @@ struct hawk_rtx_t
|
||||
hawk_oow_t expr; /* expression */
|
||||
} depth;
|
||||
|
||||
struct
|
||||
{
|
||||
hawk_val_t** ptr;
|
||||
hawk_oow_t size;
|
||||
hawk_oow_t capa;
|
||||
} forin; /* keys for for (x in y) ... */
|
||||
|
||||
hawk_oow_t errmsg_len; /* used by errbfmt() and errufmt(). don't rely on this. some other funtions don't set this properly */
|
||||
hawk_ooch_t errmsg_backup[HAWK_ERRMSG_CAPA];
|
||||
#if defined(HAWK_OOCH_IS_BCH)
|
||||
|
@ -230,6 +230,21 @@ enum hawk_rbt_style_kind_t
|
||||
|
||||
typedef enum hawk_rbt_style_kind_t hawk_rbt_style_kind_t;
|
||||
|
||||
typedef struct hawk_rbt_itr_t hawk_rbt_itr_t;
|
||||
struct hawk_rbt_itr_t
|
||||
{
|
||||
hawk_rbt_pair_t* pair;
|
||||
hawk_rbt_pair_t* _prev;
|
||||
unsigned int _dir: 1; /* 0 or 1 */
|
||||
unsigned int _state: 8;
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
unsigned int _prot_updated: 1;
|
||||
hawk_oow_t _prot_seqno;
|
||||
hawk_rbt_itr_t* _prot_prev;
|
||||
hawk_rbt_itr_t* _prot_next;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* The hawk_rbt_t type defines a red-black tree.
|
||||
*/
|
||||
@ -241,19 +256,11 @@ struct hawk_rbt_t
|
||||
hawk_rbt_pair_t xnil; /**< internal nil node */
|
||||
hawk_oow_t size; /**< number of pairs */
|
||||
hawk_rbt_pair_t* root; /**< root pair */
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
hawk_rbt_itr_t _prot_itr; /**< protected iterators */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct hawk_rbt_itr_t
|
||||
{
|
||||
hawk_rbt_pair_t* pair;
|
||||
hawk_rbt_pair_t* _prev;
|
||||
int _dir; /* 0 or 1 */
|
||||
int _state;
|
||||
};
|
||||
|
||||
typedef struct hawk_rbt_itr_t hawk_rbt_itr_t;
|
||||
|
||||
/**
|
||||
* The HAWK_RBT_COPIER_SIMPLE macros defines a copier that remembers the
|
||||
* pointer and length of data in a pair.
|
||||
@ -564,6 +571,18 @@ HAWK_EXPORT hawk_rbt_pair_t* hawk_rbt_getnextpair (
|
||||
hawk_rbt_itr_t* itr
|
||||
);
|
||||
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
HAWK_EXPORT void hawk_rbt_protectitr (
|
||||
hawk_rbt_t* rbt,
|
||||
hawk_rbt_itr_t* itr
|
||||
);
|
||||
|
||||
HAWK_EXPORT void hawk_rbt_unprotectitr (
|
||||
hawk_rbt_t* rbt,
|
||||
hawk_rbt_itr_t* itr
|
||||
);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The hawk_rbt_walk() function traverses a red-black tree in preorder
|
||||
* from the leftmost child.
|
||||
|
@ -373,7 +373,7 @@ enum hawk_nde_type_t
|
||||
HAWK_NDE_WHILE,
|
||||
HAWK_NDE_DOWHILE,
|
||||
HAWK_NDE_FOR,
|
||||
HAWK_NDE_FOREACH,
|
||||
HAWK_NDE_FORIN,
|
||||
HAWK_NDE_BREAK,
|
||||
HAWK_NDE_CONTINUE,
|
||||
HAWK_NDE_RETURN,
|
||||
|
@ -2613,7 +2613,7 @@ static hawk_nde_t* parse_for (hawk_t* awk, const hawk_loc_t* xloc)
|
||||
hawk_nde_t* init = HAWK_NULL, * test = HAWK_NULL;
|
||||
hawk_nde_t* incr = HAWK_NULL, * body = HAWK_NULL;
|
||||
hawk_nde_for_t* nde_for;
|
||||
hawk_nde_foreach_t* nde_foreach;
|
||||
hawk_nde_forin_t* nde_forin;
|
||||
hawk_loc_t ploc;
|
||||
|
||||
if (!MATCH(awk,TOK_LPAREN))
|
||||
@ -2628,17 +2628,17 @@ static hawk_nde_t* parse_for (hawk_t* awk, const hawk_loc_t* xloc)
|
||||
/* this line is very ugly. it checks the entire next
|
||||
* expression or the first element in the expression
|
||||
* is wrapped by a parenthesis */
|
||||
int no_foreach = MATCH(awk,TOK_LPAREN);
|
||||
int no_forin = MATCH(awk,TOK_LPAREN);
|
||||
|
||||
ploc = awk->tok.loc;
|
||||
init = parse_expr_withdc (awk, &ploc);
|
||||
if (init == HAWK_NULL) goto oops;
|
||||
|
||||
if (!no_foreach && init->type == HAWK_NDE_EXP_BIN &&
|
||||
if (!no_forin && init->type == HAWK_NDE_EXP_BIN &&
|
||||
((hawk_nde_exp_t*)init)->opcode == HAWK_BINOP_IN &&
|
||||
is_plain_var(((hawk_nde_exp_t*)init)->left))
|
||||
{
|
||||
/* switch to foreach - for (x in y) */
|
||||
/* switch to forin - for (x in y) */
|
||||
|
||||
if (!MATCH(awk,TOK_RPAREN))
|
||||
{
|
||||
@ -2652,20 +2652,20 @@ static hawk_nde_t* parse_for (hawk_t* awk, const hawk_loc_t* xloc)
|
||||
body = parse_statement (awk, &ploc);
|
||||
if (body == HAWK_NULL) goto oops;
|
||||
|
||||
nde_foreach = (hawk_nde_foreach_t*) hawk_callocmem (
|
||||
awk, HAWK_SIZEOF(*nde_foreach));
|
||||
if (nde_foreach == HAWK_NULL)
|
||||
nde_forin = (hawk_nde_forin_t*) hawk_callocmem (
|
||||
awk, HAWK_SIZEOF(*nde_forin));
|
||||
if (nde_forin == HAWK_NULL)
|
||||
{
|
||||
ADJERR_LOC (awk, xloc);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
nde_foreach->type = HAWK_NDE_FOREACH;
|
||||
nde_foreach->loc = *xloc;
|
||||
nde_foreach->test = init;
|
||||
nde_foreach->body = body;
|
||||
nde_forin->type = HAWK_NDE_FORIN;
|
||||
nde_forin->loc = *xloc;
|
||||
nde_forin->test = init;
|
||||
nde_forin->body = body;
|
||||
|
||||
return (hawk_nde_t*)nde_foreach;
|
||||
return (hawk_nde_t*)nde_forin;
|
||||
}
|
||||
|
||||
if (!MATCH(awk,TOK_SEMICOLON))
|
||||
|
111
hawk/lib/rbt.c
111
hawk/lib/rbt.c
@ -235,6 +235,11 @@ int hawk_rbt_init (hawk_rbt_t* rbt, hawk_gem_t* gem, int kscale, int vscale)
|
||||
/* root is set to nil initially */
|
||||
rbt->root = &rbt->xnil;
|
||||
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
rbt->_prot_itr._prot_next = &rbt->_prot_itr;
|
||||
rbt->_prot_itr._prot_prev = &rbt->_prot_itr;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -408,8 +413,7 @@ static void adjust (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
||||
}
|
||||
}
|
||||
|
||||
static hawk_rbt_pair_t* change_pair_val (
|
||||
hawk_rbt_t* rbt, hawk_rbt_pair_t* pair, void* vptr, hawk_oow_t vlen)
|
||||
static hawk_rbt_pair_t* change_pair_val (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair, void* vptr, hawk_oow_t vlen)
|
||||
{
|
||||
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
|
||||
{
|
||||
@ -769,7 +773,7 @@ static void adjust_for_delete (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair, hawk_rbt_
|
||||
|
||||
static void delete_pair (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
||||
{
|
||||
hawk_rbt_pair_t* x, * y, * par;
|
||||
hawk_rbt_pair_t* x, * y, * parent;
|
||||
|
||||
HAWK_ASSERT (pair && !IS_NIL(rbt,pair));
|
||||
|
||||
@ -786,15 +790,15 @@ static void delete_pair (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
||||
|
||||
x = IS_NIL(rbt,y->left)? y->right: y->left;
|
||||
|
||||
par = y->parent;
|
||||
if (!IS_NIL(rbt,x)) x->parent = par;
|
||||
parent = y->parent;
|
||||
if (!IS_NIL(rbt,x)) x->parent = parent;
|
||||
|
||||
if (par)
|
||||
if (parent)
|
||||
{
|
||||
if (y == par->left)
|
||||
par->left = x;
|
||||
if (y == parent->left)
|
||||
parent->left = x;
|
||||
else
|
||||
par->right = x;
|
||||
parent->right = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -804,16 +808,15 @@ static void delete_pair (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
||||
if (y == pair)
|
||||
{
|
||||
if (y->color == HAWK_RBT_BLACK && !IS_NIL(rbt,x))
|
||||
adjust_for_delete (rbt, x, par);
|
||||
adjust_for_delete (rbt, x, parent);
|
||||
|
||||
hawk_rbt_freepair (rbt, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y->color == HAWK_RBT_BLACK && !IS_NIL(rbt,x))
|
||||
adjust_for_delete (rbt, x, par);
|
||||
adjust_for_delete (rbt, x, parent);
|
||||
|
||||
#if 1
|
||||
if (pair->parent)
|
||||
{
|
||||
if (pair->parent->left == pair) pair->parent->left = y;
|
||||
@ -831,34 +834,48 @@ static void delete_pair (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
||||
|
||||
if (pair->left->parent == pair) pair->left->parent = y;
|
||||
if (pair->right->parent == pair) pair->right->parent = y;
|
||||
#else
|
||||
*y = *pair;
|
||||
if (y->parent)
|
||||
{
|
||||
if (y->parent->left == pair) y->parent->left = y;
|
||||
if (y->parent->right == pair) y->parent->right = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
rbt->root = y;
|
||||
}
|
||||
|
||||
if (y->left->parent == pair) y->left->parent = y;
|
||||
if (y->right->parent == pair) y->right->parent = y;
|
||||
#endif
|
||||
|
||||
hawk_rbt_freepair (rbt, pair);
|
||||
}
|
||||
|
||||
rbt->size--;
|
||||
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
/* an iterator set by hawk_rbt_getfirstpair() or hawk_rbt_getnextpair(), if deleted, gets invalidated.
|
||||
* this protection updates registered iterators to the next valid pair if they gets deleted.
|
||||
* the caller may reuse the iterator if _prot_updated is set to a non-zero value */
|
||||
if (rbt->_prot_itr._prot_next != &rbt->_prot_itr)
|
||||
{
|
||||
/* there are protected iterators */
|
||||
hawk_rbt_itr_t* itr = rbt->_prot_itr._prot_next;
|
||||
do
|
||||
{
|
||||
if (itr->pair == pair)
|
||||
{
|
||||
hawk_oow_t seqno = itr->_prot_seqno;
|
||||
|
||||
/* TODO: this is slow. devise a way to get the next pair safely without traversal */
|
||||
hawk_rbt_getfirstpair (rbt, itr);
|
||||
while (itr->pair && itr->_prot_seqno < seqno)
|
||||
{
|
||||
hawk_rbt_getnextpair (rbt, itr);
|
||||
}
|
||||
|
||||
itr->_prot_updated = 1;
|
||||
}
|
||||
itr = itr->_prot_next;
|
||||
}
|
||||
while (itr != &rbt->_prot_itr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int hawk_rbt_delete (hawk_rbt_t* rbt, const void* kptr, hawk_oow_t klen)
|
||||
{
|
||||
hawk_rbt_pair_t* pair;
|
||||
|
||||
pair = hawk_rbt_search (rbt, kptr, klen);
|
||||
if (pair == HAWK_NULL) return -1;
|
||||
pair = hawk_rbt_search(rbt, kptr, klen);
|
||||
if (!pair) return -1;
|
||||
|
||||
delete_pair (rbt, pair);
|
||||
return 0;
|
||||
@ -900,7 +917,6 @@ void hawk_init_rbt_itr (hawk_rbt_itr_t* itr, int dir)
|
||||
itr->_state = 0;
|
||||
}
|
||||
|
||||
|
||||
static hawk_rbt_pair_t* get_next_pair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
{
|
||||
hawk_rbt_pair_t* x_cur = itr->pair;
|
||||
@ -929,6 +945,9 @@ static hawk_rbt_pair_t* get_next_pair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
itr->pair = x_cur;
|
||||
itr->_prev = prev;
|
||||
itr->_state = 1;
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
itr->_prot_seqno++;
|
||||
#endif
|
||||
return x_cur;
|
||||
|
||||
resume_1:
|
||||
@ -954,6 +973,9 @@ static hawk_rbt_pair_t* get_next_pair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
itr->pair = x_cur;
|
||||
itr->_prev = prev;
|
||||
itr->_state = 2;
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
itr->_prot_seqno++;
|
||||
#endif
|
||||
return x_cur;
|
||||
|
||||
resume_2:
|
||||
@ -980,6 +1002,9 @@ static hawk_rbt_pair_t* get_next_pair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
}
|
||||
}
|
||||
|
||||
itr->pair = HAWK_NULL;
|
||||
itr->_prev = HAWK_NULL;
|
||||
itr->_state = 0;
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
@ -988,6 +1013,12 @@ hawk_rbt_pair_t* hawk_rbt_getfirstpair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
itr->pair = rbt->root;
|
||||
itr->_prev = rbt->root->parent;
|
||||
itr->_state = 0;
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
itr->_prot_seqno = 0;
|
||||
/* _prot_prev and _prot_next must be left uninitialized because of the way
|
||||
* this function is called in delete_pair() for protection handling
|
||||
*/
|
||||
#endif
|
||||
return get_next_pair(rbt, itr);
|
||||
}
|
||||
|
||||
@ -996,12 +1027,28 @@ hawk_rbt_pair_t* hawk_rbt_getnextpair (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
return get_next_pair(rbt, itr);
|
||||
}
|
||||
|
||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||
void hawk_rbt_protectitr (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
{
|
||||
itr->_prot_next = &rbt->_prot_itr;
|
||||
itr->_prot_prev = rbt->_prot_itr._prot_prev;
|
||||
itr->_prot_prev->_prot_next = itr;
|
||||
rbt->_prot_itr._prot_prev = itr;
|
||||
}
|
||||
|
||||
void hawk_rbt_unprotectitr (hawk_rbt_t* rbt, hawk_rbt_itr_t* itr)
|
||||
{
|
||||
itr->_prot_prev->_prot_next = itr->_prot_next;
|
||||
itr->_prot_next->_prot_prev = itr->_prot_prev;
|
||||
}
|
||||
#endif
|
||||
|
||||
void hawk_rbt_walk (hawk_rbt_t* rbt, walker_t walker, void* ctx)
|
||||
{
|
||||
hawk_rbt_itr_t itr;
|
||||
hawk_rbt_pair_t* pair;
|
||||
|
||||
itr._dir = 0;
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
pair = hawk_rbt_getfirstpair(rbt, &itr);
|
||||
while (pair)
|
||||
{
|
||||
@ -1015,7 +1062,7 @@ void hawk_rbt_rwalk (hawk_rbt_t* rbt, walker_t walker, void* ctx)
|
||||
hawk_rbt_itr_t itr;
|
||||
hawk_rbt_pair_t* pair;
|
||||
|
||||
itr._dir = 1;
|
||||
hawk_init_map_itr (&itr, 1);
|
||||
pair = hawk_rbt_getfirstpair(rbt, &itr);
|
||||
while (pair)
|
||||
{
|
||||
|
121
hawk/lib/run.c
121
hawk/lib/run.c
@ -104,7 +104,7 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||
static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde);
|
||||
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde);
|
||||
static int run_for (hawk_rtx_t* rtx, hawk_nde_for_t* nde);
|
||||
static int run_foreach (hawk_rtx_t* rtx, hawk_nde_foreach_t* nde);
|
||||
static int run_forin (hawk_rtx_t* rtx, hawk_nde_forin_t* nde);
|
||||
static int run_break (hawk_rtx_t* rtx, hawk_nde_break_t* nde);
|
||||
static int run_continue (hawk_rtx_t* rtx, hawk_nde_continue_t* nde);
|
||||
static int run_return (hawk_rtx_t* rtx, hawk_nde_return_t* nde);
|
||||
@ -1136,6 +1136,17 @@ oops_0:
|
||||
|
||||
static void fini_rtx (hawk_rtx_t* rtx, int fini_globals)
|
||||
{
|
||||
if (rtx->forin.ptr)
|
||||
{
|
||||
while (rtx->forin.size > 0)
|
||||
{
|
||||
hawk_rtx_refdownval (rtx, rtx->forin.ptr[--rtx->forin.size]);
|
||||
}
|
||||
hawk_rtx_freemem (rtx, rtx->forin.ptr);
|
||||
rtx->forin.ptr = HAWK_NULL;
|
||||
rtx->forin.capa = 0;
|
||||
}
|
||||
|
||||
if (rtx->pattern_range_state)
|
||||
hawk_rtx_freemem (rtx, rtx->pattern_range_state);
|
||||
|
||||
@ -1273,7 +1284,7 @@ static void fini_rtx (hawk_rtx_t* rtx, int fini_globals)
|
||||
{
|
||||
while (rtx->mbs_cache_count[i] > 0)
|
||||
{
|
||||
hawk_val_str_t* t = rtx->mbs_cache[i][--rtx->mbs_cache_count[i]];
|
||||
hawk_val_mbs_t* t = rtx->mbs_cache[i][--rtx->mbs_cache_count[i]];
|
||||
hawk_rtx_freeval (rtx, (hawk_val_t*)t, 0);
|
||||
}
|
||||
}
|
||||
@ -2154,7 +2165,7 @@ static HAWK_INLINE int run_block0 (hawk_rtx_t* rtx, hawk_nde_blk_t* nde)
|
||||
while (nlcls > 0)
|
||||
{
|
||||
--nlcls;
|
||||
hawk_rtx_refdownval (rtx, RTX_STACK_LCL(rtx,nlcls));
|
||||
hawk_rtx_refdownval (rtx, RTX_STACK_LCL(rtx, nlcls));
|
||||
__raw_pop (rtx);
|
||||
}
|
||||
|
||||
@ -2217,8 +2228,8 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
xret = run_for(rtx, (hawk_nde_for_t*)nde);
|
||||
break;
|
||||
|
||||
case HAWK_NDE_FOREACH:
|
||||
xret = run_foreach(rtx, (hawk_nde_foreach_t*)nde);
|
||||
case HAWK_NDE_FORIN:
|
||||
xret = run_forin(rtx, (hawk_nde_forin_t*)nde);
|
||||
break;
|
||||
|
||||
case HAWK_NDE_BREAK:
|
||||
@ -2476,16 +2487,18 @@ static int run_for (hawk_rtx_t* rtx, hawk_nde_for_t* nde)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_foreach (hawk_rtx_t* rtx, hawk_nde_foreach_t* nde)
|
||||
static int run_forin (hawk_rtx_t* rtx, hawk_nde_forin_t* nde)
|
||||
{
|
||||
hawk_nde_exp_t* test;
|
||||
hawk_val_t* rv;
|
||||
hawk_map_t* map;
|
||||
hawk_map_t* map = HAWK_NULL;
|
||||
hawk_map_pair_t* pair;
|
||||
hawk_map_itr_t itr;
|
||||
hawk_val_type_t rvtype;
|
||||
hawk_oow_t old_forin_size, i;
|
||||
int ret;
|
||||
|
||||
|
||||
test = (hawk_nde_exp_t*)nde->test;
|
||||
HAWK_ASSERT (test->type == HAWK_NDE_EXP_BIN && test->opcode == HAWK_BINOP_IN);
|
||||
|
||||
@ -2514,12 +2527,94 @@ static int run_foreach (hawk_rtx_t* rtx, hawk_nde_foreach_t* nde)
|
||||
|
||||
map = ((hawk_val_map_t*)rv)->map;
|
||||
|
||||
|
||||
#if 1
|
||||
old_forin_size = rtx->forin.size;
|
||||
|
||||
if (rtx->forin.capa - rtx->forin.size < hawk_map_getsize(map))
|
||||
{
|
||||
hawk_val_t** tmp;
|
||||
hawk_oow_t newcapa;
|
||||
|
||||
newcapa = rtx->forin.size + hawk_map_getsize(map);
|
||||
newcapa = HAWK_ALIGN_POW2(newcapa, 128);
|
||||
tmp = hawk_rtx_reallocmem(rtx, rtx->forin.ptr, newcapa * HAWK_SIZEOF(*tmp));
|
||||
if (HAWK_UNLIKELY(!tmp))
|
||||
{
|
||||
ADJERR_LOC (rtx, &test->left->loc);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtx->forin.ptr = tmp;
|
||||
rtx->forin.capa = newcapa;
|
||||
}
|
||||
|
||||
/* take a snapshot of the keys first so that the actual pairs become mutation safe
|
||||
* this proctection is needed in case the body contains destructive statements like 'delete' or '@reset'*/
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
pair = hawk_map_getfirstpair(map, &itr);
|
||||
while (pair)
|
||||
{
|
||||
hawk_val_t* str;
|
||||
|
||||
str = (hawk_val_t*)hawk_rtx_makenstrvalwithoochars(rtx, HAWK_HTB_KPTR(pair), HAWK_HTB_KLEN(pair));
|
||||
if (HAWK_UNLIKELY(!str))
|
||||
{
|
||||
ADJERR_LOC (rtx, &test->left->loc);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtx->forin.ptr[rtx->forin.size++] = str;
|
||||
hawk_rtx_refupval (rtx, str);
|
||||
|
||||
pair = hawk_map_getnextpair(map, &itr);
|
||||
}
|
||||
|
||||
/* iterate over the keys in the snapshot */
|
||||
for (i = old_forin_size; i < rtx->forin.size; i++)
|
||||
{
|
||||
if (HAWK_UNLIKELY(!do_assignment(rtx, test->left, rtx->forin.ptr[i])) || HAWK_UNLIKELY(run_statement(rtx, nde->body) <= -1))
|
||||
{
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (rtx->exit_level == EXIT_BREAK)
|
||||
{
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
goto done;
|
||||
}
|
||||
else if (rtx->exit_level == EXIT_CONTINUE)
|
||||
{
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
}
|
||||
else if (rtx->exit_level != EXIT_NONE)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
while (rtx->forin.size > old_forin_size)
|
||||
hawk_rtx_refdownval (rtx, rtx->forin.ptr[--rtx->forin.size]);
|
||||
hawk_rtx_refdownval (rtx, rv);
|
||||
return ret;
|
||||
#else
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
#if defined(HAWK_MAP_IS_RBT)
|
||||
hawk_rbt_protectitr (map, &itr);
|
||||
#endif
|
||||
pair = hawk_map_getfirstpair(map, &itr);
|
||||
while (pair)
|
||||
{
|
||||
hawk_val_t* str;
|
||||
|
||||
#if defined(HAWK_MAP_IS_RBT)
|
||||
itr._prot_updated = 0;
|
||||
#endif
|
||||
|
||||
str = (hawk_val_t*)hawk_rtx_makestrvalwithoochars(rtx, HAWK_HTB_KPTR(pair), HAWK_HTB_KLEN(pair));
|
||||
if (HAWK_UNLIKELY(!str))
|
||||
{
|
||||
@ -2529,7 +2624,7 @@ static int run_foreach (hawk_rtx_t* rtx, hawk_nde_foreach_t* nde)
|
||||
}
|
||||
|
||||
hawk_rtx_refupval (rtx, str);
|
||||
if (!do_assignment(rtx, test->left, str) || run_statement(rtx, nde->body) <= -1)
|
||||
if (HAWK_UNLIKELY(!do_assignment(rtx, test->left, str)) || HAWK_UNLIKELY(run_statement(rtx, nde->body) <= -1))
|
||||
{
|
||||
hawk_rtx_refdownval (rtx, str);
|
||||
ret = -1;
|
||||
@ -2551,12 +2646,20 @@ static int run_foreach (hawk_rtx_t* rtx, hawk_nde_foreach_t* nde)
|
||||
goto done;
|
||||
}
|
||||
|
||||
pair = hawk_map_getnextpair(map, &itr);
|
||||
#if defined(HAWK_MAP_IS_RBT)
|
||||
pair = itr._prot_updated? itr.pair: hawk_map_getnextpair(map, &itr);
|
||||
#else
|
||||
# error UNSUPPORTED
|
||||
#endif
|
||||
}
|
||||
|
||||
done:
|
||||
#if defined(HAWK_MAP_IS_RBT)
|
||||
if (map) hawk_rbt_unprotectitr (map, &itr);
|
||||
#endif
|
||||
hawk_rtx_refdownval (rtx, rv);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int run_break (hawk_rtx_t* run, hawk_nde_break_t* nde)
|
||||
|
@ -71,7 +71,7 @@ typedef struct hawk_nde_getline_t hawk_nde_getline_t;
|
||||
typedef struct hawk_nde_if_t hawk_nde_if_t;
|
||||
typedef struct hawk_nde_while_t hawk_nde_while_t;
|
||||
typedef struct hawk_nde_for_t hawk_nde_for_t;
|
||||
typedef struct hawk_nde_foreach_t hawk_nde_foreach_t;
|
||||
typedef struct hawk_nde_forin_t hawk_nde_forin_t;
|
||||
typedef struct hawk_nde_break_t hawk_nde_break_t;
|
||||
typedef struct hawk_nde_continue_t hawk_nde_continue_t;
|
||||
typedef struct hawk_nde_return_t hawk_nde_return_t;
|
||||
@ -263,8 +263,8 @@ struct hawk_nde_for_t
|
||||
hawk_nde_t* body;
|
||||
};
|
||||
|
||||
/* HAWK_NDE_FOREACH */
|
||||
struct hawk_nde_foreach_t
|
||||
/* HAWK_NDE_FORIN */
|
||||
struct hawk_nde_forin_t
|
||||
{
|
||||
HAWK_NDE_HDR;
|
||||
hawk_nde_t* test;
|
||||
|
@ -955,9 +955,9 @@ static int print_stmt (hawk_t* awk, hawk_nde_t* p, int depth)
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_FOREACH:
|
||||
case HAWK_NDE_FORIN:
|
||||
{
|
||||
hawk_nde_foreach_t* px = (hawk_nde_foreach_t*)p;
|
||||
hawk_nde_forin_t* px = (hawk_nde_forin_t*)p;
|
||||
|
||||
PRINT_TABS (awk, depth);
|
||||
hawk_getkwname (awk, HAWK_KWID_FOR, &kw);
|
||||
@ -1209,10 +1209,10 @@ void hawk_clrpt (hawk_t* awk, hawk_nde_t* tree)
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_FOREACH:
|
||||
case HAWK_NDE_FORIN:
|
||||
{
|
||||
hawk_clrpt (awk, ((hawk_nde_foreach_t*)p)->test);
|
||||
hawk_clrpt (awk, ((hawk_nde_foreach_t*)p)->body);
|
||||
hawk_clrpt (awk, ((hawk_nde_forin_t*)p)->test);
|
||||
hawk_clrpt (awk, ((hawk_nde_forin_t*)p)->body);
|
||||
hawk_freemem (awk, p);
|
||||
break;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ static void gc_trace_refs (hawk_gch_t* list)
|
||||
|
||||
/* as of now, there is only one type available - HAWK_VAL_MAP */
|
||||
HAWK_ASSERT (v->v_type == HAWK_VAL_MAP);
|
||||
itr._dir = 0;
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
pair = hawk_map_getfirstpair(((hawk_val_map_t*)v)->map, &itr);
|
||||
while (pair)
|
||||
{
|
||||
@ -184,7 +184,7 @@ static void gc_move_reachables (hawk_gch_t* list, hawk_gch_t* reachable_list)
|
||||
/* as of now, there is only one type available - HAWK_VAL_MAP */
|
||||
/* the key part is a string. don't care. but if a generic value is allowed as a key, this should change... */
|
||||
HAWK_ASSERT (v->v_type == HAWK_VAL_MAP);
|
||||
itr._dir = 0;
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
pair = hawk_map_getfirstpair(((hawk_val_map_t*)v)->map, &itr);
|
||||
while (pair)
|
||||
{
|
||||
@ -214,8 +214,29 @@ static void gc_free_unreachables (hawk_rtx_t* rtx, hawk_gch_t* list)
|
||||
while (gch != list)
|
||||
{
|
||||
tmp = gch->gc_next;
|
||||
printf ("^^^^^^^^^^^^^^^^^^^^^^^^ freeing %p(%p) gc_refs %d v_refs %d\n", gch, gch->gc_refs, hawk_gch_to_val(gch)->v_refs);
|
||||
hawk_rtx_freeval (rtx, hawk_gch_to_val(gch), 0);
|
||||
|
||||
printf ("^^^^^^^^^^^^^^^^^^^^^^^^ freeing %p gc_refs %d v_refs %d\n", gch, (int)gch->gc_refs, (int)hawk_gch_to_val(gch)->v_refs);
|
||||
//hawk_rtx_freeval (rtx, hawk_gch_to_val(gch), 0);
|
||||
|
||||
{
|
||||
// TODO: revise this. MAP ONLY as of now.
|
||||
hawk_val_map_t* v = (hawk_val_map_t*)hawk_gch_to_val(gch);
|
||||
hawk_map_pair_t* pair;
|
||||
hawk_map_itr_t itr;
|
||||
hawk_oow_t refs = 0;
|
||||
|
||||
hawk_init_map_itr (&itr, 0);
|
||||
pair = hawk_map_getfirstpair(v->map, &itr);
|
||||
while (pair)
|
||||
{
|
||||
if (HAWK_MAP_VPTR(pair) == v) refs++;
|
||||
else hawk_rtx_refdownval (rtx, HAWK_MAP_VPTR(pair));
|
||||
pair = hawk_map_getnextpair(v->map, &itr);
|
||||
}
|
||||
|
||||
while (refs-- > 0) hawk_rtx_refdownval (rtx, v);
|
||||
}
|
||||
|
||||
gch = tmp;
|
||||
}
|
||||
}
|
||||
@ -234,6 +255,7 @@ printf ("collecting garbage...\n");
|
||||
/* only unreachables are left in rtx->gc.all */
|
||||
gc_dump_refs (rtx, &rtx->gc.all);
|
||||
gc_free_unreachables (rtx, &rtx->gc.all);
|
||||
gc_dump_refs (rtx, &rtx->gc.all);
|
||||
HAWK_ASSERT (rtx->gc.all.gc_next == &rtx->gc.all);
|
||||
|
||||
gc_move_gchs (&rtx->gc.all, &reachable);
|
||||
@ -534,6 +556,7 @@ hawk_val_t* hawk_rtx_makenstrvalwithuchars (hawk_rtx_t* rtx, const hawk_uch_t* p
|
||||
v = hawk_rtx_makestrvalwithuchars(rtx, ptr, len);
|
||||
if (HAWK_UNLIKELY(!v)) return HAWK_NULL;
|
||||
|
||||
|
||||
if (x >= 0)
|
||||
{
|
||||
/* set the numeric string flag if a string
|
||||
|
Loading…
Reference in New Issue
Block a user