8000 Merge pull request #5003 from sjrd/typed-closures · sjrd/scala-js@fec4ae7 · GitHub
[go: up one dir, main page]

Skip to content

Commit fec4ae7

Browse files
authored
Merge pull request scala-js#5003 from sjrd/typed-closures
Introduce NewLambda to synthesize instances of SAM types.
2 parents e7b4f69 + 53dc4fe commit fec4ae7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1719
-317
lines changed

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

Lines changed: 224 additions & 114 deletions
Large diffs are not rendered by default.

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

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,24 @@ object Hashers {
306306
mixMethodIdent(method)
307307
mixTrees(args)
308308

309+
case ApplyTypedClosure(flags, fun, args) =>
310+
mixTag(TagApplyTypedClosure)
311+
mixInt(ApplyFlags.toBits(flags))
312+
mixTree(fun)
313+
mixTrees(args)
314+
315+
case NewLambda(descriptor, fun) =>
316+
val NewLambda.Descriptor(superClass, interfaces, methodName, paramTypes, resultType) =
317+
descriptor
318+
mixTag(TagNewLambda)
319+
mixName(superClass)
320+
mixNames(interfaces)
321+
mixMethodName(methodName)
322+
mixTypes(paramTypes)
323+
mixType(resultType)
324+
mixTree(fun)
325+
mixType(tree.tpe)
326+
309327
case UnaryOp(op, lhs) =>
310328
mixTag(TagUnaryOp)
311329
mixInt(op)
@@ -506,12 +524,20 @@ object Hashers {
506524
}
507525
mixType(tree.tpe)
508526

509-
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
527+
case Closure(flags, captureParams, params, restParam, resultType, body, captureValues) =>
510528
mixTag(TagClosure)
511-
mixBoolean(arrow)
529+
mixByte(ClosureFlags.toBits(flags).toByte)
512530
mixParamDefs(captureParams)
513531
mixParamDefs(params)
514-
restParam.foreach(mixParamDef(_))
532+
if (flags.typed) {
533+
if (restParam.isDefined)
534+
throw new InvalidIRException(tree, "Cannot hash a typed closure with a rest param")
535+
mixType(resultType)
536+
} else {
537+
if (resultType != AnyType)
538+
throw new InvalidIRException(tree, "Cannot hash a JS closure with a result type != AnyType")
539+
restParam.foreach(mixParamDef(_))
540+
}
515541
mixTree(body)
516542
mixTrees(captureValues)
517543

@@ -572,6 +598,10 @@ object Hashers {
572598
case typeRef: ArrayTypeRef =>
573599
mixTag(TagArrayTypeRef)
574600
mixArrayTypeRef(typeRef)
601+
case TransientTypeRef(name) =>
602+
mixTag(TagTransientTypeRefHashingOnly)
603+
mixName(name)
604+
// The `tpe` is intentionally ignored here; see doc of `TransientTypeRef`.
575605
}
576606

577607
def mixArrayTypeRef(arrayTypeRef: ArrayTypeRef): Unit = {
@@ -604,6 +634,11 @@ object Hashers {
604634
mixTag(if (nullable) TagArrayType else TagNonNullArrayType)
605635
mixArrayTypeRef(arrayTypeRef)
606636

637+
case ClosureType(paramTypes, resultType, nullable) =>
638+
mixTag(if (nullable) TagClosureType else TagNonNullClosureType)
639+
mixTypes(paramTypes)
640+
mixType(resultType)
641+
607642
case RecordType(fields) =>
608643
mixTag(TagRecordType)
609644
for (RecordType.Field(name, originalName, tpe, mutable) <- fields) {
@@ -614,6 +649,9 @@ object Hashers {
614649
}
615650
}
616651

652+
10000 def mixTypes(tpes: List[Type]): Unit =
653+
tpes.foreach(mixType)
654+
617655
def mixLocalIdent(ident: LocalIdent): Unit = {
618656
mixPos(ident.pos)
619657
mixName(ident.name)
@@ -644,6 +682,11 @@ object Hashers {
644682
def mixName(name: Name): Unit =
645683
mixBytes(name.encoded.bytes)
646684

685+
def mixNames(names: List[Name]): Unit = {
686+
mixInt(names.size)
687+
names.foreach(mixName(_))
688+
}
689+
647690
def mixMethodName(name: MethodName): Unit = {
648691
mixName(name.simpleName)
649692
mixInt(name.paramTypeRefs.size)

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,12 @@
1212

1313
package org.scalajs.ir
1414

15-
class InvalidIRException(val tree: Trees.IRNode, message: String)
16-
extends Exception(message)
15+
class InvalidIRException(val optTree: Option[Trees.IRNode], message: String)
16+
extends Exception(message) {
17+
18+
def this(tree: Trees.IRNode, message: String) =
19+
this(Some(tree), message)
20+
21+
def this(message: String) =
22+
this(None, message)
23+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ object Names {
436436
i += 1
437437
}
438438
appendTypeRef(base)
439+
case TransientTypeRef(name) =>
440+
builder.append('t').append(name.nameString)
439441
}
440442

441443
builder.append(simpleName.nameString)

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

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ object Printers {
7777
print(end)
7878
}
7979

80+
protected final def printRow(ts: List[Type], start: String, sep: String,
81+
end: String)(implicit dummy: DummyImplicit): Unit = {
82+
print(start)
83+
var rest = ts
84+
while (rest.nonEmpty) {
85+
print(rest.head)
86+
rest = rest.tail
87+
if (rest.nonEmpty)
88+
print(sep)
89+
}
90+
print(end)
91+
}
92+
8093
protected def printBlock(tree: Tree): Unit = {
8194
val trees = tree match {
8295
case Block(trees) => trees
@@ -340,6 +353,40 @@ object Printers {
340353
print(method)
341354
printArgs(args)
342355

356+
case ApplyTypedClosure(flags, fun, args) =>
357+
print(fun)
358+
printArgs(args)
359+
360+
case NewLambda(descriptor, fun) =>
361+
val NewLambda.Descriptor(superClass, interfaces, methodName, paramTypes, resultType) =
362+
descriptor
363+
364+
print("<newLambda>("); indent(); println()
365+
366+
print("extends ")
367+
print(superClass)
368+
if (interfaces.nonEmpty) {
369+
print(" implements ")
370+
print(interfaces.head)
371+
for (intf <- interfaces.tail) {
372+
print(", ")
373+
print(intf)
374+
}
375+
}
376+
print(',')
377+
println()
378+
379+
print("def ")
380+
print(methodName)
381+
printRow(paramTypes, "(", ", ", "): ")
382+
print(resultType)
383+
print(',')
384+
println()
385+
386+
print(fun)
387+
388+
undent(); println(); print(')')
389+
343390
case UnaryOp(op, lhs) =>
344391
import UnaryOp._
345392

@@ -848,8 +895,10 @@ object Printers {
848895
else
849896
print(name)
850897

851-
case Closure(arrow, captureParams, params, restParam, body, captureValues) =>
852-
if (arrow)
898+
case Closure(flags, captureParams, params, restParam, resultType, body, captureValues) =>
899+
if (flags.typed)
900+
print("(typed-lambda<")
901+
else if (flags.arrow)
853902
print("(arrow-lambda<")
854903
else
855904
print("(lambda<")
@@ -864,7 +913,7 @@ object Printers {
864913
print(value)
865914
}
866915
print(">")
867-
printSig(params, restParam, AnyType)
916+
printSig(params, restParam, resultType)
86 10000 8917
printBlock(body)
869918
print(')')
870919

@@ -1062,6 +1111,8 @@ object Printers {
10621111
print(base)
10631112
for (i <- 1 to dims)
10641113
print("[]")
1114+
case TransientTypeRef(name) =>
1115+
print(name)
10651116
}
10661117

10671118
def print(tpe: Type): Unit = tpe match {
@@ -1091,6 +1142,13 @@ object Printers {
10911142
if (!nullable)
10921143
print("!")
10931144

1145+
case ClosureType(paramTypes, resultType, nullable) =>
1146+
printRow(paramTypes, "((", ", ", ") => ")
1147+
print(resultType)
1148+
print(')')
1149+
if (!nullable)
1150+
print('!')
1151+
10941152
case RecordType(fields) =>
10951153
print('(')
10961154
var first = true

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import scala.util.matching.Regex
1818

1919
object ScalaJSVersions extends VersionChecks(
2020
current = "1.19.0-SNAPSHOT",
21-
binaryEmitted = "1.18"
21+
binaryEmitted = "1.19-SNAPSHOT"
2222
)
2323

2424
/** Helper class to allow for testing of logic. */

0 commit comments

Comments
 (0)
0