code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(123 lines)
1 // Type infos and methods for Pointer types
3 #include <err.h>
4 #include <gc.h>
5 #include <stdbool.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <sys/param.h>
10 #include "integers.h"
11 #include "metamethods.h"
12 #include "tables.h"
13 #include "text.h"
14 #include "types.h"
15 #include "util.h"
17 public
18 Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
19 __typeof(type->PointerInfo) ptr_info = type->PointerInfo;
20 if (!x) {
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;
26 if (!ptr) {
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:
38 if (top_level) {
39 root = ptr;
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;
43 } else {
44 TypeInfo_t rec_table = *Table$info(type, &Int64$info);
45 int64_t *id = Table$get(pending, x, &rec_table);
46 if (id) {
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);
56 if (top_level) {
57 pending = (Table_t){}; // Restore
58 root = NULL;
61 Text_t text;
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);
64 return text;
67 PUREFUNC public int32_t Pointer$compare(const void *x, const void *y, const TypeInfo_t *info) {
68 (void)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) {
74 (void)info;
75 const void *xp = *(const void **)x, *yp = *(const void **)y;
76 return xp == yp;
79 PUREFUNC public bool Pointer$is_none(const void *x, const TypeInfo_t *info) {
80 (void)info;
81 return *(void **)x == NULL;
84 public
85 void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
86 void *ptr = *(void **)obj;
87 assert(ptr != NULL);
89 const TypeInfo_t ptr_to_int_table = {.size = sizeof(Table_t),
90 .align = __alignof__(Table_t),
91 .tag = TableInfo,
92 .TableInfo.key = type,
93 .TableInfo.value = &Int64$info};
95 int64_t *id_ptr = Table$get(*pointers, &ptr, &ptr_to_int_table);
96 int64_t id;
97 if (id_ptr) {
98 id = *id_ptr;
99 } else {
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);
109 public
110 void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
111 int64_t id = 0;
112 Int64$deserialize(in, &id, pointers, &Int64$info);
113 assert(id != 0);
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;
120 } else {
121 *(void **)outval = *(void **)(pointers->data + (id - 1) * pointers->stride);