+ Ma is now Delegate

+ way to add pure Lyng parents when declaring kotlin bindings
This commit is contained in:
sergeych committed 2026-01-06 13:11:07 +01:00
1 parent 3ef68d8bb4
commit 3941ddee40
7 files changed
+136 -2

No files matched your search

@@ -61,7 +61,8 @@ open class Obj {
@Suppress("SuspiciousEqualsCombination")
fun isInstanceOf(someClass: Obj) = someClass === objClass ||
objClass.allParentsSet.contains(someClass) ||
someClass == rootObjectType
someClass == rootObjectType ||
(someClass is ObjClass && objClass.allImplementingNames.contains(someClass.className))
suspend fun invokeInstanceMethod(scope: Scope, name: String, vararg args: Obj): Obj =
@@ -124,6 +124,24 @@ open class ObjClass(
/** Direct parents in declaration order (kept deterministic). */
val directParents: List<ObjClass> = parents.toList()
/**
* Names of additional interfaces this class implements, but they are not (yet) available
* as [ObjClass] instances. This is used for "implementing existing interfaces" feature.
*/
val implementingNames = mutableSetOf<String>()
/**
* Combined set of [implementingNames] from this class and all its ancestors.
*/
val allImplementingNames: Set<String> by lazy {
buildSet {
addAll(implementingNames)
for (p in allParentsSet) {
addAll(p.implementingNames)
}
}
}
/** Optional constructor argument specs for each direct parent (set by compiler for user classes). */
open val directParentArgs: MutableMap<ObjClass, List<ParsedArgument>> = mutableMapOf()
@@ -193,7 +193,6 @@ class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
return map
}
val type = object : ObjClass("Map", ObjCollection) {
override suspend fun callOn(scope: Scope): Obj {
return ObjMap(listToMap(scope, scope.args.list))
@@ -206,6 +205,25 @@ class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
return ObjMap(keys.zip(values).toMap().toMutableMap())
}
}.apply {
implementingNames.add("Delegate")
addFn("getValue") {
val self = thisAs<ObjMap>()
val key = requiredArg<Obj>(1)
self.map[key] ?: ObjNull
}
addFn("setValue") {
val self = thisAs<ObjMap>()
val key = requiredArg<Obj>(1)
val value = requiredArg<Obj>(2)
self.map[key] = value
self
}
addFn("bind") {
val mode = requiredArg<ObjEnumEntry>(1)
if( mode.ordinal.value > 1)
raiseIllegalArgument("Map can be delegated only to val or var, got ${mode.name.value}")
thisObj
}
addFnDoc(
name = "getOrNull",
doc = "Get value by key or return null if the key is absent.",
@@ -3024,6 +3024,24 @@ class ScriptTest {
)
}
@Test
fun testMapAsDelegate() = runTest {
eval(
"""
val m = { a: 1, b: 2 }
assert(m is Delegate)
val a by m
var b by m
assertEquals(1, a)
assertEquals(2, b)
b = 42
assertEquals(42, m["b"])
assertEquals(1, a)
assertEquals(1, m["a"])
""".trimIndent()
)
}
@Test
fun testMapWithNonStringKeys() = runTest {
eval(