1 // Type infos and methods for Pointer types
11 #include "metamethods.h"
18 Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
19 __typeof(type->PointerInfo) ptr_info = type->PointerInfo;
21 Text_t typename = generic_as_text(NULL, false, ptr_info.pointed);
22 if (colorize) return Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), typename, Text("\x1b[m"));
23 else return Text$concat(Text$from_str(ptr_info.sigil), typename);
25 const void *ptr = *(const void **)x;
27 Text_t typename = generic_as_text(NULL, false, ptr_info.pointed);
28 if (colorize) return Text$concat(Text("\x1b[34;1m!"), typename, Text("\x1b[m"));
29 else return Text$concat(Text("!"), typename);
32 static const void *root = NULL;
33 static Table_t pending = EMPTY_TABLE;
34 bool top_level = (root == NULL);
36 // Check for recursive references, so if `x.foo = x`, then it prints as
37 // `@Foo{foo=@~1}` instead of overflowing the stack:
40 } else if (ptr == root) {
41 Text_t text = Text$concat(Text$from_str(ptr_info.sigil), Text("~1"));
42 return colorize ? Text$concat(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
44 TypeInfo_t rec_table = *Table$info(type, &Int64$info);
45 int64_t *id = Table$get(pending, x, &rec_table);
47 Text_t text = Text$concat(Text$from_str(ptr_info.sigil), Text("~"), Int64$value_as_text(*id));
48 return colorize ? Text$concat(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
50 int64_t next_id = (int64_t)pending.entries.length + 2;
51 Table$set(&pending, x, &next_id, &rec_table);
54 Text_t pointed = generic_as_text(ptr, colorize, ptr_info.pointed);
57 pending = (Table_t){}; // Restore
62 if (colorize) text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), Text("\x1b[m"), pointed);
63 else text = Text$concat(Text$from_str(ptr_info.sigil), pointed);
67 PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *info) {
69 const void *xp = *(const void **)x, *yp = *(const void **)y;
70 return (xp > yp) - (xp < yp);
73 PUREFUNC public bool Pointer$equal(const void *x, const void *y, const TypeInfo_t *info) {
75 const void *xp = *(const void **)x, *yp = *(const void **)y;
79 PUREFUNC public bool Pointer$is_none(const void *x, const TypeInfo_t *info) {
81 return *(void **)x == NULL;
85 void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
86 void *ptr = *(void **)obj;
89 const TypeInfo_t ptr_to_int_table = {.size = sizeof(Table_t),
90 .align = __alignof__(Table_t),
92 .TableInfo.key = type,
93 .TableInfo.value = &Int64$info};
95 int64_t *id_ptr = Table$get(*pointers, &ptr, &ptr_to_int_table);
100 id = (int64_t)pointers->entries.length + 1;
101 Table$set(pointers, &ptr, &id, &ptr_to_int_table);
104 Int64$serialize(&id, out, pointers, &Int64$info);
106 if (!id_ptr) _serialize(ptr, out, pointers, type->PointerInfo.pointed);
110 void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
112 Int64$deserialize(in, &id, pointers, &Int64$info);
115 if (id > (int64_t)pointers->length) {
116 void *obj = GC_MALLOC((size_t)type->PointerInfo.pointed->size);
117 List$insert(pointers, &obj, I(0), sizeof(void *));
118 _deserialize(in, obj, pointers, type->PointerInfo.pointed);
119 *(void **)outval = obj;
121 *(void **)outval = *(void **)(pointers->data + (id - 1) * pointers->stride);