@@ -99,8 +99,13 @@ class Desugarer extends TypeDefs { self: Typer =>
99
99
def makeScrutinee (term : Term , matchRootLoc : Opt [Loc ])(implicit ctx : Ctx ): Scrutinee =
100
100
traceUCS(s " Making a scrutinee for ` $term` " ) {
101
101
term match {
102
- case _ : SimpleTerm => Scrutinee (N , term)(matchRootLoc)
103
- case _ => Scrutinee (S (makeLocalizedName(term)), term)(matchRootLoc)
102
+ case _ : Var =>
103
+ printlnUCS(s " The scrutinee does not need an alias. " )
104
+ Scrutinee (N , term)(matchRootLoc)
105
+ case _ =>
106
+ val localizedName = makeLocalizedName(term)
107
+ printlnUCS(s " The scrutinee needs an alias: $localizedName" )
108
+ Scrutinee (S (localizedName), term)(matchRootLoc)
104
109
}
105
110
}()
106
111
@@ -160,9 +165,13 @@ class Desugarer extends TypeDefs { self: Typer =>
160
165
case Var (" _" ) => Nil
161
166
// This case handles literals.
162
167
// x is true | x is false | x is 0 | x is "text" | ...
163
- case literal @ (Var (" true" ) | Var (" false" ) | _ : Lit ) =>
164
- val test = mkBinOp(scrutinee.reference, Var (" ==" ), literal)
165
- val clause = Clause .BooleanTest (test)(scrutinee.term.toLoc.toList ::: literal.toLoc.toList)
168
+ case literal : Var if literal.name === " true" || literal.name === " false" =>
169
+ val clause = Clause .MatchLiteral (scrutinee, literal)(scrutinee.term.toLoc.toList ::: literal.toLoc.toList)
170
+ clause.bindings = scrutinee.asBinding.toList
171
+ printlnUCS(s " Add bindings to the clause: ${scrutinee.asBinding}" )
172
+ clause :: Nil
173
+ case literal : Lit =>
174
+ val clause = Clause .MatchLiteral (scrutinee, literal)(scrutinee.term.toLoc.toList ::: literal.toLoc.toList)
166
175
clause.bindings = scrutinee.asBinding.toList
167
176
printlnUCS(s " Add bindings to the clause: ${scrutinee.asBinding}" )
168
177
clause :: Nil
@@ -515,22 +524,34 @@ class Desugarer extends TypeDefs { self: Typer =>
515
524
*/
516
525
type ExhaustivenessMap = Map [Str \/ Int , Map [Var , MutCase ]]
517
526
518
- def getScurtineeKey (scrutinee : Scrutinee )(implicit ctx : Ctx , raise : Raise ): Str \/ Int = {
519
- scrutinee.term match {
520
- // The original scrutinee is an reference.
521
- case v @ Var (name) =>
522
- ctx.env.get(name) match {
523
- case S (VarSymbol (_, defVar)) => defVar.uid.fold[Str \/ Int ](L (v.name))(R (_))
524
- case S (_) | N => L (v.name)
525
- }
526
- // Otherwise, the scrutinee has a temporary name.
527
- case _ =>
528
- scrutinee.local match {
529
- case N => throw new Error (" check your `makeScrutinee`" )
530
- case S (localNameVar) => L (localNameVar.name)
531
- }
532
- }
533
- }
527
+ /**
528
+ * This method obtains a proper key of the given scrutinee
529
+ * for memorizing patterns belongs to the scrutinee.
530
+ *
531
+ * @param scrutinee the scrutinee
532
+ * @param ctx the context
533
+ * @param raise we need this to raise errors.
534
+ * @return the variable name or the variable ID
535
+ */
536
+ def getScurtineeKey (scrutinee : Scrutinee )(implicit ctx : Ctx , raise : Raise ): Str \/ Int =
537
+ traceUCS(s " [getScrutineeKey] $scrutinee" ) {
538
+ scrutinee.term match {
539
+ // The original scrutinee is an reference.
540
+ case v @ Var (name) =>
541
+ printlnUCS(" The original scrutinee is an reference." )
542
+ ctx.env.get(name) match {
543
+ case S (VarSymbol (_, defVar)) => defVar.uid.fold[Str \/ Int ](L (v.name))(R (_))
544
+ case S (_) | N => L (v.name)
545
+ }
546
+ // Otherwise, the scrutinee was localized because it might be effectful.
547
+ case _ =>
548
+ printlnUCS(" The scrutinee was localized because it might be effectful." )
549
+ scrutinee.local match {
550
+ case N => throw new Error (" check your `makeScrutinee`" )
551
+ case S (localNameVar) => L (localNameVar.name)
552
+ }
553
+ }
554
+ }()
534
555
535
556
/**
536
557
* Check the exhaustiveness of the given `MutCaseOf`.
@@ -542,10 +563,8 @@ class Desugarer extends TypeDefs { self: Typer =>
542
563
def checkExhaustive
543
564
(t : MutCaseOf , parentOpt : Opt [MutCaseOf ])
544
565
(implicit scrutineePatternMap : ExhaustivenessMap , ctx : Ctx , raise : Raise )
545
- : Unit = {
546
- printlnUCS(s " Check exhaustiveness of ${t.describe}" )
547
- indent += 1
548
- try t match {
566
+ : Unit = traceUCS(s " [checkExhaustive] ${t.describe}" ) {
567
+ t match {
549
568
case _ : Consequent => ()
550
569
case MissingCase =>
551
570
parentOpt match {
@@ -567,18 +586,26 @@ class Desugarer extends TypeDefs { self: Typer =>
567
586
case S (_) if default.isDefined =>
568
587
printlnUCS(" The match has a default branch. So, it is always safe." )
569
588
case S (patternMap) =>
570
- printlnUCS(s " The exhaustiveness map is ${scrutineePatternMap}" )
589
+ printlnUCS(s " The exhaustiveness map is " )
590
+ scrutineePatternMap.foreach { case (key, matches) =>
591
+ printlnUCS(s " - $key -> ${matches.keysIterator.mkString(" , " )}" )
592
+ }
571
593
printlnUCS(s " The scrutinee key is ${getScurtineeKey(scrutinee)}" )
572
594
printlnUCS(" Pattern map of the scrutinee:" )
573
595
if (patternMap.isEmpty)
574
596
printlnUCS(" <Empty>" )
575
597
else
576
598
patternMap.foreach { case (key, mutCase) => printlnUCS(s " - $key => $mutCase" )}
577
599
// Filter out missing cases in `branches`.
578
- val missingCases = patternMap.removedAll(branches.iterator.map {
579
- case MutCase (classNameVar -> _, _) => classNameVar
600
+ val missingCases = patternMap.removedAll(branches.iterator.flatMap {
601
+ case MutCase .Literal (tof @ Var (n), _) if n === " true" || n === " false" => Some (tof)
602
+ case MutCase .Literal (_, _) => None
603
+ case MutCase .Constructor (classNameVar -> _, _) => Some (classNameVar)
580
604
})
581
- printlnUCS(s " Number of missing cases: ${missingCases.size}" )
605
+ printlnUCS(" Missing cases" )
606
+ missingCases.foreach { case (key, m) =>
607
+ printlnUCS(s " - $key -> ${m}" )
608
+ }
582
609
if (! missingCases.isEmpty) {
583
610
throw new DesugaringException ({
584
611
val numMissingCases = missingCases.size
@@ -597,53 +624,67 @@ class Desugarer extends TypeDefs { self: Typer =>
597
624
}
598
625
}
599
626
default.foreach(checkExhaustive(_, S (t)))
600
- branches.foreach { case MutCase (_, consequent) =>
601
- checkExhaustive(consequent, S (t))
627
+ branches.foreach { branch =>
628
+ checkExhaustive(branch. consequent, S (t))
602
629
}
603
- } finally indent -= 1
604
- }
630
+ }
631
+ }()
605
632
606
- def summarizePatterns (t : MutCaseOf )(implicit ctx : Ctx , raise : Raise ): ExhaustivenessMap = {
633
+ def summarizePatterns (t : MutCaseOf )(implicit ctx : Ctx , raise : Raise ): ExhaustivenessMap = traceUCS( " [summarizePatterns] " ) {
607
634
val m = MutMap .empty[Str \/ Int , MutMap [Var , MutCase ]]
608
- def rec (t : MutCaseOf ): Unit = {
609
- printlnUCS(s " Summarize pattern of ${t.describe}" )
610
- indent += 1
611
- try t match {
635
+ def rec (t : MutCaseOf ): Unit = traceUCS(s " [rec] ${t.describe}" ) {
636
+ t match {
612
637
case Consequent (term) => ()
613
638
case MissingCase => ()
614
639
case IfThenElse (_, whenTrue, whenFalse) =>
615
640
rec(whenTrue)
616
641
rec(whenFalse)
617
642
case Match (scrutinee, branches, default) =>
618
643
val key = getScurtineeKey(scrutinee)
619
- branches.foreach { mutCase =>
620
- val patternMap = m.getOrElseUpdate( key, MutMap .empty)
621
- if (! patternMap.contains(mutCase.patternFields._1)) {
622
- patternMap += ((mutCase.patternFields._1, mutCase))
623
- }
624
- rec(mutCase.consequent)
644
+ val patternMap = m.getOrElseUpdate(key, MutMap .empty)
645
+ branches.foreach {
646
+ case mutCase @ MutCase .Literal (literal, consequent) =>
647
+ literal match {
648
+ case tof @ Var (n) if n === " true" || n === " false" =>
649
+ if (! patternMap.contains(tof)) {
650
+ patternMap += ((tof, mutCase))
651
+ }
652
+ case _ => () // TODO: Summarize literals.
653
+ }
654
+ rec(consequent)
655
+ case mutCase @ MutCase .Constructor ((className, _), consequent) =>
656
+ if (! patternMap.contains(className)) {
657
+ patternMap += ((className, mutCase))
658
+ }
659
+ rec(consequent)
625
660
}
626
661
default.foreach(rec)
627
- } finally indent -= 1
628
- }
662
+ }
663
+ }()
629
664
rec(t)
630
- printlnUCS(" Exhaustiveness map" )
631
- m.foreach { case (scrutinee, patterns) =>
632
- printlnUCS(s " - $scrutinee => " + patterns.keys.mkString(" , " ))
633
- }
665
+ printlnUCS(" Summarized patterns" )
666
+ if (m.isEmpty)
667
+ printlnUCS(" <Empty>" )
668
+ else
669
+ m.foreach { case (scrutinee, patterns) =>
670
+ printlnUCS(s " - $scrutinee => " + patterns.keysIterator.mkString(" , " ))
671
+ }
634
672
Map .from(m.iterator.map { case (key, patternMap) => key -> Map .from(patternMap) })
635
- }
673
+ }()
636
674
637
675
protected def constructTerm (m : MutCaseOf )(implicit ctx : Ctx ): Term = {
638
676
def rec (m : MutCaseOf )(implicit defs : Set [Var ]): Term = m match {
639
677
case Consequent (term) => term
640
678
case Match (scrutinee, branches, wildcard) =>
641
679
def rec2 (xs : Ls [MutCase ]): CaseBranches =
642
680
xs match {
643
- case MutCase (className -> fields, cases) :: next =>
681
+ case MutCase . Constructor (className -> fields, cases) :: next =>
644
682
// TODO: expand bindings here
645
683
val consequent = rec(cases)(defs ++ fields.iterator.map(_._2))
646
684
Case (className, mkLetFromFields(scrutinee, fields.toList, consequent), rec2(next))
685
+ case MutCase .Literal (literal, cases) :: next =>
686
+ val consequent = rec(cases)
687
+ Case (literal, consequent, rec2(next))
647
688
case Nil =>
648
689
wildcard.fold[CaseBranches ](NoCases ) { rec(_) |> Wildcard }
649
690
}
0 commit comments