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

rescala.operator.DefaultImplementations.scala Maven / Gradle / Ivy

There is a newer version: 0.35.1
Show newest version
package rescala.operator

import rescala.core._
import rescala.operator.Pulse.NoChange

trait DefaultImplementations {
  self: Operators =>

  /** @param isDynamicWithStaticDeps None means static dependencies only,
    *                                Some means dynamic with the given static ones for optimization
    */
  class SignalImpl[T](
      initial: State[Pulse[T]],
      expr: (DynamicTicket, () => T) => T,
      name: ReInfo,
      isDynamicWithStaticDeps: Option[Set[ReSource.of[State]]]
  ) extends DerivedImpl[T](initial, name, isDynamicWithStaticDeps) with Signal[T] {

    protected[this] def computePulse(rein: ReevTicket[State, Pulse[T]]): Pulse[T] = {
      Pulse.tryCatch(Pulse.diffPulse(expr(rein, () => rein.before.get), rein.before))
    }
  }

  abstract class DerivedImpl[T](
      initial: State[Pulse[T]],
      name: ReInfo,
      isDynamicWithStaticDeps: Option[Set[ReSource.of[State]]]
  ) extends Base[State, Pulse[T]](initial, name)
      with Derived
      with DisconnectableImpl {

    override type State[V] = self.State[V]

    override protected[rescala] def guardedReevaluate(rein: ReIn): Rout = {
      val rein2 = isDynamicWithStaticDeps match {
        case None       => rein.trackStatic()
        case Some(deps) => rein.trackDependencies(deps)
      }
      val newPulse = computePulse(rein2)
      if (newPulse.isChange) rein2.withValue(newPulse) else rein2
    }
    protected[this] def computePulse(rein: ReevTicket[State, Pulse[T]]): Pulse[T]
  }

  /** @param isDynamicWithStaticDeps If this is None, the event is static. Else, it is dynamic with the set of static dependencies */
  class EventImpl[T](
      initial: State[Pulse[T]],
      expr: self.DynamicTicket => Pulse[T],
      name: ReInfo,
      isDynamicWithStaticDeps: Option[Set[ReSource.of[State]]]
  ) extends DerivedImpl[T](initial, name, isDynamicWithStaticDeps)
      with Event[T] {

    override protected[rescala] def commit(base: Pulse[T]): Pulse[T] = Pulse.NoChange
    override def internalAccess(v: Pulse[T]): Pulse[T]               = v
    override protected[this] def computePulse(rein: ReevTicket[State, Pulse[T]]): Pulse[T] =
      Pulse.tryCatch(expr(rein), onEmpty = NoChange)
  }

  class ChangeEventImpl[T](
      _bud: State[(Pulse[T], Pulse[Diff[T]])],
      signal: Signal[T],
      name: ReInfo
  ) extends Base[State, (Pulse[T], Pulse[Diff[T]])](_bud, name)
      with Derived
      with Event[Diff[T]]
      with DisconnectableImpl {

    override type Value = (Pulse[T], Pulse[Diff[T]])

    override protected[rescala] def commit(base: (Pulse[T], Pulse[Diff[T]])): (Pulse[T], Pulse[Diff[T]]) =
      base.copy(_2 = Pulse.NoChange)
    override def internalAccess(v: (Pulse[T], Pulse[Diff[T]])): Pulse[Diff[T]] = v._2
    override def read(v: Value): Option[Diff[T]]                               = v._2.toOption

    override protected[rescala] def guardedReevaluate(rein: ReIn): Rout = {
      val to: Pulse[T]   = rein.collectStatic(signal)
      val from: Pulse[T] = rein.before._1
      if (to == Pulse.empty) rein // ignore empty propagations
      else if (from != Pulse.NoChange) rein.withValue((to, Pulse.Value(Diff(from, to))))
      else rein.withValue((to, Pulse.NoChange)).withPropagate(false)
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy