All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalanative.linker.Linker.scala Maven / Gradle / Ivy

The newest version!
package scala.scalanative
package linker

import scala.collection.mutable
import scalanative.nir._
import scalanative.nir.serialization._
import scalanative.io.VirtualDirectory
import scalanative.util.Scope

import ReflectiveProxy._

sealed trait Linker {

  /** Link the whole world under closed world assumption. */
  def link(entries: Seq[Global]): Result
}

object Linker {

  /** Create a new linker given tools configuration. */
  def apply(config: tools.Config,
            reporter: Reporter = Reporter.empty): Linker =
    new Impl(config, reporter)

  private final class Impl(config: tools.Config, reporter: Reporter)
      extends Linker {
    import reporter._

    def link(entries: Seq[Global]): Result = Scope { implicit in =>
      val resolved    = mutable.Set.empty[Global]
      val unresolved  = mutable.Set.empty[Global]
      val links       = mutable.Set.empty[Attr.Link]
      val defns       = mutable.UnrolledBuffer.empty[Defn]
      val direct      = mutable.Stack.empty[Global]
      var conditional = mutable.UnrolledBuffer.empty[Dep.Conditional]
      val weaks       = mutable.Set.empty[Global]
      val signatures  = mutable.Set.empty[String]
      val dyndefns    = mutable.Set.empty[Global]

      val paths = config.paths.map(p => ClassPath(VirtualDirectory.real(p)))
      def load(global: Global) =
        paths.collectFirst {
          case path if path.contains(global) =>
            path.load(global)
        }.flatten

      def processDirect =
        while (direct.nonEmpty) {
          val workitem = direct.pop()
          if (!workitem.isIntrinsic && !resolved.contains(workitem) &&
              !unresolved.contains(workitem)) {

            load(workitem).fold[Unit] {
              unresolved += workitem
              onUnresolved(workitem)
            } {
              case (deps, newlinks, newsignatures, defn) =>
                resolved += workitem
                defns += defn
                links ++= newlinks
                signatures ++= newsignatures

                // Comparing new signatures with already collected weak dependencies
                newsignatures
                  .flatMap(signature =>
                    weaks.collect {
                      case weak if Global.genSignature(weak) == signature =>
                        weak
                  })
                  .foreach { global =>
                    direct.push(global)
                    dyndefns += global
                  }

                onResolved(workitem)

                deps.foreach {
                  case Dep.Direct(dep) =>
                    direct.push(dep)
                    onDirectDependency(workitem, dep)

                  case cond @ Dep.Conditional(dep, condition) =>
                    conditional += cond
                    onConditionalDependency(workitem, dep, condition)

                  case Dep.Weak(global) =>
                    // comparing new dependencies with all signatures
                    if (signatures(Global.genSignature(global))) {
                      direct.push(global)
                      onDirectDependency(workitem, global)
                      dyndefns += global
                    }
                    weaks += global
                }

            }
          }
        }

      def processConditional = {
        val rest = mutable.UnrolledBuffer.empty[Dep.Conditional]

        conditional.foreach {
          case Dep.Conditional(dep, cond)
              if resolved.contains(dep) || unresolved.contains(dep) =>
            ()

          case Dep.Conditional(dep, cond) if resolved.contains(cond) =>
            direct.push(dep)

          case dep =>
            rest += dep
        }

        conditional = rest
      }

      onStart()

      entries.foreach { entry =>
        direct.push(entry)
        onEntry(entry)
      }

      while (direct.nonEmpty) {
        processDirect
        processConditional
      }

      val reflectiveProxies =
        genAllReflectiveProxies(dyndefns, defns)

      val defnss = defns ++ reflectiveProxies

      onComplete()

      Result(unresolved.toSeq,
             links.toSeq,
             defnss.sortBy(_.name.toString),
             signatures.toSeq)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy