Skip to content

Commit d06585f

Browse files
committed
Report error if field els is missing in If
1 parent 868af30 commit d06585f

File tree

3 files changed

+56
-64
lines changed

3 files changed

+56
-64
lines changed

shared/src/main/scala/mlscript/Typer.scala

+24-18
Original file line numberDiff line numberDiff line change
@@ -721,24 +721,30 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool)
721721
}
722722
con(s_ty, req, cs_ty)
723723
case iff @ If(body, fallback) =>
724-
val cnf = desugarIf(body)(ctx)
725-
println("Flattened conjunctions")
726-
cnf.foreach { case (conditions, term) =>
727-
println(conditions.iterator.map {
728-
case IfBodyHelpers.Condition.BooleanTest(test) => s"<$test>"
729-
case IfBodyHelpers.Condition.MatchClass(scrutinee, Var(className), fields) =>
730-
s"$scrutinee is $className"
731-
case IfBodyHelpers.Condition.MatchTuple(scrutinee, arity, fields) =>
732-
s"$scrutinee is Tuple#$arity"
733-
}.mkString("", " and ", s" => $term"))
724+
try {
725+
val cnf = desugarIf(body)(ctx)
726+
println("Flattened conjunctions")
727+
cnf.foreach { case (conditions, term) =>
728+
println(conditions.iterator.map {
729+
case IfBodyHelpers.Condition.BooleanTest(test) => s"<$test>"
730+
case IfBodyHelpers.Condition.MatchClass(scrutinee, Var(className), fields) =>
731+
s"$scrutinee is $className"
732+
case IfBodyHelpers.Condition.MatchTuple(scrutinee, arity, fields) =>
733+
s"$scrutinee is Tuple#$arity"
734+
}.mkString("", " and ", s" => $term"))
735+
}
736+
val caseTree = MutCaseOf.build(cnf)
737+
println("The mutable CaseOf tree")
738+
println(caseTree.toString)
739+
val trm = caseTree.toTerm(fallback)
740+
println(s"Desugared term: $trm")
741+
iff.desugaredIf = S(trm)
742+
typeTerm(trm)
743+
} catch {
744+
case IfDesugaringException(message) =>
745+
err(message, iff.toLoc)
746+
case e: Throwable => throw e
734747
}
735-
val caseTree = MutCaseOf.build(cnf)
736-
println("The mutable CaseOf tree")
737-
println(caseTree.toString)
738-
val trm = caseTree.toTerm(fallback)
739-
println(s"Desugared term: $trm")
740-
iff.desugaredIf = S(trm)
741-
typeTerm(trm)
742748
case New(S((nmedTy, trm)), TypingUnit(Nil)) =>
743749
typeTerm(App(Var(nmedTy.base.name).withLocOf(nmedTy), trm))
744750
case New(base, args) => ???
@@ -977,7 +983,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool)
977983
// This case handles literals.
978984
// x is true | x is false | x is 0 | x is "text" | ...
979985
case literal @ (Var("true") | Var("false") | _: Lit) =>
980-
val test = mkBinOp(scrutinee, Var("eq"), literal)
986+
val test = mkBinOp(scrutinee, Var("=="), literal)
981987
Condition.BooleanTest(test) :: Nil
982988
// This case handles simple class tests.
983989
// x is A

shared/src/main/scala/mlscript/helpers.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ trait IfImpl { self: If =>
775775
var desugaredIf: Opt[Term] = N
776776
}
777777

