From 6d15697edce2217a2bbc82def26262d18dac6373 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Wed, 21 May 2025 14:25:45 -0400 Subject: Added Set infix operations, as well as Table.with_fallback() and fixed some bugs with update assignment. --- src/stdlib/tables.c | 94 +++++++++++++++++++++++++++++++++-------------------- src/stdlib/tables.h | 2 ++ 2 files changed, 61 insertions(+), 35 deletions(-) (limited to 'src/stdlib') diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c index 8e3afe45..762afb06 100644 --- a/src/stdlib/tables.c +++ b/src/stdlib/tables.c @@ -640,19 +640,15 @@ public Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type) // Return a table such that t[k]==a[k] for all k such that a.has(k), b.has(k), and a[k]==b[k] Table_t result = {}; const size_t offset = value_offset(type); - for (int64_t i = 0; i < Table$length(a); i++) { - void *key = GET_ENTRY(a, i); - void *a_value = key + offset; - void *b_value = Table$get(b, key, type); - if (b_value && generic_equal(a_value, b_value, type->TableInfo.value)) - Table$set(&result, key, a_value, type); - } - - if (a.fallback) { - result.fallback = new(Table_t); - *result.fallback = Table$overlap(*a.fallback, b, type); + for (Table_t *t = &a; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + void *a_value = key + offset; + void *b_value = Table$get(b, key, type); + if (b_value && generic_equal(a_value, b_value, type->TableInfo.value)) + Table$set(&result, key, a_value, type); + } } - return result; } @@ -662,22 +658,41 @@ public Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type) // return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and not b.has(k) Table_t result = {}; const size_t offset = value_offset(type); - for (int64_t i = 0; i < Table$length(a); i++) { - void *key = GET_ENTRY(a, i); - Table$set(&result, key, key + offset, type); + for (Table_t *t = &a; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + Table$set(&result, key, key + offset, type); + } } - for (int64_t i = 0; i < Table$length(b); i++) { - void *key = GET_ENTRY(b, i); - Table$set(&result, key, key + offset, type); + for (Table_t *t = &b; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + Table$set(&result, key, key + offset, type); + } } + return result; +} - if (a.fallback && b.fallback) { - result.fallback = new(Table_t); - *result.fallback = Table$with(*a.fallback, *b.fallback, type); - } else { - result.fallback = a.fallback ? a.fallback : b.fallback; +// Xor is "disjunctive union" or "symmetric difference" in formal terms +public Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type) +{ + // return a table with elements in `a` or `b`, but not both + Table_t result = {}; + const size_t offset = value_offset(type); + for (Table_t *t = &a; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + if (Table$get(b, key, type) == NULL) + Table$set(&result, key, key + offset, type); + } + } + for (Table_t *t = &b; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + if (Table$get(a, key, type) == NULL) + Table$set(&result, key, key + offset, type); + } } - return result; } @@ -687,20 +702,29 @@ public Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type) // Return a table such that t[k]==a[k] for all k such that not b.has(k) or b[k] != a[k] Table_t result = {}; const size_t offset = value_offset(type); - for (int64_t i = 0; i < Table$length(a); i++) { - void *key = GET_ENTRY(a, i); - void *a_value = key + offset; - void *b_value = Table$get(b, key, type); - if (!b_value || !generic_equal(a_value, b_value, type->TableInfo.value)) - Table$set(&result, key, a_value, type); + for (Table_t *t = &a; t; t = t->fallback) { + for (int64_t i = 0; i < Table$length(*t); i++) { + void *key = GET_ENTRY(*t, i); + void *a_value = key + offset; + void *b_value = Table$get(b, key, type); + if (!b_value || !generic_equal(a_value, b_value, type->TableInfo.value)) + Table$set(&result, key, a_value, type); + } } + return result; +} - if (a.fallback) { - result.fallback = new(Table_t); - *result.fallback = Table$without(*a.fallback, b, type); +public Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback) +{ + if (fallback.entries.length <= 0) { + t.fallback = NULL; + return t; + } else { + TABLE_INCREF(fallback); + t.fallback = GC_MALLOC(sizeof(Table_t)); + *t.fallback = fallback; + return t; } - - return result; } PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type) diff --git a/src/stdlib/tables.h b/src/stdlib/tables.h index ad6127c7..f80c16c3 100644 --- a/src/stdlib/tables.h +++ b/src/stdlib/tables.h @@ -59,6 +59,8 @@ void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type); Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type); Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type); Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type); +Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type); +Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback); PUREFUNC bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type); PUREFUNC bool Table$is_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type); -- cgit v1.2.3