pub const CRDT_CORE: &str = "/* Convergent collections \u{2014} the data crate\'s observed-remove set, add-wins (`ORSet<T, AddWins>`) and\n * remove-wins (`ORSet<T, RemoveWins>`), and its observed-remove map of last-writer values\n * (`ORMap<K, LatestWrite<V>>`), ported step for step: what `SharedSet of T`, `SharedSet (RemoveWins) of T`\n * and `SharedMap from K to V` hold on the tree-walker and the VM, their state merge (`Merge \u{2026} into \u{2026}`)\n * included.\n *\n * ONE core for every C-family tier and RISC-V. A value is one 8-byte cell of the collection\'s single element\n * kind \u{2014} an Int as itself, a Bool as 0/1, a Text as its `char *` \u{2014} ordered as the interpreter\'s `CrdtScalar`\n * is: variants Int < Text < Bool, numbers by value, Text by its bytes, false before true. Entries are kept\n * sorted by element (a map\'s by key), the order both interpreters show and iterate them in. Every dot a\n * context holds arrives with a whole state, never out of order, so a context is exactly its vector clock.\n *\n * Before this text a tier defines LOGOS_FN, LOGOS_VAR and logos_alloc(n) / logos_release(p), as for\n * sched_core.c, and includes <string.h> and <stdint.h>.\n */\n\n#define LOGOS_CRDT_INT 0\n#define LOGOS_CRDT_BOOL 2\n#define LOGOS_CRDT_TEXT 3\n\n/* The variant rank of an element kind in `CrdtScalar`\'s order. */\nLOGOS_FN int logos_crdt_rank(int kind) {\n return kind == LOGOS_CRDT_TEXT ? 1 : kind == LOGOS_CRDT_BOOL ? 2 : 0;\n}\n\n/* -1, 0 or 1 as `a` orders before, with, or after `b`, both of `kind`. */\nLOGOS_FN int logos_crdt_cmp(long long a, long long b, int kind) {\n if (kind == LOGOS_CRDT_TEXT) {\n int c = strcmp((const char *)(intptr_t)a, (const char *)(intptr_t)b);\n return (c > 0) - (c < 0);\n }\n return (a > b) - (a < b);\n}\n\n/* The last replica id handed out. Ids are 1, 2, 3, \u{2026} in creation order, as the interpreter\'s are; only their\n distinctness reaches what a program can observe. */\nLOGOS_VAR long long logos_crdt_replica_seq = 0;\n\nLOGOS_FN long long logos_crdt_next_replica(void) {\n#if defined(__CUDA_ARCH__)\n return ++logos_crdt_replica_seq;\n#else\n return __atomic_add_fetch(&logos_crdt_replica_seq, 1, __ATOMIC_RELAXED);\n#endif\n}\n\n/* ---- dots and vector clocks ---- */\n\ntypedef struct { long long replica, counter; } logos_dot;\ntypedef struct { long long n, cap; logos_dot *at; } logos_dots;\ntypedef struct { long long n, cap; long long *replica, *counter; } logos_vclock;\n\nLOGOS_FN int logos_dots_has(const logos_dots *s, logos_dot d) {\n for (long long i = 0; i < s->n; i++) {\n if (s->at[i].replica == d.replica && s->at[i].counter == d.counter) return 1;\n }\n return 0;\n}\n\nLOGOS_FN void logos_dots_put(logos_dots *s, logos_dot d) {\n if (logos_dots_has(s, d)) return;\n if (s->n == s->cap) {\n long long cap = s->cap ? s->cap * 2 : 4;\n logos_dot *at = (logos_dot *)logos_alloc((size_t)cap * sizeof(logos_dot));\n if (s->n) memcpy(at, s->at, (size_t)s->n * sizeof(logos_dot));\n if (s->at) logos_release(s->at);\n s->at = at;\n s->cap = cap;\n }\n s->at[s->n++] = d;\n}\n\nLOGOS_FN logos_dots logos_dots_clone(const logos_dots *s) {\n logos_dots c = {0, 0, 0};\n for (long long i = 0; i < s->n; i++) logos_dots_put(&c, s->at[i]);\n return c;\n}\n\n/* A collection owns the cells it keeps: a Text is copied when it is stored and freed when it is dropped, so\n a caller\'s cell is only ever borrowed. Int and Bool cells are values. */\nLOGOS_FN long long logos_crdt_own(long long cell, int kind) {\n if (kind != LOGOS_CRDT_TEXT || !cell) return cell;\n const char *t = (const char *)(intptr_t)cell;\n size_t n = strlen(t) + 1;\n char *c = (char *)logos_alloc(n);\n memcpy(c, t, n);\n return (long long)(intptr_t)c;\n}\n\nLOGOS_FN void logos_crdt_drop(long long cell, int kind) {\n if (kind == LOGOS_CRDT_TEXT && cell) logos_release((void *)(intptr_t)cell);\n}\n\nLOGOS_FN void logos_dots_free(logos_dots *s) {\n if (s->at) logos_release(s->at);\n s->n = s->cap = 0;\n s->at = 0;\n}\n\nLOGOS_FN long long logos_vclock_get(const logos_vclock *c, long long replica) {\n for (long long i = 0; i < c->n; i++) {\n if (c->replica[i] == replica) return c->counter[i];\n }\n return 0;\n}\n\nLOGOS_FN void logos_vclock_set(logos_vclock *c, long long replica, long long counter) {\n for (long long i = 0; i < c->n; i++) {\n if (c->replica[i] == replica) { c->counter[i] = counter; return; }\n }\n if (c->n == c->cap) {\n long long cap = c->cap ? c->cap * 2 : 4;\n long long *r = (long long *)logos_alloc((size_t)cap * sizeof(long long));\n long long *k = (long long *)logos_alloc((size_t)cap * sizeof(long long));\n if (c->n) { memcpy(r, c->replica, (size_t)c->n * sizeof(long long)); memcpy(k, c->counter, (size_t)c->n * sizeof(long long)); }\n if (c->replica) { logos_release(c->replica); logos_release(c->counter); }\n c->replica = r;\n c->counter = k;\n c->cap = cap;\n }\n c->replica[c->n] = replica;\n c->counter[c->n] = counter;\n c->n++;\n}\n\n/* `DotContext::next`: this replica\'s next event. */\nLOGOS_FN logos_dot logos_vclock_next(logos_vclock *c, long long replica) {\n logos_dot d = {replica, logos_vclock_get(c, replica) + 1};\n logos_vclock_set(c, replica, d.counter);\n return d;\n}\n\n/* `DotContext::has_seen`. */\nLOGOS_FN int logos_vclock_seen(const logos_vclock *c, logos_dot d) {\n return logos_vclock_get(c, d.replica) >= d.counter;\n}\n\n/* `DotContext::observed`: every event the context has seen, the Lamport time a map\'s write is stamped with. */\nLOGOS_FN long long logos_vclock_total(const logos_vclock *c) {\n long long t = 0;\n for (long long i = 0; i < c->n; i++) t += c->counter[i];\n return t;\n}\n\n/* `DotContext::merge`: the per-replica maximum. */\nLOGOS_FN void logos_vclock_join(logos_vclock *c, const logos_vclock *o) {\n for (long long i = 0; i < o->n; i++) {\n if (o->counter[i] > logos_vclock_get(c, o->replica[i])) logos_vclock_set(c, o->replica[i], o->counter[i]);\n }\n}\n\nLOGOS_FN logos_vclock logos_vclock_clone(const logos_vclock *c) {\n logos_vclock k = {0, 0, 0, 0};\n for (long long i = 0; i < c->n; i++) logos_vclock_set(&k, c->replica[i], c->counter[i]);\n return k;\n}\n\nLOGOS_FN void logos_vclock_free(logos_vclock *c) {\n if (c->replica) { logos_release(c->replica); logos_release(c->counter); }\n c->replica = c->counter = 0;\n c->n = c->cap = 0;\n}\n\n/* ---- the observed-remove set ---- */\n\ntypedef struct { long long elem; logos_dots dots; } logos_crdt_entry;\n\ntypedef struct {\n long long n, cap;\n logos_crdt_entry *e; /* sorted by element; every entry holds at least one dot */\n logos_vclock ctx;\n long long replica;\n int kind;\n int remove_wins;\n} logos_crdt_set;\n\n/* The index of `elem` in the sorted entries, or of where it would go, with *found set. */\nLOGOS_FN long long logos_crdt_set_find(const logos_crdt_set *s, long long elem, int *found) {\n long long lo = 0, hi = s->n;\n while (lo < hi) {\n long long mid = lo + (hi - lo) / 2;\n int c = logos_crdt_cmp(s->e[mid].elem, elem, s->kind);\n if (c == 0) { *found = 1; return mid; }\n if (c < 0) lo = mid + 1; else hi = mid;\n }\n *found = 0;\n return lo;\n}\n\nLOGOS_FN void logos_crdt_set_reserve(logos_crdt_set *s, long long need) {\n if (need <= s->cap) return;\n long long cap = s->cap ? s->cap : 4;\n while (cap < need) cap *= 2;\n logos_crdt_entry *e = (logos_crdt_entry *)logos_alloc((size_t)cap * sizeof(logos_crdt_entry));\n if (s->n) memcpy(e, s->e, (size_t)s->n * sizeof(logos_crdt_entry));\n if (s->e) logos_release(s->e);\n s->e = e;\n s->cap = cap;\n}\n\n/* A new, empty set of `kind` elements with a replica of its own. */\nLOGOS_FN logos_crdt_set *logos_crdt_set_new(int kind, int remove_wins) {\n logos_crdt_set *s = (logos_crdt_set *)logos_alloc(sizeof(logos_crdt_set));\n s->kind = kind;\n s->remove_wins = remove_wins;\n s->replica = logos_crdt_next_replica();\n return s;\n}\n\n/* `Add v to s`: a new dot for the element. */\nLOGOS_FN void logos_crdt_set_add(logos_crdt_set *s, long long elem) {\n logos_dot d = logos_vclock_next(&s->ctx, s->replica);\n int found;\n long long i = logos_crdt_set_find(s, elem, &found);\n if (!found) {\n logos_crdt_set_reserve(s, s->n + 1);\n memmove(&s->e[i + 1], &s->e[i], (size_t)(s->n - i) * sizeof(logos_crdt_entry));\n s->e[i].elem = logos_crdt_own(elem, s->kind);\n s->e[i].dots.n = s->e[i].dots.cap = 0;\n s->e[i].dots.at = 0;\n s->n++;\n }\n logos_dots_put(&s->e[i].dots, d);\n}\n\n/* `Remove v from s`: the element\'s dots go; the context keeps having seen them. */\nLOGOS_FN void logos_crdt_set_remove(logos_crdt_set *s, long long elem) {\n int found;\n long long i = logos_crdt_set_find(s, elem, &found);\n if (!found) return;\n logos_dots_free(&s->e[i].dots);\n logos_crdt_drop(s->e[i].elem, s->kind);\n memmove(&s->e[i], &s->e[i + 1], (size_t)(s->n - i - 1) * sizeof(logos_crdt_entry));\n s->n--;\n}\n\nLOGOS_FN int logos_crdt_set_contains(const logos_crdt_set *s, long long elem) {\n int found;\n logos_crdt_set_find(s, elem, &found);\n return found;\n}\n\nLOGOS_FN long long logos_crdt_set_len(const logos_crdt_set *s) { return s->n; }\n\n/* The `i`-th element (0-based) in the set\'s order. */\nLOGOS_FN long long logos_crdt_set_nth(const logos_crdt_set *s, long long i) { return s->e[i].elem; }\n\n/* `copy of s`: the same state, the same replica. */\nLOGOS_FN logos_crdt_set *logos_crdt_set_clone(const logos_crdt_set *s) {\n logos_crdt_set *c = (logos_crdt_set *)logos_alloc(sizeof(logos_crdt_set));\n *c = *s;\n c->e = 0;\n c->n = c->cap = 0;\n logos_crdt_set_reserve(c, s->n);\n for (long long i = 0; i < s->n; i++) {\n c->e[i].elem = logos_crdt_own(s->e[i].elem, s->kind);\n c->e[i].dots = logos_dots_clone(&s->e[i].dots);\n }\n c->n = s->n;\n c->ctx = logos_vclock_clone(&s->ctx);\n return c;\n}\n\n/* `ORSet::merge`: for every element either side holds, the dots neither side observed removed survive, and\n the bias decides an element one side holds and the other removed. Both contexts are read as they stood\n before the merge; the target\'s then joins the source\'s. */\nLOGOS_FN void logos_crdt_set_merge(logos_crdt_set *s, const logos_crdt_set *o) {\n static const logos_dots none = {0, 0, 0};\n long long cap = s->n + o->n, n = 0, i = 0, j = 0;\n logos_crdt_entry *out = cap ? (logos_crdt_entry *)logos_alloc((size_t)cap * sizeof(logos_crdt_entry)) : 0;\n while (i < s->n || j < o->n) {\n int c = i == s->n ? 1 : j == o->n ? -1 : logos_crdt_cmp(s->e[i].elem, o->e[j].elem, s->kind);\n long long elem = c <= 0 ? s->e[i].elem : o->e[j].elem;\n const logos_dots *mine = c <= 0 ? &s->e[i].dots : &none;\n const logos_dots *theirs = c >= 0 ? &o->e[j].dots : &none;\n int my_removed = 0, their_removed = 0;\n if (mine->n == 0) {\n for (long long k = 0; k < theirs->n; k++) if (logos_vclock_seen(&s->ctx, theirs->at[k])) { my_removed = 1; break; }\n }\n if (theirs->n == 0) {\n for (long long k = 0; k < mine->n; k++) if (logos_vclock_seen(&o->ctx, mine->at[k])) { their_removed = 1; break; }\n }\n logos_dots combined = {0, 0, 0};\n for (long long k = 0; k < mine->n; k++) {\n if (!logos_vclock_seen(&o->ctx, mine->at[k]) || logos_dots_has(theirs, mine->at[k])) logos_dots_put(&combined, mine->at[k]);\n }\n for (long long k = 0; k < theirs->n; k++) {\n if (!logos_vclock_seen(&s->ctx, theirs->at[k]) || logos_dots_has(mine, theirs->at[k])) logos_dots_put(&combined, theirs->at[k]);\n }\n int present = mine->n > 0 || theirs->n > 0;\n int keep = s->remove_wins ? (!my_removed && !their_removed && present) : present;\n if (keep && combined.n > 0) {\n out[n].elem = c <= 0 ? elem : logos_crdt_own(elem, s->kind);\n out[n].dots = combined;\n n++;\n } else {\n logos_dots_free(&combined);\n if (c <= 0) logos_crdt_drop(elem, s->kind);\n }\n if (c <= 0) { logos_dots_free(&s->e[i].dots); i++; }\n if (c >= 0) j++;\n }\n if (s->e) logos_release(s->e);\n s->e = out;\n s->n = n;\n s->cap = cap;\n logos_vclock_join(&s->ctx, &o->ctx);\n}\n\n/* ---- the observed-remove map of last-writer values ---- */\n\ntypedef struct { long long key; logos_dots dots; } logos_crdt_key;\n/* A key\'s `LatestWrite`: its stamp and value. A placeholder (`LatestWrite::default()`, stamp 0, `Int(0)`) is\n what a key a merge meets before any write to it holds. */\ntypedef struct { long long key, stamp, value; int placeholder; } logos_crdt_value;\n\ntypedef struct {\n long long nk, capk;\n logos_crdt_key *k; /* sorted by key; every key holds at least one dot */\n long long nv, capv;\n logos_crdt_value *v; /* sorted by key; a value outlives its key\'s removal, as `ORMap::values` does */\n logos_vclock ctx;\n long long replica;\n int key_kind, value_kind;\n} logos_crdt_map;\n\nLOGOS_FN long long logos_crdt_map_find_key(const logos_crdt_map *m, long long key, int *found) {\n long long lo = 0, hi = m->nk;\n while (lo < hi) {\n long long mid = lo + (hi - lo) / 2;\n int c = logos_crdt_cmp(m->k[mid].key, key, m->key_kind);\n if (c == 0) { *found = 1; return mid; }\n if (c < 0) lo = mid + 1; else hi = mid;\n }\n *found = 0;\n return lo;\n}\n\nLOGOS_FN long long logos_crdt_map_find_value(const logos_crdt_map *m, long long key, int *found) {\n long long lo = 0, hi = m->nv;\n while (lo < hi) {\n long long mid = lo + (hi - lo) / 2;\n int c = logos_crdt_cmp(m->v[mid].key, key, m->key_kind);\n if (c == 0) { *found = 1; return mid; }\n if (c < 0) lo = mid + 1; else hi = mid;\n }\n *found = 0;\n return lo;\n}\n\n/* The dots of `key`, the key added (with no dots) when absent. */\nLOGOS_FN logos_dots *logos_crdt_map_key_entry(logos_crdt_map *m, long long key) {\n int found;\n long long i = logos_crdt_map_find_key(m, key, &found);\n if (!found) {\n if (m->nk == m->capk) {\n long long cap = m->capk ? m->capk * 2 : 4;\n logos_crdt_key *k = (logos_crdt_key *)logos_alloc((size_t)cap * sizeof(logos_crdt_key));\n if (m->nk) memcpy(k, m->k, (size_t)m->nk * sizeof(logos_crdt_key));\n if (m->k) logos_release(m->k);\n m->k = k;\n m->capk = cap;\n }\n memmove(&m->k[i + 1], &m->k[i], (size_t)(m->nk - i) * sizeof(logos_crdt_key));\n m->k[i].key = logos_crdt_own(key, m->key_kind);\n m->k[i].dots.n = m->k[i].dots.cap = 0;\n m->k[i].dots.at = 0;\n m->nk++;\n }\n return &m->k[i].dots;\n}\n\n/* The value of `key`, a placeholder added when absent. */\nLOGOS_FN logos_crdt_value *logos_crdt_map_value_entry(logos_crdt_map *m, long long key) {\n int found;\n long long i = logos_crdt_map_find_value(m, key, &found);\n if (!found) {\n if (m->nv == m->capv) {\n long long cap = m->capv ? m->capv * 2 : 4;\n logos_crdt_value *v = (logos_crdt_value *)logos_alloc((size_t)cap * sizeof(logos_crdt_value));\n if (m->nv) memcpy(v, m->v, (size_t)m->nv * sizeof(logos_crdt_value));\n if (m->v) logos_release(m->v);\n m->v = v;\n m->capv = cap;\n }\n memmove(&m->v[i + 1], &m->v[i], (size_t)(m->nv - i) * sizeof(logos_crdt_value));\n m->v[i].key = logos_crdt_own(key, m->key_kind);\n m->v[i].stamp = 0;\n m->v[i].value = 0;\n m->v[i].placeholder = 1;\n m->nv++;\n }\n return &m->v[i];\n}\n\n/* A new, empty map with a replica of its own. */\nLOGOS_FN logos_crdt_map *logos_crdt_map_new(int key_kind, int value_kind) {\n logos_crdt_map *m = (logos_crdt_map *)logos_alloc(sizeof(logos_crdt_map));\n m->key_kind = key_kind;\n m->value_kind = value_kind;\n m->replica = logos_crdt_next_replica();\n return m;\n}\n\n/* `Set m[key] to value`: a new dot for the key, then the value stamped with the context\'s Lamport time. */\nLOGOS_FN void logos_crdt_map_put(logos_crdt_map *m, long long key, long long value) {\n logos_dot d = logos_vclock_next(&m->ctx, m->replica);\n logos_dots_put(logos_crdt_map_key_entry(m, key), d);\n logos_crdt_value *v = logos_crdt_map_value_entry(m, key);\n if (!v->placeholder) logos_crdt_drop(v->value, m->value_kind);\n v->stamp = logos_vclock_total(&m->ctx);\n v->value = logos_crdt_own(value, m->value_kind);\n v->placeholder = 0;\n}\n\nLOGOS_FN int logos_crdt_map_contains(const logos_crdt_map *m, long long key) {\n int found;\n logos_crdt_map_find_key(m, key, &found);\n return found;\n}\n\n/* The value under a present `key`; *present is 0 when the key is absent. */\nLOGOS_FN long long logos_crdt_map_get(const logos_crdt_map *m, long long key, int *present) {\n int found;\n logos_crdt_map_find_key(m, key, &found);\n if (!found) { *present = 0; return 0; }\n long long i = logos_crdt_map_find_value(m, key, &found);\n *present = 1;\n return m->v[i].value;\n}\n\n/* `Remove key from m`: the key\'s dots go; its value stays, as `ORMap::remove` leaves it. */\nLOGOS_FN void logos_crdt_map_remove(logos_crdt_map *m, long long key) {\n int found;\n long long i = logos_crdt_map_find_key(m, key, &found);\n if (!found) return;\n logos_dots_free(&m->k[i].dots);\n logos_crdt_drop(m->k[i].key, m->key_kind);\n memmove(&m->k[i], &m->k[i + 1], (size_t)(m->nk - i - 1) * sizeof(logos_crdt_key));\n m->nk--;\n}\n\nLOGOS_FN long long logos_crdt_map_len(const logos_crdt_map *m) { return m->nk; }\n\n/* The `i`-th key (0-based) in key order, and its value. */\nLOGOS_FN long long logos_crdt_map_key_nth(const logos_crdt_map *m, long long i) { return m->k[i].key; }\n\nLOGOS_FN long long logos_crdt_map_value_nth(const logos_crdt_map *m, long long i) {\n int present;\n return logos_crdt_map_get(m, m->k[i].key, &present);\n}\n\n/* `copy of m`: the same state, the same replica. */\nLOGOS_FN logos_crdt_map *logos_crdt_map_clone(const logos_crdt_map *m) {\n logos_crdt_map *c = (logos_crdt_map *)logos_alloc(sizeof(logos_crdt_map));\n *c = *m;\n c->k = 0;\n c->capk = c->nk = 0;\n c->v = 0;\n c->capv = c->nv = 0;\n for (long long i = 0; i < m->nk; i++) {\n logos_dots *d = logos_crdt_map_key_entry(c, m->k[i].key);\n *d = logos_dots_clone(&m->k[i].dots);\n }\n for (long long i = 0; i < m->nv; i++) {\n logos_crdt_value *v = logos_crdt_map_value_entry(c, m->v[i].key);\n v->stamp = m->v[i].stamp;\n v->placeholder = m->v[i].placeholder;\n v->value = m->v[i].placeholder ? 0 : logos_crdt_own(m->v[i].value, m->value_kind);\n }\n c->ctx = logos_vclock_clone(&m->ctx);\n return c;\n}\n\n/* `LatestWrite`\'s order on (stamp, value): a placeholder\'s value is `Int(0)`. */\nLOGOS_FN int logos_crdt_write_cmp(const logos_crdt_value *a, const logos_crdt_value *b, int kind) {\n if (a->stamp != b->stamp) return a->stamp < b->stamp ? -1 : 1;\n int ka = a->placeholder ? LOGOS_CRDT_INT : kind, kb = b->placeholder ? LOGOS_CRDT_INT : kind;\n if (ka != kb) return logos_crdt_rank(ka) < logos_crdt_rank(kb) ? -1 : 1;\n return logos_crdt_cmp(a->placeholder ? 0 : a->value, b->placeholder ? 0 : b->value, ka);\n}\n\n/* `ORMap::merge`: every value takes the later write; a key keeps the dots the source added that the target had\n not seen, and loses the dots the source observed and no longer holds. Both contexts are read as they stood\n before the merge; the target\'s then joins the source\'s. */\nLOGOS_FN void logos_crdt_map_merge(logos_crdt_map *m, const logos_crdt_map *o) {\n for (long long i = 0; i < o->nv; i++) {\n logos_crdt_value *mine = logos_crdt_map_value_entry(m, o->v[i].key);\n if (logos_crdt_write_cmp(&o->v[i], mine, m->value_kind) > 0) {\n if (!mine->placeholder) logos_crdt_drop(mine->value, m->value_kind);\n mine->stamp = o->v[i].stamp;\n mine->placeholder = o->v[i].placeholder;\n mine->value = o->v[i].placeholder ? 0 : logos_crdt_own(o->v[i].value, m->value_kind);\n }\n }\n for (long long i = 0; i < o->nk; i++) {\n logos_dots *mine = logos_crdt_map_key_entry(m, o->k[i].key);\n for (long long k = 0; k < o->k[i].dots.n; k++) {\n if (!logos_vclock_seen(&m->ctx, o->k[i].dots.at[k])) logos_dots_put(mine, o->k[i].dots.at[k]);\n }\n }\n long long n = 0;\n for (long long i = 0; i < m->nk; i++) {\n int found;\n long long j = logos_crdt_map_find_key(o, m->k[i].key, &found);\n const logos_dots *theirs = found ? &o->k[j].dots : 0;\n logos_dots kept = {0, 0, 0};\n for (long long k = 0; k < m->k[i].dots.n; k++) {\n logos_dot d = m->k[i].dots.at[k];\n if (!logos_vclock_seen(&o->ctx, d) || (theirs && logos_dots_has(theirs, d))) logos_dots_put(&kept, d);\n }\n logos_dots_free(&m->k[i].dots);\n if (kept.n > 0) {\n m->k[n].key = m->k[i].key;\n m->k[n].dots = kept;\n n++;\n } else {\n logos_crdt_drop(m->k[i].key, m->key_kind);\n }\n }\n m->nk = n;\n logos_vclock_join(&m->ctx, &o->ctx);\n}\n\n/* Free a set: its entries\' elements and dots, the entry array, the context, the set. */\nLOGOS_FN void logos_crdt_set_free(logos_crdt_set *s) {\n if (!s) return;\n for (long long i = 0; i < s->n; i++) {\n logos_dots_free(&s->e[i].dots);\n logos_crdt_drop(s->e[i].elem, s->kind);\n }\n if (s->e) logos_release(s->e);\n logos_vclock_free(&s->ctx);\n logos_release(s);\n}\n\n/* Free a map: its keys and their dots, its values and their keys, both arrays, the context, the map. */\nLOGOS_FN void logos_crdt_map_free(logos_crdt_map *m) {\n if (!m) return;\n for (long long i = 0; i < m->nk; i++) {\n logos_dots_free(&m->k[i].dots);\n logos_crdt_drop(m->k[i].key, m->key_kind);\n }\n for (long long i = 0; i < m->nv; i++) {\n logos_crdt_drop(m->v[i].key, m->key_kind);\n if (!m->v[i].placeholder) logos_crdt_drop(m->v[i].value, m->value_kind);\n }\n if (m->k) logos_release(m->k);\n if (m->v) logos_release(m->v);\n logos_vclock_free(&m->ctx);\n logos_release(m);\n}\n";Expand description
The C family’s convergent collections: the data crate’s observed-remove set (add-wins and remove-wins) and its observed-remove map of last-writer values, ported once, in C every tier compiles — both C generators, the stepped tier and RISC-V. A tier defines its qualifiers and its allocator before this text (see the file’s header).