Skip to content

Commit a613d46

Browse files
committed
Updated to 1.1-M04.
1 parent d26d136 commit a613d46

File tree

3 files changed

+43
-32
lines changed

3 files changed

+43
-32
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.1-M03'
2+
ext.kotlin_version = '1.1-M04'
33

44
repositories {
55
mavenCentral()
@@ -19,6 +19,7 @@ repositories {
1919

2020
dependencies {
2121
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
22+
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
2223
testCompile "junit:junit:4.12"
2324
}
2425

src/main/kotlin/com/github/h0tk3y/kotlinMonads/DoNotation.kt

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,61 @@
1+
@file:Suppress("EXPERIMENTAL_FEATURE_WARNING")
2+
13
package com.github.h0tk3y.kotlinMonads
24

35
import java.io.Serializable
46
import java.util.*
5-
import kotlin.jvm.internal.CoroutineImpl
7+
import kotlin.coroutines.Continuation
8+
import kotlin.coroutines.CoroutineIntrinsics
9+
import kotlin.coroutines.startCoroutine
610

711
fun <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

1216
fun <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

3743
class 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

src/test/kotlin/com/github/h0tk3y/kotlinMonads/DoNotationTest.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@file:Suppress("EXPERIMENTAL_FEATURE_WARNING")
2+
13
package com.github.h0tk3y.kotlinMonads
24

35
import org.junit.Assert.assertEquals
@@ -6,8 +8,8 @@ import org.junit.Test
68

79
class DoNotationTest {
810
@Test fun testLinearDo() {
9-
val m = doWith(just(1)) { i ->
10-
val j = bind(returns(i * 2))
11+
val m = doWith(just(1)) {
12+
val j = bind(returns(value * 2))
1113
val k = bind(returns(j * 3))
1214
then(returns(k + 1))
1315
}
@@ -16,8 +18,8 @@ class DoNotationTest {
1618

1719
@Test fun testControlFlow() {
1820
var called = false
19-
val m = doWith(just(1)) { i ->
20-
val j = bind(returns(i * 2))
21+
val m = doWith(just(1)) {
22+
val j = bind(returns(value * 2))
2123
val k = bind(if (j % 2 == 0) none() else just(j))
2224
called = true
2325
then(returns(k))
@@ -56,8 +58,8 @@ class DoNotationTest {
5658

5759
@Test fun testBindLastStatement() {
5860
val results = mutableListOf<Int>()
59-
val m = doWith(monadListOf(2)) { i ->
60-
val x = bind(monadListOf(i + 1, i * i))
61+
val m = doWith(monadListOf(2)) {
62+
val x = bind(monadListOf(value + 1, value * value))
6163
val z = bind(returns(x))
6264
results.add(z)
6365
}

0 commit comments

Comments
 (0)