From 6502a2e388b2ef33d819e4957f6a9c3736fd0bb2 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 22 Mar 2020 18:01:05 +0000 Subject: [PATCH] changed the behavior of for(x in y) loop - it now takes a snapshot of keys before running body --- hawk/lib/Hawk.hpp | 2 +- hawk/lib/HawkStd.hpp | 2 +- hawk/lib/hawk-prv.h | 7 +++ hawk/lib/hawk-rbt.h | 41 +++++++++++---- hawk/lib/hawk.h | 2 +- hawk/lib/parse.c | 24 ++++----- hawk/lib/rbt.c | 113 ++++++++++++++++++++++++++++------------ hawk/lib/run.c | 121 +++++++++++++++++++++++++++++++++++++++---- hawk/lib/tree-prv.h | 6 +-- hawk/lib/tree.c | 10 ++-- hawk/lib/val.c | 31 +++++++++-- 11 files changed, 279 insertions(+), 80 deletions(-) diff --git a/hawk/lib/Hawk.hpp b/hawk/lib/Hawk.hpp index 187c75c7..fa790b19 100644 --- a/hawk/lib/Hawk.hpp +++ b/hawk/lib/Hawk.hpp @@ -45,7 +45,7 @@ #endif /// \file -/// AWK Interpreter +/// Hawk Interpreter ///////////////////////////////// HAWK_BEGIN_NAMESPACE(HAWK) diff --git a/hawk/lib/HawkStd.hpp b/hawk/lib/HawkStd.hpp index 06d74a3a..c2553301 100644 --- a/hawk/lib/HawkStd.hpp +++ b/hawk/lib/HawkStd.hpp @@ -30,7 +30,7 @@ #include /// \file -/// Standard AWK Interpreter +/// Standard Hawk Interpreter ///////////////////////////////// HAWK_BEGIN_NAMESPACE(HAWK) diff --git a/hawk/lib/hawk-prv.h b/hawk/lib/hawk-prv.h index 0384985a..db44d68c 100644 --- a/hawk/lib/hawk-prv.h +++ b/hawk/lib/hawk-prv.h @@ -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) diff --git a/hawk/lib/hawk-rbt.h b/hawk/lib/hawk-rbt.h index 33384741..f73d03eb 100644 --- a/hawk/lib/hawk-rbt.h +++ b/hawk/lib/hawk-rbt.h @@ -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. diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index 952a7512..f26016cb 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -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, diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index efb52059..83827357 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -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)) diff --git a/hawk/lib/rbt.c b/hawk/lib/rbt.c index 639073d1..9eacbc0e 100644 --- a/hawk/lib/rbt.c +++ b/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,7 +945,10 @@ 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; - return x_cur; + #if defined(HAWK_ENABLE_RBT_ITR_PROTECTION) + itr->_prot_seqno++; + #endif + return x_cur; resume_1: if (!IS_NIL(rbt,x_cur->child[r])) @@ -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) { diff --git a/hawk/lib/run.c b/hawk/lib/run.c index 85fdc758..cffde516 100644 --- a/hawk/lib/run.c +++ b/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,15 +2487,17 @@ 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) diff --git a/hawk/lib/tree-prv.h b/hawk/lib/tree-prv.h index f42e72a1..d9a2f519 100644 --- a/hawk/lib/tree-prv.h +++ b/hawk/lib/tree-prv.h @@ -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; diff --git a/hawk/lib/tree.c b/hawk/lib/tree.c index 883c1a60..c1572d2c 100644 --- a/hawk/lib/tree.c +++ b/hawk/lib/tree.c @@ -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; } diff --git a/hawk/lib/val.c b/hawk/lib/val.c index f278a052..b010c9d8 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -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