Skip to content

Commit 897eb28

Browse files
committed
Memorization of tuple subscrutinees
1 parent 1808130 commit 897eb28

File tree

5 files changed

+95
-127
lines changed

5 files changed

+95
-127
lines changed

hkmc2/shared/src/main/scala/hkmc2/semantics/Desugarer.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ object Desugarer:
2525

2626
class ScrutineeData:
2727
val classes: HashMap[ClassSymbol, List[BlockLocalSymbol]] = HashMap.empty
28-
val tuples: HashMap[Int, List[BlockLocalSymbol]] = HashMap.empty
28+
val tupleLead: HashMap[Int, BlockLocalSymbol] = HashMap.empty
29+
val tupleLast: HashMap[Int, BlockLocalSymbol] = HashMap.empty
2930
end Desugarer
3031

3132
class Desugarer(tl: TraceLogger, elaborator: Elaborator)
@@ -72,10 +73,13 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
7273
val arity = cls.defn.flatMap(_.paramsOpt.map(_.length)).getOrElse(0)
7374
(0 until arity).map(i => TempSymbol(nextUid, N, s"param$i")).toList
7475
})
75-
def getSubScrutinees(arity: Int): List[BlockLocalSymbol] =
76-
subScrutineeMap.getOrElseUpdate(symbol, new ScrutineeData).tuples.getOrElseUpdate(arity, {
77-
(0 until arity).map(i => TempSymbol(nextUid, N, s"elem$i")).toList
78-
})
76+
def getTupleLeadSubScrutinee(index: Int): BlockLocalSymbol =
77+
val data = subScrutineeMap.getOrElseUpdate(symbol, new ScrutineeData)
78+
data.tupleLead.getOrElseUpdate(index, TempSymbol(nextUid, N, s"first$index"))
79+
def getTupleLastSubScrutinee(index: Int): BlockLocalSymbol =
80+
val data = subScrutineeMap.getOrElseUpdate(symbol, new ScrutineeData)
81+
data.tupleLast.getOrElseUpdate(index, TempSymbol(nextUid, N, s"last$index"))
82+
7983

8084
def default: Split => Sequel = split => _ => split
8185

