diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt index c4ffa70..10efdcf 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt @@ -217,6 +217,7 @@ class BytecodeCompiler( is AssignOpRef -> compileAssignOp(ref) ?: compileEvalRef(ref) is AssignIfNullRef -> compileAssignIfNull(ref) is IncDecRef -> compileIncDec(ref, true) + is RangeRef -> compileRangeRef(ref) is ConditionalRef -> compileConditional(ref) is ElvisRef -> compileElvis(ref) is CallRef -> compileCall(ref) @@ -1216,6 +1217,34 @@ class BytecodeCompiler( 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( targetType: SlotType, rhs: CompiledValue, diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdBuilder.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdBuilder.kt index 1f342dc..e3b30da 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdBuilder.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdBuilder.kt @@ -182,6 +182,8 @@ class CmdBuilder { listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) Opcode.SET_INDEX -> listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) + Opcode.MAKE_RANGE -> + listOf(OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT, OperandKind.SLOT) Opcode.LIST_LITERAL -> listOf(OperandKind.CONST, OperandKind.SLOT, OperandKind.COUNT, OperandKind.SLOT) Opcode.GET_THIS_MEMBER -> @@ -225,6 +227,7 @@ class CmdBuilder { Opcode.BOX_OBJ -> CmdBoxObj(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.MAKE_RANGE -> CmdMakeRange(operands[0], operands[1], operands[2], operands[3]) Opcode.CHECK_IS -> CmdCheckIs(operands[0], operands[1], operands[2]) Opcode.ASSERT_IS -> CmdAssertIs(operands[0], operands[1]) Opcode.RET_LABEL -> CmdRetLabel(operands[0], operands[1]) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdDisassembler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdDisassembler.kt index 5b5fc09..2692207 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdDisassembler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdDisassembler.kt @@ -72,6 +72,7 @@ object CmdDisassembler { 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 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 CmdLoadObjAddr -> Opcode.LOAD_OBJ_ADDR to intArrayOf(cmd.addrSlot, cmd.dst) is CmdStoreObjAddr -> Opcode.STORE_OBJ_ADDR to intArrayOf(cmd.src, cmd.addrSlot) @@ -213,7 +214,7 @@ object CmdDisassembler { listOf(OperandKind.SLOT, OperandKind.SLOT) Opcode.CHECK_IS -> 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) Opcode.RET_LABEL, Opcode.THROW -> listOf(OperandKind.CONST, OperandKind.SLOT) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdRuntime.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdRuntime.kt index 4324ca0..e7b44d9 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdRuntime.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/CmdRuntime.kt @@ -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() { override suspend fun perform(frame: CmdFrame) { frame.setObj(dst, ObjNull) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/Opcode.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/Opcode.kt index 91f20ea..790c56d 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/Opcode.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/Opcode.kt @@ -29,6 +29,7 @@ enum class Opcode(val code: Int) { CONST_NULL(0x09), BOX_OBJ(0x0A), RANGE_INT_BOUNDS(0x0B), + MAKE_RANGE(0x0C), INT_TO_REAL(0x10), REAL_TO_INT(0x11), diff --git a/lynglib/src/commonTest/kotlin/ScriptTest.kt b/lynglib/src/commonTest/kotlin/ScriptTest.kt index 0e7df11..0b71fc8 100644 --- a/lynglib/src/commonTest/kotlin/ScriptTest.kt +++ b/lynglib/src/commonTest/kotlin/ScriptTest.kt @@ -1217,7 +1217,6 @@ class ScriptTest { ) } - @Ignore("Bytecode: unsupported or incorrect behavior") @Test fun forLoop1() = runTest { eval( @@ -1245,7 +1244,6 @@ class ScriptTest { ) } - @Ignore("Bytecode: unsupported or incorrect behavior") @Test fun forLoop2() = runTest { println( @@ -1371,7 +1369,6 @@ class ScriptTest { ) } - @Ignore("Bytecode: unsupported or incorrect behavior") @Test fun testOpenEndRanges() = runTest { eval( @@ -1384,7 +1381,6 @@ class ScriptTest { ) } - @Ignore("Bytecode: unsupported or incorrect behavior") @Test fun testOpenEndRanges2() = runTest { eval(