ObjInstance / ObjClass optimization no more list of accessible fields!
This commit is contained in:
parent
88b355c40d
commit
d482401b15
@ -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
|
||||
|
||||
|
@ -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.
|
@ -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 {
|
||||
|
@ -0,0 +1,8 @@
|
||||
package net.sergeych.lyng
|
||||
|
||||
enum class AccessType(val isMutable: Boolean) {
|
||||
Val(false), Var(true),
|
||||
|
||||
@Suppress("unused")
|
||||
Initialization(false)
|
||||
}
|
@ -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,
|
||||
)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
// }
|
||||
|
||||
}
|
@ -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) }
|
||||
}
|
||||
|
@ -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)
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 }
|
||||
}
|
@ -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 )
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user