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

kyo.kernel.Effect.scala Maven / Gradle / Ivy

The newest version!
package kyo.kernel

import internal.*
import kyo.Frame
import scala.annotation.nowarn
import scala.util.control.NonFatal

/** The base trait for all effects in the Kyo effect system.
  *
  * When code performs an effectful operation, instead of executing immediately, effects create a suspended computation that captures what
  * needs to be done. These suspended computations can then be interpreted in different ways through effect handlers.
  *
  * This suspension mechanism is the foundation of Kyo's effect system. It allows effectful code to be pure and composable - rather than
  * performing operations directly, code builds up a description of what operations should occur. This description can then be interpreted
  * by handlers that determine how the operations are actually executed.
  *
  * There are two kinds of effects:
  *   - [[ArrowEffect]] for suspended computations involving input/output transformations.
  *   - [[ContextEffect]] for suspended computations requiring contextual values.
  */
abstract class Effect private[kernel] ()

object Effect:

    /** Wraps a computation with error handling.
      *
      * This method allows you to catch and handle exceptions that might occur during the execution of a computation. The error handler `f`
      * will be called if a non-fatal exception occurs either during the initial evaluation or during any subsequent effect operations.
      *
      * @param v
      *   the effect computation to protect
      * @param f
      *   the error handler function that takes a Throwable and returns a new effect
      * @return
      *   a new effect that will either complete normally or handle exceptions using the provided handler
      */
    inline def catching[A, S, B >: A, S2](inline v: => A < S)(
        inline f: Throwable => B < S2
    )(using inline _frame: Frame, safepoint: Safepoint): B < (S & S2) =
        @nowarn("msg=anonymous")
        def catchingLoop(v: B < (S & S2))(using Safepoint): B < (S & S2) =
            (v: @unchecked) match
                case kyo: KyoSuspend[IX, OX, EX, Any, B, S & S2] @unchecked =>
                    new KyoContinue[IX, OX, EX, Any, B, S & S2](kyo):
                        def frame = _frame
                        def apply(v: OX[Any], context: Context)(using Safepoint) =
                            try catchingLoop(kyo(v, context))
                            catch
                                case ex: Throwable if NonFatal(ex) =>
                                    Safepoint.enrich(ex)
                                    f(ex)
                            end try
                        end apply
                case _ =>
                    v
        try catchingLoop(v)
        catch
            case ex: Throwable if NonFatal(ex) =>
                Safepoint.enrich(ex)
                f(ex)
        end try
    end catching

    private[kyo] def defer[A, S](f: Safepoint ?=> A < S)(using _frame: Frame): A < S =
        new KyoDefer[A, S]:
            def frame = _frame
            def apply(v: Unit, context: Context)(using Safepoint) =
                f
end Effect




© 2015 - 2025 Weber Informatics LLC | Privacy Policy