Skip to content

Commit 184b96e

Browse files
committed
Clean up the desugarer
1 parent dc5b8de commit 184b96e

File tree

4 files changed

+64
-79
lines changed

4 files changed

+64
-79
lines changed

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

Lines changed: 32 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,35 @@ class Desugarer(val elaborator: Elaborator)(using UnderCtx)
176176
nominate(ctx, term(coda)(using ctx)):
177177
expandMatch(_, pat, sequel)(fallback)
178178
expandMatch(scrutSymbol, headPattern, tailSplit)(fallback)
179+
180+
def termSplit(trees: Ls[Tree], finish: Term => Term): Split => Sequel =
181+
trees.foldRight(default): (t, elabFallback) =>
182+
t match
183+
case LetLike(`let`, ident @ Ident(_), N, N) => ???
184+
case LetLike(`let`, ident @ Ident(_), S(termTree), N) => fallback => ctx => trace(
185+
pre = s"termSplit: let ${ident.name} = $termTree",
186+
post = (res: Split) => s"termSplit: let >>> $res"
187+
):
188+
val sym = VarSymbol(ident)
189+
val fallbackCtx = ctx + (ident.name -> sym)
190+
Split.Let(sym, term(termTree)(using ctx), elabFallback(fallback)(fallbackCtx)).withLocOf(t)
191+
case Modified(Keyword.`do`, doLoc, computation) => fallback => ctx => trace(
192+
pre = s"termSplit: do $computation",
193+
post = (res: Split) => s"termSplit: else >>> $res"
194+
):
195+
val sym = TempSymbol(N, "doTemp")
196+
Split.Let(sym, term(computation)(using ctx), elabFallback(fallback)(ctx)).withLocOf(t)
197+
case Modified(Keyword.`else`, elsLoc, default) => fallback => ctx => trace(
198+
pre = s"termSplit: else $default",
199+
post = (res: Split) => s"termSplit: else >>> $res"
200+
):
201+
// TODO: report `rest` as unreachable
202+
Split.default(term(default)(using ctx)).withLocOf(t)
203+
case branch => fallback => ctx => trace(
204+
pre = s"termSplit: $branch",
205+
post = (res: Split) => s"termSplit >>> $res"
206+
):
207+
termSplit(branch, finish)(elabFallback(fallback)(ctx))(ctx)
179208

