[IR generator] Simplify configuration of visitor parents

Don't specify a visitor parent manually for each IR node,
use an algorithm instead.
This commit is contained in:
Sergej Jaskiewicz
2023-11-14 15:56:57 +01:00
committed by Space Team
parent 62d32471e1
commit a5b5492b2d
14 changed files with 116 additions and 152 deletions
@@ -79,11 +79,6 @@ class Element(name: String, override val propertyName: String, kind: Kind) : Abs
override val visitorParameterName: String override val visitorParameterName: String
get() = safeDecapitalizedName get() = safeDecapitalizedName
var customParentInVisitor: Element? = null
override val parentInVisitor: Element?
get() = customParentInVisitor ?: elementParents.singleOrNull()?.element?.takeIf { !it.isRootElement }
var doesNotNeedImplementation: Boolean = false var doesNotNeedImplementation: Boolean = false
val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || elementParents.any { it.element.needTransformOtherChildren } val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || elementParents.any { it.element.needTransformOtherChildren }
@@ -461,7 +461,7 @@ class ExpressionCodegen(
} }
} }
private fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: BlockInfo): PromisedValue { private fun generateInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: BlockInfo): PromisedValue {
val inlineCall = inlinedBlock.inlineCall val inlineCall = inlinedBlock.inlineCall
val callee = inlinedBlock.inlineDeclaration as? IrFunction val callee = inlinedBlock.inlineDeclaration as? IrFunction
@@ -559,7 +559,7 @@ class ExpressionCodegen(
private fun visitStatementContainer(container: IrStatementContainer, data: BlockInfo): PromisedValue { private fun visitStatementContainer(container: IrStatementContainer, data: BlockInfo): PromisedValue {
if (container is IrInlinedFunctionBlock) { if (container is IrInlinedFunctionBlock) {
return visitInlinedFunctionBlock(container, data) return generateInlinedFunctionBlock(container, data)
} }
return container.statements.fold(unitValue) { prev, exp -> return container.statements.fold(unitValue) { prev, exp ->
prev.discard() prev.discard()
@@ -9,6 +9,7 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
/** /**
* A leaf IR tree element. * A leaf IR tree element.
@@ -19,4 +20,7 @@ abstract class IrInlinedFunctionBlock : IrBlock() {
abstract var inlineCall: IrFunctionAccessExpression abstract var inlineCall: IrFunctionAccessExpression
abstract var inlinedElement: IrElement abstract var inlinedElement: IrElement
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitInlinedFunctionBlock(this, data)
} }
@@ -11,6 +11,7 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.declarations.IrReturnTarget import org.jetbrains.kotlin.ir.declarations.IrReturnTarget
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
/** /**
* A leaf IR tree element. * A leaf IR tree element.
@@ -19,4 +20,7 @@ import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
*/ */
abstract class IrReturnableBlock : IrBlock(), IrSymbolOwner, IrReturnTarget { abstract class IrReturnableBlock : IrBlock(), IrSymbolOwner, IrReturnTarget {
abstract override val symbol: IrReturnableBlockSymbol abstract override val symbol: IrReturnableBlockSymbol
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitReturnableBlock(this, data)
} }
@@ -140,6 +140,12 @@ interface IrElementTransformer<in D> : IrElementVisitor<IrElement, D> {
override fun visitComposite(expression: IrComposite, data: D): IrExpression = override fun visitComposite(expression: IrComposite, data: D): IrExpression =
visitContainerExpression(expression, data) visitContainerExpression(expression, data)
override fun visitReturnableBlock(expression: IrReturnableBlock, data: D): IrExpression =
visitBlock(expression, data)
override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: D): IrExpression =
visitBlock(inlinedBlock, data)
override fun visitSyntheticBody(body: IrSyntheticBody, data: D): IrBody = override fun visitSyntheticBody(body: IrSyntheticBody, data: D): IrBody =
visitBody(body, data) visitBody(body, data)
@@ -256,6 +256,18 @@ abstract class IrElementTransformerVoid : IrElementTransformer<Nothing?> {
final override fun visitComposite(expression: IrComposite, data: Nothing?): IrExpression = final override fun visitComposite(expression: IrComposite, data: Nothing?): IrExpression =
visitComposite(expression) visitComposite(expression)
open fun visitReturnableBlock(expression: IrReturnableBlock): IrExpression =
visitBlock(expression)
final override fun visitReturnableBlock(expression: IrReturnableBlock, data: Nothing?): IrExpression =
visitReturnableBlock(expression)
open fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock): IrExpression =
visitBlock(inlinedBlock)
final override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: Nothing?): IrExpression =
visitInlinedFunctionBlock(inlinedBlock)
open fun visitSyntheticBody(body: IrSyntheticBody): IrBody = open fun visitSyntheticBody(body: IrSyntheticBody): IrBody =
visitBody(body) visitBody(body)
@@ -124,6 +124,12 @@ interface IrElementVisitor<out R, in D> {
fun visitComposite(expression: IrComposite, data: D): R = fun visitComposite(expression: IrComposite, data: D): R =
visitContainerExpression(expression, data) visitContainerExpression(expression, data)
fun visitReturnableBlock(expression: IrReturnableBlock, data: D): R =
visitBlock(expression, data)
fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: D): R =
visitBlock(inlinedBlock, data)
fun visitSyntheticBody(body: IrSyntheticBody, data: D): R = fun visitSyntheticBody(body: IrSyntheticBody, data: D): R =
visitBody(body, data) visitBody(body, data)
@@ -304,6 +304,22 @@ interface IrElementVisitorVoid : IrElementVisitor<Unit, Nothing?> {
visitContainerExpression(expression) visitContainerExpression(expression)
} }
override fun visitReturnableBlock(expression: IrReturnableBlock, data: Nothing?) {
visitReturnableBlock(expression)
}
fun visitReturnableBlock(expression: IrReturnableBlock) {
visitBlock(expression)
}
override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock, data: Nothing?) {
visitInlinedFunctionBlock(inlinedBlock)
}
fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock) {
visitBlock(inlinedBlock)
}
override fun visitSyntheticBody(body: IrSyntheticBody, data: Nothing?) { override fun visitSyntheticBody(body: IrSyntheticBody, data: Nothing?) {
visitSyntheticBody(body) visitSyntheticBody(body)
} }
@@ -48,6 +48,9 @@ object IrTree : AbstractTreeBuilder() {
private fun declarationWithLateBinding(symbol: ClassRef<*>, initializer: Element.() -> Unit) = element(Declaration) { private fun declarationWithLateBinding(symbol: ClassRef<*>, initializer: Element.() -> Unit) = element(Declaration) {
initializer() initializer()
noAcceptMethod()
noMethodInVisitor()
fieldsToSkipInIrFactoryMethod.add("symbol") fieldsToSkipInIrFactoryMethod.add("symbol")
fieldsToSkipInIrFactoryMethod.add("containerSource") fieldsToSkipInIrFactoryMethod.add("containerSource")
@@ -72,8 +75,8 @@ object IrTree : AbstractTreeBuilder() {
} }
override val rootElement: Element by element(Other, name = "Element") { override val rootElement: Element by element(Other, name = "Element") {
hasAcceptMethod = true needAcceptMethod()
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
fun offsetField(prefix: String) = field(prefix + "Offset", int, mutable = false) { fun offsetField(prefix: String) = field(prefix + "Offset", int, mutable = false) {
@@ -110,7 +113,6 @@ object IrTree : AbstractTreeBuilder() {
typeKind = TypeKind.Class typeKind = TypeKind.Class
transformByChildren = true transformByChildren = true
transformerReturnType = statement transformerReturnType = statement
parentInVisitor = rootElement
nameInVisitorMethod = "Declaration" nameInVisitorMethod = "Declaration"
parent(declaration) parent(declaration)
@@ -194,8 +196,7 @@ object IrTree : AbstractTreeBuilder() {
+field("isAssignable", boolean, mutable = false) +field("isAssignable", boolean, mutable = false)
} }
val valueParameter: Element by element(Declaration) { val valueParameter: Element by element(Declaration) {
hasTransformMethod = true needTransformMethod()
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(valueDeclaration) parent(valueDeclaration)
@@ -239,8 +240,6 @@ object IrTree : AbstractTreeBuilder() {
+field("defaultValue", expressionBody, nullable = true, isChild = true) +field("defaultValue", expressionBody, nullable = true, isChild = true)
} }
val `class`: Element by element(Declaration) { val `class`: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(possiblyExternalDeclaration) parent(possiblyExternalDeclaration)
parent(declarationWithVisibility) parent(declarationWithVisibility)
@@ -325,8 +324,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val anonymousInitializer: Element by element(Declaration) { val anonymousInitializer: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
+descriptor("ClassDescriptor") // TODO special descriptor for anonymous initializer blocks +descriptor("ClassDescriptor") // TODO special descriptor for anonymous initializer blocks
@@ -360,8 +357,7 @@ object IrTree : AbstractTreeBuilder() {
+listField("typeParameters", typeParameter, mutability = Var, isChild = true) +listField("typeParameters", typeParameter, mutability = Var, isChild = true)
} }
val typeParameter: Element by element(Declaration) { val typeParameter: Element by element(Declaration) {
parentInVisitor = declarationBase needTransformMethod()
hasTransformMethod = true
parent(declarationBase) parent(declarationBase)
parent(declarationWithName) parent(declarationWithName)
@@ -382,8 +378,6 @@ object IrTree : AbstractTreeBuilder() {
+symbol(returnTargetSymbolType) +symbol(returnTargetSymbolType)
} }
val function: Element by element(Declaration) { val function: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(possiblyExternalDeclaration) parent(possiblyExternalDeclaration)
parent(declarationWithVisibility) parent(declarationWithVisibility)
@@ -410,8 +404,6 @@ object IrTree : AbstractTreeBuilder() {
+field("body", body, nullable = true, isChild = true) +field("body", body, nullable = true, isChild = true)
} }
val constructor: Element by element(Declaration) { val constructor: Element by element(Declaration) {
parentInVisitor = function
parent(function) parent(function)
+descriptor("ClassConstructorDescriptor") +descriptor("ClassConstructorDescriptor")
@@ -419,8 +411,6 @@ object IrTree : AbstractTreeBuilder() {
+field("isPrimary", boolean) +field("isPrimary", boolean)
} }
val enumEntry: Element by element(Declaration) { val enumEntry: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(declarationWithName) parent(declarationWithName)
@@ -430,8 +420,6 @@ object IrTree : AbstractTreeBuilder() {
+field("correspondingClass", `class`, nullable = true, isChild = true) +field("correspondingClass", `class`, nullable = true, isChild = true)
} }
val errorDeclaration: Element by element(Declaration) { val errorDeclaration: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
additionalIrFactoryMethodParameters.add( additionalIrFactoryMethodParameters.add(
@@ -454,8 +442,6 @@ object IrTree : AbstractTreeBuilder() {
parent(property) parent(property)
} }
val field: Element by element(Declaration) { val field: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(possiblyExternalDeclaration) parent(possiblyExternalDeclaration)
parent(declarationWithVisibility) parent(declarationWithVisibility)
@@ -473,8 +459,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val localDelegatedProperty: Element by element(Declaration) { val localDelegatedProperty: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(declarationWithName) parent(declarationWithName)
parent(symbolOwner) parent(symbolOwner)
@@ -489,8 +473,7 @@ object IrTree : AbstractTreeBuilder() {
+field("setter", simpleFunction, nullable = true, isChild = true) +field("setter", simpleFunction, nullable = true, isChild = true)
} }
val moduleFragment: Element by element(Declaration) { val moduleFragment: Element by element(Declaration) {
parentInVisitor = rootElement needTransformMethod()
hasTransformMethod = true
transformByChildren = true transformByChildren = true
generateIrFactoryMethod = false generateIrFactoryMethod = false
@@ -509,7 +492,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val property: Element by element(Declaration) { val property: Element by element(Declaration) {
parentInVisitor = declarationBase
isLeaf = true isLeaf = true
parent(declarationBase) parent(declarationBase)
@@ -541,7 +523,6 @@ object IrTree : AbstractTreeBuilder() {
//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class //TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class
//NOTE: declarations and statements stored separately //NOTE: declarations and statements stored separately
val script: Element by element(Declaration) { val script: Element by element(Declaration) {
parentInVisitor = declarationBase
generateIrFactoryMethod = false generateIrFactoryMethod = false
parent(declarationBase) parent(declarationBase)
@@ -567,7 +548,6 @@ object IrTree : AbstractTreeBuilder() {
+field("constructor", constructor, nullable = true) // K1 +field("constructor", constructor, nullable = true) // K1
} }
val simpleFunction: Element by element(Declaration) { val simpleFunction: Element by element(Declaration) {
parentInVisitor = function
isLeaf = true isLeaf = true
parent(function) parent(function)
@@ -585,8 +565,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val typeAlias: Element by element(Declaration) { val typeAlias: Element by element(Declaration) {
parentInVisitor = declarationBase
parent(declarationBase) parent(declarationBase)
parent(declarationWithName) parent(declarationWithName)
parent(declarationWithVisibility) parent(declarationWithVisibility)
@@ -598,8 +576,6 @@ object IrTree : AbstractTreeBuilder() {
+field("expandedType", irTypeType) +field("expandedType", irTypeType)
} }
val variable: Element by element(Declaration) { val variable: Element by element(Declaration) {
parentInVisitor = declarationBase
generateIrFactoryMethod = false generateIrFactoryMethod = false
parent(declarationBase) parent(declarationBase)
@@ -613,7 +589,6 @@ object IrTree : AbstractTreeBuilder() {
+field("initializer", expression, nullable = true, isChild = true) +field("initializer", expression, nullable = true, isChild = true)
} }
val packageFragment: Element by element(Declaration) { val packageFragment: Element by element(Declaration) {
parentInVisitor = rootElement
ownsChildren = false ownsChildren = false
parent(declarationContainer) parent(declarationContainer)
@@ -643,7 +618,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val externalPackageFragment: Element by element(Declaration) { val externalPackageFragment: Element by element(Declaration) {
parentInVisitor = packageFragment
transformByChildren = true transformByChildren = true
generateIrFactoryMethod = false generateIrFactoryMethod = false
@@ -653,9 +627,8 @@ object IrTree : AbstractTreeBuilder() {
+field("containerSource", type<DeserializedContainerSource>(), nullable = true, mutable = false) +field("containerSource", type<DeserializedContainerSource>(), nullable = true, mutable = false)
} }
val file: Element by element(Declaration) { val file: Element by element(Declaration) {
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
parentInVisitor = packageFragment
generateIrFactoryMethod = false generateIrFactoryMethod = false
parent(packageFragment) parent(packageFragment)
@@ -668,8 +641,7 @@ object IrTree : AbstractTreeBuilder() {
} }
val expression: Element by element(Expression) { val expression: Element by element(Expression) {
parentInVisitor = rootElement needTransformMethod()
hasTransformMethod = true
transformByChildren = true transformByChildren = true
parent(statement) parent(statement)
@@ -692,15 +664,13 @@ object IrTree : AbstractTreeBuilder() {
+listField("statements", statement, mutability = List, isChild = true) +listField("statements", statement, mutability = List, isChild = true)
} }
val body: Element by element(Expression) { val body: Element by element(Expression) {
hasTransformMethod = true needTransformMethod()
parentInVisitor = rootElement
visitorParameterName = "body" visitorParameterName = "body"
transformByChildren = true transformByChildren = true
typeKind = TypeKind.Class typeKind = TypeKind.Class
} }
val expressionBody: Element by element(Expression) { val expressionBody: Element by element(Expression) {
hasTransformMethod = true needTransformMethod()
parentInVisitor = body
visitorParameterName = "body" visitorParameterName = "body"
generateIrFactoryMethod = true generateIrFactoryMethod = true
@@ -712,7 +682,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val blockBody: Element by element(Expression) { val blockBody: Element by element(Expression) {
parentInVisitor = body
visitorParameterName = "body" visitorParameterName = "body"
generateIrFactoryMethod = true generateIrFactoryMethod = true
@@ -722,15 +691,12 @@ object IrTree : AbstractTreeBuilder() {
+factory +factory
} }
val declarationReference: Element by element(Expression) { val declarationReference: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+symbol(symbolType) +symbol(symbolType)
//diff: no accept //diff: no accept
} }
val memberAccessExpression: Element by element(Expression) { val memberAccessExpression: Element by element(Expression) {
parentInVisitor = declarationReference
nameInVisitorMethod = "MemberAccess" nameInVisitorMethod = "MemberAccess"
transformerReturnType = rootElement transformerReturnType = rootElement
val s = +param("S", symbolType) val s = +param("S", symbolType)
@@ -812,7 +778,6 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val functionAccessExpression: Element by element(Expression) { val functionAccessExpression: Element by element(Expression) {
parentInVisitor = memberAccessExpression
nameInVisitorMethod = "FunctionAccess" nameInVisitorMethod = "FunctionAccess"
transformerReturnType = rootElement transformerReturnType = rootElement
@@ -821,7 +786,6 @@ object IrTree : AbstractTreeBuilder() {
+field("contextReceiversCount", int) +field("contextReceiversCount", int)
} }
val constructorCall: Element by element(Expression) { val constructorCall: Element by element(Expression) {
parentInVisitor = functionAccessExpression
transformerReturnType = rootElement transformerReturnType = rootElement
parent(functionAccessExpression) parent(functionAccessExpression)
@@ -833,20 +797,17 @@ object IrTree : AbstractTreeBuilder() {
+field("constructorTypeArgumentsCount", int) +field("constructorTypeArgumentsCount", int)
} }
val getSingletonValue: Element by element(Expression) { val getSingletonValue: Element by element(Expression) {
parentInVisitor = declarationReference
nameInVisitorMethod = "SingletonReference" nameInVisitorMethod = "SingletonReference"
parent(declarationReference) parent(declarationReference)
} }
val getObjectValue: Element by element(Expression) { val getObjectValue: Element by element(Expression) {
parentInVisitor = getSingletonValue
parent(getSingletonValue) parent(getSingletonValue)
+symbol(classSymbolType, mutable = true) +symbol(classSymbolType, mutable = true)
} }
val getEnumValue: Element by element(Expression) { val getEnumValue: Element by element(Expression) {
parentInVisitor = getSingletonValue
parent(getSingletonValue) parent(getSingletonValue)
@@ -860,15 +821,12 @@ object IrTree : AbstractTreeBuilder() {
* On JVM platform it represents a MethodHandle constant. * On JVM platform it represents a MethodHandle constant.
*/ */
val rawFunctionReference: Element by element(Expression) { val rawFunctionReference: Element by element(Expression) {
parentInVisitor = declarationReference
parent(declarationReference) parent(declarationReference)
+symbol(functionSymbolType, mutable = true) +symbol(functionSymbolType, mutable = true)
} }
val containerExpression: Element by element(Expression) { val containerExpression: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
parent(statementContainer) parent(statementContainer)
@@ -878,14 +836,11 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val block: Element by element(Expression) { val block: Element by element(Expression) {
parentInVisitor = containerExpression needAcceptMethod()
hasAcceptMethod = true
parent(containerExpression) parent(containerExpression)
} }
val composite: Element by element(Expression) { val composite: Element by element(Expression) {
parentInVisitor = containerExpression
parent(containerExpression) parent(containerExpression)
} }
val returnableBlock: Element by element(Expression) { val returnableBlock: Element by element(Expression) {
@@ -898,11 +853,12 @@ object IrTree : AbstractTreeBuilder() {
val inlinedFunctionBlock: Element by element(Expression) { val inlinedFunctionBlock: Element by element(Expression) {
parent(block) parent(block)
visitorParameterName = "inlinedBlock"
+field("inlineCall", functionAccessExpression) +field("inlineCall", functionAccessExpression)
+field("inlinedElement", rootElement) +field("inlinedElement", rootElement)
} }
val syntheticBody: Element by element(Expression) { val syntheticBody: Element by element(Expression) {
parentInVisitor = body
visitorParameterName = "body" visitorParameterName = "body"
parent(body) parent(body)
@@ -910,7 +866,6 @@ object IrTree : AbstractTreeBuilder() {
+field("kind", type(Packages.exprs, "IrSyntheticBodyKind")) +field("kind", type(Packages.exprs, "IrSyntheticBodyKind"))
} }
val breakContinue: Element by element(Expression) { val breakContinue: Element by element(Expression) {
parentInVisitor = expression
visitorParameterName = "jump" visitorParameterName = "jump"
parent(expression) parent(expression)
@@ -921,27 +876,22 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val `break` by element(Expression) { val `break` by element(Expression) {
parentInVisitor = breakContinue
visitorParameterName = "jump" visitorParameterName = "jump"
parent(breakContinue) parent(breakContinue)
} }
val `continue` by element(Expression) { val `continue` by element(Expression) {
parentInVisitor = breakContinue
visitorParameterName = "jump" visitorParameterName = "jump"
parent(breakContinue) parent(breakContinue)
} }
val call: Element by element(Expression) { val call: Element by element(Expression) {
parentInVisitor = functionAccessExpression
parent(functionAccessExpression) parent(functionAccessExpression)
+symbol(simpleFunctionSymbolType, mutable = true) +symbol(simpleFunctionSymbolType, mutable = true)
+field("superQualifierSymbol", classSymbolType, nullable = true) +field("superQualifierSymbol", classSymbolType, nullable = true)
} }
val callableReference: Element by element(Expression) { val callableReference: Element by element(Expression) {
parentInVisitor = memberAccessExpression
val s = +param("S", symbolType) val s = +param("S", symbolType)
parent(memberAccessExpression.withArgs("S" to s)) parent(memberAccessExpression.withArgs("S" to s))
@@ -949,15 +899,12 @@ object IrTree : AbstractTreeBuilder() {
+symbol(s, mutable = true) +symbol(s, mutable = true)
} }
val functionReference: Element by element(Expression) { val functionReference: Element by element(Expression) {
parentInVisitor = callableReference
parent(callableReference.withArgs("S" to functionSymbolType)) parent(callableReference.withArgs("S" to functionSymbolType))
+field("reflectionTarget", functionSymbolType, nullable = true) +field("reflectionTarget", functionSymbolType, nullable = true)
} }
val propertyReference: Element by element(Expression) { val propertyReference: Element by element(Expression) {
parentInVisitor = callableReference
parent(callableReference.withArgs("S" to propertySymbolType)) parent(callableReference.withArgs("S" to propertySymbolType))
+field("field", fieldSymbolType, nullable = true) +field("field", fieldSymbolType, nullable = true)
@@ -965,8 +912,6 @@ object IrTree : AbstractTreeBuilder() {
+field("setter", simpleFunctionSymbolType, nullable = true) +field("setter", simpleFunctionSymbolType, nullable = true)
} }
val localDelegatedPropertyReference: Element by element(Expression) { val localDelegatedPropertyReference: Element by element(Expression) {
parentInVisitor = callableReference
parent(callableReference.withArgs("S" to localDelegatedPropertySymbolType)) parent(callableReference.withArgs("S" to localDelegatedPropertySymbolType))
+field("delegate", variableSymbolType) +field("delegate", variableSymbolType)
@@ -974,15 +919,12 @@ object IrTree : AbstractTreeBuilder() {
+field("setter", simpleFunctionSymbolType, nullable = true) +field("setter", simpleFunctionSymbolType, nullable = true)
} }
val classReference: Element by element(Expression) { val classReference: Element by element(Expression) {
parentInVisitor = declarationReference
parent(declarationReference) parent(declarationReference)
+symbol(classifierSymbolType, mutable = true) +symbol(classifierSymbolType, mutable = true)
+field("classType", irTypeType) +field("classType", irTypeType)
} }
val const: Element by element(Expression) { val const: Element by element(Expression) {
parentInVisitor = expression
val t = +param("T") val t = +param("T")
parent(expression) parent(expression)
@@ -991,7 +933,6 @@ object IrTree : AbstractTreeBuilder() {
+field("value", t) +field("value", t)
} }
val constantValue: Element by element(Expression) { val constantValue: Element by element(Expression) {
parentInVisitor = expression
transformByChildren = true transformByChildren = true
parent(expression) parent(expression)
@@ -1016,15 +957,11 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val constantPrimitive: Element by element(Expression) { val constantPrimitive: Element by element(Expression) {
parentInVisitor = constantValue
parent(constantValue) parent(constantValue)
+field("value", const.withArgs("T" to TypeRef.Star), isChild = true) +field("value", const.withArgs("T" to TypeRef.Star), isChild = true)
} }
val constantObject: Element by element(Expression) { val constantObject: Element by element(Expression) {
parentInVisitor = constantValue
parent(constantValue) parent(constantValue)
+field("constructor", constructorSymbolType) +field("constructor", constructorSymbolType)
@@ -1032,27 +969,19 @@ object IrTree : AbstractTreeBuilder() {
+listField("typeArguments", irTypeType, mutability = List) +listField("typeArguments", irTypeType, mutability = List)
} }
val constantArray: Element by element(Expression) { val constantArray: Element by element(Expression) {
parentInVisitor = constantValue
parent(constantValue) parent(constantValue)
+listField("elements", constantValue, mutability = List, isChild = true) +listField("elements", constantValue, mutability = List, isChild = true)
} }
val delegatingConstructorCall: Element by element(Expression) { val delegatingConstructorCall: Element by element(Expression) {
parentInVisitor = functionAccessExpression
parent(functionAccessExpression) parent(functionAccessExpression)
+symbol(constructorSymbolType, mutable = true) +symbol(constructorSymbolType, mutable = true)
} }
val dynamicExpression: Element by element(Expression) { val dynamicExpression: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
} }
val dynamicOperatorExpression: Element by element(Expression) { val dynamicOperatorExpression: Element by element(Expression) {
parentInVisitor = dynamicExpression
parent(dynamicExpression) parent(dynamicExpression)
+field("operator", type(Packages.exprs, "IrDynamicOperator")) +field("operator", type(Packages.exprs, "IrDynamicOperator"))
@@ -1060,38 +989,30 @@ object IrTree : AbstractTreeBuilder() {
+listField("arguments", expression, mutability = List, isChild = true) +listField("arguments", expression, mutability = List, isChild = true)
} }
val dynamicMemberExpression: Element by element(Expression) { val dynamicMemberExpression: Element by element(Expression) {
parentInVisitor = dynamicExpression
parent(dynamicExpression) parent(dynamicExpression)
+field("memberName", string) +field("memberName", string)
+field("receiver", expression, isChild = true) +field("receiver", expression, isChild = true)
} }
val enumConstructorCall: Element by element(Expression) { val enumConstructorCall: Element by element(Expression) {
parentInVisitor = functionAccessExpression
parent(functionAccessExpression) parent(functionAccessExpression)
+symbol(constructorSymbolType, mutable = true) +symbol(constructorSymbolType, mutable = true)
} }
val errorExpression: Element by element(Expression) { val errorExpression: Element by element(Expression) {
parentInVisitor = expression needAcceptMethod()
hasAcceptMethod = true
parent(expression) parent(expression)
+field("description", string) +field("description", string)
} }
val errorCallExpression: Element by element(Expression) { val errorCallExpression: Element by element(Expression) {
parentInVisitor = errorExpression
parent(errorExpression) parent(errorExpression)
+field("explicitReceiver", expression, nullable = true, isChild = true) +field("explicitReceiver", expression, nullable = true, isChild = true)
+listField("arguments", expression, mutability = List, isChild = true) +listField("arguments", expression, mutability = List, isChild = true)
} }
val fieldAccessExpression: Element by element(Expression) { val fieldAccessExpression: Element by element(Expression) {
parentInVisitor = declarationReference
nameInVisitorMethod = "FieldAccess" nameInVisitorMethod = "FieldAccess"
ownsChildren = false ownsChildren = false
@@ -1105,19 +1026,14 @@ object IrTree : AbstractTreeBuilder() {
+field("origin", statementOriginType, nullable = true) +field("origin", statementOriginType, nullable = true)
} }
val getField: Element by element(Expression) { val getField: Element by element(Expression) {
parentInVisitor = fieldAccessExpression
parent(fieldAccessExpression) parent(fieldAccessExpression)
} }
val setField: Element by element(Expression) { val setField: Element by element(Expression) {
parentInVisitor = fieldAccessExpression
parent(fieldAccessExpression) parent(fieldAccessExpression)
+field("value", expression, isChild = true) +field("value", expression, isChild = true)
} }
val functionExpression: Element by element(Expression) { val functionExpression: Element by element(Expression) {
parentInVisitor = expression
transformerReturnType = rootElement transformerReturnType = rootElement
parent(expression) parent(expression)
@@ -1126,21 +1042,16 @@ object IrTree : AbstractTreeBuilder() {
+field("function", simpleFunction, isChild = true) +field("function", simpleFunction, isChild = true)
} }
val getClass: Element by element(Expression) { val getClass: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("argument", expression, isChild = true) +field("argument", expression, isChild = true)
} }
val instanceInitializerCall: Element by element(Expression) { val instanceInitializerCall: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("classSymbol", classSymbolType) +field("classSymbol", classSymbolType)
} }
val loop: Element by element(Expression) { val loop: Element by element(Expression) {
parentInVisitor = expression
visitorParameterName = "loop" visitorParameterName = "loop"
ownsChildren = false ownsChildren = false
@@ -1156,36 +1067,28 @@ object IrTree : AbstractTreeBuilder() {
} }
} }
val whileLoop: Element by element(Expression) { val whileLoop: Element by element(Expression) {
parentInVisitor = loop
visitorParameterName = "loop" visitorParameterName = "loop"
childrenOrderOverride = listOf("condition", "body") childrenOrderOverride = listOf("condition", "body")
parent(loop) parent(loop)
} }
val doWhileLoop: Element by element(Expression) { val doWhileLoop: Element by element(Expression) {
parentInVisitor = loop
visitorParameterName = "loop" visitorParameterName = "loop"
parent(loop) parent(loop)
} }
val `return`: Element by element(Expression) { val `return`: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("value", expression, isChild = true) +field("value", expression, isChild = true)
+field("returnTargetSymbol", returnTargetSymbolType) +field("returnTargetSymbol", returnTargetSymbolType)
} }
val stringConcatenation: Element by element(Expression) { val stringConcatenation: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+listField("arguments", expression, mutability = List, isChild = true) +listField("arguments", expression, mutability = List, isChild = true)
} }
val suspensionPoint: Element by element(Expression) { val suspensionPoint: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("suspensionPointIdParameter", variable, isChild = true) +field("suspensionPointIdParameter", variable, isChild = true)
@@ -1193,22 +1096,17 @@ object IrTree : AbstractTreeBuilder() {
+field("resumeResult", expression, isChild = true) +field("resumeResult", expression, isChild = true)
} }
val suspendableExpression: Element by element(Expression) { val suspendableExpression: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("suspensionPointId", expression, isChild = true) +field("suspensionPointId", expression, isChild = true)
+field("result", expression, isChild = true) +field("result", expression, isChild = true)
} }
val `throw`: Element by element(Expression) { val `throw`: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("value", expression, isChild = true) +field("value", expression, isChild = true)
} }
val `try`: Element by element(Expression) { val `try`: Element by element(Expression) {
parentInVisitor = expression
visitorParameterName = "aTry" visitorParameterName = "aTry"
parent(expression) parent(expression)
@@ -1218,16 +1116,14 @@ object IrTree : AbstractTreeBuilder() {
+field("finallyExpression", expression, nullable = true, isChild = true) +field("finallyExpression", expression, nullable = true, isChild = true)
} }
val catch: Element by element(Expression) { val catch: Element by element(Expression) {
parentInVisitor = rootElement
visitorParameterName = "aCatch" visitorParameterName = "aCatch"
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
+field("catchParameter", variable, isChild = true) +field("catchParameter", variable, isChild = true)
+field("result", expression, isChild = true) +field("result", expression, isChild = true)
} }
val typeOperatorCall: Element by element(Expression) { val typeOperatorCall: Element by element(Expression) {
parentInVisitor = expression
nameInVisitorMethod = "TypeOperator" nameInVisitorMethod = "TypeOperator"
parent(expression) parent(expression)
@@ -1237,7 +1133,6 @@ object IrTree : AbstractTreeBuilder() {
+field("typeOperand", irTypeType) +field("typeOperand", irTypeType)
} }
val valueAccessExpression: Element by element(Expression) { val valueAccessExpression: Element by element(Expression) {
parentInVisitor = declarationReference
nameInVisitorMethod = "ValueAccess" nameInVisitorMethod = "ValueAccess"
parent(declarationReference) parent(declarationReference)
@@ -1246,30 +1141,23 @@ object IrTree : AbstractTreeBuilder() {
+field("origin", statementOriginType, nullable = true) +field("origin", statementOriginType, nullable = true)
} }
val getValue: Element by element(Expression) { val getValue: Element by element(Expression) {
parentInVisitor = valueAccessExpression
parent(valueAccessExpression) parent(valueAccessExpression)
} }
val setValue: Element by element(Expression) { val setValue: Element by element(Expression) {
parentInVisitor = valueAccessExpression
parent(valueAccessExpression) parent(valueAccessExpression)
+field("value", expression, isChild = true) +field("value", expression, isChild = true)
} }
val varargElement: Element by element(Expression) val varargElement: Element by element(Expression)
val vararg: Element by element(Expression) { val vararg: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("varargElementType", irTypeType) +field("varargElementType", irTypeType)
+listField("elements", varargElement, mutability = List, isChild = true) +listField("elements", varargElement, mutability = List, isChild = true)
} }
val spreadElement: Element by element(Expression) { val spreadElement: Element by element(Expression) {
parentInVisitor = rootElement
visitorParameterName = "spread" visitorParameterName = "spread"
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
parent(varargElement) parent(varargElement)
@@ -1277,27 +1165,23 @@ object IrTree : AbstractTreeBuilder() {
+field("expression", expression, isChild = true) +field("expression", expression, isChild = true)
} }
val `when`: Element by element(Expression) { val `when`: Element by element(Expression) {
parentInVisitor = expression
parent(expression) parent(expression)
+field("origin", statementOriginType, nullable = true) +field("origin", statementOriginType, nullable = true)
+listField("branches", branch, mutability = List, isChild = true) +listField("branches", branch, mutability = List, isChild = true)
} }
val branch: Element by element(Expression) { val branch: Element by element(Expression) {
parentInVisitor = rootElement
visitorParameterName = "branch" visitorParameterName = "branch"
hasAcceptMethod = true needAcceptMethod()
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
+field("condition", expression, isChild = true) +field("condition", expression, isChild = true)
+field("result", expression, isChild = true) +field("result", expression, isChild = true)
} }
val elseBranch: Element by element(Expression) { val elseBranch: Element by element(Expression) {
parentInVisitor = branch
visitorParameterName = "branch" visitorParameterName = "branch"
hasTransformMethod = true needTransformMethod()
transformByChildren = true transformByChildren = true
parent(branch) parent(branch)
@@ -50,6 +50,22 @@ abstract class AbstractTreeBuilder {
elementParents.add(ElementRef(type.element, type.args, type.nullable)) elementParents.add(ElementRef(type.element, type.args, type.nullable))
} }
protected fun Element.needAcceptMethod() {
customHasAcceptMethod = true
}
protected fun Element.noAcceptMethod() {
customHasAcceptMethod = false
}
protected fun Element.needTransformMethod() {
hasTransformMethod = true
}
protected fun Element.noMethodInVisitor() {
generateVisitorMethod = false
}
protected fun param(name: String, vararg bounds: TypeRef, variance: Variance = Variance.INVARIANT): TypeVariable { protected fun param(name: String, vararg bounds: TypeRef, variance: Variance = Variance.INVARIANT): TypeVariable {
return TypeVariable(name, bounds.toList(), variance) return TypeVariable(name, bounds.toList(), variance)
} }
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.ir.generator.model
import org.jetbrains.kotlin.generators.tree.* import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.ListField as AbstractListField import org.jetbrains.kotlin.generators.tree.ListField as AbstractListField
import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE
import org.jetbrains.kotlin.ir.generator.IrTree
import org.jetbrains.kotlin.ir.generator.elementBaseType
import org.jetbrains.kotlin.utils.SmartPrinter import org.jetbrains.kotlin.utils.SmartPrinter
import org.jetbrains.kotlin.utils.topologicalSort import org.jetbrains.kotlin.utils.topologicalSort
import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef
@@ -53,7 +55,19 @@ class Element(
override val args: Map<NamedTypeParameterRef, TypeRef> override val args: Map<NamedTypeParameterRef, TypeRef>
get() = emptyMap() get() = emptyMap()
override var parentInVisitor: Element? = null /**
* Allows to forcibly skip generation of the method for this element in visitors.
*/
var generateVisitorMethod = true
override val parentInVisitor: Element?
get() {
if (!generateVisitorMethod) return null
return customParentInVisitor
?: elementParents.singleOrNull { it.typeKind == TypeKind.Class }?.element
?: IrTree.rootElement.takeIf { elementBaseType in otherParents }
}
var typeKind: TypeKind? = null var typeKind: TypeKind? = null
set(value) { set(value) {
@@ -86,7 +100,11 @@ class Element(
override var visitorParameterName = category.defaultVisitorParam override var visitorParameterName = category.defaultVisitorParam
override var hasAcceptMethod = false // By default, accept is generated only for leaves. var customHasAcceptMethod: Boolean? = null
override val hasAcceptMethod: Boolean
get() = customHasAcceptMethod ?: (isLeaf && parentInVisitor != null)
override var hasTransformMethod = false override var hasTransformMethod = false
@@ -37,9 +37,6 @@ internal fun markLeaves(elements: List<Element>) {
for (el in leaves) { for (el in leaves) {
el.isLeaf = true el.isLeaf = true
if (el.parentInVisitor != null) {
el.hasAcceptMethod = true
}
} }
} }
@@ -56,10 +56,16 @@ abstract class AbstractElement<Element, Field>(
*/ */
abstract val visitorParameterName: String abstract val visitorParameterName: String
/**
* @see parentInVisitor
*/
var customParentInVisitor: Element? = null
/** /**
* The default element to visit if the method for visiting this element is not overridden. * The default element to visit if the method for visiting this element is not overridden.
*/ */
abstract val parentInVisitor: Element? open val parentInVisitor: Element?
get() = customParentInVisitor ?: elementParents.singleOrNull()?.element?.takeIf { !it.isRootElement }
override val allParents: List<Element> override val allParents: List<Element>
get() = elementParents.map { it.element } get() = elementParents.map { it.element }
@@ -92,7 +98,7 @@ abstract class AbstractElement<Element, Field>(
/** /**
* The return type of the corresponding transformer method for this element. * The return type of the corresponding transformer method for this element.
* *
* By default, computed using [org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes], but can be customizaed via * By default, computed using [org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes], but can be customized via
* [transformerReturnType] * [transformerReturnType]
*/ */
val transformerClass: Element val transformerClass: Element
@@ -11,7 +11,7 @@ fun <Element : AbstractElement<Element, *>> Element.traverseParents(block: (Elem
} }
/** /**
* For each tree element, sets its [AbstractElement.baseTransformerType] to one of it parents if that parent type is used at least once as * For each tree element, sets its [AbstractElement.baseTransformerType] to one of its parents if that parent type is used at least once as
* a type of a field, except when that field is explicitly opted out of it via * a type of a field, except when that field is explicitly opted out of it via
* [AbstractField.useInBaseTransformerDetection]. * [AbstractField.useInBaseTransformerDetection].
*/ */