ObjInstance / ObjClass optimization no more list of accessible fields!

This commit is contained in:
Sergey Chernov 2025-06-10 23:51:01 +04:00
parent 88b355c40d
commit d482401b15
14 changed files with 81 additions and 84 deletions

View File

@ -158,7 +158,7 @@ For example, for our class Point:
assert( Point(1,2) < Point(2,2) )
assert( Point(1,2) < Point(1,3) )
Point(1,1+1)
>>> Point(1, 2)
>>> Point(x=1,y=2)
# Theory

View File

@ -39,22 +39,5 @@ We can just put the code into the module code:
## class initialization
class foo {
private static var instanceCounter = 0
val instanceId = instanceCounter
fun close() {
instanceCounter--
}
// instance initializatino could be as this:
if( instanceId > 100 )
throw Exception("Too many instances")
static {
// static, one-per-class initializer could be posted here
instanceCounter = 1
}
}
already done using `ObjInstance` class and instance-bound context with local
context stored in ObjInstance and class constructor statement in ObjClass.

View File

@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = "net.sergeych"
version = "0.2.1-SNAPSHOT"
version = "0.3.0-SNAPSHOT"
buildscript {
repositories {

View File

@ -0,0 +1,8 @@
package net.sergeych.lyng
enum class AccessType(val isMutable: Boolean) {
Val(false), Var(true),
@Suppress("unused")
Initialization(false)
}

View File

@ -23,8 +23,8 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
suspend fun assignToContext(
context: Context,
fromArgs: Arguments = context.args,
defaultAccessType: Compiler.AccessType = Compiler.AccessType.Var,
defaultVisibility: Compiler.Visibility = Compiler.Visibility.Public
defaultAccessType: AccessType = AccessType.Var,
defaultVisibility: Visibility = Visibility.Public
) {
fun assign(a: Item, value: Obj) {
context.addItem(a.name, (a.accessType ?: defaultAccessType).isMutable, value,
@ -100,7 +100,7 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
* So it is a [Statement] that must be executed on __caller context__.
*/
val defaultValue: Statement? = null,
val accessType: Compiler.AccessType? = null,
val visibility: Compiler.Visibility? = null,
val accessType: AccessType? = null,
val visibility: Visibility? = null,
)
}

View File

@ -19,11 +19,12 @@ class Compiler(
private fun parseScript(start: Pos, cc: CompilerContext): Script {
val statements = mutableListOf<Statement>()
// val returnScope = cc.startReturnScope()
while (parseStatement(cc, braceMeansLambda = true)?.also {
statements += it
} != null) {/**/
}
return Script(start, statements)
return Script(start, statements)//returnScope.needCatch)
}
private fun parseStatement(cc: CompilerContext, braceMeansLambda: Boolean = false): Statement? {
@ -439,17 +440,6 @@ class Compiler(
}
}
enum class AccessType(val isMutable: Boolean) {
Val(false), Var(true),
@Suppress("unused")
Initialization(false)
}
enum class Visibility {
Public, Private, Protected//, Internal
}
/**
* Parse argument declaration, used in lambda (and later in fn too)
* @return declaration or null if there is no valid list of arguments
@ -765,22 +755,6 @@ class Compiler(
// fields. Note that 'this' is already set by class
constructorArgsDeclaration?.assignToContext(this)
bodyInit?.execute(this)
// export public
for ((name, record) in objects) {
when (record.visibility) {
Visibility.Public -> {
thisObj.objClass.publicFields += name
thisObj.objClass.protectedFields += name
}
Visibility.Protected ->
thisObj.objClass.protectedFields += name
Visibility.Private -> {
//println("private field: $name")
}
}
}
thisObj
}

View File

@ -123,15 +123,23 @@ internal class CompilerContext(val tokens: List<Token>) {
/**
* Scan backwards as deep as specified looking for visibility token. Does not change position.
*/
fun getVisibility(default: Compiler.Visibility = Compiler.Visibility.Public, depths: Int = 2): Compiler.Visibility {
fun getVisibility(default: Visibility = Visibility.Public, depths: Int = 2): Visibility {
for( i in -depths .. -1) {
when( atOffset(i)?.type) {
Token.Type.PROTECTED -> return Compiler.Visibility.Protected
Token.Type.PRIVATE -> return Compiler.Visibility.Private
Token.Type.PROTECTED -> return Visibility.Protected
Token.Type.PRIVATE -> return Visibility.Private
else -> {}
}
}
return default
}
// data class ReturnScope(val needCatch: Boolean = false)
// private val
// fun startReturnScope(): ReturnScope {
// return ReturnScope()
// }
}

View File

@ -78,7 +78,7 @@ class Context(
name: String,
isMutable: Boolean,
value: Obj,
visibility: Compiler.Visibility = Compiler.Visibility.Public
visibility: Visibility = Visibility.Public
): ObjRecord {
return ObjRecord(value, isMutable, visibility).also { objects.put(name, it) }
}

View File

@ -12,7 +12,7 @@ import net.sergeych.synctools.ProtectedOp
data class ObjRecord(
var value: Obj,
val isMutable: Boolean,
val visibility: Compiler.Visibility = Compiler.Visibility.Public
val visibility: Visibility = Visibility.Public
)
/**
@ -341,4 +341,5 @@ class ObjIndexOutOfBoundsError(context: Context, message: String = "index out of
class ObjIllegalArgumentError(context: Context, message: String = "illegal argument") : ObjError(context, message)
class ObjIllegalAssignmentError(context: Context, message: String = "illegal assignment") : ObjError(context, message)
class ObjSymbolNotDefinedError(context: Context, message: String = "symbol is not defined") : ObjError(context, message)
class ObjIterationFinishedError(context: Context) : ObjError(context, "iteration finished")
class ObjIterationFinishedError(context: Context) : ObjError(context, "iteration finished")
class ObjAccessError(context: Context, message: String = "access not allowed error") : ObjError(context, message)

View File

@ -7,9 +7,6 @@ class ObjClass(
vararg val parents: ObjClass,
) : Obj() {
internal val publicFields = mutableSetOf<String>()
internal val protectedFields = mutableSetOf<String>()
var instanceConstructor: Statement? = null
val allParentsSet: Set<ObjClass> = parents.flatMap {
@ -42,10 +39,10 @@ class ObjClass(
name: String,
initialValue: Obj,
isMutable: Boolean = false,
visibility: Compiler.Visibility = Compiler.Visibility.Public,
visibility: Visibility = Visibility.Public,
pos: Pos = Pos.builtIn
) {
if (name in members || allParentsSet.any { name in it.members } == true)
if (name in members || allParentsSet.any { name in it.members })
throw ScriptError(pos, "$name is already defined in $objClass or one of its supertypes")
members[name] = ObjRecord(initialValue, isMutable, visibility)
}

View File

@ -5,38 +5,48 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
internal lateinit var instanceContext: Context
override suspend fun readField(context: Context, name: String): ObjRecord {
return if( name in objClass.publicFields ) instanceContext[name]!!
else super.readField(context, name)
return instanceContext[name]?.let {
if (it.visibility.isPublic)
it
else
context.raiseError(ObjAccessError(context, "can't access non-public field $name"))
}
?: super.readField(context, name)
}
override suspend fun writeField(context: Context, name: String, newValue: Obj) {
if( name in objClass.publicFields ) {
val f = instanceContext[name]!!
if( !f.isMutable ) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
if( f.value.assign(context, newValue) == null)
instanceContext[name]?.let { f ->
if (!f.visibility.isPublic)
ObjIllegalAssignmentError(context, "can't assign to non-public field $name")
if (!f.isMutable) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
if (f.value.assign(context, newValue) == null)
f.value = newValue
}
else super.writeField(context, name, newValue)
} ?: super.writeField(context, name, newValue)
}
override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj {
if( name in objClass.publicFields ) return instanceContext[name]!!.value.invoke(context, this, args)
return super.invokeInstanceMethod(context, name, args)
}
override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj =
instanceContext[name]?.let {
if (it.visibility.isPublic)
it.value.invoke(context, this, args)
else
context.raiseError(ObjAccessError(context, "can't invoke non-public method $name"))
}
?: super.invokeInstanceMethod(context, name, args)
private val publicFields: Map<String, ObjRecord>
get() = instanceContext.objects.filter { it.value.visibility.isPublic }
override fun toString(): String {
val fields = objClass.publicFields.map {
instanceContext[it]?.value?.toString() ?: "??"
}.joinToString(", ")
val fields = publicFields.map { "${it.key}=${it.value.value}" }.joinToString(",")
return "${objClass.className}($fields)"
}
override suspend fun compareTo(context: Context, other: Obj): Int {
if( other !is ObjInstance ) return -1
if( other.objClass != objClass ) return -1
for( f in objClass.publicFields ) {
val a = instanceContext[f]!!.value
val b = other.instanceContext[f]!!.value
if (other !is ObjInstance) return -1
if (other.objClass != objClass) return -1
for (f in publicFields) {
val a = f.value.value
val b = other.instanceContext[f.key]!!.value
val d = a.compareTo(context, b)
if (d != 0) return d
}

View File

@ -6,6 +6,7 @@ import kotlin.math.*
class Script(
override val pos: Pos,
private val statements: List<Statement> = emptyList(),
// private val catchReturn: Boolean = false,
) : Statement() {
override suspend fun execute(context: Context): Obj {

View File

@ -0,0 +1,8 @@
package net.sergeych.lyng
enum class Visibility {
Public, Private, Protected;//, Internal
val isPublic by lazy { this == Public }
@Suppress("unused")
val isProtected by lazy { this == Protected }
}

View File

@ -1513,4 +1513,11 @@ class ScriptTest {
assert( Point(1,2) < Point(1,3) )
""".trimIndent())
}
@Test
fun testAccessShortcuts() {
assertTrue( Visibility.Public.isPublic )
assertFalse( Visibility.Private.isPublic )
assertFalse( Visibility.Protected.isPublic )
}
}