Skip to content

Commit 49c854e

Browse files
authored
feat(stdlib)!: Handle printing of reference cycles (#1844)
* feat(stdlib)!: Handle printing of reference cycles * include boxes, arrays, improve average case perf * make types in test recursive
1 parent b3d68a4 commit 49c854e

File tree

2 files changed

+340
-33
lines changed

2 files changed

+340
-33
lines changed

compiler/test/suites/cycles.re

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
open Grain_tests.TestFramework;
2+
open Grain_tests.Runner;
3+
4+
describe("cyclic references", ({test, testSkip}) => {
5+
let test_or_skip =
6+
Sys.backend_type == Other("js_of_ocaml") ? testSkip : test;
7+
8+
let assertRun = makeRunner(test_or_skip);
9+
10+
assertRun(
11+
"cycles1",
12+
{|
13+
record rec A {
14+
mut a: Option<A>
15+
}
16+
let x = { a: None }
17+
x.a = Some(x)
18+
print(x)
19+
|},
20+
"<1> {\n a: Some(<cycle to <1>>)\n}\n",
21+
);
22+
assertRun(
23+
"cycles2",
24+
{|
25+
record rec A {
26+
val: Number,
27+
mut a: Option<A>
28+
}
29+
30+
let x = { val: 1, a: None }
31+
let y = { val: 2, a: None }
32+
let xOpt = Some(x)
33+
let yOpt = Some(y)
34+
x.a = yOpt
35+
y.a = xOpt
36+
37+
print([x, y])
38+
|},
39+
"[<1> {\n val: 1,\n a: Some({\n val: 2,\n a: Some(<cycle to <1>>)\n })\n}, <2> {\n val: 2,\n a: Some(<1> {\n val: 1,\n a: Some(<cycle to <2>>)\n })\n}]\n",
40+
);
41+
assertRun(
42+
"cycles3",
43+
{|
44+
record rec A {
45+
val: Number,
46+
mut next: Option<A>
47+
}
48+
49+
let a = { val: 1, next: None }
50+
let aOpt = Some(a)
51+
let b = Some({ val: 2, next: aOpt })
52+
let c = Some({ val: 3, next: b })
53+
let d = Some({ val: 4, next: c })
54+
let e = Some({ val: 5, next: d })
55+
a.next = e
56+
print([aOpt, b, c, d, e])
57+
|},
58+
{|[Some(<1> {
59+
val: 1,
60+
next: Some({
61+
val: 5,
62+
next: Some({
63+
val: 4,
64+
next: Some({
65+
val: 3,
66+
next: Some({
67+
val: 2,
68+
next: Some(<cycle to <1>>)
69+
})
70+
})
71+
})
72+
})
73+
}), Some(<2> {
74+
val: 2,
75+
next: Some(<1> {
76+
val: 1,
77+
next: Some({
78+
val: 5,
79+
next: Some({
80+
val: 4,
81+
next: Some({
82+
val: 3,
83+
next: Some(<cycle to <2>>)
84+
})
85+
})
86+
})
87+
})
88+
}), Some(<3> {
89+
val: 3,
90+
next: Some(<2> {
91+
val: 2,
92+
next: Some(<1> {
93+
val: 1,
94+
next: Some({
95+
val: 5,
96+
next: Some({
97+
val: 4,
98+
next: Some(<cycle to <3>>)
99+
})
100+
})
101+
})
102+
})
103+
}), Some(<4> {
104+
val: 4,
105+
next: Some(<3> {
106+
val: 3,
107+
next: Some(<2> {
108+
val: 2,
109+
next: Some(<1> {
110+
val: 1,
111+
next: Some({
112+
val: 5,
113+
next: Some(<cycle to <4>>)
114+
})
115+
})
116+
})
117+
})
118+
}), Some(<5> {
119+
val: 5,
120+
next: Some(<4> {
121+
val: 4,
122+
next: Some(<3> {
123+
val: 3,
124+
next: Some(<2> {
125+
val: 2,
126+
next: Some(<1> {
127+
val: 1,
128+
next: Some(<cycle to <5>>)
129+
})
130+
})
131+
})
132+
})
133+
})]
134+
|},
135+
);
136+
assertRun(
137+
"cycles4",
138+
{|
139+
enum rec R {
140+
Rec(Box<Option<R>>),
141+
}
142+
143+
let a = box(None)
144+
let b = Rec(a)
145+
a := Some(b)
146+
print(a)
147+
print(unbox(a))
148+
|},
149+
"<1> box(Some(Rec(<cycle to <1>>)))\nSome(Rec(<1> box(Some(Rec(<cycle to <1>>)))))\n",
150+
);
151+
assertRun(
152+
"cycles5",
153+
{|
154+
enum rec R {
155+
Rec(Array<Option<R>>),
156+
}
157+
158+
let a = [> None]
159+
let b = Rec(a)
160+
a[0] = Some(b)
161+
print(a)
162+
|},
163+
"<1> [> Some(Rec(<cycle to <1>>))]\n",
164+
);
165+
});

0 commit comments

Comments
 (0)