com.jtransc.lang.extra.kt Maven / Gradle / Ivy
package com.jtransc.lang
import com.jtransc.ds.getOrPut2
import java.util.*
import kotlin.reflect.KProperty
interface Extra {
var extra: HashMap?
class Mixin(override var extra: HashMap? = null) : Extra
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
class Property(val name: String? = null, val defaultGen: () -> T) {
inline operator fun getValue(thisRef: Extra, property: KProperty<*>): T {
val res = (thisRef.extra?.get(name ?: property.name) as T?)
if (res == null) {
val r = defaultGen()
setValue(thisRef, property, r)
return r
}
return res
}
inline operator fun setValue(thisRef: Extra, property: KProperty<*>, value: T): Unit = run {
//beforeSet(value)
if (thisRef.extra == null) thisRef.extra = hashMapOf()
thisRef.extra?.set(name ?: property.name, value as Any?)
//afterSet(value)
}
}
class PropertyThis(val name: String? = null, val defaultGen: T2.() -> T) {
inline operator fun getValue(thisRef: T2, property: KProperty<*>): T {
val res = (thisRef.extra?.get(name ?: property.name) as T?)
if (res == null) {
val r = defaultGen(thisRef)
setValue(thisRef, property, r)
return r
}
return res
}
inline operator fun setValue(thisRef: T2, property: KProperty<*>, value: T): Unit = run {
//beforeSet(value)
if (thisRef.extra == null) thisRef.extra = LinkedHashMap()
thisRef.extra?.set(name ?: property.name, value as Any?)
//afterSet(value)
}
}
}
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
class extraProperty(val default: () -> T) {
inline operator fun getValue(thisRef: Extra, property: KProperty<*>): T = (thisRef.extra?.get(property.name) as T?) ?: default()
inline operator fun setValue(thisRef: Extra, property: KProperty<*>, value: T): Unit = run {
if (thisRef.extra == null) thisRef.extra = LinkedHashMap()
thisRef.extra?.set(property.name, value as Any?)
}
}
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
class weakExtra(val default: () -> T) {
val map = WeakHashMap()
inline operator fun getValue(thisRef: Any, property: KProperty<*>): T {
return map.getOrPut2(thisRef, default)
}
inline operator fun setValue(thisRef: Any, property: KProperty<*>, value: T): Unit = run {
map.put(thisRef, value)
}
}