org.jetbrains.kotlinx.jupyter.api.VariableState.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-jupyter-api Show documentation
Show all versions of kotlin-jupyter-api Show documentation
API for libraries supporting Kotlin Jupyter notebooks
package org.jetbrains.kotlinx.jupyter.api
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.isAccessible
interface VariableState {
val property: KProperty<*>
val scriptInstance: Any?
val stringValue: String?
val value: Result
}
data class VariableStateImpl(
override val property: KProperty1,
override val scriptInstance: Any,
) : VariableState {
private val stringCache =
VariableStateCache {
value.getOrNull()?.let { value ->
try {
value.toString()
} catch (e: Throwable) {
"${value::class.simpleName}: [exception thrown: $e]"
}
}
}
private val valCache =
VariableStateCache>(
{ oldValue, newValue ->
oldValue.getOrNull() !== newValue.getOrNull()
},
{
property.asAccessible { prop ->
try {
Result.success(prop.get(scriptInstance))
} catch (ex: Throwable) {
Result.failure(ex)
}
}
},
)
fun update(): Boolean {
return (valCache.forceUpdate()).also { isChanged ->
if (isChanged) stringCache.update()
}
}
override val stringValue: String? get() = stringCache.get()
override val value: Result get() = valCache.get()
companion object {
private fun , R> T.asAccessible(action: (T) -> R): R {
val wasAccessible = isAccessible
isAccessible = true
val res = action(this)
isAccessible = wasAccessible
return res
}
}
}
private class VariableStateCache(
val equalityChecker: (T, T) -> Boolean = { x, y -> x == y },
val calculate: (T?) -> T,
) {
private var cachedVal: T? = null
private var shouldRenew: Boolean = true
fun getOrNull(): T? {
return if (shouldRenew) {
calculate(cachedVal).also {
cachedVal = it
shouldRenew = false
}
} else {
cachedVal
}
}
fun get(): T = getOrNull()!!
fun update() {
shouldRenew = true
}
fun forceUpdate(): Boolean {
val oldVal = getOrNull()
update()
val newVal = get()
return oldVal != null && equalityChecker(oldVal, newVal)
}
}