'in' and '!in' operators.

This commit is contained in:
Dmitry Petrov
2016-08-17 17:21:33 +03:00
committed by Dmitry Petrov
parent 96e3c52878
commit 0d94c3aeb4
5 changed files with 131 additions and 47 deletions
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.lexer.KtTokens
internal fun getIrOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_OPERATOR[ktOperator]
internal val KT_TOKEN_TO_IR_OPERATOR =
mapOf(
KtTokens.EQ to IrOperator.EQ,
KtTokens.PLUSEQ to IrOperator.PLUSEQ,
KtTokens.MINUSEQ to IrOperator.MINUSEQ,
KtTokens.MULTEQ to IrOperator.MULTEQ,
KtTokens.DIVEQ to IrOperator.DIVEQ,
KtTokens.PERCEQ to IrOperator.PERCEQ,
KtTokens.PLUS to IrOperator.PLUS,
KtTokens.MINUS to IrOperator.MINUS,
KtTokens.MUL to IrOperator.MUL,
KtTokens.DIV to IrOperator.DIV,
KtTokens.PERC to IrOperator.PERC,
KtTokens.RANGE to IrOperator.RANGE,
KtTokens.LT to IrOperator.LT,
KtTokens.LTEQ to IrOperator.LTEQ,
KtTokens.GT to IrOperator.GT,
KtTokens.GTEQ to IrOperator.GTEQ,
KtTokens.EQEQ to IrOperator.EQEQ,
KtTokens.EXCLEQ to IrOperator.EXCLEQ,
KtTokens.EQEQEQ to IrOperator.EQEQEQ,
KtTokens.EXCLEQEQEQ to IrOperator.EXCLEQEQ,
KtTokens.IN_KEYWORD to IrOperator.IN,
KtTokens.NOT_IN to IrOperator.NOT_IN
)
internal val AUGMENTED_ASSIGNMENTS =
setOf(IrOperator.PLUSEQ, IrOperator.MINUSEQ, IrOperator.MULTEQ, IrOperator.DIVEQ, IrOperator.PERCEQ)
internal val BINARY_OPERATORS_DESUGARED_TO_CALLS =
setOf(IrOperator.PLUS, IrOperator.MINUS, IrOperator.MUL, IrOperator.DIV, IrOperator.PERC, IrOperator.RANGE)
internal val COMPARISON_OPERATORS =
setOf(IrOperator.LT, IrOperator.LTEQ, IrOperator.GT, IrOperator.GTEQ)
internal val EQUALITY_OPERATORS =
setOf(IrOperator.EQEQ, IrOperator.EXCLEQ)
internal val IDENTITY_OPERATORS =
setOf(IrOperator.EQEQEQ, IrOperator.EXCLEQEQ)
internal val IN_OPERATORS =
setOf(IrOperator.IN, IrOperator.NOT_IN)
@@ -16,13 +16,12 @@
package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrBinaryOperatorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.ir.expressions.IrUnaryOperatorExpressionImpl
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
@@ -34,48 +33,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.types.typeUtil.makeNullable
internal val KT_TOKEN_TO_IR_OPERATOR =
mapOf(
KtTokens.EQ to IrOperator.EQ,
KtTokens.PLUSEQ to IrOperator.PLUSEQ,
KtTokens.MINUSEQ to IrOperator.MINUSEQ,
KtTokens.MULTEQ to IrOperator.MULTEQ,
KtTokens.DIVEQ to IrOperator.DIVEQ,
KtTokens.PERCEQ to IrOperator.PERCEQ,
KtTokens.PLUS to IrOperator.PLUS,
KtTokens.MINUS to IrOperator.MINUS,
KtTokens.MUL to IrOperator.MUL,
KtTokens.DIV to IrOperator.DIV,
KtTokens.PERC to IrOperator.PERC,
KtTokens.RANGE to IrOperator.RANGE,
KtTokens.LT to IrOperator.LT,
KtTokens.LTEQ to IrOperator.LTEQ,
KtTokens.GT to IrOperator.GT,
KtTokens.GTEQ to IrOperator.GTEQ,
KtTokens.EQEQ to IrOperator.EQEQ,
KtTokens.EXCLEQ to IrOperator.EXCLEQ,
KtTokens.EQEQEQ to IrOperator.EQEQEQ,
KtTokens.EXCLEQEQEQ to IrOperator.EXCLEQEQ
)
internal val AUGMENTED_ASSIGNMENTS =
setOf(IrOperator.PLUSEQ, IrOperator.MINUSEQ, IrOperator.MULTEQ, IrOperator.DIVEQ, IrOperator.PERCEQ)
internal val BINARY_OPERATORS_DESUGARED_TO_CALLS =
setOf(IrOperator.PLUS, IrOperator.MINUS, IrOperator.MUL, IrOperator.DIV, IrOperator.PERC, IrOperator.RANGE)
internal val COMPARISON_OPERATORS =
setOf(IrOperator.LT, IrOperator.LTEQ, IrOperator.GT, IrOperator.GTEQ)
internal val EQUALITY_OPERATORS =
setOf(IrOperator.EQEQ, IrOperator.EXCLEQ)
internal val IDENTITY_OPERATORS =
setOf(IrOperator.EQEQEQ, IrOperator.EXCLEQEQ)
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
override val context: IrGeneratorContext get() = irStatementGenerator.context
@@ -92,10 +49,23 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
in COMPARISON_OPERATORS -> generateComparisonOperator(expression, irOperator)
in EQUALITY_OPERATORS -> generateEqualityOperator(expression, irOperator)
in IDENTITY_OPERATORS -> generateIdentityOperator(expression, irOperator)
in IN_OPERATORS -> generateInOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
}
}
private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
val operatorCall = getResolvedCall(expression)!!
val irOperatorCall = IrCallGenerator(irStatementGenerator).generateCall(expression, operatorCall, irOperator)
return if (irOperator == IrOperator.IN)
irOperatorCall
else
IrUnaryOperatorExpressionImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType,
IrOperator.EXCL, null, irOperatorCall)
}
private fun generateIdentityOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!)
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!)
@@ -175,9 +145,6 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
}
}
private fun getIrOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_OPERATOR[ktOperator]
private fun generateAssignment(expression: KtBinaryExpression): IrExpression {
val ktLeft = expression.left!!
val ktRight = expression.right!!
+4
View File
@@ -0,0 +1,4 @@
fun test1(a: Any, x: Collection<Any>) = a in x
fun test2(a: Any, x: Collection<Any>) = a !in x
fun <T> test3(a: T, x: Collection<T>) = a in x
fun <T> test4(a: T, x: Collection<T>) = a !in x
+31
View File
@@ -0,0 +1,31 @@
IrFile /in.kt
IrFunction public fun test1(/*0*/ a: kotlin.Any, /*1*/ x: kotlin.collections.Collection<kotlin.Any>): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=true
RETURN type=<no-type>
CALL .contains type=kotlin.Boolean operator=IN
$this: GET_VAR x type=kotlin.collections.Collection<kotlin.Any>
element: GET_VAR a type=kotlin.Any
IrFunction public fun test2(/*0*/ a: kotlin.Any, /*1*/ x: kotlin.collections.Collection<kotlin.Any>): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=true
RETURN type=<no-type>
UNARY_OP operator=EXCL type=kotlin.Boolean related=null
CALL .contains type=kotlin.Boolean operator=NOT_IN
$this: GET_VAR x type=kotlin.collections.Collection<kotlin.Any>
element: GET_VAR a type=kotlin.Any
IrFunction public fun </*0*/ T> test3(/*0*/ a: T, /*1*/ x: kotlin.collections.Collection<T>): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=true
RETURN type=<no-type>
CALL .contains type=kotlin.Boolean operator=IN
$this: GET_VAR x type=kotlin.collections.Collection<T>
element: GET_VAR a type=T
IrFunction public fun </*0*/ T> test4(/*0*/ a: T, /*1*/ x: kotlin.collections.Collection<T>): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=true
RETURN type=<no-type>
UNARY_OP operator=EXCL type=kotlin.Boolean related=null
CALL .contains type=kotlin.Boolean operator=NOT_IN
$this: GET_VAR x type=kotlin.collections.Collection<T>
element: GET_VAR a type=T
@@ -125,6 +125,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("in.kt")
public void testIn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/in.kt");
doTest(fileName);
}
@TestMetadata("primitiveComparisons.kt")
public void testPrimitiveComparisons() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/primitiveComparisons.kt");