IrTypes in psi2ir (work in progress)
This commit is contained in:
+1
@@ -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()
|
||||
|
||||
+7
-5
@@ -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)
|
||||
|
||||
+54
-17
@@ -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
|
||||
}
|
||||
|
||||
+22
-11
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-9
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+59
-23
@@ -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
|
||||
|
||||
+17
-10
@@ -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
|
||||
Reference in New Issue
Block a user