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

tofu.data.calc.CalcRunner.scala Maven / Gradle / Ivy

package tofu.data.calc

import tofu.data.Nothing2T

import scala.annotation.tailrec

trait CalcRunner[-F[+_, +_]] {
  def apply[R, SI, SO, E, A, X](calc: CalcM[F, R, SI, SO, E, A])(r: R, init: SI, cont: Continue[A, E, SO, X]): X

  def runPair[R, SI, SO, E, A](calc: CalcM[F, R, SI, SO, E, A])(r: R, init: SI): (SO, Either[E, A]) = {
    val cont = new Continue[A, E, SO, (SO, Either[E, A])] {
      def success(s: SO, a: A): (SO, Either[E, A]) = (s, Right(a))
      def error(s: SO, e: E): (SO, Either[E, A])   = (s, Left(e))
    }
    apply(calc)(r, init, cont)
  }
}

object CalcRunner extends LowPriorRunner {
  implicit val nothingRunner: CalcRunner[Nothing] = nothing2TRunner
}

trait LowPriorRunner { self: CalcRunner.type =>
  // scala 2.12 instance for use when Nothing breaks implicit search
  implicit val nothing2TRunner: CalcRunner[Nothing2T] = new CalcRunner[Nothing2T] {

    @tailrec
    override final def apply[R, SI, SO, E, A, X](
        calc: CalcM[Nothing2T, R, SI, SO, E, A]
    )(r: R, init: SI, cont: Continue[A, E, SO, X]): X =
      calc match {
        case res: CalcM.CalcMRes[R, SI, SO, E, A]                                                           => res.submit(r, init, cont)
        case d: CalcM.Defer[Nothing2T, R, ?, ?, ?, ?]                                                       => apply(d.runStep())(r, init, cont)
        case m: CalcM.ProvideM[
              Nothing2T @unchecked,
              R @unchecked,
              SI @unchecked,
              SO @unchecked,
              E @unchecked,
              A @unchecked
            ] =>
          apply(m.inner)(m.r, init, cont)
        case sub: CalcM.Sub[Nothing2T @unchecked, SI @unchecked, SO @unchecked, E @unchecked, A @unchecked] => sub.fa
        case b1: CalcM.Bound[
              Nothing2T @unchecked,
              R @unchecked,
              SI @unchecked,
              sm,
              SO @unchecked,
              em,
              E @unchecked,
              am,
              A @unchecked
            ] =>
          type SM = sm
          type EM = em
          type AM = am
          b1.src match {
            case res: CalcM.CalcMRes[R, SI, SM, EM, AM]                                                  =>
              val (st, next) = res.submit(r, init, b1.continue.withState[sm])
              apply(next)(r, st, cont)
            case d: CalcM.Defer[Nothing2T, R, SI, SM, EM, AM]                                            =>
              apply(d.runStep().bind(b1.continue))(r, init, cont)
            case m: CalcM.ProvideM[
                  Nothing2T @unchecked,
                  R @unchecked,
                  SI @unchecked,
                  SM @unchecked,
                  EM @unchecked,
                  AM @unchecked
                ] =>
              type Cont[r] = Continue[am, em, sm, CalcM[Nothing2T, r, sm, SO, E, A]]
              val kcont = m.any.substitute[Cont](b1.continue)
              apply(m.inner.bind(kcont))(m.r, init, cont)
            case sub: CalcM.Sub[Nothing2T @unchecked, ?, ?, ?, ?]                                        => sub.fa
            case b2: CalcM.Bound[Nothing2T @unchecked, R @unchecked, SI @unchecked, sp, ?, ep, ?, ap, ?] =>
              apply(b2.src.bind(Continue.compose(b2.continue, b1.continue)))(r, init, cont)
          }
      }

  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy