[IR generator] Auto-generate IrElementTransformerVoid

This commit is contained in:
Sergej Jaskiewicz
2023-10-31 13:19:28 +01:00
committed by Space Team
parent 6798ff4a73
commit 18ed85c26e
6 changed files with 175 additions and 30 deletions
@@ -31,6 +31,7 @@ val statementOriginType = type(exprs, "IrStatementOrigin")
val elementVisitorType = type(visitors, "IrElementVisitor")
val elementVisitorVoidType = type(visitors, "IrElementVisitorVoid")
val elementTransformerType = type(visitors, "IrElementTransformer")
val elementTransformerVoidType = type(visitors, "IrElementTransformerVoid", TypeKind.Class)
val typeTransformerType = type(visitors, "IrTypeTransformer")
val mutableAnnotationContainerType = type(declarations, "IrMutableAnnotationContainer")
val irTypeType = type(types, "IrType")
@@ -29,8 +29,8 @@ fun main(args: Array<String>) {
yield(printVisitor(generationPath, model))
yield(printVisitorVoid(generationPath, model))
yield(printTransformer(generationPath, model))
yield(printTransformerVoid(generationPath, model))
yield(printTypeVisitor(generationPath, model))
// IrElementTransformerVoid is too random to autogenerate
yield(printFactory(generationPath, model))
}.map {
GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false)
@@ -5,11 +5,14 @@
package org.jetbrains.kotlin.ir.generator.print
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.*
import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration
import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType
import org.jetbrains.kotlin.ir.generator.*
import org.jetbrains.kotlin.ir.generator.model.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.withIndent
@@ -119,6 +122,139 @@ fun printTransformer(generationPath: File, model: Model): GeneratedFile =
TransformerPrinter(printer, visitorType, model.rootElement)
}
private class TransformerVoidPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
) : AbstractVisitorPrinter<Element, Field>(printer, visitSuperTypeByDefault = false) {
override val visitorTypeParameters: List<TypeVariable>
get() = emptyList()
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementTransformerType.withArgs(visitorDataType)
override val visitorDataType: TypeRef
get() = StandardTypes.nothing.copy(nullable = true)
// IrPackageFragment is treated as transformByChildren in IrElementTransformerVoid for historical reasons.
private val Element.isPackageFragment: Boolean
get() = name == IrTree.packageFragment.name
// Despite IrFile and IrExternalPackageFragment being transformByChildren, we treat them differently in IrElementTransformerVoid
// than in IrElementTransformer for historical reasons. We want to preserve the historical semantics here.
private val Element.isPackageFragmentChild: Boolean
get() = elementParents.any { it.element.isPackageFragment }
private val Element.transformByChildrenVoid: Boolean
get() = element.transformByChildren || isPackageFragment
override fun visitMethodReturnType(element: Element): Element =
when {
element.isPackageFragment -> element
element.transformByChildren -> element.getTransformExplicitType()
else -> element.parentInVisitor?.let(this::visitMethodReturnType) ?: element
}
override val allowTypeParametersInVisitorMethods: Boolean
get() = false
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods() {
println()
val typeParameter = TypeVariable("T", listOf(IrTree.rootElement))
printFunctionDeclaration(
name = "transformPostfix",
parameters = listOf(FunctionParameter("body", Lambda(receiver = typeParameter, returnType = StandardTypes.unit))),
returnType = typeParameter,
typeParameters = listOf(typeParameter),
extensionReceiver = typeParameter,
visibility = Visibility.PROTECTED,
isInline = true,
)
println(" {")
withIndent {
println("transformChildrenVoid()")
println("this.body()")
println("return this")
}
println("}")
println()
printFunctionDeclaration(
name = "transformChildrenVoid",
parameters = emptyList(),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
visibility = Visibility.PROTECTED,
)
println(" {")
withIndent {
println("transformChildrenVoid(this@", visitorType.simpleName, ")")
}
println("}")
}
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
val parent = element.parentInVisitor
if (!element.transformByChildrenVoid && parent == null) return
printer.run {
println()
printVisitMethodDeclaration(element, hasDataParameter = false, modality = Modality.OPEN)
if (element.transformByChildrenVoid && !element.isPackageFragmentChild) {
println(" {")
withIndent {
println(element.visitorParameterName, ".transformChildren(this, null)")
println("return ", element.visitorParameterName)
}
println("}")
} else {
println(" =")
withIndent {
print(parent!!.visitFunctionName, "(", element.visitorParameterName, ")")
if (element.isPackageFragmentChild) {
print(" as ", element.render())
}
println()
}
}
println()
printVisitMethodDeclaration(
element = element,
modality = Modality.FINAL,
override = true,
returnType = element.getTransformExplicitType(),
)
println(" =")
withIndent {
println(element.visitFunctionName, "(", element.visitorParameterName, ")")
}
}
}
}
fun printTransformerVoid(generationPath: File, model: Model): GeneratedFile =
printGeneratedType(
generationPath,
TREE_GENERATOR_README,
elementTransformerVoidType.packageName,
elementTransformerVoidType.simpleName,
) {
TransformerVoidPrinter(this, elementTransformerVoidType).printVisitor(model.elements)
println()
val transformerParameter = FunctionParameter("transformer", elementTransformerVoidType)
printFunctionDeclaration(
name = "transformChildrenVoid",
parameters = listOf(transformerParameter),
returnType = StandardTypes.unit,
extensionReceiver = IrTree.rootElement,
)
println(" {")
withIndent {
println("transformChildren(", transformerParameter.name, ", null)")
}
println("}")
}
private class TypeTransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
@@ -260,7 +396,7 @@ fun printTypeVisitor(generationPath: File, model: Model): GeneratedFile =
}
private fun Element.getTransformExplicitType(): Element {
return generateSequence(this) { it.parentInVisitor?.element }
return generateSequence(this) { it.parentInVisitor }
.firstNotNullOfOrNull {
when {
it.transformByChildren -> it.transformerReturnType ?: it