@@ -407,6 +411,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
407411
// 3. A fixed number of trailing patterns.
408412
val (lead, rest) = args.foldLeft[(Ls[Tree], Opt[(Opt[Tree], Ls[Tree])])]((Nil, N)):
409413
case ((lead, N), Jux(Ident(".."), pat)) => (lead, S((S(pat), Nil)))
414+
case ((lead, N), App(Ident(".."), TyTup(tys))) => (lead, S((S(Tup(tys)), Nil)))
410415
case ((lead, N), Ident("..")) => (lead, S((N, Nil)))
411416
case ((lead, N), pat) => (lead :+ pat, N)
412417
case ((lead, S((rest, last))), pat) => (lead, S((rest, last :+ pat)))
@@ -423,7 +428,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
423428
val (wrapLast, reversedLastMatches) = last.reverseIterator.zipWithIndex
424429
.foldLeft[(Split => Split, Ls[(BlockLocalSymbol, Tree)])]((identity, Nil)):
425430
case ((wrapInner, matches), (pat, lastIndex)) =>
426-
val sym = TempSymbol(nextUid, N, s"last$lastIndex")
431+
val sym = scrutSymbol.getTupleLastSubScrutinee(lastIndex)
427432
val wrap = (split: Split) =>
428433
Split.Let(sym, app(tupleGet(using ctx).ref((Ident("tupleGet"): Ident).withLoc(pat.toLoc)), tup(fld(ref), fld(int(-1 - lastIndex))), sym), wrapInner(split))
429434
(wrap, (sym, pat) :: matches)
@@ -438,7 +443,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
438443
case N => (identity: Split => Split, Nil)
439444
val (wrap, matches) = lead.zipWithIndex.foldRight((wrapRest, restMatches)):
440445
case ((pat, i), (wrapInner, matches)) =>
441-
val sym = TempSymbol(nextUid, N, s"first$i")
446+
val sym = scrutSymbol.getTupleLeadSubScrutinee(i)
442447
val wrap = (split: Split) => Split.Let(sym, Term.Sel(ref, Ident(s"$i"))(N), wrapInner(split))
443448
(wrap, (sym, pat) :: matches)
444449
Branch(

hkmc2/shared/src/test/mlscript/ucs/normalization/UnifySubScrutinees.mls

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ fun sum(acc, xs) =
4343
//│ > xs@30 is Cons($param0@31, $param1@32) and
4444
//│ > let x@33 = $param0@31#0
4545
//│ > let xs@34 = $param1@32#0
46-
//│ > else globalThis:block#3#666.sum‹member:sum›(builtin:+#96(acc@29#666, x@33#666), xs@34#666)
46+
//│ > else globalThis:block#3#666.sum‹member:sum›(builtin:+#99(acc@29#666, x@33#666), xs@34#666)
4747
//│ > xs@30 is Nil then acc@29#666
4848
//│ Normalized:
4949
//│ > if
5050
//│ > xs@30 is Cons($param0@31, $param1@32) and
5151
//│ > let x@33 = $param0@31#0
5252
//│ > let xs@34 = $param1@32#0
53-
//│ > else globalThis:block#3#666.sum‹member:sum›(builtin:+#96(acc@29#666, x@33#666), xs@34#666)
53+
//│ > else globalThis:block#3#666.sum‹member:sum›(builtin:+#99(acc@29#666, x@33#666), xs@34#666)
5454
//│ > xs@30 is Nil then acc@29#666
5555

5656
:todo
@@ -70,7 +70,7 @@ fun test(xs) =
7070
//│ > let x@52 = $param0@45#1
7171
//│ > $param1@46 is Cons($param0@48, $param1@49) and
7272
//│ > let y@53 = $param0@48#1
73-
//│ > $param1@49 is Nil then builtin:+#97(x@52#666, y@53#666)
73+
//│ > $param1@49 is Nil then builtin:+#100(x@52#666, y@53#666)
7474
//│ > xs@39 is Some($param0@40) and $param0@40 is Cons($param0@41, $param1@42) and $param0@41 is "mul" and $param1@42 is Cons($param0@45, $param1@46) and
7575
//│ > let x@47 = $param0@45#0
7676
//│ > $param1@46 is Cons($param0@48, $param1@49) and
@@ -89,7 +89,7 @@ fun test(xs) =
8989
//│ > let x@52 = $param0@45#1
9090
//│ > $param1@46 is Cons($param0@48, $param1@49) and
9191
//│ > let y@53 = $param0@48#1
92-
//│ > $param1@49 is Nil then builtin:+#97(x@52#666, y@53#666)
92+
//│ > $param1@49 is Nil then builtin:+#100(x@52#666, y@53#666)
9393
//│ > $param0@41 is "mul" and $param1@42 is Cons($param0@45, $param1@46) and
9494
//│ > let x@47 = $param0@45#0
9595
//│ > $param1@46 is Cons($param0@48, $param1@49) and

hkmc2/shared/src/test/mlscript/ucs/normalization/UnifyTupleElements.mls

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ fun add_6(x, y) =
1414
//│ > if
1515
//│ > let $scrut@16 = [x@14#666, y@15#666]
1616
//│ > $scrut@16 is []=2 and
17-
//│ > let $first0@28 = $scrut@16#10.0
18-
//│ > let $first1@27 = $scrut@16#11.1
19-
//│ > $first0@28 is Some($param0@29) and
20-
//│ > let xv@30 = $param0@29#0
21-
//│ > $first1@27 is Some($param0@31) and
22-
//│ > let yv@32 = $param0@31#0
23-
//│ > else builtin:+#95(xv@30#666, yv@32#666)
17+
//│ > let $first0@18 = $scrut@16#10.0
18+
//│ > let $first1@17 = $scrut@16#11.1
19+
//│ > $first0@18 is Some($param0@21) and
20+
//│ > let xv@23 = $param0@21#1
21+
//│ > $first1@17 is Some($param0@19) and
22+
//│ > let yv@24 = $param0@19#1
23+
//│ > else builtin:+#98(xv@23#666, yv@24#666)
2424
//│ > $scrut@16 is []=2 and
25-
//│ > let $first0@24 = $scrut@16#7.0
26-
//│ > let $first1@23 = $scrut@16#8.1
27-
//│ > $first0@24 is Some($param0@25) and
28-
//│ > let xv@26 = $param0@25#0
29-
//│ > $first1@23 is None then xv@26#666
25+
//│ > let $first0@18 = $scrut@16#7.0
26+
//│ > let $first1@17 = $scrut@16#8.1
27+
//│ > $first0@18 is Some($param0@21) and
28+
//│ > let xv@22 = $param0@21#0
29+
//│ > $first1@17 is None then xv@22#666
3030
//│ > $scrut@16 is []=2 and
31-
//│ > let $first0@20 = $scrut@16#4.0
32-
//│ > let $first1@19 = $scrut@16#5.1
33-
//│ > $first0@20 is None and $first1@19 is Some($param0@21) and
34-
//│ > let yv@22 = $param0@21#0
35-
//│ > else yv@22#666
31+
//│ > let $first0@18 = $scrut@16#4.0
32+
//│ > let $first1@17 = $scrut@16#5.1
33+
//│ > $first0@18 is None and $first1@17 is Some($param0@19) and
34+
//│ > let yv@20 = $param0@19#0
35+
//│ > else yv@20#666
3636
//│ > $scrut@16 is []=2 and
3737
//│ > let $first0@18 = $scrut@16#1.0
3838
//│ > let $first1@17 = $scrut@16#2.1
@@ -41,68 +41,17 @@ fun add_6(x, y) =
4141
//│ > if
4242
//│ > let $scrut@16 = [x@14#666, y@15#666]
4343
//│ > $scrut@16 is []=2 and
44-
//│ > let $first0@28 = $scrut@16#10.0
45-
//│ > let $first1@27 = $scrut@16#11.1
46-
//│ > $first0@28 is Some($param0@29) and
47-
//│ > let xv@30 = $param0@29#0
48-
//│ > $first1@27 is Some($param0@31) and
49-
//│ > let yv@32 = $param0@31#0
50-
//│ > else builtin:+#95(xv@30#666, yv@32#666)
51-
//│ > let $first0@24 = $scrut@16#7.0
52-
//│ > let $first1@23 = $scrut@16#8.1
53-
//│ > $first0@24 is Some($param0@25) and
54-
//│ > let xv@26 = $param0@25#0
55-
//│ > $first1@23 is None then xv@26#666
56-
//│ > let $first0@20 = $scrut@16#4.0
57-
//│ > let $first1@19 = $scrut@16#5.1
58-
//│ > $first0@20 is None and
59-
//│ > $first1@19 is Some($param0@21) and
60-
//│ > let yv@22 = $param0@21#0
61-
//│ > else yv@22#666
62-
//│ > let $first0@18 = $scrut@16#1.0
63-
//│ > let $first1@17 = $scrut@16#2.1
64-
//│ > $first0@18 is None $first1@17 is None then 0
65-
//│ > let $first0@18 = $scrut@16#1.0
66-
//│ > let $first1@17 = $scrut@16#2.1
67-
//│ > $first0@18 is None $first1@17 is None then 0
68-
//│ > let $first0@20 = $scrut@16#4.0
69-
//│ > let $first1@19 = $scrut@16#5.1
70-
//│ > $first0@20 is None and
71-
//│ > $first1@19 is Some($param0@21) and
72-
//│ > let yv@22 = $param0@21#0
73-
//│ > else yv@22#666
74-
//│ > let $first0@18 = $scrut@16#1.0
75-
//│ > let $first1@17 = $scrut@16#2.1
76-
//│ > $first0@18 is None $first1@17 is None then 0
77-
//│ > let $first0@18 = $scrut@16#1.0
78-
//│ > let $first1@17 = $scrut@16#2.1
79-
//│ > $first0@18 is None $first1@17 is None then 0
80-
//│ > let $first0@24 = $scrut@16#7.0
81-
//│ > let $first1@23 = $scrut@16#8.1
82-
//│ > $first0@24 is Some($param0@25) and
83-
//│ > let xv@26 = $param0@25#0
84-
//│ > $first1@23 is None then xv@26#666
85-
//│ > let $first0@20 = $scrut@16#4.0
86-
//│ > let $first1@19 = $scrut@16#5.1
87-
//│ > $first0@20 is None and
88-
//│ > $first1@19 is Some($param0@21) and
89-
//│ > let yv@22 = $param0@21#0
90-
//│ > else yv@22#666
91-
//│ > let $first0@18 = $scrut@16#1.0
92-
//│ > let $first1@17 = $scrut@16#2.1
93-
//│ > $first0@18 is None $first1@17 is None then 0
94-
//│ > let $first0@18 = $scrut@16#1.0
95-
//│ > let $first1@17 = $scrut@16#2.1
96-
//│ > $first0@18 is None $first1@17 is None then 0
97-
//│ > let $first0@20 = $scrut@16#4.0
98-
//│ > let $first1@19 = $scrut@16#5.1
99-
//│ > $first0@20 is None and
100-
//│ > $first1@19 is Some($param0@21) and
101-
//│ > let yv@22 = $param0@21#0
102-
//│ > else yv@22#666
103-
//│ > let $first0@18 = $scrut@16#1.0
104-
//│ > let $first1@17 = $scrut@16#2.1
105-
//│ > $first0@18 is None $first1@17 is None then 0
106-
//│ > let $first0@18 = $scrut@16#1.0
107-
//│ > let $first1@17 = $scrut@16#2.1
108-
//│ > $first0@18 is None $first1@17 is None then 0
44+
//│ > let $first0@18 = $scrut@16#10.0
45+
//│ > let $first1@17 = $scrut@16#11.1
46+
//│ > $first0@18 is Some($param0@21) and
47+
//│ > let xv@23 = $param0@21#1
48+
//│ > $first1@17 is Some($param0@19) and
49+
//│ > let yv@24 = $param0@19#1
50+
//│ > else builtin:+#98(xv@23#666, yv@24#666)
51+
//│ > let xv@22 = $param0@21#0
52+
//│ > $first1@17 is None then xv@22#666
53+
//│ > $first0@18 is None and
54+
//│ > $first1@17 is Some($param0@19) and
55+
//│ > let yv@20 = $param0@19#0
56+
//│ > else yv@20#666
57+
//│ > $first1@17 is None then 0

hkmc2/shared/src/test/mlscript/ucs/patterns/RestTuple.mls

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,26 +104,41 @@ foo(["boom"])
104104
fun nested_tuple_patterns(xs) = if xs is
105105
[x, ..[y, z], w] then x + y + z + w
106106
[] then 0
107-
//│ ╔══[ERROR] Unrecognized pattern.
108-
//│ ║ l.105: [x, ..[y, z], w] then x + y + z + w
109-
//│ ╙── ^^^^^^^^
110107
//│ Desugared:
111108
//│ > if
112-
//│ > xs@78 is []=3 and
109+
//│ > xs@78 is []>=2 and
113110
//│ > let $first0@81 = xs@78#2.0
114-
//│ > let $first1@80 = xs@78#3.1
115-
//│ > let $first2@79 = xs@78#4.2
111+
//│ > let $rest@80 = globalThis:block#1#666.tupleSlice‹member:tupleSlice›(xs@78#3, 1, 1)
112+
//│ > let $last0@79 = globalThis:block#1#666.tupleGet‹member:tupleGet›(xs@78#4, -1)
116113
//│ > let x@82 = $first0@81#0
114+
//│ > $rest@80 is []=2 and
115+
//│ > let $first0@84 = $rest@80#1.0
116+
//│ > let $first1@83 = $rest@80#2.1
117+
//│ > let y@85 = $first0@84#0
118+
//│ > let z@86 = $first1@83#0
119+
//│ > let w@87 = $last0@79#0
120+
//│ > else builtin:+#95(builtin:+#96(builtin:+#97(x@82#666, y@85#666), z@86#666), w@87#666)
117121
//│ > xs@78 is []=0 then 0
118122
//│ JS:
119123
//│ function nested_tuple_patterns(xs) {
120-
//│ let first2, first1, first0, x;
121-
//│ if (Array.isArray(xs) && xs.length === 3) {
124+
//│ let last0, rest, first0, x, first1, first01, y, z, w, tmp, tmp1;
125+
//│ if (Array.isArray(xs) && xs.length >= 2) {
122126
//│ first0 = xs[0];
123-
//│ first1 = xs[1];
124-
//│ first2 = xs[2];
127+
//│ rest = globalThis.tupleSlice(xs, 1, 1);
128+
//│ last0 = globalThis.tupleGet(xs, -1);
125129
//│ x = first0;
126-
//│ throw new globalThis.Error("match error")
130+
//│ if (Array.isArray(rest) && rest.length === 2) {
131+
//│ first01 = rest[0];
132+
//│ first1 = rest[1];
133+
//│ y = first01;
134+
//│ z = first1;
135+
//│ w = last0;
136+
//│ tmp = x + y;
137+
//│ tmp1 = tmp + z;
138+
//│ return tmp1 + w
139+
//│ } else {
140+
//│ throw new globalThis.Error("match error")
141+
//│ }
127142
//│ } else {
128143
//│ if (Array.isArray(xs) && xs.length === 0) {
129144
//│ return 0

hkmc2/shared/src/test/mlscript/ucs/patterns/SimpleTuple.mls

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,15 @@ fun multiple_checks(xs) =
115115
//│ > if
116116
//│ > xs@105 is []=0 then 0
117117
//│ > xs@105 is []=1 and
118-
//│ > let $first0@121 = xs@105#8.0
119-
//│ > let x@122 = $first0@121#0
120-
//│ > else builtin:+#92(x@122#666, 1)
118+
//│ > let $first0@108 = xs@105#8.0
119+
//│ > let x@119 = $first0@108#2
120+
//│ > else builtin:+#92(x@119#666, 1)
121121
//│ > xs@105 is []=2 and
122-
//│ > let $first0@116 = xs@105#5.0
123-
//│ > let $first1@115 = xs@105#6.1
124-
//│ > let x@117 = $first0@116#0
125-
//│ > let y@118 = $first1@115#0
126-
//│ > else builtin:+#90(builtin:+#91(x@117#666, y@118#666), 2)
122+
//│ > let $first0@108 = xs@105#5.0
123+
//│ > let $first1@107 = xs@105#6.1
124+
//│ > let x@115 = $first0@108#1
125+
//│ > let y@116 = $first1@107#1
126+
//│ > else builtin:+#90(builtin:+#91(x@115#666, y@116#666), 2)
127127
//│ > xs@105 is []=3 and
128128
//│ > let $first0@108 = xs@105#1.0
129129
//│ > let $first1@107 = xs@105#2.1
@@ -160,19 +160,18 @@ fun multiple_checks(xs) =
160160
[None] then 0
161161
//│ Desugared:
162162
//│ > if
163-
//│ > xs@150 is []=1 and
164-
//│ > let $first0@152 = xs@150#3.0
165-
//│ > $first0@152 is Some($param0@153) and
166-
//│ > let x@154 = $param0@153#0
167-
//│ > else builtin:+#93(x@154#666, 1)
168-
//│ > xs@150 is []=1 and
169-
//│ > let $first0@151 = xs@150#1.0
170-
//│ > $first0@151 is None then 0
163+
//│ > xs@147 is []=1 and
164+
//│ > let $first0@148 = xs@147#3.0
165+
//│ > $first0@148 is Some($param0@149) and
166+
//│ > let x@150 = $param0@149#0
167+
//│ > else builtin:+#93(x@150#666, 1)
168+
//│ > xs@147 is []=1 and
169+
//│ > let $first0@148 = xs@147#1.0
170+
//│ > $first0@148 is None then 0
171171
//│ Normalized:
172-
//│ > if xs@150 is []=1 and
173-
//│ > let $first0@152 = xs@150#3.0
174-
//│ > $first0@152 is Some($param0@153) and
175-
//│ > let x@154 = $param0@153#0
176-
//│ > else builtin:+#93(x@154#666, 1)
177-
//│ > let $first0@151 = xs@150#1.0
178-
//│ > $first0@151 is None then 0
172+
//│ > if xs@147 is []=1 and
173+
//│ > let $first0@148 = xs@147#3.0
174+
//│ > $first0@148 is Some($param0@149) and
175+
//│ > let x@150 = $param0@149#0
176+
//│ > else builtin:+#93(x@150#666, 1)
177+
//│ > $first0@148 is None then 0

0 commit comments

Comments
 (0)