fixed errors
This commit is contained in:
parent
aeeec2d417
commit
6eabcc315f
@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
group = "net.sergeych"
|
||||
version = "0.10.3-SNAPSHOT"
|
||||
version = "0.11.1-SNAPSHOT"
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
||||
@ -30,10 +30,11 @@ class ClosureScope(val callScope: Scope, val closureScope: Scope) :
|
||||
Scope(callScope, callScope.args, thisObj = closureScope.thisObj) {
|
||||
|
||||
init {
|
||||
// Preserve the lexical class context from where the lambda was defined (closure),
|
||||
// so that visibility checks (private/protected) inside lambdas executed within other
|
||||
// methods (e.g., Mutex.withLock) still see the original declaring class context.
|
||||
this.currentClassCtx = closureScope.currentClassCtx
|
||||
// Preserve the lexical class context of the closure by default. This ensures that lambdas
|
||||
// created inside a class method keep access to that class's private/protected members even
|
||||
// when executed from within another object's method (e.g., Mutex.withLock), which may set
|
||||
// its own currentClassCtx temporarily. If the closure has no class context, inherit caller's.
|
||||
this.currentClassCtx = closureScope.currentClassCtx ?: callScope.currentClassCtx
|
||||
}
|
||||
|
||||
override fun get(name: String): ObjRecord? {
|
||||
|
||||
@ -226,6 +226,17 @@ class Compiler(
|
||||
val opToken = cc.next()
|
||||
val op = byLevel[level][opToken.type]
|
||||
if (op == null) {
|
||||
// handle ternary conditional at the top precedence level only: a ? b : c
|
||||
if (opToken.type == Token.Type.QUESTION && level == 0) {
|
||||
val thenRef = parseExpressionLevel(level + 1)
|
||||
?: throw ScriptError(opToken.pos, "Expecting expression after '?'")
|
||||
val colon = cc.next()
|
||||
if (colon.type != Token.Type.COLON) colon.raiseSyntax("missing ':'")
|
||||
val elseRef = parseExpressionLevel(level + 1)
|
||||
?: throw ScriptError(colon.pos, "Expecting expression after ':'")
|
||||
lvalue = ConditionalRef(lvalue!!, thenRef, elseRef)
|
||||
continue
|
||||
}
|
||||
cc.previous()
|
||||
break
|
||||
}
|
||||
|
||||
@ -62,7 +62,10 @@ open class ObjBuffer(val byteArray: UByteArray) : Obj() {
|
||||
val size by byteArray::size
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return byteArray.hashCode()
|
||||
// On some platforms (notably JS), UByteArray.hashCode() is not content-based.
|
||||
// For map/set keys we must ensure hash is consistent with equals(contentEquals).
|
||||
// Convert to ByteArray and use contentHashCode() which is value-based and stable.
|
||||
return byteArray.asByteArray().contentHashCode()
|
||||
}
|
||||
|
||||
override suspend fun compareTo(scope: Scope, other: Obj): Int {
|
||||
|
||||
@ -32,9 +32,15 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
// Direct (unmangled) lookup first
|
||||
instanceScope[name]?.let {
|
||||
val decl = it.declaringClass ?: objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val allowed = if (it.visibility == net.sergeych.lyng.Visibility.Private) (decl === objClass) else canAccessMember(it.visibility, decl, caller)
|
||||
if (!allowed)
|
||||
// When execution passes through suspension points (e.g., withLock),
|
||||
// currentClassCtx could be lost. Fall back to the instance scope class ctx
|
||||
// to preserve correct visibility semantics for private/protected members
|
||||
// accessed from within the class methods.
|
||||
// Allow unconditional access when accessing through `this` of the same instance
|
||||
if (scope.thisObj === this) return it
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 // do not default to objClass for outsiders
|
||||
if (!canAccessMember(it.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl?.className ?: "?"})"))
|
||||
return it
|
||||
}
|
||||
@ -51,15 +57,15 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
return null
|
||||
}
|
||||
findMangled()?.let { rec ->
|
||||
val declName = rec.importedFrom?.packageName // unused; use mangled key instead
|
||||
// derive declaring class by mangled prefix: try self then parents
|
||||
val declaring = when {
|
||||
instanceScope.objects.containsKey("${cls.className}::$name") -> cls
|
||||
else -> cls.mroParents.firstOrNull { instanceScope.objects.containsKey("${it.className}::$name") }
|
||||
}
|
||||
val caller = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val allowed = if (rec.visibility == net.sergeych.lyng.Visibility.Private) (declaring === objClass) else canAccessMember(rec.visibility, declaring, caller)
|
||||
if (!allowed)
|
||||
if (scope.thisObj === this) return rec
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 // do not default to objClass for outsiders
|
||||
if (!canAccessMember(rec.visibility, declaring, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${declaring?.className ?: "?"})"))
|
||||
return rec
|
||||
}
|
||||
@ -71,10 +77,14 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
// Direct (unmangled) first
|
||||
instanceScope[name]?.let { f ->
|
||||
val decl = f.declaringClass ?: objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val allowed = if (f.visibility == net.sergeych.lyng.Visibility.Private) (decl === objClass) else canAccessMember(f.visibility, decl, caller)
|
||||
if (!allowed)
|
||||
if (scope.thisObj === this) {
|
||||
// direct self-assignment allowed; enforce mutability below
|
||||
} else {
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 // do not default to objClass for outsiders
|
||||
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
|
||||
@ -95,10 +105,12 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
instanceScope.objects.containsKey("${cls.className}::$name") -> cls
|
||||
else -> cls.mroParents.firstOrNull { instanceScope.objects.containsKey("${it.className}::$name") }
|
||||
}
|
||||
val caller = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val allowed = if (rec.visibility == net.sergeych.lyng.Visibility.Private) (declaring === objClass) else canAccessMember(rec.visibility, declaring, caller)
|
||||
if (!allowed)
|
||||
if (scope.thisObj !== this) {
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 // do not default to objClass for outsiders
|
||||
if (!canAccessMember(rec.visibility, declaring, caller))
|
||||
ObjIllegalAssignmentException(scope, "can't assign to field $name (declared in ${declaring?.className ?: "?"})").raise()
|
||||
}
|
||||
if (!rec.isMutable) ObjIllegalAssignmentException(scope, "can't reassign val $name").raise()
|
||||
if (rec.value.assign(scope, newValue) == null)
|
||||
rec.value = newValue
|
||||
@ -111,9 +123,9 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
onNotFoundResult: (()->Obj?)?): Obj =
|
||||
instanceScope[name]?.let { rec ->
|
||||
val decl = rec.declaringClass ?: objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val allowed = if (rec.visibility == net.sergeych.lyng.Visibility.Private) (decl === objClass) else canAccessMember(rec.visibility, decl, caller)
|
||||
if (!allowed)
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 ?: if (scope.thisObj === this) objClass else null
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't invoke method $name (declared in ${decl?.className ?: "?"})"))
|
||||
// execute with lexical class context propagated to declaring class
|
||||
val saved = instanceScope.currentClassCtx
|
||||
@ -131,7 +143,8 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||
// fallback: class-scope function (registered during class body execution)
|
||||
objClass.classScope?.objects?.get(name)?.let { rec ->
|
||||
val decl = rec.declaringClass ?: objClass.findDeclaringClassOf(name)
|
||||
val caller = scope.currentClassCtx
|
||||
val caller0 = scope.currentClassCtx ?: instanceScope.currentClassCtx
|
||||
val caller = caller0 ?: if (scope.thisObj === this) objClass else null
|
||||
if (!canAccessMember(rec.visibility, decl, caller))
|
||||
scope.raiseError(ObjAccessException(scope, "can't invoke method $name (declared in ${decl?.className ?: "?"})"))
|
||||
val saved = instanceScope.currentClassCtx
|
||||
|
||||
@ -253,6 +253,24 @@ class BinaryOpRef(private val op: BinOp, private val left: ObjRef, private val r
|
||||
}
|
||||
}
|
||||
|
||||
/** Conditional (ternary) operator reference: cond ? a : b */
|
||||
class ConditionalRef(
|
||||
private val condition: ObjRef,
|
||||
private val ifTrue: ObjRef,
|
||||
private val ifFalse: ObjRef
|
||||
) : ObjRef {
|
||||
override suspend fun get(scope: Scope): ObjRecord {
|
||||
val condVal = if (net.sergeych.lyng.PerfFlags.RVAL_FASTPATH) condition.evalValue(scope) else condition.get(scope).value
|
||||
val condTrue = when (condVal) {
|
||||
is ObjBool -> condVal.value
|
||||
is ObjInt -> condVal.value != 0L
|
||||
else -> condVal.toBool()
|
||||
}
|
||||
val branch = if (condTrue) ifTrue else ifFalse
|
||||
return branch.get(scope)
|
||||
}
|
||||
}
|
||||
|
||||
/** Cast operator reference: left `as` rightType or `as?` (nullable). */
|
||||
class CastRef(
|
||||
private val valueRef: ObjRef,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user