Refactoring.
'if' expressions (represented as 'when' without subject).
This commit is contained in:
committed by
Dmitry Petrov
parent
1ddf889d8a
commit
5709826096
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -24,6 +25,8 @@ import org.jetbrains.kotlin.types.isNullabilityFlexible
|
||||
|
||||
fun IrExpression.toExpectedType(expectedType: KotlinType?): IrExpression {
|
||||
if (expectedType == null) return this
|
||||
if (KotlinBuiltIns.isUnit(expectedType)) return this // TODO expose coercion to Unit in IR?
|
||||
|
||||
val valueType = type ?: throw AssertionError("expectedType != null, valueType == null: $this")
|
||||
|
||||
if (valueType.isNullabilityFlexible() && !expectedType.isMarkedNullable) {
|
||||
|
||||
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModule
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.generators.IrGeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.IrModuleGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.foldStringConcatenation
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.inlineDesugaredBlocks
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -33,8 +33,8 @@ class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
|
||||
)
|
||||
|
||||
fun generateModule(moduleDescriptor: ModuleDescriptor, ktFiles: List<KtFile>, bindingContext: BindingContext): IrModule {
|
||||
val irGeneratorContext = IrGeneratorContext(moduleDescriptor, bindingContext)
|
||||
val irModule = IrModuleGenerator(irGeneratorContext).generateModule(ktFiles)
|
||||
val irGeneratorContext = GeneratorContext(moduleDescriptor, bindingContext)
|
||||
val irModule = ModuleGenerator(irGeneratorContext).generateModule(ktFiles)
|
||||
postprocess(irModule)
|
||||
return irModule
|
||||
}
|
||||
|
||||
+9
-9
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.IrVariableLValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.VariableLValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.IrValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.createRematerializableValue
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
@@ -32,12 +32,12 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenerator {
|
||||
override val context: IrGeneratorContext get() =
|
||||
irStatementGenerator.context
|
||||
class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
override val context: GeneratorContext get() =
|
||||
statementGenerator.context
|
||||
|
||||
private val temporaryVariableFactory: IrTemporaryVariableFactory get() =
|
||||
irStatementGenerator.temporaryVariableFactory
|
||||
private val temporaryVariableFactory: TemporaryVariableFactory get() =
|
||||
statementGenerator.temporaryVariableFactory
|
||||
|
||||
private val expressionValues = HashMap<KtExpression, IrValue>()
|
||||
private val receiverValues = HashMap<ReceiverValue, IrValue>()
|
||||
@@ -51,7 +51,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
}
|
||||
|
||||
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint)
|
||||
putValue(ktExpression, IrVariableLValue(irTmpVar))
|
||||
putValue(ktExpression, VariableLValue(irTmpVar))
|
||||
return irTmpVar
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
}
|
||||
|
||||
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, valueParameterDescriptor.name.asString())
|
||||
putValue(valueParameterDescriptor, IrVariableLValue(irTmpVar))
|
||||
putValue(valueParameterDescriptor, VariableLValue(irTmpVar))
|
||||
return irTmpVar
|
||||
}
|
||||
|
||||
@@ -249,6 +249,6 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
}
|
||||
|
||||
private fun generateExpression(ktExpression: KtExpression): IrExpression =
|
||||
expressionValues[ktExpression]?.load() ?: irStatementGenerator.generateExpression(ktExpression)
|
||||
expressionValues[ktExpression]?.load() ?: statementGenerator.generateExpression(ktExpression)
|
||||
|
||||
}
|
||||
+2
-2
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
|
||||
class IrDeclarationGenerator(override val context: IrGeneratorContext) : IrGenerator {
|
||||
class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator {
|
||||
fun generateAnnotationEntries(annotationEntries: List<KtAnnotationEntry>) {
|
||||
// TODO create IrAnnotation's for each KtAnnotationEntry
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class IrDeclarationGenerator(override val context: IrGeneratorContext) : IrGener
|
||||
}
|
||||
|
||||
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
|
||||
IrStatementGenerator(context, scopeOwner, IrTemporaryVariableFactory(scopeOwner))
|
||||
StatementGenerator(context, scopeOwner, TemporaryVariableFactory(scopeOwner))
|
||||
.generateExpression(ktExpression)
|
||||
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
|
||||
|
||||
interface IrGenerator {
|
||||
val context: IrGeneratorContext
|
||||
val context: GeneratorContext
|
||||
}
|
||||
|
||||
fun <K, V : Any> IrGenerator.get(slice: ReadOnlySlice<K, V>, key: K): V? =
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class IrGeneratorContext(
|
||||
class GeneratorContext(
|
||||
val moduleDescriptor: ModuleDescriptor,
|
||||
val bindingContext: BindingContext
|
||||
) {
|
||||
+2
-2
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class IrModuleGenerator(override val context: IrGeneratorContext) : IrGenerator {
|
||||
class ModuleGenerator(override val context: GeneratorContext) : IrGenerator {
|
||||
fun generateModule(ktFiles: List<KtFile>): IrModule {
|
||||
val irDeclarationGenerator = IrDeclarationGenerator(context)
|
||||
val irDeclarationGenerator = DeclarationGenerator(context)
|
||||
|
||||
val irModule = IrModuleImpl(context.moduleDescriptor)
|
||||
for (ktFile in ktFiles) {
|
||||
+30
-28
@@ -20,12 +20,10 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.*
|
||||
@@ -36,8 +34,8 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
|
||||
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
|
||||
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
||||
class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): IrGenerator {
|
||||
override val context: GeneratorContext get() = statementGenerator.context
|
||||
|
||||
fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression {
|
||||
val ktOperator = expression.operationReference.getReferencedNameElementType()
|
||||
@@ -50,6 +48,10 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
}
|
||||
}
|
||||
|
||||
fun generatePostfixExpression(expression: KtPostfixExpression): IrExpression {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression {
|
||||
val ktOperator = expression.operationReference.getReferencedNameElementType()
|
||||
if (ktOperator == KtTokens.IDENTIFIER) {
|
||||
@@ -77,8 +79,8 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
// TODO desugar '?:' to 'if'?
|
||||
val specialCallForElvis = getResolvedCall(expression)!!
|
||||
val returnType = specialCallForElvis.resultingDescriptor.returnType!!
|
||||
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!).toExpectedType(returnType.makeNullable())
|
||||
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!).toExpectedType(returnType)
|
||||
val irArgument0 = statementGenerator.generateExpression(expression.left!!).toExpectedType(returnType.makeNullable())
|
||||
val irArgument1 = statementGenerator.generateExpression(expression.right!!).toExpectedType(returnType)
|
||||
return IrBinaryOperatorExpressionImpl(
|
||||
expression.startOffset, expression.endOffset, returnType,
|
||||
IrOperator.ELVIS, null, irArgument0, irArgument1
|
||||
@@ -86,8 +88,8 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
}
|
||||
|
||||
private fun generateBinaryBooleanOperator(expression: KtBinaryExpression, irOperator: IrBinaryOperator): IrExpression {
|
||||
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!).toExpectedType(context.builtIns.booleanType)
|
||||
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!).toExpectedType(context.builtIns.booleanType)
|
||||
val irArgument0 = statementGenerator.generateExpression(expression.left!!).toExpectedType(context.builtIns.booleanType)
|
||||
val irArgument1 = statementGenerator.generateExpression(expression.right!!).toExpectedType(context.builtIns.booleanType)
|
||||
return IrBinaryOperatorExpressionImpl(
|
||||
expression.startOffset, expression.endOffset, context.builtIns.booleanType,
|
||||
irOperator, getResolvedCall(expression)?.resultingDescriptor, irArgument0, irArgument1
|
||||
@@ -97,7 +99,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
|
||||
val operatorCall = getResolvedCall(expression)!!
|
||||
|
||||
val irOperatorCall = IrCallGenerator(irStatementGenerator).generateCall(expression, operatorCall, irOperator)
|
||||
val irOperatorCall = CallGenerator(statementGenerator).generateCall(expression, operatorCall, irOperator)
|
||||
|
||||
return if (irOperator == IrOperator.IN)
|
||||
irOperatorCall
|
||||
@@ -107,8 +109,8 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
}
|
||||
|
||||
private fun generateIdentityOperator(expression: KtBinaryExpression, irOperator: IrBinaryOperator): IrExpression {
|
||||
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!)
|
||||
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!)
|
||||
val irArgument0 = statementGenerator.generateExpression(expression.left!!)
|
||||
val irArgument1 = statementGenerator.generateExpression(expression.right!!)
|
||||
return IrBinaryOperatorExpressionImpl(
|
||||
expression.startOffset, expression.endOffset, context.builtIns.booleanType,
|
||||
irOperator, null, irArgument0, irArgument1
|
||||
@@ -119,7 +121,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
val relatedCall = getResolvedCall(expression)!!
|
||||
val relatedDescriptor = relatedCall.resultingDescriptor
|
||||
|
||||
val irCallGenerator = IrCallGenerator(irStatementGenerator)
|
||||
val irCallGenerator = CallGenerator(statementGenerator)
|
||||
|
||||
// NB special typing rules for equality operators: both arguments are nullable
|
||||
|
||||
@@ -144,7 +146,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
val compareToCall = getResolvedCall(expression)!!
|
||||
val compareToDescriptor = compareToCall.resultingDescriptor
|
||||
|
||||
val irCallGenerator = IrCallGenerator(irStatementGenerator)
|
||||
val irCallGenerator = CallGenerator(statementGenerator)
|
||||
|
||||
return if (shouldKeepComparisonAsBinaryOperation(compareToDescriptor)) {
|
||||
val irArgument0 = irCallGenerator.generateReceiver(expression.left!!, compareToCall.dispatchReceiver, compareToDescriptor.dispatchReceiverParameter!!)!!
|
||||
@@ -172,7 +174,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
|
||||
private fun generateBinaryOperatorWithConventionalCall(expression: KtBinaryExpression, irOperator: IrOperator?): IrExpression {
|
||||
val operatorCall = getResolvedCall(expression)!!
|
||||
return IrCallGenerator(irStatementGenerator).generateCall(expression, operatorCall, irOperator)
|
||||
return CallGenerator(statementGenerator).generateCall(expression, operatorCall, irOperator)
|
||||
}
|
||||
|
||||
private fun generatePrefixIncrementDecrementOperator(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
||||
@@ -184,10 +186,10 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
return irLValue.prefixAugmentedStore(operatorCall, irOperator)
|
||||
}
|
||||
|
||||
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktBaseExpression, irLValue) }
|
||||
val opCallGenerator = CallGenerator(statementGenerator).apply { putValue(ktBaseExpression, irLValue) }
|
||||
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, irLValue.type, true, irOperator)
|
||||
val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator)
|
||||
val irTmp = irStatementGenerator.temporaryVariableFactory.createTemporaryVariable(irOpCall)
|
||||
val irTmp = statementGenerator.temporaryVariableFactory.createTemporaryVariable(irOpCall)
|
||||
irBlock.addStatement(irTmp)
|
||||
irBlock.addStatement(irLValue.store(irTmp.load()))
|
||||
irBlock.addStatement(irTmp.load())
|
||||
@@ -202,10 +204,10 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false
|
||||
|
||||
if (isSimpleAssignment && irLValue is IrLValueWithAugmentedStore) {
|
||||
return irLValue.augmentedStore(operatorCall, irOperator, irStatementGenerator.generateExpression(expression.right!!))
|
||||
return irLValue.augmentedStore(operatorCall, irOperator, statementGenerator.generateExpression(expression.right!!))
|
||||
}
|
||||
|
||||
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktLeft, irLValue) }
|
||||
val opCallGenerator = CallGenerator(statementGenerator).apply { putValue(ktLeft, irLValue) }
|
||||
val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator)
|
||||
|
||||
return if (isSimpleAssignment) {
|
||||
@@ -222,20 +224,20 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
val ktLeft = expression.left!!
|
||||
val ktRight = expression.right!!
|
||||
val irLValue = generateLValue(ktLeft, IrOperator.EQ)
|
||||
return irLValue.store(irStatementGenerator.generateExpression(ktRight))
|
||||
return irLValue.store(statementGenerator.generateExpression(ktRight))
|
||||
}
|
||||
|
||||
private fun generateLValue(ktLeft: KtExpression, irOperator: IrOperator?): IrLValue {
|
||||
if (ktLeft is KtArrayAccessExpression) {
|
||||
val irArrayValue = irStatementGenerator.generateExpression(ktLeft.arrayExpression!!)
|
||||
val indexExpressions = ktLeft.indexExpressions.map { it to irStatementGenerator.generateExpression(it) }
|
||||
val irArrayValue = statementGenerator.generateExpression(ktLeft.arrayExpression!!)
|
||||
val indexExpressions = ktLeft.indexExpressions.map { it to statementGenerator.generateExpression(it) }
|
||||
val indexedGetCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft)
|
||||
val indexedSetCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
|
||||
val type = indexedGetCall?.run { resultingDescriptor.returnType }
|
||||
?: indexedSetCall?.run { resultingDescriptor.valueParameters.last().type }
|
||||
?: throw AssertionError("Either 'get' or 'set' call should be present for an indexed LValue: ${ktLeft.text}")
|
||||
return IrIndexedLValue(irStatementGenerator, ktLeft, irOperator,
|
||||
irArrayValue, type, indexExpressions, indexedGetCall, indexedSetCall)
|
||||
return IndexedLValue(statementGenerator, ktLeft, irOperator,
|
||||
irArrayValue, type, indexExpressions, indexedGetCall, indexedSetCall)
|
||||
}
|
||||
|
||||
val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS")
|
||||
@@ -246,10 +248,10 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
if (descriptor.isDelegated)
|
||||
TODO("Delegated local variable")
|
||||
else
|
||||
IrVariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator)
|
||||
VariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator)
|
||||
is PropertyDescriptor ->
|
||||
IrCallGenerator(irStatementGenerator).run {
|
||||
IrPropertyLValue(
|
||||
CallGenerator(statementGenerator).run {
|
||||
PropertyLValue(
|
||||
ktLeft, irOperator, descriptor,
|
||||
generateReceiver(ktLeft, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter),
|
||||
generateReceiver(ktLeft, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter),
|
||||
+41
-11
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.IrVariableLValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.VariableLValue
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
@@ -38,17 +38,17 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
|
||||
class IrStatementGenerator(
|
||||
override val context: IrGeneratorContext,
|
||||
class StatementGenerator(
|
||||
override val context: GeneratorContext,
|
||||
val scopeOwner: DeclarationDescriptor,
|
||||
val temporaryVariableFactory: IrTemporaryVariableFactory
|
||||
val temporaryVariableFactory: TemporaryVariableFactory
|
||||
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
|
||||
|
||||
fun generateExpression(ktExpression: KtExpression): IrExpression =
|
||||
ktExpression.genExpr()
|
||||
|
||||
private fun KtElement.genStmt(): IrStatement =
|
||||
deparenthesize().accept(this@IrStatementGenerator, null)
|
||||
deparenthesize().accept(this@StatementGenerator, null)
|
||||
|
||||
private fun KtElement.genExpr(): IrExpression =
|
||||
genStmt().assertCast()
|
||||
@@ -77,8 +77,8 @@ class IrStatementGenerator(
|
||||
val irTmpInitializer = temporaryVariableFactory.createTemporaryVariable(ktInitializer.genExpr())
|
||||
irBlock.addStatement(irTmpInitializer)
|
||||
|
||||
val irCallGenerator = IrCallGenerator(this)
|
||||
irCallGenerator.putValue(ktInitializer, IrVariableLValue(irTmpInitializer))
|
||||
val irCallGenerator = CallGenerator(this)
|
||||
irCallGenerator.putValue(ktInitializer, VariableLValue(irTmpInitializer))
|
||||
|
||||
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
|
||||
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
||||
@@ -188,7 +188,7 @@ class IrStatementGenerator(
|
||||
companionObjectDescriptor)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
IrCallGenerator(this).generateCall(expression, resolvedCall)
|
||||
CallGenerator(this).generateCall(expression, resolvedCall)
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||
@@ -207,7 +207,7 @@ class IrStatementGenerator(
|
||||
TODO("VariableAsFunctionResolvedCall = variable call + invoke call")
|
||||
}
|
||||
|
||||
return IrCallGenerator(this).generateCall(expression, resolvedCall)
|
||||
return CallGenerator(this).generateCall(expression, resolvedCall)
|
||||
}
|
||||
|
||||
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement =
|
||||
@@ -239,8 +239,38 @@ class IrStatementGenerator(
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Nothing?): IrStatement =
|
||||
IrOperatorExpressionGenerator(this).generateBinaryExpression(expression)
|
||||
OperatorExpressionGenerator(this).generateBinaryExpression(expression)
|
||||
|
||||
override fun visitPrefixExpression(expression: KtPrefixExpression, data: Nothing?): IrStatement =
|
||||
IrOperatorExpressionGenerator(this).generatePrefixExpression(expression)
|
||||
OperatorExpressionGenerator(this).generatePrefixExpression(expression)
|
||||
|
||||
override fun visitPostfixExpression(expression: KtPostfixExpression, data: Nothing?): IrStatement =
|
||||
OperatorExpressionGenerator(this).generatePostfixExpression(expression)
|
||||
|
||||
override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement {
|
||||
val resultType = getInferredTypeWithSmartcasts(expression)
|
||||
val irWhen = IrWhenExpressionImpl(expression.startOffset, expression.endOffset, resultType)
|
||||
|
||||
var ktBranch: KtIfExpression? = expression
|
||||
branches@while (ktBranch != null) {
|
||||
val irBranch = IrBranchImpl(ktBranch.startOffset, ktBranch.endOffset,
|
||||
ktBranch.condition!!.genExpr().toExpectedType(context.builtIns.booleanType),
|
||||
ktBranch.then!!.genExpr().toExpectedType(resultType))
|
||||
irWhen.addBranch(irBranch)
|
||||
|
||||
val ktElse = ktBranch.`else`
|
||||
|
||||
ktBranch = when (ktElse) {
|
||||
is KtIfExpression -> ktElse
|
||||
null ->
|
||||
break@branches
|
||||
else -> {
|
||||
irWhen.elseExpression = ktElse.genExpr().toExpectedType(resultType)
|
||||
break@branches
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return irWhen
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class IrTemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) {
|
||||
class TemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) {
|
||||
private var lastTemporaryIndex = 0
|
||||
private fun nextTemporaryIndex() = lastTemporaryIndex++
|
||||
|
||||
+12
-12
@@ -22,13 +22,13 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.load
|
||||
import org.jetbrains.kotlin.psi2ir.generators.IrCallGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.IrStatementGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.StatementGenerator
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class IrIndexedLValue(
|
||||
var irStatementGenerator: IrStatementGenerator,
|
||||
class IndexedLValue(
|
||||
var statementGenerator: StatementGenerator,
|
||||
val ktArrayAccessExpression: KtArrayAccessExpression,
|
||||
val irOperator: IrOperator?,
|
||||
val irArray: IrExpression,
|
||||
@@ -50,7 +50,7 @@ class IrIndexedLValue(
|
||||
}
|
||||
|
||||
private fun generateGetOrSetCallAsDesugaredBlock(call: ResolvedCall<*>, irArgument: IrExpression? = null): IrExpression {
|
||||
val callGenerator = IrCallGenerator(irStatementGenerator)
|
||||
val callGenerator = CallGenerator(statementGenerator)
|
||||
setupCallGeneratorContext(callGenerator)
|
||||
|
||||
if (irArgument != null) {
|
||||
@@ -64,19 +64,19 @@ class IrIndexedLValue(
|
||||
if (indexedGetCall == null) throw AssertionError("Indexed LValue has no 'get' call: ${ktArrayAccessExpression.text}")
|
||||
if (indexedSetCall == null) throw AssertionError("Indexed LValue has no 'set' call: ${ktArrayAccessExpression.text}")
|
||||
|
||||
val callGenerator = IrCallGenerator(irStatementGenerator)
|
||||
val callGenerator = CallGenerator(statementGenerator)
|
||||
|
||||
val irBlock = createDesugaredBlockWithTemporaries(indexedSetCall, callGenerator, true, irOperator)
|
||||
|
||||
val operatorCallReceiver = operatorCall.extensionReceiver ?: operatorCall.dispatchReceiver
|
||||
callGenerator.putValue(operatorCallReceiver!!,
|
||||
IrSingleExpressionValue(callGenerator.generateCall(ktArrayAccessExpression, indexedGetCall, irOperator)))
|
||||
val irTmp = irStatementGenerator.temporaryVariableFactory.createTemporaryVariable(
|
||||
val irTmp = statementGenerator.temporaryVariableFactory.createTemporaryVariable(
|
||||
callGenerator.generateCall(ktArrayAccessExpression, operatorCall, irOperator))
|
||||
irBlock.addStatement(irTmp)
|
||||
|
||||
callGenerator.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(),
|
||||
IrVariableLValue(irTmp))
|
||||
VariableLValue(irTmp))
|
||||
|
||||
irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedSetCall, irOperator))
|
||||
|
||||
@@ -89,7 +89,7 @@ class IrIndexedLValue(
|
||||
if (indexedGetCall == null) throw AssertionError("Indexed LValue has no 'get' call: ${ktArrayAccessExpression.text}")
|
||||
if (indexedSetCall == null) throw AssertionError("Indexed LValue has no 'set' call: ${ktArrayAccessExpression.text}")
|
||||
|
||||
val callGenerator = IrCallGenerator(irStatementGenerator)
|
||||
val callGenerator = CallGenerator(statementGenerator)
|
||||
|
||||
val irBlock = createDesugaredBlockWithTemporaries(indexedSetCall, callGenerator, false, irOperator)
|
||||
|
||||
@@ -109,7 +109,7 @@ class IrIndexedLValue(
|
||||
|
||||
private fun createDesugaredBlockWithTemporaries(
|
||||
call: ResolvedCall<*>,
|
||||
callGenerator: IrCallGenerator,
|
||||
callGenerator: CallGenerator,
|
||||
hasResult: Boolean,
|
||||
operator: IrOperator?
|
||||
): IrBlockExpressionImpl {
|
||||
@@ -124,7 +124,7 @@ class IrIndexedLValue(
|
||||
hasResult, operator)
|
||||
}
|
||||
|
||||
private fun defineTemporaryVariables(irBlock: IrBlockExpression, callGenerator: IrCallGenerator) {
|
||||
private fun defineTemporaryVariables(irBlock: IrBlockExpression, callGenerator: CallGenerator) {
|
||||
irBlock.addIfNotNull(callGenerator.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array"))
|
||||
|
||||
var index = 0
|
||||
@@ -133,7 +133,7 @@ class IrIndexedLValue(
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCallGeneratorContext(callGenerator: IrCallGenerator) {
|
||||
private fun setupCallGeneratorContext(callGenerator: CallGenerator) {
|
||||
callGenerator.putValue(ktArrayAccessExpression.arrayExpression!!, IrSingleExpressionValue(irArray))
|
||||
|
||||
for ((ktIndexExpression, irIndexValue) in indexValues) {
|
||||
+3
-3
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class IrPropertyLValue(
|
||||
class PropertyLValue(
|
||||
val ktElement: KtElement,
|
||||
val irOperator: IrOperator?,
|
||||
val descriptor: PropertyDescriptor,
|
||||
@@ -37,8 +37,8 @@ class IrPropertyLValue(
|
||||
|
||||
private fun IrPropertyAccessExpression.setReceivers() =
|
||||
apply {
|
||||
dispatchReceiver = this@IrPropertyLValue.dispatchReceiver
|
||||
extensionReceiver = this@IrPropertyLValue.extensionReceiver
|
||||
dispatchReceiver = this@PropertyLValue.dispatchReceiver
|
||||
extensionReceiver = this@PropertyLValue.extensionReceiver
|
||||
}
|
||||
|
||||
override fun load(): IrExpression =
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class IrVariableLValue(
|
||||
class VariableLValue(
|
||||
val startOffset: Int,
|
||||
val endOffset: Int,
|
||||
val descriptor: VariableDescriptor,
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir
|
||||
|
||||
const val CHILD_DECLARATION_SLOT = 0
|
||||
const val DETACHED_SLOT = Int.MIN_VALUE
|
||||
const val CHILD_EXPRESSION_SLOT = 0
|
||||
const val ARGUMENT0_SLOT = 0
|
||||
@@ -25,4 +24,8 @@ const val DISPATCH_RECEIVER_SLOT = -1
|
||||
const val EXTENSION_RECEIVER_SLOT = -2
|
||||
const val FUNCTION_BODY_SLOT = 0
|
||||
const val MODULE_SLOT = 0
|
||||
const val INITIALIZER_SLOT = 0
|
||||
const val INITIALIZER_SLOT = 0
|
||||
const val WHEN_SUBJECT_VARIABLE_SLOT = -1
|
||||
const val WHEN_ELSE_EXPRESSION_SLOT = -2
|
||||
const val BRANCH_CONDITION_SLOT = -1
|
||||
const val BRANCH_RESULT_SLOT = -2
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.assertCast
|
||||
import org.jetbrains.kotlin.ir.assertDetached
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
@@ -56,8 +53,11 @@ class IrBlockExpressionImpl(
|
||||
statements.getOrNull(slot)
|
||||
|
||||
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||
newChild.assertDetached()
|
||||
if (0 <= slot && slot < statements.size) {
|
||||
statements[slot].detach()
|
||||
statements[slot] = newChild.assertCast()
|
||||
newChild.setTreeLocation(this, slot)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
interface IrWhenExpression : IrExpression {
|
||||
var subject: IrVariable?
|
||||
val branches: List<IrBranch>
|
||||
var elseExpression: IrExpression?
|
||||
|
||||
fun addBranch(branch: IrBranch)
|
||||
}
|
||||
|
||||
interface IrBranch : IrElement {
|
||||
var condition: IrExpression
|
||||
var result: IrExpression
|
||||
}
|
||||
|
||||
class IrWhenExpressionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType?
|
||||
) : IrExpressionBase(startOffset, endOffset, type), IrWhenExpression {
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType?,
|
||||
subject: IrVariable
|
||||
) : this(startOffset, endOffset, type) {
|
||||
this.subject = subject
|
||||
}
|
||||
|
||||
override var subject: IrVariable? = null
|
||||
set(value) {
|
||||
value?.assertDetached()
|
||||
subject?.detach()
|
||||
field = value
|
||||
field?.setTreeLocation(this, WHEN_SUBJECT_VARIABLE_SLOT)
|
||||
}
|
||||
|
||||
override val branches: MutableList<IrBranch> = ArrayList()
|
||||
|
||||
override var elseExpression: IrExpression? = null
|
||||
set(value) {
|
||||
value?.assertDetached()
|
||||
subject?.detach()
|
||||
field = value
|
||||
field?.setTreeLocation(this, WHEN_ELSE_EXPRESSION_SLOT)
|
||||
}
|
||||
|
||||
override fun addBranch(branch: IrBranch) {
|
||||
branch.assertDetached()
|
||||
branch.setTreeLocation(this, branches.size)
|
||||
branches.add(branch)
|
||||
}
|
||||
|
||||
override fun getChild(slot: Int): IrElement? =
|
||||
when (slot) {
|
||||
WHEN_SUBJECT_VARIABLE_SLOT -> subject
|
||||
WHEN_ELSE_EXPRESSION_SLOT -> elseExpression
|
||||
else -> branches.getOrNull(slot)
|
||||
}
|
||||
|
||||
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||
newChild.assertDetached()
|
||||
when (slot) {
|
||||
WHEN_SUBJECT_VARIABLE_SLOT ->
|
||||
subject = newChild.assertCast()
|
||||
WHEN_ELSE_EXPRESSION_SLOT ->
|
||||
elseExpression = newChild.assertCast()
|
||||
in branches.indices -> {
|
||||
branches[slot].detach()
|
||||
branches[slot] = newChild.assertCast()
|
||||
newChild.setTreeLocation(this, slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitWhenExpression(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
subject?.accept(visitor, data)
|
||||
branches.forEach { it.accept(visitor, data) }
|
||||
elseExpression?.accept(visitor, data)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun ifThen(startOffset: Int, endOffset: Int, type: KotlinType?, condition: IrExpression, thenExpression: IrExpression) =
|
||||
IrWhenExpressionImpl(startOffset, endOffset, type).apply {
|
||||
addBranch(IrBranchImpl(startOffset, endOffset, condition, thenExpression))
|
||||
}
|
||||
|
||||
fun ifThenElse(startOffset: Int, endOffset: Int, type: KotlinType?,
|
||||
condition: IrExpression, thenExpression: IrExpression, elseExpression: IrExpression) =
|
||||
IrWhenExpressionImpl(startOffset, endOffset, type).apply {
|
||||
addBranch(IrBranchImpl(startOffset, endOffset, condition, thenExpression))
|
||||
this.elseExpression = elseExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IrBranchImpl(startOffset: Int, endOffset: Int) : IrElementBase(startOffset, endOffset), IrBranch {
|
||||
constructor(startOffset: Int, endOffset: Int, condition: IrExpression, result: IrExpression) : this(startOffset, endOffset) {
|
||||
this.condition = condition
|
||||
this.result = result
|
||||
}
|
||||
|
||||
private var conditionImpl: IrExpression? = null
|
||||
override var condition: IrExpression
|
||||
get() = conditionImpl!!
|
||||
set(value) {
|
||||
value.assertDetached()
|
||||
conditionImpl?.detach()
|
||||
conditionImpl = value
|
||||
value.setTreeLocation(this, BRANCH_CONDITION_SLOT)
|
||||
}
|
||||
|
||||
private var resultImpl: IrExpression? = null
|
||||
override var result: IrExpression
|
||||
get() = resultImpl!!
|
||||
set(value) {
|
||||
value.assertDetached()
|
||||
resultImpl?.detach()
|
||||
resultImpl = value
|
||||
value.setTreeLocation(this, BRANCH_RESULT_SLOT)
|
||||
}
|
||||
|
||||
override fun getChild(slot: Int): IrElement? =
|
||||
when (slot) {
|
||||
BRANCH_CONDITION_SLOT -> condition
|
||||
BRANCH_RESULT_SLOT -> result
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||
when (slot) {
|
||||
BRANCH_CONDITION_SLOT ->
|
||||
condition = newChild.assertCast()
|
||||
BRANCH_RESULT_SLOT ->
|
||||
result = newChild.assertCast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitBranch(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
conditionImpl?.accept(visitor, data)
|
||||
resultImpl?.accept(visitor, data)
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetPropertyExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSetPropertyExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrWhenExpression
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
@@ -70,6 +71,19 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor<Unit, String> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(expression: IrWhenExpression, data: String) {
|
||||
expression.dumpLabeledElementWith(data) {
|
||||
expression.subject?.let { subject ->
|
||||
subject.accept(this, "\$subject:")
|
||||
}
|
||||
for (branch in expression.branches) {
|
||||
branch.condition.accept(this, "if")
|
||||
branch.result.accept(this, "then")
|
||||
}
|
||||
expression.elseExpression?.accept(this, "else")
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun IrElement.dumpLabeledElementWith(label: String, body: () -> Unit) {
|
||||
printer.println(accept(elementRenderer, null).withLabel(label))
|
||||
indented(body)
|
||||
|
||||
@@ -112,9 +112,14 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: Nothing?): String =
|
||||
"STRING_CONCATENATION type=${expression.renderType()}"
|
||||
|
||||
override fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: Nothing?): String {
|
||||
return "TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
|
||||
}
|
||||
override fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: Nothing?): String =
|
||||
"TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
|
||||
|
||||
override fun visitWhenExpression(expression: IrWhenExpression, data: Nothing?): String =
|
||||
"WHEN subject=${expression.subject?.descriptor?.name} type=${expression.type.render()}"
|
||||
|
||||
override fun visitBranch(branch: IrBranch, data: Nothing?): String =
|
||||
"BRANCH"
|
||||
|
||||
override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String =
|
||||
"DUMMY ${declaration.descriptor.name}"
|
||||
|
||||
@@ -63,8 +63,10 @@ interface IrElementVisitor<out R, in D> {
|
||||
fun visitBinaryOperator(expression: IrBinaryOperatorExpression, data: D) = visitOperatorExpression(expression, data)
|
||||
fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: D) = visitExpression(expression, data)
|
||||
|
||||
fun visitWhenExpression(expression: IrWhenExpression, data: D) = visitExpression(expression, data)
|
||||
fun visitBranch(branch: IrBranch, data: D): R = visitElement(branch, data)
|
||||
|
||||
// NB Use it only for testing purposes; will be removed as soon as all Kotlin expression types are covered
|
||||
fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data)
|
||||
fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data)
|
||||
|
||||
}
|
||||
|
||||
+8
-2
@@ -16,8 +16,14 @@ IrFile /elvis.kt
|
||||
IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value=''
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value=''
|
||||
RETURN type=<no-type>
|
||||
BINARY_OP operator=ELVIS type=kotlin.String related=null
|
||||
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String?
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
fun test(i: Int) =
|
||||
if (i > 0) 1
|
||||
else if (i < 0) -1
|
||||
else 0
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
IrFile /ifElseIf.kt
|
||||
IrFunction public fun test(/*0*/ i: kotlin.Int): kotlin.Int
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
WHEN subject=null type=kotlin.Int
|
||||
if: BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
GET_VAR i type=kotlin.Int operator=null
|
||||
LITERAL Int type=kotlin.Int value='0'
|
||||
then: LITERAL Int type=kotlin.Int value='1'
|
||||
if: BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
GET_VAR i type=kotlin.Int operator=null
|
||||
LITERAL Int type=kotlin.Int value='0'
|
||||
then: DUMMY MINUS type=kotlin.Int
|
||||
else: LITERAL Int type=kotlin.Int value='0'
|
||||
+11
-3
@@ -18,7 +18,9 @@ IrFile /smartCasts.kt
|
||||
IrFunction public fun test1(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
CALL .println type=kotlin.Unit operator=null
|
||||
message: GET_PROPERTY .length type=kotlin.Int operator=null
|
||||
$this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
@@ -37,7 +39,10 @@ IrFile /smartCasts.kt
|
||||
IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value=''
|
||||
RETURN type=<no-type>
|
||||
CALL .overloaded type=kotlin.String operator=null
|
||||
s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
@@ -45,7 +50,10 @@ IrFile /smartCasts.kt
|
||||
IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value=''
|
||||
RETURN type=<no-type>
|
||||
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
GET_VAR x type=kotlin.Any operator=null
|
||||
|
||||
@@ -14,7 +14,9 @@ IrFile /smartCastsWithDestructuring.kt
|
||||
IrFunction public fun test(/*0*/ x: I1): kotlin.Unit
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
WHEN subject=null type=kotlin.Unit
|
||||
if: DUMMY KtIsExpression type=kotlin.Boolean
|
||||
then: RETURN type=<no-type>
|
||||
BLOCK type=<no-type> hasResult=false operator=SYNTHETIC_BLOCK
|
||||
VAR val tmp0: I1
|
||||
GET_VAR x type=I1 operator=null
|
||||
|
||||
@@ -137,6 +137,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifElseIf.kt")
|
||||
public void testIfElseIf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/ifElseIf.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implicitCastOnPlatformType.kt")
|
||||
public void testImplicitCastOnPlatformType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/implicitCastOnPlatformType.kt");
|
||||
|
||||
Reference in New Issue
Block a user