Bytecode compile in/not in via contains
This commit is contained in:
parent
63bcb91504
commit
250220a42f
@ -204,6 +204,29 @@ class BytecodeCompiler(
|
|||||||
if (op == BinOp.AND || op == BinOp.OR) {
|
if (op == BinOp.AND || op == BinOp.OR) {
|
||||||
return compileLogical(op, binaryLeft(ref), binaryRight(ref), refPos(ref))
|
return compileLogical(op, binaryLeft(ref), binaryRight(ref), refPos(ref))
|
||||||
}
|
}
|
||||||
|
if (op == BinOp.IN || op == BinOp.NOTIN) {
|
||||||
|
val leftValue = compileRefWithFallback(binaryLeft(ref), null, refPos(ref)) ?: return null
|
||||||
|
val rightValue = compileRefWithFallback(binaryRight(ref), null, refPos(ref)) ?: return null
|
||||||
|
val leftObj = ensureObjSlot(leftValue)
|
||||||
|
val rightObj = ensureObjSlot(rightValue)
|
||||||
|
val methodId = builder.addConst(BytecodeConst.StringVal("contains"))
|
||||||
|
if (methodId > 0xFFFF) return null
|
||||||
|
val argSlot = allocSlot()
|
||||||
|
builder.emit(Opcode.BOX_OBJ, leftObj.slot, argSlot)
|
||||||
|
updateSlotType(argSlot, SlotType.OBJ)
|
||||||
|
val callSlot = allocSlot()
|
||||||
|
builder.emit(Opcode.CALL_VIRTUAL, rightObj.slot, methodId, argSlot, 1, callSlot)
|
||||||
|
val boolSlot = allocSlot()
|
||||||
|
builder.emit(Opcode.OBJ_TO_BOOL, callSlot, boolSlot)
|
||||||
|
updateSlotType(boolSlot, SlotType.BOOL)
|
||||||
|
if (op == BinOp.NOTIN) {
|
||||||
|
val outSlot = allocSlot()
|
||||||
|
builder.emit(Opcode.NOT_BOOL, boolSlot, outSlot)
|
||||||
|
updateSlotType(outSlot, SlotType.BOOL)
|
||||||
|
return CompiledValue(outSlot, SlotType.BOOL)
|
||||||
|
}
|
||||||
|
return CompiledValue(boolSlot, SlotType.BOOL)
|
||||||
|
}
|
||||||
val leftRef = binaryLeft(ref)
|
val leftRef = binaryLeft(ref)
|
||||||
val rightRef = binaryRight(ref)
|
val rightRef = binaryRight(ref)
|
||||||
var a = compileRef(leftRef) ?: return null
|
var a = compileRef(leftRef) ?: return null
|
||||||
|
|||||||
@ -5201,6 +5201,20 @@ class ScriptTest {
|
|||||||
assertEquals(ObjInt(2), scope.eval("firstEvenOrMinus()"))
|
assertEquals(ObjInt(2), scope.eval("firstEvenOrMinus()"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInOperatorBytecode() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
fun inList(x, xs) { x in xs }
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
val disasm = scope.disassembleSymbol("inList")
|
||||||
|
assertFalse(disasm.contains("not a compiled body"))
|
||||||
|
assertEquals(ObjTrue, scope.eval("inList(2, [1,2,3])"))
|
||||||
|
assertEquals(ObjFalse, scope.eval("inList(5, [1,2,3])"))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFilterBug() = runTest {
|
fun testFilterBug() = runTest {
|
||||||
eval(
|
eval(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user