[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
This commit is contained in:
committed by
Space Team
parent
7e01fc5906
commit
6d5b07ebe9
+19
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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<Element>
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val generationPath = args.firstOrNull()?.let { File(it) }
|
||||
?: File("compiler/ir/ir.tree/gen").canonicalFile
|
||||
@@ -32,9 +34,7 @@ fun main(args: Array<String>) {
|
||||
elementTransformerVoidType to ::TransformerVoidPrinter,
|
||||
typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement),
|
||||
),
|
||||
afterConfiguration = {
|
||||
markLeaves(model.elements)
|
||||
},
|
||||
ImplementationConfigurator,
|
||||
enableBaseTransformerTypeDetection = false,
|
||||
addFiles = { add(printFactory(generationPath, model)) }
|
||||
)
|
||||
|
||||
+15
@@ -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<Implementation, Element, Field>() {
|
||||
override fun createImplementation(element: Element, name: String?) = Implementation(element, name)
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
|
||||
+3
-14
@@ -17,7 +17,7 @@ class Element(
|
||||
name: String,
|
||||
override val propertyName: String,
|
||||
category: Category,
|
||||
) : AbstractElement<Element, Field, Nothing>(name) {
|
||||
) : AbstractElement<Element, Field, Implementation>(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<String>? = 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<Element>
|
||||
typealias ElementOrRef = GenericElementOrRef<Element>
|
||||
typealias ElementOrRef = GenericElementOrRef<Element>
|
||||
|
||||
+14
@@ -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<Implementation, Element, Field>(element, name) {
|
||||
override val allFields
|
||||
get() = element.allFields
|
||||
}
|
||||
-24
@@ -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<Element>
|
||||
|
||||
internal fun markLeaves(elements: List<Element>) {
|
||||
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
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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)
|
||||
|
||||
|
||||
+5
@@ -42,6 +42,11 @@ abstract class AbstractElement<Element, Field, Implementation>(
|
||||
val isRootElement: Boolean
|
||||
get() = elementParents.isEmpty()
|
||||
|
||||
/**
|
||||
* A list of [Element]s which are direct subclasses of this element.
|
||||
*/
|
||||
lateinit var subElements: Set<Element>
|
||||
|
||||
var isSealed: Boolean = false
|
||||
|
||||
/**
|
||||
|
||||
+5
-12
@@ -69,18 +69,11 @@ abstract class AbstractImplementationConfigurator<Implementation, Element, Imple
|
||||
}
|
||||
|
||||
private fun generateDefaultImplementations(elements: List<Element>) {
|
||||
collectLeafsWithoutImplementation(elements).forEach {
|
||||
impl(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectLeafsWithoutImplementation(elements: List<Element>): Set<Element> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+20
@@ -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 <Element : AbstractElement<Element, *, *>> initializeSubElements(elements: List<Element>){
|
||||
val elementSubclasses = elements.associateWith { mutableSetOf<Element>() }
|
||||
|
||||
for (element in elements) {
|
||||
for (parent in element.elementParents) {
|
||||
elementSubclasses.getValue(parent.element) += element
|
||||
}
|
||||
}
|
||||
|
||||
for ((element, subElements) in elementSubclasses) {
|
||||
element.subElements = subElements
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -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 <Element, Implementation, ElementField, ImplementationField> generateTree(
|
||||
builderConfigurator: AbstractBuilderConfigurator<Element, Implementation, ImplementationField, ElementField>? = null,
|
||||
createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter<Implementation, Element, ImplementationField>)? = null,
|
||||
createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter<Element, Implementation, ImplementationField, ElementField>)? = null,
|
||||
afterConfiguration: () -> Unit = {},
|
||||
enableBaseTransformerTypeDetection: Boolean = true,
|
||||
addFiles: MutableList<GeneratedFile>.() -> Unit = {},
|
||||
) where Element : AbstractElement<Element, ElementField, Implementation>,
|
||||
@@ -100,13 +97,13 @@ fun <Element, Implementation, ElementField, ImplementationField> 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<GeneratedFile>()
|
||||
|
||||
model.elements.mapTo(generatedFiles) { element ->
|
||||
|
||||
Reference in New Issue
Block a user