IrTypes in psi2ir (work in progress)

This commit is contained in:
Dmitry Petrov
2018-05-14 12:40:56 +03:00
parent 0774ca415c
commit 5f4f6ef863
12 changed files with 250 additions and 99 deletions
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
import org.jetbrains.kotlin.types.KotlinType
class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateAssignment(ktExpression: KtBinaryExpression): IrExpression {
val ktLeft = ktExpression.left!!
val irRhs = ktExpression.right!!.genExpr()
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.buildStatement
import org.jetbrains.kotlin.ir.builders.irIfThenMaybeElse
import org.jetbrains.kotlin.ir.builders.whenComma
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
@@ -27,13 +29,13 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.intermediate.defaultLoad
import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.intermediate.defaultLoad
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList
class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateIfExpression(expression: KtIfExpression): IrExpression {
val resultType = getInferredTypeWithImplicitCastsOrFail(expression).toIrType()
@@ -68,10 +70,10 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
resultType: IrType
): IrWhen {
if (irBranches.size == 1) {
return IrIfThenElseImpl(
ktIf.startOffset, ktIf.endOffset, resultType,
irBranches[0].condition, irBranches[0].result, irElseResult
)
val irBranch0 = irBranches[0]
return buildStatement(ktIf.startOffset, ktIf.endOffset) {
irIfThenMaybeElse(resultType, irBranch0.condition, irBranch0.result, irElseResult)
}
}
val irWhen = IrWhenImpl(ktIf.startOffset, ktIf.endOffset, resultType, IrStatementOrigin.WHEN)
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.putDefault
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.psi.KtClassOrObject
@@ -143,24 +145,29 @@ class DataClassMembersGenerator(
+irReturn(
irCall(
constructorSymbol,
dataClassConstructor.returnType.toIrType(),
dataClassConstructor.typeParameters.associate { it to it.defaultType }
dataClassConstructor.returnType.toIrType()
).apply {
mapTypeParameters { it.defaultType.toIrType() }
mapValueParameters {
irGet(irFunction.valueParameters[it.index].symbol)
val irValueParameter = irFunction.valueParameters[it.index]
irGet(irValueParameter.type, irValueParameter.symbol)
}
}
)
}
}
override fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function, declaration) {
val irType = classDescriptor.defaultType.toIrType()
+irIfThenReturnTrue(irEqeqeq(irThis(), irOther()))
+irIfThenReturnFalse(irNotIs(irOther(), classDescriptor.defaultType, irClass.symbol))
val otherWithCast = irTemporary(irImplicitCast(irOther(), classDescriptor.defaultType, irClass.symbol), "other_with_cast")
+irIfThenReturnFalse(irNotIs(irOther(), irType))
val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast")
for (property in properties) {
val arg1 = irGet(irThis(), getPropertyGetterSymbol(property))
val arg2 = irGet(irGet(otherWithCast.symbol), getPropertyGetterSymbol(property))
val irPropertyType = property.type.toIrType()
val arg1 = irGet(irPropertyType, irThis(), getPropertyGetterSymbol(property))
val arg2 = irGet(irPropertyType, irGet(irPropertyType, otherWithCast.symbol), getPropertyGetterSymbol(property))
+irIfThenReturnFalse(irNotEquals(arg1, arg2))
}
+irReturnTrue()
@@ -199,34 +206,58 @@ class DataClassMembersGenerator(
override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function, declaration) {
val irIntType = context.irBuiltIns.intType
val result = irTemporaryVar(irInt(0), "result").symbol
var first = true
for (property in properties) {
val hashCodeOfProperty = getHashCodeOfProperty(irThis(), property)
val irNewValue =
if (first) hashCodeOfProperty
else irCallOp(intPlus, irCallOp(intTimes, irGet(result), irInt(31)), hashCodeOfProperty)
else
irCallOp(
intPlus,
irIntType,
irCallOp(
intTimes, irIntType, irGet(irIntType, result), irInt(31)
),
hashCodeOfProperty
)
+irSetVar(result, irNewValue)
first = false
}
+irReturn(irGet(result))
+irReturn(irGet(irIntType, result))
}
}
private fun MemberFunctionBuilder.getHashCodeOfProperty(receiver: IrExpression, property: PropertyDescriptor): IrExpression {
val getterSymbol = getPropertyGetterSymbol(property)
val propertyType = property.type
val irPropertyType = propertyType.toIrType()
return when {
property.type.containsNull() ->
irLetS(irGet(receiver, getterSymbol)) { variable ->
irIfNull(context.builtIns.intType, irGet(variable), irInt(0), getHashCodeOf(irGet(variable)))
propertyType.containsNull() ->
irLetS(
irGet(irPropertyType, receiver, getterSymbol)
) { variable ->
irIfNull(
context.irBuiltIns.intType,
irGet(irPropertyType, variable),
irInt(0),
getHashCodeOf(
propertyType,
irGet(irPropertyType, variable)
)
)
}
else ->
getHashCodeOf(irGet(receiver, getterSymbol))
getHashCodeOf(
propertyType,
irGet(irPropertyType, receiver, getterSymbol)
)
}
}
private fun MemberFunctionBuilder.getHashCodeOf(irValue: IrExpression): IrExpression {
val hashCodeFunctionDescriptor = getHashCodeFunction(irValue.type)
private fun MemberFunctionBuilder.getHashCodeOf(kotlinType: KotlinType, irValue: IrExpression): IrExpression {
val hashCodeFunctionDescriptor = getHashCodeFunction(kotlinType)
val hashCodeFunctionSymbol = declarationGenerator.context.symbolTable.referenceFunction(hashCodeFunctionDescriptor.original)
return irCall(hashCodeFunctionSymbol, hashCodeFunctionDescriptor).apply {
if (descriptor.dispatchReceiverParameter != null) {
@@ -243,19 +274,25 @@ class DataClassMembersGenerator(
irConcat.addArgument(irString(classDescriptor.name.asString() + "("))
var first = true
for (property in properties) {
val irPropertyType = property.type.toIrType()
if (!first) irConcat.addArgument(irString(", "))
irConcat.addArgument(irString(property.name.asString() + "="))
val irPropertyValue = irGet(irThis(), getPropertyGetterSymbol(property))
val irPropertyValue = irGet(irPropertyType, irThis(), getPropertyGetterSymbol(property))
val typeConstructorDescriptor = property.type.constructor.declarationDescriptor
val irPropertyStringValue =
if (typeConstructorDescriptor is ClassDescriptor &&
KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor)
)
irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol).apply {
irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply {
putValueArgument(0, irPropertyValue)
}
else
irPropertyValue
irConcat.addArgument(irPropertyStringValue)
first = false
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.*
@@ -55,8 +56,10 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
val kPropertyType = getKPropertyTypeForDelegatedProperty(propertyDescriptor)
val irProperty = IrPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, true,
propertyDescriptor
ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
isDelegated = true,
descriptor = propertyDescriptor,
type = propertyDescriptor.type.toIrType()
).apply {
backingField = generateDelegateFieldForProperty(propertyDescriptor, kPropertyType, ktDelegate)
}
@@ -171,10 +174,12 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
private fun createThisValueForDelegate(thisClass: ClassDescriptor?, ktDelegate: KtPropertyDelegate): IntermediateValue? =
thisClass?.let {
generateExpressionValue(it.thisAsReceiverParameter.type) {
generateExpressionValue(it.thisAsReceiverParameter.type.toIrType()) {
val thisAsReceiverParameter = thisClass.thisAsReceiverParameter
IrGetValueImpl(
ktDelegate.startOffset, ktDelegate.endOffset,
context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter)
thisAsReceiverParameter.type.toIrType(),
context.symbolTable.referenceValueParameter(thisAsReceiverParameter)
)
}
}
@@ -225,7 +230,8 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
val irLocalDelegatedProperty = IrLocalDelegatedPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
variableDescriptor
variableDescriptor,
variableDescriptor.type.toIrType()
).apply {
delegate = generateDelegateVariableForLocalDelegatedProperty(ktDelegate, variableDescriptor, kPropertyType, scopeOwnerSymbol)
}
@@ -363,7 +369,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
irPropertyReference: IrCallableReference
): IrBody =
with(createBodyGenerator(irGetter.symbol)) {
irBlockBody(ktDelegate) {
val startOffset = ktDelegate.startOffset
val endOffset = ktDelegate.endOffset
irBlockBody(startOffset, endOffset) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
@@ -371,8 +379,8 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
+irReturn(
CallGenerator(statementGenerator).generateCall(
ktDelegate.startOffset,
ktDelegate.endOffset,
startOffset,
endOffset,
conventionMethodCall
)
)
@@ -386,14 +394,17 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
delegateReceiverValue: IntermediateValue,
irPropertyReference: IrCallableReference
): IrBody = with(createBodyGenerator(irSetter.symbol)) {
irBlockBody(ktDelegate) {
val startOffset = ktDelegate.startOffset
val endOffset = ktDelegate.endOffset
irBlockBody(startOffset, endOffset) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue)
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetter.valueParameters[0].symbol)
+irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall))
val irSetterParameter = irSetter.valueParameters[0]
conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetterParameter.type, irSetterParameter.symbol)
+irReturn(CallGenerator(statementGenerator).generateCall(startOffset, endOffset, conventionMethodCall))
}
}
}
@@ -142,17 +142,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
): IrBlockBody {
val property = getter.correspondingProperty
val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset)
val startOffset = ktProperty.startOffset
val endOffset = ktProperty.endOffset
val irBody = IrBlockBodyImpl(startOffset, endOffset)
val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property)
irBody.statements.add(
IrReturnImpl(
ktProperty.startOffset, ktProperty.endOffset, context.builtIns.nothingType,
startOffset, endOffset, context.irBuiltIns.nothingType,
irAccessor.symbol,
IrGetFieldImpl(
ktProperty.startOffset, ktProperty.endOffset,
startOffset, endOffset,
context.symbolTable.referenceField(property),
property.type.toIrType(),
receiver
)
)
@@ -167,17 +170,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
): IrBlockBody {
val property = setter.correspondingProperty
val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset)
val startOffset = ktProperty.startOffset
val endOffset = ktProperty.endOffset
val irBody = IrBlockBodyImpl(startOffset, endOffset)
val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property)
val setterParameter = irAccessor.valueParameters.single().symbol
val irValueParameter = irAccessor.valueParameters.single()
irBody.statements.add(
IrSetFieldImpl(
ktProperty.startOffset, ktProperty.endOffset,
startOffset, endOffset,
context.symbolTable.referenceField(property),
receiver,
IrGetValueImpl(ktProperty.startOffset, ktProperty.endOffset, setterParameter)
IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol),
context.irBuiltIns.unitType
)
)
return irBody
@@ -186,11 +192,14 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun generateReceiverExpressionForDefaultPropertyAccessor(ktProperty: KtElement, property: PropertyDescriptor): IrExpression? {
val containingDeclaration = property.containingDeclaration
return when (containingDeclaration) {
is ClassDescriptor ->
is ClassDescriptor -> {
val thisAsReceiverParameter = containingDeclaration.thisAsReceiverParameter
IrGetValueImpl(
ktProperty.startOffset, ktProperty.endOffset,
context.symbolTable.referenceValue(containingDeclaration.thisAsReceiverParameter)
thisAsReceiverParameter.type.toIrType(),
context.symbolTable.referenceValue(thisAsReceiverParameter)
)
}
else -> null
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@@ -46,6 +47,14 @@ import java.lang.AssertionError
class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
private fun createErrorExpression(ktExpression: KtExpression, text: String) =
IrErrorExpressionImpl(
ktExpression.startOffset,
ktExpression.endOffset,
context.irBuiltIns.nothingType,
text
)
fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression {
val ktOperator = expression.operationReference.getReferencedNameElementType()
val irOperator = getPrefixOperator(ktOperator)
@@ -57,7 +66,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
irOperator
)
in OPERATORS_DESUGARED_TO_CALLS -> generatePrefixOperatorAsCall(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
else -> createErrorExpression(expression, ktOperator.toString())
}
}
@@ -72,7 +81,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
irOperator
)
IrStatementOrigin.EXCLEXCL -> generateExclExclOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
else -> createErrorExpression(expression, ktOperator.toString())
}
}
@@ -91,7 +100,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
}
return IrTypeOperatorCallImpl(
expression.startOffset, expression.endOffset, resultType, irOperator, rhsType,
expression.startOffset, expression.endOffset, resultType.toIrType(), irOperator, rhsType.toIrType(),
context.symbolTable.referenceClassifier(rhsType.constructor.declarationDescriptor!!),
expression.left.genExpr()
)
@@ -103,8 +112,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val againstType = getOrFail(BindingContext.TYPE, expression.typeReference)
return IrTypeOperatorCallImpl(
expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator,
againstType, context.symbolTable.referenceClassifier(againstType.constructor.declarationDescriptor!!),
expression.startOffset, expression.endOffset, context.irBuiltIns.booleanType, irOperator,
againstType.toIrType(),
context.symbolTable.referenceClassifier(againstType.constructor.declarationDescriptor!!),
expression.leftHandSide.genExpr()
)
}
@@ -128,19 +138,24 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
in IDENTITY_OPERATORS -> generateIdentityOperator(expression, irOperator)
in IN_OPERATORS -> generateInOperator(expression, irOperator)
in BINARY_BOOLEAN_OPERATORS -> generateBinaryBooleanOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
else -> createErrorExpression(expression, ktOperator.toString())
}
}
private fun generateElvis(expression: KtBinaryExpression): IrExpression {
val specialCallForElvis = getResolvedCall(expression)!!
val resultType = specialCallForElvis.resultingDescriptor.returnType!!
val resultType = specialCallForElvis.resultingDescriptor.returnType!!.toIrType()
val irArgument0 = expression.left!!.genExpr()
val irArgument1 = expression.right!!.genExpr()
return irBlock(expression, IrStatementOrigin.ELVIS, resultType) {
return irBlock(expression.startOffset, expression.endOffset, IrStatementOrigin.ELVIS, resultType) {
val temporary = irTemporary(irArgument0, "elvis_lhs")
+irIfNull(resultType, irGet(temporary.symbol), irArgument1, irGet(temporary.symbol))
+irIfNull(
resultType,
irGet(temporary.type, temporary.symbol),
irArgument1,
irGet(temporary.type, temporary.symbol)
)
}
}
@@ -167,7 +182,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
irContainsCall
IrStatementOrigin.NOT_IN ->
IrUnaryPrimitiveImpl(
expression.startOffset, expression.endOffset, IrStatementOrigin.NOT_IN,
expression.startOffset, expression.endOffset,
context.irBuiltIns.booleanType,
IrStatementOrigin.NOT_IN,
context.irBuiltIns.booleanNotSymbol,
irContainsCall
)
@@ -182,7 +199,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irArgument1 = expression.right!!.genExpr()
val irIdentityEquals = IrBinaryPrimitiveImpl(
expression.startOffset, expression.endOffset, irOperator,
expression.startOffset, expression.endOffset,
context.irBuiltIns.booleanType,
irOperator,
context.irBuiltIns.eqeqeqSymbol,
irArgument0, irArgument1
)
@@ -192,7 +211,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
irIdentityEquals
IrStatementOrigin.EXCLEQEQ ->
IrUnaryPrimitiveImpl(
expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQEQ,
expression.startOffset, expression.endOffset,
context.irBuiltIns.booleanType,
IrStatementOrigin.EXCLEQEQ,
context.irBuiltIns.booleanNotSymbol,
irIdentityEquals
)
@@ -218,6 +239,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irEquals = IrBinaryPrimitiveImpl(
expression.startOffset, expression.endOffset,
context.irBuiltIns.booleanType,
irOperator,
eqeqSymbol,
expression.left!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo?.leftType, comparisonType),
@@ -230,6 +252,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
IrStatementOrigin.EXCLEQ ->
IrUnaryPrimitiveImpl(
expression.startOffset, expression.endOffset,
context.irBuiltIns.booleanType,
IrStatementOrigin.EXCLEQ,
context.irBuiltIns.booleanNotSymbol,
irEquals
@@ -253,14 +276,18 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol
?: context.irBuiltIns.eqeqSymbol
IrBinaryPrimitiveImpl(
startOffset, endOffset, irOperator,
startOffset, endOffset,
context.irBuiltIns.booleanType,
irOperator,
eqeqSymbol,
arg1.promoteToPrimitiveNumericType(comparisonInfo.leftType, comparisonType),
arg2.promoteToPrimitiveNumericType(comparisonInfo.rightType, comparisonType)
)
} else {
IrBinaryPrimitiveImpl(
startOffset, endOffset, irOperator,
startOffset, endOffset,
context.irBuiltIns.booleanType,
irOperator,
context.irBuiltIns.eqeqSymbol,
arg1, arg2
)
@@ -281,7 +308,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
operandType == targetType || operandNNType == targetType ->
this
type.containsNull() ->
// TODO operandType may have inaccurate nullability
operandType.containsNull() ->
safeCallOnDispatchReceiver(this@OperatorExpressionGenerator, startOffset, endOffset) { dispatchReceiver ->
invokeConversionFunction(
startOffset, endOffset,
@@ -308,10 +336,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
IrCallImpl(
startOffset,
endOffset,
functionDescriptor.returnType!!,
functionDescriptor.returnType!!.toIrType(),
context.symbolTable.referenceFunction(functionDescriptor.original),
functionDescriptor,
typeArguments = null,
origin = null, // TODO origin for widening conversions?
superQualifierSymbol = null
).apply {
@@ -331,17 +358,21 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
return if (comparisonInfo != null) {
IrBinaryPrimitiveImpl(
startOffset, endOffset, origin,
startOffset, endOffset,
context.irBuiltIns.booleanType,
origin,
getComparisonOperatorSymbol(origin, comparisonInfo.comparisonType),
expression.left!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.leftType, comparisonInfo.comparisonType),
expression.right!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.rightType, comparisonInfo.comparisonType)
)
} else {
IrBinaryPrimitiveImpl(
startOffset, endOffset, origin,
startOffset, endOffset,
context.irBuiltIns.booleanType,
origin,
getComparisonOperatorSymbol(origin, context.irBuiltIns.int),
generateCall(getResolvedCall(expression)!!, expression, origin),
IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, 0)
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, 0)
)
}
}
@@ -367,11 +398,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irArgument = ktArgument.genExpr()
val ktOperator = expression.operationReference
val resultType = irArgument.type.makeNotNullable()
val resultType = irArgument.type.makeNotNull()
return irBlock(ktOperator, origin, resultType) {
return irBlock(ktOperator.startOffset, ktOperator.endOffset, origin, resultType) {
val temporary = irTemporary(irArgument, "notnull")
+irIfNull(resultType, irGet(temporary.symbol), irThrowNpe(origin), irGet(temporary.symbol))
+irIfNull(
resultType,
irGet(temporary.type, temporary.symbol),
irThrowNpe(origin),
irGet(temporary.type, temporary.symbol)
)
}
}
@@ -85,14 +85,33 @@ fun IrBuilderWithScope.irReturn(value: IrExpression) =
value
)
fun IrBuilderWithScope.irReturnTrue() =
irReturn(IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, true))
fun IrBuilderWithScope.irBoolean(value: Boolean) =
IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, value)
fun IrBuilderWithScope.irReturnFalse() =
irReturn(IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, false))
fun IrBuilderWithScope.irTrue() = irBoolean(true)
fun IrBuilderWithScope.irFalse() = irBoolean(false)
fun IrBuilderWithScope.irReturnTrue() = irReturn(irTrue())
fun IrBuilderWithScope.irReturnFalse() = irReturn(irFalse())
fun IrBuilderWithScope.irElseBranch(expression: IrExpression) =
IrElseBranchImpl(startOffset, endOffset, irTrue(), expression)
fun IrBuilderWithScope.irIfThen(type: IrType, condition: IrExpression, thenPart: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, type).apply {
branches.add(IrBranchImpl(startOffset, endOffset, condition, thenPart))
}
fun IrBuilderWithScope.irIfThenElse(type: IrType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, type, condition, thenPart, elsePart)
IrIfThenElseImpl(startOffset, endOffset, type).apply {
branches.add(IrBranchImpl(startOffset, endOffset, condition, thenPart))
branches.add(irElseBranch(elsePart))
}
fun IrBuilderWithScope.irIfThenMaybeElse(type: IrType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression?) =
if (elsePart != null)
irIfThenElse(type, condition, thenPart, elsePart)
else
irIfThen(type, condition, thenPart)
fun IrBuilderWithScope.irIfNull(type: IrType, subject: IrExpression, thenPart: IrExpression, elsePart: IrExpression) =
irIfThenElse(type, irEqualsNull(subject), thenPart, elsePart)
@@ -101,10 +120,10 @@ fun IrBuilderWithScope.irThrowNpe(origin: IrStatementOrigin) =
IrNullaryPrimitiveImpl(startOffset, endOffset, context.irBuiltIns.nothingType, origin, context.irBuiltIns.throwNpeSymbol)
fun IrBuilderWithScope.irIfThenReturnTrue(condition: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType, condition, irReturnTrue())
irIfThen(context.irBuiltIns.unitType, condition, irReturnTrue())
fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType, condition, irReturnFalse())
irIfThen(context.irBuiltIns.unitType, condition, irReturnFalse())
fun IrBuilderWithScope.irGet(type: IrType, variable: IrValueSymbol) =
IrGetValueImpl(startOffset, endOffset, type, variable)
@@ -86,6 +86,7 @@ class IrBlockBuilder(
val origin: IrStatementOrigin? = null,
var resultType: IrType? = null
) : IrStatementsBuilder<IrBlock>(context, scope, startOffset, endOffset) {
private val statements = ArrayList<IrStatement>()
inline fun block(body: IrBlockBuilder.() -> Unit): IrBlock {
@@ -107,6 +108,33 @@ class IrBlockBuilder(
}
}
class IrSingleStatementBuilder(
context: IrGeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int,
val origin: IrStatementOrigin? = null
) : IrBuilderWithScope(context, scope, startOffset, endOffset) {
inline fun <T : IrElement> build(statementBuilder: IrSingleStatementBuilder.() -> T): T =
statementBuilder()
}
inline fun <T : IrElement> IrGeneratorWithScope.buildStatement(
startOffset: Int,
endOffset: Int,
origin: IrStatementOrigin?,
builder: IrSingleStatementBuilder.() -> T
) =
IrSingleStatementBuilder(context, scope, startOffset, endOffset, origin).builder()
inline fun <T : IrElement> IrGeneratorWithScope.buildStatement(
startOffset: Int,
endOffset: Int,
builder: IrSingleStatementBuilder.() -> T
) =
IrSingleStatementBuilder(context, scope, startOffset, endOffset).builder()
fun <T : IrBuilder> T.at(startOffset: Int, endOffset: Int) = apply {
this.startOffset = startOffset
this.endOffset = endOffset
@@ -86,17 +86,24 @@ fun IrMemberAccessExpression.removeValueArgument(valueParameterDescriptor: Value
removeValueArgument(valueParameterDescriptor.index)
}
inline fun <T : IrMemberAccessExpression> T.mapValueParameters(transform: (ValueParameterDescriptor) -> IrExpression?): T {
descriptor.valueParameters.forEach {
putValueArgument(it.index, transform(it))
inline fun <T : IrMemberAccessExpression> T.mapTypeParameters(transform: (TypeParameterDescriptor) -> IrType) : T =
apply {
descriptor.typeParameters.forEach {
putTypeArgument(it.index, transform(it))
}
}
return this
}
inline fun <T : IrMemberAccessExpression> T.mapValueParametersIndexed(transform: (Int, ValueParameterDescriptor) -> IrExpression?): T {
descriptor.valueParameters.forEach {
putValueArgument(it.index, transform(it.index, it))
inline fun <T : IrMemberAccessExpression> T.mapValueParameters(transform: (ValueParameterDescriptor) -> IrExpression?): T =
apply {
descriptor.valueParameters.forEach {
putValueArgument(it.index, transform(it))
}
}
inline fun <T : IrMemberAccessExpression> T.mapValueParametersIndexed(transform: (Int, ValueParameterDescriptor) -> IrExpression?): T =
apply {
descriptor.valueParameters.forEach {
putValueArgument(it.index, transform(it.index, it))
}
}
return this
}
@@ -31,19 +31,4 @@ class IrIfThenElseImpl(
IrWhenBase(startOffset, endOffset, type) {
override val branches: MutableList<IrBranch> = SmartList()
constructor(
startOffset: Int,
endOffset: Int,
type: IrType,
condition: IrExpression,
thenBranch: IrExpression,
elseBranch: IrExpression? = null,
origin: IrStatementOrigin? = null
) : this(startOffset, endOffset, type, origin) {
branches.add(IrBranchImpl(startOffset, endOffset, condition, thenBranch))
if (elseBranch != null) {
branches.add(IrBranchImpl.elseBranch(elseBranch))
}
}
}
@@ -51,7 +51,8 @@ class IrWhenImpl(
endOffset: Int,
type: IrType,
override val origin: IrStatementOrigin? = null
) : IrWhenBase(startOffset, endOffset, type) {
) :
IrWhenBase(startOffset, endOffset, type) {
constructor(
startOffset: Int,
@@ -71,7 +72,9 @@ open class IrBranchImpl(
endOffset: Int,
override var condition: IrExpression,
override var result: IrExpression
) : IrElementBase(startOffset, endOffset), IrBranch {
) :
IrElementBase(startOffset, endOffset),
IrBranch {
constructor(condition: IrExpression, result: IrExpression) :
this(condition.startOffset, condition.endOffset, condition, result)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -25,3 +26,15 @@ val IrType.classifierOrFail: IrClassifierSymbol
val IrType.classifierOrNull: IrClassifierSymbol?
get() = safeAs<IrSimpleType>()?.classifier
fun IrType.makeNotNull() =
if (this is IrSimpleType && this.hasQuestionMark)
IrSimpleTypeImpl(
classifier,
false,
arguments,
annotations,
Variance.INVARIANT
)
else
this