aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-19 15:45:33 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-11-19 15:45:33 -0500
commit90573ba7a15bb47a11c1eb6f69ed04c01b69724d (patch)
tree0eba69a480d59862bff9294533618b81003c2e32 /stdlib
parent2c904ff1737e34008f7a6c5d4b072d87a45a3fbc (diff)
Tweak behavior for printing recursive structures
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/pointers.c50
1 files changed, 25 insertions, 25 deletions
diff --git a/stdlib/pointers.c b/stdlib/pointers.c
index 6a5f1e75..41defb95 100644
--- a/stdlib/pointers.c
+++ b/stdlib/pointers.c
@@ -7,16 +7,13 @@
#include <stdlib.h>
#include <sys/param.h>
+#include "integers.h"
#include "metamethods.h"
+#include "tables.h"
#include "text.h"
#include "types.h"
#include "util.h"
-typedef struct recursion_s {
- const void *ptr;
- struct recursion_s *next;
-} recursion_t;
-
public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
auto ptr_info = type->PointerInfo;
if (!x) {
@@ -37,30 +34,33 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *ty
return Text$concat(Text("!"), typename);
}
+ static const void *root = NULL;
+ static Table_t pending = {};
+ bool top_level = (root == NULL);
+
// 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) {
- Text_t text = Text$concat(
- colorize ? Text("\x1b[34;1m") : Text(""),
- Text$from_str(ptr_info.sigil),
- Text(".."),
- Text$format("%d", depth),
- colorize ? Text("\x1b[m") : Text(""));
- return text;
- }
+ // `@Foo{foo=@~1}` instead of overflowing the stack:
+ if (top_level) {
+ root = ptr;
+ } else if (ptr == root) {
+ return Text$format(colorize ? "\x1b[34;1m%s~1\x1b[m" : "%s~1", ptr_info.sigil);
+ } else {
+ TypeInfo_t rec_table = ((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
+ .tag=TableInfo, .TableInfo.key=type, .TableInfo.value=&Int64$info});
+ int64_t *id = Table$get(pending, x, &rec_table);
+ if (id)
+ return Text$format(colorize ? "\x1b[34;1m%s~%ld\x1b[m" : "%s~%ld", ptr_info.sigil, *id);
+ int64_t next_id = pending.entries.length + 2;
+ Table$set(&pending, x, &next_id, &rec_table);
}
- Text_t pointed;
- { // Stringify with this pointer flagged as a recursive one:
- recursion_t my_recursion = {.ptr=ptr, .next=recursion};
- recursion = &my_recursion;
- pointed = generic_as_text(ptr, colorize, ptr_info.pointed);
- recursion = recursion->next;
+ Text_t pointed = generic_as_text(ptr, colorize, ptr_info.pointed);
+
+ if (top_level) {
+ pending = (Table_t){}; // Restore
+ root = NULL;
}
+
Text_t text;
if (colorize)
text = Text$concat(Text("\x1b[34;1m"), Text$from_str(ptr_info.sigil), Text("\x1b[m"), pointed);