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

libretto.scaletto.impl.futurebased.BridgeImpl.scala Maven / Gradle / Ivy

The newest version!
package libretto.scaletto.impl.futurebased

import libretto.exec.Executing
import libretto.exec.Executor.CancellationReason
import libretto.lambda.util.SourcePos
import libretto.scaletto.ScalettoBridge
import libretto.scaletto.impl.FreeScaletto
import libretto.util.{Async, Scheduler}
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.FiniteDuration

object BridgeImpl extends ScalettoBridge {
  override type Dsl = FreeScaletto.type
  override val dsl: FreeScaletto.type = FreeScaletto
  import dsl.{-⚬, =⚬, |*|, |+|, |&|, Done, One, Need, Ping, Pong, Val}

  override opaque type Execution <: libretto.exec.Execution =
    ExecutionImpl

  def execute[A, B](prg: A -⚬ B)(
    ec: ExecutionContext,
    scheduler: Scheduler,
    blockingEC: ExecutionContext,
  ): Executing[this.type, A, B] = {
    val execution = new ExecutionImpl(new ResourceRegistry, blockingEC)(using ec, scheduler)
    val (in, out) = execution.execute(prg)
    Executing(using this)(execution, in, out)
  }

  def cancelExecution(exn: Execution, pos: SourcePos): Async[Unit] =
    exn.cancel(pos)

  def watchForCancellation(exn: Execution): Async[CancellationReason] =
    exn.watchForCancellation()

  extension [I](using exn: Execution)(port: exn.InPort[I]) {
    override def prepend[H](f: H -⚬ I): exn.InPort[H] =
      exn.InPort.contramap(port)(f)

    override def zipIn[J](that: exn.InPort[J]): (exn.InPort[I |*| J]) =
      exn.InPort.pair(port, that)
  }

  extension (using exn: Execution)(port: exn.InPort[One]) {
    override def dischargeOne(): Unit =
      exn.InPort.discardOne(port)
  }

  extension (using exn: Execution)(port: exn.InPort[Done]) {
    override def supplyDone(): Unit =
      exn.InPort.supplyDone(port)
  }

  extension [A, B](using exn: Execution)(port: exn.InPort[A |*| B]) {
    override def unzipIn(): (exn.InPort[A], exn.InPort[B]) =
      exn.InPort.split(port)
  }

  extension [A, B](using exn: Execution)(port: exn.InPort[A |+| B]) {
    override def injectLeft(): exn.InPort[A]  = exn.InPort.supplyLeft(port)
    override def injectRight(): exn.InPort[B] = exn.InPort.supplyRight(port)
  }

  extension [A, B](using exn: Execution)(port: exn.InPort[A |&| B]) {
    def awaitChoice(): Async[Either[Throwable, Either[exn.InPort[A], exn.InPort[B]]]] =
      exn.InPort.supplyChoice(port)
  }

  extension [A](using exn: Execution)(port: exn.OutPort[A]) {
    override def append[B](f: A -⚬ B): exn.OutPort[B] =
      exn.OutPort.map(port)(f)

    override def zip[B](that: exn.OutPort[B]): exn.OutPort[A |*| B] =
      exn.OutPort.pair(port, that)
  }

  extension (using exn: Execution)(port: exn.OutPort[One]) {
    override def discardOne(): Unit =
      exn.OutPort.discardOne(port)
  }

  extension (using exn: Execution)(port: exn.OutPort[Done]) {
    override def awaitDone(): Async[Either[Throwable, Unit]] =
      exn.OutPort.awaitDone(port)
  }

  extension (using exn: Execution)(port: exn.OutPort[Ping]) {
    override def awaitPing(): Async[Either[Throwable, Unit]] =
      exn.OutPort.awaitPing(port)

    override def awaitNoPing(
      duration: FiniteDuration,
    ): Async[Either[Either[Throwable, Unit], exn.OutPort[Ping]]] =
      exn.OutPort.awaitNoPing(port, duration)
  }

  extension (using exn: Execution)(port: exn.OutPort[Need]) {
    override def supplyNeed(): Unit =
      exn.OutPort.supplyNeed(port)
  }

  extension (using exn: Execution)(port: exn.OutPort[Pong]) {
    override def supplyPong(): Unit =
      exn.OutPort.supplyPong(port)
  }

  extension [A, B](using exn: Execution)(port: exn.OutPort[A |*| B]) {
    override def unzip(): (exn.OutPort[A], exn.OutPort[B]) =
      exn.OutPort.split(port)
  }

  extension [A, B](using exn: Execution)(port: exn.OutPort[A |+| B]) {
    override def awaitEither(): Async[Either[Throwable, Either[exn.OutPort[A], exn.OutPort[B]]]] =
      exn.OutPort.awaitEither(port)
  }

  extension [A, B](using exn: Execution)(port: exn.OutPort[A |&| B]) {
    override def chooseLeft(): exn.OutPort[A]  = exn.OutPort.chooseLeft(port)
    override def chooseRight(): exn.OutPort[B] = exn.OutPort.chooseRight(port)
  }

  extension [I, O](using exn: Execution)(port: exn.InPort[I =⚬ O]) {
    override def simulateFunction(): (exn.OutPort[I], exn.InPort[O]) =
      exn.InPort.functionInputOutput(port)
  }

  extension [I, O](using exn: Execution)(port: exn.OutPort[I =⚬ O]) {
    override def useFunction(): (exn.InPort[I], exn.OutPort[O]) =
      exn.OutPort.functionInputOutput(port)
  }

  extension [A](using exn: Execution)(port: exn.InPort[Val[A]]) {
    override def supplyVal(value: A): Unit =
      exn.InPort.supplyVal(port, value)
  }

  extension [A](using exn: Execution)(port: exn.OutPort[Val[A]]) {
    override def awaitVal(): Async[Either[Throwable, A]] =
      exn.OutPort.awaitVal(port)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy