aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-10 14:20:54 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-10 14:20:54 -0400
commit3b1d88ab93ddda16f1806ca3a10faae5e72ec511 (patch)
tree9982b43acc0c5cb129a871e0c150ea88d3003973
parentf78cd6357acf7bd8eae6687f2530201acd522329 (diff)
Bugfix for table literals with duplicated keys
-rw-r--r--builtins/table.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/builtins/table.c b/builtins/table.c
index a1ce610c..16b06f6f 100644
--- a/builtins/table.c
+++ b/builtins/table.c
@@ -503,8 +503,22 @@ public CORD Table$as_text(const table_t *t, bool colorize, const TypeInfo *type)
public table_t Table$from_entries(array_t entries, const TypeInfo *type)
{
assert(type->tag == TableInfo);
- table_t t = {.entries=entries};
- hashmap_resize_buckets(&t, entries.length, type);
+ if (entries.length == 0)
+ return (table_t){};
+
+ table_t t = {};
+ int64_t length = entries.length + entries.length / 4;
+ int64_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[length]);
+ t.bucket_info = GC_MALLOC_ATOMIC(alloc_size);
+ memset(t.bucket_info->buckets, 0, sizeof(bucket_t[length]));
+ t.bucket_info->count = length;
+ t.bucket_info->last_free = length-1;
+
+ int64_t offset = value_offset(type);
+ for (int64_t i = 0; i < entries.length; i++) {
+ void *key = entries.data + i*entries.stride;
+ Table$set(&t, key, key + offset, type);
+ }
return t;
}