Skip to content

Commit df5b3c6

Browse files
committed
Replace rest field in ir.ParamDef with special members
1 parent 40c51ec commit df5b3c6

File tree

19 files changed

+361
-280
lines changed

19 files changed

+361
-280
lines changed

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

Lines changed: 84 additions & 68 deletions
Large diffs are not rendered by default.

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

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
346346
None
347347
} else {
348348
val formalArgsRegistry = new FormalArgsRegistry(1, false)
349-
val List(arg) = formalArgsRegistry.genFormalArgs()
349+
val (List(arg), None) = formalArgsRegistry.genFormalArgs()
350350
val body = genExportSameArgc(jsName, formalArgsRegistry,
351351
alts = setters.map(ExportedSymbol),
352352
paramIndex = 0, static = static)
@@ -430,7 +430,7 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
430430
val formalArgsRegistry = new FormalArgsRegistry(minArgc, needsRestParam)
431431

432432
// List of formal parameters
433-
val formalArgs = formalArgsRegistry.genFormalArgs()
433+
val (formalArgs, restParam) = formalArgsRegistry.genFormalArgs()
434434

435435
// Create tuples: (methods, argCounts). This will be the cases we generate
436436
val caseDefinitions =
@@ -483,7 +483,7 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
483483
}
484484
}
485485

486-
js.JSMethodDef(flags, genExpr(jsName), formalArgs, body)(
486+
js.JSMethodDef(flags, genExpr(jsName), formalArgs, restParam, body)(
487487
OptimizerHints.empty, None)
488488
}
489489

@@ -796,21 +796,16 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
796796
js.This()(encodeClassType(sym.owner))
797797
}
798798

799-
def boxIfNeeded(call: js.Tree): js.Tree = {
800-
ensureBoxed(call,
801-
enteringPhase(currentRun.posterasurePhase)(sym.tpe.resultType))
802-
}
803-
804799
if (isNonNativeJSClass(currentClassSym)) {
805800
assert(sym.owner == currentClassSym.get, sym.fullName)
806-
boxIfNeeded(genApplyJSClassMethod(receiver, sym, args))
801+
ensureResultBoxed(genApplyJSClassMethod(receiver, sym, args), sym)
807802
} else {
808803
if (sym.isClassConstructor)
809804
genNew(currentClassSym, sym, args)
810805
else if (sym.isPrivate)
811-
boxIfNeeded(genApplyMethodStatically(receiver, sym, args))
806+
ensureResultBoxed(genApplyMethodStatically(receiver, sym, args), sym)
812807
else
813-
boxIfNeeded(genApplyMethod(receiver, sym, args))
808+
ensureResultBoxed(genApplyMethod(receiver, sym, args), sym)
814809
}
815810
}
816811

@@ -1061,22 +1056,22 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
10611056
if (needsRestParam) freshLocalIdent("rest")(NoPosition).name
10621057
else null
10631058

