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

commonMain.effekt.handler.kt Maven / Gradle / Ivy

Go to download

Provides fully-fledged multishot delimitied continuations in Kotlin with Coroutines

The newest version!
package effekt

import Prompt
import Reader
import abortS0
import abortWith0
import abortWithFast
import ask
import pushReader
import reset
import takeSubCont
import takeSubContOnce
import takeSubContWithFinal
import kotlin.jvm.JvmInline

public interface Handler {
  public fun prompt(): HandlerPrompt
}

public interface StatefulHandler : Handler {
  public val reader: Reader
}

public suspend fun  StatefulHandler.get(): S = reader.ask()

public suspend inline fun  Handler.use(crossinline body: suspend (Cont) -> E): A =
  prompt().prompt.takeSubCont { sk ->
    body(Cont(sk))
  }

public suspend inline fun  Handler.useOnce(crossinline body: suspend (Cont) -> E): A =
  prompt().prompt.takeSubContOnce { sk ->
    body(Cont(sk))
  }

public suspend inline fun  Handler.useWithFinal(crossinline body: suspend (Pair, Cont>) -> E): A =
  prompt().prompt.takeSubContWithFinal { sk ->
    body(Cont(sk.first) to Cont(sk.second))
  }

public fun  Handler.discard(body: suspend () -> E): Nothing = prompt().prompt.abortS0(body)

public fun  Handler.discardWith(value: Result): Nothing = prompt().prompt.abortWith0(value)

public suspend fun  Handler.discardWithFast(value: Result): Nothing = prompt().prompt.abortWithFast(deleteDelimiter = true, value)

public suspend fun  handle(
  handler: ((() -> HandlerPrompt) -> H), body: suspend H.() -> E
): E = handle { handler { this }.body() }

public suspend fun  handle(body: suspend HandlerPrompt.() -> E): E = with(HandlerPrompt()) {
  handle { body() }
}

public suspend fun  Handler.handle(body: suspend () -> E): E = prompt().prompt.reset(body)

public suspend fun , S> handleStateful(
  handler: ((() -> StatefulPrompt) -> H), value: S, fork: S.() -> S,
  body: suspend H.() -> E
): E {
  val p = StatefulPrompt()
  val h = handler { p }
  return h.handleStateful(value, fork) { h.body() }
}

public suspend fun  handleStateful(
  value: S, fork: S.() -> S, body: suspend StatefulPrompt.() -> E
): E = with(StatefulPrompt()) {
  handleStateful(value, fork) { body() }
}

public suspend fun  StatefulHandler.handleStateful(
  value: S, fork: S.() -> S,
  body: suspend () -> E
): E = reader.pushReader(value, fork) {
  prompt().prompt.reset(body)
}

@JvmInline
public value class HandlerPrompt private constructor(@PublishedApi internal val prompt: Prompt) : Handler {
  public constructor() : this(Prompt())

  override fun prompt(): HandlerPrompt = this
}

public class StatefulPrompt(
  private val prompt: HandlerPrompt = HandlerPrompt(), override val reader: Reader = Reader()
) : StatefulHandler, Handler by prompt

@JvmInline
public value class Cont @PublishedApi internal constructor(internal val subCont: SubCont) {
  public suspend fun resumeWith(value: Result, shouldClear: Boolean = false): R =
    subCont.pushSubContWith(value, isDelimiting = true, shouldClear)

  public suspend operator fun invoke(value: T, shouldClear: Boolean = false): R =
    resumeWith(Result.success(value), shouldClear)

  public suspend fun resumeWithException(exception: Throwable, shouldClear: Boolean = false): R =
    resumeWith(Result.failure(exception), shouldClear)

  public fun copy(): Cont = Cont(subCont.copy())
  public fun clear() { subCont.clear() }
}