Step 25A: bytecode enum declarations
This commit is contained in:
parent
8b196c7b0c
commit
4db0a7fbab
@ -113,8 +113,10 @@ Goal: migrate the compiler so all values live in frames/bytecode, keeping JVM te
|
|||||||
## Interpreter Removal (next)
|
## Interpreter Removal (next)
|
||||||
|
|
||||||
- [ ] Step 25: Replace Statement-based declaration calls in bytecode.
|
- [ ] Step 25: Replace Statement-based declaration calls in bytecode.
|
||||||
- [ ] Add bytecode const/op for class/enum/function declarations (no `Statement` objects in constants).
|
- [x] Add bytecode const/op for enum declarations (no `Statement` objects in constants).
|
||||||
- [ ] Replace `emitStatementCall` usage for `ClassDeclStatement`, `FunctionDeclStatement`, `EnumDeclStatement`.
|
- [ ] Add bytecode const/op for class/function declarations (no `Statement` objects in constants).
|
||||||
|
- [x] Replace `emitStatementCall` usage for `EnumDeclStatement`.
|
||||||
|
- [ ] Replace `emitStatementCall` usage for `ClassDeclStatement` and `FunctionDeclStatement`.
|
||||||
- [ ] Add JVM disasm coverage to ensure module init has no `CALL_SLOT` to `Callable@...` for declarations.
|
- [ ] Add JVM disasm coverage to ensure module init has no `CALL_SLOT` to `Callable@...` for declarations.
|
||||||
- [ ] Step 26: Bytecode-backed lambdas (remove `ValueFnRef` runtime execution).
|
- [ ] Step 26: Bytecode-backed lambdas (remove `ValueFnRef` runtime execution).
|
||||||
- [ ] Compile lambda bodies to bytecode and emit an opcode to create a callable from bytecode + capture plan.
|
- [ ] Compile lambda bodies to bytecode and emit an opcode to create a callable from bytecode + capture plan.
|
||||||
|
|||||||
@ -5803,23 +5803,13 @@ class Compiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val stmtPos = startPos
|
val stmtPos = startPos
|
||||||
val enumDeclStatement = object : Statement() {
|
return EnumDeclStatement(
|
||||||
override val pos: Pos = stmtPos
|
declaredName = declaredName,
|
||||||
override suspend fun execute(scope: Scope): Obj {
|
qualifiedName = qualifiedName,
|
||||||
val enumClass = ObjEnumClass.createSimpleEnum(qualifiedName, names)
|
entries = names.toList(),
|
||||||
scope.addItem(declaredName, false, enumClass, recordType = ObjRecord.Type.Enum)
|
lifted = lifted,
|
||||||
if (lifted) {
|
startPos = stmtPos
|
||||||
for (entry in names) {
|
)
|
||||||
val rec = enumClass.getInstanceMemberOrNull(entry, includeAbstract = false, includeStatic = true)
|
|
||||||
if (rec != null) {
|
|
||||||
scope.addItem(entry, false, rec.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return enumClass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EnumDeclStatement(StatementDeclExecutable(enumDeclStatement), stmtPos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun parseObjectDeclaration(isExtern: Boolean = false): Statement {
|
private suspend fun parseObjectDeclaration(isExtern: Boolean = false): Statement {
|
||||||
|
|||||||
@ -17,19 +17,34 @@
|
|||||||
package net.sergeych.lyng
|
package net.sergeych.lyng
|
||||||
|
|
||||||
import net.sergeych.lyng.obj.Obj
|
import net.sergeych.lyng.obj.Obj
|
||||||
|
import net.sergeych.lyng.obj.ObjEnumClass
|
||||||
|
import net.sergeych.lyng.obj.ObjRecord
|
||||||
|
|
||||||
class EnumDeclStatement(
|
class EnumDeclStatement(
|
||||||
val executable: DeclExecutable,
|
val declaredName: String,
|
||||||
|
val qualifiedName: String,
|
||||||
|
val entries: List<String>,
|
||||||
|
val lifted: Boolean,
|
||||||
private val startPos: Pos,
|
private val startPos: Pos,
|
||||||
) : Statement() {
|
) : Statement() {
|
||||||
override val pos: Pos = startPos
|
override val pos: Pos = startPos
|
||||||
|
|
||||||
override suspend fun execute(scope: Scope): Obj {
|
override suspend fun execute(scope: Scope): Obj {
|
||||||
return executable.execute(scope)
|
val enumClass = ObjEnumClass.createSimpleEnum(qualifiedName, entries)
|
||||||
|
scope.addItem(declaredName, false, enumClass, recordType = ObjRecord.Type.Enum)
|
||||||
|
if (lifted) {
|
||||||
|
for (entry in entries) {
|
||||||
|
val rec = enumClass.getInstanceMemberOrNull(entry, includeAbstract = false, includeStatic = true)
|
||||||
|
if (rec != null) {
|
||||||
|
scope.addItem(entry, false, rec.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumClass
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun callOn(scope: Scope): Obj {
|
override suspend fun callOn(scope: Scope): Obj {
|
||||||
val target = scope.parent ?: scope
|
val target = scope.parent ?: scope
|
||||||
return executable.execute(target)
|
return execute(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,7 +195,7 @@ class BytecodeCompiler(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
is net.sergeych.lyng.EnumDeclStatement -> {
|
is net.sergeych.lyng.EnumDeclStatement -> {
|
||||||
val value = emitStatementCall(stmt)
|
val value = emitDeclEnum(stmt)
|
||||||
builder.emit(Opcode.RET, value.slot)
|
builder.emit(Opcode.RET, value.slot)
|
||||||
val localCount = maxOf(nextSlot, value.slot + 1) - scopeSlotCount
|
val localCount = maxOf(nextSlot, value.slot + 1) - scopeSlotCount
|
||||||
builder.build(
|
builder.build(
|
||||||
@ -4110,7 +4110,6 @@ class BytecodeCompiler(
|
|||||||
val executable = when (stmt) {
|
val executable = when (stmt) {
|
||||||
is net.sergeych.lyng.ClassDeclStatement -> stmt.executable
|
is net.sergeych.lyng.ClassDeclStatement -> stmt.executable
|
||||||
is net.sergeych.lyng.FunctionDeclStatement -> stmt.executable
|
is net.sergeych.lyng.FunctionDeclStatement -> stmt.executable
|
||||||
is net.sergeych.lyng.EnumDeclStatement -> stmt.executable
|
|
||||||
else -> throw BytecodeCompileException(
|
else -> throw BytecodeCompileException(
|
||||||
"Bytecode compile error: unsupported declaration ${stmt::class.simpleName}",
|
"Bytecode compile error: unsupported declaration ${stmt::class.simpleName}",
|
||||||
stmt.pos
|
stmt.pos
|
||||||
@ -4123,6 +4122,21 @@ class BytecodeCompiler(
|
|||||||
return CompiledValue(dst, SlotType.OBJ)
|
return CompiledValue(dst, SlotType.OBJ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun emitDeclEnum(stmt: net.sergeych.lyng.EnumDeclStatement): CompiledValue {
|
||||||
|
val constId = builder.addConst(
|
||||||
|
BytecodeConst.EnumDecl(
|
||||||
|
declaredName = stmt.declaredName,
|
||||||
|
qualifiedName = stmt.qualifiedName,
|
||||||
|
entries = stmt.entries,
|
||||||
|
lifted = stmt.lifted
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val dst = allocSlot()
|
||||||
|
builder.emit(Opcode.DECL_ENUM, constId, dst)
|
||||||
|
updateSlotType(dst, SlotType.OBJ)
|
||||||
|
return CompiledValue(dst, SlotType.OBJ)
|
||||||
|
}
|
||||||
|
|
||||||
private fun compileStatementValueOrFallback(stmt: Statement, needResult: Boolean = true): CompiledValue? {
|
private fun compileStatementValueOrFallback(stmt: Statement, needResult: Boolean = true): CompiledValue? {
|
||||||
val target = if (stmt is BytecodeStatement) stmt.original else stmt
|
val target = if (stmt is BytecodeStatement) stmt.original else stmt
|
||||||
setPos(target.pos)
|
setPos(target.pos)
|
||||||
@ -4158,7 +4172,7 @@ class BytecodeCompiler(
|
|||||||
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
||||||
is net.sergeych.lyng.ClassDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.ClassDeclStatement -> emitDeclExec(target)
|
||||||
is net.sergeych.lyng.FunctionDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.FunctionDeclStatement -> emitDeclExec(target)
|
||||||
is net.sergeych.lyng.EnumDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.EnumDeclStatement -> emitDeclEnum(target)
|
||||||
is net.sergeych.lyng.TryStatement -> emitTry(target, true)
|
is net.sergeych.lyng.TryStatement -> emitTry(target, true)
|
||||||
is net.sergeych.lyng.WhenStatement -> compileWhen(target, true)
|
is net.sergeych.lyng.WhenStatement -> compileWhen(target, true)
|
||||||
is net.sergeych.lyng.BreakStatement -> compileBreak(target)
|
is net.sergeych.lyng.BreakStatement -> compileBreak(target)
|
||||||
@ -4191,7 +4205,7 @@ class BytecodeCompiler(
|
|||||||
is IfStatement -> compileIfStatement(target)
|
is IfStatement -> compileIfStatement(target)
|
||||||
is net.sergeych.lyng.ClassDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.ClassDeclStatement -> emitDeclExec(target)
|
||||||
is net.sergeych.lyng.FunctionDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.FunctionDeclStatement -> emitDeclExec(target)
|
||||||
is net.sergeych.lyng.EnumDeclStatement -> emitDeclExec(target)
|
is net.sergeych.lyng.EnumDeclStatement -> emitDeclEnum(target)
|
||||||
is net.sergeych.lyng.ForInStatement -> {
|
is net.sergeych.lyng.ForInStatement -> {
|
||||||
val resultSlot = emitForIn(target, false) ?: return null
|
val resultSlot = emitForIn(target, false) ?: return null
|
||||||
CompiledValue(resultSlot, SlotType.OBJ)
|
CompiledValue(resultSlot, SlotType.OBJ)
|
||||||
|
|||||||
@ -38,6 +38,12 @@ sealed class BytecodeConst {
|
|||||||
val captureTableId: Int? = null,
|
val captureTableId: Int? = null,
|
||||||
) : BytecodeConst()
|
) : BytecodeConst()
|
||||||
data class DeclExec(val executable: net.sergeych.lyng.DeclExecutable) : BytecodeConst()
|
data class DeclExec(val executable: net.sergeych.lyng.DeclExecutable) : BytecodeConst()
|
||||||
|
data class EnumDecl(
|
||||||
|
val declaredName: String,
|
||||||
|
val qualifiedName: String,
|
||||||
|
val entries: List<String>,
|
||||||
|
val lifted: Boolean,
|
||||||
|
) : BytecodeConst()
|
||||||
data class SlotPlan(val plan: Map<String, Int>, val captures: List<String> = emptyList()) : BytecodeConst()
|
data class SlotPlan(val plan: Map<String, Int>, val captures: List<String> = emptyList()) : BytecodeConst()
|
||||||
data class CaptureTable(val entries: List<BytecodeCaptureEntry>) : BytecodeConst()
|
data class CaptureTable(val entries: List<BytecodeCaptureEntry>) : BytecodeConst()
|
||||||
data class ExtensionPropertyDecl(
|
data class ExtensionPropertyDecl(
|
||||||
|
|||||||
@ -157,7 +157,7 @@ class CmdBuilder {
|
|||||||
Opcode.PUSH_TRY ->
|
Opcode.PUSH_TRY ->
|
||||||
listOf(OperandKind.SLOT, OperandKind.IP, OperandKind.IP)
|
listOf(OperandKind.SLOT, OperandKind.IP, OperandKind.IP)
|
||||||
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_DESTRUCTURE,
|
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_DESTRUCTURE,
|
||||||
Opcode.DECL_EXEC,
|
Opcode.DECL_EXEC, Opcode.DECL_ENUM,
|
||||||
Opcode.ASSIGN_DESTRUCTURE ->
|
Opcode.ASSIGN_DESTRUCTURE ->
|
||||||
listOf(OperandKind.CONST, OperandKind.SLOT)
|
listOf(OperandKind.CONST, OperandKind.SLOT)
|
||||||
Opcode.ADD_INT, Opcode.SUB_INT, Opcode.MUL_INT, Opcode.DIV_INT, Opcode.MOD_INT,
|
Opcode.ADD_INT, Opcode.SUB_INT, Opcode.MUL_INT, Opcode.DIV_INT, Opcode.MOD_INT,
|
||||||
@ -411,6 +411,7 @@ class CmdBuilder {
|
|||||||
Opcode.DECL_DELEGATED -> CmdDeclDelegated(operands[0], operands[1])
|
Opcode.DECL_DELEGATED -> CmdDeclDelegated(operands[0], operands[1])
|
||||||
Opcode.DECL_DESTRUCTURE -> CmdDeclDestructure(operands[0], operands[1])
|
Opcode.DECL_DESTRUCTURE -> CmdDeclDestructure(operands[0], operands[1])
|
||||||
Opcode.DECL_EXEC -> CmdDeclExec(operands[0], operands[1])
|
Opcode.DECL_EXEC -> CmdDeclExec(operands[0], operands[1])
|
||||||
|
Opcode.DECL_ENUM -> CmdDeclEnum(operands[0], operands[1])
|
||||||
Opcode.DECL_EXT_PROPERTY -> CmdDeclExtProperty(operands[0], operands[1])
|
Opcode.DECL_EXT_PROPERTY -> CmdDeclExtProperty(operands[0], operands[1])
|
||||||
Opcode.CALL_DIRECT -> CmdCallDirect(operands[0], operands[1], operands[2], operands[3])
|
Opcode.CALL_DIRECT -> CmdCallDirect(operands[0], operands[1], operands[2], operands[3])
|
||||||
Opcode.ASSIGN_DESTRUCTURE -> CmdAssignDestructure(operands[0], operands[1])
|
Opcode.ASSIGN_DESTRUCTURE -> CmdAssignDestructure(operands[0], operands[1])
|
||||||
|
|||||||
@ -212,6 +212,7 @@ object CmdDisassembler {
|
|||||||
is CmdDeclDelegated -> Opcode.DECL_DELEGATED to intArrayOf(cmd.constId, cmd.slot)
|
is CmdDeclDelegated -> Opcode.DECL_DELEGATED to intArrayOf(cmd.constId, cmd.slot)
|
||||||
is CmdDeclDestructure -> Opcode.DECL_DESTRUCTURE to intArrayOf(cmd.constId, cmd.slot)
|
is CmdDeclDestructure -> Opcode.DECL_DESTRUCTURE to intArrayOf(cmd.constId, cmd.slot)
|
||||||
is CmdDeclExec -> Opcode.DECL_EXEC to intArrayOf(cmd.constId, cmd.slot)
|
is CmdDeclExec -> Opcode.DECL_EXEC to intArrayOf(cmd.constId, cmd.slot)
|
||||||
|
is CmdDeclEnum -> Opcode.DECL_ENUM to intArrayOf(cmd.constId, cmd.slot)
|
||||||
is CmdDeclExtProperty -> Opcode.DECL_EXT_PROPERTY to intArrayOf(cmd.constId, cmd.slot)
|
is CmdDeclExtProperty -> Opcode.DECL_EXT_PROPERTY to intArrayOf(cmd.constId, cmd.slot)
|
||||||
is CmdCallDirect -> Opcode.CALL_DIRECT to intArrayOf(cmd.id, cmd.argBase, cmd.argCount, cmd.dst)
|
is CmdCallDirect -> Opcode.CALL_DIRECT to intArrayOf(cmd.id, cmd.argBase, cmd.argCount, cmd.dst)
|
||||||
is CmdAssignDestructure -> Opcode.ASSIGN_DESTRUCTURE to intArrayOf(cmd.constId, cmd.slot)
|
is CmdAssignDestructure -> Opcode.ASSIGN_DESTRUCTURE to intArrayOf(cmd.constId, cmd.slot)
|
||||||
@ -283,7 +284,7 @@ object CmdDisassembler {
|
|||||||
Opcode.PUSH_TRY ->
|
Opcode.PUSH_TRY ->
|
||||||
listOf(OperandKind.SLOT, OperandKind.IP, OperandKind.IP)
|
listOf(OperandKind.SLOT, OperandKind.IP, OperandKind.IP)
|
||||||
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_DESTRUCTURE,
|
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_DESTRUCTURE,
|
||||||
Opcode.DECL_EXEC,
|
Opcode.DECL_EXEC, Opcode.DECL_ENUM,
|
||||||
Opcode.ASSIGN_DESTRUCTURE ->
|
Opcode.ASSIGN_DESTRUCTURE ->
|
||||||
listOf(OperandKind.CONST, OperandKind.SLOT)
|
listOf(OperandKind.CONST, OperandKind.SLOT)
|
||||||
Opcode.ADD_INT, Opcode.SUB_INT, Opcode.MUL_INT, Opcode.DIV_INT, Opcode.MOD_INT,
|
Opcode.ADD_INT, Opcode.SUB_INT, Opcode.MUL_INT, Opcode.DIV_INT, Opcode.MOD_INT,
|
||||||
|
|||||||
@ -1324,6 +1324,26 @@ class CmdDeclExec(internal val constId: Int, internal val slot: Int) : Cmd() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CmdDeclEnum(internal val constId: Int, internal val slot: Int) : Cmd() {
|
||||||
|
override suspend fun perform(frame: CmdFrame) {
|
||||||
|
val decl = frame.fn.constants[constId] as? BytecodeConst.EnumDecl
|
||||||
|
?: error("DECL_ENUM expects EnumDecl at $constId")
|
||||||
|
val scope = frame.ensureScope()
|
||||||
|
val enumClass = ObjEnumClass.createSimpleEnum(decl.qualifiedName, decl.entries)
|
||||||
|
scope.addItem(decl.declaredName, false, enumClass, recordType = ObjRecord.Type.Enum)
|
||||||
|
if (decl.lifted) {
|
||||||
|
for (entry in decl.entries) {
|
||||||
|
val rec = enumClass.getInstanceMemberOrNull(entry, includeAbstract = false, includeStatic = true)
|
||||||
|
if (rec != null) {
|
||||||
|
scope.addItem(entry, false, rec.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.storeObjResult(slot, enumClass)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CmdDeclDestructure(internal val constId: Int, internal val slot: Int) : Cmd() {
|
class CmdDeclDestructure(internal val constId: Int, internal val slot: Int) : Cmd() {
|
||||||
override suspend fun perform(frame: CmdFrame) {
|
override suspend fun perform(frame: CmdFrame) {
|
||||||
val decl = frame.fn.constants[constId] as? BytecodeConst.DestructureDecl
|
val decl = frame.fn.constants[constId] as? BytecodeConst.DestructureDecl
|
||||||
|
|||||||
@ -159,6 +159,7 @@ enum class Opcode(val code: Int) {
|
|||||||
THROW(0xBB),
|
THROW(0xBB),
|
||||||
RETHROW_PENDING(0xBC),
|
RETHROW_PENDING(0xBC),
|
||||||
DECL_EXEC(0xBD),
|
DECL_EXEC(0xBD),
|
||||||
|
DECL_ENUM(0xBE),
|
||||||
ITER_PUSH(0xBF),
|
ITER_PUSH(0xBF),
|
||||||
ITER_POP(0xC0),
|
ITER_POP(0xC0),
|
||||||
ITER_CANCEL(0xC1),
|
ITER_CANCEL(0xC1),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user