IrTypes in psi2ir: generators (seem to be) complete

This commit is contained in:
Dmitry Petrov
2018-05-14 15:07:38 +03:00
parent 5f4f6ef863
commit 54e9a2bb7b
21 changed files with 190 additions and 100 deletions
@@ -92,7 +92,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
irBlock(ktExpression.startOffset, ktExpression.endOffset, origin, irLValue.type) {
val temporary = irTemporary(irLValue.load())
val opCall = statementGenerator.pregenerateCall(opResolvedCall)
opCall.setExplicitReceiverValue(VariableLValue(startOffset, endOffset, temporary.symbol))
opCall.setExplicitReceiverValue(
VariableLValue(context, startOffset, endOffset, temporary.symbol, temporary.type)
)
val irOpCall = CallGenerator(statementGenerator).generateCall(ktExpression, opCall, origin)
+irLValue.store(irOpCall)
+irGet(temporary.type, temporary.symbol)
@@ -118,31 +120,37 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
@Suppress("DEPRECATION")
if (descriptor.isDelegated)
DelegatedLocalPropertyLValue(
context,
ktLeft.startOffset, ktLeft.endOffset,
descriptor.type,
descriptor.type.toIrType(),
descriptor.getter?.let { context.symbolTable.referenceDeclaredFunction(it) },
descriptor.setter?.let { context.symbolTable.referenceDeclaredFunction(it) },
origin
)
else
VariableLValue(
ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceVariable(descriptor),
origin
)
createVariableValue(ktLeft, descriptor, origin)
is PropertyDescriptor ->
generateAssignmentReceiverForProperty(descriptor, origin, ktLeft, resolvedCall)
is ValueDescriptor ->
VariableLValue(
ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceValue(descriptor),
origin
)
createVariableValue(ktLeft, descriptor, origin)
else ->
OnceExpressionValue(ktLeft.genExpr())
}
}
private fun createVariableValue(
ktExpression: KtExpression,
descriptor: ValueDescriptor,
origin: IrStatementOrigin
) =
VariableLValue(
context,
ktExpression.startOffset, ktExpression.endOffset,
context.symbolTable.referenceValue(descriptor),
descriptor.type.toIrType(),
origin
)
private fun createBackingFieldLValue(
ktExpression: KtExpression,
descriptor: PropertyDescriptor,
@@ -150,8 +158,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
origin: IrStatementOrigin?
): BackingFieldLValue =
BackingFieldLValue(
context,
ktExpression.startOffset, ktExpression.endOffset,
descriptor.type,
descriptor.type.toIrType(),
context.symbolTable.referenceField(descriptor),
receiverValue, origin
)
@@ -189,7 +198,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
ktExpression: KtExpression,
descriptor: PropertyDescriptor,
propertyReceiver: CallReceiver,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
typeArgumentsMap: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin?,
superQualifier: ClassDescriptor?
): PropertyLValueBase {
@@ -201,24 +210,32 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
val setterDescriptor = descriptor.setter
val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
val propertyIrType = descriptor.type.toIrType()
return if (getterSymbol != null || setterSymbol != null) {
val typeArgumentsList =
typeArgumentsMap?.let { typeArguments ->
descriptor.typeParameters.map { typeArguments[it]!!.toIrType() }
}
AccessorPropertyLValue(
context,
scope,
ktExpression.startOffset, ktExpression.endOffset, origin,
descriptor.type,
propertyIrType,
getterSymbol,
getterDescriptor,
setterSymbol,
setterDescriptor,
typeArguments,
typeArgumentsList,
propertyReceiver,
superQualifierSymbol
)
} else
FieldPropertyLValue(
context,
scope,
ktExpression.startOffset, ktExpression.endOffset, origin,
context.symbolTable.referenceField(descriptor),
propertyIrType,
propertyReceiver,
superQualifierSymbol
)
@@ -72,8 +72,10 @@ class BodyGenerator(
val ktDestructuringDeclaration = ktParameter.destructuringDeclaration ?: continue
val valueParameter = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter)
val parameterValue = VariableLValue(
context,
ktDestructuringDeclaration.startOffset, ktDestructuringDeclaration.endOffset,
context.symbolTable.referenceValue(valueParameter),
valueParameter.type.toIrType(),
IrStatementOrigin.DESTRUCTURING_DECLARATION
)
statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue)
@@ -164,8 +164,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
): IntermediateValue {
val thisValue = createThisValueForDelegate(thisClass, ktDelegate)
return BackingFieldLValue(
context,
ktDelegate.startOffset, ktDelegate.endOffset,
irDelegateField.descriptor.type,
irDelegateField.descriptor.type.toIrType(),
irDelegateField,
thisValue,
null
@@ -327,7 +328,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
}
private fun createVariableValueForDelegate(irDelegate: IrVariableSymbol, ktDelegate: KtPropertyDelegate) =
VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, irDelegate)
VariableLValue(context, ktDelegate.startOffset, ktDelegate.endOffset, irDelegate, irDelegate.descriptor.type.toIrType())
private inline fun createLocalPropertyAccessor(
getterDescriptor: VariableAccessorDescriptor,
@@ -162,7 +162,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
val iteratorCall = statementGenerator.pregenerateCall(iteratorResolvedCall)
val irIteratorCall = callGenerator.generateCall(ktLoopRange, iteratorCall, IrStatementOrigin.FOR_LOOP_ITERATOR)
val irIterator = scope.createTemporaryVariable(irIteratorCall, "iterator", origin = IrDeclarationOrigin.FOR_LOOP_ITERATOR)
val iteratorValue = VariableLValue(irIterator)
val iteratorValue = VariableLValue(context, irIterator)
irForBlock.statements.add(irIterator)
val irInnerWhile = IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, IrStatementOrigin.FOR_LOOP_INNER_WHILE)
@@ -196,7 +196,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
statementGenerator.declareComponentVariablesInBlock(
ktLoopDestructuringDeclaration,
irInnerBody,
VariableLValue(irLoopParameter)
VariableLValue(context, irLoopParameter)
)
}
@@ -44,16 +44,19 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter, irValueParameter: IrValueParameter): IrDeclaration {
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
val irPropertyType = propertyDescriptor.type.toIrType()
return IrPropertyImpl(
ktParameter.startOffset, ktParameter.endOffset,
IrDeclarationOrigin.DEFINED, false,
propertyDescriptor
propertyDescriptor,
irPropertyType
).also { irProperty ->
irProperty.backingField =
generatePropertyBackingField(ktParameter, propertyDescriptor) {
IrExpressionBodyImpl(
IrGetValueImpl(
ktParameter.startOffset, ktParameter.endOffset,
irPropertyType,
irValueParameter.symbol,
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
)
@@ -99,8 +102,10 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty =
IrPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOrigin.DEFINED, false,
propertyDescriptor
IrDeclarationOrigin.DEFINED,
false,
propertyDescriptor,
propertyDescriptor.type.toIrType()
).buildWithScope { irProperty ->
irProperty.backingField =
if (propertyDescriptor.hasBackingField())
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateClassLiteral(ktClassLiteral: KtClassLiteralExpression): IrExpression {
val ktArgument = ktClassLiteral.receiverExpression!!
val lhs = getOrFail(BindingContext.DOUBLE_COLON_LHS, ktArgument)
@@ -409,4 +409,5 @@ abstract class StatementGeneratorExtension(val statementGenerator: StatementGene
fun KtExpression.genExpr() = statementGenerator.generateExpression(this)
fun KtExpression.genStmt() = statementGenerator.generateStatement(this)
fun KotlinType.toIrType() = with(statementGenerator) { toIrType() }
fun translateType(kotlinType: KotlinType) = kotlinType.toIrType()
}
@@ -26,23 +26,25 @@ import org.jetbrains.kotlin.types.KotlinType
import java.lang.AssertionError
class ArrayAccessAssignmentReceiver(
val irArray: IrExpression,
val irIndices: List<IrExpression>,
val indexedGetCall: CallBuilder?,
val indexedSetCall: CallBuilder?,
val callGenerator: CallGenerator,
val startOffset: Int,
val endOffset: Int,
val origin: IrStatementOrigin
private val irArray: IrExpression,
private val irIndices: List<IrExpression>,
private val indexedGetCall: CallBuilder?,
private val indexedSetCall: CallBuilder?,
private val callGenerator: CallGenerator,
private val startOffset: Int,
private val endOffset: Int,
private val origin: IrStatementOrigin
) : AssignmentReceiver {
private val type: KotlinType =
private val kotlinType: KotlinType =
indexedGetCall?.run { descriptor.returnType!! } ?: indexedSetCall?.run { descriptor.valueParameters.last().type }
?: throw AssertionError("Array access should have either indexed-get call or indexed-set call")
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression {
val hasResult = origin.isAssignmentOperatorWithResult()
val resultType = if (hasResult) type else callGenerator.context.builtIns.unitType
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, origin)
val resultType = if (hasResult) kotlinType else callGenerator.context.builtIns.unitType
val irResultType = callGenerator.translateType(resultType)
val irBlock = IrBlockImpl(startOffset, endOffset, irResultType, origin)
val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(irArray, irBlock, "array")
@@ -52,7 +54,12 @@ class ArrayAccessAssignmentReceiver(
indexedGetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
indexedSetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
val irLValue = LValueWithGetterAndSetterCalls(callGenerator, indexedGetCall, indexedSetCall, type, startOffset, endOffset, origin)
val irLValue = LValueWithGetterAndSetterCalls(
callGenerator,
indexedGetCall, indexedSetCall,
callGenerator.translateType(kotlinType),
startOffset, endOffset, origin
)
irBlock.inlineStatement(withLValue(irLValue))
return irBlock
@@ -16,26 +16,30 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
class BackingFieldLValue(
val startOffset: Int,
val endOffset: Int,
override val type: KotlinType,
val symbol: IrFieldSymbol,
val receiver: IntermediateValue?,
val origin: IrStatementOrigin?
private val context: IrGeneratorContext,
private val startOffset: Int,
private val endOffset: Int,
override val type: IrType,
private val symbol: IrFieldSymbol,
private val receiver: IntermediateValue?,
private val origin: IrStatementOrigin?
) : LValue, AssignmentReceiver {
override fun store(irExpression: IrExpression): IrExpression =
IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, origin)
IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, context.irBuiltIns.unitType, origin)
override fun load(): IrExpression =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), origin)
IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver?.load(), origin)
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this)
@@ -16,25 +16,31 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
class DelegatedLocalPropertyLValue(
private val context: IrGeneratorContext,
val startOffset: Int,
val endOffset: Int,
override val type: KotlinType,
val getterSymbol: IrSimpleFunctionSymbol?,
val setterSymbol: IrSimpleFunctionSymbol?,
override val type: IrType,
private val getterSymbol: IrSimpleFunctionSymbol?,
private val setterSymbol: IrSimpleFunctionSymbol?,
val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver {
) :
LValue,
AssignmentReceiver {
override fun load(): IrExpression =
IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, null, origin)
IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, origin)
override fun store(irExpression: IrExpression): IrExpression =
IrCallImpl(startOffset, endOffset, type, setterSymbol!!, setterSymbol.descriptor, null, origin).apply {
IrCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, setterSymbol!!, setterSymbol.descriptor, origin).apply {
putValueArgument(0, irExpression)
}
@@ -19,10 +19,11 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression
class ExtensionInvokeCallReceiver(
val callBuilder: CallBuilder,
val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue
private val callBuilder: CallBuilder,
private val functionReceiver: IntermediateValue,
private val extensionInvokeReceiver: IntermediateValue
) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument:
// receiver.extFun(p1, ..., pN)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
import org.jetbrains.kotlin.types.KotlinType
@@ -26,11 +27,12 @@ class LValueWithGetterAndSetterCalls(
val callGenerator: CallGenerator,
val getterCall: CallBuilder?,
val setterCall: CallBuilder?,
override val type: KotlinType,
override val type: IrType,
val startOffset: Int,
val endOffset: Int,
val origin: IrStatementOrigin? = null
) : LValue {
private val descriptor: CallableDescriptor =
getterCall?.descriptor ?: setterCall?.descriptor
?: throw AssertionError("Call-based LValue should have either a getter or a setter call")
@@ -17,22 +17,24 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.ir.types.IrType
abstract class PropertyLValueBase(
protected val context: IrGeneratorContext,
val scope: Scope,
val startOffset: Int,
val endOffset: Int,
val origin: IrStatementOrigin?,
override val type: KotlinType,
override val type: IrType,
val callReceiver: CallReceiver,
val superQualifier: IrClassSymbol?
) : LValue, AssignmentReceiver {
@@ -64,20 +66,25 @@ abstract class PropertyLValueBase(
}
class FieldPropertyLValue(
context: IrGeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int,
origin: IrStatementOrigin?,
val field: IrFieldSymbol,
type: IrType,
callReceiver: CallReceiver,
superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, field.descriptor.type, callReceiver, superQualifier) {
) :
PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
IrGetFieldImpl(
startOffset, endOffset,
field,
type,
dispatchReceiverValue?.load(),
origin,
superQualifier
@@ -92,6 +99,7 @@ class FieldPropertyLValue(
field,
dispatchReceiverValue?.load(),
irExpression,
context.irBuiltIns.unitType,
origin,
superQualifier
)
@@ -99,57 +107,76 @@ class FieldPropertyLValue(
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
FieldPropertyLValue(
context,
scope, startOffset, endOffset, origin,
field,
type,
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
superQualifier
)
}
class AccessorPropertyLValue(
context: IrGeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int,
origin: IrStatementOrigin?,
type: KotlinType,
type: IrType,
val getter: IrFunctionSymbol?,
val getterDescriptor: FunctionDescriptor?,
val setter: IrFunctionSymbol?,
val setterDescriptor: FunctionDescriptor?,
val typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
val typeArguments: List<IrType>?,
callReceiver: CallReceiver,
superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
) : PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
private val typeArgumentsCount = typeArguments?.size ?: 0
private fun IrMemberAccessExpression.putTypeArguments() {
typeArguments?.forEachIndexed { index, irType ->
putTypeArgument(index, irType)
}
}
override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrGetterCallImpl(
startOffset, endOffset,
type,
getter!!, getterDescriptor!!,
typeArguments,
typeArgumentsCount,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),
origin,
superQualifier
)
).apply {
putTypeArguments()
}
}
override fun store(irExpression: IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrSetterCallImpl(
startOffset, endOffset,
context.irBuiltIns.unitType,
setter!!, setterDescriptor!!,
typeArguments,
typeArgumentsCount,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),
irExpression,
origin,
superQualifier
)
).apply {
putTypeArguments()
}
}
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
AccessorPropertyLValue(
scope, startOffset, endOffset, origin,
context, scope,
startOffset, endOffset, origin,
type, getter, getterDescriptor, setter, setterDescriptor,
typeArguments,
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
class RematerializableValue(val irExpression: IrExpressionWithCopy) : IntermediateValue {
override val type: IrType get() = irExpression.type
override fun load(): IrExpression = irExpression.copy()
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.constNull
import org.jetbrains.kotlin.ir.builders.equalsNull
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrIfThenElseImpl
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.makeNullable
@@ -35,6 +35,7 @@ class SafeCallReceiver(
val dispatchReceiver: IntermediateValue?,
val isAssignmentReceiver: Boolean
) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
val safeReceiverValue = VariableLValue(irTmp)
@@ -50,19 +51,17 @@ class SafeCallReceiver(
}
val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
val resultType = if (isAssignmentReceiver) irResult.type.builtIns.unitType else irResult.type.makeNullable()
val resultType = if (isAssignmentReceiver) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL)
irBlock.statements.add(irTmp)
val irIfThenElse = IrIfThenElseImpl(
startOffset, endOffset, resultType,
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()),
generator.context.constNull(startOffset, endOffset),
irResult,
IrStatementOrigin.SAFE_CALL
)
val irIfThenElse =
generator.buildStatement(startOffset, endOffset, IrStatementOrigin.SAFE_CALL) {
irIfNull(resultType, safeReceiverValue.load(), irNull(), irResult)
}
irBlock.statements.add(irIfThenElse)
return irBlock
@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.constNull
import org.jetbrains.kotlin.ir.builders.equalsNull
import org.jetbrains.kotlin.ir.builders.irBlock
import org.jetbrains.kotlin.ir.builders.irIfNull
import org.jetbrains.kotlin.ir.builders.irNull
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrIfThenElseImpl
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.types.typeUtil.makeNullable
class SafeExtensionInvokeCallReceiver(
val generator: GeneratorWithScope,
@@ -33,6 +32,7 @@ class SafeExtensionInvokeCallReceiver(
val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue
) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument:
// receiver?.extFun(p1, ..., pN)
@@ -53,19 +53,14 @@ class SafeExtensionInvokeCallReceiver(
val resultType = irResult.type.makeNullable()
return IrBlockImpl(
startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL,
arrayListOf(
irTmp,
IrIfThenElseImpl(
startOffset, endOffset, resultType,
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()),
generator.context.constNull(startOffset, endOffset),
irResult,
IrStatementOrigin.SAFE_CALL
)
return generator.irBlock(startOffset, endOffset, IrStatementOrigin.SAFE_CALL, resultType) {
+irTmp
+irIfNull(
resultType,
safeReceiverValue.load(), irNull(),
irResult
)
)
}
}
}
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression
class SimpleCallReceiver(
val dispatchReceiverValue: IntermediateValue?,
val extensionReceiverValue: IntermediateValue?
private val dispatchReceiverValue: IntermediateValue?,
private val extensionReceiverValue: IntermediateValue?
) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
class TransientReceiverValue(override val type: IrType) : IntermediateValue {
override fun load(): IrExpression {
throw AssertionError("Transient receiver should not be instantiated")
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
@@ -23,27 +24,31 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
class VariableLValue(
private val context: IrGeneratorContext,
val startOffset: Int,
val endOffset: Int,
val symbol: IrValueSymbol,
override val type: IrType,
val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver {
constructor(irVariable: IrVariable, origin: IrStatementOrigin? = null) : this(
irVariable.startOffset, irVariable.endOffset, irVariable.symbol, origin
)
) :
LValue,
AssignmentReceiver {
override val type: KotlinType get() = symbol.descriptor.type
constructor(context: IrGeneratorContext, irVariable: IrVariable, origin: IrStatementOrigin? = null) :
this(context, irVariable.startOffset, irVariable.endOffset, irVariable.symbol, irVariable.type, origin)
override fun load(): IrExpression =
IrGetValueImpl(startOffset, endOffset, symbol, origin)
IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableImpl(
startOffset, endOffset,
context.irBuiltIns.unitType,
symbol.assertedCast<IrVariableSymbol> { "Not a variable: ${symbol.descriptor}" },
irExpression, origin
)
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.IrWhen
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
// TODO rewrite using IR Builders
fun primitiveOp1(
startOffset: Int, endOffset: Int,
primitiveOpSymbol: IrSimpleFunctionSymbol,
@@ -36,5 +36,17 @@ fun IrType.makeNotNull() =
annotations,
Variance.INVARIANT
)
else
this
fun IrType.makeNullable() =
if (this is IrSimpleType && !this.hasQuestionMark)
IrSimpleTypeImpl(
classifier,
true,
arguments,
annotations,
Variance.INVARIANT
)
else
this