blob: 819365c6b21c2a532fed943dd353a336ed86139a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
package dev.isxander.yacl3.dsl
import dev.isxander.yacl3.api.Option
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
interface FutureValue<T> {
fun onReady(block: (T) -> Unit)
fun <R> map(block: (T) -> R): FutureValue<R>
fun <R> flatMap(block: (T) -> FutureValue<R>): FutureValue<R>
fun getOrNull(): T?
fun getOrThrow(): T = getOrNull() ?: error("Value not ready yet!")
open class Impl<T>(default: T? = null) : FutureValue<T> {
var value: T? = default
set(value) {
field = value
while (taskQueue.isNotEmpty()) {
taskQueue.removeFirst()(value!!)
}
}
private val taskQueue = ArrayDeque<(T) -> Unit>()
override fun onReady(block: (T) -> Unit) {
if (value != null) block(value!!)
else taskQueue.add(block)
}
override fun <R> map(block: (T) -> R): FutureValue<R> {
val future = Impl<R>()
onReady {
future.value = block(it)
}
return future
}
override fun <R> flatMap(block: (T) -> FutureValue<R>): FutureValue<R> {
val future = Impl<R>()
onReady {
block(it).onReady { inner ->
future.value = inner
}
}
return future
}
override fun getOrNull(): T? = value
}
}
interface Reference<T> : ReadOnlyProperty<Any?, FutureValue<T>> {
operator fun get(id: String): FutureValue<T>
override fun getValue(thisRef: Any?, property: KProperty<*>): FutureValue<T> {
return get(property.name)
}
operator fun invoke(name: String? = null, block: (T) -> Unit): ReadOnlyProperty<Any?, FutureValue<T>> {
return ReadOnlyProperty { thisRef, property ->
val future = get(name ?: property.name)
future.onReady(block)
future
}
}
}
operator fun <T> FutureValue<out Reference<T>>.get(id: String): FutureValue<T> {
val future = FutureValue.Impl<FutureValue<T>>()
onReady {
future.value = it[id]
}
return future.flatten()
}
fun FutureValue<GroupDslReference>.getOption(id: String): FutureValue<Option<*>> {
val future = FutureValue.Impl<FutureValue<Option<*>>>()
onReady {
future.value = it.get<Any?>(id) as FutureValue<Option<*>>
}
return future.flatten()
}
private fun <T> FutureValue<FutureValue<T>>.flatten(): FutureValue<T> {
val future = FutureValue.Impl<T>()
onReady { outer ->
outer.onReady { inner ->
future.value = inner
}
}
return future
}
class RegisterableDelegateProvider<Dsl, Return>(
private val registerFunction: (String, Dsl.() -> Unit) -> Return,
private val action: Dsl.() -> Unit
) {
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ExistingDelegateProvider<Return> {
return ExistingDelegateProvider(registerFunction(property.name, action))
}
}
class ExistingDelegateProvider<Return>(
private val delegate: Return
) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Return {
return delegate
}
}
|