180209
/** Desugar a _term split_ (TS) into a _split_ of core abstract syntax.
181210
* @param tree the tree representing the term split.
@@ -187,34 +216,7 @@ class Desugarer(val elaborator: Elaborator)(using UnderCtx)
187216
def termSplit(tree: Tree, finish: Term => Term): Split => Sequel =
188217
log(s"termSplit: $tree")
189218
tree match
190-
case blk: Block =>
191-
blk.desugStmts.foldRight(default): (t, elabFallback) =>
192-
t match
193-
case LetLike(`let`, ident @ Ident(_), N, N) => ???
194-
case LetLike(`let`, ident @ Ident(_), S(termTree), N) => fallback => ctx => trace(
195-
pre = s"termSplit: let ${ident.name} = $termTree",
196-
post = (res: Split) => s"termSplit: let >>> $res"
197-
):
198-
val sym = VarSymbol(ident)
199-
val fallbackCtx = ctx + (ident.name -> sym)
200-
Split.Let(sym, term(termTree)(using ctx), elabFallback(fallback)(fallbackCtx)).withLocOf(t)
201-
case Modified(Keyword.`do`, doLoc, computation) => fallback => ctx => trace(
202-
pre = s"termSplit: do $computation",
203-
post = (res: Split) => s"termSplit: else >>> $res"
204-
):
205-
val sym = TempSymbol(N, "doTemp")
206-
Split.Let(sym, term(computation)(using ctx), elabFallback(fallback)(ctx)).withLocOf(t)
207-
case Modified(Keyword.`else`, elsLoc, default) => fallback => ctx => trace(
208-
pre = s"termSplit: else $default",
209-
post = (res: Split) => s"termSplit: else >>> $res"
210-
):
211-
// TODO: report `rest` as unreachable
212-
Split.default(term(default)(using ctx)).withLocOf(t)
213-
case branch => fallback => ctx => trace(
214-
pre = s"termSplit: $branch",
215-
post = (res: Split) => s"termSplit >>> $res"
216-
):
217-
termSplit(branch, finish)(elabFallback(fallback)(ctx))(ctx).withLocOf(t)
219+
case blk: Block => termSplit(blk.desugStmts, finish)
218220
case coda is rhs => fallback => ctx =>
219221
nominate(ctx, finish(term(coda)(using ctx))):
220222
patternSplit(rhs, _)(fallback)
@@ -246,6 +248,7 @@ class Desugarer(val elaborator: Elaborator)(using UnderCtx)
246248
):
247249
nominate(ctx, finish(term(headCoda)(using ctx))):
248250
expandMatch(_, headPattern, tailSplit)(fallback)
251+
// Handle binary operators.
249252
case tree @ OpApp(lhs, opIdent @ Ident(opName), rhss) => fallback => ctx => trace(
250253
pre = s"termSplit: after op <<< $opName",
251254
post = (res: Split) => s"termSplit: after op >>> $res"
@@ -261,35 +264,10 @@ class Desugarer(val elaborator: Elaborator)(using UnderCtx)
261264
val arguments = Term.Tup(first :: second :: Nil)(Tree.DummyTup)
262265
val joint = FlowSymbol("‹applied-result›")
263266
Term.App(opRef, arguments)(Tree.DummyApp, N, joint)
264-
rhss match
265-
case rhs :: Nil => termSplit(rhs, finishInner)(fallback)
266-
case _ => ???
267-
case tree @ App(opIdent @ Ident(opName), rawTup @ Tup(lhs :: rhs :: Nil)) => fallback => ctx => trace(
268-
pre = s"termSplit: after op <<< $opName",
269-
post = (res: Split) => s"termSplit: after op >>> $res"
270-
):
271-
// Resolve the operator.
272-
val opRef = term(opIdent)
273-
// Elaborate and finish the LHS. Nominate the LHS if necessary.
274-
nominate(ctx, finish(term(lhs)(using ctx))): lhsSymbol =>
275-
// Compose a function that takes the RHS and finishes the application.
276-
val finishInner = (rhsTerm: Term) =>
277-
val first = Fld(FldFlags.empty, lhsSymbol.ref(/* FIXME ident? */), N)
278-
val second = Fld(FldFlags.empty, rhsTerm, N)
279-
val arguments = Term.Tup(first :: second :: Nil)(rawTup)
280-
val joint = FlowSymbol("‹applied-result›")
281-
Term.App(opRef, arguments)(tree, N, joint)
282-
termSplit(rhs, finishInner)(fallback)
267+
termSplit(rhss, finishInner)(fallback)
283268
// Handle operator splits.
284269
case tree @ OpSplit(lhs, rhss) => fallback => ctx =>
285270
nominate(ctx, finish(term(lhs)(using ctx))): vs =>
286-
val mkInnerFinish = (op: Term) => (rhsTerm: Term) =>
287-
val first = Fld(FldFlags.empty, vs.ref(/* FIXME ident? */), N)
288-
val second = Fld(FldFlags.empty, rhsTerm, N)
289-
val rawTup = Tup(lhs :: Nil): Tup // <-- loc might be wrong
290-
val arguments = Term.Tup(first :: second :: Nil)(rawTup)
291-
val joint = FlowSymbol("‹applied-result›")
292-
Term.App(op, arguments)(Tree.DummyApp, N, joint)
293271
rhss.foldRight(Function.const(fallback): Sequel): (branch, elabFallback) =>
294272
branch match
295273
case LetLike(`let`, pat, termTree, N) => ctx =>

hkmc2/shared/src/test/mlscript/backlog/UCS.mls

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,12 @@ else
8888
1
8989
//│ ╔══[ERROR] The following branches are unreachable.
9090
//│ ╟── Because the previous split is full.
91-
//│ ║ l.85: if audits.has(1) === true do
92-
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^
9391
//│ ║ l.86: print("ok")
94-
//│ ╙── ^^^^^^^^^^^^^
92+
//│ ║ ^^^^^^^^^^^
93+
//│ ║ l.87: else
94+
//│ ║ ^^^^
95+
//│ ║ l.88: 1
96+
//│ ╙── ^^^
9597
//│ = 1
9698

9799
// ——— ——— ———
@@ -185,10 +187,10 @@ let foo =
185187
case
186188
Tuple(...elements) then elements
187189
//│ ╔══[ERROR] mismatched arity: expect 3, found 1
188-
//│ ║ l.186: Tuple(...elements) then elements
190+
//│ ║ l.187: Tuple(...elements) then elements
189191
//│ ╙── ^^^^^^^^^^^^^^^^^^
190192
//│ ╔══[ERROR] Unrecognized pattern (spread)
191-
//│ ║ l.186: Tuple(...elements) then elements
193+
//│ ║ l.187: Tuple(...elements) then elements
192194
//│ ╙── ^^^^^^^^
193195
//│ foo = [function]
194196

@@ -206,20 +208,20 @@ fun foo(x) = if x is Foo.
206208
Bar then "Bar"
207209
Foo then "Foo"
208210
//│ ╔══[ERROR] Unrecognized pattern split.
209-
//│ ║ l.205: fun foo(x) = if x is Foo.
211+
//│ ║ l.206: fun foo(x) = if x is Foo.
210212
//│ ║ ^^^^
211-
//│ ║ l.206: Bar then "Bar"
213+
//│ ║ l.207: Bar then "Bar"
212214
//│ ╙── ^^
213215

