8000 Replace topoSortDistinctsBy with topoSortDistinctsWith by gzm0 · Pull Request #4462 · scala-js/scala-js · GitHub
[go: up one dir, main page]

Skip to content

Replace topoSortDistinctsBy with topoSortDistinctsWith #4462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 6, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 19 additions & 36 deletions compiler/src/main/scala/org/scalajs/nscplugin/GenJSExports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,22 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
} else {
// Sort them so that, e.g., isInstanceOf[String]
// comes before isInstanceOf[Object]
val sortedAltsByTypeTest = topoSortDistinctsBy(
altsByTypeTest)(_._1)(RTTypeTest.Ordering)
val sortedAltsByTypeTest = topoSortDistinctsWith(altsByTypeTest) { (lhs, rhs) =>
(lhs._1, rhs._1) match {
// NoTypeTest is always last
case (_, NoTypeTest) => true
case (NoTypeTest, _) => false

case (PrimitiveTypeTest(_, rank1), PrimitiveTypeTest(_, rank2)) =>
rank1 <= rank2

case (InstanceOfTypeTest(t1), InstanceOfTypeTest(t2)) =>
t1 <:< t2

case (_: PrimitiveTypeTest, _: InstanceOfTypeTest) => true
case (_: InstanceOfTypeTest, _: PrimitiveTypeTest) => false
}
}

val defaultCase = genThrowTypeError()

Expand Down Expand Up @@ -946,47 +960,16 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {

private case object NoTypeTest extends RTTypeTest

private object RTTypeTest {
implicit object Ordering extends PartialOrdering[RTTypeTest] {
override def tryCompare(lhs: RTTypeTest, rhs: RTTypeTest): Option[Int] = {
if (lteq(lhs, rhs)) if (lteq(rhs, lhs)) Some(0) else Some(-1)
else if (lteq(rhs, lhs)) Some(1) else None
}

override def lteq(lhs: RTTypeTest, rhs: RTTypeTest): Boolean = {
(lhs, rhs) match {
// NoTypeTest is always last
case (_, NoTypeTest) => true
case (NoTypeTest, _) => false

case (PrimitiveTypeTest(_, rank1), PrimitiveTypeTest(_, rank2)) =>
rank1 <= rank2

case (InstanceOfTypeTest(t1), InstanceOfTypeTest(t2)) =>
t1 <:< t2

case (_: PrimitiveTypeTest, _: InstanceOfTypeTest) => true
case (_: InstanceOfTypeTest, _: PrimitiveTypeTest) => false
}
}

override def equiv(lhs: RTTypeTest, rhs: RTTypeTest): Boolean = {
lhs == rhs
}
}
}

// Very simple O(n²) topological sort for elements assumed to be distinct
private def topoSortDistinctsBy[A <: AnyRef, B](coll: List[A])(f: A => B)(
implicit ord: PartialOrdering[B]): List[A] = {

private def topoSortDistinctsWith[A <: AnyRef](coll: List[A])(
lteq: (A, A) => Boolean): List[A] = {
@scala.annotation.tailrec
def loop(coll: List[A], acc: List[A]): List[A] = {
if (coll.isEmpty) acc
else if (coll.tail.isEmpty) coll.head :: acc
else {
val (lhs, rhs) = coll.span(x => !coll.forall(
y => (x eq y) || !ord.lteq(f(x), f(y))))
y => (x eq y) || !lteq(x, y)))
assert(!rhs.isEmpty, s"cycle while ordering $coll")
loop(lhs ::: rhs.tail, rhs.head :: acc)
}
Expand Down
0