8000 Codegen: Make the handling of default clause jumps more generic. · scala-js/scala-js@ee3e9a0 · GitHub
[go: up one dir, main page]

Skip to content

Commit ee3e9a0

Browse files
committed
Codegen: Make the handling of default clause jumps more generic.
Previously, we had to recognize specific shapes of case bodies in order to extract jumps to default labels. This was fragile, as changes in nsc's codegen could invalidate our assumptions. We now take a more general approach. We register the default label in the `enclosingLabelDefInfos`. Jumps to that label can therefore be handled wherever they appear inside the case bodies. We still require a specific shape to extract the *definition* of the default label in the wildcard case. This can't be helped, as far as I can tell. Ultimately, the JS code generated for the test suites is unchanged, both in 2.12 and 2.13.
1 parent 498e56b commit ee3e9a0

File tree

1 file changed

+51
-87
lines changed

1 file changed

+51
-87
lines changed

compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala

Lines changed: 51 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,93 +3883,55 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
38833883
if (isStat) jstpe.VoidType
38843884
else toIRType(tree.tpe)
38853885

3886-
val defaultLabelSym = cases.collectFirst {
3886+
val optDefaultLabelSymAndInfo = cases.collectFirst {
38873887
case CaseDef(Ident(nme.WILDCARD), EmptyTree,
38883888
body @ LabelDef(_, Nil, rhs)) if hasSynthCaseSymbol(body) =>
3889-
body.symbol
3890-
}.getOrElse(NoSymbol)
3889+
body.symbol -> new EnclosingLabelDefInfoWithResultAsAssigns(Nil)
3890+
}
38913891

