108 lines
3.1 KiB
Kotlin

package net.sergeych.ling
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlin.math.floor
@Serializable
sealed class Obj {
open val asStr: ObjString by lazy {
if( this is ObjString) this else ObjString(this.toString())
}
companion object {
inline fun <reified T> from(obj: T): Obj {
return when(obj) {
is Obj -> obj
is Double -> ObjReal(obj)
is Float -> ObjReal(obj.toDouble())
is Int -> ObjInt(obj.toLong())
is Long -> ObjInt(obj)
is String -> ObjString(obj)
is CharSequence -> ObjString(obj.toString())
is Boolean -> ObjBool(obj)
Unit -> ObjVoid
null -> ObjNull
else -> throw IllegalArgumentException("cannot convert to Obj: $obj")
}
}
}
}
@Suppress("unused")
inline fun <reified T> T.toObj(): Obj = Obj.from(this)
@Serializable
@SerialName("void")
object ObjVoid: Obj() {
override fun equals(other: Any?): Boolean {
return other is ObjVoid || other is Unit
}
}
@Serializable
@SerialName("null")
object ObjNull: Obj() {
override fun equals(other: Any?): Boolean {
return other is ObjNull || other == null
}
}
@Serializable
@SerialName("string")
data class ObjString(val value: String): Obj() {
override fun toString(): String = value
}
interface Numeric {
val longValue: Long
val doubleValue: Double
val toObjInt: ObjInt
val toObjReal: ObjReal
}
fun Obj.toDouble(): Double =
(this as? Numeric)?.doubleValue
?: (this as? ObjString)?.value?.toDouble()
?: throw IllegalArgumentException("cannot convert to double $this")
@Suppress("unused")
fun Obj.toLong(): Long =
(this as? Numeric)?.longValue
?: (this as? ObjString)?.value?.toLong()
?: throw IllegalArgumentException("cannot convert to double $this")
fun Obj.toInt(): Int = toLong().toInt()
@Serializable
@SerialName("real")
data class ObjReal(val value: Double): Obj(), Numeric {
override val asStr by lazy { ObjString(value.toString()) }
override val longValue: Long by lazy { floor(value).toLong() }
override val doubleValue: Double by lazy { value }
override val toObjInt: ObjInt by lazy { ObjInt(longValue) }
override val toObjReal: ObjReal by lazy { ObjReal(value) }
}
@Serializable
@SerialName("int")
data class ObjInt(val value: Long): Obj(), Numeric {
override val asStr by lazy { ObjString(value.toString()) }
override val longValue: Long by lazy { value }
override val doubleValue: Double by lazy { value.toDouble() }
override val toObjInt: ObjInt by lazy { ObjInt(value) }
override val toObjReal: ObjReal by lazy { ObjReal(doubleValue) }
}
@Serializable
@SerialName("bool")
data class ObjBool(val value: Boolean): Obj() {
override val asStr by lazy { ObjString(value.toString()) }
}
data class ObjNamespace(val name: String,val context: Context): Obj() {
override fun toString(): String {
return "namespace ${name}"
}
}