1064-
def genFormalArgs()(implicit pos: Position): List[js.ParamDef] = {
1059+
def genFormalArgs()(implicit pos: Position): (List[js.ParamDef], Option[js.ParamDef]) = {
10651060
val fixedParamDefs = fixedParamNames.toList.map { paramName =>
10661061
js.ParamDef(js.LocalIdent(paramName), NoOriginalName, jstpe.AnyType,
1067-
mutable = false, rest = false)
1062+
mutable = false)
10681063
}
10691064

1070-
if (needsRestParam) {
1071-
val restParamDef = {
1072-
js.ParamDef(js.LocalIdent(restParamName),
1073-
NoOriginalName, jstpe.AnyType,
1074-
mutable = false, rest = true)
1065+
val restParam = {
1066+
if (needsRestParam) {
1067+
Some(js.ParamDef(js.LocalIdent(restParamName),
1068+
NoOriginalName, jstpe.AnyType, mutable = false))
1069+
} else {
1070+
None
10751071
}
1076-
fixedParamDefs :+ restParamDef
1077-
} else {
1078-
fixedParamDefs
10791072
}
1073+
1074+
(fixedParamDefs, restParam)
10801075
}
10811076

10821077
def genArgRef(index: Int)(implicit pos: Position): js.Tree = {

ir/shared/src/main/scala/org/scalajs/ir/Hashers.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,19 @@ object Hashers {
4848
if (methodDef.hash.isDefined) methodDef
4949
else {
5050
val hasher = new TreeHasher()
51-
val JSMethodDef(flags, name, args, body) = methodDef
51+
val JSMethodDef(flags, name, params, restParam, body) = methodDef
5252

5353
hasher.mixPos(methodDef.pos)
5454
hasher.mixInt(MemberFlags.toBits(flags))
5555
hasher.mixTree(name)
56-
hasher.mixParamDefs(args)
56+
hasher.mixParamDefs(params)
57+
restParam.foreach(hasher.mixParamDef(_))
5758
hasher.mixTree(body)
5859
hasher.mixInt(OptimizerHints.toBits(methodDef.optimizerHints))
5960

6061
val hash = hasher.finalizeHash()
6162

62-
JSMethodDef(flags, name, args, body)(
63+
JSMethodDef(flags, name, params, restParam, body)(
6364
methodDef.optimizerHints, Some(hash))(methodDef.pos)
6465
}
6566
}
@@ -121,7 +122,6 @@ object Hashers {
121122
mixOriginalName(paramDef.originalName)
122123
mixType(paramDef.ptpe)
123124
mixBoolean(paramDef.mutable)
124-
mixBoolean(paramDef.rest)
125125
}
126126

127127
def mixParamDefs(paramDefs: List[ParamDef]): Unit =
@@ -494,11 +494,12 @@ object Hashers {
494494
mixTag(TagThis)
495495
mixType(tree.tpe)
496496

497-
case Closure(arrow, captureParams, params, body, captureValues) =>
497+
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
498498
mixTag(TagClosure)
499499
mixBoolean(arrow)
500500
mixParamDefs(captureParams)
501501
mixParamDefs(params)
502+
restParam.foreach(mixParamDef(_))
502503
mixTree(body)
503504
mixTrees(captureValues)
504505

ir/shared/src/main/scala/org/scalajs/ir/Printers.scala

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,24 @@ object Printers {
8989
}
9090
}
9191

92-
protected def printSig(args: List[ParamDef], resultType: Type): Unit = {
93-
printRow(args, "(", ", ", ")")
92+
protected def printSig(args: List[ParamDef], restParam: Option[ParamDef],
93+
resultType: Type): Unit = {
94+
print("(")
95+
var rem = args
96+
while (rem.nonEmpty) {
97+
printAnyNode(rem.head)
98+
rem = rem.tail
99+
if (rem.nonEmpty || restParam.nonEmpty)
100+
print(", ")
101+
}
102+
103+
restParam.foreach { p =>
104+
print("...")
105+
printAnyNode(p)
106+
}
107+
108+
print(")")
109+
94110
if (resultType != NoType) {
95111
print(": ")
96112
print(resultType)
@@ -121,12 +137,9 @@ object Printers {
121137
}
122138

123139
def print(paramDef: ParamDef): Unit = {
124-
val ParamDef(ident, originalName, ptpe, mutable, rest) = paramDef
125-
140+
val ParamDef(ident, originalName, ptpe, mutable) = paramDef
126141
if (mutable)
127142
print("var ")
128-
if (rest)
129-
print("...")
130143
print(ident)
131144
print(originalName)
132145
print(": ")
@@ -828,7 +841,7 @@ object Printers {
828841
case This() =>
829842
print("this")
830843

831-
case Closure(arrow, captureParams, params, body, captureValues) =>
844+
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
832845
if (arrow)
833846
print("(arrow-lambda<")
834847
else
@@ -843,7 +856,8 @@ object Printers {
843856
print(" = ")
844857
print(value)
845858
}
846-
printRow(params, ">(", ", ", ") = ")
859+
print(">")
860+
printSig(params, restParam, AnyType)
847861
printBlock(body)
848862
print(')')
849863

@@ -944,28 +958,28 @@ object Printers {
944958
print("def ")
945959
print(name)
946960
print(originalName)
947-
printSig(args, resultType)
961+
printSig(args, restParam = None, resultType)
948962
body.fold {
949963
print("<abstract>")
950964
} { body =>
951965
printBlock(body)
952966
}
953967

954968
case tree: JSMethodDef =>
955-
val JSMethodDef(flags, name, args, body) = tree
969+
val JSMethodDef(flags, name, args, restParam, body) = tree
956970
print(tree.optimizerHints)
957971
print(flags.namespace.prefixString)
958972
print("def ")
959973
printJSMemberName(name)
960-
printSig(args, AnyType)
974+
printSig(args, restParam, AnyType)
961975
printBlock(body)
962976

963977
case JSPropertyDef(flags, name, getterBody, setterArgAndBody) =>
964978
getterBody foreach { body =>
965979
print(flags.namespace.prefixString)
966980
print("get ")
967981
printJSMemberName(name)
968-
printSig(Nil, AnyType)
982+
printSig(Nil, None, AnyType)
969983
printBlock(body)
970984
}
971985

@@ -977,7 +991,7 @@ object Printers {
977991
print(flags.namespace.prefixString)
978992
print("set ")
979993
printJSMemberName(name)
980-
printSig(arg :: Nil, NoType)
994+
printSig(arg :: Nil, None, NoType)
981995
printBlock(body)
982996
}
983997

ir/shared/src/main/scala/org/scalajs/ir/Serializers.scala

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -546,11 +546,11 @@ object Serializers {
546546
writeTagAndPos(TagThis)
547547
writeType(tree.tpe)
548548

549-
case Closure(arrow, captureParams, params, body, captureValues) =>
549+
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
550550
writeTagAndPos(TagClosure)
551551
writeBoolean(arrow)
552552
writeParamDefs(captureParams)
553-
writeParamDefs(params)
553+
writeParamDefs(params, restParam)
554554
writeTree(body)
555555
writeTrees(captureValues)
556556

@@ -653,7 +653,7 @@ object Serializers {
653653
bufferUnderlying.continue()
654654

655655
case methodDef: JSMethodDef =>
656-
val JSMethodDef(flags, name, args, body) = methodDef
656+
val JSMethodDef(flags, name, args, restParam, body) = methodDef
657657

658658
writeByte(TagJSMethodDef)
659659
writeOptHash(methodDef.hash)
@@ -664,7 +664,7 @@ object Serializers {
664664

665665
// Write out method def
666666
writeInt(MemberFlags.toBits(flags)); writeTree(name)
667-
writeParamDefs(args); writeTree(body)
667+
writeParamDefs(args, restParam); writeTree(body)
668668
writeInt(OptimizerHints.toBits(methodDef.optimizerHints))
669669

670670
// Jump back and write true length
@@ -770,18 +770,26 @@ object Serializers {
770770
buffer.writeInt(encodedNameToIndex(originalName.get))
771771
}
772772

773-
def writeParamDef(paramDef: ParamDef): Unit = {
773+
def writeParamDef(paramDef: ParamDef, rest: Boolean = false): Unit = {
774+
// rest is tmp for backwards compat testing.
774775
writePosition(paramDef.pos)
775776
writeLocalIdent(paramDef.name)
776777
writeOriginalName(paramDef.originalName)
777778
writeType(paramDef.ptpe)
778779
buffer.writeBoolean(paramDef.mutable)
779-
buffer.writeBoolean(paramDef.rest)
780+
buffer.writeBoolean(rest)
780781
}
781782

782-
def writeParamDefs(paramDefs: List[ParamDef]): Unit = {
783-
buffer.writeInt(paramDefs.size)
784-
paramDefs.foreach(writeParamDef)
783+
def writeParamDefs(paramDefs: List[ParamDef],
784+
restParamDef: Option[ParamDef] = None): Unit = {
785+
// restParamDef is tmp for backwards compat testing.
786+
val totalSize =
787+
if (restParamDef.isEmpty) paramDefs.size
788+
else paramDefs.size + 1
789+
790+
buffer.writeInt(totalSize)
791+
paramDefs.foreach(writeParamDef(_))
792+
restParamDef.foreach(writeParamDef(_, rest = true))
785793
}
786794

787795
def writeType(tpe: Type): Unit = {
@@ -1171,8 +1179,10 @@ object Serializers {
11711179
case TagThis =>
11721180
This()(readType())
11731181
case TagClosure =>
1174-
Closure(readBoolean(), readParamDefs(), readParamDefs(), readTree(),
1175-
readTrees())
1182+
val arrow = readBoolean()
1183+
val captureParams = readParamDefs()
1184+
val (params, restParam) = readParamDefsWithRest()
1185+
Closure(arrow, captureParams, params, restParam, readTree(), readTrees())
11761186
case TagCreateJSClass =>
11771187
CreateJSClass(readClassName(), readTrees())
11781188
}
@@ -1315,8 +1325,11 @@ object Serializers {
13151325
// read and discard the length
13161326
val len = readInt()
13171327
assert(len >= 0)
1318-
JSMethodDef(MemberFlags.fromBits(readInt()), readTree(),
1319-
readParamDefs(), readTree())(
1328+
1329+
val flags = MemberFlags.fromBits(readInt())
1330+
val name = readTree()
1331+
val (params, restParam) = readParamDefsWithRest()
1332+
JSMethodDef(flags, name, params, restParam, readTree())(
13201333
OptimizerHints.fromBits(readInt()), optHash)
13211334

13221335
case TagJSPropertyDef =>
@@ -1402,13 +1415,46 @@ object Serializers {
14021415

14031416
def readParamDef(): ParamDef = {
14041417
implicit val pos = readPosition()
1405-
ParamDef(readLocalIdent(), readOriginalName(), readType(), readBoolean(),
1406-
readBoolean())
1418+
val name = readLocalIdent()
1419+
val originalName = readOriginalName()
1420+
val ptpe = readType()
1421+
val mutable = readBoolean()
1422+
1423+
if (true) { // tmp: test backwards compat
1424+
val rest = readBoolean()
1425+
assert(!rest, "Illegal rest parameter")
1426+
}
1427+
1428+
ParamDef(name, originalName, ptpe, mutable)
14071429
}
14081430

14091431
def readParamDefs(): List[ParamDef] =
14101432
List.fill(readInt())(readParamDef())
14111433

1434+
def readParamDefsWithRest(): (List[ParamDef], Option[ParamDef]) = {
1435+
if (true) { // tmp: test backwards compat
1436+
val (params, isRest) = List.fill(readInt()) {
1437+
implicit val pos = readPosition()
1438+
(ParamDef(readLocalIdent(), readOriginalName(), readType(), readBoolean()), readBoolean())
1439+
}.unzip
1440+
1441+
if (isRest.forall(!_)) {
1442+
(params, None)
1443+
} else {
1444+
assert(isRest.init.forall(!_), "illegal non-last rest parameter")
1445+
(params.init, Some(params.last))
1446+
}
1447+
} else {
1448+
val params = readParamDefs()
1449+
1450+
val restParam =
1451+
if (readBoolean()) Some(readParamDef())
1452+
else None
1453+
1454+
(params, restParam)
1455+
}
1456+
}
1457+
14121458
def readType(): Type = {
14131459
val tag = readByte()
14141460
(tag: @switch) match {

ir/shared/src/main/scala/org/scalajs/ir/Transformers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ object Transformers {
203203

204204
// Atomic expressions
205205

206-
case Closure(arrow, captureParams, params, body, captureValues) =>
207-
Closure(arrow, captureParams, params, transformExpr(body),
206+
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
207+
Closure(arrow, captureParams, params, restParam, transformExpr(body),
208208
captureValues.map(transformExpr))
209209

210210
case CreateJSClass(className, captureValues) =>
@@ -248,8 +248,8 @@ object Transformers {
248248
memberDef.optimizerHints, None)
249249

250250
case memberDef: JSMethodDef =>
251-
val JSMethodDef(flags, name, args, body) = memberDef
252-
JSMethodDef(flags, name, args, transformExpr(body))(
251+
val JSMethodDef(flags, name, args, restParam, body) = memberDef
252+
JSMethodDef(flags, name, args, restParam, transformExpr(body))(
253253
memberDef.optimizerHints, None)
254254

255255
case JSPropertyDef(flags, name, getterBody, setterArgAndBody) =>

0 commit comments

Comments
 (0)