From 7ab4ca6f518702557af75181af266659e2d9f2a1 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Thu, 14 Sep 2023 19:38:26 +0300 Subject: [PATCH] [IR generator] Inherit Element from AbstractElement This is a step towards commonizing the code generator between FIR and IR: KT-61970 --- .../fir/tree/generator/model/Element.kt | 12 +--- .../kotlin/ir/generator/model/Model.kt | 57 ++++++++++--------- .../ir/generator/model/Transformations.kt | 10 ++-- .../kotlin/ir/generator/print/Elements.kt | 6 +- .../kotlin/ir/generator/print/Types.kt | 8 +-- .../kotlin/generators/tree/AbstractElement.kt | 34 +++++++---- 6 files changed, 69 insertions(+), 58 deletions(-) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt index b7d245ec411..24260429336 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.generators.tree.ElementOrRef import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef -class Element(override val name: String, kind: Kind) : AbstractElement { +class Element(override val name: String, kind: Kind) : AbstractElement() { companion object { private val allowedKinds = setOf( ImplementationKind.Interface, @@ -31,10 +31,6 @@ class Element(override val name: String, kind: Kind) : AbstractElement) = ElementRef(this, args, nullable) - override val fields = mutableSetOf() override val type: String = "Fir$name" override val packageName: String = BASE_PACKAGE + kind.packageName.let { if (it.isBlank()) it else "." + it } @@ -63,7 +59,7 @@ class Element(override val name: String, kind: Kind) : AbstractElement> = mutableMapOf() + val overridenFields: MutableMap> = mutableMapOf() val useNullableForReplace: MutableSet = mutableSetOf() val allImplementations: List by lazy { if (doesNotNeedImplementation) { @@ -149,10 +145,6 @@ class Element(override val name: String, kind: Kind) : AbstractElement, - val fields: MutableList, + override val name: String, + override val packageName: String, + override val params: List, + override val fields: MutableSet, val additionalFactoryMethodParameters: MutableList, -) { +) : AbstractElement() { var elementParents: List = emptyList() var otherParents: List> = emptyList() + + override val parentRefs: List + get() = elementParents + + override val allFields: List + get() = fields.toList() + + override val element: Element + get() = this + + override val nullable: Boolean + get() = false + + override val args: Map + get() = emptyMap() + var visitorParent: ElementRef? = null var transformerReturnType: Element? = null val targetKind = config.typeKind - var kind: ImplementationKind? = null + override var kind: ImplementationKind? = null val typeName get() = elementName2typeName(name) - val allParents: List - get() = elementParents + otherParents + + override val type: String + get() = typeName + var isLeaf = config.isForcedLeaf val childrenOrderOverride: List? = config.childrenOrderOverride var walkableChildren: List = emptyList() @@ -79,25 +99,8 @@ class Element( } } -// FIXME: Replace this class with `typealias ElementRef = org.jetbrains.kotlin.generators.tree.ElementRef` -// FIXME: as soon as Element implements the org.jetbrains.kotlin.generators.tree.AbstractElement interface. -data class ElementRef( - val element: Element, - override val args: Map = emptyMap(), - override val nullable: Boolean = false, -) : ParametrizedTypeRef, ClassOrElementRef { - override fun copy(args: Map) = ElementRef(element, args, nullable) - override fun copy(nullable: Boolean) = ElementRef(element, args, nullable) - override fun toString() = "${element.name}<${args}>" - - override val type: String - get() = element.typeName - - override val packageName: String - get() = element.packageName - - override fun getTypeWithArguments(notNull: Boolean): String = type + generics -} +typealias ElementRef = GenericElementRef +typealias ElementOrRef = GenericElementOrRef sealed class Field( config: FieldConfig, 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 index 0c758dd74c5..d067053d7a5 100644 --- 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 @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.generator.elementBaseType import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction import org.jetbrains.kotlin.utils.addToStdlib.castAll import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance +import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef private object InferredOverriddenType : TypeRef { override val type: String @@ -34,7 +35,7 @@ fun config2model(config: Config): Model { name = ec.name, packageName = ec.category.packageName, params = ec.params, - fields = ec.fields.mapTo(mutableListOf(), ::transformFieldConfig), + fields = ec.fields.mapTo(mutableSetOf(), ::transformFieldConfig), additionalFactoryMethodParameters = ec.additionalIrFactoryMethodParameters.mapTo(mutableListOf(), ::transformFieldConfig) ).also { ec2el[ec.element] = it @@ -85,6 +86,7 @@ private fun transformFieldConfig(fc: FieldConfig): Field = when (fc) { } @OptIn(UnsafeCastFunction::class) +@Suppress("UNCHECKED_CAST") private fun replaceElementRefs(config: Config, mapping: Map): Element { val visited = mutableMapOf() @@ -110,7 +112,7 @@ private fun replaceElementRefs(config: Config, mapping: Map for (ec in config.elements) { val el = mapping[ec.element]!! @@ -119,8 +121,8 @@ private fun replaceElementRefs(config: Config, mapping: Map() el.elementParents = elParents.takeIf { it.isNotEmpty() || el == rootEl.element } ?: listOf(rootEl) el.otherParents = otherParents.castAll>().toList() - el.visitorParent = ec.visitorParent?.let(::transform) as ElementRef? - el.transformerReturnType = (ec.transformerReturnType?.let(::transform) as ElementRef?)?.element + el.visitorParent = ec.visitorParent?.let(::transform) as GenericElementRef? + el.transformerReturnType = (ec.transformerReturnType?.let(::transform) as GenericElementRef?)?.element for (field in el.fields) { when (field) { diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt index cafe9ed5a41..45602c44339 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.generator.model.* import org.jetbrains.kotlin.generators.tree.TypeRefWithNullability import org.jetbrains.kotlin.ir.generator.util.tryParameterizedBy import java.io.File +import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef fun printElements(generationPath: File, model: Model) = sequence { for (element in model.elements) { @@ -39,7 +40,7 @@ fun printElements(generationPath: File, model: Model) = sequence { ) addTypeVariables(element.params.map { it.toPoet() }) - val (classes, interfaces) = element.allParents.partition { it.typeKind == TypeKind.Class } + val (classes, interfaces) = (element.elementParents + element.otherParents).partition { it.typeKind == TypeKind.Class } classes.singleOrNull()?.let { superclass(it.toPoet()) } @@ -229,7 +230,8 @@ fun printElements(generationPath: File, model: Model) = sequence { args.add(dataParam) if (child is SingleField) { - val elRef = child.typeRef as ElementRef + @Suppress("UNCHECKED_CAST") + val elRef = child.typeRef as GenericElementRef if (!elRef.element.transform) { append(" as %T") if (child.nullable) append("?") diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Types.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Types.kt index d142b21f040..ece4f04a3cf 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Types.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Types.kt @@ -10,9 +10,9 @@ import org.jetbrains.kotlin.generators.tree.* import org.jetbrains.kotlin.ir.generator.config.ElementConfigOrRef import org.jetbrains.kotlin.ir.generator.model.Element import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName -import org.jetbrains.kotlin.ir.generator.model.ElementRef import org.jetbrains.kotlin.ir.generator.util.* import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef fun Element.toPoet() = ClassName(packageName, typeName) fun Element.toPoetSelfParameterized() = toPoet().parameterizedByIfAny(poetTypeVariables) @@ -21,7 +21,7 @@ val Element.poetTypeVariables get() = params.map { TypeVariableName(it.name) } fun TypeRef.toPoet(): TypeName { return when (this) { - is ElementRef -> ClassName(element.packageName, element.typeName).parameterizedByIfAny(typeArgsToPoet()) + is GenericElementRef<*, *> -> ClassName(element.packageName!!, element.type).parameterizedByIfAny(typeArgsToPoet()) is ClassRef<*> -> ClassName(packageName, simpleNames).parameterizedByIfAny(typeArgsToPoet()) is NamedTypeParameterRef -> TypeVariableName(name) is ElementConfigOrRef -> ClassName(this.element.category.packageName, elementName2typeName(element.name)).parameterizedByIfAny( @@ -50,7 +50,7 @@ private fun ParametrizedTypeRef<*, *>.typeArgsToPoet(): List { return fromPositional(args as Map) } else { check(positional.isEmpty()) { "Can't yet handle mixed index-name args" } - this as ElementRef // Named args must only be used with generated elements (for now) + this as GenericElementRef<*, *> // Named args must only be used with generated elements (for now) val args = args.entries .associate { p -> PositionTypeParameterRef(element.params.withIndex().single { it.value.name == p.key.name }.index) to p.value } @@ -68,7 +68,7 @@ fun TypeVariable.toPoet() = TypeVariableName( val ClassOrElementRef.typeKind: TypeKind get() = when (this) { - is ElementRef -> element.kind!!.typeKind + is GenericElementRef<*, *> -> element.kind!!.typeKind is ClassRef<*> -> kind else -> error("Unexpected type: $this") } 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 3123ba9fb93..158c84d9165 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 @@ -8,27 +8,39 @@ package org.jetbrains.kotlin.generators.tree import org.jetbrains.kotlin.generators.tree.printer.generics /** - * A common interface representing a FIR or IR tree element. + * A class representing a FIR or IR tree element. */ -interface AbstractElement : ElementOrRef, FieldContainer, ImplementationKindOwner +abstract class AbstractElement : ElementOrRef, FieldContainer, ImplementationKindOwner where Element : AbstractElement, Field : AbstractField { - val name: String + abstract val name: String - val fields: Set + abstract val fields: Set - val params: List + abstract val params: List - val parentRefs: List> + abstract val parentRefs: List> - val overridenFields: Map> - - val isSealed: Boolean + open val isSealed: Boolean get() = false - override val allParents: List + override val allParents: List get() = parentRefs.map { it.element } - override fun getTypeWithArguments(notNull: Boolean): String = type + generics + final override fun getTypeWithArguments(notNull: Boolean): String = type + generics + + abstract override val allFields: List + + final override fun get(fieldName: String): Field? { + return allFields.firstOrNull { it.name == fieldName } + } + + @Suppress("UNCHECKED_CAST") + final override fun copy(nullable: Boolean) = + ElementRef(this as Element, args, nullable) + + @Suppress("UNCHECKED_CAST") + final override fun copy(args: Map) = + ElementRef(this as Element, args, nullable) }