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

parsley.internal.deepembedding.PreservationAnalysis.scala Maven / Gradle / Ivy

The newest version!
package parsley.internal.deepembedding

import scala.collection.mutable
import parsley.internal.machine.instructions, instructions.Instr

private [deepembedding] object PreservationAnalysis {
    def determinePreserve(recs: Iterable[Rec[_]], instrs: Array[Instr]): Unit = if (recs.nonEmpty) {
        var start = System.currentTimeMillis()
        implicit val coordinator: EventCoordinator = new EventCoordinator
        val recReactors = mutable.ListBuffer.empty[(Rec[_], DataflowReactor)]
        val reactors = mutable.Map.empty[Int, DataflowReactor]
        val sources = mutable.Map.empty[Int, EventSource[Iterable[Int]]]
        val dependencies = new EventSource[(DataflowReactor, Int)]
        val topo = mutable.ListBuffer.empty[(Int, DataflowReactor)]
        // Build reactors and event streams
        def addToNetwork(label: Int, reactor: DataflowReactor): Unit = {
            reactors(label) = reactor
            for (dependency <- instructions.dependencies(instrs, label)) {
                dependencies.fire((reactor, dependency))
            }
            // Poor mans topological sort, it's not completely accurate
            // to make it accurate we'd have to form a graph in the _other_ direction
            // graph from dependency -> dependent as opposed to dependent -> dependencies
            (label -> reactor) +=: topo
        }
        for (rec <- recs) {
            val source = new EventSource[Iterable[Int]]
            val reactor = new DataflowReactor(rec.label, source)
            recReactors += (rec -> reactor)
            sources(rec.label) = source
            addToNetwork(rec.label, reactor)
        }
        for (relation <- dependencies) {
            val (dependent, label) = relation
            val source = sources.getOrElseUpdate(label, {
                val source = new EventSource[Iterable[Int]]
                addToNetwork(label, new DataflowReactor(label, source))
                source
            })
            source.foreach(dependent)
        }
        // Initialise dataflow
        coordinator.run()
        for ((label, reactor) <- topo) {
            reactor(instructions.statefulIndicesToReturn(instrs, label))
        }
        // Execute
        coordinator.run()
        for ((rec, reactor) <- recReactors) {
            rec.preserve = reactor.preserve
        }
    }
}

private [deepembedding] class DataflowReactor(label: Int, val source: EventSource[Iterable[Int]]) extends (Iterable[Int] => Unit) {
    private val preserveSet = mutable.Set.empty[Int]
    def apply(newInfo: Iterable[Int]): Unit = {
        val oldSize = preserveSet.size
        preserveSet ++= newInfo
        if (preserveSet.size > oldSize) {
            source.fire(preserveSet)
        }
    }
    def preserve: Array[Int] = preserveSet.toSeq.sorted.toArray
}

private [deepembedding] sealed trait Event[+A]
private [deepembedding] case class Fired[A](x: A, handlers: Iterable[A => Unit]) extends Event[A]
private [deepembedding] case class Handled(f: () => Unit) extends Event[Nothing]

private [deepembedding] class EventCoordinator {
    val events = mutable.Queue.empty[Event[_]]
    def add(event: Event[_]): Unit = events.enqueue(event)
    def run(): Unit = {
        while (events.nonEmpty) events.dequeue() match {
            case Fired(x, handlers) => for (handler <- handlers) add(Handled(() => handler(x)))
            case Handled(f) => f()
        }
    }
}

private [deepembedding] abstract class EventStream[+A] {
    def foreach(f: A => Unit): Unit
}

private [deepembedding] class EventSource[A](implicit coordinator: EventCoordinator) extends EventStream[A] {
    val observers = mutable.Set.empty[A => Unit]
    def fire(x: A): Unit = coordinator.add(Fired(x, observers))
    def foreach(f: A => Unit): Unit = observers += f
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy