From 7dcc8f86a50c2ffb3a7a04903ce6633604503cac Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Fri, 23 Dec 2016 13:09:39 +0700 Subject: [PATCH] backend: add files from psi2ir.builders and some from psi2ir.generators --- .../psi2ir/builders/ExpressionHelpers.kt | 135 +++++++++++++++++ .../kotlin/psi2ir/builders/IrBuilder.kt | 137 ++++++++++++++++++ .../builders/IrMemberFunctionBuilder.kt | 41 ++++++ .../kotlin/psi2ir/builders/ScopeHelpers.kt | 34 +++++ .../kotlin/psi2ir/generators/Primitives.kt | 64 ++++++++ .../kotlin/psi2ir/generators/Scope.kt | 47 ++++++ 6 files changed, 458 insertions(+) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ExpressionHelpers.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrBuilder.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrMemberFunctionBuilder.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ScopeHelpers.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Primitives.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ExpressionHelpers.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ExpressionHelpers.kt new file mode 100644 index 00000000000..867e05a5230 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ExpressionHelpers.kt @@ -0,0 +1,135 @@ +/* + * 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.builders + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.psi2ir.generators.eqeqeq +import org.jetbrains.kotlin.psi2ir.generators.primitiveOp1 +import org.jetbrains.kotlin.psi2ir.generators.primitiveOp2 +import org.jetbrains.kotlin.types.KotlinType + + +inline fun IrBuilderWithScope.irLet( + value: IrExpression, + origin: IrStatementOrigin? = null, + nameHint: String? = null, + body: (VariableDescriptor) -> IrExpression +): IrExpression { + val irTemporary = scope.createTemporaryVariable(value, nameHint) + val irResult = body(irTemporary.descriptor) + val irBlock = IrBlockImpl(startOffset, endOffset, irResult.type, origin) + irBlock.statements.add(irTemporary) + irBlock.statements.add(irResult) + return irBlock +} + +fun IrStatementsBuilder.defineTemporary(value: IrExpression, nameHint: String? = null): VariableDescriptor { + val temporary = scope.createTemporaryVariable(value, nameHint) + +temporary + return temporary.descriptor +} + +fun IrStatementsBuilder.defineTemporaryVar(value: IrExpression, nameHint: String? = null): VariableDescriptor { + val temporary = scope.createTemporaryVariable(value, nameHint, isMutable = true) + +temporary + return temporary.descriptor +} + +fun IrBuilderWithScope.irReturn(value: IrExpression) = + IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, scope.assertCastOwner(), value) + +fun IrBuilderWithScope.irReturnTrue() = + irReturn(IrConstImpl(startOffset, endOffset, context.builtIns.booleanType, IrConstKind.Boolean, true)) + +fun IrBuilderWithScope.irReturnFalse() = + irReturn(IrConstImpl(startOffset, endOffset, context.builtIns.booleanType, IrConstKind.Boolean, false)) + +fun IrBuilderWithScope.irIfThenElse(type: KotlinType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression) = + IrIfThenElseImpl(startOffset, endOffset, type, condition, thenPart, elsePart) + +fun IrBuilderWithScope.irIfNull(type: KotlinType, subject: IrExpression, thenPart: IrExpression, elsePart: IrExpression) = + irIfThenElse(type, irEqualsNull(subject), thenPart, elsePart) + +fun IrBuilderWithScope.irThrowNpe(origin: IrStatementOrigin) = + IrNullaryPrimitiveImpl(startOffset, endOffset, origin, context.irBuiltIns.throwNpe) + +fun IrBuilderWithScope.irIfThenReturnTrue(condition: IrExpression) = + IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, irReturnTrue()) + +fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) = + IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, irReturnFalse()) + +fun IrBuilderWithScope.irThis() = + scope.classOwner().let { classOwner -> + IrGetValueImpl(startOffset, endOffset, classOwner.thisAsReceiverParameter) + } + +fun IrBuilderWithScope.irGet(variable: VariableDescriptor) = + IrGetValueImpl(startOffset, endOffset, variable) + +fun IrBuilderWithScope.irSetVar(variable: VariableDescriptor, value: IrExpression) = + IrSetVariableImpl(startOffset, endOffset, variable, value, IrStatementOrigin.EQ) + +fun IrBuilderWithScope.irOther() = + irGet(scope.functionOwner().valueParameters.single()) + +fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) = + context.eqeqeq(startOffset, endOffset, arg1, arg2) + +fun IrBuilderWithScope.irNull() = + IrConstImpl.constNull(startOffset, endOffset, context.builtIns.nullableNothingType) + +fun IrBuilderWithScope.irEqualsNull(argument: IrExpression) = + primitiveOp2(startOffset, endOffset, context.irBuiltIns.eqeq, IrStatementOrigin.EQEQ, + argument, irNull()) + +fun IrBuilderWithScope.irNotEquals(arg1: IrExpression, arg2: IrExpression) = + primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNot, IrStatementOrigin.EXCLEQ, + primitiveOp2(startOffset, endOffset, context.irBuiltIns.eqeq, IrStatementOrigin.EXCLEQ, + arg1, arg2)) + +fun IrBuilderWithScope.irGet(receiver: IrExpression, property: PropertyDescriptor): IrExpression = + IrGetterCallImpl(startOffset, endOffset, property.getter!!, null, receiver, null, IrStatementOrigin.GET_PROPERTY) + +fun IrBuilderWithScope.irCall(callee: CallableDescriptor) = + IrCallImpl(startOffset, endOffset, callee.returnType!!, callee, null) + +fun IrBuilderWithScope.irCallOp(callee: CallableDescriptor, dispatchReceiver: IrExpression, argument: IrExpression) = + IrCallImpl(startOffset, endOffset, callee.returnType!!, callee, null).apply { + this.dispatchReceiver = dispatchReceiver + putValueArgument(0, argument) + } + +fun IrBuilderWithScope.irNotIs(argument: IrExpression, type: KotlinType) = + IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.booleanType, IrTypeOperator.NOT_INSTANCEOF, type, argument) + +fun IrBuilderWithScope.irAs(argument: IrExpression, type: KotlinType) = + IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, type, argument) + +fun IrBuilderWithScope.irInt(value: Int) = + IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value) + +fun IrBuilderWithScope.irString(value: String) = + IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, value) + +fun IrBuilderWithScope.irConcat() = + IrStringConcatenationImpl(startOffset, endOffset, context.builtIns.stringType) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrBuilder.kt new file mode 100644 index 00000000000..0e5d566e7d4 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrBuilder.kt @@ -0,0 +1,137 @@ +/* + * 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.builders + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.generators.Generator +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope +import org.jetbrains.kotlin.psi2ir.generators.Scope +import org.jetbrains.kotlin.types.KotlinType +import java.util.* + +abstract class IrBuilder( + override val context: GeneratorContext, + var startOffset: Int, + var endOffset: Int +) : Generator + +abstract class IrBuilderWithScope( + context: GeneratorContext, + override val scope: Scope, + startOffset: Int, + endOffset: Int +) : IrBuilder(context, startOffset, endOffset), GeneratorWithScope + +abstract class IrStatementsBuilder( + context: GeneratorContext, + scope: Scope, + startOffset: Int, + endOffset: Int +) : IrBuilderWithScope(context, scope, startOffset, endOffset), GeneratorWithScope { + operator fun IrStatement.unaryPlus() { + addStatement(this) + } + + protected abstract fun addStatement(irStatement: IrStatement) + protected abstract fun doBuild(): T +} + +open class IrBlockBodyBuilder( + context: GeneratorContext, + scope: Scope, + startOffset: Int, + endOffset: Int +) : IrStatementsBuilder(context, scope, startOffset, endOffset) { + private val irBlockBody = IrBlockBodyImpl(startOffset, endOffset) + + inline fun blockBody(body: IrBlockBodyBuilder.() -> Unit): IrBlockBody { + body() + return doBuild() + } + + override fun addStatement(irStatement: IrStatement) { + irBlockBody.statements.add(irStatement) + } + + override fun doBuild(): IrBlockBody { + return irBlockBody + } +} + +class IrBlockBuilder( + context: GeneratorContext, scope: Scope, + startOffset: Int, endOffset: Int, + val origin: IrStatementOrigin? = null, + var resultType: KotlinType? = null +) : IrStatementsBuilder(context, scope, startOffset, endOffset) { + private val statements = ArrayList() + + inline fun block(body: IrBlockBuilder.() -> Unit): IrBlock { + body() + return doBuild() + } + + override fun addStatement(irStatement: IrStatement) { + statements.add(irStatement) + } + + override fun doBuild(): IrBlock { + val resultType = this.resultType ?: + (statements.lastOrNull() as? IrExpression)?.type ?: + context.builtIns.unitType + val irBlock = IrBlockImpl(startOffset, endOffset, resultType, origin) + irBlock.statements.addAll(statements) + return irBlock + } +} + +fun T.at(startOffset: Int, endOffset: Int): T { + this.startOffset = startOffset + this.endOffset = endOffset + return this +} + +fun T.at(psiElement: PsiElement): T { + this.startOffset = psiElement.startOffset + this.endOffset = psiElement.endOffset + return this +} + +inline fun GeneratorWithScope.irBlock(ktElement: KtElement? = null, origin: IrStatementOrigin? = null, resultType: KotlinType? = null, + body: IrBlockBuilder.() -> Unit +): IrExpression = + IrBlockBuilder(context, scope, + ktElement?.startOffset ?: UNDEFINED_OFFSET, + ktElement?.endOffset ?: UNDEFINED_OFFSET, + origin, resultType + ).block(body) + +inline fun GeneratorWithScope.irBlockBody(ktElement: KtElement? = null, body: IrBlockBodyBuilder.() -> Unit) : IrBlockBody = + IrBlockBodyBuilder(context, scope, + ktElement?.startOffset ?: UNDEFINED_OFFSET, + ktElement?.endOffset ?: UNDEFINED_OFFSET + ).blockBody(body) \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrMemberFunctionBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrMemberFunctionBuilder.kt new file mode 100644 index 00000000000..7f586b6c164 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/IrMemberFunctionBuilder.kt @@ -0,0 +1,41 @@ +/* + * 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.builders + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.psi2ir.generators.Scope + +class IrMemberFunctionBuilder( + context: GeneratorContext, + val irClass: IrClassImpl, + val function: FunctionDescriptor, + val origin: IrDeclarationOrigin, + startOffset: Int = UNDEFINED_OFFSET, + endOffset: Int = UNDEFINED_OFFSET +) : IrBlockBodyBuilder(context, Scope(function), startOffset, endOffset) { + inline fun addToClass(body: IrMemberFunctionBuilder.() -> Unit) { + val irFunction = IrFunctionImpl(startOffset, endOffset, origin, function) + body() + irFunction.body = doBuild() + irClass.addMember(irFunction) + } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ScopeHelpers.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ScopeHelpers.kt new file mode 100644 index 00000000000..d62955684b6 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/builders/ScopeHelpers.kt @@ -0,0 +1,34 @@ +/* + * 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.builders + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.psi2ir.generators.Scope + +inline fun Scope.assertCastOwner() = + scopeOwner as? T ?: + throw AssertionError("Unexpected scopeOwner: $scopeOwner") + +fun Scope.functionOwner(): FunctionDescriptor = + assertCastOwner() + +fun Scope.classOwner(): ClassDescriptor = + when (scopeOwner) { + is ClassDescriptor -> scopeOwner + is MemberDescriptor -> scopeOwner.containingDeclaration as ClassDescriptor + else -> throw AssertionError("Unexpected scopeOwner: $scopeOwner") + } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Primitives.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Primitives.kt new file mode 100644 index 00000000000..fdbefdc077f --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Primitives.kt @@ -0,0 +1,64 @@ +/* + * 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.CallableDescriptor +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* + +fun primitiveOp1(startOffset: Int, endOffset: Int, primitiveOpDescriptor: CallableDescriptor, origin: IrStatementOrigin, + argument: IrExpression): IrExpression = + IrUnaryPrimitiveImpl(startOffset, endOffset, origin, primitiveOpDescriptor, argument) + +fun primitiveOp2(startOffset: Int, endOffset: Int, primitiveOpDescriptor: CallableDescriptor, origin: IrStatementOrigin, + argument1: IrExpression, argument2: IrExpression): IrExpression = + IrBinaryPrimitiveImpl(startOffset, endOffset, origin, primitiveOpDescriptor, argument1, argument2) + +fun GeneratorContext.constNull(startOffset: Int, endOffset: Int): IrExpression = + IrConstImpl.constNull(startOffset, endOffset, builtIns.nullableNothingType) + +fun GeneratorContext.equalsNull(startOffset: Int, endOffset: Int, argument: IrExpression): IrExpression = + primitiveOp2(startOffset, endOffset, irBuiltIns.eqeq, IrStatementOrigin.EQEQ, + argument, constNull(startOffset, endOffset)) + +fun GeneratorContext.eqeqeq(startOffset: Int, endOffset: Int, argument1: IrExpression, argument2: IrExpression): IrExpression = + primitiveOp2(startOffset, endOffset, irBuiltIns.eqeqeq, IrStatementOrigin.EQEQEQ, argument1, argument2) + +fun GeneratorContext.throwNpe(startOffset: Int, endOffset: Int, origin: IrStatementOrigin): IrExpression = + IrNullaryPrimitiveImpl(startOffset, endOffset, origin, irBuiltIns.throwNpe) + +// a || b == if (a) true else b +fun GeneratorContext.oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.OROR): IrWhen = + IrIfThenElseImpl(startOffset, endOffset, builtIns.booleanType, + a, IrConstImpl.constTrue(b.startOffset, b.endOffset, b.type), b, + origin) + +fun GeneratorContext.oror(a: IrExpression, b: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.OROR): IrWhen = + oror(b.startOffset, b.endOffset, a, b, origin) + +fun GeneratorContext.whenComma(a: IrExpression, b: IrExpression): IrWhen = + oror(a, b, IrStatementOrigin.WHEN_COMMA) + +// a && b == if (a) b else false +fun GeneratorContext.andand(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.ANDAND): IrWhen = + IrIfThenElseImpl(startOffset, endOffset, builtIns.booleanType, + a, b, IrConstImpl.constFalse(b.startOffset, b.endOffset, b.type), + origin) + +fun GeneratorContext.andand(a: IrExpression, b: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.ANDAND): IrWhen = + andand(b.startOffset, b.endOffset, a, b, origin) \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt new file mode 100644 index 00000000000..8f35c03c992 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt @@ -0,0 +1,47 @@ +/* + * 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.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.impl.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 Scope(val scopeOwner: DeclarationDescriptor) { + private var lastTemporaryIndex: Int = 0 + private fun nextTemporaryIndex(): Int = lastTemporaryIndex++ + + private fun createDescriptorForTemporaryVariable(type: KotlinType, nameHint: String? = null, isMutable: Boolean = false): IrTemporaryVariableDescriptor = + IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier(getNameForTemporary(nameHint)), type, isMutable) + + private fun getNameForTemporary(nameHint: String?): String { + val index = nextTemporaryIndex() + return if (nameHint != null) "tmp${index}_$nameHint" else "tmp$index" + } + + fun createTemporaryVariable(irExpression: IrExpression, nameHint: String? = null, isMutable: Boolean = false): IrVariable = + IrVariableImpl( + irExpression.startOffset, irExpression.endOffset, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, + createDescriptorForTemporaryVariable(irExpression.type, nameHint, isMutable), + irExpression + ) +}