Refactor top-down generation.

This commit is contained in:
Dmitry Petrov
2016-08-17 11:15:18 +03:00
committed by Dmitry Petrov
parent 278dc14124
commit 177acaabf5
9 changed files with 182 additions and 195 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrModule
import org.jetbrains.kotlin.ir.declarations.IrModuleImpl
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.IrGeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.IrModuleGenerator
@@ -32,9 +31,8 @@ class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
)
fun generateModule(moduleDescriptor: ModuleDescriptor, ktFiles: List<KtFile>, bindingContext: BindingContext): IrModule {
val irModule = IrModuleImpl(moduleDescriptor)
val irGeneratorContext = IrGeneratorContext(ktFiles, irModule, bindingContext)
IrModuleGenerator(irGeneratorContext).generateModuleContent()
val irGeneratorContext = IrGeneratorContext(moduleDescriptor, bindingContext)
val irModule = IrModuleGenerator(irGeneratorContext).generateModule(ktFiles)
postprocess(irModule)
return irModule
}
@@ -29,17 +29,19 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class IrCallGenerator(
private val irStatementGenerator: IrStatementGenerator
) : IrGenerator {
override val context: IrGeneratorContext get() = irStatementGenerator.context
class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenerator {
override val context: IrGeneratorContext get() =
irStatementGenerator.context
private val temporaryVariableFactory: IrTemporaryVariableFactory get() =
irStatementGenerator.temporaryVariableFactory
private val expressionValues = HashMap<KtExpression, IrValue>()
private val receiverValues = HashMap<ReceiverValue, IrValue>()
private val valueArgumentValues = HashMap<ValueParameterDescriptor, IrValue>()
fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression): IrVariable {
val irTmpVar = irStatementGenerator.declarationFactory.createTemporaryVariable(irExpression)
fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String? = null): IrVariable {
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint)
putValue(ktExpression, IrTemporaryVariableValue(irTmpVar))
return irTmpVar
}
@@ -150,7 +152,7 @@ class IrCallGenerator(
val temporariesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
for (valueArgument in valueArgumentsInEvaluationOrder) {
val irArgument = generateValueArgument(valueArgument, valueArgumentsToValueParameters[valueArgument]!!) ?: continue
val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument)
val irTemporary = temporaryVariableFactory.createTemporaryVariable(irArgument)
temporariesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
irBlock.addStatement(irTemporary)
}
@@ -1,88 +0,0 @@
/*
* 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.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.types.KotlinType
abstract class IrDeclarationFactoryBase {
fun createFunction(ktFunction: KtFunction, functionDescriptor: FunctionDescriptor, body: IrBody): IrFunction =
IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset,
IrDeclarationOriginKind.DEFINED, functionDescriptor, body)
fun createSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor, valueInitializer: IrBody?): IrSimpleProperty =
IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOriginKind.DEFINED, propertyDescriptor, valueInitializer)
fun createPropertyGetter(
ktPropertyAccessor: KtPropertyAccessor,
irProperty: IrProperty,
getterDescriptor: PropertyGetterDescriptor,
getterBody: IrBody
): IrPropertyGetter =
IrPropertyGetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, getterDescriptor, getterBody)
.apply { irProperty.getter = this }
fun createPropertySetter(
ktPropertyAccessor: KtPropertyAccessor,
irProperty: IrProperty,
setterDescriptor: PropertySetterDescriptor,
setterBody: IrBody
) : IrPropertySetter =
IrPropertySetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, setterDescriptor, setterBody)
.apply { irProperty.setter = this }
}
class IrDeclarationFactory() : IrDeclarationFactoryBase()
class IrLocalDeclarationsFactory(val scopeOwner: DeclarationDescriptor) : IrDeclarationFactoryBase() {
private var lastTemporaryIndex = 0
private fun nextTemporaryIndex() = lastTemporaryIndex++
fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor =
IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type)
fun createTemporaryVariable(irExpression: IrExpression): IrVariable =
IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
createDescriptorForTemporaryVariable(
irExpression.type
?: throw AssertionError("No type for $irExpression")
),
irExpression)
fun createLocalVariable(ktElement: KtElement, descriptor: VariableDescriptor): IrVariable =
IrVariableImpl(ktElement.startOffset, ktElement.endOffset, IrDeclarationOriginKind.DEFINED,
descriptor)
fun createLocalVariable(ktElement: KtElement, descriptor: VariableDescriptor, initializer: IrExpression): IrVariable =
IrVariableImpl(ktElement.startOffset, ktElement.endOffset, IrDeclarationOriginKind.DEFINED,
descriptor, initializer)
}
@@ -17,76 +17,122 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDummyDeclaration
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
interface IrDeclarationGenerator : IrGenerator
abstract class IrDeclarationGeneratorBase(
override val context: IrGeneratorContext,
val declarationFactory: IrDeclarationFactoryBase
) : IrDeclarationGenerator {
protected abstract fun <D : IrDeclaration> D.register(): D
class IrDeclarationGenerator(override val context: IrGeneratorContext) : IrGenerator {
fun generateAnnotationEntries(annotationEntries: List<KtAnnotationEntry>) {
// TODO create IrAnnotation's for each KtAnnotationEntry
}
fun generateMemberDeclaration(ktDeclaration: KtDeclaration) {
// TODO visitor?
when (ktDeclaration) {
is KtNamedFunction -> generateFunctionDeclaration(ktDeclaration)
is KtProperty -> generatePropertyDeclaration(ktDeclaration)
is KtClassOrObject -> generateClassOrObjectDeclaration(ktDeclaration)
is KtTypeAlias -> generateTypeAliasDeclaration(ktDeclaration)
}
}
fun generateMemberDeclaration(ktDeclaration: KtDeclaration): IrDeclaration =
when (ktDeclaration) {
is KtNamedFunction ->
generateFunctionDeclaration(ktDeclaration)
is KtProperty ->
generatePropertyDeclaration(ktDeclaration)
is KtClassOrObject ->
generateClassOrObjectDeclaration(ktDeclaration)
is KtTypeAlias ->
generateTypeAliasDeclaration(ktDeclaration)
else ->
IrDummyDeclaration(
ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktDeclaration)
)
}
private fun generateClassOrObjectDeclaration(ktDeclaration: KtClassOrObject) {
IrDummyDeclaration(
ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.CLASS, ktDeclaration)
).register()
}
fun generateClassOrObjectDeclaration(ktDeclaration: KtClassOrObject): IrDeclaration =
IrDummyDeclaration(
ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.CLASS, ktDeclaration)
)
private fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias) {
IrDummyDeclaration(
ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)
).register()
}
fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration =
IrDummyDeclaration(
ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)
)
fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction) {
fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction): IrFunction {
val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktNamedFunction)
val body = generateFunctionBody(functionDescriptor, ktNamedFunction.bodyExpression ?: TODO("function without body expression"))
declarationFactory.createFunction(ktNamedFunction, functionDescriptor, body).register()
return createFunction(ktNamedFunction, functionDescriptor, body)
}
fun generatePropertyDeclaration(ktProperty: KtProperty) {
fun generateLocalVariable(scopeOwner: DeclarationDescriptor, ktProperty: KtProperty): IrVariable {
if (ktProperty.delegateExpression != null) TODO("Local delegated property")
val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty)
val irLocalVariable = IrVariableImpl(ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOriginKind.DEFINED, variableDescriptor)
irLocalVariable.initializer = ktProperty.initializer?.let {
generateExpressionWithinContext(it, scopeOwner)
}
return irLocalVariable
}
fun generatePropertyDeclaration(ktProperty: KtProperty): IrProperty {
val propertyDescriptor = getPropertyDescriptor(ktProperty)
if (ktProperty.hasDelegate()) TODO("handle delegated property")
val initializer = ktProperty.initializer?.let { generateInitializerBody(propertyDescriptor, it) }
val irProperty = declarationFactory.createSimpleProperty(ktProperty, propertyDescriptor, initializer).register()
val irProperty = createSimpleProperty(ktProperty, propertyDescriptor, initializer)
ktProperty.getter?.let { ktGetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter)
val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?")
val getterBody = generateFunctionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter"))
declarationFactory.createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody).register()
createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody)
}
ktProperty.setter?.let { ktSetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter)
val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?")
val setterBody = generateFunctionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter"))
declarationFactory.createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody).register()
createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody)
}
return irProperty
}
fun createFunction(ktFunction: KtFunction, functionDescriptor: FunctionDescriptor, body: IrBody): IrFunction =
IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset,
IrDeclarationOriginKind.DEFINED, functionDescriptor, body)
fun createSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor, valueInitializer: IrBody?): IrSimpleProperty =
IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOriginKind.DEFINED, propertyDescriptor, valueInitializer)
fun createPropertyGetter(
ktPropertyAccessor: KtPropertyAccessor,
irProperty: IrProperty,
getterDescriptor: PropertyGetterDescriptor,
getterBody: IrBody
): IrPropertyGetter =
IrPropertyGetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, getterDescriptor, getterBody)
.apply { irProperty.getter = this }
fun createPropertySetter(
ktPropertyAccessor: KtPropertyAccessor,
irProperty: IrProperty,
setterDescriptor: PropertySetterDescriptor,
setterBody: IrBody
) : IrPropertySetter =
IrPropertySetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, setterDescriptor, setterBody)
.apply { irProperty.setter = this }
private fun getPropertyDescriptor(ktProperty: KtProperty): PropertyDescriptor {
val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty)
val propertyDescriptor = variableDescriptor as? PropertyDescriptor ?: TODO("not a property?")
@@ -94,7 +140,7 @@ abstract class IrDeclarationGeneratorBase(
}
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
IrStatementGenerator(context, scopeOwner, IrLocalDeclarationsFactory(scopeOwner))
IrStatementGenerator(context, scopeOwner, IrTemporaryVariableFactory(scopeOwner))
.generateExpression(ktExpression)
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
@@ -1,40 +0,0 @@
/*
* 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.psi2ir.generators
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFileImpl
import org.jetbrains.kotlin.psi.KtFile
class IrFileGenerator(
private val ktFile: KtFile,
private val irFile: IrFile,
context: IrGeneratorContext,
declarationFactory: IrDeclarationFactory
) : IrDeclarationGeneratorBase(context, declarationFactory) {
override fun <D : IrDeclaration> D.register(): D =
apply { irFile.addDeclaration(this) }
fun generateFileContent() {
generateAnnotationEntries(ktFile.annotationEntries)
for (topLevelDeclaration in ktFile.declarations) {
generateMemberDeclaration(topLevelDeclaration)
}
}
}
@@ -24,13 +24,11 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.BindingContext
class IrGeneratorContext(
val inputFiles: List<KtFile>,
val irModule: IrModuleImpl,
val moduleDescriptor: ModuleDescriptor,
val bindingContext: BindingContext
) {
val moduleDescriptor: ModuleDescriptor get() = irModule.descriptor
val builtIns: KotlinBuiltIns get() = moduleDescriptor.builtIns
val sourceManager = PsiSourceManager()
val builtIns: KotlinBuiltIns get() = moduleDescriptor.builtIns
}
@@ -16,21 +16,38 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.ir.declarations.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
class IrModuleGenerator(override val context: IrGeneratorContext) : IrDeclarationGenerator {
fun generateModuleContent() {
for (ktFile in context.inputFiles) {
val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile)
class IrModuleGenerator(override val context: IrGeneratorContext) : IrGenerator {
fun generateModule(ktFiles: List<KtFile>): IrModule {
val irDeclarationGenerator = IrDeclarationGenerator(context)
val irModule = IrModuleImpl(context.moduleDescriptor)
for (ktFile in ktFiles) {
val fileEntry = context.sourceManager.getOrCreateFileEntry(ktFile)
val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile)
val fileName = fileEntry.getRecognizableName()
val irFile = IrFileImpl(fileEntry, fileName, packageFragmentDescriptor)
context.sourceManager.putFileEntry(irFile, fileEntry)
context.irModule.addFile(irFile)
val irFileElementFactory = IrDeclarationFactory()
val generator = IrFileGenerator(ktFile, irFile, context, irFileElementFactory)
generator.generateFileContent()
for (ktDeclaration in ktFile.declarations) {
val irDeclaration = irDeclarationGenerator.generateMemberDeclaration(ktDeclaration)
irFile.addDeclaration(irDeclaration)
if (irDeclaration is IrProperty) {
irDeclaration.getter?.let {
irFile.addDeclaration(it)
}
irDeclaration.setter?.let {
irFile.addDeclaration(it)
}
}
}
irModule.addFile(irFile)
}
return irModule
}
}
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.assertCast
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginKind
import org.jetbrains.kotlin.ir.declarations.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -38,7 +40,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
class IrStatementGenerator(
override val context: IrGeneratorContext,
val scopeOwner: DeclarationDescriptor,
val declarationFactory: IrLocalDeclarationsFactory
val temporaryVariableFactory: IrTemporaryVariableFactory
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
fun generateExpression(ktExpression: KtExpression): IrExpression =
@@ -58,7 +60,7 @@ class IrStatementGenerator(
val variableDescriptor = getOrFail(BindingContext.VARIABLE, property)
val irLocalVariable = declarationFactory.createLocalVariable(property, variableDescriptor)
val irLocalVariable = IrVariableImpl(property.startOffset, property.endOffset, IrDeclarationOriginKind.DEFINED, variableDescriptor)
irLocalVariable.initializer = property.initializer?.let {
it.genExpr().toExpectedType(variableDescriptor.type)
}
@@ -72,7 +74,7 @@ class IrStatementGenerator(
val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null,
hasResult = false, isDesugared = true)
val ktInitializer = multiDeclaration.initializer!!
val irTmpInitializer = declarationFactory.createTemporaryVariable(ktInitializer.genExpr())
val irTmpInitializer = temporaryVariableFactory.createTemporaryVariable(ktInitializer.genExpr())
irBlock.addStatement(irTmpInitializer)
val irCallGenerator = IrCallGenerator(this)
@@ -82,7 +84,8 @@ class IrStatementGenerator(
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
val irComponentCall = irCallGenerator.generateCall(ktEntry, componentResolvedCall, IrOperator.COMPONENT_N.withIndex(index + 1))
val irComponentVar = declarationFactory.createLocalVariable(ktEntry, componentVariable, irComponentCall)
val irComponentVar = IrVariableImpl(ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOriginKind.DEFINED,
componentVariable, irComponentCall)
irBlock.addStatement(irComponentVar)
}
@@ -0,0 +1,51 @@
/*
* 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.psi2ir.generators
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginKind
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
class IrTemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) {
private var lastTemporaryIndex = 0
private fun nextTemporaryIndex() = lastTemporaryIndex++
private fun createDescriptorForTemporaryVariable(type: KotlinType, nameHint: String? = null): IrTemporaryVariableDescriptor =
IrTemporaryVariableDescriptorImpl(
scopeOwner,
Name.identifier(
if (nameHint != null)
"tmp${nextTemporaryIndex()}\$$nameHint"
else
"tmp${nextTemporaryIndex()}"
),
type)
fun createTemporaryVariable(irExpression: IrExpression, nameHint: String? = null): IrVariable =
IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
createDescriptorForTemporaryVariable(
irExpression.type ?: throw AssertionError("No type for $irExpression"),
nameHint
),
irExpression)
}