Skip to content

Commit 32d9273

Browse files
committed
Improve circular reference printing
1 parent fac8da8 commit 32d9273

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

compiler-core/templates/echo.mjs

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ function echo(value, file, line) {
22
const grey = "\u001b[90m";
33
const reset_color = "\u001b[39m";
44
const file_line = `${file}:${line}`;
5-
const string_value = new Echo$Inspector.inspect(value);
5+
const inspector = new Echo$Inspector();
6+
const string_value = inspector.inspect(value);
67

78
if (globalThis.process?.stderr?.write) {
89
// If we're in Node.js, use `stderr`
@@ -25,6 +26,35 @@ function echo(value, file, line) {
2526
class Echo$Inspector {
2627
#references = new Set();
2728

29+
#isDict(value) {
30+
try {
31+
// We can only check if an object is a stdlib Dict if it is one of the
32+
// project's dependencies.
33+
// The `Dict` class is the default export of `stdlib/dict.mjs`
34+
// that we import as `$stdlib$dict`.
35+
return value instanceof $stdlib$dict.default;
36+
} catch {
37+
// If stdlib is not one of the project's dependencies then `$stdlib$dict`
38+
// will not have been imported and the check will throw an exception meaning
39+
// we can't check if something is actually a `Dict`.
40+
return false;
41+
}
42+
}
43+
44+
#float(float) {
45+
const string = float.toString().replace("+", "");
46+
if (string.indexOf(".") >= 0) {
47+
return string;
48+
} else {
49+
const index = string.indexOf("e");
50+
if (index >= 0) {
51+
return string.slice(0, index) + ".0" + string.slice(index);
52+
} else {
53+
return string + ".0";
54+
}
55+
}
56+
}
57+
2858
inspect(v) {
2959
const t = typeof v;
3060
if (v === true) return "True";
@@ -33,9 +63,9 @@ class Echo$Inspector {
3363
if (v === undefined) return "Nil";
3464
if (t === "string") return this.#string(v);
3565
if (t === "bigint" || Number.isInteger(v)) return v.toString();
36-
if (t === "number") return float_to_string(v);
37-
if (v instanceof UtfCodepoint) return this.#utfCodepoint(v);
38-
if (v instanceof BitArray) return this.#bit_array(v);
66+
if (t === "number") return this.#float(v);
67+
if (v instanceof $UtfCodepoint) return this.#utfCodepoint(v);
68+
if (v instanceof $BitArray) return this.#bit_array(v);
3969
if (v instanceof RegExp) return `//js(${v})`;
4070
if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`;
4171
if (v instanceof globalThis.Error) return `//js(${v.toString()})`;
@@ -52,9 +82,9 @@ class Echo$Inspector {
5282

5383
if (Array.isArray(v))
5484
return `#(${v.map((v) => this.inspect(v)).join(", ")})`;
55-
if (v instanceof List) return this.#list(v);
56-
if (v instanceof CustomType) return this.#customType(v);
57-
if (v instanceof Dict) return this.#dict(v);
85+
if (v instanceof $List) return this.#list(v);
86+
if (v instanceof $CustomType) return this.#customType(v);
87+
if (this.#isDict(v)) return this.#dict(v);
5888
if (v instanceof Set)
5989
return `//js(Set(${[...v].map((v) => this.inspect(v)).join(", ")}))`;
6090
return this.#object(v);
@@ -74,7 +104,13 @@ class Echo$Inspector {
74104
#dict(map) {
75105
let body = "dict.from_list([";
76106
let first = true;
107+
108+
let key_value_pairs = [];
77109
map.forEach((value, key) => {
110+
key_value_pairs.push([key, value]);
111+
});
112+
key_value_pairs.sort();
113+
key_value_pairs.forEach(([key, value]) => {
78114
if (!first) body = body + ", ";
79115
body = body + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")";
80116
first = false;
@@ -95,15 +131,15 @@ class Echo$Inspector {
95131
}
96132

97133
#list(list) {
98-
if (list instanceof Empty) {
134+
if (list instanceof $Empty) {
99135
return "[]";
100136
}
101137

102138
let char_out = 'charlist.from_string("';
103139
let list_out = "[";
104140

105141
let current = list;
106-
while (current instanceof NonEmpty) {
142+
while (current instanceof $NonEmpty) {
107143
let element = current.head;
108144
current = current.tail;
109145

@@ -171,11 +207,12 @@ class Echo$Inspector {
171207
}
172208

173209
#bit_array(bits) {
174-
let acc = "<<";
175210
if (bits.bitSize === 0) {
176-
return acc;
211+
return "<<>>";
177212
}
178213

214+
let acc = "<<";
215+
179216
for (let i = 0; i < bits.byteSize - 1; i++) {
180217
acc += bits.byteAt(i).toString();
181218
acc += ", ";

0 commit comments

Comments
 (0)