[FIR/IR generator] Share visitor-related properties between FIR & IR

This commit is contained in:
Sergej Jaskiewicz
2023-09-19 18:15:25 +02:00
committed by Space Team
parent bdfb3c3ac9
commit 75b509c185
13 changed files with 152 additions and 83 deletions
@@ -55,6 +55,24 @@ class Element(override val name: String, kind: Kind) : AbstractElement<Element,
override var isSealed: Boolean = false
override val hasAcceptMethod: Boolean
get() = true
override val hasTransformMethod: Boolean
get() = true
override val hasAcceptChildrenMethod: Boolean
get() = isRootElement
override val hasTransformChildrenMethod: Boolean
get() = isRootElement
override val walkableChildren: List<Field>
get() = emptyList() // Use Implementation#walkableChildren instead
override val transformableChildren: List<Field>
get() = emptyList() // Use Implementation#transformableChildren instead
var baseTransformerType: Element? = null
val transformerType: Element get() = baseTransformerType ?: this
@@ -59,6 +59,22 @@ class Implementation(val element: Element, val name: String?) : FieldContainer,
}
}
override val hasAcceptChildrenMethod: Boolean
get() {
val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass
return !isInterface && !isAbstract
}
override val hasTransformChildrenMethod: Boolean
get() = true
override val walkableChildren: List<FieldWithDefault>
get() = allFields.filter { it.isFirType && !it.withGetter && it.needAcceptAndTransform }
override val transformableChildren: List<FieldWithDefault>
get() = walkableChildren.filter { it.isMutable }
fun addParent(parent: Implementation, arg: Importable? = null) {
_parents += ImplementationWithArg(parent, arg)
}
@@ -60,22 +60,26 @@ fun SmartPrinter.printElement(element: Element) {
}
}
}
if (allFields.isNotEmpty()) {
if (hasAcceptMethod) {
if (allFields.isNotEmpty()) {
println()
}
override()
println("fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =")
withIndent {
println("visitor.visit${element.name}(this, data)")
}
}
if (hasTransformMethod) {
println()
}
override()
println("fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =")
withIndent {
println("visitor.visit${element.name}(this, data)")
}
println()
println("@Suppress(\"UNCHECKED_CAST\")")
override()
println("fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =")
withIndent {
println("transformer.transform$name(this, data) as E")
println("@Suppress(\"UNCHECKED_CAST\")")
override()
println("fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =")
withIndent {
println("transformer.transform$name(this, data) as E")
}
}
fun Field.replaceDeclaration(override: Boolean, overridenType: TypeRef? = null, forceNullable: Boolean = false) {
@@ -121,12 +125,16 @@ fun SmartPrinter.printElement(element: Element) {
}
println()
println("fun accept(visitor: FirVisitorVoid) = accept(visitor, null)")
println()
println("fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D)")
if (element.hasAcceptChildrenMethod) {
println()
println("fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D)")
}
println()
println("fun acceptChildren(visitor: FirVisitorVoid) = acceptChildren(visitor, null)")
println()
println("fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement")
if (element.hasTransformChildrenMethod) {
println()
println("fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement")
}
}
}
println("}")
@@ -138,14 +138,14 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
fun Field.acceptString(): String = "${name}${call()}accept(visitor, data)"
if (!isInterface && !isAbstract) {
if (hasAcceptChildrenMethod) {
print("override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {")
if (element.allFirFields.isNotEmpty()) {
val walkableFields = walkableChildren
if (walkableFields.isNotEmpty()) {
println()
withIndent {
for (field in allFields.filter { it.isFirType }) {
if (field.withGetter || !field.needAcceptAndTransform) continue
for (field in walkableFields) {
when (field.name) {
"explicitReceiver" -> {
val explicitReceiver = implementation["explicitReceiver"]!!
@@ -202,65 +202,65 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
println()
}
abstract()
print("override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): $typeWithArguments")
if (!isInterface && !isAbstract) {
println(" {")
withIndent {
for (field in allFields) {
when {
!field.isMutable || !field.isFirType || field.withGetter || !field.needAcceptAndTransform -> {}
field.name == "explicitReceiver" -> {
val explicitReceiver = implementation["explicitReceiver"]!!
val dispatchReceiver = implementation["dispatchReceiver"]!!
val extensionReceiver = implementation["extensionReceiver"]!!
if (explicitReceiver.isMutable) {
println("explicitReceiver = explicitReceiver${explicitReceiver.call()}transform(transformer, data)")
}
if (dispatchReceiver.isMutable) {
println(
"""
if (hasTransformChildrenMethod) {
abstract()
print("override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): $typeWithArguments")
if (!isInterface && !isAbstract) {
println(" {")
withIndent {
for (field in transformableChildren) {
when {
field.name == "explicitReceiver" -> {
val explicitReceiver = implementation["explicitReceiver"]!!
val dispatchReceiver = implementation["dispatchReceiver"]!!
val extensionReceiver = implementation["extensionReceiver"]!!
if (explicitReceiver.isMutable) {
println("explicitReceiver = explicitReceiver${explicitReceiver.call()}transform(transformer, data)")
}
if (dispatchReceiver.isMutable) {
println(
"""
|if (dispatchReceiver !== explicitReceiver) {
| dispatchReceiver = dispatchReceiver?.transform(transformer, data)
| }
""".trimMargin(),
)
}
if (extensionReceiver.isMutable) {
println(
"""
)
}
if (extensionReceiver.isMutable) {
println(
"""
|if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
| extensionReceiver = extensionReceiver?.transform(transformer, data)
| }
""".trimMargin(),
)
)
}
}
}
field.name in setOf("dispatchReceiver", "extensionReceiver") -> {}
field.name in setOf("dispatchReceiver", "extensionReceiver") -> {}
field.needsSeparateTransform -> {
if (!(element.needTransformOtherChildren && field.needTransformInOtherChildren)) {
println("transform${field.name.replaceFirstChar(Char::uppercaseChar)}(transformer, data)")
field.needsSeparateTransform -> {
if (!(element.needTransformOtherChildren && field.needTransformInOtherChildren)) {
println("transform${field.name.replaceFirstChar(Char::uppercaseChar)}(transformer, data)")
}
}
}
!element.needTransformOtherChildren -> {
field.transform()
}
!element.needTransformOtherChildren -> {
field.transform()
}
else -> {}
else -> {}
}
}
if (element.needTransformOtherChildren) {
println("transformOtherChildren(transformer, data)")
}
println("return this")
}
if (element.needTransformOtherChildren) {
println("transformOtherChildren(transformer, data)")
}
println("return this")
println("}")
} else {
println()
}
println("}")
} else {
println()
}
for (field in allFields) {