From 6d5b07ebe926c50f7173f49d6c8a51bb1f794d3c Mon Sep 17 00:00:00 2001 From: Wojciech Litewka Date: Wed, 21 Feb 2024 17:35:35 +0100 Subject: [PATCH] [tree generator] Add AbstractElement#subElements, drop semantic leaves The notion of IR element class being 'semantically leaf' is rather hacky. Instead, now we only distinguish whether an element has its implementation class, which is what this notion was actually trying to represent. ^KT-65773 In Progress --- .../generator/ImplementationConfigurator.kt | 19 +++++++++++++++ .../jetbrains/kotlin/ir/generator/IrTree.kt | 4 ---- .../org/jetbrains/kotlin/ir/generator/Main.kt | 8 +++---- ...bstractIrTreeImplementationConfigurator.kt | 15 ++++++++++++ .../generator/config/AbstractTreeBuilder.kt | 2 +- .../kotlin/ir/generator/model/Element.kt | 17 +++---------- .../ir/generator/model/Implementation.kt | 14 +++++++++++ .../ir/generator/model/Transformations.kt | 24 ------------------- .../ir/generator/print/FactoryPrinter.kt | 4 ++-- .../kotlin/generators/tree/AbstractElement.kt | 5 ++++ .../AbstractImplementationConfigurator.kt | 17 ++++--------- .../generators/tree/initializeSubElements.kt | 20 ++++++++++++++++ .../kotlin/generators/tree/printer/common.kt | 5 +--- 13 files changed, 89 insertions(+), 65 deletions(-) create mode 100644 compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt create mode 100644 compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt create mode 100644 compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt delete mode 100644 compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt create mode 100644 generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt new file mode 100644 index 00000000000..a0d0de2c45f --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.generator + +import org.jetbrains.kotlin.ir.generator.config.AbstractIrTreeImplementationConfigurator + +object ImplementationConfigurator : AbstractIrTreeImplementationConfigurator() { + override fun configure(): Unit = with(IrTree) { + impl(simpleFunction) + impl(property) + } + + override fun configureAllImplementations() { + // Use configureFieldInAllImplementations to customize certain fields in all implementation classes + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt index 5973d2e3d08..c2e3a9dbfd1 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt @@ -496,8 +496,6 @@ object IrTree : AbstractTreeBuilder() { +listField("files", file, mutability = MutableList) } val property: Element by element(Declaration) { - isLeaf = true - parent(declarationBase) parent(possiblyExternalDeclaration) parent(overridableDeclaration.withArgs("S" to propertySymbolType)) @@ -552,8 +550,6 @@ object IrTree : AbstractTreeBuilder() { +field("constructor", constructor, nullable = true, isChild = false) // K1 } val simpleFunction: Element by element(Declaration) { - isLeaf = true - parent(function) parent(overridableDeclaration.withArgs("S" to simpleFunctionSymbolType)) parent(attributeContainer) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt index 7d6091e3aec..5cb38b2c857 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.ir.generator import org.jetbrains.kotlin.generators.tree.printer.generateTree -import org.jetbrains.kotlin.ir.generator.model.markLeaves +import org.jetbrains.kotlin.ir.generator.model.Element import org.jetbrains.kotlin.ir.generator.print.* import org.jetbrains.kotlin.utils.bind import java.io.File @@ -15,6 +15,8 @@ const val BASE_PACKAGE = "org.jetbrains.kotlin.ir" internal const val TREE_GENERATOR_README = "compiler/ir/ir.tree/tree-generator/ReadMe.md" +typealias Model = org.jetbrains.kotlin.generators.tree.Model + fun main(args: Array) { val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/ir/ir.tree/gen").canonicalFile @@ -32,9 +34,7 @@ fun main(args: Array) { elementTransformerVoidType to ::TransformerVoidPrinter, typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement), ), - afterConfiguration = { - markLeaves(model.elements) - }, + ImplementationConfigurator, enableBaseTransformerTypeDetection = false, addFiles = { add(printFactory(generationPath, model)) } ) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt new file mode 100644 index 00000000000..70451ede64c --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.generator.config + +import org.jetbrains.kotlin.generators.tree.config.AbstractImplementationConfigurator +import org.jetbrains.kotlin.ir.generator.model.Element +import org.jetbrains.kotlin.ir.generator.model.Field +import org.jetbrains.kotlin.ir.generator.model.Implementation + +abstract class AbstractIrTreeImplementationConfigurator : AbstractImplementationConfigurator() { + override fun createImplementation(element: Element, name: String?) = Implementation(element, name) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt index c45a1ce10ba..b10fc179b6b 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.ir.generator.model.* import org.jetbrains.kotlin.ir.generator.model.ElementOrRef import org.jetbrains.kotlin.ir.generator.model.ElementRef import org.jetbrains.kotlin.ir.generator.model.ListField -import org.jetbrains.kotlin.ir.generator.model.Model +import org.jetbrains.kotlin.ir.generator.Model import org.jetbrains.kotlin.types.Variance import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt index eb949ff4d06..6f220670e96 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt @@ -17,7 +17,7 @@ class Element( name: String, override val propertyName: String, category: Category, -) : AbstractElement(name) { +) : AbstractElement(name) { enum class Category(private val packageDir: String, val defaultVisitorParam: String) { Expression("expressions", "expression"), @@ -78,17 +78,6 @@ class Element( override val namePrefix: String get() = "Ir" - /** - * Whether this element is semantically a leaf element in the hierarchy. - * - * This is set automatically by the [markLeaves] function for all true leaves, but can also be set manually to `true` if - * this element should be considered a leaf semantically. - * - * For example, we only generate [org.jetbrains.kotlin.ir.declarations.IrFactory] methods for leaf elements. - * If we want to generate a method for this element, but it has subclasses, it can be done by manually setting this property to `true`. - */ - var isLeaf = false - override var childrenOrderOverride: List? = null override var visitorParameterName = category.defaultVisitorParam @@ -96,7 +85,7 @@ class Element( var customHasAcceptMethod: Boolean? = null override val hasAcceptMethod: Boolean - get() = customHasAcceptMethod ?: (isLeaf && parentInVisitor != null) + get() = customHasAcceptMethod ?: (implementations.isNotEmpty() && parentInVisitor != null) override var hasTransformMethod = false @@ -135,4 +124,4 @@ class Element( } typealias ElementRef = GenericElementRef -typealias ElementOrRef = GenericElementOrRef \ No newline at end of file +typealias ElementOrRef = GenericElementOrRef diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt new file mode 100644 index 00000000000..8745e36578b --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.generator.model + +import org.jetbrains.kotlin.generators.tree.AbstractImplementation +import org.jetbrains.kotlin.generators.tree.ImplementationKind + +class Implementation(element: Element, name: String?) : AbstractImplementation(element, name) { + override val allFields + get() = element.allFields +} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt deleted file mode 100644 index 453b76c6686..00000000000 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.generator.model - -typealias Model = org.jetbrains.kotlin.generators.tree.Model - -internal fun markLeaves(elements: List) { - val leaves = elements.toMutableSet() - - for (el in elements) { - for (parent in el.elementParents) { - if (!parent.element.isLeaf) { - leaves.remove(parent.element) - } - } - } - - for (el in leaves) { - el.isLeaf = true - } -} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt index bace47eb821..39fcb2faa62 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.ir.generator.TREE_GENERATOR_README import org.jetbrains.kotlin.ir.generator.irFactoryType import org.jetbrains.kotlin.ir.generator.model.Element import org.jetbrains.kotlin.ir.generator.model.Field -import org.jetbrains.kotlin.ir.generator.model.Model +import org.jetbrains.kotlin.ir.generator.Model import org.jetbrains.kotlin.ir.generator.stageControllerType import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.utils.SmartPrinter @@ -33,7 +33,7 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile = p withIndent { println("val stageController: ", stageControllerType.render()) val factoryMethods = model.elements - .filter { it.isLeaf && it.generateIrFactoryMethod } + .filter { it.implementations.isNotEmpty() && it.generateIrFactoryMethod } .sortedWith(compareBy({ it.packageName }, { it.name })) .map(::FactoryMethod) diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt index a2821da5c18..afdfb1f930a 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt @@ -42,6 +42,11 @@ abstract class AbstractElement( val isRootElement: Boolean get() = elementParents.isEmpty() + /** + * A list of [Element]s which are direct subclasses of this element. + */ + lateinit var subElements: Set + var isSealed: Boolean = false /** diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt index 8517ac41569..a9727198200 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt @@ -69,18 +69,11 @@ abstract class AbstractImplementationConfigurator) { - collectLeafsWithoutImplementation(elements).forEach { - impl(it) - } - } - - private fun collectLeafsWithoutImplementation(elements: List): Set { - val leafs = elements.toMutableSet() - elements.forEach { element -> - leafs.removeAll(element.elementParents.map { it.element }.toSet()) - } - leafs.removeAll(elementsWithImpl) - return leafs + elements + .filter { it.subElements.isEmpty() && it !in elementsWithImpl && !it.doesNotNeedImplementation } + .forEach { + impl(it) + } } /** diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt new file mode 100644 index 00000000000..15dd82c57f8 --- /dev/null +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.generators.tree + +internal fun > initializeSubElements(elements: List){ + val elementSubclasses = elements.associateWith { mutableSetOf() } + + for (element in elements) { + for (parent in element.elementParents) { + elementSubclasses.getValue(parent.element) += element + } + } + + for ((element, subElements) in elementSubclasses) { + element.subElements = subElements + } +} diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt index 0d1d5c9ee0d..b0f12d2613e 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt @@ -72,8 +72,6 @@ fun printGeneratedType( * @param builderConfigurator The class for configuring the set of builders, see [Builder] and [AbstractBuilderConfigurator]. * @param createImplementationPrinter Provide the class that prints implementations of elements, see [AbstractImplementationPrinter]. * @param createBuilderPrinter Provide the class that prints the corresponding builder for each element class, see [AbstractBuilderPrinter]. - * @param afterConfiguration The routine to run after all implementations and builders were fully configured, - * but before anything was printed to a file. * @param enableBaseTransformerTypeDetection Whether to use a special algorithm for inferring return types of transformer methods for each * element, see [detectBaseTransformerTypes]. * @param addFiles Arbitrary files to add to the set of generated files. @@ -89,7 +87,6 @@ fun generateTree( builderConfigurator: AbstractBuilderConfigurator? = null, createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter)? = null, createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter)? = null, - afterConfiguration: () -> Unit = {}, enableBaseTransformerTypeDetection: Boolean = true, addFiles: MutableList.() -> Unit = {}, ) where Element : AbstractElement, @@ -100,13 +97,13 @@ fun generateTree( if (enableBaseTransformerTypeDetection) { detectBaseTransformerTypes(model) } + initializeSubElements(model.elements) implementationConfigurator?.configureImplementations(model) val implementations = model.elements.flatMap { it.implementations } InterfaceAndAbstractClassConfigurator((model.elements + implementations)) .configureInterfacesAndAbstractClasses() addPureAbstractElement(model.elements, pureAbstractElement) builderConfigurator?.configureBuilders() - afterConfiguration() val generatedFiles = mutableListOf() model.elements.mapTo(generatedFiles) { element ->