Make IrScript a statement container first, update JS support
The IrScript is now the IrStatementContainer with significant statements order, and the code is adapted accordingly
This commit is contained in:
@@ -17,9 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformSubsetFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -111,11 +114,6 @@ private class DeclarationContainerLoweringVisitor(
|
|||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
loweringPass.lower(declaration)
|
loweringPass.lower(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitScript(declaration: IrScript) {
|
|
||||||
declaration.acceptChildrenVoid(this)
|
|
||||||
loweringPass.lower(declaration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BodyLoweringPass.runOnFilePostfix(
|
fun BodyLoweringPass.runOnFilePostfix(
|
||||||
@@ -160,11 +158,8 @@ private class BodyLoweringVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitScript(declaration: IrScript, data: IrDeclaration?) {
|
override fun visitScript(declaration: IrScript, data: IrDeclaration?) {
|
||||||
ArrayList(declaration.declarations).forEach { it.accept(this, declaration) }
|
|
||||||
if (withLocalDeclarations) {
|
|
||||||
declaration.statements.forEach { it.accept(this, null) }
|
|
||||||
}
|
|
||||||
declaration.thisReceiver.accept(this, declaration)
|
declaration.thisReceiver.accept(this, declaration)
|
||||||
|
ArrayList(declaration.statements).forEach { it.accept(this, declaration) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,22 +209,26 @@ interface DeclarationTransformer : FileLoweringPass {
|
|||||||
|
|
||||||
val visitor = this
|
val visitor = this
|
||||||
|
|
||||||
|
fun IrDeclaration.replaceInContainer(container: MutableList<in IrDeclaration>, result: List<IrDeclaration>): Boolean {
|
||||||
|
var index = container.indexOf(this)
|
||||||
|
if (index == -1) {
|
||||||
|
index = container.indexOf(declaration)
|
||||||
|
} else {
|
||||||
|
container.removeAt(index)
|
||||||
|
--index
|
||||||
|
}
|
||||||
|
return container.addAll(index + 1, result)
|
||||||
|
}
|
||||||
|
|
||||||
fun IrDeclaration.transform() {
|
fun IrDeclaration.transform() {
|
||||||
|
|
||||||
acceptVoid(visitor)
|
acceptVoid(visitor)
|
||||||
|
|
||||||
val result = transformer.transformFlatRestricted(this)
|
val result = transformer.transformFlatRestricted(this)
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
(parent as? IrDeclarationContainer)?.let {
|
when (val parentCopy = parent) {
|
||||||
var index = it.declarations.indexOf(this)
|
is IrDeclarationContainer -> replaceInContainer(parentCopy.declarations, result)
|
||||||
if (index == -1) {
|
is IrStatementContainer -> replaceInContainer(parentCopy.statements, result)
|
||||||
index = it.declarations.indexOf(declaration)
|
|
||||||
} else {
|
|
||||||
it.declarations.removeAt(index)
|
|
||||||
--index
|
|
||||||
}
|
|
||||||
|
|
||||||
it.declarations.addAll(index + 1, result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,12 +247,12 @@ interface DeclarationTransformer : FileLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitScript(declaration: IrScript) {
|
override fun visitScript(declaration: IrScript) {
|
||||||
ArrayList(declaration.declarations).forEach { it.accept(this, null) }
|
ArrayList(declaration.statements).forEach {
|
||||||
declaration.declarations.transformFlat(transformer::transformFlatRestricted)
|
if (transformer.withLocalDeclarations || it is IrDeclaration) {
|
||||||
|
it.accept(this, null)
|
||||||
if (transformer.withLocalDeclarations) {
|
}
|
||||||
declaration.statements.forEach { it.accept(this, null) }
|
|
||||||
}
|
}
|
||||||
|
declaration.statements.transformSubsetFlat(transformer::transformFlatRestricted)
|
||||||
|
|
||||||
declaration.thisReceiver.accept(this, null)
|
declaration.thisReceiver.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-10
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.ir.addChild
|
import org.jetbrains.kotlin.backend.common.ir.addChild
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.setDeclarationsParent
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -22,8 +24,12 @@ open class LocalClassPopupLowering(val context: BackendContext) : BodyLoweringPa
|
|||||||
runOnFilePostfix(irFile, withLocalDeclarations = true, allowDeclarationModification = true)
|
runOnFilePostfix(irFile, withLocalDeclarations = true, allowDeclarationModification = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class ExtractedLocalClass(
|
||||||
|
val local: IrClass, val newContainer: IrDeclarationParent, val extractedUnder: IrStatement?
|
||||||
|
)
|
||||||
|
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
val extractedLocalClasses = arrayListOf<Pair<IrClass, IrDeclarationContainer>>()
|
val extractedLocalClasses = arrayListOf<ExtractedLocalClass>()
|
||||||
|
|
||||||
irBody.transform(object : IrElementTransformerVoidWithContext() {
|
irBody.transform(object : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
@@ -32,22 +38,46 @@ open class LocalClassPopupLowering(val context: BackendContext) : BodyLoweringPa
|
|||||||
if (allScopes.size > 1) allScopes[allScopes.lastIndex - 1] else createScope(container as IrSymbolOwner)
|
if (allScopes.size > 1) allScopes[allScopes.lastIndex - 1] else createScope(container as IrSymbolOwner)
|
||||||
if (!shouldPopUp(declaration, currentScope)) return declaration
|
if (!shouldPopUp(declaration, currentScope)) return declaration
|
||||||
|
|
||||||
val newContainer = run {
|
var extractedUnder: IrStatement? = declaration
|
||||||
var currentParent = declaration.parent
|
var newContainer = declaration.parent
|
||||||
while (currentParent is IrDeclaration && currentParent !is IrClass && currentParent !is IrScript) {
|
while (newContainer is IrDeclaration && newContainer !is IrClass && newContainer !is IrScript) {
|
||||||
currentParent = currentParent.parent
|
extractedUnder = newContainer
|
||||||
|
newContainer = newContainer.parent
|
||||||
|
}
|
||||||
|
when (newContainer) {
|
||||||
|
is IrStatementContainer -> {
|
||||||
|
// TODO: check if it is the correct behavior
|
||||||
|
if (extractedUnder == declaration) {
|
||||||
|
extractedUnder = (newContainer.statements.indexOf(extractedUnder) + 1)
|
||||||
|
.takeIf { it > 0 && it < newContainer.statements.size }
|
||||||
|
?.let { newContainer.statements[it] }
|
||||||
|
}
|
||||||
|
extractedLocalClasses.add(ExtractedLocalClass(declaration, newContainer, extractedUnder))
|
||||||
}
|
}
|
||||||
|
is IrDeclarationContainer -> extractedLocalClasses.add(ExtractedLocalClass(declaration, newContainer, extractedUnder))
|
||||||
currentParent as IrDeclarationContainer // IrClass or IrScript or IrPackageFragment
|
else -> error("Inexpected container type $newContainer")
|
||||||
}
|
}
|
||||||
|
|
||||||
extractedLocalClasses.add(declaration to newContainer)
|
|
||||||
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
|
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
|
||||||
}
|
}
|
||||||
}, null)
|
}, null)
|
||||||
|
|
||||||
for ((local, newContainer) in extractedLocalClasses) {
|
for ((local, newContainer, extractedUnder) in extractedLocalClasses) {
|
||||||
newContainer.addChild(local)
|
when (newContainer) {
|
||||||
|
is IrStatementContainer -> {
|
||||||
|
val insertIndex = extractedUnder?.let { newContainer.statements.indexOf(it) } ?: -1
|
||||||
|
if (insertIndex >= 0) {
|
||||||
|
newContainer.statements.add(insertIndex, local)
|
||||||
|
} else {
|
||||||
|
newContainer.statements.add(local)
|
||||||
|
}
|
||||||
|
local.setDeclarationsParent(newContainer)
|
||||||
|
}
|
||||||
|
is IrDeclarationContainer -> {
|
||||||
|
newContainer.addChild(local)
|
||||||
|
}
|
||||||
|
else -> error("Inexpected container type $newContainer")
|
||||||
|
}
|
||||||
|
|
||||||
local.acceptVoid(object : IrElementVisitorVoid {
|
local.acceptVoid(object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
|
|||||||
+7
-1
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -162,6 +162,12 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
|||||||
return super.visitEnumEntry(declaration)
|
return super.visitEnumEntry(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitScript(declaration: IrScript): IrStatement {
|
||||||
|
withBuilder(declaration.symbol) {
|
||||||
|
return super.visitScript(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
||||||
|
|||||||
-4
@@ -117,10 +117,6 @@ class BlockDecomposerTransformer(
|
|||||||
function = declaration
|
function = declaration
|
||||||
|
|
||||||
with(declaration) {
|
with(declaration) {
|
||||||
val transformedDeclarations = declarations.map { it.transform(statementTransformer, null) as IrDeclaration }
|
|
||||||
declarations.clear()
|
|
||||||
declarations.addAll(transformedDeclarations)
|
|
||||||
|
|
||||||
val transformedStatements = mutableListOf<IrStatement>()
|
val transformedStatements = mutableListOf<IrStatement>()
|
||||||
statements.forEach {
|
statements.forEach {
|
||||||
val transformer = if (it === statements.last()) expressionTransformer else statementTransformer
|
val transformer = if (it === statements.last()) expressionTransformer else statementTransformer
|
||||||
|
|||||||
+8
-5
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweri
|
|||||||
private fun lower(irScript: IrScript): List<IrDeclaration> {
|
private fun lower(irScript: IrScript): List<IrDeclaration> {
|
||||||
val (startOffset, endOffset) = getFunctionBodyOffsets(irScript)
|
val (startOffset, endOffset) = getFunctionBodyOffsets(irScript)
|
||||||
|
|
||||||
val initializeStatements = irScript.declarations
|
val initializeStatements = irScript.statements
|
||||||
.filterIsInstance<IrProperty>()
|
.filterIsInstance<IrProperty>()
|
||||||
.mapNotNull { it.backingField }
|
.mapNotNull { it.backingField }
|
||||||
.filter { it.initializer != null }
|
.filter { it.initializer != null }
|
||||||
@@ -55,14 +56,16 @@ class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweri
|
|||||||
it.body = it.factory.createBlockBody(
|
it.body = it.factory.createBlockBody(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
irScript.statements.prepareForEvaluateScriptFunction(it)
|
irScript.statements.filter { it !is IrDeclaration }.prepareForEvaluateScriptFunction(it)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
with(irScript) {
|
with(irScript) {
|
||||||
declarations += initializeScriptFunction
|
statements.removeIf { it !is IrDeclaration }
|
||||||
declarations += evaluateScriptFunction
|
statements += initializeScriptFunction
|
||||||
statements.clear()
|
initializeScriptFunction.patchDeclarationParents(this)
|
||||||
|
statements += evaluateScriptFunction
|
||||||
|
evaluateScriptFunction.patchDeclarationParents(this)
|
||||||
statements += createCall(initializeScriptFunction)
|
statements += createCall(initializeScriptFunction)
|
||||||
statements += createCall(evaluateScriptFunction)
|
statements += createCall(evaluateScriptFunction)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -152,7 +152,7 @@ class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLowe
|
|||||||
|
|
||||||
script.transformChildrenVoid(transformer)
|
script.transformChildrenVoid(transformer)
|
||||||
|
|
||||||
script.declarations.forEach {
|
script.statements.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrSimpleFunction -> it.dispatchReceiverParameter = null
|
is IrSimpleFunction -> it.dispatchReceiverParameter = null
|
||||||
is IrProperty -> {
|
is IrProperty -> {
|
||||||
|
|||||||
+12
-1
@@ -29,8 +29,19 @@ class StaticMembersLowering(val context: JsIrBackendContext) : DeclarationTransf
|
|||||||
if (declaration.isExported(context)) {
|
if (declaration.isExported(context)) {
|
||||||
context.additionalExportedDeclarations.add(declaration)
|
context.additionalExportedDeclarations.add(declaration)
|
||||||
}
|
}
|
||||||
|
var extractedUnder = declaration
|
||||||
|
var newContainer = declaration.parent
|
||||||
|
while (newContainer is IrDeclaration && newContainer != irClass.file) {
|
||||||
|
extractedUnder = newContainer
|
||||||
|
newContainer = newContainer.parent
|
||||||
|
}
|
||||||
|
val insertBefore = irClass.file.declarations.indexOf(extractedUnder)
|
||||||
|
if (insertBefore >= 0) {
|
||||||
|
irClass.file.declarations.add(insertBefore, declaration)
|
||||||
|
} else {
|
||||||
|
irClass.file.declarations += declaration
|
||||||
|
}
|
||||||
declaration.parent = irClass.file
|
declaration.parent = irClass.file
|
||||||
irClass.file.declarations += declaration
|
|
||||||
return listOf()
|
return listOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -52,8 +52,11 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatemen
|
|||||||
|
|
||||||
override fun visitScript(irScript: IrScript, context: JsGenerationContext): JsStatement {
|
override fun visitScript(irScript: IrScript, context: JsGenerationContext): JsStatement {
|
||||||
return JsGlobalBlock().apply {
|
return JsGlobalBlock().apply {
|
||||||
statements += irScript.declarations.map { it.accept(this@IrDeclarationToJsTransformer, context) }
|
irScript.statements.forEach {
|
||||||
statements += irScript.statements.map { it.accept(IrElementToJsStatementTransformer(), context) }
|
statements +=
|
||||||
|
if (it is IrDeclaration) it.accept(this@IrDeclarationToJsTransformer, context)
|
||||||
|
else it.accept(IrElementToJsStatementTransformer(), context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,10 +186,12 @@ class NameTables(
|
|||||||
for (declaration in p.declarations) {
|
for (declaration in p.declarations) {
|
||||||
generateNamesForTopLevelDecl(declaration)
|
generateNamesForTopLevelDecl(declaration)
|
||||||
if (declaration is IrScript) {
|
if (declaration is IrScript) {
|
||||||
for (memberDecl in declaration.declarations) {
|
for (memberDecl in declaration.statements) {
|
||||||
generateNamesForTopLevelDecl(memberDecl)
|
if (memberDecl is IrDeclaration) {
|
||||||
if (memberDecl is IrClass) {
|
generateNamesForTopLevelDecl(memberDecl)
|
||||||
classDeclaration += memberDecl
|
if (memberDecl is IrClass) {
|
||||||
|
classDeclaration += memberDecl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -100,7 +100,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
|
|
||||||
fun generatePropertyAccessor(
|
fun generatePropertyAccessor(
|
||||||
descriptor: PropertyAccessorDescriptor,
|
descriptor: PropertyAccessorDescriptor,
|
||||||
ktProperty: KtProperty,
|
ktProperty: KtVariableDeclaration,
|
||||||
ktAccessor: KtPropertyAccessor?
|
ktAccessor: KtPropertyAccessor?
|
||||||
): IrSimpleFunction =
|
): IrSimpleFunction =
|
||||||
declareSimpleFunctionInner(
|
declareSimpleFunctionInner(
|
||||||
@@ -121,9 +121,9 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
|
|
||||||
fun generateDefaultAccessorForPrimaryConstructorParameter(
|
fun generateDefaultAccessorForPrimaryConstructorParameter(
|
||||||
descriptor: PropertyAccessorDescriptor,
|
descriptor: PropertyAccessorDescriptor,
|
||||||
ktParameter: KtParameter
|
ktElement: KtElement
|
||||||
): IrSimpleFunction =
|
): IrSimpleFunction =
|
||||||
declareSimpleFunctionInner(descriptor, ktParameter, IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR).buildWithScope { irAccessor ->
|
declareSimpleFunctionInner(descriptor, ktElement, IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR).buildWithScope { irAccessor ->
|
||||||
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.typeParameters)
|
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.typeParameters)
|
||||||
irAccessor.returnType = descriptor.returnType!!.toIrType()
|
irAccessor.returnType = descriptor.returnType!!.toIrType()
|
||||||
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irAccessor)
|
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irAccessor)
|
||||||
|
|||||||
+58
-21
@@ -16,10 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
@@ -41,38 +42,74 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
generateSimpleProperty(ktProperty, propertyDescriptor)
|
generateSimpleProperty(ktProperty, propertyDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateDestructuringDeclarationEntryAsPropertyDeclaration(ktEntry: KtDestructuringDeclarationEntry, entryInitializer: IrExpression): IrProperty {
|
||||||
|
val propertyDescriptor = getPropertyDescriptor(ktEntry)
|
||||||
|
return context.symbolTable.declareProperty(
|
||||||
|
ktEntry.startOffsetSkippingComments, ktEntry.endOffset,
|
||||||
|
IrDeclarationOrigin.DEFINED,
|
||||||
|
propertyDescriptor,
|
||||||
|
isDelegated = false
|
||||||
|
).buildWithScope { irProperty ->
|
||||||
|
irProperty.backingField = generatePropertyBackingField(ktEntry, propertyDescriptor) { null }
|
||||||
|
|
||||||
|
irProperty.getter = generateGetterIfRequired(ktEntry, propertyDescriptor)
|
||||||
|
irProperty.setter = generateSetterIfRequired(ktEntry, propertyDescriptor)
|
||||||
|
|
||||||
|
irProperty.linkCorrespondingPropertySymbol()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter, irValueParameter: IrValueParameter): IrDeclaration {
|
fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter, irValueParameter: IrValueParameter): IrDeclaration {
|
||||||
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
|
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
|
||||||
|
return generateSyntheticProperty(ktParameter, propertyDescriptor, irValueParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateSyntheticProperty(
|
||||||
|
ktDeclarationContainer: KtElement, propertyDescriptor: PropertyDescriptor,
|
||||||
|
irValueParameter: IrValueParameter?, generateSyntheticAccessors: Boolean = false
|
||||||
|
): IrProperty {
|
||||||
val irPropertyType = propertyDescriptor.type.toIrType()
|
val irPropertyType = propertyDescriptor.type.toIrType()
|
||||||
return context.symbolTable.declareProperty(
|
return context.symbolTable.declareProperty(
|
||||||
ktParameter.startOffsetSkippingComments, ktParameter.endOffset,
|
ktDeclarationContainer.startOffsetSkippingComments, ktDeclarationContainer.endOffset,
|
||||||
IrDeclarationOrigin.DEFINED,
|
IrDeclarationOrigin.DEFINED,
|
||||||
propertyDescriptor,
|
propertyDescriptor,
|
||||||
isDelegated = false
|
isDelegated = false
|
||||||
).also { irProperty ->
|
).also { irProperty ->
|
||||||
irProperty.backingField =
|
irProperty.backingField =
|
||||||
generatePropertyBackingField(ktParameter, propertyDescriptor) {
|
generatePropertyBackingField(ktDeclarationContainer, propertyDescriptor) {
|
||||||
context.irFactory.createExpressionBody(
|
if (irValueParameter == null) null
|
||||||
IrGetValueImpl(
|
else {
|
||||||
ktParameter.startOffsetSkippingComments, ktParameter.endOffset,
|
context.irFactory.createExpressionBody(
|
||||||
irPropertyType,
|
IrGetValueImpl(
|
||||||
irValueParameter.symbol,
|
ktDeclarationContainer.startOffsetSkippingComments, ktDeclarationContainer.endOffset,
|
||||||
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
irPropertyType,
|
||||||
|
irValueParameter.symbol,
|
||||||
|
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val getter = propertyDescriptor.getter
|
val getter = propertyDescriptor.getter
|
||||||
?: throw AssertionError("Property declared in primary constructor has no getter: $propertyDescriptor")
|
?: if (generateSyntheticAccessors)
|
||||||
|
// TODO: check if this is the correct way to generate synthetic accessor
|
||||||
|
PropertyGetterDescriptorImpl(
|
||||||
|
propertyDescriptor,
|
||||||
|
Annotations.EMPTY, Modality.FINAL, DescriptorVisibilities.PUBLIC, false, false, false,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED, null, propertyDescriptor.source
|
||||||
|
).apply {
|
||||||
|
initialize(propertyDescriptor.type)
|
||||||
|
}
|
||||||
|
else throw AssertionError("Property declared in primary constructor has no getter: $propertyDescriptor")
|
||||||
irProperty.getter =
|
irProperty.getter =
|
||||||
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(getter, ktParameter)
|
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(getter, ktDeclarationContainer)
|
||||||
|
|
||||||
if (propertyDescriptor.isVar) {
|
if (propertyDescriptor.isVar) {
|
||||||
val setter = propertyDescriptor.setter
|
val setter = propertyDescriptor.setter
|
||||||
|
// TODO: implement setter descriptor generation, if needed
|
||||||
?: throw AssertionError("Property declared in primary constructor has no setter: $propertyDescriptor")
|
?: throw AssertionError("Property declared in primary constructor has no setter: $propertyDescriptor")
|
||||||
irProperty.setter =
|
irProperty.setter =
|
||||||
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(setter, ktParameter)
|
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(setter, ktDeclarationContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
irProperty.linkCorrespondingPropertySymbol()
|
irProperty.linkCorrespondingPropertySymbol()
|
||||||
@@ -105,7 +142,7 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
private fun PropertyDescriptor.actuallyHasBackingField(bindingContext: BindingContext) =
|
private fun PropertyDescriptor.actuallyHasBackingField(bindingContext: BindingContext) =
|
||||||
hasBackingField(bindingContext) || context.extensions.isPropertyWithPlatformField(this)
|
hasBackingField(bindingContext) || context.extensions.isPropertyWithPlatformField(this)
|
||||||
|
|
||||||
private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty =
|
private fun generateSimpleProperty(ktProperty: KtVariableDeclaration, propertyDescriptor: PropertyDescriptor): IrProperty =
|
||||||
context.symbolTable.declareProperty(
|
context.symbolTable.declareProperty(
|
||||||
ktProperty.startOffsetSkippingComments, ktProperty.endOffset,
|
ktProperty.startOffsetSkippingComments, ktProperty.endOffset,
|
||||||
IrDeclarationOrigin.DEFINED,
|
IrDeclarationOrigin.DEFINED,
|
||||||
@@ -154,18 +191,18 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateGetterIfRequired(ktProperty: KtProperty, property: PropertyDescriptor): IrSimpleFunction? {
|
private fun generateGetterIfRequired(ktProperty: KtVariableDeclaration, property: PropertyDescriptor): IrSimpleFunction? {
|
||||||
val getter = property.getter ?: return null
|
val getter = property.getter ?: return null
|
||||||
return FunctionGenerator(declarationGenerator).generatePropertyAccessor(getter, ktProperty, ktProperty.getter)
|
return FunctionGenerator(declarationGenerator).generatePropertyAccessor(getter, ktProperty, (ktProperty as? KtProperty)?.getter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSetterIfRequired(ktProperty: KtProperty, property: PropertyDescriptor): IrSimpleFunction? {
|
private fun generateSetterIfRequired(ktProperty: KtVariableDeclaration, property: PropertyDescriptor): IrSimpleFunction? {
|
||||||
if (!property.isVar) return null
|
if (!property.isVar) return null
|
||||||
val setter = property.setter ?: return null
|
val setter = property.setter ?: return null
|
||||||
return FunctionGenerator(declarationGenerator).generatePropertyAccessor(setter, ktProperty, ktProperty.setter)
|
return FunctionGenerator(declarationGenerator).generatePropertyAccessor(setter, ktProperty, (ktProperty as? KtProperty)?.setter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPropertyDescriptor(ktProperty: KtProperty): PropertyDescriptor {
|
private fun getPropertyDescriptor(ktProperty: KtVariableDeclaration): PropertyDescriptor {
|
||||||
val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty)
|
val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty)
|
||||||
return variableDescriptor as? PropertyDescriptor ?: TODO("not a property: $variableDescriptor")
|
return variableDescriptor as? PropertyDescriptor ?: TODO("not a property: $variableDescriptor")
|
||||||
}
|
}
|
||||||
|
|||||||
+117
-13
@@ -5,14 +5,36 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.assertCast
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.builders.declarations.IrFunctionBuilder
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.WrappedFunctionDescriptorWithContainerSource
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.varargElementType
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
|
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
|
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||||
|
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||||
|
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||||
|
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||||
|
|
||||||
class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
||||||
fun generateScriptDeclaration(ktScript: KtScript): IrDeclaration? {
|
fun generateScriptDeclaration(ktScript: KtScript): IrDeclaration? {
|
||||||
@@ -29,20 +51,102 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
|||||||
val startOffset = ktScript.pureStartOffset
|
val startOffset = ktScript.pureStartOffset
|
||||||
val endOffset = ktScript.pureEndOffset
|
val endOffset = ktScript.pureEndOffset
|
||||||
|
|
||||||
irScript.thisReceiver = context.symbolTable.declareValueParameter(
|
fun makeReceiver(descriptor: ClassDescriptor): IrValueParameter {
|
||||||
startOffset, endOffset,
|
val receiverParameterDescriptor = descriptor.thisAsReceiverParameter
|
||||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
return context.symbolTable.declareValueParameter(
|
||||||
descriptor.thisAsReceiverParameter,
|
startOffset, endOffset,
|
||||||
descriptor.thisAsReceiverParameter.type.toIrType()
|
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||||
).also { it.parent = irScript }
|
receiverParameterDescriptor,
|
||||||
|
receiverParameterDescriptor.type.toIrType()
|
||||||
|
).also { it.parent = irScript }
|
||||||
|
}
|
||||||
|
|
||||||
|
irScript.thisReceiver = makeReceiver(descriptor)
|
||||||
|
|
||||||
for (d in ktScript.declarations) {
|
for (d in ktScript.declarations) {
|
||||||
if (d is KtScriptInitializer) irScript.statements += BodyGenerator(
|
when (d) {
|
||||||
irScript.symbol,
|
is KtScriptInitializer -> {
|
||||||
context
|
irScript.statements += BodyGenerator(
|
||||||
).generateExpressionBody(d.body!!).expression
|
irScript.symbol,
|
||||||
else irScript.declarations += declarationGenerator.generateMemberDeclaration(d)!!
|
context
|
||||||
|
).generateExpressionBody(d.body!!).expression
|
||||||
|
}
|
||||||
|
is KtDestructuringDeclaration -> {
|
||||||
|
// copied with modifications from StatementGenerator.visitDestructuringDeclaration
|
||||||
|
// TODO: consider code deduplication
|
||||||
|
val bodyGenerator = BodyGenerator(irScript.symbol, context)
|
||||||
|
val statementGenerator = bodyGenerator.createStatementGenerator()
|
||||||
|
val irBlock = IrCompositeImpl(
|
||||||
|
d.startOffsetSkippingComments, d.endOffset,
|
||||||
|
context.irBuiltIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION
|
||||||
|
)
|
||||||
|
val ktInitializer = d.initializer!!
|
||||||
|
val initializerExpr = ktInitializer.deparenthesize().accept(statementGenerator, null).assertCast<IrExpression>()
|
||||||
|
val containerValue =
|
||||||
|
statementGenerator.scope.createTemporaryVariableInBlock(context, initializerExpr, irBlock, "container")
|
||||||
|
|
||||||
|
val callGenerator = CallGenerator(statementGenerator)
|
||||||
|
|
||||||
|
for ((index, ktEntry) in d.entries.withIndex()) {
|
||||||
|
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
||||||
|
|
||||||
|
val componentSubstitutedCall = statementGenerator.pregenerateCall(componentResolvedCall)
|
||||||
|
componentSubstitutedCall.setExplicitReceiverValue(containerValue)
|
||||||
|
|
||||||
|
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
|
||||||
|
|
||||||
|
// componentN for '_' SHOULD NOT be evaluated
|
||||||
|
if (componentVariable.name.isSpecial || ktEntry.isSingleUnderscore) continue
|
||||||
|
|
||||||
|
val irComponentCall = callGenerator.generateCall(
|
||||||
|
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, componentSubstitutedCall,
|
||||||
|
IrStatementOrigin.COMPONENT_N.withIndex(index + 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
val irComponentProperty =
|
||||||
|
PropertyGenerator(declarationGenerator).generateDestructuringDeclarationEntryAsPropertyDeclaration(
|
||||||
|
ktEntry, irComponentCall
|
||||||
|
)
|
||||||
|
val irComponentBackingField = irComponentProperty.backingField!!
|
||||||
|
|
||||||
|
irScript.statements += irComponentProperty
|
||||||
|
|
||||||
|
val irComponentInitializer = IrSetFieldImpl(
|
||||||
|
ktEntry.startOffsetSkippingComments, ktEntry.endOffset,
|
||||||
|
irComponentBackingField.symbol,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
|
origin = null, superQualifierSymbol = null
|
||||||
|
).apply {
|
||||||
|
value = irComponentCall
|
||||||
|
receiver = IrGetValueImpl(
|
||||||
|
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, irScript.thisReceiver.symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
irBlock.statements.add(irComponentInitializer)
|
||||||
|
}
|
||||||
|
irScript.statements += irBlock
|
||||||
|
}
|
||||||
|
else -> irScript.statements += declarationGenerator.generateMemberDeclaration(d)!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor.resultValue?.let { resultDescriptor ->
|
||||||
|
// TODO: initializer
|
||||||
|
// TODO: do not keet direct link
|
||||||
|
val resultProperty =
|
||||||
|
PropertyGenerator(declarationGenerator)
|
||||||
|
.generateSyntheticProperty(ktScript, resultDescriptor, null, generateSyntheticAccessors = true)
|
||||||
|
resultProperty.origin = IrDeclarationOrigin.SCRIPT_RESULT_PROPERTY
|
||||||
|
irScript.statements += resultProperty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ParameterDescriptor.toIrValueParameter(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin) =
|
||||||
|
context.symbolTable.declareValueParameter(
|
||||||
|
startOffset, endOffset, origin,
|
||||||
|
this,
|
||||||
|
type.toIrType(),
|
||||||
|
varargElementType?.toIrType()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.declarations
|
package org.jetbrains.kotlin.ir.declarations
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||||
|
|
||||||
//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class
|
//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class
|
||||||
//NOTE: declarations and statements stored separately
|
//NOTE: declarations and statements stored separately
|
||||||
abstract class IrScript :
|
abstract class IrScript :
|
||||||
IrDeclarationBase(), IrSymbolDeclaration<IrScriptSymbol>, IrDeclarationContainer, IrDeclarationWithName, IrDeclarationParent {
|
IrDeclarationBase(), IrSymbolDeclaration<IrScriptSymbol>, IrDeclarationWithName,
|
||||||
abstract val statements: MutableList<IrStatement>
|
IrDeclarationParent, IrStatementContainer {
|
||||||
|
|
||||||
// NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver
|
// NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver
|
||||||
abstract var thisReceiver: IrValueParameter
|
abstract var thisReceiver: IrValueParameter
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
|
||||||
private val SCRIPT_ORIGIN = object : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE") {}
|
private val SCRIPT_ORIGIN = object : IrDeclarationOriginImpl("SCRIPT") {}
|
||||||
|
|
||||||
class IrScriptImpl(
|
class IrScriptImpl(
|
||||||
override val symbol: IrScriptSymbol,
|
override val symbol: IrScriptSymbol,
|
||||||
@@ -38,7 +38,6 @@ class IrScriptImpl(
|
|||||||
|
|
||||||
override var annotations: List<IrConstructorCall> = SmartList()
|
override var annotations: List<IrConstructorCall> = SmartList()
|
||||||
|
|
||||||
override val declarations: MutableList<IrDeclaration> = mutableListOf()
|
|
||||||
override val statements: MutableList<IrStatement> = mutableListOf()
|
override val statements: MutableList<IrStatement> = mutableListOf()
|
||||||
|
|
||||||
override lateinit var thisReceiver: IrValueParameter
|
override lateinit var thisReceiver: IrValueParameter
|
||||||
@@ -59,13 +58,11 @@ class IrScriptImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||||
declarations.forEach { it.accept(visitor, data) }
|
|
||||||
statements.forEach { it.accept(visitor, data) }
|
statements.forEach { it.accept(visitor, data) }
|
||||||
thisReceiver.accept(visitor, data)
|
thisReceiver.accept(visitor, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||||
declarations.transformInPlace(transformer, data)
|
|
||||||
statements.transformInPlace(transformer, data)
|
statements.transformInPlace(transformer, data)
|
||||||
thisReceiver = thisReceiver.transform(transformer, data)
|
thisReceiver = thisReceiver.transform(transformer, data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,10 +117,9 @@ open class DeepCopyIrTreeWithSymbols(
|
|||||||
//TODO: something may go wrong, because expected using symbolRemapper
|
//TODO: something may go wrong, because expected using symbolRemapper
|
||||||
IrScriptSymbolImpl(declaration.descriptor as ScriptDescriptor),
|
IrScriptSymbolImpl(declaration.descriptor as ScriptDescriptor),
|
||||||
declaration.name
|
declaration.name
|
||||||
).also {
|
).also { scriptCopy ->
|
||||||
it.thisReceiver = declaration.thisReceiver.transform()
|
scriptCopy.thisReceiver = declaration.thisReceiver.transform()
|
||||||
declaration.transformDeclarationsTo(it)
|
declaration.statements.mapTo(scriptCopy.statements) { it.transform() }
|
||||||
it.statements.addAll(declaration.statements.map { it.transform() })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ private tailrec fun erase(type: IrType): IrClass? {
|
|||||||
|
|
||||||
return when (classifier) {
|
return when (classifier) {
|
||||||
is IrClassSymbol -> classifier.owner
|
is IrClassSymbol -> classifier.owner
|
||||||
|
is IrScriptSymbol -> null // TODO: check if correct
|
||||||
is IrTypeParameterSymbol -> erase(classifier.owner.superTypes.first())
|
is IrTypeParameterSymbol -> erase(classifier.owner.superTypes.first())
|
||||||
else -> error(classifier)
|
else -> error(classifier)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,19 +46,42 @@ inline fun <T> MutableList<T>.transformFlat(transformation: (T) -> List<T>?) {
|
|||||||
while (i < size) {
|
while (i < size) {
|
||||||
val item = get(i)
|
val item = get(i)
|
||||||
|
|
||||||
val transformed = transformation(item)
|
i = replaceInPlace(transformation(item), i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (transformed?.size) {
|
/**
|
||||||
null -> i++
|
* Transforms a subset of a mutable list in place.
|
||||||
0 -> removeAt(i)
|
* Each element `it` that has a type S is replaced with a result of `transformation(it)`,
|
||||||
1 -> set(i++, transformed.first())
|
* `null` means "keep existing element" (to avoid creating excessive singleton lists).
|
||||||
else -> {
|
*/
|
||||||
addAll(i, transformed)
|
inline fun <T, reified S : T> MutableList<T>.transformSubsetFlat(transformation: (S) -> List<S>?) {
|
||||||
i += transformed.size
|
var i = 0
|
||||||
removeAt(i)
|
while (i < size) {
|
||||||
}
|
val item = get(i)
|
||||||
|
|
||||||
|
if (item !is S) {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
i = replaceInPlace(transformation(item), i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PublishedApi internal fun <T> MutableList<T>.replaceInPlace(transformed: List<T>?, atIndex: Int): Int {
|
||||||
|
var i = atIndex
|
||||||
|
when (transformed?.size) {
|
||||||
|
null -> i++
|
||||||
|
0 -> removeAt(i)
|
||||||
|
1 -> set(i++, transformed.first())
|
||||||
|
else -> {
|
||||||
|
addAll(i, transformed)
|
||||||
|
i += transformed.size
|
||||||
|
removeAt(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+9
-4
@@ -143,7 +143,10 @@ abstract class AbstractReplTestRunner : TestCase() {
|
|||||||
var t = 2 * 2
|
var t = 2 * 2
|
||||||
class A(val value: Int = 5) {
|
class A(val value: Int = 5) {
|
||||||
fun bar(): Int {
|
fun bar(): Int {
|
||||||
var q = 4
|
class B(val value: Int = 4) {
|
||||||
|
fun baz(): Int = value
|
||||||
|
}
|
||||||
|
var q = B().baz()
|
||||||
var w = 1
|
var w = 1
|
||||||
return q + w
|
return q + w
|
||||||
}
|
}
|
||||||
@@ -221,9 +224,11 @@ abstract class AbstractReplTestRunner : TestCase() {
|
|||||||
if (compileResult !is ReplCompileResult.CompiledClasses) return compileResult.toString()
|
if (compileResult !is ReplCompileResult.CompiledClasses) return compileResult.toString()
|
||||||
|
|
||||||
val evalResult = tester.evaluate(compileResult)
|
val evalResult = tester.evaluate(compileResult)
|
||||||
if (evalResult !is ReplEvalResult.ValueResult) return evalResult.toString()
|
when (evalResult) {
|
||||||
|
is ReplEvalResult.Error.Runtime -> return evalResult.cause.toString()
|
||||||
result = evalResult.value
|
!is ReplEvalResult.ValueResult -> return evalResult.toString()
|
||||||
|
else -> result = evalResult.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user