Enforce bytecode-only class and instance init bodies

This commit is contained in:
Sergey Chernov 2026-02-13 01:37:16 +03:00
parent 70ba424ef9
commit 05cba5b653
2 changed files with 31 additions and 3 deletions

View File

@ -37,7 +37,8 @@ class ClassStaticFieldInitStatement(
override val pos: Pos = startPos override val pos: Pos = startPos
override suspend fun execute(scope: Scope): Obj { override suspend fun execute(scope: Scope): Obj {
val initValue = initializer?.execute(scope)?.byValueCopy() ?: ObjNull val initValue = initializer?.let { execBytecodeOnly(scope, it, "class static field init") }?.byValueCopy()
?: ObjNull
val cls = scope.thisObj as? ObjClass val cls = scope.thisObj as? ObjClass
?: scope.raiseIllegalState("static field init requires class scope") ?: scope.raiseIllegalState("static field init requires class scope")
return if (isDelegated) { return if (isDelegated) {
@ -98,4 +99,13 @@ class ClassStaticFieldInitStatement(
initValue initValue
} }
} }
private suspend fun execBytecodeOnly(scope: Scope, stmt: Statement, label: String): Obj {
val bytecode = when (stmt) {
is net.sergeych.lyng.bytecode.BytecodeStatement -> stmt
is BytecodeBodyProvider -> stmt.bytecodeBody()
else -> null
} ?: scope.raiseIllegalState("$label requires bytecode statement")
return bytecode.execute(scope)
}
} }

View File

@ -38,7 +38,7 @@ class InstanceFieldInitStatement(
override val pos: Pos, override val pos: Pos,
) : Statement() { ) : Statement() {
override suspend fun execute(scope: Scope): Obj { override suspend fun execute(scope: Scope): Obj {
val initValue = initializer?.execute(scope)?.byValueCopy() val initValue = initializer?.let { execBytecodeOnly(scope, it, "instance field init") }?.byValueCopy()
?: if (isLateInitVal) ObjUnset else ObjNull ?: if (isLateInitVal) ObjUnset else ObjNull
scope.addItem( scope.addItem(
storageName, storageName,
@ -54,6 +54,15 @@ class InstanceFieldInitStatement(
) )
return ObjVoid return ObjVoid
} }
private suspend fun execBytecodeOnly(scope: Scope, stmt: Statement, label: String): Obj {
val bytecode = when (stmt) {
is net.sergeych.lyng.bytecode.BytecodeStatement -> stmt
is BytecodeBodyProvider -> stmt.bytecodeBody()
else -> null
} ?: scope.raiseIllegalState("$label requires bytecode statement")
return bytecode.execute(scope)
}
} }
class InstancePropertyInitStatement( class InstancePropertyInitStatement(
@ -100,7 +109,7 @@ class InstanceDelegatedInitStatement(
override val pos: Pos, override val pos: Pos,
) : Statement() { ) : Statement() {
override suspend fun execute(scope: Scope): Obj { override suspend fun execute(scope: Scope): Obj {
val initValue = initializer.execute(scope) val initValue = execBytecodeOnly(scope, initializer, "instance delegated init")
val accessType = ObjString(accessTypeLabel) val accessType = ObjString(accessTypeLabel)
val finalDelegate = try { val finalDelegate = try {
initValue.invokeInstanceMethod( initValue.invokeInstanceMethod(
@ -127,4 +136,13 @@ class InstanceDelegatedInitStatement(
} }
return ObjVoid return ObjVoid
} }
private suspend fun execBytecodeOnly(scope: Scope, stmt: Statement, label: String): Obj {
val bytecode = when (stmt) {
is net.sergeych.lyng.bytecode.BytecodeStatement -> stmt
is BytecodeBodyProvider -> stmt.bytecodeBody()
else -> null
} ?: scope.raiseIllegalState("$label requires bytecode statement")
return bytecode.execute(scope)
}
} }