All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlinx.jupyter.api.VariableState.kt Maven / Gradle / Ivy

There is a newer version: 0.12.0-335
Show newest version
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)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy