Skip to content

Commit

Permalink
(fixup) Do not generate acceptChildren/transformChildren for some non…
Browse files Browse the repository at this point in the history
…-leaf elements
  • Loading branch information
udalov committed Feb 7, 2022
1 parent f2b5ac5 commit eb3dbac
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 42 deletions.
Expand Up @@ -25,6 +25,10 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.types.Variance

// Note the style of the DSL to describe IR elements, which is these things in the following order:
// 1) config (see properties of ElementConfig)
// 2) parents
// 3) fields
object IrTree : AbstractTreeBuilder() {
private fun symbol(type: TypeRef) = field("symbol", type)
private fun descriptor(typeName: String) =
Expand Down Expand Up @@ -183,11 +187,15 @@ object IrTree : AbstractTreeBuilder() {
+field("body", blockBody, mutable = true, isChild = true)
}
val declarationContainer: ElementConfig by element(Declaration) {
ownsChildren = false

parent(declarationParent)

+listField("declarations", declaration, mutability = List, isChild = true)
}
val typeParametersContainer: ElementConfig by element(Declaration) {
ownsChildren = false

parent(declaration)
parent(declarationParent)

Expand Down Expand Up @@ -448,6 +456,7 @@ object IrTree : AbstractTreeBuilder() {
}
val packageFragment: ElementConfig by element(Declaration) {
visitorParent = baseElement
ownsChildren = false

parent(declarationContainer)
parent(symbolOwner)
Expand Down Expand Up @@ -494,6 +503,8 @@ object IrTree : AbstractTreeBuilder() {
+field("type", irTypeType, mutable = true)
}
val statementContainer: ElementConfig by element(Expression) {
ownsChildren = false

+listField("statements", statement, mutability = List, isChild = true)
}
val body: ElementConfig by element(Expression) {
Expand Down Expand Up @@ -832,6 +843,7 @@ object IrTree : AbstractTreeBuilder() {
val fieldAccessExpression: ElementConfig by element(Expression) {
visitorParent = declarationReference
visitorName = "fieldAccess"
ownsChildren = false

parent(declarationReference)

Expand Down Expand Up @@ -880,6 +892,7 @@ object IrTree : AbstractTreeBuilder() {
val loop: ElementConfig by element(Expression) {
visitorParent = expression
visitorParam = "loop"
ownsChildren = false

parent(expression)

Expand Down
Expand Up @@ -34,6 +34,8 @@ class ElementConfig(
var transformByChildren = false
var transformerReturnType: ElementConfig? = null

var ownsChildren = true // If false, acceptChildren/transformChildren will NOT be generated.

var typeKind: TypeKind? = null

var generationCallback: (TypeSpec.Builder.() -> Unit)? = null
Expand Down
Expand Up @@ -30,14 +30,13 @@ class Element(
var isLeaf = false
var walkableChildren: List<Field> = emptyList()
val transformableChildren get() = walkableChildren.filter { it.transformable }
val acceptChildrenSupers = mutableListOf<Element>()
val transformChildrenSupers = mutableListOf<Element>()

val visitFunName = "visit" + (config.visitorName ?: name).replaceFirstChar(Char::uppercaseChar)
val visitorParam = config.visitorParam ?: config.category.defaultVisitorParam
var accept = config.accept
val transform = config.transform
val transformByChildren = config.transformByChildren
val ownsChildren = config.ownsChildren

val generationCallback = config.generationCallback
val suppressPrint = config.suppressPrint
Expand Down
Expand Up @@ -234,47 +234,27 @@ private fun processFieldOverrides(elements: List<Element>) {

private fun addWalkableChildren(elements: List<Element>) {
for (element in elements) {
val walkableChildren = element.fields.filter { it.isChild }.associateBy { it.name }.toMutableMap()
val walkableChildren = mutableMapOf<String, Field>()

fun visitParents(visited: Element) {
for (parent in visited.elementParents) {
for (field in parent.element.fields) {
if (field.isChild) {
walkableChildren.remove(field.name)
if (!parent.element.ownsChildren) {
for (field in parent.element.fields) {
if (field.isChild) {
walkableChildren[field.name] = field
}
}
}

visitParents(parent.element)
visitParents(parent.element)
}
}
}

visitParents(element)
element.walkableChildren = walkableChildren.values.toList()
}

for (element in iterateElementsParentFirst(elements)) {
fun visitParentsForAccept(of: Element) {
for (parent in of.elementParents) {
if (parent.element.walkableChildren.isNotEmpty()) {
element.acceptChildrenSupers.add(parent.element)
} else {
visitParentsForAccept(parent.element)
}
}
}
element.fields.filter { it.isChild }.associateByTo(walkableChildren) { it.name }

fun visitParentsForTransform(of: Element) {
for (parent in of.elementParents) {
if (parent.element.transformableChildren.isNotEmpty()) {
element.transformChildrenSupers.add(parent.element)
} else {
visitParentsForTransform(parent.element)
}
}
}

visitParentsForAccept(element)
visitParentsForTransform(element)
element.walkableChildren = walkableChildren.values.toList()
}
}

Expand Down
Expand Up @@ -99,18 +99,14 @@ fun printElements(generationPath: File, model: Model) = sequence {
}.build())
}

if (element.walkableChildren.isNotEmpty() || element.acceptChildrenSupers.size > 1) {
if (element.ownsChildren && element.walkableChildren.isNotEmpty()) {
addFunction(FunSpec.builder("acceptChildren").apply {
addModifiers(KModifier.OVERRIDE)
val d = TypeVariableName("D")
addTypeVariable(d)
addParameter("visitor", elementVisitorType.toPoet().tryParameterizedBy(UNIT, d))
addParameter("data", d)

for (ancestor in element.acceptChildrenSupers) {
addStatement("super<%T>.acceptChildren(visitor, data)", ancestor.toPoet())
}

for (child in element.walkableChildren) {
addStatement(buildString {
append(child.name)
Expand All @@ -124,18 +120,14 @@ fun printElements(generationPath: File, model: Model) = sequence {
}.build())
}

if (element.transformableChildren.isNotEmpty() || element.transformChildrenSupers.size > 1) {
if (element.ownsChildren && element.transformableChildren.isNotEmpty()) {
addFunction(FunSpec.builder("transformChildren").apply {
addModifiers(KModifier.OVERRIDE)
val d = TypeVariableName("D")
addTypeVariable(d)
addParameter("transformer", elementTransformerType.toPoet().tryParameterizedBy(d))
addParameter("data", d)

for (ancestor in element.transformChildrenSupers) {
addStatement("super<%T>.transformChildren(transformer, data)", ancestor.toPoet())
}

for (child in element.transformableChildren) {
val args = mutableListOf<Any>()
val code = buildString {
Expand Down

0 comments on commit eb3dbac

Please sign in to comment.