diff --git a/TODO.md b/TODO.md index fea80b8..190cdbd 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,7 @@ Consider whether a stack or a queue makes most sense for the freelist. +Consider a naming convention to indicate grab'd vs ungrab'd results. + Needed by prospect: @@ -87,8 +89,6 @@ Needed by prospect: } // patch - // composePatch -> subtractUnit; - // composePatch -> unionUnit; // computePatch -> subtractUnit; // I guess? // stripInterests -> relabel; // stripPatch -> stripInterests; @@ -96,6 +96,8 @@ Needed by prospect: applyPatch -> unionPIDs; biasedIntersection -> intersectUnit; biasedIntersection -> step; + composePatch -> subtractUnit; + composePatch -> unionUnit; computeAggregatePatch -> subtractCustom; labelInterests -> relabel; limitPatch -> intersectAsymmetric; @@ -105,6 +107,7 @@ Needed by prospect: updateInterests -> unionUnit; dropInterests -> project; labelPatch -> labelInterests; + patchSeq -> composePatch; // mux computeAffectedPIDs -> matchMatcher; @@ -121,11 +124,12 @@ Needed by prospect: muxUpdateStream -> patchUnion; // core - observeAtMeta -> union; + observeAtMeta -> unionUnit; // user code userCode -> project; userCode -> observeAtMeta; + userCode -> patchSeq; // semantics semantics -> muxUpdateStream; diff --git a/main.c b/main.c index ffec8d8..2a6f5f5 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,13 @@ #include "critbit.h" #include "route.h" +#include +#define LITERAL4(s) ({ \ + int ___v = 0; \ + memcpy(&___v, s, 4); \ + ntohl(___v); \ + }) + static void atom_incref(void *atom_context, tt_arena_t *a, tt_atom_t atom) { /* printf("incref %u\n", atom); */ } @@ -130,43 +137,43 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, 'B', TT_EOS})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); } tt_arena_flush(&a); - tt_dump_arena_dot("after1", TT_NO_PTR, &a); + tt_dump_arena_dot_styled("after1", TT_NO_PTR, &a, 1); printf("\n============================================================ 2\n"); { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_EOS})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); @@ -177,18 +184,18 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); @@ -199,18 +206,18 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, b_set /* !!! */, {TT_BOS, 'A', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); @@ -221,18 +228,18 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', 'B', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_EOS})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); @@ -243,18 +250,18 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', 'B', TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_WILD, TT_EOS})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); @@ -265,39 +272,121 @@ int main(int argc, char *argv[]) { tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_WILD, TT_EOS})); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot("A", A, &a); + tt_dump_arena_dot_styled("A", A, &a, 1); tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, 'B', TT_EOS})); printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); - tt_dump_arena_dot("B", B, &a); - tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_node_ptr_t C = tt_trie_union_map(&a, A, B); tt_arena_flush(&a); - tt_dump_arena_dot("Cpredrop", C, &a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot("Cpostdrop", C, &a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); putchar('\n'); tt_dump_routingtable(&a, C, 0); - tt_node_ptr_t D = tt_trie_union(&a, C, C); + tt_node_ptr_t D = tt_trie_union_map(&a, C, C); tt_drop(&a, C); tt_arena_flush(&a); - tt_dump_arena_dot("D", D, &a); + tt_dump_arena_dot_styled("D", D, &a, 1); tt_dump_routingtable(&a, D, 0); tt_node_ptr_t E = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD})); - tt_node_ptr_t F = tt_trie_union(&a, D, E); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("E", E, &a, 1); + tt_node_ptr_t F = tt_trie_union_map(&a, D, E); tt_drop(&a, D); tt_drop(&a, E); tt_arena_flush(&a); - tt_dump_arena_dot("F", F, &a); + tt_dump_arena_dot_styled("F", F, &a, 1); tt_dump_routingtable(&a, F, 0); + + tt_node_ptr_t G = tt_grab(&a, tt_trie_relabel_const(&a, F, a_set)); tt_drop(&a, F); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("G", G, &a, 1); + tt_dump_routingtable(&a, G, 0); + tt_drop(&a, G); + } + + printf("\n============================================================ 8\n"); + { + tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, TT_EMPTY_DICT, {TT_BOS, 'A', TT_WILD, TT_EOS})); + printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("A", A, &a, 1); + tt_dump_routingtable(&a, A, 0); + tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, TT_EMPTY_DICT, {TT_BOS, TT_WILD, 'B', TT_EOS})); + printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_dump_routingtable(&a, B, 0); + tt_node_ptr_t C = tt_trie_subtract_set(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); + tt_drop(&a, A); + tt_drop(&a, B); + printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); + putchar('\n'); + tt_dump_routingtable(&a, C, 0); + tt_drop(&a, C); + } + + printf("\n============================================================ 9\n"); + { + tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, TT_EMPTY_DICT, {TT_WILD})); + printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("A", A, &a, 1); + tt_dump_routingtable(&a, A, 0); + tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, TT_EMPTY_DICT, {TT_BOS, 'A', 'B', TT_EOS})); + printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); + tt_dump_arena_dot_styled("B", B, &a, 1); + tt_dump_routingtable(&a, B, 0); + tt_node_ptr_t C = tt_trie_subtract_set(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("Cpredrop", C, &a, 1); + tt_drop(&a, A); + tt_drop(&a, B); + printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("Cpostdrop", C, &a, 1); + tt_replace(&a, &C, tt_trie_relabel_const(&a, C, a_set)); + printf("\nC node post relabel: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("Cpostrelabel", C, &a, 1); + putchar('\n'); + tt_dump_routingtable(&a, C, 0); + tt_drop(&a, C); + } + + printf("\n============================================================ A\n"); + { + tt_node_ptr_t d = TT_EMPTY_DICT; + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("appl"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("caar"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("cadr"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("cdar"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("cddr"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("cons"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("goog"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("lisp"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("snoc"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("spcx"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("twtr"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("unit"), TT_EMPTY)); + tt_replace(&a, &d, tt_dict_set(&a, d, LITERAL4("void"), TT_EMPTY)); + printf("\nd node: %u/%u\n", tt_ptr_idx(d), tt_ptr_tag(d)); + tt_arena_flush(&a); + tt_dump_arena_dot_styled("d", d, &a, 1); + tt_drop(&a, d); } tt_arena_flush(&a); - tt_dump_arena_dot("afterAll", TT_NO_PTR, &a); /* expect a_set and b_set here */ + tt_dump_arena_dot_styled("afterAll", TT_NO_PTR, &a, 1); /* expect a_set and b_set here */ tt_arena_done(&a); return EXIT_SUCCESS; diff --git a/route.c b/route.c index c804476..3ed2bde 100644 --- a/route.c +++ b/route.c @@ -193,7 +193,7 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a, tt_node_ptr_t w2 = TT_BRANCH_WILDCARD(a,r2); tt_node_ptr_t dict1 = TT_BRANCH_OTHERS(a,r1); tt_node_ptr_t dict2 = TT_BRANCH_OTHERS(a,r2); - tt_node_ptr_t result_wild = TT_NO_PTR; /* grab'd */ + tt_node_ptr_t result_wild = TT_EMPTY; /* grab'd */ tt_node_ptr_t result_others = TT_EMPTY_DICT; /* grab'd */ tt_node_ptr_t result = TT_NO_PTR; /* grab'd */ int ok = 1; @@ -240,13 +240,17 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a, (TT_EMPTY_P(w2) && (tt_dict_size(a, dict1) >= tt_dict_size(a, dict2)))) { /* Either a wildcard on the left, or no wildcard at all but the left is larger */ - result_wild = tt_grab(a, w1); - result_others = left_base_keep ? tt_grab(a, dict1) : TT_EMPTY_DICT; + if (left_base_keep) { + result_wild = tt_grab(a, w1); + result_others = tt_grab(a, dict1); + } ok = ok && tt_dict_foreach(a, dict2, NULL, examine_key); } else { /* Either a wildcard on the right, or no wildcard at all but the right is larger */ - result_wild = tt_grab(a, w2); - result_others = right_base_keep ? tt_grab(a, dict2) : TT_EMPTY_DICT; + if (right_base_keep) { + result_wild = tt_grab(a, w2); + result_others = tt_grab(a, dict2); + } ok = ok && tt_dict_foreach(a, dict1, NULL, examine_key); } @@ -298,8 +302,8 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a, return g(r1, r2); } -tt_node_ptr_t tt_trie_union(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2) { - tt_node_ptr_t f_union(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2) { +tt_node_ptr_t tt_trie_union_map(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2) { + tt_node_ptr_t f_union_map(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2) { tt_tag_t t1 = tt_ptr_tag(r1); tt_tag_t t2 = tt_ptr_tag(r2); if (t1 != TT_TAG_OK) { @@ -314,7 +318,69 @@ tt_node_ptr_t tt_trie_union(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2) { return tt_grab(a, result); } } - return tt_trie_combine(a, r1, r2, 1, 1, 1, 1, NULL, f_union); + return tt_trie_combine(a, r1, r2, 1, 1, 1, 1, NULL, f_union_map); +} + +tt_node_ptr_t tt_trie_subtract_set(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2) { + tt_node_ptr_t f_subtract_set(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2) { + return TT_EMPTY; + } + return tt_trie_combine(a, r1, r2, 0, 1, 1, 0, NULL, f_subtract_set); +} + +tt_node_ptr_t tt_trie_relabel(tt_arena_t *a, + tt_node_ptr_t r, + void *f_context, + tt_node_ptr_t (*f)(void *f_context, + tt_node_ptr_t oldlabel)) +{ + tt_node_ptr_t walk(tt_node_ptr_t r) { + if (TT_EMPTY_P(r)) { + return r; + } + + switch (tt_ptr_tag(r)) { + case TT_TAG_OK: + return tt_cons_ok(a, RET_IF_NO_PTR(f(f_context, TT_OK_DICT(a, r)))); + + case TT_TAG_TAIL: + return tt_cons_tail(a, RET_IF_NO_PTR(walk(TT_TAIL_TRIE(a, r)))); + + case TT_TAG_BRANCH: { + tt_node_ptr_t wild = tt_grab(a, RET_IF_NO_PTR(walk(TT_BRANCH_WILDCARD(a, r)))); + tt_node_ptr_t others = TT_EMPTY_DICT; /* grab'd */ + tt_node_ptr_t result = TT_NO_PTR; + int visit_edge(void *context, tt_atom_t key, tt_node_ptr_t trie) { + tt_node_ptr_t new_trie = tt_grab(a, walk(trie)); + tt_node_ptr_t new_others; + if (TT_NO_PTR_P(new_trie)) return 0; + new_others = tt_grab(a, rupdate_dict(a, wild, others, key, new_trie)); + tt_drop(a, new_trie); + if (TT_NO_PTR_P(new_others)) return 0; + tt_drop(a, others); + others = new_others; + return 1; + } + if (tt_dict_foreach(a, TT_BRANCH_OTHERS(a, r), NULL, visit_edge)) { + result = rbranch(a, wild, others); + } + tt_drop(a, wild); + tt_drop(a, others); + return result; + } + + default: + assert(0); + } + } + return walk(r); +} + +tt_node_ptr_t tt_trie_relabel_const(tt_arena_t *a, tt_node_ptr_t r, tt_node_ptr_t newlabel) { + tt_node_ptr_t relabel_to_const(void *context, tt_node_ptr_t oldlabel) { + return newlabel; + } + return tt_trie_relabel(a, r, NULL, relabel_to_const); } tt_node_ptr_t tt_begin_path(tt_arena_t *a, tt_node_ptr_t ok_dict) { diff --git a/route.h b/route.h index 09d8a7d..8a39fe9 100644 --- a/route.h +++ b/route.h @@ -26,7 +26,16 @@ extern tt_node_ptr_t tt_trie_combine(tt_arena_t *a, tt_node_ptr_t r2)); /* N.B. Returns a tt_grab'd result. */ -extern tt_node_ptr_t tt_trie_union(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2); +extern tt_node_ptr_t tt_trie_union_map(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2); +extern tt_node_ptr_t tt_trie_subtract_set(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2); + +/* ungrab'd */ +extern tt_node_ptr_t tt_trie_relabel(tt_arena_t *a, + tt_node_ptr_t r, + void *f_context, + tt_node_ptr_t (*f)(void *f_context, + tt_node_ptr_t oldlabel)); +extern tt_node_ptr_t tt_trie_relabel_const(tt_arena_t *a, tt_node_ptr_t r, tt_node_ptr_t newlabel); /* These return ungrab'd */ extern tt_node_ptr_t tt_begin_path(tt_arena_t *a, tt_node_ptr_t ok_dict); diff --git a/treetrie.c b/treetrie.c index b663f9d..25b1f03 100644 --- a/treetrie.c +++ b/treetrie.c @@ -8,6 +8,10 @@ #include "treetrie.h" #include "fasthash.h" +/* These two only included for tt_dump_arena_dot_styled. */ +#include "route.h" +#include + /* Customized special-purpose fasthash variation */ #define mix(h) ({ \ (h) ^= (h) >> 23; \ @@ -354,7 +358,11 @@ static void dump_dot_edge(tt_arena_t *a, tt_node_ptr_t p, int lr, char const *ed } } -void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t *a) { +void tt_dump_arena_dot_styled(char const *rootlabel, + tt_node_ptr_t rootptr, + tt_arena_t *a, + int style) +{ int i; printf("digraph Arena {\n"); @@ -392,7 +400,37 @@ void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t printf("label=\"branch"); break; case TT_TAG_LEAF: - printf("shape=underline,label=\"leaf a%d", (int) a->nodes[n].b); + switch (style) { + case 1: { + char buf[5]; + int v = (int) a->nodes[n].b; + if (v < -9 || v >= 32) { + int j; + v = htonl(v); + memcpy(buf, &v, 4); + for (j = 0; j < 4; j++) { + if (buf[j] < 32) { buf[j] = ' '; } + } + buf[4] = '\0'; + } else { + switch (v) { + case TT_WILD: buf[0] = '*'; buf[1] = '\0'; break; + case TT_BOS: buf[0] = buf[1] = '<'; buf[2] = '\0'; break; + case TT_EOS: buf[0] = buf[1] = '>'; buf[2] = '\0'; break; + case TT_BOC: buf[0] = buf[1] = '{'; buf[2] = '\0'; break; + case TT_EOC: buf[0] = buf[1] = '}'; buf[2] = '\0'; break; + default: + snprintf(buf, sizeof(buf), "%d", v); + buf[4] = '\0'; + } + } + printf("shape=underline,label=\"leaf '%s'", buf); + break; + } + case 0: + default: + printf("shape=underline,label=\"leaf a%d", (int) a->nodes[n].b); + } break; case TT_TAG_NODE: printf("label=\"node @%d", a->headers[n].inuse.index); @@ -436,6 +474,10 @@ void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t printf("}\n"); } +void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t *a) { + tt_dump_arena_dot_styled(rootlabel, rootptr, a, 0); +} + void tt_arena_flush1(tt_arena_t *a, tt_free_chain_t *c) { tt_node_idx_t i = a->free_chain.head; chain_splice(a, c, &a->free_chain); @@ -538,11 +580,14 @@ inline tt_node_ptr_t tt_grab(tt_arena_t *a, tt_node_ptr_t p) { inline void tt_drop(tt_arena_t *a, tt_node_ptr_t p) { tt_node_idx_t i = tt_ptr_idx(p); tt_tag_t t = tt_ptr_tag(p); - if (t != TT_TAG_INVALID && t != TT_TAG_SPECIAL - && a->headers[i].inuse.refcount < TT_REFCOUNT_LIMIT) { - /* printf("++++++++++++++++++++++++++++++ dropping %d\n", i); */ - if (--(a->headers[i].inuse.refcount) == 0) { - recycle_node(a, p); + if (t != TT_TAG_INVALID && t != TT_TAG_SPECIAL) { + uint32_t oldcount = a->headers[i].inuse.refcount; + if (oldcount < TT_REFCOUNT_LIMIT) { + /* printf("++++++++++++++++++++++++++++++ dropping %d\n", i); */ + assert(oldcount != 0); + if (--(a->headers[i].inuse.refcount) == 0) { + recycle_node(a, p); + } } } } diff --git a/treetrie.h b/treetrie.h index 67207ef..e8b064c 100644 --- a/treetrie.h +++ b/treetrie.h @@ -109,6 +109,10 @@ extern void tt_arena_done(tt_arena_t *a); extern void tt_dump_arena_summary(tt_arena_t *a); extern void tt_dump_arena(tt_arena_t *a, int show_free_chain); +extern void tt_dump_arena_dot_styled(char const *rootlabel, + tt_node_ptr_t rootptr, + tt_arena_t *a, + int style); extern void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t *a); extern void tt_arena_flush(tt_arena_t *a); @@ -178,6 +182,12 @@ static inline tt_node_ptr_t tt_right(tt_arena_t *a, tt_node_ptr_t p) { #define TT_DICT_ROOT(a,p) tt_left(a,p) #define TT_DICT_SIZE(a,p) ((uint32_t) tt_right(a,p)) +static inline void tt_replace(tt_arena_t *a, tt_node_ptr_t *target, tt_node_ptr_t newval) { + tt_grab(a, newval); + tt_drop(a, *target); + *target = newval; +} + #ifdef __cplusplus } #endif