@@ -9,7 +9,7 @@ import utils.TraceLogger
99import syntax .Literal
1010import Keyword .{as , and , `do` , `else` , is , let , `then` , where }
1111import collection .mutable .{HashMap , SortedSet }
12- import Elaborator .{ctx , Ctxl }
12+ import Elaborator .{ctx , Ctxl , UnderCtx }
1313import scala .annotation .targetName
1414import hkmc2 .semantics .ClassDef .Parameterized
1515
@@ -26,11 +26,11 @@ object Desugarer:
2626 val tupleLast : HashMap [Int , BlockLocalSymbol ] = HashMap .empty
2727end Desugarer
2828
29- class Desugarer (val elaborator : Elaborator )
29+ class Desugarer (val elaborator : Elaborator )( using UnderCtx )
3030 (using raise : Raise , state : Elaborator .State , c : Elaborator .Ctx ) extends DesugaringBase :
3131 import Desugarer .*
3232 import Elaborator .Ctx
33- import elaborator .term , elaborator .tl .*
33+ import elaborator .term , elaborator .subterm , elaborator . tl .*
3434
3535 given Ordering [Loc ] = Ordering .by: loc =>
3636 (loc.spanStart, loc.spanEnd)
@@ -126,7 +126,7 @@ class Desugarer(val elaborator: Elaborator)
126126 raise(ErrorReport (msg " only one branch is supported in shorthands " -> tree.toLoc :: Nil ))
127127 termSplitShorthands(branch, finish)(fallback)(ctx)
128128 case coda is rhs => fallback => ctx =>
129- nominate(ctx, finish(term (coda)(using ctx))):
129+ nominate(ctx, finish(subterm (coda)(using ctx))):
130130 patternSplitShorthands(rhs, _)(fallback)
131131 case matches => fallback =>
132132 // There are N > 0 conjunct matches. We use `::[T]` instead of `List[T]`.
@@ -177,6 +177,35 @@ class Desugarer(val elaborator: Elaborator)
177177 nominate(ctx, term(coda)(using ctx)):
178178 expandMatch(_, pat, sequel)(fallback)
179179 expandMatch(scrutSymbol, headPattern, tailSplit)(fallback)
180+
181+ def termSplit (trees : Ls [Tree ], finish : Term => Term ): Split => Sequel =
182+ trees.foldRight(default): (t, elabFallback) =>
183+ t match
184+ case LetLike (`let`, ident @ Ident (_), N , N ) => ???
185+ case LetLike (`let`, ident @ Ident (_), S (termTree), N ) => fallback => ctx => trace(
186+ pre = s " termSplit: let ${ident.name} = $termTree" ,
187+ post = (res : Split ) => s " termSplit: let >>> $res"
188+ ):
189+ val sym = VarSymbol (ident)
190+ val fallbackCtx = ctx + (ident.name -> sym)
191+ Split .Let (sym, term(termTree)(using ctx), elabFallback(fallback)(fallbackCtx)).withLocOf(t)
192+ case Modified (Keyword .`do`, doLoc, computation) => fallback => ctx => trace(
193+ pre = s " termSplit: do $computation" ,
194+ post = (res : Split ) => s " termSplit: else >>> $res"
195+ ):
196+ val sym = TempSymbol (N , " doTemp" )
197+ Split .Let (sym, term(computation)(using ctx), elabFallback(fallback)(ctx)).withLocOf(t)
198+ case Modified (Keyword .`else`, elsLoc, default) => fallback => ctx => trace(
199+ pre = s " termSplit: else $default" ,
200+ post = (res : Split ) => s " termSplit: else >>> $res"
201+ ):
202+ // TODO: report `rest` as unreachable
203+ Split .default(term(default)(using ctx)).withLocOf(t)
204+ case branch => fallback => ctx => trace(
205+ pre = s " termSplit: $branch" ,
206+ post = (res : Split ) => s " termSplit >>> $res"
207+ ):
208+ termSplit(branch, finish)(elabFallback(fallback)(ctx))(ctx)
180209
181210 /** Desugar a _term split_ (TS) into a _split_ of core abstract syntax.
182211 * @param tree the tree representing the term split.
@@ -186,35 +215,9 @@ class Desugarer(val elaborator: Elaborator)
186215 * matches and splits
187216 */
188217 def termSplit (tree : Tree , finish : Term => Term ): Split => Sequel =
218+ log(s " termSplit: $tree" )
189219 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)
220+ case blk : Block => termSplit(blk.desugStmts, finish)
218221 case coda is rhs => fallback => ctx =>
219222 nominate(ctx, finish(term(coda)(using ctx))):
220223 patternSplit(rhs, _)(fallback)
@@ -246,7 +249,8 @@ class Desugarer(val elaborator: Elaborator)
246249 ):
247250 nominate(ctx, finish(term(headCoda)(using ctx))):
248251 expandMatch(_, headPattern, tailSplit)(fallback)
249- case tree @ App (opIdent @ Ident (opName), rawTup @ Tup (lhs :: rhs :: Nil )) => fallback => ctx => trace(
252+ // Handle binary operators.
253+ case tree @ OpApp (lhs, opIdent @ Ident (opName), rhss) => fallback => ctx => trace(
250254 pre = s " termSplit: after op <<< $opName" ,
251255 post = (res : Split ) => s " termSplit: after op >>> $res"
252256 ):
@@ -258,22 +262,16 @@ class Desugarer(val elaborator: Elaborator)
258262 val finishInner = (rhsTerm : Term ) =>
259263 val first = Fld (FldFlags .empty, lhsSymbol.ref(/* FIXME ident? */ ), N )
260264 val second = Fld (FldFlags .empty, rhsTerm, N )
261- val arguments = Term .Tup (first :: second :: Nil )(rawTup )
265+ val arguments = Term .Tup (first :: second :: Nil )(Tree . DummyTup )
262266 val joint = FlowSymbol (" ‹applied-result›" )
263- Term .App (opRef, arguments)(tree, N , joint)
264- termSplit(rhs, finishInner)(fallback)
265- case tree @ App (lhs, blk @ OpBlock (opRhsApps)) => fallback => ctx =>
267+ Term .App (opRef, arguments)(Tree .DummyApp , N , joint)
268+ termSplit(rhss, finishInner)(fallback)
269+ // Handle operator splits.
270+ case tree @ OpSplit (lhs, rhss) => fallback => ctx =>
266271 nominate(ctx, finish(term(lhs)(using ctx))): vs =>
267- val mkInnerFinish = (op : Term ) => (rhsTerm : Term ) =>
268- val first = Fld (FldFlags .empty, vs.ref(/* FIXME ident? */ ), N )
269- val second = Fld (FldFlags .empty, rhsTerm, N )
270- val rawTup = Tup (lhs :: Nil ): Tup // <-- loc might be wrong
271- val arguments = Term .Tup (first :: second :: Nil )(rawTup)
272- val joint = FlowSymbol (" ‹applied-result›" )
273- Term .App (op, arguments)(tree, N , joint)
274- opRhsApps.foldRight(Function .const(fallback): Sequel ): (tt, elabFallback) =>
275- tt match
276- case (Tree .Empty (), LetLike (`let`, pat, termTree, N )) => ctx =>
272+ rhss.foldRight(Function .const(fallback): Sequel ): (branch, elabFallback) =>
273+ branch match
274+ case LetLike (`let`, pat, termTree, N ) => ctx =>
277275 val ident = pat match // TODO handle patterns and rm special cases
278276 case ident : Ident => ident
279277 case und : Under => new Ident (" _" ).withLocOf(und)
@@ -283,22 +281,20 @@ class Desugarer(val elaborator: Elaborator)
283281 val sym = VarSymbol (ident)
284282 val fallbackCtx = ctx + (ident.name -> sym)
285283 Split .Let (sym, term(termTree)(using ctx), elabFallback(fallbackCtx))
286- case ( Tree . Empty (), Modified (Keyword .`do`, doLoc, computation) ) => ctx => trace(
284+ case Modified (Keyword .`do`, doLoc, computation) => ctx => trace(
287285 pre = s " termSplit: do $computation" ,
288- post = (res : Split ) => s " termSplit: else >>> $res"
286+ post = (res : Split ) => s " termSplit: do >>> $res"
289287 ):
290288 val sym = TempSymbol (N , " doTemp" )
291289 Split .Let (sym, term(computation)(using ctx), elabFallback(ctx))
292- case ( Tree . Empty (), Modified (Keyword .`else`, elsLoc, default) ) => ctx =>
290+ case Modified (Keyword .`else`, elsLoc, default) => ctx =>
293291 // TODO: report `rest` as unreachable
294292 Split .default(term(default)(using ctx))
295- case ((rawOp @ Ident (_)), rhs) => ctx =>
296- val op = term(rawOp)(using ctx)
297- val innerFinish = mkInnerFinish(op)
298- termSplit(rhs, innerFinish)(elabFallback(ctx))(ctx)
299- case (op, rhs) => ctx =>
300- raise(ErrorReport (msg " Unrecognized operator branch. " -> op.toLoc :: Nil ))
301- elabFallback(ctx)
293+ case rawRhs => ctx =>
294+ log(s " rawRhs: $rawRhs" )
295+ val rhs = rawRhs.splitOn(Trm (vs.ref(/* FIXME ident? */ )))
296+ log(s " rhs: $rhs" )
297+ termSplit(rhs, identity)(elabFallback(ctx))(ctx)
302298 case _ => fallback => _ =>
303299 raise(ErrorReport (msg " Unrecognized term split ( ${tree.describe}). " -> tree.toLoc :: Nil ))
304300 fallback.withoutLoc // Hacky... a loc is always added for the result
@@ -308,15 +304,14 @@ class Desugarer(val elaborator: Elaborator)
308304 * @param scrutinee the elaborated scrutinee
309305 * @param cont the continuation that needs the symbol and the context
310306 */
311- def nominate (baseCtx : Ctx , scrutinee : Term )
307+ def nominate (baseCtx : Ctx , scrutinee : Term , nameHint : Str = " scrut " )
312308 (cont : BlockLocalSymbol => Sequel ): Split = scrutinee match
313309 case ref @ Term .Ref (symbol : VarSymbol ) =>
314310 val innerCtx = baseCtx + (ref.tree.name -> symbol)
315311 cont(symbol)(innerCtx)
316312 case _ =>
317- val name = " scrut"
318- val symbol = TempSymbol (N , name)
319- val innerCtx = baseCtx + (name -> symbol)
313+ val symbol = TempSymbol (N , nameHint)
314+ val innerCtx = baseCtx + (nameHint -> symbol)
320315 Split .Let (symbol, scrutinee, cont(symbol)(innerCtx))
321316
322317 /** Decompose a `Tree` of conjunct matches. The tree is from the same line in
@@ -435,7 +430,7 @@ class Desugarer(val elaborator: Elaborator)
435430 pre = s " patternBranch <<< $patternAndMatches -> ${consequent.fold(_.showDbg, _.showDbg)}" ,
436431 post = (res : Split ) => s " patternBranch >>> ${res.showDbg}" )
437432 case _ =>
438- raise(ErrorReport (msg " Unrecognized pattern split. " -> tree.toLoc :: Nil ))
433+ raise(ErrorReport (msg " Unrecognized pattern split ( ${tree.describe} ) ." -> tree.toLoc :: Nil ))
439434 _ => _ => Split .default(Term .Error )
440435
441436 /** Elaborate a single match (a scrutinee and a pattern) and forms a split
@@ -448,7 +443,7 @@ class Desugarer(val elaborator: Elaborator)
448443 def expandMatch (scrutSymbol : BlockLocalSymbol , pattern : Tree , sequel : Sequel ): Split => Sequel =
449444 def ref = scrutSymbol.ref(/* FIXME ident? */ )
450445 def dealWithCtorCase (ctor : Ctor , compile : Bool )(fallback : Split ): Sequel = ctx =>
451- val clsTrm = elaborator.cls(ctor, inAppPrefix = false )
446+ val clsTrm = elaborator.cls(term( ctor) , inAppPrefix = false )
452447 clsTrm.symbol.flatMap(_.asClsLike) match
453448 case S (cls : ClassSymbol ) =>
454449 if compile then warn(msg " Cannot compile the class ` ${cls.name}` " -> ctor.toLoc)
@@ -475,7 +470,7 @@ class Desugarer(val elaborator: Elaborator)
475470 pre = s " expandMatch <<< ${ctor}( ${args.iterator.map(_.showDbg).mkString(" , " )}) " ,
476471 post = (r : Split ) => s " expandMatch >>> ${r.showDbg}"
477472 ):
478- val clsTrm = elaborator.cls(ctor, inAppPrefix = false )
473+ val clsTrm = elaborator.cls(term( ctor) , inAppPrefix = false )
479474 clsTrm.symbol.flatMap(_.asClsLike) match
480475 case S (cls : ClassSymbol ) =>
481476 val paramSymbols = cls.defn match
@@ -584,10 +579,10 @@ class Desugarer(val elaborator: Elaborator)
584579 Branch (ref, Pattern .Lit (IntLit (- value)), sequel(ctx)) ~: fallback
585580 case App (Ident (" -" ), Tup (DecLit (value) :: Nil )) => fallback => ctx =>
586581 Branch (ref, Pattern .Lit (DecLit (- value)), sequel(ctx)) ~: fallback
587- case App ( Ident (" &" ), Tree . Tup (lhs :: rhs :: Nil ) ) => fallback => ctx =>
582+ case OpApp (lhs, Ident (" &" ), rhs :: Nil ) => fallback => ctx =>
588583 val newSequel = expandMatch(scrutSymbol, rhs, sequel)(fallback)
589584 expandMatch(scrutSymbol, lhs, newSequel)(fallback)(ctx)
590- case App ( Ident (" |" ), Tree . Tup (lhs :: rhs :: Nil ) ) => fallback => ctx =>
585+ case OpApp (lhs, Ident (" |" ), rhs :: Nil ) => fallback => ctx =>
591586 val newFallback = expandMatch(scrutSymbol, rhs, sequel)(fallback)(ctx)
592587 expandMatch(scrutSymbol, lhs, sequel)(newFallback)(ctx)
593588 // A single constructor pattern.
@@ -598,6 +593,9 @@ class Desugarer(val elaborator: Elaborator)
598593 dealWithAppCtorCase(app, ctor, args, false )
599594 case app @ App (ctor : Ctor , Tup (args)) =>
600595 dealWithAppCtorCase(app, ctor, args, false )
596+ case app @ OpApp (lhs, ctor : Ctor , rhss) =>
597+ // TODO improve (eventually remove DummyApp)
598+ dealWithAppCtorCase(Tree .DummyApp , ctor, lhs :: rhss, false )
601599 // A single literal pattern
602600 case literal : Literal => fallback => ctx => trace(
603601 pre = s " expandMatch: literal <<< $literal" ,
0 commit comments