'!!' operator

This commit is contained in:
Dmitry Petrov
2016-08-26 17:31:02 +03:00
committed by Dmitry Petrov
parent 92a7ecfac7
commit 57c1b3e0e2
5 changed files with 64 additions and 0 deletions
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.lang.AssertionError
@@ -60,6 +61,7 @@ class OperatorExpressionGenerator(
return when (irOperator) {
null -> throw AssertionError("Unexpected postfix operator: $ktOperator")
in INCREMENT_DECREMENT_OPERATORS -> generatePostfixIncrementDecrementOperator(expression, irOperator)
IrOperator.EXCLEXCL -> generateExclExclOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
}
}
@@ -272,6 +274,28 @@ class OperatorExpressionGenerator(
}
}
private fun generateExclExclOperator(expression: KtPostfixExpression, irOperator: IrOperator): IrExpression {
val ktArgument = expression.baseExpression!!
val irArgument = statementGenerator.generateExpression(ktArgument)
val ktOperator = expression.operationReference
val resultType = irArgument.type.makeNotNullable()
val irBlock = IrBlockImpl(ktOperator.startOffset, ktOperator.endOffset, resultType, irOperator)
val argumentValue = createRematerializableOrTemporary(scope, irArgument, irBlock, "notnull")
val irIfThenElse = IrIfThenElseImpl(ktOperator.startOffset, ktOperator.endOffset, resultType,
context.equalsNull(ktOperator.startOffset, ktOperator.endOffset, argumentValue.load()),
context.throwNpe(ktOperator.startOffset, ktOperator.endOffset, irOperator),
argumentValue.load())
return if (irBlock.statements.isEmpty()) {
irIfThenElse
}
else {
irBlock.addStatement(irIfThenElse)
irBlock
}
}
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
val resolvedCall = getResolvedCall(expression)!!
return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator)
@@ -35,6 +35,9 @@ fun GeneratorContext.equalsNull(startOffset: Int, endOffset: Int, argument: IrEx
primitiveOp2(startOffset, endOffset, irBuiltIns.eqeq, IrOperator.EQEQ,
argument, constNull(startOffset, endOffset))
fun GeneratorContext.throwNpe(startOffset: Int, endOffset: Int, operator: IrOperator): IrExpression =
IrNullaryPrimitiveImpl(startOffset, endOffset, operator, irBuiltIns.throwNpe)
// a || b == if (a) true else b
fun GeneratorContext.oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen =
IrIfThenElseImpl(startOffset, endOffset, builtIns.booleanType,
+3
View File
@@ -0,0 +1,3 @@
fun test1(a: Any?) = a!!
fun test2(a: Any?) = a?.hashCode()!!
+28
View File
@@ -0,0 +1,28 @@
FILE /bangbang.kt
FUN public fun test1(/*0*/ a: kotlin.Any?): kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from=test1
WHEN type=kotlin.Any operator=null
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
arg0: GET_VAR a type=kotlin.Any? operator=null
arg1: CONST Null type=kotlin.Nothing? value='null'
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
else: GET_VAR a type=kotlin.Any? operator=null
FUN public fun test2(/*0*/ a: kotlin.Any?): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=test2
BLOCK type=kotlin.Int operator=EXCLEXCL
VAR val tmp1_notnull: kotlin.Int?
WHEN type=kotlin.Int? operator=SAFE_CALL
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
arg0: GET_VAR a type=kotlin.Any? operator=null
arg1: CONST Null type=kotlin.Nothing? value='null'
then: CONST Null type=kotlin.Nothing? value='null'
else: CALL .hashCode type=kotlin.Int operator=null
$this: GET_VAR a type=kotlin.Any? operator=null
WHEN type=kotlin.Int operator=null
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
arg0: GET_VAR tmp1_notnull type=kotlin.Int? operator=null
arg1: CONST Null type=kotlin.Nothing? value='null'
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
else: GET_VAR tmp1_notnull type=kotlin.Int? operator=null
@@ -112,6 +112,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("bangbang.kt")
public void testBangbang() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/bangbang.kt");
doTest(fileName);
}
@TestMetadata("booleanOperators.kt")
public void testBooleanOperators() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/booleanOperators.kt");