Add bytecode MAKE_RANGE and re-enable open range tests

This commit is contained in:
Sergey Chernov 2026-01-29 03:40:40 +03:00
parent eaee738dee
commit a73c118c77
6 changed files with 50 additions and 5 deletions

View File

@ -217,6 +217,7 @@ class BytecodeCompiler(
is AssignOpRef -> compileAssignOp(ref) ?: compileEvalRef(ref) is AssignOpRef -> compileAssignOp(ref) ?: compileEvalRef(ref)
is AssignIfNullRef -> compileAssignIfNull(ref) is AssignIfNullRef -> compileAssignIfNull(ref)
is IncDecRef -> compileIncDec(ref, true) is IncDecRef -> compileIncDec(ref, true)
is RangeRef -> compileRangeRef(ref)
is ConditionalRef -> compileConditional(ref) is ConditionalRef -> compileConditional(ref)
is ElvisRef -> compileElvis(ref) is ElvisRef -> compileElvis(ref)
is CallRef -> compileCall(ref) is CallRef -> compileCall(ref)
@ -1216,6 +1217,34 @@ class BytecodeCompiler(
return CompiledValue(dst, SlotType.OBJ) return CompiledValue(dst, SlotType.OBJ)
} }
private fun compileRangeRef(ref: RangeRef): CompiledValue? {
val startSlot = if (ref.left != null) {
val start = compileRefWithFallback(ref.left, null, Pos.builtIn) ?: return null
ensureObjSlot(start).slot
} else {
val slot = allocSlot()
builder.emit(Opcode.CONST_NULL, slot)
updateSlotType(slot, SlotType.OBJ)
slot
}
val endSlot = if (ref.right != null) {
val end = compileRefWithFallback(ref.right, null, Pos.builtIn) ?: return null
ensureObjSlot(end).slot
} else {
val slot = allocSlot()
builder.emit(Opcode.CONST_NULL, slot)
updateSlotType(slot, SlotType.OBJ)
slot
}
val inclusiveSlot = allocSlot()
val inclusiveId = builder.addConst(BytecodeConst.Bool(ref.isEndInclusive))
builder.emit(Opcode.CONST_BOOL, inclusiveId, inclusiveSlot)
val dst = allocSlot()
builder.emit(Opcode.MAKE_RANGE, startSlot, endSlot, inclusiveSlot, dst)
updateSlotType(dst, SlotType.OBJ)
return CompiledValue(dst, SlotType.OBJ)
}
private fun compileAssignOpBinary( private fun compileAssignOpBinary(
targetType: SlotType, targetType: SlotType,
rhs: CompiledValue, rhs: CompiledValue,

View File

@ -182,6 +182,8 @@ class CmdBuilder {
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
Opcode.SET_INDEX -> Opcode.SET_INDEX ->
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
Opcode.MAKE_RANGE ->
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
Opcode.LIST_LITERAL -> Opcode.LIST_LITERAL ->
listOf(OperandKind.CONST, OperandKind.SLOT, OperandKind.COUNT, OperandKind.SLOT) listOf(OperandKind.CONST, OperandKind.SLOT, OperandKind.COUNT, OperandKind.SLOT)
Opcode.GET_THIS_MEMBER -> Opcode.GET_THIS_MEMBER ->
@ -225,6 +227,7 @@ class CmdBuilder {
Opcode.BOX_OBJ -> CmdBoxObj(operands[0], operands[1]) Opcode.BOX_OBJ -> CmdBoxObj(operands[0], operands[1])
Opcode.OBJ_TO_BOOL -> CmdObjToBool(operands[0], operands[1]) Opcode.OBJ_TO_BOOL -> CmdObjToBool(operands[0], operands[1])
Opcode.RANGE_INT_BOUNDS -> CmdRangeIntBounds(operands[0], operands[1], operands[2], operands[3]) Opcode.RANGE_INT_BOUNDS -> CmdRangeIntBounds(operands[0], operands[1], operands[2], operands[3])
Opcode.MAKE_RANGE -> CmdMakeRange(operands[0], operands[1], operands[2], operands[3])
Opcode.CHECK_IS -> CmdCheckIs(operands[0], operands[1], operands[2]) Opcode.CHECK_IS -> CmdCheckIs(operands[0], operands[1], operands[2])
Opcode.ASSERT_IS -> CmdAssertIs(operands[0], operands[1]) Opcode.ASSERT_IS -> CmdAssertIs(operands[0], operands[1])
Opcode.RET_LABEL -> CmdRetLabel(operands[0], operands[1]) Opcode.RET_LABEL -> CmdRetLabel(operands[0], operands[1])

View File

@ -72,6 +72,7 @@ object CmdDisassembler {
is CmdCheckIs -> Opcode.CHECK_IS to intArrayOf(cmd.objSlot, cmd.typeSlot, cmd.dst) is CmdCheckIs -> Opcode.CHECK_IS to intArrayOf(cmd.objSlot, cmd.typeSlot, cmd.dst)
is CmdAssertIs -> Opcode.ASSERT_IS to intArrayOf(cmd.objSlot, cmd.typeSlot) is CmdAssertIs -> Opcode.ASSERT_IS to intArrayOf(cmd.objSlot, cmd.typeSlot)
is CmdRangeIntBounds -> Opcode.RANGE_INT_BOUNDS to intArrayOf(cmd.src, cmd.startSlot, cmd.endSlot, cmd.okSlot) is CmdRangeIntBounds -> Opcode.RANGE_INT_BOUNDS to intArrayOf(cmd.src, cmd.startSlot, cmd.endSlot, cmd.okSlot)
is CmdMakeRange -> Opcode.MAKE_RANGE to intArrayOf(cmd.startSlot, cmd.endSlot, cmd.inclusiveSlot, cmd.dst)
is CmdResolveScopeSlot -> Opcode.RESOLVE_SCOPE_SLOT to intArrayOf(cmd.scopeSlot, cmd.addrSlot) is CmdResolveScopeSlot -> Opcode.RESOLVE_SCOPE_SLOT to intArrayOf(cmd.scopeSlot, cmd.addrSlot)
is CmdLoadObjAddr -> Opcode.LOAD_OBJ_ADDR to intArrayOf(cmd.addrSlot, cmd.dst) is CmdLoadObjAddr -> Opcode.LOAD_OBJ_ADDR to intArrayOf(cmd.addrSlot, cmd.dst)
is CmdStoreObjAddr -> Opcode.STORE_OBJ_ADDR to intArrayOf(cmd.src, cmd.addrSlot) is CmdStoreObjAddr -> Opcode.STORE_OBJ_ADDR to intArrayOf(cmd.src, cmd.addrSlot)
@ -213,7 +214,7 @@ object CmdDisassembler {
listOf(OperandKind.SLOT, OperandKind.SLOT) listOf(OperandKind.SLOT, OperandKind.SLOT)
Opcode.CHECK_IS -> Opcode.CHECK_IS ->
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
Opcode.RANGE_INT_BOUNDS -> Opcode.RANGE_INT_BOUNDS, Opcode.MAKE_RANGE ->
listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT)
Opcode.RET_LABEL, Opcode.THROW -> Opcode.RET_LABEL, Opcode.THROW ->
listOf(OperandKind.CONST, OperandKind.SLOT) listOf(OperandKind.CONST, OperandKind.SLOT)

View File

@ -141,6 +141,21 @@ class CmdConstBool(internal val constId: Int, internal val dst: Int) : Cmd() {
} }
} }
class CmdMakeRange(
internal val startSlot: Int,
internal val endSlot: Int,
internal val inclusiveSlot: Int,
internal val dst: Int,
) : Cmd() {
override suspend fun perform(frame: CmdFrame) {
val start = frame.slotToObj(startSlot)
val end = frame.slotToObj(endSlot)
val inclusive = frame.slotToObj(inclusiveSlot).toBool()
frame.storeObjResult(dst, ObjRange(start, end, isEndInclusive = inclusive))
return
}
}
class CmdConstNull(internal val dst: Int) : Cmd() { class CmdConstNull(internal val dst: Int) : Cmd() {
override suspend fun perform(frame: CmdFrame) { override suspend fun perform(frame: CmdFrame) {
frame.setObj(dst, ObjNull) frame.setObj(dst, ObjNull)

View File

@ -29,6 +29,7 @@ enum class Opcode(val code: Int) {
CONST_NULL(0x09), CONST_NULL(0x09),
BOX_OBJ(0x0A), BOX_OBJ(0x0A),
RANGE_INT_BOUNDS(0x0B), RANGE_INT_BOUNDS(0x0B),
MAKE_RANGE(0x0C),
INT_TO_REAL(0x10), INT_TO_REAL(0x10),
REAL_TO_INT(0x11), REAL_TO_INT(0x11),

View File

@ -1217,7 +1217,6 @@ class ScriptTest {
) )
} }
@Ignore("Bytecode: unsupported or incorrect behavior")
@Test @Test
fun forLoop1() = runTest { fun forLoop1() = runTest {
eval( eval(
@ -1245,7 +1244,6 @@ class ScriptTest {
) )
} }
@Ignore("Bytecode: unsupported or incorrect behavior")
@Test @Test
fun forLoop2() = runTest { fun forLoop2() = runTest {
println( println(
@ -1371,7 +1369,6 @@ class ScriptTest {
) )
} }
@Ignore("Bytecode: unsupported or incorrect behavior")
@Test @Test
fun testOpenEndRanges() = runTest { fun testOpenEndRanges() = runTest {
eval( eval(
@ -1384,7 +1381,6 @@ class ScriptTest {
) )
} }
@Ignore("Bytecode: unsupported or incorrect behavior")
@Test @Test
fun testOpenEndRanges2() = runTest { fun testOpenEndRanges2() = runTest {
eval( eval(