Add bytecode support for destructuring decls
This commit is contained in:
parent
eb58720365
commit
b857686d7d
@ -114,6 +114,22 @@ class BytecodeCompiler(
|
|||||||
localSlotMutables
|
localSlotMutables
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is DestructuringVarDeclStatement -> {
|
||||||
|
val value = emitDestructuringVarDecl(stmt) ?: return null
|
||||||
|
builder.emit(Opcode.RET, value.slot)
|
||||||
|
val localCount = maxOf(nextSlot, value.slot + 1) - scopeSlotCount
|
||||||
|
builder.build(
|
||||||
|
name,
|
||||||
|
localCount,
|
||||||
|
addrCount = nextAddrSlot,
|
||||||
|
returnLabels = returnLabels,
|
||||||
|
scopeSlotIndices,
|
||||||
|
scopeSlotNames,
|
||||||
|
scopeSlotIsModule,
|
||||||
|
localSlotNames,
|
||||||
|
localSlotMutables
|
||||||
|
)
|
||||||
|
}
|
||||||
is net.sergeych.lyng.ThrowStatement -> compileThrowStatement(name, stmt)
|
is net.sergeych.lyng.ThrowStatement -> compileThrowStatement(name, stmt)
|
||||||
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> compileExtensionPropertyDecl(name, stmt)
|
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> compileExtensionPropertyDecl(name, stmt)
|
||||||
is net.sergeych.lyng.TryStatement -> {
|
is net.sergeych.lyng.TryStatement -> {
|
||||||
@ -3282,7 +3298,7 @@ class BytecodeCompiler(
|
|||||||
is BlockStatement -> emitBlock(target, true)
|
is BlockStatement -> emitBlock(target, true)
|
||||||
is VarDeclStatement -> emitVarDecl(target)
|
is VarDeclStatement -> emitVarDecl(target)
|
||||||
is DelegatedVarDeclStatement -> emitDelegatedVarDecl(target)
|
is DelegatedVarDeclStatement -> emitDelegatedVarDecl(target)
|
||||||
is DestructuringVarDeclStatement -> emitStatementEval(target)
|
is DestructuringVarDeclStatement -> emitDestructuringVarDecl(target)
|
||||||
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
||||||
is net.sergeych.lyng.ClassDeclStatement -> emitStatementEval(target)
|
is net.sergeych.lyng.ClassDeclStatement -> emitStatementEval(target)
|
||||||
is net.sergeych.lyng.FunctionDeclStatement -> emitStatementEval(target)
|
is net.sergeych.lyng.FunctionDeclStatement -> emitStatementEval(target)
|
||||||
@ -3329,7 +3345,7 @@ class BytecodeCompiler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BlockStatement -> emitBlock(target, false)
|
is BlockStatement -> emitBlock(target, false)
|
||||||
is DestructuringVarDeclStatement -> emitStatementEval(target)
|
is DestructuringVarDeclStatement -> emitDestructuringVarDecl(target)
|
||||||
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
is net.sergeych.lyng.ExtensionPropertyDeclStatement -> emitExtensionPropertyDecl(target)
|
||||||
is net.sergeych.lyng.BreakStatement -> compileBreak(target)
|
is net.sergeych.lyng.BreakStatement -> compileBreak(target)
|
||||||
is net.sergeych.lyng.ContinueStatement -> compileContinue(target)
|
is net.sergeych.lyng.ContinueStatement -> compileContinue(target)
|
||||||
@ -3591,6 +3607,23 @@ class BytecodeCompiler(
|
|||||||
return CompiledValue(value.slot, SlotType.OBJ)
|
return CompiledValue(value.slot, SlotType.OBJ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun emitDestructuringVarDecl(stmt: DestructuringVarDeclStatement): CompiledValue? {
|
||||||
|
val value = compileStatementValueOrFallback(stmt.initializer) ?: return null
|
||||||
|
val declId = builder.addConst(
|
||||||
|
BytecodeConst.DestructureDecl(
|
||||||
|
stmt.pattern,
|
||||||
|
stmt.names,
|
||||||
|
stmt.isMutable,
|
||||||
|
stmt.visibility,
|
||||||
|
stmt.isTransient,
|
||||||
|
stmt.pos
|
||||||
|
)
|
||||||
|
)
|
||||||
|
builder.emit(Opcode.DECL_DESTRUCTURE, declId, value.slot)
|
||||||
|
updateSlotType(value.slot, SlotType.OBJ)
|
||||||
|
return CompiledValue(value.slot, SlotType.OBJ)
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateNameObjClass(name: String, initializer: Statement?, initializerObjClass: ObjClass? = null) {
|
private fun updateNameObjClass(name: String, initializer: Statement?, initializerObjClass: ObjClass? = null) {
|
||||||
val cls = initializerObjClass ?: objClassForInitializer(initializer)
|
val cls = initializerObjClass ?: objClassForInitializer(initializer)
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package net.sergeych.lyng.bytecode
|
|||||||
|
|
||||||
import net.sergeych.lyng.Pos
|
import net.sergeych.lyng.Pos
|
||||||
import net.sergeych.lyng.Visibility
|
import net.sergeych.lyng.Visibility
|
||||||
|
import net.sergeych.lyng.obj.ListLiteralRef
|
||||||
import net.sergeych.lyng.obj.Obj
|
import net.sergeych.lyng.obj.Obj
|
||||||
import net.sergeych.lyng.obj.ObjProperty
|
import net.sergeych.lyng.obj.ObjProperty
|
||||||
|
|
||||||
@ -52,6 +53,14 @@ sealed class BytecodeConst {
|
|||||||
val visibility: Visibility,
|
val visibility: Visibility,
|
||||||
val isTransient: Boolean,
|
val isTransient: Boolean,
|
||||||
) : BytecodeConst()
|
) : BytecodeConst()
|
||||||
|
data class DestructureDecl(
|
||||||
|
val pattern: ListLiteralRef,
|
||||||
|
val names: List<String>,
|
||||||
|
val isMutable: Boolean,
|
||||||
|
val visibility: Visibility,
|
||||||
|
val isTransient: Boolean,
|
||||||
|
val pos: Pos,
|
||||||
|
) : BytecodeConst()
|
||||||
data class CallArgsPlan(val tailBlock: Boolean, val specs: List<CallArgSpec>) : BytecodeConst()
|
data class CallArgsPlan(val tailBlock: Boolean, val specs: List<CallArgSpec>) : BytecodeConst()
|
||||||
data class CallArgSpec(val name: String?, val isSplat: Boolean)
|
data class CallArgSpec(val name: String?, val isSplat: Boolean)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,7 +144,7 @@ class CmdBuilder {
|
|||||||
listOf(OperandKind.CONST, OperandKind.SLOT)
|
listOf(OperandKind.CONST, OperandKind.SLOT)
|
||||||
Opcode.PUSH_SCOPE, Opcode.PUSH_SLOT_PLAN ->
|
Opcode.PUSH_SCOPE, Opcode.PUSH_SLOT_PLAN ->
|
||||||
listOf(OperandKind.CONST)
|
listOf(OperandKind.CONST)
|
||||||
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED ->
|
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_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,
|
||||||
Opcode.ADD_REAL, Opcode.SUB_REAL, Opcode.MUL_REAL, Opcode.DIV_REAL,
|
Opcode.ADD_REAL, Opcode.SUB_REAL, Opcode.MUL_REAL, Opcode.DIV_REAL,
|
||||||
@ -378,6 +378,7 @@ class CmdBuilder {
|
|||||||
Opcode.POP_SLOT_PLAN -> CmdPopSlotPlan()
|
Opcode.POP_SLOT_PLAN -> CmdPopSlotPlan()
|
||||||
Opcode.DECL_LOCAL -> CmdDeclLocal(operands[0], operands[1])
|
Opcode.DECL_LOCAL -> CmdDeclLocal(operands[0], operands[1])
|
||||||
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_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.CALL_MEMBER_SLOT -> CmdCallMemberSlot(operands[0], operands[1], operands[2], operands[3], operands[4])
|
Opcode.CALL_MEMBER_SLOT -> CmdCallMemberSlot(operands[0], operands[1], operands[2], operands[3], operands[4])
|
||||||
|
|||||||
@ -186,6 +186,7 @@ object CmdDisassembler {
|
|||||||
is CmdPopSlotPlan -> Opcode.POP_SLOT_PLAN to intArrayOf()
|
is CmdPopSlotPlan -> Opcode.POP_SLOT_PLAN to intArrayOf()
|
||||||
is CmdDeclLocal -> Opcode.DECL_LOCAL to intArrayOf(cmd.constId, cmd.slot)
|
is CmdDeclLocal -> Opcode.DECL_LOCAL to intArrayOf(cmd.constId, cmd.slot)
|
||||||
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 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 CmdCallMemberSlot -> Opcode.CALL_MEMBER_SLOT to intArrayOf(cmd.recvSlot, cmd.methodId, cmd.argBase, cmd.argCount, cmd.dst)
|
is CmdCallMemberSlot -> Opcode.CALL_MEMBER_SLOT to intArrayOf(cmd.recvSlot, cmd.methodId, cmd.argBase, cmd.argCount, cmd.dst)
|
||||||
@ -241,7 +242,7 @@ object CmdDisassembler {
|
|||||||
listOf(OperandKind.CONST, OperandKind.SLOT)
|
listOf(OperandKind.CONST, OperandKind.SLOT)
|
||||||
Opcode.PUSH_SCOPE, Opcode.PUSH_SLOT_PLAN ->
|
Opcode.PUSH_SCOPE, Opcode.PUSH_SLOT_PLAN ->
|
||||||
listOf(OperandKind.CONST)
|
listOf(OperandKind.CONST)
|
||||||
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED ->
|
Opcode.DECL_LOCAL, Opcode.DECL_EXT_PROPERTY, Opcode.DECL_DELEGATED, Opcode.DECL_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,
|
||||||
Opcode.ADD_REAL, Opcode.SUB_REAL, Opcode.MUL_REAL, Opcode.DIV_REAL,
|
Opcode.ADD_REAL, Opcode.SUB_REAL, Opcode.MUL_REAL, Opcode.DIV_REAL,
|
||||||
|
|||||||
@ -1216,6 +1216,30 @@ class CmdDeclDelegated(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) {
|
||||||
|
val decl = frame.fn.constants[constId] as? BytecodeConst.DestructureDecl
|
||||||
|
?: error("DECL_DESTRUCTURE expects DestructureDecl at $constId")
|
||||||
|
val value = frame.slotToObj(slot)
|
||||||
|
val scope = frame.ensureScope()
|
||||||
|
for (name in decl.names) {
|
||||||
|
scope.addItem(name, true, ObjVoid, decl.visibility, isTransient = decl.isTransient)
|
||||||
|
}
|
||||||
|
decl.pattern.setAt(decl.pos, scope, value)
|
||||||
|
if (!decl.isMutable) {
|
||||||
|
for (name in decl.names) {
|
||||||
|
val rec = scope.objects[name] ?: continue
|
||||||
|
val immutableRec = rec.copy(isMutable = false)
|
||||||
|
scope.objects[name] = immutableRec
|
||||||
|
scope.localBindings[name] = immutableRec
|
||||||
|
scope.updateSlotFor(name, immutableRec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.storeObjResult(slot, ObjVoid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CmdDeclExtProperty(internal val constId: Int, internal val slot: Int) : Cmd() {
|
class CmdDeclExtProperty(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.ExtensionPropertyDecl
|
val decl = frame.fn.constants[constId] as? BytecodeConst.ExtensionPropertyDecl
|
||||||
|
|||||||
@ -126,6 +126,7 @@ enum class Opcode(val code: Int) {
|
|||||||
DECL_LOCAL(0x89),
|
DECL_LOCAL(0x89),
|
||||||
DECL_EXT_PROPERTY(0x8A),
|
DECL_EXT_PROPERTY(0x8A),
|
||||||
DECL_DELEGATED(0x8B),
|
DECL_DELEGATED(0x8B),
|
||||||
|
DECL_DESTRUCTURE(0x8C),
|
||||||
|
|
||||||
CALL_DIRECT(0x90),
|
CALL_DIRECT(0x90),
|
||||||
CALL_MEMBER_SLOT(0x92),
|
CALL_MEMBER_SLOT(0x92),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user