2025-05-21 13:41:01 +04:00

88 lines
2.3 KiB
Kotlin

package net.sergeych.ling
class Context(
val parent: Context?,
val args: Arguments = Arguments.EMPTY,
var pos: Pos = Pos.builtIn
) {
constructor(
args: Arguments = Arguments.EMPTY,
pos: Pos = Pos.builtIn
)
: this(Script.defaultContext, args, pos)
fun raiseNotImplemented(): Nothing = raiseError("operation not implemented")
fun raiseNPE(): Nothing = raiseError(ObjNullPointerError(this))
fun raiseError(message: String): Nothing {
throw ExecutionError(ObjError(this, message))
}
fun raiseError(obj: ObjError): Nothing {
throw ExecutionError(obj)
}
private val objects = mutableMapOf<String, StoredObj>()
operator fun get(name: String): StoredObj? =
objects[name]
?: parent?.get(name)
fun copy(pos: Pos, args: Arguments = Arguments.EMPTY): Context = Context(this, args, pos)
fun addItem(name: String, isMutable: Boolean, value: Obj?) {
objects.put(name, StoredObj(name, value, isMutable))
}
fun getOrCreateNamespace(name: String) =
(objects.getOrPut(name) {
StoredObj(
name,
ObjNamespace(name, copy(pos)),
isMutable = false
)
}.value as ObjNamespace)
.context
inline fun <reified T> addFn(vararg names: String, crossinline fn: suspend Context.() -> T) {
val newFn = object : Statement() {
override val pos: Pos = Pos.builtIn
override suspend fun execute(context: Context): Obj {
return try {
from(context.fn())
} catch (e: Exception) {
raise(e.message ?: "unexpected error")
}
}
}
for (name in names) {
addItem(
name,
false,
newFn
)
}
}
inline fun <reified T> addConst(value: T, vararg names: String) {
val obj = Obj.from(value)
for (name in names) {
addItem(
name,
false,
obj
)
}
}
suspend fun eval(code: String): Obj =
Compiler().compile(code.toSource()).execute(this)
fun containsLocal(name: String): Boolean = name in objects
}