778+
final case class IfDesugaringException(message: Str) extends Exception(message)
779+
778780
object IfBodyHelpers {
779781
abstract class Condition
780782

@@ -955,7 +957,8 @@ object MutCaseOf {
955957
}
956958
final case object MissingCase extends MutCaseOf {
957959
override def append(branch: Ls[Condition] -> Term): Unit = ???
958-
override def toTerm(implicit fallback: Opt[Term]): Term = fallback.getOrElse(???)
960+
override def toTerm(implicit fallback: Opt[Term]): Term =
961+
fallback.getOrElse(throw new IfDesugaringException("missing a default branch"))
959962
}
960963

961964
private def buildBranch(conditions: Ls[Condition], term: Term): MutCaseOf = {

shared/src/test/diff/nu/Humiliation.mls

+28-45
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,32 @@ class Foo(x)
77
//│ = [Function: Foo1]
88

99

10-
:d
1110
if 1 is 1 then 1
12-
//│ 0. Typing term if (is (1,) (1,)) then 1
13-
//│ | Flattened conjunctions
14-
//│ | <eq (1,) (1,)> => 1
15-
//│ | The mutable CaseOf tree
16-
//│ | IfThenElse(eq (1,) (1,),Consequent(1),MissingCase)
17-
//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing
18-
//│ at: scala.Predef$.$qmark$qmark$qmark(Predef.scala:344)
19-
//│ at: mlscript.MutCaseOf$MissingCase$.$anonfun$toTerm$1(helpers.scala:958)
20-
//│ at: scala.Option.getOrElse(Option.scala:201)
21-
//│ at: mlscript.MutCaseOf$MissingCase$.toTerm(helpers.scala:958)
22-
//│ at: mlscript.MutCaseOf$IfThenElse.toTerm(helpers.scala:901)
23-
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:738)
24-
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
25-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
26-
//│ at: mlscript.Typer.typeStatement(Typer.scala:376)
27-
//│ at: mlscript.DiffTests.$anonfun$new$55(DiffTests.scala:558)
28-
29-
30-
if f is
31-
Foo(a) then a
32-
//│ ╔══[ERROR] identifier not found: f
33-
//│ ║ l.30: if f is
34-
//│ ╙── ^
11+
//│ ╔══[ERROR] missing a default branch
12+
//│ ║ l.10: if 1 is 1 then 1
13+
//│ ╙── ^^^^^^^^^^^^^
3514
//│ res: error
3615
//│ Code generation encountered an error:
37-
//│ unresolved symbol f
16+
//│ if expression has not been not desugared
17+
18+
fun test(x) = if x is 1 then 0 else 1
19+
//│ test: number -> (0 | 1)
20+
//│ = [Function: test]
3821

3922
if f is
4023
Foo(a) then a
4124
Foo(a) then a
4225
//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing
4326
//│ at: scala.Predef$.$qmark$qmark$qmark(Predef.scala:344)
44-
//│ at: mlscript.MutCaseOf$Consequent.append(helpers.scala:953)
45-
//│ at: mlscript.MutCaseOf$Match.append(helpers.scala:916)
46-
//│ at: mlscript.MutCaseOf$.$anonfun$build$1(helpers.scala:987)
47-
//│ at: mlscript.MutCaseOf$.$anonfun$build$1$adapted(helpers.scala:987)
27+
//│ at: mlscript.MutCaseOf$Consequent.append(helpers.scala:955)
28+
//│ at: mlscript.MutCaseOf$Match.append(helpers.scala:918)
29+
//│ at: mlscript.MutCaseOf$.$anonfun$build$1(helpers.scala:990)
30+
//│ at: mlscript.MutCaseOf$.$anonfun$build$1$adapted(helpers.scala:990)
4831
//│ at: scala.collection.immutable.List.foreach(List.scala:333)
49-
//│ at: mlscript.MutCaseOf$.build(helpers.scala:987)
50-
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:735)
32+
//│ at: mlscript.MutCaseOf$.build(helpers.scala:990)
33+
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:736)
5134
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
52-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
35+
//│ at: mlscript.Typer.typeTerm(Typer.scala:753)
5336

5437

5538
class Bar(y, z)
@@ -61,7 +44,7 @@ fun test(f) = if f is
6144
Foo(a) then a
6245
Bar(b, c) then b + c
6346
//│ test: (Bar & {y: int, z: int} | (Foo with {x: 'x})) -> (int | 'x)
64-
//│ = [Function: test]
47+
//│ = [Function: test1]
6548

6649

6750
class Pair(fst, snd)
@@ -75,15 +58,15 @@ if x is
7558
Pair(y, 1) then x
7659
//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing
7760
//│ at: scala.Predef$.$qmark$qmark$qmark(Predef.scala:344)
78-
//│ at: mlscript.MutCaseOf$IfThenElse.append(helpers.scala:888)
79-
//│ at: mlscript.MutCaseOf$Match.append(helpers.scala:916)
80-
//│ at: mlscript.MutCaseOf$.$anonfun$build$1(helpers.scala:987)
81-
//│ at: mlscript.MutCaseOf$.$anonfun$build$1$adapted(helpers.scala:987)
61+
//│ at: mlscript.MutCaseOf$IfThenElse.append(helpers.scala:890)
62+
//│ at: mlscript.MutCaseOf$Match.append(helpers.scala:918)
63+
//│ at: mlscript.MutCaseOf$.$anonfun$build$1(helpers.scala:990)
64+
//│ at: mlscript.MutCaseOf$.$anonfun$build$1$adapted(helpers.scala:990)
8265
//│ at: scala.collection.immutable.List.foreach(List.scala:333)
83-
//│ at: mlscript.MutCaseOf$.build(helpers.scala:987)
84-
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:735)
66+
//│ at: mlscript.MutCaseOf$.build(helpers.scala:990)
67+
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:736)
8568
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
86-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
69+
//│ at: mlscript.Typer.typeTerm(Typer.scala:753)
8770

8871
class Z()
8972
class O()
@@ -164,18 +147,18 @@ fun foo(x, y) = if x is Z() and y is O() then 0 else 1
164147
//│ at: scala.Predef$.$qmark$qmark$qmark(Predef.scala:344)
165148
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:626)
166149
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
167-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
150+
//│ at: mlscript.Typer.typeTerm(Typer.scala:753)
168151
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:714)
169152
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
170-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
171-
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:741)
153+
//│ at: mlscript.Typer.typeTerm(Typer.scala:753)
154+
//│ at: mlscript.Typer.$anonfun$typeTerm$2(Typer.scala:742)
172155
//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:30)
173-
//│ at: mlscript.Typer.typeTerm(Typer.scala:747)
156+
//│ at: mlscript.Typer.typeTerm(Typer.scala:753)
174157

175158
fun foo(x, y) = if x is
176159
Z() and y is O() then 0 else 1
177160
//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here
178-
//│ ║ l.176: Z() and y is O() then 0 else 1
161+
//│ ║ l.159: Z() and y is O() then 0 else 1
179162
//│ ╙── ^^^^
180163
//│ foo: (Z, O,) -> 0
181164
//│ = [Function: foo6]

0 commit comments

Comments
 (0)