better scopeFacade
This commit is contained in:
parent
d82302dd01
commit
66d9a40bb1
@ -114,6 +114,17 @@ scope.eval("val y = inc(41); log('Answer:', y)")
|
||||
|
||||
You can register multiple names (aliases) at once: `addFn<ObjInt>("inc", "increment") { ... }`.
|
||||
|
||||
Scope-backed Kotlin lambdas receive a `ScopeFacade` (not a full `Scope`). For migration and convenience, these utilities are available on the facade:
|
||||
|
||||
- Access: `args`, `pos`, `thisObj`, `get(name)`
|
||||
- Invocation: `call(...)`, `resolve(...)`, `assign(...)`, `toStringOf(...)`, `inspect(...)`, `trace(...)`
|
||||
- Args helpers: `requiredArg<T>()`, `requireOnlyArg<T>()`, `requireExactCount(...)`, `requireNoArgs()`, `thisAs<T>()`
|
||||
- Errors: `raiseError(...)`, `raiseClassCastError(...)`, `raiseIllegalArgument(...)`, `raiseIllegalState(...)`, `raiseNoSuchElement(...)`,
|
||||
`raiseSymbolNotFound(...)`, `raiseNotImplemented(...)`, `raiseNPE()`, `raiseIndexOutOfBounds(...)`, `raiseIllegalAssignment(...)`,
|
||||
`raiseUnset(...)`, `raiseNotFound(...)`, `raiseAssertionFailed(...)`, `raiseIllegalOperation(...)`, `raiseIterationFinished()`
|
||||
|
||||
If you truly need the full `Scope` (e.g., for low-level interop), use `requireScope()` explicitly.
|
||||
|
||||
### 5) Add Kotlin‑backed fields
|
||||
|
||||
If you need a simple field (with a value) instead of a computed property, use `createField`. This adds a field to the class that will be present in all its instances.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
||||
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,10 +24,10 @@ package net.sergeych.lyng.io.fs
|
||||
import net.sergeych.lyng.ModuleScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScopeFacade
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lyngio.fs.LyngFS
|
||||
import net.sergeych.lyngio.fs.LyngFs
|
||||
import net.sergeych.lyngio.fs.LyngPath
|
||||
@ -478,7 +478,7 @@ private suspend inline fun ScopeFacade.fsGuard(crossinline block: suspend () ->
|
||||
return try {
|
||||
block()
|
||||
} catch (e: AccessDeniedException) {
|
||||
raiseError(ObjIllegalOperationException(requireScope(), e.reasonDetail ?: "access denied"))
|
||||
raiseIllegalOperation(e.reasonDetail ?: "access denied")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,10 +21,10 @@ import kotlinx.coroutines.flow.Flow
|
||||
import net.sergeych.lyng.ModuleScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScopeFacade
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.requireScope
|
||||
import net.sergeych.lyngio.process.*
|
||||
import net.sergeych.lyngio.process.security.ProcessAccessDeniedException
|
||||
import net.sergeych.lyngio.process.security.ProcessAccessPolicy
|
||||
@ -210,9 +210,9 @@ private suspend inline fun ScopeFacade.processGuard(crossinline block: suspend (
|
||||
return try {
|
||||
block()
|
||||
} catch (e: ProcessAccessDeniedException) {
|
||||
raiseError(ObjIllegalOperationException(requireScope(), e.reasonDetail ?: "process access denied"))
|
||||
raiseIllegalOperation(e.reasonDetail ?: "process access denied")
|
||||
} catch (e: Exception) {
|
||||
raiseError(ObjIllegalOperationException(requireScope(), e.message ?: "process error"))
|
||||
raiseIllegalOperation(e.message ?: "process error")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2026 Sergey S. Chernov
|
||||
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -12,13 +12,12 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.sergeych.lyng
|
||||
|
||||
import net.sergeych.lyng.obj.Obj
|
||||
import net.sergeych.lyng.obj.ObjRecord
|
||||
import net.sergeych.lyng.obj.ObjString
|
||||
import net.sergeych.lyng.obj.*
|
||||
|
||||
/**
|
||||
* Limited facade for Kotlin bridge callables.
|
||||
@ -108,3 +107,29 @@ inline fun <reified T : Obj> ScopeFacade.thisAs(): T {
|
||||
|
||||
fun ScopeFacade.requireScope(): Scope =
|
||||
(this as? ScopeBridge)?.scope ?: raiseIllegalState("ScopeFacade requires ScopeBridge")
|
||||
|
||||
fun ScopeFacade.raiseNPE(): Nothing = requireScope().raiseNPE()
|
||||
|
||||
fun ScopeFacade.raiseIndexOutOfBounds(message: String = "Index out of bounds"): Nothing =
|
||||
requireScope().raiseIndexOutOfBounds(message)
|
||||
|
||||
fun ScopeFacade.raiseIllegalAssignment(message: String): Nothing =
|
||||
requireScope().raiseIllegalAssignment(message)
|
||||
|
||||
fun ScopeFacade.raiseUnset(message: String = "property is unset (not initialized)"): Nothing =
|
||||
requireScope().raiseUnset(message)
|
||||
|
||||
fun ScopeFacade.raiseNotFound(message: String = "not found"): Nothing =
|
||||
requireScope().raiseNotFound(message)
|
||||
|
||||
fun ScopeFacade.raiseError(obj: Obj, pos: Pos = this.pos, message: String): Nothing =
|
||||
requireScope().raiseError(obj, pos, message)
|
||||
|
||||
fun ScopeFacade.raiseAssertionFailed(message: String): Nothing =
|
||||
raiseError(ObjAssertionFailedException(requireScope(), message))
|
||||
|
||||
fun ScopeFacade.raiseIllegalOperation(message: String = "Operation is illegal"): Nothing =
|
||||
raiseError(ObjIllegalOperationException(requireScope(), message))
|
||||
|
||||
fun ScopeFacade.raiseIterationFinished(): Nothing =
|
||||
raiseError(ObjIterationFinishedException(requireScope()))
|
||||
|
||||
@ -26,7 +26,6 @@ import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.stdlib_included.rootLyng
|
||||
import net.sergeych.lyng.bridge.LyngClassBridge
|
||||
import net.sergeych.lynon.ObjLynonClass
|
||||
import net.sergeych.mp_tools.globalDefer
|
||||
import kotlin.math.*
|
||||
@ -326,7 +325,7 @@ class Script(
|
||||
": " + toStringOf(call(args[1])).value
|
||||
else ""
|
||||
if (!cond.value == true)
|
||||
raiseError(ObjAssertionFailedException(requireScope(), "Assertion failed$message"))
|
||||
raiseAssertionFailed("Assertion failed$message")
|
||||
}
|
||||
|
||||
fun unwrapCompareArg(value: Obj): Obj {
|
||||
@ -342,12 +341,7 @@ class Script(
|
||||
val a = unwrapCompareArg(requiredArg(0))
|
||||
val b = unwrapCompareArg(requiredArg(1))
|
||||
if (a.compareTo(requireScope(), b) != 0) {
|
||||
raiseError(
|
||||
ObjAssertionFailedException(
|
||||
requireScope(),
|
||||
"Assertion failed: ${inspect(a)} == ${inspect(b)}"
|
||||
)
|
||||
)
|
||||
raiseAssertionFailed("Assertion failed: ${inspect(a)} == ${inspect(b)}")
|
||||
}
|
||||
}
|
||||
// alias used in tests
|
||||
@ -355,23 +349,13 @@ class Script(
|
||||
val a = unwrapCompareArg(requiredArg(0))
|
||||
val b = unwrapCompareArg(requiredArg(1))
|
||||
if (a.compareTo(requireScope(), b) != 0)
|
||||
raiseError(
|
||||
ObjAssertionFailedException(
|
||||
requireScope(),
|
||||
"Assertion failed: ${inspect(a)} == ${inspect(b)}"
|
||||
)
|
||||
)
|
||||
raiseAssertionFailed("Assertion failed: ${inspect(a)} == ${inspect(b)}")
|
||||
}
|
||||
addVoidFn("assertNotEquals") {
|
||||
val a = unwrapCompareArg(requiredArg(0))
|
||||
val b = unwrapCompareArg(requiredArg(1))
|
||||
if (a.compareTo(requireScope(), b) == 0)
|
||||
raiseError(
|
||||
ObjAssertionFailedException(
|
||||
requireScope(),
|
||||
"Assertion failed: ${inspect(a)} != ${inspect(b)}"
|
||||
)
|
||||
)
|
||||
raiseAssertionFailed("Assertion failed: ${inspect(a)} != ${inspect(b)}")
|
||||
}
|
||||
addFnDoc(
|
||||
"assertThrows",
|
||||
@ -409,12 +393,7 @@ class Script(
|
||||
} catch (_: ScriptError) {
|
||||
ObjNull
|
||||
}
|
||||
if (result == null) raiseError(
|
||||
ObjAssertionFailedException(
|
||||
requireScope(),
|
||||
"Expected exception but nothing was thrown"
|
||||
)
|
||||
)
|
||||
if (result == null) raiseAssertionFailed("Expected exception but nothing was thrown")
|
||||
expectedClass?.let {
|
||||
if (!result.isInstanceOf(it)) {
|
||||
val actual = if (result is ObjException) result.exceptionClass else result.objClass
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
||||
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -39,7 +39,7 @@ class ObjArrayIterator(val array: Obj) : Obj() {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
if (self.nextIndex < self.lastIndex) {
|
||||
self.array.invokeInstanceMethod(requireScope(), "getAt", (self.nextIndex++).toObj())
|
||||
} else raiseError(ObjIterationFinishedException(requireScope()))
|
||||
} else raiseIterationFinished()
|
||||
}
|
||||
addFn("hasNext") {
|
||||
val self = thisAs<ObjArrayIterator>()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2026 Sergey S. Chernov
|
||||
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -12,17 +12,28 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.sergeych.lyng.obj
|
||||
|
||||
import net.sergeych.lyng.Pos
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScopeFacade
|
||||
import net.sergeych.lyng.raiseAssertionFailed as coreRaiseAssertionFailed
|
||||
import net.sergeych.lyng.raiseError as coreRaiseError
|
||||
import net.sergeych.lyng.raiseIllegalAssignment as coreRaiseIllegalAssignment
|
||||
import net.sergeych.lyng.raiseIllegalOperation as coreRaiseIllegalOperation
|
||||
import net.sergeych.lyng.raiseIndexOutOfBounds as coreRaiseIndexOutOfBounds
|
||||
import net.sergeych.lyng.raiseIterationFinished as coreRaiseIterationFinished
|
||||
import net.sergeych.lyng.raiseNPE as coreRaiseNPE
|
||||
import net.sergeych.lyng.raiseNotFound as coreRaiseNotFound
|
||||
import net.sergeych.lyng.raiseUnset as coreRaiseUnset
|
||||
import net.sergeych.lyng.requireExactCount as coreRequireExactCount
|
||||
import net.sergeych.lyng.requireNoArgs as coreRequireNoArgs
|
||||
import net.sergeych.lyng.requireOnlyArg as coreRequireOnlyArg
|
||||
import net.sergeych.lyng.requiredArg as coreRequiredArg
|
||||
import net.sergeych.lyng.requireScope as coreRequireScope
|
||||
import net.sergeych.lyng.requiredArg as coreRequiredArg
|
||||
import net.sergeych.lyng.thisAs as coreThisAs
|
||||
|
||||
inline fun <reified T : Obj> ScopeFacade.requiredArg(index: Int): T = coreRequiredArg(index)
|
||||
@ -36,3 +47,29 @@ fun ScopeFacade.requireNoArgs() = coreRequireNoArgs()
|
||||
inline fun <reified T : Obj> ScopeFacade.thisAs(): T = coreThisAs()
|
||||
|
||||
internal fun ScopeFacade.requireScope(): Scope = coreRequireScope()
|
||||
|
||||
fun ScopeFacade.raiseNPE(): Nothing = coreRaiseNPE()
|
||||
|
||||
fun ScopeFacade.raiseIndexOutOfBounds(message: String = "Index out of bounds"): Nothing =
|
||||
coreRaiseIndexOutOfBounds(message)
|
||||
|
||||
fun ScopeFacade.raiseIllegalAssignment(message: String): Nothing =
|
||||
coreRaiseIllegalAssignment(message)
|
||||
|
||||
fun ScopeFacade.raiseUnset(message: String = "property is unset (not initialized)"): Nothing =
|
||||
coreRaiseUnset(message)
|
||||
|
||||
fun ScopeFacade.raiseNotFound(message: String = "not found"): Nothing =
|
||||
coreRaiseNotFound(message)
|
||||
|
||||
fun ScopeFacade.raiseError(obj: Obj, pos: Pos = this.pos, message: String): Nothing =
|
||||
coreRaiseError(obj, pos, message)
|
||||
|
||||
fun ScopeFacade.raiseAssertionFailed(message: String): Nothing =
|
||||
coreRaiseAssertionFailed(message)
|
||||
|
||||
fun ScopeFacade.raiseIllegalOperation(message: String = "Operation is illegal"): Nothing =
|
||||
coreRaiseIllegalOperation(message)
|
||||
|
||||
fun ScopeFacade.raiseIterationFinished(): Nothing =
|
||||
coreRaiseIterationFinished()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user