Skip to content

Commit 02c57f5

Browse files
committed
Add Handlers inspired by Effekt and corresponding tests
1 parent fdcb28e commit 02c57f5

File tree

7 files changed

+527
-145
lines changed

7 files changed

+527
-145
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package effekt
2+
3+
import Prompt
4+
import abortS0
5+
import reset
6+
import shift0
7+
import kotlin.jvm.JvmInline
8+
9+
public interface Handler<R, E> {
10+
public fun prompt(): ObscurePrompt<E>
11+
public suspend fun unit(value: R): E
12+
public suspend fun <A> use(body: suspend (Cont<A, E>) -> E): A = prompt().prompt.shift0(body)
13+
public fun <A> useAbort(body: suspend () -> E): A = prompt().prompt.abortS0(body)
14+
}
15+
16+
public suspend fun <R, E, H : Handler<R, E>> handle(
17+
handler: ((() -> ObscurePrompt<E>) -> H), body: suspend H.() -> R
18+
): E {
19+
val prompt = ObscurePrompt(Prompt<E>())
20+
val handler = handler { prompt }
21+
return handler.handle(body)
22+
}
23+
24+
public suspend fun <R, E, H : Handler<R, E>> H.handle(body: suspend H.() -> R): E {
25+
return prompt().prompt.reset {
26+
val res = body()
27+
prompt().prompt.abortS0 { unit(res) }
28+
}
29+
}
30+
31+
@JvmInline
32+
public value class ObscurePrompt<E> internal constructor(internal val prompt: Prompt<E>)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package effekt
2+
3+
import get
4+
import newReset
5+
import pushState
6+
import set
7+
import shift0
8+
9+
public interface StateScope {
10+
public suspend fun <T> field(init: T): Field<T>
11+
public interface Field<T> {
12+
public suspend fun get(): T
13+
public suspend fun set(value: T)
14+
}
15+
}
16+
17+
public suspend inline fun <T> StateScope.Field<T>.update(f: (T) -> T) {
18+
set(f(get()))
19+
}
20+
21+
public suspend fun <R> region(body: suspend StateScope.() -> R): R = newReset {
22+
body(StateScopeImpl(this))
23+
}
24+
25+
private class StateScopeImpl<R>(val prompt: Prompt<R>) : StateScope {
26+
override suspend fun <T> field(init: T): StateScope.Field<T> = FieldImpl<T>().apply {
27+
prompt.shift0 {
28+
pushState(init) {
29+
it(Unit)
30+
}
31+
}
32+
}
33+
34+
private class FieldImpl<T> : StateScope.Field<T>, State<T> {
35+
override suspend fun get(): T = (this as State<T>).get()
36+
override suspend fun set(value: T) = (this as State<T>).set(value)
37+
}
38+
}

library/src/commonMain/kotlin/handle.kt

-64
This file was deleted.

library/src/commonTest/kotlin/ContinuationTest.kt

+16
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,22 @@ class ContinuationTest {
356356
}
357357
}
358358
}
359+
360+
@Test
361+
fun ex4dot2dot1() = runTest {
362+
topReset<Int> {
363+
shift0 { k -> k(k(100)) } + 10
364+
} + 1 shouldBe 121
365+
}
366+
367+
@Test
368+
fun ex4dot2dot2() = runTest {
369+
topReset<Int> p1@{
370+
if(newReset p2@{
371+
shift<Boolean, Int> { 21 }
372+
}) 1 else 2
373+
} * 2 shouldBe 42
374+
}
359375
}
360376

361377
val stackSafeIterations: Int = when (platform) {

library/src/commonTest/kotlin/HandleTest.kt

-81
This file was deleted.

0 commit comments

Comments
 (0)