1+ @file:Suppress(" EXPERIMENTAL_FEATURE_WARNING" )
2+
13package com.github.h0tk3y.kotlinMonads
24
35import java.io.Serializable
46import java.util.*
5- import kotlin.jvm.internal.CoroutineImpl
7+ import kotlin.coroutines.Continuation
8+ import kotlin.coroutines.CoroutineIntrinsics
9+ import kotlin.coroutines.startCoroutine
610
711fun <M : Monad <M , * >, T > doWith (m : Monad <M , T >,
8- coroutine c : DoController <M , T >.(T ) -> Continuation < Unit > ): Monad <M , T > {
9- return (m bind { x -> doWith(this , x , c) })
10- }
12+ c : suspend DoController <M , T >.() -> Unit ): Monad <M , T > =
13+ m. bind { t -> doWith(this , t , c) }
14+
1115
1216fun <M : Monad <M , * >, T > doWith (aReturn : Return <M >,
1317 defaultValue : T ,
14- coroutine c : DoController <M , T >.(T ) -> Continuation < Unit > ): Monad <M , T > {
18+ c : suspend DoController <M , T >.() -> Unit ): Monad <M , T > {
1519 val controller = DoController (aReturn, defaultValue)
16- c(controller, defaultValue).resume(Unit )
20+ c.startCoroutine(controller, object : Continuation <Unit > {
21+ override fun resume (value : Unit ) {}
22+ override fun resumeWithException (exception : Throwable ) = throw exception
23+ })
1724 return controller.lastResult
1825}
1926
20- private fun <T , R > backupLabel (c : Continuation <T >, block : Continuation <T >.() -> R ): R {
21- val reflect = CoroutineImpl ::class .java
22- val labelField = reflect.getDeclaredField(" label" )
27+ val labelField by lazy {
28+ val jClass = Class .forName(" kotlin.jvm.internal.RestrictedCoroutineImpl" )
29+ return @lazy jClass.getDeclaredField(" label" ).apply { isAccessible = true }
30+ }
2331
24- labelField.isAccessible = true
25- val l = labelField.get(c )
26- labelField.isAccessible = false
32+ var < T > Continuation < T >.label
33+ get() = labelField.get(this )
34+ set(value) = labelField.set( this @label, value)
2735
36+ private fun <T , R > backupLabel (c : Continuation <T >, block : Continuation <T >.() -> R ): R {
37+ val backupLabel = c.label
2838 val r = block(c)
29-
30- labelField.isAccessible = true
31- labelField.set(c, l)
32- labelField.isAccessible = false
33-
39+ c.label = backupLabel
3440 return r
3541}
3642
3743class DoController <M : Monad <M , * >, T >(val returning : Return <M >,
38- initialValue : T ) : Serializable {
39- var lastResult: Monad <M , T > = returning.returns(initialValue )
40- private set
44+ val value : T ) : Serializable, Return<M> by returning {
45+ var lastResult: Monad <M , T > = returning.returns(value )
46+ internal set
4147
4248 private val stackSignals = Stack <Boolean >().apply { push(false ) }
4349
44- fun <T > returns (t : T ) = returning.returns(t)
45-
46- suspend fun bind (m : Monad <M , T >, c : Continuation <T >) {
50+ suspend fun bind (m : Monad <M , T >): T = CoroutineIntrinsics .suspendCoroutineOrReturn { c ->
4751 stackSignals.pop()
4852 stackSignals.push(true )
4953 var anyCont = false
5054 val o = m.bind { x ->
5155 stackSignals.push(false )
52- backupLabel(c) { c.resume(x) }
56+ backupLabel(c) {
57+ c.resume(x)
58+ }
5359 val contHasMonad = stackSignals.pop()
5460 if (contHasMonad) {
5561 anyCont = true
@@ -59,9 +65,10 @@ class DoController<M : Monad<M, *>, T>(val returning: Return<M>,
5965 }
6066 }
6167 lastResult = if (anyCont) o else m
68+ CoroutineIntrinsics .SUSPENDED
6269 }
6370
64- suspend fun then (m : Monad <M , T >, c : Continuation <Unit >) {
71+ suspend fun then (m : Monad <M , T >) = CoroutineIntrinsics .suspendCoroutineOrReturn <Unit > { c ->
6572 stackSignals.pop()
6673 stackSignals.push(true )
6774 var anyCont = false
@@ -77,6 +84,7 @@ class DoController<M : Monad<M, *>, T>(val returning: Return<M>,
7784 }
7885 }
7986 lastResult = if (anyCont) o else m
87+ CoroutineIntrinsics .SUSPENDED
8088 }
8189}
8290
0 commit comments