Type operators.

This commit is contained in:
Dmitry Petrov
2016-08-19 11:33:44 +03:00
committed by Dmitry Petrov
parent 5709826096
commit d6040d8570
9 changed files with 135 additions and 57 deletions
@@ -19,66 +19,65 @@ package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.ir.expressions.IrBinaryOperator
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.lexer.KtTokens
fun getIrBinaryOperator(ktOperator: IElementType): IrBinaryOperator? =
KT_TOKEN_TO_IR_BINARY_OPERATOR[ktOperator]
when (ktOperator) {
KtTokens.EQ -> IrOperator.EQ
KtTokens.PLUSEQ -> IrOperator.PLUSEQ
KtTokens.MINUSEQ -> IrOperator.MINUSEQ
KtTokens.MULTEQ -> IrOperator.MULTEQ
KtTokens.DIVEQ -> IrOperator.DIVEQ
KtTokens.PERCEQ -> IrOperator.PERCEQ
KtTokens.PLUS -> IrOperator.PLUS
KtTokens.MINUS -> IrOperator.MINUS
KtTokens.MUL -> IrOperator.MUL
KtTokens.DIV -> IrOperator.DIV
KtTokens.PERC -> IrOperator.PERC
KtTokens.RANGE -> IrOperator.RANGE
KtTokens.LT -> IrOperator.LT
KtTokens.LTEQ -> IrOperator.LTEQ
KtTokens.GT -> IrOperator.GT
KtTokens.GTEQ -> IrOperator.GTEQ
KtTokens.EQEQ -> IrOperator.EQEQ
KtTokens.EXCLEQ -> IrOperator.EXCLEQ
KtTokens.EQEQEQ -> IrOperator.EQEQEQ
KtTokens.EXCLEQEQEQ -> IrOperator.EXCLEQEQ
KtTokens.IN_KEYWORD -> IrOperator.IN
KtTokens.NOT_IN -> IrOperator.NOT_IN
KtTokens.ANDAND -> IrOperator.ANDAND
KtTokens.OROR -> IrOperator.OROR
KtTokens.ELVIS -> IrOperator.ELVIS
else -> null
}
fun getIrPrefixOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_PREFIX_OPERATOR[ktOperator]
when (ktOperator) {
KtTokens.PLUSPLUS -> IrOperator.PREFIX_INCR
KtTokens.MINUSMINUS -> IrOperator.PREFIX_DECR
KtTokens.EXCL -> IrOperator.EXCL
KtTokens.MINUS -> IrOperator.UMINUS
else -> null
}
fun getIrPostfixOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_POSTFIX_OPERATOR[ktOperator]
when (ktOperator) {
KtTokens.PLUSPLUS -> IrOperator.POSTFIX_INCR
KtTokens.MINUSMINUS -> IrOperator.POSTFIX_DECR
KtTokens.EXCLEXCL -> IrOperator.EXCLEXCL
else -> null
}
private val KT_TOKEN_TO_IR_BINARY_OPERATOR = mapOf<IElementType, IrBinaryOperator>(
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,
KtTokens.ANDAND to IrOperator.ANDAND,
KtTokens.OROR to IrOperator.OROR,
KtTokens.ELVIS to IrOperator.ELVIS
)
private val KT_TOKEN_TO_IR_PREFIX_OPERATOR = mapOf<IElementType, IrOperator>(
KtTokens.PLUSPLUS to IrOperator.PREFIX_INCR,
KtTokens.MINUSMINUS to IrOperator.PREFIX_DECR,
KtTokens.EXCL to IrOperator.EXCL,
KtTokens.MINUS to IrOperator.UMINUS
)
private val KT_TOKEN_TO_IR_POSTFIX_OPERATOR = mapOf<IElementType, IrOperator>(
KtTokens.PLUSPLUS to IrOperator.POSTFIX_INCR,
KtTokens.MINUSMINUS to IrOperator.POSTFIX_DECR,
KtTokens.EXCLEXCL to IrOperator.EXCLEXCL
)
fun getIrTypeOperator(ktOperator: IElementType): IrTypeOperator? =
when (ktOperator) {
KtTokens.IS_KEYWORD -> IrTypeOperator.INSTANCEOF
KtTokens.NOT_IS -> IrTypeOperator.NOT_INSTANCEOF
KtTokens.AS_KEYWORD -> IrTypeOperator.CAST
KtTokens.AS_SAFE -> IrTypeOperator.SAFE_CAST
else -> null
}
val AUGMENTED_ASSIGNMENTS =
setOf(IrOperator.PLUSEQ, IrOperator.MINUSEQ, IrOperator.MULTEQ, IrOperator.DIVEQ, IrOperator.PERCEQ)
@@ -52,6 +52,33 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I
TODO("not implemented")
}
fun generateCastExpression(expression: KtBinaryExpressionWithTypeRHS): IrExpression {
val ktOperator = expression.operationReference.getReferencedNameElementType()
val irOperator = getIrTypeOperator(ktOperator)
val rhsType = getOrFail(BindingContext.TYPE, expression.right!!)
val resultType = when (irOperator) {
IrTypeOperator.CAST ->
rhsType
IrTypeOperator.SAFE_CAST ->
rhsType.makeNullable()
else ->
throw AssertionError("Unexpected IrTypeOperator: $irOperator")
}
return IrTypeOperatorExpressionImpl(expression.startOffset, expression.endOffset, resultType, irOperator, rhsType,
statementGenerator.generateExpression(expression.left))
}
fun generateInstanceOfExpression(expression: KtIsExpression): IrStatement {
val ktOperator = expression.operationReference.getReferencedNameElementType()
val irOperator = getIrTypeOperator(ktOperator)!!
val againstType = getOrFail(BindingContext.TYPE, expression.typeReference)
return IrTypeOperatorExpressionImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator,
againstType, statementGenerator.generateExpression(expression.leftHandSide))
}
fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression {
val ktOperator = expression.operationReference.getReferencedNameElementType()
if (ktOperator == KtTokens.IDENTIFIER) {
@@ -247,6 +247,12 @@ class StatementGenerator(
override fun visitPostfixExpression(expression: KtPostfixExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generatePostfixExpression(expression)
override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generateCastExpression(expression)
override fun visitIsExpression(expression: KtIsExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generateInstanceOfExpression(expression)
override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement {
val resultType = getInferredTypeWithSmartcasts(expression)
val irWhen = IrWhenExpressionImpl(expression.startOffset, expression.endOffset, resultType)
@@ -273,4 +279,6 @@ class StatementGenerator(
return irWhen
}
}
+4 -2
View File
@@ -17,11 +17,13 @@ IrFile /elvis.kt
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String
GET_VAR b type=kotlin.Any? operator=null
then: RETURN type=<no-type>
LITERAL String type=kotlin.String value=''
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String?
GET_VAR a type=kotlin.Any? operator=null
then: RETURN type=<no-type>
LITERAL String type=kotlin.String value=''
RETURN type=<no-type>
+6 -3
View File
@@ -19,7 +19,8 @@ IrFile /smartCasts.kt
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String
GET_VAR x type=kotlin.Any operator=null
then: RETURN type=<no-type>
CALL .println type=kotlin.Unit operator=null
message: GET_PROPERTY .length type=kotlin.Int operator=null
@@ -40,7 +41,8 @@ IrFile /smartCasts.kt
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String
GET_VAR x type=kotlin.Any operator=null
then: RETURN type=<no-type>
LITERAL String type=kotlin.String value=''
RETURN type=<no-type>
@@ -51,7 +53,8 @@ IrFile /smartCasts.kt
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String
GET_VAR x type=kotlin.Any operator=null
then: RETURN type=<no-type>
LITERAL String type=kotlin.String value=''
RETURN type=<no-type>
@@ -15,7 +15,8 @@ IrFile /smartCastsWithDestructuring.kt
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
WHEN subject=null type=kotlin.Unit
if: DUMMY KtIsExpression type=kotlin.Boolean
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=I2
GET_VAR x type=I1 operator=null
then: RETURN type=<no-type>
BLOCK type=<no-type> hasResult=false operator=SYNTHETIC_BLOCK
VAR val tmp0: I1
+6
View File
@@ -0,0 +1,6 @@
interface IThing
fun test1(x: Any) = x is IThing
fun test2(x: Any) = x !is IThing
fun test3(x: Any) = x as IThing
fun test4(x: Any) = x as? IThing
+26
View File
@@ -0,0 +1,26 @@
IrFile /typeOperators.kt
DUMMY IThing
IrFunction public fun test1(/*0*/ x: kotlin.Any): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
RETURN type=<no-type>
TYPE_OP operator=INSTANCEOF typeOperand=IThing
GET_VAR x type=kotlin.Any operator=null
IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.Boolean
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
RETURN type=<no-type>
TYPE_OP operator=NOT_INSTANCEOF typeOperand=IThing
GET_VAR x type=kotlin.Any operator=null
IrFunction public fun test3(/*0*/ x: kotlin.Any): IThing
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
RETURN type=<no-type>
TYPE_OP operator=CAST typeOperand=IThing
GET_VAR x type=kotlin.Any operator=null
IrFunction public fun test4(/*0*/ x: kotlin.Any): IThing?
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
RETURN type=<no-type>
TYPE_OP operator=SAFE_CAST typeOperand=IThing
GET_VAR x type=kotlin.Any operator=null
@@ -208,4 +208,10 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/stringPlus.kt");
doTest(fileName);
}
@TestMetadata("typeOperators.kt")
public void testTypeOperators() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/typeOperators.kt");
doTest(fileName);
}
}