diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-02-17 14:20:14 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-02-17 14:20:14 -0500 |
| commit | 21a35cbc4587374c4f18c690e9f4d40e725a6033 (patch) | |
| tree | 719625fae926669ec2d95116e0b97cab6b3eaedc | |
| parent | 8ebf9bd3adf232930e3a4f5ca089d51595b93adf (diff) | |
Getting back to old typeinfo stuff from SSS
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | builtins/functions.c | 111 | ||||
| -rw-r--r-- | builtins/pointer.c | 68 | ||||
| -rw-r--r-- | builtins/pointer.h | 16 | ||||
| -rw-r--r-- | builtins/string.c | 31 | ||||
| -rw-r--r-- | builtins/string.h | 49 | ||||
| -rw-r--r-- | builtins/table.c | 81 | ||||
| -rw-r--r-- | builtins/types.c | 295 | ||||
| -rw-r--r-- | builtins/types.h | 10 | ||||
| -rw-r--r-- | metamethods/cord.c | 138 |
10 files changed, 268 insertions, 533 deletions
@@ -25,7 +25,7 @@ O=-Og CFLAGS=$(CCONFIG) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) LDLIBS=-lgc -lgccjit -lcord -lm -lunistring BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/builtins.o builtins/floats.o builtins/functions.o builtins/integers.o \ - builtins/memory.o builtins/string.o builtins/table.o builtins/types.o + builtins/pointer.o builtins/memory.o builtins/string.o builtins/table.o builtins/types.o all: nextlang libnext.so diff --git a/builtins/functions.c b/builtins/functions.c index 1e3e1066..2892107a 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -10,9 +10,15 @@ #include "../files.h" #include "../util.h" #include "functions.h" +#include "array.h" +#include "table.h" +#include "pointer.h" #include "string.h" -void fail(const char *fmt, ...) +extern bool USE_COLOR; +extern const void *SSS_HASH_VECTOR; + +public void fail(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -21,12 +27,75 @@ void fail(const char *fmt, ...) raise(SIGABRT); } -Str_t builtin_last_err() +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 TableInfo: return Table_hash(obj, type); + case CustomInfo: + if (!type->CustomInfo.hash) + goto hash_data; + return type->CustomInfo.hash(obj, type); + default: { + hash_data:; + uint32_t hash; + halfsiphash((void*)obj, type->size, SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); + return hash; + } + } +} + +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 TableInfo: return Table_compare(x, y, type); + case CustomInfo: + if (!type->CustomInfo.compare) + goto compare_data; + return type->CustomInfo.compare(x, y, type); + default: + compare_data: + return (int32_t)memcmp((void*)x, (void*)y, type->size); + } +} + +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 TableInfo: return Table_equal(x, y, type); + case CustomInfo: + if (!type->CustomInfo.equal) + goto use_generic_compare; + return type->CustomInfo.equal(x, y, type); + default: + use_generic_compare: + return (generic_compare(x, y, type) == 0); + } +} + +public CORD generic_cord(const void *obj, bool colorize, const TypeInfo *type) +{ + switch (type->tag) { + case PointerInfo: return Pointer__cord(obj, colorize, type); + case ArrayInfo: return Array_cord(obj, colorize, type); + case TableInfo: return Table_cord(obj, colorize, type); + case CustomInfo: + if (!type->CustomInfo.cord) + builtin_fail("No cord function provided for type: %s!\n", type->name); + return type->CustomInfo.cord(obj, colorize, type); + default: errx(1, "Invalid type tag: %d", type->tag); + } +} + + +public CORD builtin_last_err() { - const char *str = strerror(errno); - char *copy = GC_MALLOC_ATOMIC(strlen(str)+1); - strcpy(copy, str); - return (Str_t){.data=copy, .length=strlen(str), .stride=1}; + return CORD_from_char_star(strerror(errno)); } static inline char *without_colors(const char *str) @@ -48,33 +117,33 @@ static inline char *without_colors(const char *str) return buf; } -void __doctest(const char *label, CORD expr, const char *type, bool use_color, const char *expected, const char *filename, int start, int end) +public void __doctest(CORD label, void *expr, TypeInfo *type, CORD expected, const char *filename, int start, int end) { - static sss_file_t *file = NULL; + static file_t *file = NULL; if (filename && (file == NULL || strcmp(file->filename, filename) != 0)) - file = sss_load_file(filename); + file = load_file(filename); if (filename && file) - CORD_fprintf(stderr, use_color ? "\x1b[33;1m>>> \x1b[0m%.*s\x1b[m\n" : ">>> %.*s\n", (end - start), file->text + start); + CORD_fprintf(stderr, USE_COLOR ? "\x1b[33;1m>>> \x1b[0m%.*s\x1b[m\n" : ">>> %.*s\n", (end - start), file->text + start); if (expr) { - const char *expr_str = CORD_to_const_char_star(expr); - if (!use_color) - expr_str = without_colors(expr_str); + CORD expr_str = generic_cord(expr, USE_COLOR, type); + CORD type_name = generic_cord(NULL, false, type); - CORD_fprintf(stderr, use_color ? "\x1b[2m%s\x1b[0m %s \x1b[2m: %s\x1b[m\n" : "%s %s : %s\n", label, expr_str, type); + CORD_fprintf(stderr, USE_COLOR ? "\x1b[2m%r\x1b[0m %r \x1b[2m: %r\x1b[m\n" : "%r %r : %r\n", label, expr_str, type_name); if (expected) { - const char *actual = use_color ? without_colors(expr_str) : expr_str; - bool success = (strcmp(actual, expected) == 0); - if (!success && strchr(expected, ':')) { - actual = heap_strf("%s : %s", actual, type); - success = (strcmp(actual, expected) == 0); + CORD expr_plain = USE_COLOR ? generic_cord(expr, false, type) : expr_str; + bool success = (CORD_cmp(expr_str, expected) == 0); + if (!success && CORD_chr(expected, 0, ':')) { + expr_plain = heap_strf("%s : %s", expr_plain, type_name); + success = (CORD_cmp(CORD_catn(3, expr_plain, " : ", type_name), expected) == 0); } if (!success) { if (filename && file) - fprint_span(stderr, file, file->text+start, file->text+end, "\x1b[31;1m", 2, use_color); - builtin_fail(use_color ? "\x1b[31;1mExpected: \x1b[32;7m%s\x1b[0m\n\x1b[31;1m But got: \x1b[31;7m%s\x1b[0m\n" : "Expected: %s\n But got: %s\n", expected, actual); + fprint_span(stderr, file, file->text+start, file->text+end, "\x1b[31;1m", 2, USE_COLOR); + builtin_fail(USE_COLOR ? "\x1b[31;1mExpected: \x1b[32;7m%s\x1b[0m\n\x1b[31;1m But got: \x1b[31;7m%s\x1b[0m\n" : "Expected: %s\n But got: %s\n", + expected, expr_str); } } } diff --git a/builtins/pointer.c b/builtins/pointer.c new file mode 100644 index 00000000..69d11c07 --- /dev/null +++ b/builtins/pointer.c @@ -0,0 +1,68 @@ + +#include <gc.h> +#include <gc/cord.h> +#include <stdalign.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <ctype.h> +#include <sys/param.h> +#include <err.h> + +#include "types.h" +#include "../util.h" +#include "../SipHash/halfsiphash.h" + +extern const void *SSS_HASH_VECTOR; + +typedef struct recursion_s { + const void *ptr; + struct recursion_s *next; +} recursion_t; + +public CORD Pointer__cord(const void *x, bool colorize, const TypeInfo *type) { + auto ptr_info = type->PointerInfo; + const void *ptr = *(const void**)x; + if (!ptr) + return colorize ? CORD_asprintf("\x1b[34;1m!%s\x1b[m", ptr_info.pointed->name) : CORD_cat(ptr_info.sigil, ptr_info.pointed->name); + + // Check for recursive references, so if `x.foo = x`, then it prints as + // `@Foo{foo=@..1}` instead of overflowing the stack: + static recursion_t *recursion = NULL; + int32_t depth = 0; + for (recursion_t *r = recursion; r; r = r->next) { + ++depth; + if (r->ptr == ptr) + return CORD_asprintf(colorize ? "\x1b[34;1m%s..%d\x1b[m" : "%s..%d", ptr_info.sigil, depth); + } + + CORD pointed; + { // Stringify with this pointer flagged as a recursive one: + recursion_t my_recursion = {.ptr=ptr, .next=recursion}; + recursion = &my_recursion; + pointed = generic_cord(ptr, colorize, ptr_info.pointed); + recursion = recursion->next; + } + return colorize ? CORD_asprintf("\x1b[34;1m%s%r\x1b[m", ptr_info.sigil, pointed) : CORD_cat(ptr_info.sigil, pointed); +} + +public int32_t Pointer__compare(const void *x, const void *y, const TypeInfo *type) { + (void)type; + const void *xp = *(const void**)x, *yp = *(const void**)y; + return (xp > yp) - (xp < yp); +} + +public bool Pointer__equal(const void *x, const void *y, const TypeInfo *type) { + (void)type; + const void *xp = *(const void**)x, *yp = *(const void**)y; + return xp == yp; +} + +public uint32_t Pointer__hash(const void *x, const TypeInfo *type) { + (void)type; + uint32_t hash; + halfsiphash(x, sizeof(void*), SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); + return hash; +} + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/pointer.h b/builtins/pointer.h new file mode 100644 index 00000000..b8583b72 --- /dev/null +++ b/builtins/pointer.h @@ -0,0 +1,16 @@ +#pragma once +#include <gc/cord.h> +#include <stdbool.h> +#include <stdint.h> + +#include "types.h" + +CORD Pointer__cord(const void *x, bool colorize, const TypeInfo *type); +int32_t Pointer__compare(const void *x, const void *y, const TypeInfo *type); +bool Pointer__equal(const void *x, const void *y, const TypeInfo *type); +uint32_t Pointer__hash(const void *x, const TypeInfo *type); + +#define POINTER_TYPE(_sigil, _pointed) (&(TypeInfo){\ + .size=sizeof(void*), .align=alignof(void*), .tag=PointerInfo, .PointerInfo.sigil=_sigil, .PointerInfo.pointed=_pointed}) + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/string.c b/builtins/string.c index ce641762..3b417d39 100644 --- a/builtins/string.c +++ b/builtins/string.c @@ -21,11 +21,6 @@ extern const void *SSS_HASH_VECTOR; -typedef struct { - enum { FIND_FAILURE, FIND_SUCCESS } status; - int32_t index; -} find_result_t; - public CORD Str__quoted(CORD str, bool colorize) { // Note: it's important to have unicode strings not get broken up with @@ -131,8 +126,6 @@ public CORD Str__titlecased(CORD str) return (CORD)u8_totitle((const uint8_t*)str, len-1, uc_locale_language(), NULL, dest, &len); } -typedef enum { WHERE_ANYWHERE, WHERE_START, WHERE_END } where_e; - public bool Str__has(CORD str, CORD target, where_e where) { if (!target) return true; @@ -257,29 +250,7 @@ public CORD Str__join(CORD glue, Str_Array_t pieces) return ret; } -public struct { - TypeInfo type; - CORD (*uppercased)(CORD s); - CORD (*lowercased)(CORD s); - CORD (*titlecased)(CORD s); - bool (*has)(CORD s, CORD prefix, where_e where); - bool (*ends_with)(CORD s, CORD suffix); - CORD (*without)(CORD s, CORD target, where_e where); - CORD (*without_suffix)(CORD s, CORD suffix); - CORD (*trimmed)(CORD s, CORD trim_chars, where_e where); - CORD (*slice)(CORD s, int64_t first, int64_t stride, int64_t length); - char *(*c_string)(CORD str); - CORD (*from_c_string)(char *str); - find_result_t (*find)(CORD str, CORD pat); - CORD (*replace)(CORD text, CORD pat, CORD replacement, int64_t limit); - CORD (*quoted)(CORD text, bool colorize); - Str_Array_t (*split)(CORD str, CORD split_chars); - CORD (*join)(CORD glue, Str_Array_t pieces); - bool (*equal)(CORD *x, CORD *y); - int32_t (*compare)(CORD *x, CORD *y); - int (*hash)(CORD *s, TypeInfo *type); - CORD (*cord)(CORD *s, bool colorize, TypeInfo *type); -} Str_type = { +public Str_namespace_t Str_type = { .type={ .name="Str", .size=sizeof(CORD), diff --git a/builtins/string.h b/builtins/string.h index c58c4468..e625d7e2 100644 --- a/builtins/string.h +++ b/builtins/string.h @@ -3,6 +3,8 @@ #include <stdbool.h> #include <stdint.h> +#include "types.h" + typedef struct { CORD *data; unsigned long int length:42; @@ -10,5 +12,52 @@ typedef struct { short int stride:16; } Str_Array_t; +typedef enum { WHERE_ANYWHERE, WHERE_START, WHERE_END } where_e; + +typedef struct { + enum { FIND_FAILURE, FIND_SUCCESS } status; + int32_t index; +} find_result_t; + +typedef struct { + TypeInfo type; + CORD (*uppercased)(CORD s); + CORD (*lowercased)(CORD s); + CORD (*titlecased)(CORD s); + bool (*has)(CORD s, CORD prefix, where_e where); + bool (*ends_with)(CORD s, CORD suffix); + CORD (*without)(CORD s, CORD target, where_e where); + CORD (*without_suffix)(CORD s, CORD suffix); + CORD (*trimmed)(CORD s, CORD trim_chars, where_e where); + CORD (*slice)(CORD s, int64_t first, int64_t stride, int64_t length); + char *(*c_string)(CORD str); + CORD (*from_c_string)(char *str); + find_result_t (*find)(CORD str, CORD pat); + CORD (*replace)(CORD text, CORD pat, CORD replacement, int64_t limit); + CORD (*quoted)(CORD text, bool colorize); + Str_Array_t (*split)(CORD str, CORD split_chars); + CORD (*join)(CORD glue, Str_Array_t pieces); + bool (*equal)(CORD *x, CORD *y); + int32_t (*compare)(CORD *x, CORD *y); + int (*hash)(CORD *s, TypeInfo *type); + CORD (*cord)(CORD *s, bool colorize, TypeInfo *type); +} Str_namespace_t; +extern Str_namespace_t Str_type; + +CORD Str__quoted(CORD str, bool colorize); +int Str__compare(CORD *x, CORD *y); +bool Str__equal(CORD *x, CORD *y); +uint32_t Str__hash(CORD *cord); +CORD Str__uppercased(CORD str); +CORD Str__lowercased(CORD str); +CORD Str__titlecased(CORD str); +bool Str__has(CORD str, CORD target, where_e where); +CORD Str__without(CORD str, CORD target, where_e where); +CORD Str__trimmed(CORD str, CORD skip, where_e where); +CORD Str__slice(CORD str, int64_t first, int64_t stride, int64_t length); +find_result_t Str__find(CORD str, CORD pat); +CORD Str__replace(CORD text, CORD pat, CORD replacement, int64_t limit); +Str_Array_t Str__split(CORD str, CORD split); +CORD Str__join(CORD glue, Str_Array_t pieces); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/table.c b/builtins/table.c index 7ba33b1c..1c696a31 100644 --- a/builtins/table.c +++ b/builtins/table.c @@ -43,21 +43,6 @@ extern const void *SSS_HASH_VECTOR; -extern CORD CString_cord(const char **s, bool colorize, const TypeInfo *type); -extern uint32_t CString_hash(const char **s, const TypeInfo *type); -extern uint32_t CString_compare(const char **x, const char **y, const TypeInfo *type); -static TypeInfo CString_typeinfo = { - .name="CString", - .size=sizeof(char*), - .align=alignof(char*), - .tag=CustomInfo, - .CustomInfo={ - .cord=(void*)CString_cord, - .hash=(void*)CString_hash, - .compare=(void*)CString_compare, - }, -}; - TypeInfo MemoryPointer_typeinfo = { .name="@Memory", .size=sizeof(void*), @@ -69,12 +54,12 @@ TypeInfo MemoryPointer_typeinfo = { }, }; -TypeInfo CStringToVoidStarTable_type = { - .name="{CString=>@Memory}", +TypeInfo StrToVoidStarTable_type = { + .name="{Str=>@Memory}", .size=sizeof(table_t), .align=alignof(table_t), .tag=TableInfo, - .TableInfo={.key=&CString_typeinfo,.value=&MemoryPointer_typeinfo, + .TableInfo={.key=&Str_type.type, .value=&MemoryPointer_typeinfo, .entry_size=16, .value_offset=8}, }; @@ -430,23 +415,39 @@ public int32_t Table_compare(const table_t *x, const table_t *y, const TypeInfo { assert(type->tag == TableInfo); auto table = type->TableInfo; - struct { - const char *name; - const TypeInfo *type; - } member_data[] = {{"key", table.key}, {"value", table.value}}; - TypeInfo entry_type = { - .name="Entry", - .size=ENTRY_SIZE, - .align=MAX(table.key->align, table.value->align), - .tag=StructInfo, - .StructInfo={ - .members=(array_t){.data=member_data, .length=2, .stride=sizeof(member_data[0])}, - } - }; + if (x->entries.length == 0) + return 0; + else if (x->entries.length != y->entries.length) + 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, &entry_type); - Array_sort(&y_entries, &entry_type); - return Array_compare(&x_entries, &y_entries, &entry_type); + 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; + diff = generic_compare(x_value, y_value, table.value); + if (diff != 0) return diff; + } + + if (!x->default_value != !y->default_value) { + return (!x->default_value) - (!y->default_value); + } else if (x->default_value && y->default_value) { + int32_t diff = generic_compare(x->default_value, y->default_value, table.value); + if (diff != 0) return diff; + } + + if (!x->fallback != !y->fallback) { + return (!x->fallback) - (!y->fallback); + } else if (x->fallback && y->fallback) { + return generic_compare(x->fallback, y->fallback, type); + } + + return 0; } public uint32_t Table_hash(const table_t *t, const TypeInfo *type) @@ -504,7 +505,7 @@ public CORD Table_cord(const table_t *t, bool colorize, const TypeInfo *type) } if (t->default_value) { - c = CORD_cat(c, "; default="); + c = CORD_cat(c, t->fallback ? "; default=" : "; default="); c = CORD_cat(c, generic_cord(t->default_value, colorize, table.value)); } @@ -525,29 +526,29 @@ public table_t Table_from_entries(array_t entries, const TypeInfo *type) void *Table_str_get(const table_t *t, const char *key) { - void **ret = Table_get(t, &key, &CStringToVoidStarTable_type); + void **ret = Table_get(t, &key, &StrToVoidStarTable_type); return ret ? *ret : NULL; } void *Table_str_get_raw(const table_t *t, const char *key) { - void **ret = Table_get_raw(t, &key, &CStringToVoidStarTable_type); + void **ret = Table_get_raw(t, &key, &StrToVoidStarTable_type); return ret ? *ret : NULL; } void *Table_str_reserve(table_t *t, const char *key, const void *value) { - return Table_reserve(t, &key, &value, &CStringToVoidStarTable_type); + return Table_reserve(t, &key, &value, &StrToVoidStarTable_type); } void Table_str_set(table_t *t, const char *key, const void *value) { - Table_set(t, &key, &value, &CStringToVoidStarTable_type); + Table_set(t, &key, &value, &StrToVoidStarTable_type); } void Table_str_remove(table_t *t, const char *key) { - return Table_remove(t, &key, &CStringToVoidStarTable_type); + return Table_remove(t, &key, &StrToVoidStarTable_type); } void *Table_str_entry(const table_t *t, int64_t n) diff --git a/builtins/types.c b/builtins/types.c index 56826b59..a33c17f2 100644 --- a/builtins/types.c +++ b/builtins/types.c @@ -8,306 +8,13 @@ #include "array.h" #include "table.h" +#include "pointer.h" #include "types.h" #include "../util.h" #include "../SipHash/halfsiphash.h" extern const void *SSS_HASH_VECTOR; -public uint32_t generic_hash(const void *obj, const TypeInfo *type) -{ - switch (type->tag) { - case ArrayInfo: return Array_hash(obj, type); - case TableInfo: return Table_hash(obj, type); - case StructInfo: { - auto info = type->StructInfo; - if (info.members.length == 0) - return 0; - - uint32_t hash_values[info.members.length] = {}; - int64_t offset = 0; - for (int64_t i = 0; i < info.members.length; i++) { - typedef struct {const char *name; const TypeInfo *type;} struct_member_t; - struct_member_t *member = info.members.data + i*info.members.stride; - if (member->type->align > 1 && (offset % member->type->align)) - offset += member->type->align - (offset % member->type->align); - hash_values[i] = generic_hash(obj + offset, member->type); - offset += member->type->size; - } - uint32_t hash; - halfsiphash(hash_values, sizeof(uint32_t)*info.members.length, SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); - return hash; - } - case EnumInfo: { - auto info = type->EnumInfo; - int32_t tag = *(int32_t*)obj; - int64_t offset = 4; - typedef struct { int64_t tag; const char *name; const TypeInfo *type;} tu_member_t; - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - offset = MAX(offset, member->type->align); - } - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - if (member->tag != tag) continue; - struct { - int64_t tag; - uint32_t value_hash; - } data = {tag, generic_hash(obj + offset, member->type)}; - uint32_t hash; - halfsiphash(&data, sizeof(data), SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); - return hash; - } - uint32_t hash; - halfsiphash(&tag, sizeof(tag), SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); - return hash; - } - case CustomInfo: - if (!type->CustomInfo.hash) - goto hash_data; - return type->CustomInfo.hash(obj, type); - case PointerInfo: - default: { - hash_data:; - uint32_t hash; - halfsiphash((void*)obj, type->size, SSS_HASH_VECTOR, (uint8_t*)&hash, sizeof(hash)); - return hash; - } - } -} - -public int32_t generic_compare(const void *x, const void *y, const TypeInfo *type) -{ - switch (type->tag) { - case ArrayInfo: return Array_compare(x, y, type); - case TableInfo: return Table_compare(x, y, type); - case StructInfo: { - auto info = type->StructInfo; - typedef struct {const char *name; const TypeInfo *type;} struct_member_t; - auto members = (ARRAY_OF(struct_member_t))&info.members; - int64_t offset = 0; - foreach (members, member, last) { - if (member->type->align > 1 && (offset % member->type->align)) - offset += member->type->align - (offset % member->type->align); - int32_t cmp = generic_compare(x + offset, y + offset, member->type); - if (cmp != 0) return cmp; - offset += member->type->size; - } - return 0; - } - case EnumInfo: { - auto info = type->EnumInfo; - int32_t xtag = *(int32_t*)x, - ytag = *(int32_t*)y; - - if (xtag != ytag) - return xtag - ytag; - - int64_t offset = 4; - typedef struct { int64_t tag; const char *name; const TypeInfo *type;} tu_member_t; - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - offset = MAX(offset, member->type->align); - } - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - if (member->tag != xtag) continue; - return generic_compare(x + offset, y + offset, member->type); - } - return 0; - } - case CustomInfo: - if (!type->CustomInfo.compare) - goto compare_data; - return type->CustomInfo.compare(x, y, type); - case PointerInfo: - default: - compare_data: - return (int32_t)memcmp((void*)x, (void*)y, type->size); - } -} - -public bool generic_equal(const void *x, const void *y, const TypeInfo *type) -{ - switch (type->tag) { - case ArrayInfo: return Array_equal(x, y, type); - case TableInfo: return Table_equal(x, y, type); - case StructInfo: { - auto info = type->StructInfo; - typedef struct {const char *name; const TypeInfo *type;} struct_member_t; - auto members = (ARRAY_OF(struct_member_t))&info.members; - int64_t offset = 0; - foreach (members, member, last) { - if (member->type->align > 1 && (offset % member->type->align)) - offset += member->type->align - (offset % member->type->align); - bool equal = generic_equal(x + offset, y + offset, member->type); - if (!equal) return false; - offset += member->type->size; - } - return true; - } - case EnumInfo: { - auto info = type->EnumInfo; - int32_t xtag = *(int32_t*)x, - ytag = *(int32_t*)y; - - if (xtag != ytag) - return false; - - int64_t offset = 4; - typedef struct { int64_t tag; const char *name; const TypeInfo *type;} tu_member_t; - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - offset = MAX(offset, member->type->align); - } - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - if (member->tag != xtag) continue; - return generic_equal(x + offset, y + offset, member->type); - } - return true; - } - case CustomInfo: - if (!type->CustomInfo.equal) - goto use_generic_compare; - return type->CustomInfo.equal(x, y, type); - case PointerInfo: - default: - use_generic_compare: - return (generic_compare(x, y, type) == 0); - } -} - -public CORD generic_cord(const void *obj, bool colorize, const TypeInfo *type) -{ - switch (type->tag) { - case PointerInfo: { - auto ptr_info = type->PointerInfo; - static TypeInfo ptr_type = {.name="@Memory", .size=sizeof(void*), .align=alignof(void*)}; - static TypeInfo int_type = {.name="Int", .size=sizeof(int64_t), .align=alignof(int64_t)}; - static TypeInfo ptr_to_int_type = { - .name="{@Memory=>Int}", - .size=sizeof(table_t), - .align=alignof(table_t), - .tag=TableInfo, - .TableInfo={.key=&ptr_type, .value=&int_type, .entry_size=16, .value_offset=8}, - }; - - static int64_t zero = 0; - static table_t recursion = {.default_value=&zero}; - static table_t *current_recursion = NULL; - - CORD c; - bool first_ptr_call = (current_recursion == NULL); - if (first_ptr_call && ptr_info.cyclic) { - current_recursion = &recursion; - } - - if (ptr_info.cyclic) { - int64_t *found = Table_reserve(current_recursion, obj, NULL, &ptr_to_int_type); - if (*found) { - CORD_sprintf(&c, colorize ? "\x1b[34;1m%s%s#%ld\x1b[m" : "%s%s#%ld", - ptr_info.sigil, ptr_info.pointed ? ptr_info.pointed->name : "", *found); - goto done; - } else { - *found = Table_length(current_recursion); - } - } - - void *ptr = *(void**)obj; - if (ptr == NULL) { - CORD_sprintf(&c, colorize ? "\x1b[34;1m!%s\x1b[m" : "!%s", ptr_info.pointed ? ptr_info.pointed->name : ""); - } else { - CORD_sprintf(&c, colorize ? "\x1b[34;1m%s\x1b[m%r" : "%s%r", - ptr_info.sigil, ptr_info.pointed ? generic_cord(ptr, colorize, ptr_info.pointed) : "???"); - } - - done:; - if (first_ptr_call && ptr_info.cyclic) { - recursion = (table_t){.default_value=&zero}; - current_recursion = NULL; - } - - return c; - } - case StructInfo: { - auto info = type->StructInfo; - CORD c = "{"; - int64_t offset = 0; - for (int64_t i = 0; i < info.members.length; i++) { - if (i > 0) c = CORD_cat(c, ", "); - typedef struct {const char *name; const TypeInfo *type;} struct_member_t; - struct_member_t *member = info.members.data + i*info.members.stride; - if (member->type->align > 1 && (offset % member->type->align)) - offset += member->type->align - (offset % member->type->align); - - // Print the field name only if it's not an anonymous field ("_%ld" format) - char *end; - if (member->name[0] != '_' || strtol(member->name+1, &end, 10) != i+1 || *end) { - c = CORD_cat(c, member->name); - c = CORD_cat(c, "="); - } - - c = CORD_cat(c, generic_cord(obj + offset, colorize, member->type)); - offset += member->type->size; - } - c = CORD_cat(c, "}"); - if (strncmp(type->name, "struct(", strlen("struct(")) != 0) - CORD_sprintf(&c, colorize ? "\x1b[1m%s\x1b[m%r" : "%s%r", type->name, c); - return c; - } - case EnumInfo: { - auto info = type->EnumInfo; - int32_t tag = *(int32_t*)obj; - int64_t offset = 4; - typedef struct { int64_t tag; const char *name; const TypeInfo *type;} tu_member_t; - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - offset = MAX(offset, member->type->align); - } - for (int64_t i = 0; i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - if (member->tag == tag) { - CORD c; - CORD_sprintf(&c, colorize ? "\x1b[36m%s\x1b[m" : "%s", member->name); - if (member->type && member->type->size > 0) - c = CORD_cat(c, generic_cord(obj + offset, colorize, member->type)); - return c; - } - } - - CORD c = colorize ? "\x1b[36m" : ""; - int32_t tag_remainder = tag; - for (int64_t i = 0; tag_remainder && i < info.members.length; i++) { - tu_member_t *member = info.members.data + i*info.members.stride; - if (tag_remainder & member->tag) { - if (tag_remainder != tag) - c = CORD_cat(c, "+"); - c = CORD_cat(c, member->name); - tag_remainder &= ~member->tag; - } - } - if (tag_remainder) { - if (tag_remainder != tag) - c = CORD_cat(c, "+"); - c = CORD_cat(c, "???"); - } - - if (colorize) - c = CORD_cat(c, "\x1b[m"); - - return c; - } - case ArrayInfo: return Array_cord(obj, colorize, type); - case TableInfo: return Table_cord(obj, colorize, type); - case CustomInfo: - if (!type->CustomInfo.cord) - builtin_fail("No cord function provided for type: %s!\n", type->name); - return type->CustomInfo.cord(obj, colorize, type); - default: errx(1, "Invalid type tag: %d", type->tag); - } -} - public CORD Type__cord(void *type_namespace, bool colorize, const TypeInfo *type) { (void)type_namespace; diff --git a/builtins/types.h b/builtins/types.h index 960098b9..dccb6d2f 100644 --- a/builtins/types.h +++ b/builtins/types.h @@ -4,7 +4,6 @@ #include <stdint.h> #include "datatypes.h" -#include "string.h" struct TypeInfo; @@ -17,7 +16,7 @@ typedef struct TypeInfo { const char *name; int64_t size, align; struct { // Anonymous tagged union for convenience - enum { CustomInfo, PointerInfo, ArrayInfo, TableInfo, StructInfo, EnumInfo } tag; + enum { CustomInfo, PointerInfo, ArrayInfo, TableInfo } tag; union { struct { equal_fn_t equal; @@ -28,7 +27,6 @@ typedef struct TypeInfo { struct { const char *sigil; struct TypeInfo *pointed; - bool cyclic; } PointerInfo; struct { struct TypeInfo *item; @@ -37,12 +35,6 @@ typedef struct TypeInfo { struct TypeInfo *key, *value; int64_t entry_size, value_offset; } TableInfo; - struct { - array_t members; // [{name, type}] - } StructInfo; - struct { - array_t members; // [{tag, name, type}] - } EnumInfo; }; }; } TypeInfo; diff --git a/metamethods/cord.c b/metamethods/cord.c deleted file mode 100644 index 52c30608..00000000 --- a/metamethods/cord.c +++ /dev/null @@ -1,138 +0,0 @@ -#include <err.h> -#include <gc/cord.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> - -#include "../util.h" -#include "../builtins/datatypes.h" - -typedef const struct cord_info_s cord_info_t; -struct cord_info_s { - union { - struct { - char sigil; - CORD (*func)(void *x, bool use_color, cord_info_t *info); - cord_info_t *info; - } pointer; - int8_t precision; - struct { - CORD (*func)(void *x, bool use_color, cord_info_t *info); - cord_info_t *info; - } array; - struct { - CORD (*key_func)(void *x, bool use_color, cord_info_t *info); - cord_info_t *key_info; - size_t value_offset; - CORD (*value_func)(void *x, bool use_color, cord_info_t *info); - cord_info_t *value_info; - } table; - }; -}; -#define INFO(type, ...) (&(cord_info_t){.type={__VA_ARGS__}}) - -// x := @[Str] -// Pointer__as_str(&x, color, INFO(pointer, '@', Array__as_str, INFO(array, Str__quoted, NULL))) - -// x := {Int=>Bool} -// Table__as_str(&x, color, INFO(table, Int64__as_str, NULL, Bool__as_str, NULL)) - -// x := [[Foo]] -// Array__as_str(&x, color, INFO(array, Array__as_str, INFO(array, Foo__as_str, NULL))) - -CORD Bool__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Bool"; - return *(bool*)x ? "yes" : "no"; -} - -CORD Int__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Int"; - return CORD_asprintf("%ld", *(Int_t)x); -} - -CORD Int32__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Int32"; - return CORD_asprintf("%d", *(Int32_t)x); -} - -CORD Int16__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Int16"; - return CORD_asprintf("%d", *(Int16_t)x); -} - -CORD Int8__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Int8"; - return CORD_asprintf("%d", *(Int8_t)x); -} - -CORD Num__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Num"; - return CORD_asprintf("%g", *(Num_t)x); -} - -CORD Num32__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Num32"; - return CORD_asprintf("%g", *(Num32_t)x); -} - -CORD Str__as_str(void *x, bool color, cord_info_t *info) { - if (!x) return "Str"; - return Str__quoted(*(CORD*)x, color); -} - -CORD Pointer__as_str(void *x, bool color, cord_info_t *info) -{ - static const sigils[] = {['@']="@", ['?']="?", ['&']="&", ['!']="!"}; - if (!x) - return CORD_cat(sigils[info->pointer.sigil], info->pointer.func(NULL, color, info->pointer.info)); - void *ptr = *(void**)x; - CORD pointed = info->pointer.func(ptr, color, info->pointer.info); - return CORD_cat(ptr ? sigils[info->pointer.sigil] : "!", pointed); -} - -CORD Array__as_str(void *x, bool color, cord_info_t *info) -{ - if (!x) - return CORD_asprintf("[%r]", info->array.func(NULL, color, info->array.info)); - CORD cord = "["; - array_t *arr = x; - for (int64_t i = 0; i < arr->length; i++) { - if (i > 0) cord = CORD_cat(cord, ", "); - cord = CORD_cat(cord, info->array.func(arr->data + i*arr->stride, color, info->array.info)); - } - return CORD_cat(cord, "]"); -} - -CORD Table__as_str(void *x, bool color, cord_info_t *info) -{ - if (!x) { - return CORD_asprintf( - "{%r=>%r}", - info->table.key_func(NULL, color, info->table.key_info), - info->table.value_func(NULL, color, info->table.value_info)); - } - CORD cord = "{"; - table_t *table = x; - array_t entries = table->entries; - for (int64_t i = 0; i < entries.length; i++) { - if (i > 0) cord = CORD_cat(cord, ", "); - void *key = entries.data + i*entries.stride; - cord = CORD_cat(cord, info->table.key_func(key, color, info->table.key_info)); - cord = CORD_cat(cord, "="); - cord = CORD_cat(cord, info->table.value_func(key + info->table.value_offset, color, info->table.value_info)); - } - if (table->fallback) { - cord = CORD_cat(cord, "; fallback="); - cord = CORD_cat(cord, Table__as_str(table->fallback, color, info)); - if (table->default_value) cord = CORD_cat(cord, ", "); - } else if (table->default_value) { - if (table->default_value) cord = CORD_cat(cord, "; "); - } - if (table->default_value) { - cord = CORD_cat(cord, "default="); - cord = CORD_cat(cord, info->table.value_func(table->default_value, color, info->table.value_info)); - } - return CORD_cat(cord, "}"); -} - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
