another MI bug fixed, added tests for MI serialization
This commit is contained in:
1 parent
1e6dd89778
commit
41657b3558
4 files changed
+106
-13
No files matched your search
@@ -64,7 +64,7 @@ open class ObjClass(
|
||||
|
||||
/**
|
||||
* All ancestors as a Set for fast `isInstanceOf` checks. Order is not guaranteed here and
|
||||
* must not be used for resolution — use [parentsLinearized] instead.
|
||||
* must not be used for resolution
|
||||
*/
|
||||
val allParentsSet: Set<ObjClass> =
|
||||
buildSet {
|
||||
@@ -173,7 +173,19 @@ open class ObjClass(
|
||||
if (isRoot) {
|
||||
c.constructorMeta?.let { meta ->
|
||||
val argsHere = argsForThis ?: Arguments.EMPTY
|
||||
// Assign constructor params into instance scope (unmangled)
|
||||
meta.assignToContext(instance.instanceScope, argsHere)
|
||||
// Also expose them under MI-mangled storage keys `${Class}::name` so qualified views can access them
|
||||
// and so that base-class casts like `(obj as Base).field` work.
|
||||
for (p in meta.params) {
|
||||
val rec = instance.instanceScope.objects[p.name]
|
||||
if (rec != null) {
|
||||
val mangled = "${c.className}::${p.name}"
|
||||
// Always point the mangled name to the current record to keep writes consistent
|
||||
// across re-bindings (e.g., second pass before ctor)
|
||||
instance.instanceScope.objects[mangled] = rec
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Initialize direct parents first, in order
|
||||
@@ -203,6 +215,15 @@ open class ObjClass(
|
||||
c.constructorMeta?.let { meta ->
|
||||
val argsHere = argsForThis ?: Arguments.EMPTY
|
||||
meta.assignToContext(instance.instanceScope, argsHere)
|
||||
// Ensure mangled aliases exist for qualified access starting from this class
|
||||
for (p in meta.params) {
|
||||
val rec = instance.instanceScope.objects[p.name]
|
||||
if (rec != null) {
|
||||
val mangled = "${c.className}::${p.name}"
|
||||
// Overwrite to ensure alias refers to the latest ObjRecord after re-binding
|
||||
instance.instanceScope.objects[mangled] = rec
|
||||
}
|
||||
}
|
||||
}
|
||||
val execScope = instance.instanceScope.createChildScope(args = argsForThis ?: Arguments.EMPTY, newThisObj = instance)
|
||||
ctor.execute(execScope)
|
||||
@@ -259,7 +280,7 @@ open class ObjClass(
|
||||
fun addFn(
|
||||
name: String,
|
||||
isOpen: Boolean = false,
|
||||
visibility: net.sergeych.lyng.Visibility = net.sergeych.lyng.Visibility.Public,
|
||||
visibility: Visibility = Visibility.Public,
|
||||
code: suspend Scope.() -> Obj
|
||||
) {
|
||||
val stmt = statement { code() }
|
||||
|
||||
@@ -159,7 +159,10 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
?: super.invokeInstanceMethod(scope, name, args, onNotFoundResult)
|
||||
|
||||
private val publicFields: Map<String, ObjRecord>
|
||||
get() = instanceScope.objects.filter { it.value.visibility.isPublic && it.value.type.serializable }
|
||||
get() = instanceScope.objects.filter {
|
||||
// Expose only human-facing fields: skip MI-mangled storage entries like "Class::name"
|
||||
!it.key.contains("::") && it.value.visibility.isPublic && it.value.type.serializable
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val fields = publicFields.map { "${it.key}=${it.value.value}" }.joinToString(",")
|
||||
@@ -237,7 +240,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
// Visibility: declaring class is the qualified ancestor for mangled storage
|
||||
val decl = rec.declaringClass ?: startClass
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(rec.visibility, decl, caller))
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl.className})"))
|
||||
return rec
|
||||
}
|
||||
@@ -246,7 +249,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
instance.instanceScope[name]?.let { rec ->
|
||||
val decl = rec.declaringClass ?: instance.objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(rec.visibility, decl, caller))
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl?.className ?: "?"})"))
|
||||
return rec
|
||||
}
|
||||
@@ -255,7 +258,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
val r = memberFromAncestor(name) ?: scope.raiseError("no such field: $name")
|
||||
val decl = r.declaringClass ?: startClass
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(r.visibility, decl, caller))
|
||||
if (!canAccessMember(r.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl.className})"))
|
||||
return when (val value = r.value) {
|
||||
is net.sergeych.lyng.Statement -> ObjRecord(value.execute(instance.instanceScope.createChildScope(scope.pos, newThisObj = instance)), r.isMutable)
|
||||
@@ -269,7 +272,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
instance.instanceScope.objects[mangled]?.let { f ->
|
||||
val decl = f.declaringClass ?: startClass
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(f.visibility, decl, caller))
|
||||
if (!canAccessMember(f.visibility, decl, caller))
|
||||
ObjIllegalAssignmentException(scope, "can't assign to field $name (declared in ${decl.className})").raise()
|
||||
if (!f.isMutable) ObjIllegalAssignmentException(scope, "can't reassign val $name").raise()
|
||||
if (f.value.assign(scope, newValue) == null) f.value = newValue
|
||||
@@ -280,7 +283,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
instance.instanceScope[name]?.let { f ->
|
||||
val decl = f.declaringClass ?: instance.objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(f.visibility, decl, caller))
|
||||
if (!canAccessMember(f.visibility, decl, caller))
|
||||
ObjIllegalAssignmentException(scope, "can't assign to field $name (declared in ${decl?.className ?: "?"})").raise()
|
||||
if (!f.isMutable) ObjIllegalAssignmentException(scope, "can't reassign val $name").raise()
|
||||
if (f.value.assign(scope, newValue) == null) f.value = newValue
|
||||
@@ -290,7 +293,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
val r = memberFromAncestor(name) ?: scope.raiseError("no such field: $name")
|
||||
val decl = r.declaringClass ?: startClass
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(r.visibility, decl, caller))
|
||||
if (!canAccessMember(r.visibility, decl, caller))
|
||||
ObjIllegalAssignmentException(scope, "can't assign to field $name (declared in ${decl.className})").raise()
|
||||
if (!r.isMutable) scope.raiseError("can't assign to read-only field: $name")
|
||||
if (r.value.assign(scope, newValue) == null) r.value = newValue
|
||||
@@ -301,7 +304,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
memberFromAncestor(name)?.let { rec ->
|
||||
val decl = rec.declaringClass ?: startClass
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(rec.visibility, decl, caller))
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't invoke method $name (declared in ${decl.className})"))
|
||||
val saved = instance.instanceScope.currentClassCtx
|
||||
instance.instanceScope.currentClassCtx = decl
|
||||
@@ -316,7 +319,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
|
||||
instance.instanceScope[name]?.let { rec ->
|
||||
val decl = rec.declaringClass ?: instance.objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx
|
||||
if (!net.sergeych.lyng.canAccessMember(rec.visibility, decl, caller))
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't invoke method $name (declared in ${decl?.className ?: "?"})"))
|
||||
val saved = instance.instanceScope.currentClassCtx
|
||||
instance.instanceScope.currentClassCtx = decl
|
||||
|
||||
Reference in new issue
Block a user