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(2,2) )
|
||||||
assert( Point(1,2) < Point(1,3) )
|
assert( Point(1,2) < Point(1,3) )
|
||||||
Point(1,1+1)
|
Point(1,1+1)
|
||||||
>>> Point(1, 2)
|
>>> Point(x=1,y=2)
|
||||||
|
|
||||||
# Theory
|
# Theory
|
||||||
|
|
||||||
|
@ -39,22 +39,5 @@ We can just put the code into the module code:
|
|||||||
|
|
||||||
## class initialization
|
## class initialization
|
||||||
|
|
||||||
class foo {
|
already done using `ObjInstance` class and instance-bound context with local
|
||||||
|
context stored in ObjInstance and class constructor statement in ObjClass.
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.2.1-SNAPSHOT"
|
version = "0.3.0-SNAPSHOT"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
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(
|
suspend fun assignToContext(
|
||||||
context: Context,
|
context: Context,
|
||||||
fromArgs: Arguments = context.args,
|
fromArgs: Arguments = context.args,
|
||||||
defaultAccessType: Compiler.AccessType = Compiler.AccessType.Var,
|
defaultAccessType: AccessType = AccessType.Var,
|
||||||
defaultVisibility: Compiler.Visibility = Compiler.Visibility.Public
|
defaultVisibility: Visibility = Visibility.Public
|
||||||
) {
|
) {
|
||||||
fun assign(a: Item, value: Obj) {
|
fun assign(a: Item, value: Obj) {
|
||||||
context.addItem(a.name, (a.accessType ?: defaultAccessType).isMutable, value,
|
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__.
|
* So it is a [Statement] that must be executed on __caller context__.
|
||||||
*/
|
*/
|
||||||
val defaultValue: Statement? = null,
|
val defaultValue: Statement? = null,
|
||||||
val accessType: Compiler.AccessType? = null,
|
val accessType: AccessType? = null,
|
||||||
val visibility: Compiler.Visibility? = null,
|
val visibility: Visibility? = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -19,11 +19,12 @@ class Compiler(
|
|||||||
|
|
||||||
private fun parseScript(start: Pos, cc: CompilerContext): Script {
|
private fun parseScript(start: Pos, cc: CompilerContext): Script {
|
||||||
val statements = mutableListOf<Statement>()
|
val statements = mutableListOf<Statement>()
|
||||||
|
// val returnScope = cc.startReturnScope()
|
||||||
while (parseStatement(cc, braceMeansLambda = true)?.also {
|
while (parseStatement(cc, braceMeansLambda = true)?.also {
|
||||||
statements += it
|
statements += it
|
||||||
} != null) {/**/
|
} != null) {/**/
|
||||||
}
|
}
|
||||||
return Script(start, statements)
|
return Script(start, statements)//returnScope.needCatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseStatement(cc: CompilerContext, braceMeansLambda: Boolean = false): Statement? {
|
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)
|
* Parse argument declaration, used in lambda (and later in fn too)
|
||||||
* @return declaration or null if there is no valid list of arguments
|
* @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
|
// fields. Note that 'this' is already set by class
|
||||||
constructorArgsDeclaration?.assignToContext(this)
|
constructorArgsDeclaration?.assignToContext(this)
|
||||||
bodyInit?.execute(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
|
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.
|
* 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) {
|
for( i in -depths .. -1) {
|
||||||
when( atOffset(i)?.type) {
|
when( atOffset(i)?.type) {
|
||||||
Token.Type.PROTECTED -> return Compiler.Visibility.Protected
|
Token.Type.PROTECTED -> return Visibility.Protected
|
||||||
Token.Type.PRIVATE -> return Compiler.Visibility.Private
|
Token.Type.PRIVATE -> return Visibility.Private
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return default
|
return default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// data class ReturnScope(val needCatch: Boolean = false)
|
||||||
|
|
||||||
|
// private val
|
||||||
|
|
||||||
|
// fun startReturnScope(): ReturnScope {
|
||||||
|
// return ReturnScope()
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
@ -78,7 +78,7 @@ class Context(
|
|||||||
name: String,
|
name: String,
|
||||||
isMutable: Boolean,
|
isMutable: Boolean,
|
||||||
value: Obj,
|
value: Obj,
|
||||||
visibility: Compiler.Visibility = Compiler.Visibility.Public
|
visibility: Visibility = Visibility.Public
|
||||||
): ObjRecord {
|
): ObjRecord {
|
||||||
return ObjRecord(value, isMutable, visibility).also { objects.put(name, it) }
|
return ObjRecord(value, isMutable, visibility).also { objects.put(name, it) }
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import net.sergeych.synctools.ProtectedOp
|
|||||||
data class ObjRecord(
|
data class ObjRecord(
|
||||||
var value: Obj,
|
var value: Obj,
|
||||||
val isMutable: Boolean,
|
val isMutable: Boolean,
|
||||||
val visibility: Compiler.Visibility = Compiler.Visibility.Public
|
val visibility: Visibility = Visibility.Public
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -342,3 +342,4 @@ class ObjIllegalArgumentError(context: Context, message: String = "illegal argum
|
|||||||
class ObjIllegalAssignmentError(context: Context, message: String = "illegal assignment") : 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 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,
|
vararg val parents: ObjClass,
|
||||||
) : Obj() {
|
) : Obj() {
|
||||||
|
|
||||||
internal val publicFields = mutableSetOf<String>()
|
|
||||||
internal val protectedFields = mutableSetOf<String>()
|
|
||||||
|
|
||||||
var instanceConstructor: Statement? = null
|
var instanceConstructor: Statement? = null
|
||||||
|
|
||||||
val allParentsSet: Set<ObjClass> = parents.flatMap {
|
val allParentsSet: Set<ObjClass> = parents.flatMap {
|
||||||
@ -42,10 +39,10 @@ class ObjClass(
|
|||||||
name: String,
|
name: String,
|
||||||
initialValue: Obj,
|
initialValue: Obj,
|
||||||
isMutable: Boolean = false,
|
isMutable: Boolean = false,
|
||||||
visibility: Compiler.Visibility = Compiler.Visibility.Public,
|
visibility: Visibility = Visibility.Public,
|
||||||
pos: Pos = Pos.builtIn
|
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")
|
throw ScriptError(pos, "$name is already defined in $objClass or one of its supertypes")
|
||||||
members[name] = ObjRecord(initialValue, isMutable, visibility)
|
members[name] = ObjRecord(initialValue, isMutable, visibility)
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,48 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
|
|||||||
internal lateinit var instanceContext: Context
|
internal lateinit var instanceContext: Context
|
||||||
|
|
||||||
override suspend fun readField(context: Context, name: String): ObjRecord {
|
override suspend fun readField(context: Context, name: String): ObjRecord {
|
||||||
return if( name in objClass.publicFields ) instanceContext[name]!!
|
return instanceContext[name]?.let {
|
||||||
else super.readField(context, name)
|
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) {
|
override suspend fun writeField(context: Context, name: String, newValue: Obj) {
|
||||||
if( name in objClass.publicFields ) {
|
instanceContext[name]?.let { f ->
|
||||||
val f = instanceContext[name]!!
|
if (!f.visibility.isPublic)
|
||||||
if( !f.isMutable ) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
|
ObjIllegalAssignmentError(context, "can't assign to non-public field $name")
|
||||||
if( f.value.assign(context, newValue) == null)
|
if (!f.isMutable) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
|
||||||
|
if (f.value.assign(context, newValue) == null)
|
||||||
f.value = newValue
|
f.value = newValue
|
||||||
}
|
} ?: super.writeField(context, name, newValue)
|
||||||
else super.writeField(context, name, newValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj {
|
override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj =
|
||||||
if( name in objClass.publicFields ) return instanceContext[name]!!.value.invoke(context, this, args)
|
instanceContext[name]?.let {
|
||||||
return super.invokeInstanceMethod(context, name, args)
|
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 {
|
override fun toString(): String {
|
||||||
val fields = objClass.publicFields.map {
|
val fields = publicFields.map { "${it.key}=${it.value.value}" }.joinToString(",")
|
||||||
instanceContext[it]?.value?.toString() ?: "??"
|
|
||||||
}.joinToString(", ")
|
|
||||||
return "${objClass.className}($fields)"
|
return "${objClass.className}($fields)"
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun compareTo(context: Context, other: Obj): Int {
|
override suspend fun compareTo(context: Context, other: Obj): Int {
|
||||||
if( other !is ObjInstance ) return -1
|
if (other !is ObjInstance) return -1
|
||||||
if( other.objClass != objClass ) return -1
|
if (other.objClass != objClass) return -1
|
||||||
for( f in objClass.publicFields ) {
|
for (f in publicFields) {
|
||||||
val a = instanceContext[f]!!.value
|
val a = f.value.value
|
||||||
val b = other.instanceContext[f]!!.value
|
val b = other.instanceContext[f.key]!!.value
|
||||||
val d = a.compareTo(context, b)
|
val d = a.compareTo(context, b)
|
||||||
if (d != 0) return d
|
if (d != 0) return d
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import kotlin.math.*
|
|||||||
class Script(
|
class Script(
|
||||||
override val pos: Pos,
|
override val pos: Pos,
|
||||||
private val statements: List<Statement> = emptyList(),
|
private val statements: List<Statement> = emptyList(),
|
||||||
|
// private val catchReturn: Boolean = false,
|
||||||
) : Statement() {
|
) : Statement() {
|
||||||
|
|
||||||
override suspend fun execute(context: Context): Obj {
|
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) )
|
assert( Point(1,2) < Point(1,3) )
|
||||||
""".trimIndent())
|
""".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