From 7355b2f7fe6f5dda2aee8feca025350146ccd0f5 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 17 Feb 2024 18:38:29 -0500 Subject: [PATCH] Change things up to use type params for all array and table methods --- builtins/array.c | 51 ++++++++++++++++++-------------- builtins/array.h | 48 +++++++++--------------------- builtins/functions.c | 15 +++++----- builtins/table.c | 69 +++++++++++++++++++++++++++++--------------- builtins/types.c | 4 +-- builtins/types.h | 8 +++-- compile.c | 56 +++++++++++++++++++++++++++-------- environment.c | 5 +--- typecheck.c | 38 +++++++----------------- typecheck.h | 1 - types.c | 27 ++--------------- types.h | 5 +--- 12 files changed, 163 insertions(+), 164 deletions(-) diff --git a/builtins/array.c b/builtins/array.c index e91b980..447650f 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -17,11 +17,17 @@ extern const void *SSS_HASH_VECTOR; +static inline size_t get_item_size(const TypeInfo *info) +{ + return info->ArrayInfo.item->size; +} + // Replace the array's .data pointer with a new pointer to a copy of the // data that is compacted and has a stride of exactly `item_size` -public void Array_compact(array_t *arr, int64_t item_size) +public void Array__compact(array_t *arr, const TypeInfo *type) { void *copy = NULL; + int64_t item_size = get_item_size(type); if (arr->length > 0) { copy = arr->atomic ? GC_MALLOC_ATOMIC(arr->length * item_size) : GC_MALLOC(arr->length * item_size); if ((int64_t)arr->stride == item_size) { @@ -41,13 +47,14 @@ public void Array_compact(array_t *arr, int64_t item_size) }; } -public void Array_insert(array_t *arr, const void *item, int64_t index, int64_t item_size) +public void Array__insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type) { if (index < 1) index = arr->length - index + 1; if (index < 1) index = 1; else if (index > (int64_t)arr->length + 1) index = (int64_t)arr->length + 1; + int64_t item_size = get_item_size(type); if (!arr->data) { arr->free = 4; arr->data = arr->atomic ? GC_MALLOC_ATOMIC(arr->free * item_size) : GC_MALLOC(arr->free * item_size); @@ -64,7 +71,7 @@ public void Array_insert(array_t *arr, const void *item, int64_t index, int64_t arr->stride = item_size; } else { if (arr->copy_on_write) - Array_compact(arr, item_size); + Array__compact(arr, type); if (index != arr->length+1) memmove((void*)arr->data + index*item_size, arr->data + (index-1)*item_size, (arr->length - index)*item_size); @@ -75,13 +82,14 @@ public void Array_insert(array_t *arr, const void *item, int64_t index, int64_t memcpy((void*)arr->data + (index-1)*item_size, item, item_size); } -public void Array_insert_all(array_t *arr, array_t to_insert, int64_t index, int64_t item_size) +public void Array__insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type) { if (index < 1) index = arr->length - index + 1; if (index < 1) index = 1; else if (index > (int64_t)arr->length + 1) index = (int64_t)arr->length + 1; + int64_t item_size = get_item_size(type); if (!arr->data) { arr->free = to_insert.length; arr->data = arr->atomic ? GC_MALLOC_ATOMIC(item_size*arr->free) : GC_MALLOC(item_size*arr->free); @@ -96,7 +104,7 @@ public void Array_insert_all(array_t *arr, array_t to_insert, int64_t index, int arr->copy_on_write = 0; } else { if (arr->copy_on_write) - Array_compact(arr, item_size); + Array__compact(arr, type); if (index != arr->length+1) memmove((void*)arr->data + index*item_size, arr->data + (index-1)*item_size, (arr->length - index + to_insert.length-1)*item_size); @@ -107,7 +115,7 @@ public void Array_insert_all(array_t *arr, array_t to_insert, int64_t index, int memcpy((void*)arr->data + (index-1 + i)*item_size, to_insert.data + i*to_insert.stride, item_size); } -public void Array_remove(array_t *arr, int64_t index, int64_t count, int64_t item_size) +public void Array__remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type) { if (index < 1) index = arr->length - index + 1; @@ -118,6 +126,7 @@ public void Array_remove(array_t *arr, int64_t index, int64_t count, int64_t ite // TODO: optimize arr.remove(1) by just updating the .data and .length values + int64_t item_size = get_item_size(type); if (index + count > arr->length) { if (arr->free >= 0) arr->free += count; @@ -139,7 +148,7 @@ public void Array_remove(array_t *arr, int64_t index, int64_t count, int64_t ite arr->length -= count; } -public void Array_sort(array_t *arr, const TypeInfo *type) +public void Array__sort(array_t *arr, const TypeInfo *type) { const TypeInfo *item_type = type->ArrayInfo.item; int64_t item_size = item_type->size; @@ -147,15 +156,16 @@ public void Array_sort(array_t *arr, const TypeInfo *type) item_size += item_type->align - (item_size % item_type->align); // padding if (arr->copy_on_write || (int64_t)arr->stride != item_size) - Array_compact(arr, item_size); + Array__compact(arr, type); qsort_r(arr->data, arr->length, item_size, (void*)generic_compare, (void*)item_type); } -public void Array_shuffle(array_t *arr, int64_t item_size) +public void Array__shuffle(array_t *arr, const TypeInfo *type) { + int64_t item_size = get_item_size(type); if (arr->copy_on_write || (int64_t)arr->stride != item_size) - Array_compact(arr, item_size); + Array__compact(arr, type); char tmp[item_size]; for (int64_t i = arr->length-1; i > 1; i--) { @@ -166,11 +176,8 @@ public void Array_shuffle(array_t *arr, int64_t item_size) } } -public array_t Array_slice(array_t *array, int64_t first, int64_t stride, int64_t length, bool readonly, const TypeInfo *type) +public array_t Array__slice(array_t *array, int64_t first, int64_t stride, int64_t length, bool readonly, const TypeInfo *type) { - TypeInfo *item = type->ArrayInfo.item; - int64_t item_size = item->size; - if (stride > INT16_MAX) stride = INT16_MAX; else if (stride < INT16_MIN) @@ -214,6 +221,7 @@ public array_t Array_slice(array_t *array, int64_t first, int64_t stride, int64_ // never do modifictions array->copy_on_write = !readonly; + int64_t item_size = get_item_size(type); return (array_t){ .atomic=array->atomic, .data=array->data + item_size*(first-1), @@ -223,7 +231,7 @@ public array_t Array_slice(array_t *array, int64_t first, int64_t stride, int64_ }; } -public bool Array_contains(array_t array, void *item, const TypeInfo *type) +public bool Array__contains(array_t array, void *item, const TypeInfo *type) { TypeInfo *item_type = type->ArrayInfo.item; for (int64_t i = 0; i < array.length; i++) @@ -232,12 +240,13 @@ public bool Array_contains(array_t array, void *item, const TypeInfo *type) return false; } -public void Array_clear(array_t *array) +public void Array__clear(array_t *array, const TypeInfo *type) { + (void)type; *array = (array_t){.data=0, .length=0}; } -public int32_t Array_compare(const array_t *x, const array_t *y, const TypeInfo *type) +public int32_t Array__compare(const array_t *x, const array_t *y, const TypeInfo *type) { // Early out for arrays with the same data, e.g. two copies of the same array: if (x->data == y->data && x->stride == y->stride) @@ -264,12 +273,12 @@ public int32_t Array_compare(const array_t *x, const array_t *y, const TypeInfo return (x->length > y->length) - (x->length < y->length); } -public bool Array_equal(const array_t *x, const array_t *y, const TypeInfo *type) +public bool Array__equal(const array_t *x, const array_t *y, const TypeInfo *type) { - return (Array_compare(x, y, type) == 0); + return (Array__compare(x, y, type) == 0); } -public CORD Array_cord(const array_t *arr, bool colorize, const TypeInfo *type) +public CORD Array__cord(const array_t *arr, bool colorize, const TypeInfo *type) { if (!arr) return CORD_all("[", generic_as_str(NULL, false, type->ArrayInfo.item), "]"); @@ -286,7 +295,7 @@ public CORD Array_cord(const array_t *arr, bool colorize, const TypeInfo *type) return c; } -public uint32_t Array_hash(const array_t *arr, const TypeInfo *type) +public uint32_t Array__hash(const array_t *arr, const TypeInfo *type) { // Array hash is calculated as a rolling, compacting hash of the length of the array, followed by // the hashes of its items (or the items themselves if they're small plain data) diff --git a/builtins/array.h b/builtins/array.h index 9815ddf..ff62db3 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -7,40 +7,18 @@ #include "functions.h" #include "types.h" -void Array_insert(array_t *arr, const void *item, int64_t index, int64_t item_size); -void Array_insert_all(array_t *arr, array_t to_insert, int64_t index, int64_t item_size); -void Array_remove(array_t *arr, int64_t index, int64_t count, int64_t item_size); -void Array_sort(array_t *arr, const TypeInfo *type); -void Array_shuffle(array_t *arr, int64_t item_size); -void Array_clear(array_t *array); -void Array_compact(array_t *arr, int64_t item_size); -bool Array_contains(array_t array, void *item, const TypeInfo *type); -array_t Array_slice(array_t *array, int64_t first, int64_t stride, int64_t length, bool readonly, const TypeInfo *type); -uint32_t Array_hash(const array_t *arr, const TypeInfo *type); -int32_t Array_compare(const array_t *x, const array_t *y, const TypeInfo *type); -bool Array_equal(const array_t *x, const array_t *y, const TypeInfo *type); -CORD Array_as_str(const array_t *arr, bool colorize, const TypeInfo *type); - -// Due to some C language weirdness, the type of "foo" is inferred to be `char[3]` instead of `const char*` -// This is a hacky workaround to ensure that __typeof("foo") => `const char *` -#define FIX_STR_LITERAL(s) _Generic(((void)0, s), char*: (const char*)s, default: s) - -#define ARRAY_OF(t) t** -#define EMPTY_ARRAY(t) (t**)new(array_t) -#define LENGTH(arr) (((array_t*)(arr))->length) -#define ARRAY(x, ...) (__typeof(FIX_STR_LITERAL(x))**)new(array_t, \ - .data=memcpy(GC_MALLOC(sizeof((__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__})), (__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__}, \ - sizeof((__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__})), \ - .length=(sizeof((__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__})) / sizeof(FIX_STR_LITERAL(x)), \ - .stride=sizeof(FIX_STR_LITERAL(x))) -#define STATIC_ARRAY(x, ...) ((array_t){ \ - .data=(__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__}, \ - .length=(sizeof((__typeof(FIX_STR_LITERAL(x))[]){x, __VA_ARGS__})) / sizeof(FIX_STR_LITERAL(x)), \ - .stride=sizeof(FIX_STR_LITERAL(x))}) -#define foreach(arr, var, last) for (__typeof(arr[0]) var = arr[0], last = ith_addr(arr, LENGTH(arr)-1); var && var <= last; var = ((void*)var) + ((array_t*)(arr))->stride) -#define ith_addr(arr, i) ((__typeof(arr[0]))(((array_t*)(arr))->data + (i)*((array_t*)(arr))->stride)) -#define ith(arr, i) (*ith_addr(arr,i)) -#define append(arr, obj) Array_insert((array_t*)(arr), (__typeof((arr)[0][0])[]){obj}, 0, sizeof((arr)[0][0])) -#define remove(arr, i) Array_remove((array_t*)(arr), (i)+1, 1, sizeof(arr[0][0])) +void Array__insert(array_t *arr, const void *item, int64_t index, const TypeInfo *type); +void Array__insert_all(array_t *arr, array_t to_insert, int64_t index, const TypeInfo *type); +void Array__remove(array_t *arr, int64_t index, int64_t count, const TypeInfo *type); +void Array__sort(array_t *arr, const TypeInfo *type); +void Array__shuffle(array_t *arr, const TypeInfo *type); +void Array__clear(array_t *array, const TypeInfo *type); +void Array__compact(array_t *arr, const TypeInfo *type); +bool Array__contains(array_t array, void *item, const TypeInfo *type); +array_t Array__slice(array_t *array, int64_t first, int64_t stride, int64_t length, bool readonly, const TypeInfo *type); +uint32_t Array__hash(const array_t *arr, const TypeInfo *type); +int32_t Array__compare(const array_t *x, const array_t *y, const TypeInfo *type); +bool Array__equal(const array_t *x, const array_t *y, const TypeInfo *type); +CORD Array__as_str(const array_t *arr, bool colorize, const TypeInfo *type); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/functions.c b/builtins/functions.c index 1b22efd..93453a3 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -31,8 +31,8 @@ public void fail(const char *fmt, ...) public uint32_t generic_hash(const void *obj, const TypeInfo *type) { switch (type->tag) { - case PointerInfo: return Pointer__hash(obj, type); - case ArrayInfo: return Array_hash(obj, type); + case PointerInfo: case FunctionInfo: return Pointer__hash(obj, type); + case ArrayInfo: return Array__hash(obj, type); case TableInfo: return Table_hash(obj, type); case CustomInfo: if (!type->CustomInfo.hash) @@ -50,8 +50,8 @@ public uint32_t generic_hash(const void *obj, const TypeInfo *type) public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type) { switch (type->tag) { - case PointerInfo: return Pointer__compare(x, y, type); - case ArrayInfo: return Array_compare(x, y, type); + case PointerInfo: case FunctionInfo: return Pointer__compare(x, y, type); + case ArrayInfo: return Array__compare(x, y, type); case TableInfo: return Table_compare(x, y, type); case CustomInfo: if (!type->CustomInfo.compare) @@ -66,8 +66,8 @@ public int32_t generic_compare(const void *x, const void *y, const TypeInfo *typ public bool generic_equal(const void *x, const void *y, const TypeInfo *type) { switch (type->tag) { - case PointerInfo: return Pointer__equal(x, y, type); - case ArrayInfo: return Array_equal(x, y, type); + case PointerInfo: case FunctionInfo: return Pointer__equal(x, y, type); + case ArrayInfo: return Array__equal(x, y, type); case TableInfo: return Table_equal(x, y, type); case CustomInfo: if (!type->CustomInfo.equal) @@ -83,7 +83,8 @@ public CORD generic_as_str(const void *obj, bool colorize, const TypeInfo *type) { switch (type->tag) { case PointerInfo: return Pointer__cord(obj, colorize, type); - case ArrayInfo: return Array_as_str(obj, colorize, type); + case FunctionInfo: return Func__as_str(obj, colorize, type); + case ArrayInfo: return Array__as_str(obj, colorize, type); case TableInfo: return Table_as_str(obj, colorize, type); case TypeInfoInfo: return Type__as_str(obj, colorize, type); case CustomInfo: diff --git a/builtins/table.c b/builtins/table.c index 32e6bb8..ad8c6e4 100644 --- a/builtins/table.c +++ b/builtins/table.c @@ -37,11 +37,10 @@ // Helper accessors for type functions/values: #define HASH_KEY(t, k) (generic_hash((k), type->TableInfo.key) % ((t)->bucket_info->count)) #define EQUAL_KEYS(x, y) (generic_equal((x), (y), type->TableInfo.key)) -#define ENTRY_SIZE (type->TableInfo.entry_size) -#define VALUE_OFFSET (type->TableInfo.value_offset) #define END_OF_CHAIN UINT32_MAX #define GET_ENTRY(t, i) ((t)->entries.data + (t)->entries.stride*(i)) +#define ENTRY_TYPE(type) (&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo}) extern const void *SSS_HASH_VECTOR; @@ -59,10 +58,34 @@ TypeInfo StrToVoidStarTable_type = { .size=sizeof(table_t), .align=alignof(table_t), .tag=TableInfo, - .TableInfo={.key=&Str_type.type, .value=&MemoryPointer_typeinfo, - .entry_size=16, .value_offset=8}, + .TableInfo={.key=&Str_type.type, .value=&MemoryPointer_typeinfo}, }; +static inline size_t entry_size(const TypeInfo *info) +{ + size_t size = info->TableInfo.key->size; + if (info->TableInfo.value->align > 1 && size % info->TableInfo.value->align) + size += info->TableInfo.value->align - (size % info->TableInfo.value->align); // padding + size += info->TableInfo.value->size; + if (info->TableInfo.key->align > 1 && size % info->TableInfo.key->align) + size += info->TableInfo.key->align - (size % info->TableInfo.key->align); // padding + return size; +} + +static inline size_t entry_align(const TypeInfo *info) +{ + return MAX(info->TableInfo.key->align, info->TableInfo.value->align); +} + +static inline size_t value_offset(const TypeInfo *info) +{ + size_t offset = info->TableInfo.key->size; + if (info->TableInfo.value->align > 1 && offset % info->TableInfo.value->align) + offset += info->TableInfo.value->align - (offset % info->TableInfo.value->align); // padding + return offset; +} + + static inline void hshow(const table_t *t) { hdebug("{"); @@ -79,7 +102,7 @@ static inline void hshow(const table_t *t) static void maybe_copy_on_write(table_t *t, const TypeInfo *type) { if (t->entries.copy_on_write) { - Array_compact(&t->entries, type->TableInfo.entry_size); + Array__compact(&t->entries, ENTRY_TYPE(type)); } if (t->bucket_info && t->bucket_info->copy_on_write) { @@ -110,7 +133,7 @@ public void *Table_get_raw(const table_t *t, const void *key, const TypeInfo *ty void *entry = GET_ENTRY(t, buckets[i].index); if (EQUAL_KEYS(entry, key)) { hdebug("Found key!\n"); - return entry + VALUE_OFFSET; + return entry + value_offset(type); } if (buckets[i].next_bucket == END_OF_CHAIN) break; @@ -250,18 +273,18 @@ public void *Table_reserve(table_t *t, const void *key, const void *value, const maybe_copy_on_write(t, type); - char buf[ENTRY_SIZE] = {}; + char buf[entry_size(type)] = {}; memcpy(buf, key, key_size); if (value && value_size > 0) - memcpy(buf + VALUE_OFFSET, value, value_size); + memcpy(buf + value_offset(type), value, value_size); else - memset(buf + VALUE_OFFSET, 0, value_size); - Array_insert(&t->entries, buf, 0, ENTRY_SIZE); + memset(buf + value_offset(type), 0, value_size); + Array__insert(&t->entries, buf, 0, ENTRY_TYPE(type)); int64_t entry_index = t->entries.length-1; void *entry = GET_ENTRY(t, entry_index); Table_set_bucket(t, entry, entry_index, type); - return entry + VALUE_OFFSET; + return entry + value_offset(type); } public void Table_set(table_t *t, const void *key, const void *value, const TypeInfo *type) @@ -336,13 +359,13 @@ public void Table_remove(table_t *t, const void *key, const TypeInfo *type) // Clobber the entry being removed (in the middle of the array) with // the last entry: - memcpy(GET_ENTRY(t, bucket->index), GET_ENTRY(t, last_entry), ENTRY_SIZE); + memcpy(GET_ENTRY(t, bucket->index), GET_ENTRY(t, last_entry), entry_size(type)); } // Last entry is being removed, so clear it out to be safe: - memset(GET_ENTRY(t, last_entry), 0, ENTRY_SIZE); + memset(GET_ENTRY(t, last_entry), 0, entry_size(type)); - Array_remove(&t->entries, t->entries.length, 1, ENTRY_SIZE); + Array__remove(&t->entries, t->entries.length, 1, ENTRY_TYPE(type)); int64_t bucket_to_clear; if (prev) { // Middle (or end) of a chain @@ -392,7 +415,7 @@ public bool Table_equal(const table_t *x, const table_t *y, const TypeInfo *type const TypeInfo *value_type = type->TableInfo.value; for (int64_t i = 0, length = Table_length(x); i < length; i++) { void *x_key = GET_ENTRY(x, i); - void *x_value = x_key + VALUE_OFFSET; + void *x_value = x_key + value_offset(type); void *y_value = Table_get_raw(y, x_key, type); if (!y_value) return false; @@ -421,15 +444,15 @@ public int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo return (x->entries.length > y->entries.length) - (x->entries.length < y->entries.length); array_t x_entries = x->entries, y_entries = y->entries; - Array_sort(&x_entries, table.key); - Array_sort(&y_entries, table.key); + Array__sort(&x_entries, table.key); + Array__sort(&y_entries, table.key); for (int64_t i = 0; i < x_entries.length; i++) { void *x_key = x_entries.data + x_entries.stride * i; void *y_key = y_entries.data + y_entries.stride * i; int32_t diff = generic_compare(x_key, y_key, table.key); if (diff != 0) return diff; - void *x_value = x_key + table.value_offset; - void *y_value = y_key + table.value_offset; + void *x_value = x_key + value_offset(type); + void *y_value = y_key + value_offset(type); diff = generic_compare(x_value, y_value, table.value); if (diff != 0) return diff; } @@ -457,13 +480,13 @@ public uint32_t Table_hash(const table_t *t, const TypeInfo *type) // hash(#t, xor(hash(k) for k in t.keys), xor(hash(v) for v in t.values), hash(t.fallback), hash(t.default)) // Where fallback and default hash to zero if absent auto table = type->TableInfo; - int64_t value_offset = table.value_offset; + int64_t val_off = value_offset(type); uint32_t key_hashes = 0, value_hashes = 0, fallback_hash = 0, default_hash = 0; for (int64_t i = 0, length = Table_length(t); i < length; i++) { void *entry = GET_ENTRY(t, i); key_hashes ^= generic_hash(entry, table.key); - value_hashes ^= generic_hash(entry + value_offset, table.value); + value_hashes ^= generic_hash(entry + val_off, table.value); } if (t->fallback) @@ -492,7 +515,7 @@ public CORD Table_as_str(const table_t *t, bool colorize, const TypeInfo *type) if (!t) return CORD_all("{", generic_as_str(NULL, false, table.key), "=>", generic_as_str(NULL, false, table.value), "}"); - int64_t value_offset = table.value_offset; + int64_t val_off = value_offset(type); CORD c = "{"; for (int64_t i = 0, length = Table_length(t); i < length; i++) { if (i > 0) @@ -500,7 +523,7 @@ public CORD Table_as_str(const table_t *t, bool colorize, const TypeInfo *type) void *entry = GET_ENTRY(t, i); c = CORD_cat(c, generic_as_str(entry, colorize, table.key)); c = CORD_cat(c, "=>"); - c = CORD_cat(c, generic_as_str(entry + value_offset, colorize, table.value)); + c = CORD_cat(c, generic_as_str(entry + val_off, colorize, table.value)); } if (t->fallback) { diff --git a/builtins/types.c b/builtins/types.c index b5527c6..f77a36f 100644 --- a/builtins/types.c +++ b/builtins/types.c @@ -47,8 +47,8 @@ public struct { public CORD Func__as_str(const void *fn, bool colorize, const TypeInfo *type) { (void)fn; - CORD c = type->TypeInfoInfo.type_str; - if (colorize) + CORD c = type->FunctionInfo.type_str; + if (fn && colorize) CORD_sprintf(&c, "\x1b[32;1m%r\x1b[m", c); return c; } diff --git a/builtins/types.h b/builtins/types.h index eac34de..0430fbe 100644 --- a/builtins/types.h +++ b/builtins/types.h @@ -15,7 +15,7 @@ typedef CORD (*str_fn_t)(const void*, bool, const struct TypeInfo*); typedef struct TypeInfo { int64_t size, align; struct { // Anonymous tagged union for convenience - enum { CustomInfo, PointerInfo, ArrayInfo, TableInfo, TypeInfoInfo, } tag; + enum { CustomInfo, PointerInfo, ArrayInfo, TableInfo, FunctionInfo, TypeInfoInfo, OpaqueInfo, } tag; union { struct { equal_fn_t equal; @@ -32,15 +32,19 @@ typedef struct TypeInfo { } ArrayInfo; struct { struct TypeInfo *key, *value; - int64_t entry_size, value_offset; } TableInfo; + struct { + const char *type_str; + } FunctionInfo; struct { const char *type_str; } TypeInfoInfo; + struct {} OpaqueInfo; }; }; } TypeInfo; CORD Type__as_str(const void *typeinfo, bool colorize, const TypeInfo *type); +CORD Func__as_str(const void *fn, bool colorize, const TypeInfo *type); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/compile.c b/compile.c index a230d71..c706ee7 100644 --- a/compile.c +++ b/compile.c @@ -414,17 +414,49 @@ CORD compile(env_t *env, ast_t *ast) return NULL; } -// CORD compile_type_info(env_t *env, type_t *t) -// { -// switch (t->tag) { -// case BoolType: return "&Bool$Info"; -// case IntType: return CORD_asprintf("&Int%ld$Info", Match(t, IntType)->bits); -// case NumType: return CORD_asprintf("&Num%ld$Info", Match(t, NumType)->bits); -// case StringType: return CORD_all("&", Match(t, StringType)->dsl ? Match(t, StringType)->dsl : "Str", "$Info"); -// case StructType: return CORD_all("&", Match(t, StructType)->name, "$Info"); -// case EnumType: return CORD_all("&", Match(t, EnumType)->name, "$Info"); -// case ArrayType: return CORD_all("&((TypeInfo){", Match(t, EnumType)->name, "$Info"); -// } -// } +CORD compile_type_info(env_t *env, type_t *t) +{ + switch (t->tag) { + case BoolType: return "&Bool_type"; + case IntType: return CORD_asprintf("&Int%ld_type", Match(t, IntType)->bits); + case NumType: return CORD_asprintf("&Num%ld_type", Match(t, NumType)->bits); + case StringType: return CORD_all("&", Match(t, StringType)->dsl ? Match(t, StringType)->dsl : "Str", "_type"); + case StructType: return CORD_all("&", Match(t, StructType)->name, "_type"); + case EnumType: return CORD_all("&", Match(t, EnumType)->name, "_type"); + case ArrayType: { + type_t *item_t = Match(t, ArrayType)->item_type; + return CORD_asprintf( + "&((TypeInfo){.size=%zu, .align=%zu, .tag=ArrayInfo, .ArrayInfo.item=%r})", + sizeof(array_t), alignof(array_t), + compile_type_info(env, item_t)); + } + case TableType: { + type_t *key_type = Match(t, TableType)->key_type; + type_t *value_type = Match(t, TableType)->value_type; + return CORD_asprintf( + "&((TypeInfo){.size=%zu, .align=%zu, .tag=TableInfo, .TableInfo.key=%r, .TableInfo.value=%r})", + sizeof(table_t), alignof(table_t), + compile_type_info(env, key_type), + compile_type_info(env, value_type)); + } + case PointerType: { + auto ptr = Match(t, PointerType); + CORD sigil = ptr->is_stack ? "&" : (ptr->is_optional ? "?" : "@"); + if (ptr->is_readonly) sigil = CORD_cat(sigil, "(readonly)"); + return CORD_asprintf( + "&((TypeInfo){.size=%zu, .align=%zu, .tag=PointerInfo, .PointerInfo.sigil=\"%r\", .PointerInfo.pointed=%r})", + sizeof(void*), alignof(void*), + sigil, compile_type_info(env, ptr->pointed)); + } + case FunctionType: { + return CORD_asprintf("&((TypeInfo){.size=%zu, .align=%zu, .tag=FunctionInfo, .FunctionInfo.type_str=\"%r\"})", + sizeof(void*), alignof(void*), type_to_cord(t)); + } + case ClosureType: { + errx(1, "No typeinfo for closures yet"); + } + default: errx(1, "No such typeinfo"); + } +} // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/environment.c b/environment.c index d6bb4c6..7e909cc 100644 --- a/environment.c +++ b/environment.c @@ -51,10 +51,7 @@ env_t *new_compilation_unit(void) table_t namespace; } global_types[] = { {"Bool", Type(BoolType), "Bool_t", "Bool", {}}, - {"Int", Type(IntType, .bits=64), "Int_t", "Int", Table_from_entries(*(array_t*)ARRAY( - new(ns_entry_t, "min", {"Int.min", Type(IntType, .bits=64)}), - new(ns_entry_t, "max", {"Int.max", Type(IntType, .bits=64)}), - ), &StrToVoidStarTable_type)}, + {"Int", Type(IntType, .bits=64), "Int_t", "Int", {}}, }; for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) { diff --git a/typecheck.c b/typecheck.c index 4234e56..374efa9 100644 --- a/typecheck.c +++ b/typecheck.c @@ -74,24 +74,6 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast) code_err(ast, "I don't know how to get this type"); } -type_t *get_iter_type(env_t *env, ast_t *iter) -{ - type_t *iter_t = get_type(env, iter); - for (;;) { - if (iter_t->tag == PointerType) iter_t = Match(iter_t, PointerType)->pointed; - // else if (iter_t->tag == VariantType) iter_t = Match(iter_t, VariantType)->variant_of; - else break; - } - type_t *value_t = value_type(iter_t); - switch (value_t->tag) { - case ArrayType: return Match(value_t, ArrayType)->item_type; - case TableType: return table_entry_type(value_t); - default: - code_err(iter, "I don't know how to iterate over %T values like this", iter_t); - break; - } -} - type_t *get_math_type(env_t *env, ast_t *ast, type_t *lhs_t, type_t *rhs_t) { (void)env; @@ -218,8 +200,8 @@ type_t *get_type(env_t *env, ast_t *ast) type_t *merged = item_type ? type_or_type(item_type, t2) : t2; if (!merged) code_err(item->ast, - "This array item has type %s, which is different from earlier array items which have type %s", - type_to_string(t2), type_to_string(item_type)); + "This array item has type %T, which is different from earlier array items which have type %T", + t2, item_type); item_type = merged; } } else { @@ -244,16 +226,16 @@ type_t *get_type(env_t *env, ast_t *ast) type_t *key_merged = key_type ? type_or_type(key_type, key_t) : key_t; if (!key_merged) code_err(table_entry->key, - "This table entry has type %s, which is different from earlier table entries which have type %s", - type_to_string(key_t), type_to_string(key_type)); + "This table entry has type %T, which is different from earlier table entries which have type %T", + key_t, key_type); key_type = key_merged; type_t *value_t = get_type(env, table_entry->value); type_t *val_merged = value_type ? type_or_type(value_type, value_t) : value_t; if (!val_merged) code_err(table_entry->value, - "This table entry has type %s, which is different from earlier table entries which have type %s", - type_to_string(value_t), type_to_string(value_type)); + "This table entry has type %T, which is different from earlier table entries which have type %T", + value_t, value_type); value_type = val_merged; } } @@ -316,9 +298,9 @@ type_t *get_type(env_t *env, ast_t *ast) } case Block: { auto block = Match(ast, Block); - if (LENGTH(block->statements) == 0) - return Type(VoidType); ast_list_t *last = block->statements; + if (!last) + return Type(VoidType); while (last->next) last = last->next; @@ -503,8 +485,8 @@ type_t *get_type(env_t *env, ast_t *ast) type_t *t_either = type_or_type(true_t, false_t); if (!t_either) code_err(if_->else_body, - "I was expecting this block to have a %s value (based on earlier clauses), but it actually has a %s value.", - type_to_string(true_t), type_to_string(false_t)); + "I was expecting this block to have a %T value (based on earlier clauses), but it actually has a %T value.", + true_t, false_t); return t_either; } else { return Type(VoidType); diff --git a/typecheck.h b/typecheck.h index 39d5b01..706d01d 100644 --- a/typecheck.h +++ b/typecheck.h @@ -14,6 +14,5 @@ type_t *get_math_type(env_t *env, ast_t *ast, type_t *lhs_t, type_t *rhs_t); bool is_discardable(env_t *env, ast_t *ast); type_t *get_namespace_type(env_t *env, ast_t *namespace_ast, type_t *type); type_t *get_file_type(env_t *env, const char *path); -type_t *get_iter_type(env_t *env, ast_t *iter); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/types.c b/types.c index 43f3da3..39c719a 100644 --- a/types.c +++ b/types.c @@ -8,7 +8,7 @@ #include "types.h" #include "util.h" -static CORD type_to_cord(type_t *t) { +CORD type_to_cord(type_t *t) { switch (t->tag) { case UnknownType: return "???"; case AbortType: return "Abort"; @@ -127,16 +127,12 @@ int printf_type(FILE *stream, const struct printf_info *info, const void *const return CORD_put(type_to_cord(t), stream); } -const char *type_to_string(type_t *t) { - return CORD_to_const_char_star(type_to_cord(t)); -} - bool type_eq(type_t *a, type_t *b) { if (a == b) return true; if (a->tag != b->tag) return false; if (a->tag == PlaceholderType) return a == b; - return streq(type_to_string(a), type_to_string(b)); + return (CORD_cmp(type_to_cord(a), type_to_cord(b)) == 0); } bool type_is_a(type_t *t, type_t *req) @@ -431,25 +427,6 @@ bool can_have_cycles(type_t *t) return _can_have_cycles(t, &seen); } -type_t *table_entry_type(type_t *table_type) -{ - static table_t cache = {0}; - arg_t *fields = new( - arg_t, .name="key", - .type=Match(table_type, TableType)->key_type); - fields->next = new( - arg_t, .name="value", - .type=Match(table_type, TableType)->value_type); - type_t *t = Type(StructType, .fields=fields); - type_t *cached = Table_str_get(&cache, type_to_string(t)); - if (cached) { - return cached; - } else { - Table_str_set(&cache, type_to_string(t), t); - return t; - } -} - type_t *replace_type(type_t *t, type_t *target, type_t *replacement) { if (type_eq(t, target)) diff --git a/types.h b/types.h index af42c38..99cb9d4 100644 --- a/types.h +++ b/types.h @@ -99,9 +99,7 @@ struct type_s { int printf_pointer_size(const struct printf_info *info, size_t n, int argtypes[n], int size[n]); int printf_type(FILE *stream, const struct printf_info *info, const void *const args[]); -const char *type_to_string_concise(type_t *t); -const char *type_to_typeof_string(type_t *t); -const char *type_to_string(type_t *t); +CORD type_to_cord(type_t *t); bool type_eq(type_t *a, type_t *b); bool type_is_a(type_t *t, type_t *req); type_t *type_or_type(type_t *a, type_t *b); @@ -114,7 +112,6 @@ bool has_stack_memory(type_t *t); bool can_promote(type_t *actual, type_t *needed); bool can_leave_uninitialized(type_t *t); bool can_have_cycles(type_t *t); -type_t *table_entry_type(type_t *table_t); type_t *replace_type(type_t *t, type_t *target, type_t *replacement); size_t type_size(type_t *t); size_t type_align(type_t *t);