38923892
var clauses: List[(List[js.MatchableLiteral], js.Tree)] = Nil
38933893
var optElseClause: Option[js.Tree] = None
3894-
var optElseClauseLabel: Option[LabelName] = None
3895-
3896-
def genJumpToElseClause(implicit pos: ir.Position): js.Tree = {
3897-
if (optElseClauseLabel.isEmpty)
3898-
optElseClauseLabel = Some(freshLabelName("default"))
3899-
js.Return(js.Skip(), optElseClauseLabel.get)
3900-
}
3901-
3902-
for (caze @ CaseDef(pat, guard, body) <- cases) {
3903-
assert(guard == EmptyTree, s"found a case guard at ${caze.pos}")
3904-
3905-
def genBody(body: Tree): js.Tree = body match {
3906-
case MaybeAsInstanceOf(app @ Apply(_, Nil)) if app.symbol == defaultLabelSym =>
3907-
genJumpToElseClause
3908-
case Block(List(app @ Apply(_, Nil)), _) if app.symbol == defaultLabelSym =>
3909-
genJumpToElseClause
3910-
3911-
case If(cond, thenp, elsep) =>
3912-
js.If(genExpr(cond), genBody(thenp), genBody(elsep))(
3913-
resultType)(body.pos)
3914-
3915-
/* For #1955. If we receive a tree with the shape
3916-
* if (cond) {
3917-
* thenp
3918-
* } else {
3919-
* elsep
3920-
* }
3921-
* scala.runtime.BoxedUnit.UNIT
3922-
* we rewrite it as
3923-
* if (cond) {
3924-
* thenp
3925-
* scala.runtime.BoxedUnit.UNIT
3926-
* } else {
3927-
* elsep
3928-
* scala.runtime.BoxedUnit.UNIT
3929-
* }
3930-
* so that it fits the shape of if/elses we can deal with.
3931-
*/
3932-
case Block(List(If(cond, thenp, elsep)), s: Select)
3933-
if s.symbol == definitions.BoxedUnit_UNIT =>
3934-
val newThenp = Block(thenp, s).setType(s.tpe).setPos(thenp.pos)
3935-
val newElsep = Block(elsep, s).setType(s.tpe).setPos(elsep.pos)
3936-
js.If(genExpr(cond), genBody(newThenp), genBody(newElsep))(
3937-
resultType)(body.pos)
39383894

3939-
case _ =>
3895+
withScopedVars(
3896+
enclosingLabelDefInfos := enclosingLabelDefInfos.get ++ optDefaultLabelSymAndInfo.toList
3897+
) {
3898+
for (caze @ CaseDef(pat, guard, body) <- cases) {
3899+
assert(guard == EmptyTree, s"found a case guard at ${caze.pos}")
3900+
3901+
def genBody(body: Tree): js.Tree =
39403902
genStatOrExpr(body, isStat)
3941-
}
39423903

3943-
def invalidCase(tree: Tree): Nothing =
3944-
abort(s"Invalid case in alternative in switch-like pattern match: $tree at: ${tree.pos}")
3904+
def invalidCase(tree: Tree): Nothing =
3905+
abort(s"Invalid case in alternative in switch-like pattern match: $tree at: ${tree.pos}")
39453906

3946-
def genMatchableLiteral(tree: Literal): js.MatchableLiteral = {
3947-
genExpr(tree) match {
3948-
case matchableLiteral: js.MatchableLiteral => matchableLiteral
3949-
case otherExpr => invalidCase(tree)
3907+
def genMatchableLiteral(tree: Literal): js.MatchableLiteral = {
3908+
genExpr(tree) match {
3909+
case matchableLiteral: js.MatchableLiteral => matchableLiteral
3910+
case otherExpr => invalidCase(tree)
3911+
}
39503912
}
3951-
}
39523913

3953-
pat match {
3954-
case lit: Literal =>
3955-
clauses = (List(genMatchableLiteral(lit)), genBody(body)) :: clauses
3956-
case Ident(nme.WILDCARD) =>
3957-
optElseClause = Some(body match {
3958-
case LabelDef(_, Nil, rhs) if hasSynthCaseSymbol(body) =>
3959-
genBody(rhs)
3960-
case _ =>
3961-
genBody(body)
3962-
})
3963-
case Alternative(alts) =>
3964-
val genAlts = {
3965-
alts map {
3966-
case lit: Literal => genMatchableLiteral(lit)
3967-
case _ => invalidCase(tree)
3914+
pat match {
3915+
case lit: Literal =>
3916+
clauses = (List(genMatchableLiteral(lit)), genBody(body)) :: clauses
3917+
case Ident(nme.WILDCARD) =>
3918+
optElseClause = Some(body match {
3919+
case LabelDef(_, Nil, rhs) if hasSynthCaseSymbol(body) =>
3920+
genBody(rhs)
3921+
case _ =>
3922+
genBody(body)
3923+
})
3924+
case Alternative(alts) =>
3925+
val genAlts = {
3926+
alts map {
3927+
case lit: Literal => genMatchableLiteral(lit)
3928+
case _ => invalidCase(tree)
3929+
}
39683930
}
3969-
}
3970-
clauses = (genAlts, genBody(body)) :: clauses
3971-
case _ =>
3972-
invalidCase(tree)
3931+
clauses = (genAlts, genBody(body)) :: clauses
3932+
case _ =>
3933+
invalidCase(tree)
3934+
}
39733935
}
39743936
}
39753937

@@ -4012,21 +3974,23 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
40123974
}
40133975
}
40143976

4015-
optElseClauseLabel.fold[js.Tree] {
4016-
buildMatch(clauses.reverse, elseClause, resultType)
4017-
} { elseClauseLabel =>
4018-
val matchResultLabel = freshLabelName("matchResult")
4019-
val patchedClauses = for ((alts, body) <- clauses) yield {
4020-
implicit val pos = body.pos
4021-
val newBody = js.Return(body, matchResultLabel)
4022-
(alts, newBody)
4023-
}
4024-
js.Labeled(matchResultLabel, resultType, js.Block(List(
4025-
js.Labeled(elseClauseLabel, jstpe.VoidType, {
3977+
optDefaultLabelSymAndInfo match {
3978+
case Some((defaultLabelSym, defaultLabelInfo)) if defaultLabelInfo.generatedReturns > 0 =>
3979+
val matchResultLabel = freshLabelName("matchResult")
3980+
val patchedClauses = for ((alts, body) <- clauses) yield {
3981+
implicit val pos = body.pos
3982+
val newBody = js.Return(body, matchResultLabel)
3983+
(alts, newBody)
3984+
}
3985+
js.Labeled(matchResultLabel, resultType, js.Block(List(
3986+
js.Labeled(encodeLabelSym(defaultLabelSym), jstpe.VoidType, {
40263987
buildMatch(patchedClauses.reverse, js.Skip(), jstpe.VoidType)
40273988
}),
40283989
elseClause
4029-
)))
3990+
)))
3991+
3992+
case _ =>
3993+
buildMatch(clauses.reverse, elseClause, resultType)
40303994
}
40313995
}
40323996

0 commit comments

Comments
 (0)
0