Skip to content

Commit d65804e

Browse files
committed
Memorization of tuple subscrutinees
1 parent d4b5a09 commit d65804e

File tree

4 files changed

+91
-123
lines changed

4 files changed

+91
-123
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

@@ -413,6 +417,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
413417
// 3. A fixed number of trailing patterns.
414418
val (lead, rest) = args.foldLeft[(Ls[Tree], Opt[(Opt[Tree], Ls[Tree])])]((Nil, N)):
415419
case ((lead, N), Jux(Ident(".."), pat)) => (lead, S((S(pat), Nil)))
420+
case ((lead, N), App(Ident(".."), TyTup(tys))) => (lead, S((S(Tup(tys)), Nil)))
416421
case ((lead, N), Ident("..")) => (lead, S((N, Nil)))
417422
case ((lead, N), pat) => (lead :+ pat, N)
418423
case ((lead, S((rest, last))), pat) => (lead, S((rest, last :+ pat)))
@@ -429,7 +434,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
429434
val (wrapLast, reversedLastMatches) = last.reverseIterator.zipWithIndex
430435
.foldLeft[(Split => Split, Ls[(BlockLocalSymbol, Tree)])]((identity, Nil)):
431436
case ((wrapInner, matches), (pat, lastIndex)) =>
432-
val sym = TempSymbol(nextUid, N, s"last$lastIndex")
437+
val sym = scrutSymbol.getTupleLastSubScrutinee(lastIndex)
433438
val wrap = (split: Split) =>
434439
Split.Let(sym, app(tupleGet(using ctx).ref((Ident("tupleGet"): Ident).withLoc(pat.toLoc)), tup(fld(ref), fld(int(-1 - lastIndex))), sym), wrapInner(split))
435440
(wrap, (sym, pat) :: matches)
@@ -444,7 +449,7 @@ class Desugarer(tl: TraceLogger, elaborator: Elaborator)
444449
case N => (identity: Split => Split, Nil)
445450
val (wrap, matches) = lead.zipWithIndex.foldRight((wrapRest, restMatches)):
446451
case ((pat, i), (wrapInner, matches)) =>
447-
val sym = TempSymbol(nextUid, N, s"first$i")
452+
val sym = scrutSymbol.getTupleLeadSubScrutinee(i)
448453
val wrap = (split: Split) => Split.Let(sym, Term.Sel(ref, Ident(s"$i"))(N), wrapInner(split))
449454
(wrap, (sym, pat) :: matches)
450455
Branch(

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@34 = [x@32#666, y@33#666]
1616
//│ > $scrut@34 is []=2 and
17-
//│ > let $first0@46 = $scrut@34#10.0
18-
//│ > let $first1@45 = $scrut@34#11.1
19-
//│ > $first0@46 is Some($param0@47) and
20-
//│ > let xv@48 = $param0@47#0
21-
//│ > $first1@45 is Some($param0@49) and
22-
//│ > let yv@50 = $param0@49#0
23-
//│ > else globalThis:import#Prelude#666.+‹member:+›(xv@48#666, yv@50#666)
17+
//│ > let $first0@36 = $scrut@34#10.0
18+
//│ > let $first1@35 = $scrut@34#11.1
19+
//│ > $first0@36 is Some($param0@39) and
20+
//│ > let xv@41 = $param0@39#1
21+
//│ > $first1@35 is Some($param0@37) and
22+
//│ > let yv@42 = $param0@37#1
23+
//│ > else globalThis:import#Prelude#666.+‹member:+›(xv@41#666, yv@42#666)
2424
//│ > $scrut@34 is []=2 and
25-
//│ > let $first0@42 = $scrut@34#7.0
26-
//│ > let $first1@41 = $scrut@34#8.1
27-
//│ > $first0@42 is Some($param0@43) and
28-
//│ > let xv@44 = $param0@43#0
29-
//│ > $first1@41 is None then xv@44#666
25+
//│ > let $first0@36 = $scrut@34#7.0
26+
//│ > let $first1@35 = $scrut@34#8.1
27+
//│ > $first0@36 is Some($param0@39) and
28+
//│ > let xv@40 = $param0@39#0
29+
//│ > $first1@35 is None then xv@40#666
3030
//│ > $scrut@34 is []=2 and
31-
//│ > let $first0@38 = $scrut@34#4.0
32-
//│ > let $first1@37 = $scrut@34#5.1
33-
//│ > $first0@38 is None and $first1@37 is Some($param0@39) and
34-
//│ > let yv@40 = $param0@39#0
35-
//│ > else yv@40#666
31+
//│ > let $first0@36 = $scrut@34#4.0
32+
//│ > let $first1@35 = $scrut@34#5.1
33+
//│ > $first0@36 is None and $first1@35 is Some($param0@37) and
34+
//│ > let yv@38 = $param0@37#0
35+
//│ > else yv@38#666
3636
//│ > $scrut@34 is []=2 and
3737
//│ > let $first0@36 = $scrut@34#1.0
3838
//│ > let $first1@35 = $scrut@34#2.1
@@ -41,68 +41,17 @@ fun add_6(x, y) =
4141
//│ > if
4242
//│ > let $scrut@34 = [x@32#666, y@33#666]
4343
//│ > $scrut@34 is []=2 and
44-
//│ > let $first0@46 = $scrut@34#10.0
45-
//│ > let $first1@45 = $scrut@34#11.1
46-
//│ > $first0@46 is Some($param0@47) and
47-
//│ > let xv@48 = $param0@47#0
48-
//│ > $first1@45 is Some($param0@49) and
49-
//│ > let yv@50 = $param0@49#0
50-
//│ > else globalThis:import#Prelude#666.+‹member:+›(xv@48#666, yv@50#666)
51-
//│ > let $first0@42 = $scrut@34#7.0
52-
//│ > let $first1@41 = $scrut@34#8.1
53-
//│ > $first0@42 is Some($param0@43) and
54-
//│ > let xv@44 = $param0@43#0
55-
//│ > $first1@41 is None then xv@44#666
56-
//│ > let $first0@38 = $scrut@34#4.0
57-
//│ > let $first1@37 = $scrut@34#5.1
58-
//│ > $first0@38 is None and
59-
//│ > $first1@37 is Some($param0@39) and
60-
//│ > let yv@40 = $param0@39#0
61-
//│ > else yv@40#666
62-
//│ > let $first0@36 = $scrut@34#1.0
63-
//│ > let $first1@35 = $scrut@34#2.1
64-
//│ > $first0@36 is None $first1@35 is None then 0
65-
//│ > let $first0@36 = $scrut@34#1.0
66-
//│ > let $first1@35 = $scrut@34#2.1
67-
//│ > $first0@36 is None $first1@35 is None then 0
68-
//│ > let $first0@38 = $scrut@34#4.0
69-
//│ > let $first1@37 = $scrut@34#5.1
70-
//│ > $first0@38 is None and
71-
//│ > $first1@37 is Some($param0@39) and
72-
//│ > let yv@40 = $param0@39#0
73-
//│ > else yv@40#666
74-
//│ > let $first0@36 = $scrut@34#1.0
75-
//│ > let $first1@35 = $scrut@34#2.1
76-
//│ > $first0@36 is None $first1@35 is None then 0
77-
//│ > let $first0@36 = $scrut@34#1.0
78-
//│ > let $first1@35 = $scrut@34#2.1
79-
//│ > $first0@36 is None $first1@35 is None then 0
80-
//│ > let $first0@42 = $scrut@34#7.0
81-
//│ > let $first1@41 = $scrut@34#8.1
82-
//│ > $first0@42 is Some($param0@43) and
83-
//│ > let xv@44 = $param0@43#0
84-
//│ > $first1@41 is None then xv@44#666
85-
//│ > let $first0@38 = $scrut@34#4.0
86-
//│ > let $first1@37 = $scrut@34#5.1
87-
//│ > $first0@38 is None and
88-
//│ > $first1@37 is Some($param0@39) and
89-
//│ > let yv@40 = $param0@39#0
90-
//│ > else yv@40#666
91-
//│ > let $first0@36 = $scrut@34#1.0
92-
//│ > let $first1@35 = $scrut@34#2.1
93-
//│ > $first0@36 is None $first1@35 is None then 0
94-
//│ > let $first0@36 = $scrut@34#1.0
95-
//│ > let $first1@35 = $scrut@34#2.1
96-
//│ > $first0@36 is None $first1@35 is None then 0
97-
//│ > let $first0@38 = $scrut@34#4.0
98-
//│ > let $first1@37 = $scrut@34#5.1
99-
//│ > $first0@38 is None and
100-
//│ > $first1@37 is Some($param0@39) and
101-
//│ > let yv@40 = $param0@39#0
102-
//│ > else yv@40#666
103-
//│ > let $first0@36 = $scrut@34#1.0
104-
//│ > let $first1@35 = $scrut@34#2.1
105-
//│ > $first0@36 is None $first1@35 is None then 0
106-
//│ > let $first0@36 = $scrut@34#1.0
107-
//│ > let $first1@35 = $scrut@34#2.1
108-
//│ > $first0@36 is None $first1@35 is None then 0
44+
//│ > let $first0@36 = $scrut@34#10.0
45+
//│ > let $first1@35 = $scrut@34#11.1
46+
//│ > $first0@36 is Some($param0@39) and
47+
//│ > let xv@41 = $param0@39#1
48+
//│ > $first1@35 is Some($param0@37) and
49+
//│ > let yv@42 = $param0@37#1
50+
//│ > else globalThis:import#Prelude#666.+‹member:+›(xv@41#666, yv@42#666)
51+
//│ > let xv@40 = $param0@39#0
52+
//│ > $first1@35 is None then xv@40#666
53+
//│ > $first0@36 is None and
54+
//│ > $first1@35 is Some($param0@37) and
55+
//│ > let yv@38 = $param0@37#0
56+
//│ > else yv@38#666
57+
//│ > $first1@35 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@96 is []=3 and
109+
//│ > xs@96 is []>=2 and
113110
//│ > let $first0@99 = xs@96#2.0
114-
//│ > let $first1@98 = xs@96#3.1
115-
//│ > let $first2@97 = xs@96#4.2
111+
//│ > let $rest@98 = globalThis:block#1#666.tupleSlice‹member:tupleSlice›(xs@96#3, 1, 1)
112+
//│ > let $last0@97 = globalThis:block#1#666.tupleGet‹member:tupleGet›(xs@96#4, -1)
116113
//│ > let x@100 = $first0@99#0
114+
//│ > $rest@98 is []=2 and
115+
//│ > let $first0@102 = $rest@98#1.0
116+
//│ > let $first1@101 = $rest@98#2.1
117+
//│ > let y@103 = $first0@102#0
118+
//│ > let z@104 = $first1@101#0
119+
//│ > let w@105 = $last0@97#0
120+
//│ > else globalThis:import#Prelude#666.+‹member:+›(globalThis:import#Prelude#666.+‹member:+›(globalThis:import#Prelude#666.+‹member:+›(x@100#666, y@103#666), z@104#666), w@105#666)
117121
//│ > xs@96 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@123 is []=0 then 0
117117
//│ > xs@123 is []=1 and
118-
//│ > let $first0@139 = xs@123#8.0
119-
//│ > let x@140 = $first0@139#0
120-
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@140#666, 1)
118+
//│ > let $first0@126 = xs@123#8.0
119+
//│ > let x@137 = $first0@126#2
120+
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@137#666, 1)
121121
//│ > xs@123 is []=2 and
122-
//│ > let $first0@134 = xs@123#5.0
123-
//│ > let $first1@133 = xs@123#6.1
124-
//│ > let x@135 = $first0@134#0
125-
//│ > let y@136 = $first1@133#0
126-
//│ > else globalThis:import#Prelude#666.+‹member:+›(globalThis:import#Prelude#666.+‹member:+›(x@135#666, y@136#666), 2)
122+
//│ > let $first0@126 = xs@123#5.0
123+
//│ > let $first1@125 = xs@123#6.1
124+
//│ > let x@133 = $first0@126#1
125+
//│ > let y@134 = $first1@125#1
126+
//│ > else globalThis:import#Prelude#666.+‹member:+›(globalThis:import#Prelude#666.+‹member:+›(x@133#666, y@134#666), 2)
127127
//│ > xs@123 is []=3 and
128128
//│ > let $first0@126 = xs@123#1.0
129129
//│ > let $first1@125 = xs@123#2.1
@@ -160,19 +160,18 @@ fun multiple_checks(xs) =
160160
[None] then 0
161161
//│ Desugared:
162162
//│ > if
163-
//│ > xs@168 is []=1 and
164-
//│ > let $first0@170 = xs@168#3.0
165-
//│ > $first0@170 is Some($param0@171) and
166-
//│ > let x@172 = $param0@171#0
167-
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@172#666, 1)
168-
//│ > xs@168 is []=1 and
169-
//│ > let $first0@169 = xs@168#1.0
170-
//│ > $first0@169 is None then 0
163+
//│ > xs@165 is []=1 and
164+
//│ > let $first0@166 = xs@165#3.0
165+
//│ > $first0@166 is Some($param0@167) and
166+
//│ > let x@168 = $param0@167#0
167+
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@168#666, 1)
168+
//│ > xs@165 is []=1 and
169+
//│ > let $first0@166 = xs@165#1.0
170+
//│ > $first0@166 is None then 0
171171
//│ Normalized:
172-
//│ > if xs@168 is []=1 and
173-
//│ > let $first0@170 = xs@168#3.0
174-
//│ > $first0@170 is Some($param0@171) and
175-
//│ > let x@172 = $param0@171#0
176-
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@172#666, 1)
177-
//│ > let $first0@169 = xs@168#1.0
178-
//│ > $first0@169 is None then 0
172+
//│ > if xs@165 is []=1 and
173+
//│ > let $first0@166 = xs@165#3.0
174+
//│ > $first0@166 is Some($param0@167) and
175+
//│ > let x@168 = $param0@167#0
176+
//│ > else globalThis:import#Prelude#666.+‹member:+›(x@168#666, 1)
177+
//│ > $first0@166 is None then 0

0 commit comments

Comments
 (0)