[IR generator] Inherit Element from AbstractElement

This is a step towards commonizing the code generator between
FIR and IR: KT-61970
This commit is contained in:
Sergej Jaskiewicz
2023-09-14 19:38:26 +03:00
committed by Space Team
parent f9d17a2d51
commit 7ab4ca6f51
6 changed files with 69 additions and 58 deletions
@@ -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<Element, Field> {
class Element(override val name: String, kind: Kind) : AbstractElement<Element, Field>() {
companion object {
private val allowedKinds = setOf(
ImplementationKind.Interface,
@@ -31,10 +31,6 @@ class Element(override val name: String, kind: Kind) : AbstractElement<Element,
override val nullable: Boolean
get() = false
override fun copy(nullable: Boolean) = ElementRef(this, args, nullable)
override fun copy(args: Map<NamedTypeParameterRef, TypeRef>) = ElementRef(this, args, nullable)
override val fields = mutableSetOf<Field>()
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<Element,
var doesNotNeedImplementation: Boolean = false
val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || parentRefs.any { it.element.needTransformOtherChildren }
override val overridenFields: MutableMap<Field, MutableMap<Field, Boolean>> = mutableMapOf()
val overridenFields: MutableMap<Field, MutableMap<Field, Boolean>> = mutableMapOf()
val useNullableForReplace: MutableSet<Field> = mutableSetOf()
val allImplementations: List<Implementation> by lazy {
if (doesNotNeedImplementation) {
@@ -149,10 +145,6 @@ class Element(override val name: String, kind: Kind) : AbstractElement<Element,
return typeWithArguments
}
override fun get(fieldName: String): Field? {
return allFields.firstOrNull { it.name == fieldName }
}
enum class Kind(val packageName: String) {
Expression("expressions"),
Declaration("declarations"),
@@ -11,25 +11,45 @@ import org.jetbrains.kotlin.ir.generator.config.ElementConfig
import org.jetbrains.kotlin.ir.generator.config.FieldConfig
import org.jetbrains.kotlin.ir.generator.util.*
import org.jetbrains.kotlin.utils.topologicalSort
import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef
import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef
class Element(
config: ElementConfig,
val name: String,
val packageName: String,
val params: List<TypeVariable>,
val fields: MutableList<Field>,
override val name: String,
override val packageName: String,
override val params: List<TypeVariable>,
override val fields: MutableSet<Field>,
val additionalFactoryMethodParameters: MutableList<Field>,
) {
) : AbstractElement<Element, Field>() {
var elementParents: List<ElementRef> = emptyList()
var otherParents: List<ClassRef<*>> = emptyList()
override val parentRefs: List<ElementOrRef>
get() = elementParents
override val allFields: List<Field>
get() = fields.toList()
override val element: Element
get() = this
override val nullable: Boolean
get() = false
override val args: Map<NamedTypeParameterRef, TypeRef>
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<ClassOrElementRef>
get() = elementParents + otherParents
override val type: String
get() = typeName
var isLeaf = config.isForcedLeaf
val childrenOrderOverride: List<String>? = config.childrenOrderOverride
var walkableChildren: List<Field> = emptyList()
@@ -79,25 +99,8 @@ class Element(
}
}
// FIXME: Replace this class with `typealias ElementRef = org.jetbrains.kotlin.generators.tree.ElementRef<Element, Field>`
// FIXME: as soon as Element implements the org.jetbrains.kotlin.generators.tree.AbstractElement interface.
data class ElementRef(
val element: Element,
override val args: Map<NamedTypeParameterRef, TypeRef> = emptyMap(),
override val nullable: Boolean = false,
) : ParametrizedTypeRef<ElementRef, NamedTypeParameterRef>, ClassOrElementRef {
override fun copy(args: Map<NamedTypeParameterRef, TypeRef>) = 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<Element, Field>
typealias ElementOrRef = GenericElementOrRef<Element, Field>
sealed class Field(
config: FieldConfig,
@@ -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<ElementConfig, Element>): Element {
val visited = mutableMapOf<TypeRef, TypeRef>()
@@ -110,7 +112,7 @@ private fun replaceElementRefs(config: Config, mapping: Map<ElementConfig, Eleme
}.also { visited[type] = it }
}
val rootEl = transform(config.rootElement) as ElementRef
val rootEl = transform(config.rootElement) as GenericElementRef<Element, Field>
for (ec in config.elements) {
val el = mapping[ec.element]!!
@@ -119,8 +121,8 @@ private fun replaceElementRefs(config: Config, mapping: Map<ElementConfig, Eleme
.partitionIsInstance<TypeRef, ElementRef>()
el.elementParents = elParents.takeIf { it.isNotEmpty() || el == rootEl.element } ?: listOf(rootEl)
el.otherParents = otherParents.castAll<ClassRef<*>>().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<Element, Field>?
el.transformerReturnType = (ec.transformerReturnType?.let(::transform) as GenericElementRef<Element, Field>?)?.element
for (field in el.fields) {
when (field) {
@@ -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<Element, Field>
if (!elRef.element.transform) {
append(" as %T")
if (child.nullable) append("?")
@@ -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<TypeName> {
return fromPositional(args as Map<PositionTypeParameterRef, TypeRef>)
} 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")
}
@@ -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<Element, Field> : ElementOrRef<Element, Field>, FieldContainer, ImplementationKindOwner
abstract class AbstractElement<Element, Field> : ElementOrRef<Element, Field>, FieldContainer, ImplementationKindOwner
where Element : AbstractElement<Element, Field>,
Field : AbstractField {
val name: String
abstract val name: String
val fields: Set<Field>
abstract val fields: Set<Field>
val params: List<TypeVariable>
abstract val params: List<TypeVariable>
val parentRefs: List<ElementOrRef<Element, Field>>
abstract val parentRefs: List<ElementOrRef<Element, Field>>
val overridenFields: Map<Field, Map<Field, Boolean>>
val isSealed: Boolean
open val isSealed: Boolean
get() = false
override val allParents: List<ImplementationKindOwner>
override val allParents: List<Element>
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<Field>
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<NamedTypeParameterRef, TypeRef>) =
ElementRef(this as Element, args, nullable)
}