Revert "Improve decodeClassObj class resolution in LynonDecoder, add fallback lookup mechanisms, and refine related tests"
This reverts commit dd1a1544c6d49641783d221b15e23c7150010161.
This commit is contained in:
parent
ab05f83e77
commit
71a37a2906
@ -1,20 +1,3 @@
|
|||||||
<!--
|
|
||||||
~ Copyright 2025 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.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ 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.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="lyng:site [jsBrowserDevelopmentRun]" type="GradleRunConfiguration" factoryName="Gradle">
|
<configuration default="false" name="lyng:site [jsBrowserDevelopmentRun]" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
<ExternalSystemSettings>
|
<ExternalSystemSettings>
|
||||||
@ -34,11 +17,8 @@
|
|||||||
</ExternalSystemSettings>
|
</ExternalSystemSettings>
|
||||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
|
|
||||||
<DebugAllEnabled>false</DebugAllEnabled>
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
<RunAsTest>false</RunAsTest>
|
<RunAsTest>false</RunAsTest>
|
||||||
<GradleProfilingDisabled>true</GradleProfilingDisabled>
|
|
||||||
<GradleCoverageDisabled>true</GradleCoverageDisabled>
|
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
@ -78,72 +78,15 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe
|
|||||||
|
|
||||||
private suspend fun decodeClassObj(scope: Scope): ObjClass {
|
private suspend fun decodeClassObj(scope: Scope): ObjClass {
|
||||||
val className = decodeObject(scope, ObjString.type, null) as ObjString
|
val className = decodeObject(scope, ObjString.type, null) as ObjString
|
||||||
val name = className.value
|
return scope.get(className.value)?.value?.let {
|
||||||
// 1) Try direct lookup in this scope (locals/parents/this members)
|
|
||||||
scope.get(name)?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
if (it !is ObjClass)
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
||||||
return it
|
it
|
||||||
}
|
} ?: scope.also {
|
||||||
// 2) Try ancestry lookup including instance/class members, but without invoking overridden get
|
println("Class not found: $className")
|
||||||
scope.chainLookupWithMembers(name)?.value?.let {
|
println("::: ${runCatching { scope.eval("Vault")}.getOrNull() }")
|
||||||
if (it !is ObjClass)
|
println("::2 [${className}]: ${scope.get(className.value)}")
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
}.raiseSymbolNotFound("can't deserialize: not found type $className")
|
||||||
return it
|
|
||||||
}
|
|
||||||
// 3) Try to find nearest ModuleScope and check its locals and its parent (root) locals
|
|
||||||
run {
|
|
||||||
var s: Scope? = scope
|
|
||||||
val visited = HashSet<Long>(4)
|
|
||||||
while (s != null) {
|
|
||||||
if (!visited.add(s.frameId)) break
|
|
||||||
if (s is net.sergeych.lyng.ModuleScope) {
|
|
||||||
s.objects[name]?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
s.localBindings[name]?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
s.parent?.let { p ->
|
|
||||||
p.objects[name]?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
p.localBindings[name]?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
p.thisObj.objClass.getInstanceMemberOrNull(name)?.value?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
s = s.parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 4) Try ImportProvider root scope globals (e.g., stdlib)
|
|
||||||
runCatching { scope.currentImportProvider.rootScope.objects[name]?.value }.getOrNull()?.let {
|
|
||||||
if (it !is ObjClass)
|
|
||||||
scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
// // 5) As a final fallback, try to evaluate the name in this scope using the compiler
|
|
||||||
// runCatching { scope.eval(name) }.getOrNull()?.let {
|
|
||||||
// if (it !is ObjClass)
|
|
||||||
// scope.raiseClassCastError("Expected obj class but got ${it::class.simpleName}")
|
|
||||||
// return it
|
|
||||||
// }
|
|
||||||
// If everything failed, raise an informative error
|
|
||||||
scope.raiseSymbolNotFound("can't deserialize: not found type ${className}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun decodeAnyList(scope: Scope, fixedSize: Int? = null): MutableList<Obj> {
|
suspend fun decodeAnyList(scope: Scope, fixedSize: Int? = null): MutableList<Obj> {
|
||||||
|
|||||||
@ -25,7 +25,10 @@ import net.sergeych.lyng.obj.*
|
|||||||
import net.sergeych.lynon.*
|
import net.sergeych.lynon.*
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.test.*
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertContentEquals
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class LynonTests {
|
class LynonTests {
|
||||||
|
|
||||||
@ -41,73 +44,6 @@ class LynonTests {
|
|||||||
assertEquals(3, sizeInTetrades(257u))
|
assertEquals(3, sizeInTetrades(257u))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("This is not yet implemented")
|
|
||||||
@Test
|
|
||||||
fun decodeClassObj_shouldResolveDottedQualifiedNames() = runTest {
|
|
||||||
// Define nested namespaces and a class with a qualified name via eval
|
|
||||||
val module = net.sergeych.lyng.Script.defaultImportManager.newModule()
|
|
||||||
module.eval(
|
|
||||||
"""
|
|
||||||
package ns.sub
|
|
||||||
class Vault() { fun toString() { "ns.sub.Vault" } }
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
|
|
||||||
val child = module.createChildScope(module.pos)
|
|
||||||
|
|
||||||
// Sanity: eval resolves both qualified and unqualified in the same module context
|
|
||||||
val qualified = child.eval("ns.sub.Vault")
|
|
||||||
assertTrue(qualified is ObjClass)
|
|
||||||
|
|
||||||
val inst = child.eval("ns.sub.Vault()")
|
|
||||||
assertTrue(inst is ObjInstance)
|
|
||||||
|
|
||||||
// Encode and decode instance; decoder should resolve class by its encoded name
|
|
||||||
val bout = MemoryBitOutput()
|
|
||||||
val enc = LynonEncoder(bout)
|
|
||||||
enc.encodeAny(child, inst)
|
|
||||||
val bin = MemoryBitInput(bout.toBitArray())
|
|
||||||
val dec = LynonDecoder(bin)
|
|
||||||
|
|
||||||
val decoded = dec.decodeAny(child)
|
|
||||||
assertTrue(decoded is ObjInstance)
|
|
||||||
val decObj = decoded as ObjInstance
|
|
||||||
assertEquals("Vault", decObj.objClass.className)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun decodeClassObj_shouldResolveWhenEvalFindsButGetMisses() = runTest {
|
|
||||||
// Build a module scope and define a class there via eval (simulating imported/user code)
|
|
||||||
val module = net.sergeych.lyng.Script.defaultImportManager.newModule()
|
|
||||||
module.eval("class Vault() { fun toString() { \"Vault\" } }")
|
|
||||||
|
|
||||||
// Build a child scope where local bindings do not include the class name explicitly
|
|
||||||
val child = module.createChildScope(module.pos)
|
|
||||||
|
|
||||||
// Sanity: eval in the child must resolve the class by name
|
|
||||||
val evalResolved = child.eval("Vault")
|
|
||||||
assertTrue(evalResolved is ObjClass)
|
|
||||||
|
|
||||||
// Create an instance so that encoder will write type Other + class name and constructor args
|
|
||||||
val inst = child.eval("Vault()")
|
|
||||||
assertTrue(inst is ObjInstance)
|
|
||||||
|
|
||||||
// Encode the instance and then decode it with our decoder that contains robust class lookup
|
|
||||||
val bout = MemoryBitOutput()
|
|
||||||
val enc = LynonEncoder(bout)
|
|
||||||
enc.encodeAny(child, inst)
|
|
||||||
val bin = MemoryBitInput(bout.toBitArray())
|
|
||||||
val dec = LynonDecoder(bin)
|
|
||||||
|
|
||||||
val decoded = dec.decodeAny(child)
|
|
||||||
assertTrue(decoded is ObjInstance)
|
|
||||||
// Class should be resolvable and preserved
|
|
||||||
val instObj = inst as ObjInstance
|
|
||||||
val decObj = decoded as ObjInstance
|
|
||||||
assertEquals(instObj.objClass.className, decObj.objClass.className)
|
|
||||||
assertEquals("Vault", decObj.objClass.className)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSizeInBits() {
|
fun testSizeInBits() {
|
||||||
assertEquals(1, sizeInBits(0u))
|
assertEquals(1, sizeInBits(0u))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user