@@ -3192,7 +3192,7 @@ class JSCodeGen()(using genCtx: Context) {
3192
3192
case resType => resType
3193
3193
}
3194
3194
3195
- var clauses : List [(List [js.Tree ], js.Tree )] = Nil
3195
+ var clauses : List [(List [js.MatchableLiteral ], js.Tree )] = Nil
3196
3196
var optDefaultClause : Option [js.Tree ] = None
3197
3197
3198
3198
for (caze @ CaseDef (pat, guard, body) <- cases) {
@@ -3201,19 +3201,29 @@ class JSCodeGen()(using genCtx: Context) {
3201
3201
3202
3202
val genBody = genStatOrExpr(body, isStat)
3203
3203
3204
+ def invalidCase (): Nothing =
3205
+ abortMatch(" Invalid case" )
3206
+
3207
+ def genMatchableLiteral (tree : Literal ): js.MatchableLiteral = {
3208
+ genExpr(tree) match {
3209
+ case matchableLiteral : js.MatchableLiteral => matchableLiteral
3210
+ case otherExpr => invalidCase()
3211
+ }
3212
+ }
3213
+
3204
3214
pat match {
3205
3215
case lit : Literal =>
3206
- clauses = (List (genExpr (lit)), genBody) :: clauses
3216
+ clauses = (List (genMatchableLiteral (lit)), genBody) :: clauses
3207
3217
case Ident (nme.WILDCARD ) =>
3208
3218
optDefaultClause = Some (genBody)
3209
3219
case Alternative (alts) =>
3210
3220
val genAlts = alts.map {
3211
- case lit : Literal => genExpr (lit)
3212
- case _ => abortMatch( " Invalid case in alternative " )
3221
+ case lit : Literal => genMatchableLiteral (lit)
3222
+ case _ => invalidCase( )
3213
3223
}
3214
3224
clauses = (genAlts, genBody) :: clauses
3215
3225
case _ =>
3216
- abortMatch( " Invalid case pattern " )
3226
+ invalidCase( )
3217
3227
}
3218
3228
}
3219
3229
@@ -3228,10 +3238,6 @@ class JSCodeGen()(using genCtx: Context) {
3228
3238
* case is a typical product of `match`es that are full of
3229
3239
* `case n if ... =>`, which are used instead of `if` chains for
3230
3240
* convenience and/or readability.
3231
- *
3232
- * When no optimization applies, and any of the case values is not a
3233
- * literal int, we emit a series of `if..else` instead of a `js.Match`.
3234
- * This became necessary in 2.13.2 with strings and nulls.
3235
3241
*/
3236
3242
def isInt (tree : js.Tree ): Boolean = tree.tpe == jstpe.IntType
3237
3243
@@ -3251,32 +3257,8 @@ class JSCodeGen()(using genCtx: Context) {
3251
3257
js.If (js.BinaryOp (op, genSelector, uniqueAlt), caseRhs, defaultClause)(resultType)
3252
3258
3253
3259
case _ =>
3254
- if (isInt(genSelector) &&
3255
- clauses.forall(_._1.forall(_.isInstanceOf [js.IntLiteral ]))) {
3256
- // We have int literals only: use a js.Match
3257
- val intClauses = clauses.asInstanceOf [List [(List [js.IntLiteral ], js.Tree )]]
3258
- js.Match (genSelector, intClauses, defaultClause)(resultType)
3259
- } else {
3260
- // We have other stuff: generate an if..else chain
3261
- val (tempSelectorDef, tempSelectorRef) = genSelector match {
3262
- case varRef : js.VarRef =>
3263
- (js.Skip (), varRef)
3264
- case _ =>
3265
- val varDef = js.VarDef (freshLocalIdent(), NoOriginalName ,
3266
- genSelector.tpe, mutable = false , genSelector)
3267
- (varDef, varDef.ref)
3268
- }
3269
- val ifElseChain = clauses.foldRight(defaultClause) { (caze, elsep) =>
3270
- val conds = caze._1.map { caseValue =>
3271
- js.BinaryOp (js.BinaryOp .=== , tempSelectorRef, caseValue)
3272
- }
3273
- val cond = conds.reduceRight[js.Tree ] { (left, right) =>
3274
- js.If (left, js.BooleanLiteral (true ), right)(jstpe.BooleanType )
3275
- }
3276
- js.If (cond, caze._2, elsep)(resultType)
3277
- }
3278
- js.Block (tempSelectorDef, ifElseChain)
3279
- }
3260
+ // We have more than one case: use a js.Match
3261
+ js.Match (genSelector, clauses, defaultClause)(resultType)
3280
3262
}
3281
3263
}
3282
3264
0 commit comments