import java.lang.Systemimport java.lang.IndexOutOfBoundsException////// Static denotes the region of global lifetime.///pubtypealiasStatic = IO////// A type alias used while we transition to a proper `Heap` effect.///typealiasHeap[h: Eff] = h////// An enum that holds type information where a witness is not available.///pubenumProxy[_: Type] {case Proxy}////// An enum that holds effect information where a witness is not available.///pubenumProxyEff[_: Eff] {case Proxy}////// An enum that holds type-level Bool information where a witness is not available.///pubenumProxyBool[_: Bool] {case Proxy}////// The uninterpretable Chan effect.////// The `Chan` effect represents the global region of channels.////// The `Chan` effect is uninterpretable which means that it cannot be handled.///pubeffChan////// The uninterpretable IO effect.////// The `IO` effect represents the actions not described by any other effect.////// The `IO` effect is uninterpretable which means that it cannot be handled.///pubeffIO////// The uninterpretable `NonDet` effect.////// The `NonDet` effect represents one or more non-deterministic actions.////// The `NonDet` effect is uninterpretable which means that it cannot be handled.///pubeffNonDet////// The pure identity function.///pubdefidentity(x: a): a = x////// The identity function, automatically casting to the required effect.///pubdefeidentity(x: a): a \ ef = checked_ecast(x)////// The constant function.///pubdefconstant(x: a): b -> a \ ef = _ -> checked_ecast(x)////// Returns the function `f` with input arguments swapped./// That is, given the function `f: (a, b) -> c`, returns a function `(b, a) -> c`///pubdefflip(f: (a, b) -> c \ ef): (b, a) -> c \ ef = (x, y) -> f(y, x)////// Partially applying this function in the form ``f `on` g`` lifts the binary function `f` to work on/// inputs transformed by `g`.///pubdefon(f: (b, b) -> c \ ef1, g: a -> b \ ef2, x: a, y: a): c \ { ef1, ef2 } = f(g(x), g(y))////// Returns the first component of `t`.///pubdeffst(p: (a, b)): a =let (x, _) = p;x////// Returns the second component of `t`.///pubdefsnd(p: (a, b)): b =let (_, y) = p;y////// Returns the pair `p` with the components swapped./// That is, returns `(y, x)` if `p = (x, y)`.///pubdefswap(p: (a, b)): (b, a) =let (x, y) = p; (y, x)////// Forwards function composition. Applies the function on the left first.////// Given the functions `f: a -> b` and `g: b -> c` returns a function `a -> c`///pubdef>>(f: a -> b \ ef1, g: b -> c \ ef2): a -> c \ { ef1, ef2 } = x -> g(f(x))////// Pipes the given value `x` into the function `f`.////// Given a value `x` and a function `f` returns `f(x)`.///pubdef|>(x: a, f: a -> b \ ef): b \ ef = f(x)////// Pipes the given pair `x` into the function `f`.////// Given a pair `x` and a function `f` returns `f(x)`.///pubdef||>(x: (a, b), f: a -> (b -> c \ ef)): c \ ef = f(fst(x), snd(x))////// Pipes the given value `x` into the function `f`.////// Given a value `x` and a function `f` returns `x`.///pubdef!>(x: a, f: a -> Unit \ ef): a \ ef = f(x); x////// Coerces the given value `x`.///pubdefcoerce(x: t): Coerce.Out[t] \ Coerce.Aef[t] withCoerce[t] = Coerce.coerce(x)////// Converts `x` to a string and prints it to standard out followed by a new line.///pubdefprintln(x: a): Unit \ IOwithToString[a] = System.out.println(x |> ToString.toString)////// Touches the given region capability `rc`.///pubdeftouch(_: Region[r]): Unit \ r = checked_ecast(())////// Crashes the current process with the given message `m`.///pubdefbug!(m: String): a = unsafeIO { System.err.println("*".repeat(80)); System.err.println("**"); System.err.println("** BUG: ${m}"); System.err.println("**"); System.err.println("*".repeat(80)); System.err.println(""); ?panic}////// Asserts that this expression is unreachable. Crashes if not.///pubdefunreachable!(): a = bug!("Reached unreachable expression.")////// Throws an `IndexOutOfBoundsException` with the given message `m`.///pubdefindexOutOfBounds!(m: String): a = unsafeIO {thrownew IndexOutOfBoundsException(m)}pubenumPurity[a: Type, b: Type, ef: Eff] {case Pure(a -> b)case Impure(a -> b \ ef)}pubenumPurity2[a: Type, b: Type, c: Type, ef: Eff] {case Pure(a -> b -> c)case Impure(a -> b -> c \ ef)}pubenumPurity3[a: Type, b: Type, c: Type, d: Type, ef: Eff] {case Pure(a -> b -> c -> d)case Impure(a -> b -> c -> d \ ef)}////// Returns `Purity.Pure(g)` if `f` has no effects./// Returns `Purity.Impure(g)` otherwise./// The function `g` can then be used in a context that requires/// it to be pure.///pubdefpurityOf(f: a -> b \ ef): Purity[a, b, ef] =matchReflect.reflectEff((ProxyEff.Proxy: ProxyEff[ef])) {case Reflect.Purity.Pure => Purity.Pure(unchecked_cast(fasa -> b \ {}))case Reflect.Purity.Impure => Purity.Impure(f) }////// Returns `Purity2.Pure(g)` if `f` has no effects./// Returns `Purity2.Impure(g)` otherwise./// The function `g` can then be used in a context that requires/// it to be pure.///pubdefpurityOf2(f: a -> b -> c \ ef): Purity2[a, b, c, ef] =matchReflect.reflectEff((ProxyEff.Proxy: ProxyEff[ef])) {case Reflect.Purity.Pure => Purity2.Pure(unchecked_cast(fasa -> b -> c \ {}))case Reflect.Purity.Impure => Purity2.Impure(f) }////// Returns `Purity3.Pure(g)` if `f` has no effects./// Returns `Purity3.Impure(g)` otherwise./// The function `g` can then be used in a context that requires/// it to be pure.///pubdefpurityOf3(f: a -> b -> c -> d \ ef): Purity3[a, b, c, d, ef] =matchReflect.reflectEff((ProxyEff.Proxy: ProxyEff[ef])) {case Reflect.Purity.Pure => Purity3.Pure(unchecked_cast(fasa -> b -> c -> d \ {}))case Reflect.Purity.Impure => Purity3.Impure(f) }