214216
fun foo(x) = if x is Foo
215217
.Bar then "Bar"
216218
.Foo then "Foo"
217219
//│ ╔══[ERROR] Unrecognized pattern split.
218-
//│ ║ l.214: fun foo(x) = if x is Foo
220+
//│ ║ l.215: fun foo(x) = if x is Foo
219221
//│ ║ ^^^
220-
//│ ║ l.215: .Bar then "Bar"
222+
//│ ║ l.216: .Bar then "Bar"
221223
//│ ║ ^^^^^^^^^^^^^^^^^
222-
//│ ║ l.216: .Foo then "Foo"
224+
//│ ║ l.217: .Foo then "Foo"
223225
//│ ╙── ^^^^^^^^^^^^^^^^^
224226

225227
// ——— ——— ———

hkmc2/shared/src/test/mlscript/ucs/future/AppSplits.mls

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
fun foo(x) = x > 1
66

77
:todo
8-
:pe
98
:e
109
if foo of
1110
0 then "a"
1211
1 then "b"
13-
//│ /!!!\ Uncaught error: scala.MatchError: InfixApp(IntLit(0),keyword 'then',StrLit(a)) (of class hkmc2.syntax.Tree$InfixApp)
12+
//│ ╔══[ERROR] Unrecognized term split (application).
13+
//│ ║ l.9: if foo of
14+
//│ ║ ^^^^^^
15+
//│ ║ l.10: 0 then "a"
16+
//│ ║ ^^^^^^^^^^^^
17+
//│ ║ l.11: 1 then "b"
18+
//│ ╙── ^^^^^^^^^^^^
1419

1520
:todo
1621
:pe
@@ -19,12 +24,12 @@ if foo of 1,
1924
0 then "a"
2025
1 then "b"
2126
//│ ╔══[PARSE ERROR] Expected an expression; found block instead
22-
//│ ║ l.19: 0 then "a"
27+
//│ ║ l.24: 0 then "a"
2328
//│ ╙── ^
2429
//│ ╔══[ERROR] Unrecognized term split (juxtaposition).
25-
//│ ║ l.18: if foo of 1,
30+
//│ ║ l.23: if foo of 1,
2631
//│ ║ ^^^^^^^^^
27-
//│ ║ l.19: 0 then "a"
32+
//│ ║ l.24: 0 then "a"
2833
//│ ╙── ^^
2934

3035
:todo
@@ -34,9 +39,9 @@ if foo
3439
(0) then "a"
3540
(1) then "b"
3641
//│ ╔══[ERROR] Unrecognized term split (juxtaposition).
37-
//│ ║ l.33: if foo
42+
//│ ║ l.38: if foo
3843
//│ ║ ^^^
39-
//│ ║ l.34: (0) then "a"
44+
//│ ║ l.39: (0) then "a"
4045
//│ ╙── ^^
4146

4247

hkmc2/shared/src/test/mlscript/ucs/syntax/SimpleUCS.mls

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,13 @@ fun f(x, y, b) =
125125
Some(xv) and b then xv + b
126126
_ then "roll"
127127
//│ ╔══[PARSE ERROR] Expected start of statement in this position; found 'is' keyword instead
128-
//│ ║ l.124: is None then "bruh"
128+
//│ ║ l.136: is None then "bruh"
129129
//│ ╙── ^^
130130
//│ ╔══[PARSE ERROR] Unexpected identifier here
131-
//│ ║ l.124: is None then "bruh"
131+
//│ ║ l.136: is None then "bruh"
132132
//│ ╙── ^^^^
133133
//│ ╔══[ERROR] Unrecognized pattern split.
134-
//│ ║ l.124: is None then "bruh"
134+
//│ ║ l.136: is None then "bruh"
135135
//│ ╙── ^^^^
136136

137137
:fixme
@@ -143,13 +143,13 @@ fun g(x, y, b) =
143143
Some(xv) and b then xv + b
144144
_ then "roll"
145145
//│ ╔══[PARSE ERROR] Expected start of statement in this position; found 'is' keyword instead
146-
//│ ║ l.142: is None then "bruh"
146+
//│ ║ l.154: is None then "bruh"
147147
//│ ╙── ^^
148148
//│ ╔══[PARSE ERROR] Unexpected identifier here
149-
//│ ║ l.142: is None then "bruh"
149+
//│ ║ l.154: is None then "bruh"
150150
//│ ╙── ^^^^
151151
//│ ╔══[ERROR] Unrecognized pattern split.
152-
//│ ║ l.142: is None then "bruh"
152+
//│ ║ l.154: is None then "bruh"
153153
//│ ╙── ^^^^
154154

155155

@@ -212,9 +212,9 @@ fun f(x) =
212212
0 ::
213213
Nil() then "oh"
214214
//│ ╔══[ERROR] Unrecognized pattern split.
215-
//│ ║ l.212: 0 ::
215+
//│ ║ l.224: 0 ::
216216
//│ ║ ^^^^
217-
//│ ║ l.213: Nil() then "oh"
217+
//│ ║ l.225: Nil() then "oh"
218218
//│ ╙── ^^^^^^
219219

220220

0 commit comments

Comments
 (0)