diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt index a43e5181716..ac478407e91 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt @@ -14,13 +14,11 @@ import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration import org.jetbrains.kotlin.generators.tree.printer.printFunctionWithBlockBody import org.jetbrains.kotlin.ir.generator.config.AbstractTreeBuilder -import org.jetbrains.kotlin.ir.generator.config.ElementConfig -import org.jetbrains.kotlin.ir.generator.config.ElementConfig.Category.* -import org.jetbrains.kotlin.ir.generator.config.ListFieldConfig.Mutability.* -import org.jetbrains.kotlin.ir.generator.config.ListFieldConfig.Mutability.Array -import org.jetbrains.kotlin.ir.generator.config.ListFieldConfig.Mutability.List -import org.jetbrains.kotlin.ir.generator.config.SimpleFieldConfig +import org.jetbrains.kotlin.ir.generator.model.Element +import org.jetbrains.kotlin.ir.generator.model.Element.Category.* import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName +import org.jetbrains.kotlin.ir.generator.model.ListField.Mutability.* +import org.jetbrains.kotlin.ir.generator.model.SingleField import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -28,14 +26,14 @@ import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.withIndent // Note the style of the DSL to describe IR elements, which is these things in the following order: -// 1) config (see properties of ElementConfig) +// 1) config (see properties of Element) // 2) parents // 3) fields object IrTree : AbstractTreeBuilder() { - private fun symbol(type: TypeRefWithNullability, mutable: Boolean = false): SimpleFieldConfig = + private fun symbol(type: TypeRefWithNullability, mutable: Boolean = false): SingleField = field("symbol", type, mutable = mutable) - private fun descriptor(typeName: String, nullable: Boolean = false): SimpleFieldConfig = + private fun descriptor(typeName: String, nullable: Boolean = false): SingleField = field( name = "descriptor", type = type(Packages.descriptors, typeName), @@ -46,7 +44,7 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } - private fun declarationWithLateBinding(symbol: ClassRef<*>, initializer: ElementConfig.() -> Unit) = element(Declaration) { + private fun declarationWithLateBinding(symbol: ClassRef<*>, initializer: Element.() -> Unit) = element(Declaration) { initializer() fieldsToSkipInIrFactoryMethod.add("symbol") @@ -68,13 +66,13 @@ object IrTree : AbstractTreeBuilder() { } } - private val factory: SimpleFieldConfig = field("factory", irFactoryType, mutable = false) { + private val factory: SingleField = field("factory", irFactoryType, mutable = false) { skipInIrFactory() } - override val rootElement: ElementConfig by element(Other, name = "element") { - accept = true - transform = true + override val rootElement: Element by element(Other, name = "element") { + hasAcceptMethod = true + hasTransformMethod = true transformByChildren = true fun offsetField(prefix: String) = field(prefix + "Offset", int, mutable = false) { @@ -93,9 +91,9 @@ object IrTree : AbstractTreeBuilder() { kDoc = "The root interface of the IR tree. Each IR node implements this interface." } - val statement: ElementConfig by element(Other) + val statement: Element by element(Other) - val declaration: ElementConfig by element(Declaration) { + val declaration: Element by element(Declaration) { parent(statement) parent(symbolOwner) parent(mutableAnnotationContainerType) @@ -107,37 +105,37 @@ object IrTree : AbstractTreeBuilder() { } +factory } - val declarationBase: ElementConfig by element(Declaration) { + val declarationBase: Element by element(Declaration) { typeKind = TypeKind.Class transformByChildren = true transformerReturnType = statement - visitorParent = rootElement + parentInVisitor = rootElement visitorName = "declaration" parent(declaration) } - val declarationParent: ElementConfig by element(Declaration) - val declarationWithVisibility: ElementConfig by element(Declaration) { + val declarationParent: Element by element(Declaration) + val declarationWithVisibility: Element by element(Declaration) { parent(declaration) +field("visibility", type(Packages.descriptors, "DescriptorVisibility")) } - val declarationWithName: ElementConfig by element(Declaration) { + val declarationWithName: Element by element(Declaration) { parent(declaration) +field("name", type()) } - val possiblyExternalDeclaration: ElementConfig by element(Declaration) { + val possiblyExternalDeclaration: Element by element(Declaration) { parent(declarationWithName) +field("isExternal", boolean) { useFieldInIrFactory(defaultValue = "false") } } - val symbolOwner: ElementConfig by element(Declaration) { + val symbolOwner: Element by element(Declaration) { +symbol(symbolType) } - val metadataSourceOwner: ElementConfig by element(Declaration) { + val metadataSourceOwner: Element by element(Declaration) { val metadataField = +field("metadata", type(Packages.declarations, "MetadataSource"), nullable = true) { skipInIrFactory() kDoc = """ @@ -159,7 +157,7 @@ object IrTree : AbstractTreeBuilder() { but this is only for performance purposes (before it was done using simple maps). """.trimIndent() } - val overridableMember: ElementConfig by element(Declaration) { + val overridableMember: Element by element(Declaration) { parent(declaration) parent(declarationWithVisibility) parent(declarationWithName) @@ -167,7 +165,7 @@ object IrTree : AbstractTreeBuilder() { +field("modality", type()) } - val overridableDeclaration: ElementConfig by element(Declaration) { + val overridableDeclaration: Element by element(Declaration) { val s = +param("S", symbolType) parent(overridableMember) @@ -178,14 +176,14 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val memberWithContainerSource: ElementConfig by element(Declaration) { + val memberWithContainerSource: Element by element(Declaration) { parent(declarationWithName) +field("containerSource", type(), nullable = true, mutable = false) { useFieldInIrFactory(defaultValue = "null") } } - val valueDeclaration: ElementConfig by element(Declaration) { + val valueDeclaration: Element by element(Declaration) { parent(declarationWithName) parent(symbolOwner) @@ -194,9 +192,9 @@ object IrTree : AbstractTreeBuilder() { +field("type", irTypeType) +field("isAssignable", boolean, mutable = false) } - val valueParameter: ElementConfig by element(Declaration) { - transform = true - visitorParent = declarationBase + val valueParameter: Element by element(Declaration) { + hasTransformMethod = true + parentInVisitor = declarationBase parent(declarationBase) parent(valueDeclaration) @@ -239,8 +237,8 @@ object IrTree : AbstractTreeBuilder() { } +field("defaultValue", expressionBody, nullable = true, isChild = true) } - val `class`: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val `class`: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(possiblyExternalDeclaration) @@ -306,7 +304,7 @@ object IrTree : AbstractTreeBuilder() { """.trimIndent() } } - val attributeContainer: ElementConfig by element(Declaration) { + val attributeContainer: Element by element(Declaration) { kDoc = """ Represents an IR element that can be copied, but must remember its original element. It is useful, for example, to keep track of generated names for anonymous declarations. @@ -325,8 +323,8 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val anonymousInitializer: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val anonymousInitializer: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) @@ -337,7 +335,7 @@ object IrTree : AbstractTreeBuilder() { } +field("body", blockBody, isChild = true) } - val declarationContainer: ElementConfig by element(Declaration) { + val declarationContainer: Element by element(Declaration) { ownsChildren = false parent(declarationParent) @@ -352,7 +350,7 @@ object IrTree : AbstractTreeBuilder() { optInAnnotation = unsafeDuringIrConstructionApiAnnotation } } - val typeParametersContainer: ElementConfig by element(Declaration) { + val typeParametersContainer: Element by element(Declaration) { ownsChildren = false parent(declaration) @@ -360,9 +358,9 @@ object IrTree : AbstractTreeBuilder() { +listField("typeParameters", typeParameter, mutability = Var, isChild = true) } - val typeParameter: ElementConfig by element(Declaration) { - visitorParent = declarationBase - transform = true + val typeParameter: Element by element(Declaration) { + parentInVisitor = declarationBase + hasTransformMethod = true parent(declarationBase) parent(declarationWithName) @@ -376,14 +374,14 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val returnTarget: ElementConfig by element(Declaration) { + val returnTarget: Element by element(Declaration) { parent(symbolOwner) +descriptor("FunctionDescriptor") +symbol(returnTargetSymbolType) } - val function: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val function: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(possiblyExternalDeclaration) @@ -410,8 +408,8 @@ object IrTree : AbstractTreeBuilder() { } +field("body", body, nullable = true, isChild = true) } - val constructor: ElementConfig by element(Declaration) { - visitorParent = function + val constructor: Element by element(Declaration) { + parentInVisitor = function parent(function) @@ -419,8 +417,8 @@ object IrTree : AbstractTreeBuilder() { +symbol(constructorSymbolType) +field("isPrimary", boolean) } - val enumEntry: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val enumEntry: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(declarationWithName) @@ -430,8 +428,8 @@ object IrTree : AbstractTreeBuilder() { +field("initializerExpression", expressionBody, nullable = true, isChild = true) +field("correspondingClass", `class`, nullable = true, isChild = true) } - val errorDeclaration: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val errorDeclaration: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) @@ -448,14 +446,14 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val functionWithLateBinding: ElementConfig by declarationWithLateBinding(simpleFunctionSymbolType) { + val functionWithLateBinding: Element by declarationWithLateBinding(simpleFunctionSymbolType) { parent(simpleFunction) } - val propertyWithLateBinding: ElementConfig by declarationWithLateBinding(propertySymbolType) { + val propertyWithLateBinding: Element by declarationWithLateBinding(propertySymbolType) { parent(property) } - val field: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val field: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(possiblyExternalDeclaration) @@ -473,8 +471,8 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val localDelegatedProperty: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val localDelegatedProperty: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(declarationWithName) @@ -489,9 +487,9 @@ object IrTree : AbstractTreeBuilder() { +field("getter", simpleFunction, isChild = true) +field("setter", simpleFunction, nullable = true, isChild = true) } - val moduleFragment: ElementConfig by element(Declaration) { - visitorParent = rootElement - transform = true + val moduleFragment: Element by element(Declaration) { + parentInVisitor = rootElement + hasTransformMethod = true transformByChildren = true generateIrFactoryMethod = false @@ -509,9 +507,9 @@ object IrTree : AbstractTreeBuilder() { baseGetter = "UNDEFINED_OFFSET" } } - val property: ElementConfig by element(Declaration) { - visitorParent = declarationBase - isForcedLeaf = true + val property: Element by element(Declaration) { + parentInVisitor = declarationBase + isLeaf = true parent(declarationBase) parent(possiblyExternalDeclaration) @@ -541,8 +539,8 @@ object IrTree : AbstractTreeBuilder() { //TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class //NOTE: declarations and statements stored separately - val script: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val script: Element by element(Declaration) { + parentInVisitor = declarationBase generateIrFactoryMethod = false parent(declarationBase) @@ -567,9 +565,9 @@ object IrTree : AbstractTreeBuilder() { +field("targetClass", classSymbolType, nullable = true) +field("constructor", constructor, nullable = true) // K1 } - val simpleFunction: ElementConfig by element(Declaration) { - visitorParent = function - isForcedLeaf = true + val simpleFunction: Element by element(Declaration) { + parentInVisitor = function + isLeaf = true parent(function) parent(overridableDeclaration.withArgs("S" to simpleFunctionSymbolType)) @@ -585,8 +583,8 @@ object IrTree : AbstractTreeBuilder() { skipInIrFactory() } } - val typeAlias: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val typeAlias: Element by element(Declaration) { + parentInVisitor = declarationBase parent(declarationBase) parent(declarationWithName) @@ -598,8 +596,8 @@ object IrTree : AbstractTreeBuilder() { +field("isActual", boolean) +field("expandedType", irTypeType) } - val variable: ElementConfig by element(Declaration) { - visitorParent = declarationBase + val variable: Element by element(Declaration) { + parentInVisitor = declarationBase generateIrFactoryMethod = false @@ -613,8 +611,8 @@ object IrTree : AbstractTreeBuilder() { +field("isLateinit", boolean) +field("initializer", expression, nullable = true, isChild = true) } - val packageFragment: ElementConfig by element(Declaration) { - visitorParent = rootElement + val packageFragment: Element by element(Declaration) { + parentInVisitor = rootElement ownsChildren = false parent(declarationContainer) @@ -643,8 +641,8 @@ object IrTree : AbstractTreeBuilder() { ) } } - val externalPackageFragment: ElementConfig by element(Declaration) { - visitorParent = packageFragment + val externalPackageFragment: Element by element(Declaration) { + parentInVisitor = packageFragment transformByChildren = true generateIrFactoryMethod = false @@ -653,10 +651,10 @@ object IrTree : AbstractTreeBuilder() { +symbol(externalPackageFragmentSymbolType) +field("containerSource", type(), nullable = true, mutable = false) } - val file: ElementConfig by element(Declaration) { - transform = true + val file: Element by element(Declaration) { + hasTransformMethod = true transformByChildren = true - visitorParent = packageFragment + parentInVisitor = packageFragment generateIrFactoryMethod = false parent(packageFragment) @@ -668,9 +666,9 @@ object IrTree : AbstractTreeBuilder() { +field("fileEntry", type(Packages.tree, "IrFileEntry")) } - val expression: ElementConfig by element(Expression) { - visitorParent = rootElement - transform = true + val expression: Element by element(Expression) { + parentInVisitor = rootElement + hasTransformMethod = true transformByChildren = true parent(statement) @@ -687,22 +685,22 @@ object IrTree : AbstractTreeBuilder() { } +field("type", irTypeType) } - val statementContainer: ElementConfig by element(Expression) { + val statementContainer: Element by element(Expression) { ownsChildren = false +listField("statements", statement, mutability = List, isChild = true) } - val body: ElementConfig by element(Expression) { - transform = true - visitorParent = rootElement - visitorParam = "body" + val body: Element by element(Expression) { + hasTransformMethod = true + parentInVisitor = rootElement + visitorParameterName = "body" transformByChildren = true typeKind = TypeKind.Class } - val expressionBody: ElementConfig by element(Expression) { - transform = true - visitorParent = body - visitorParam = "body" + val expressionBody: Element by element(Expression) { + hasTransformMethod = true + parentInVisitor = body + visitorParameterName = "body" generateIrFactoryMethod = true parent(body) @@ -712,9 +710,9 @@ object IrTree : AbstractTreeBuilder() { useFieldInIrFactory() } } - val blockBody: ElementConfig by element(Expression) { - visitorParent = body - visitorParam = "body" + val blockBody: Element by element(Expression) { + parentInVisitor = body + visitorParameterName = "body" generateIrFactoryMethod = true parent(body) @@ -722,16 +720,16 @@ object IrTree : AbstractTreeBuilder() { +factory } - val declarationReference: ElementConfig by element(Expression) { - visitorParent = expression + val declarationReference: Element by element(Expression) { + parentInVisitor = expression parent(expression) +symbol(symbolType) //diff: no accept } - val memberAccessExpression: ElementConfig by element(Expression) { - visitorParent = declarationReference + val memberAccessExpression: Element by element(Expression) { + parentInVisitor = declarationReference visitorName = "memberAccess" transformerReturnType = rootElement val s = +param("S", symbolType) @@ -812,8 +810,8 @@ object IrTree : AbstractTreeBuilder() { ) } } - val functionAccessExpression: ElementConfig by element(Expression) { - visitorParent = memberAccessExpression + val functionAccessExpression: Element by element(Expression) { + parentInVisitor = memberAccessExpression visitorName = "functionAccess" transformerReturnType = rootElement @@ -821,8 +819,8 @@ object IrTree : AbstractTreeBuilder() { +field("contextReceiversCount", int) } - val constructorCall: ElementConfig by element(Expression) { - visitorParent = functionAccessExpression + val constructorCall: Element by element(Expression) { + parentInVisitor = functionAccessExpression transformerReturnType = rootElement parent(functionAccessExpression) @@ -833,21 +831,21 @@ object IrTree : AbstractTreeBuilder() { } +field("constructorTypeArgumentsCount", int) } - val getSingletonValue: ElementConfig by element(Expression) { - visitorParent = declarationReference + val getSingletonValue: Element by element(Expression) { + parentInVisitor = declarationReference visitorName = "SingletonReference" parent(declarationReference) } - val getObjectValue: ElementConfig by element(Expression) { - visitorParent = getSingletonValue + val getObjectValue: Element by element(Expression) { + parentInVisitor = getSingletonValue parent(getSingletonValue) +symbol(classSymbolType, mutable = true) } - val getEnumValue: ElementConfig by element(Expression) { - visitorParent = getSingletonValue + val getEnumValue: Element by element(Expression) { + parentInVisitor = getSingletonValue parent(getSingletonValue) @@ -860,15 +858,15 @@ object IrTree : AbstractTreeBuilder() { * On JS platform it represents a plain reference to JavaScript function. * On JVM platform it represents a MethodHandle constant. */ - val rawFunctionReference: ElementConfig by element(Expression) { - visitorParent = declarationReference + val rawFunctionReference: Element by element(Expression) { + parentInVisitor = declarationReference parent(declarationReference) +symbol(functionSymbolType, mutable = true) } - val containerExpression: ElementConfig by element(Expression) { - visitorParent = expression + val containerExpression: Element by element(Expression) { + parentInVisitor = expression parent(expression) parent(statementContainer) @@ -878,41 +876,41 @@ object IrTree : AbstractTreeBuilder() { baseDefaultValue = "ArrayList(2)" } } - val block: ElementConfig by element(Expression) { - visitorParent = containerExpression - accept = true + val block: Element by element(Expression) { + parentInVisitor = containerExpression + hasAcceptMethod = true parent(containerExpression) } - val composite: ElementConfig by element(Expression) { - visitorParent = containerExpression + val composite: Element by element(Expression) { + parentInVisitor = containerExpression parent(containerExpression) } - val returnableBlock: ElementConfig by element(Expression) { + val returnableBlock: Element by element(Expression) { parent(block) parent(symbolOwner) parent(returnTarget) +symbol(returnableBlockSymbolType) } - val inlinedFunctionBlock: ElementConfig by element(Expression) { + val inlinedFunctionBlock: Element by element(Expression) { parent(block) +field("inlineCall", functionAccessExpression) +field("inlinedElement", rootElement) } - val syntheticBody: ElementConfig by element(Expression) { - visitorParent = body - visitorParam = "body" + val syntheticBody: Element by element(Expression) { + parentInVisitor = body + visitorParameterName = "body" parent(body) +field("kind", type(Packages.exprs, "IrSyntheticBodyKind")) } - val breakContinue: ElementConfig by element(Expression) { - visitorParent = expression - visitorParam = "jump" + val breakContinue: Element by element(Expression) { + parentInVisitor = expression + visitorParameterName = "jump" parent(expression) @@ -922,42 +920,42 @@ object IrTree : AbstractTreeBuilder() { } } val `break` by element(Expression) { - visitorParent = breakContinue - visitorParam = "jump" + parentInVisitor = breakContinue + visitorParameterName = "jump" parent(breakContinue) } val `continue` by element(Expression) { - visitorParent = breakContinue - visitorParam = "jump" + parentInVisitor = breakContinue + visitorParameterName = "jump" parent(breakContinue) } - val call: ElementConfig by element(Expression) { - visitorParent = functionAccessExpression + val call: Element by element(Expression) { + parentInVisitor = functionAccessExpression parent(functionAccessExpression) +symbol(simpleFunctionSymbolType, mutable = true) +field("superQualifierSymbol", classSymbolType, nullable = true) } - val callableReference: ElementConfig by element(Expression) { - visitorParent = memberAccessExpression + val callableReference: Element by element(Expression) { + parentInVisitor = memberAccessExpression val s = +param("S", symbolType) parent(memberAccessExpression.withArgs("S" to s)) +symbol(s, mutable = true) } - val functionReference: ElementConfig by element(Expression) { - visitorParent = callableReference + val functionReference: Element by element(Expression) { + parentInVisitor = callableReference parent(callableReference.withArgs("S" to functionSymbolType)) +field("reflectionTarget", functionSymbolType, nullable = true) } - val propertyReference: ElementConfig by element(Expression) { - visitorParent = callableReference + val propertyReference: Element by element(Expression) { + parentInVisitor = callableReference parent(callableReference.withArgs("S" to propertySymbolType)) @@ -965,8 +963,8 @@ object IrTree : AbstractTreeBuilder() { +field("getter", simpleFunctionSymbolType, nullable = true) +field("setter", simpleFunctionSymbolType, nullable = true) } - val localDelegatedPropertyReference: ElementConfig by element(Expression) { - visitorParent = callableReference + val localDelegatedPropertyReference: Element by element(Expression) { + parentInVisitor = callableReference parent(callableReference.withArgs("S" to localDelegatedPropertySymbolType)) @@ -974,16 +972,16 @@ object IrTree : AbstractTreeBuilder() { +field("getter", simpleFunctionSymbolType) +field("setter", simpleFunctionSymbolType, nullable = true) } - val classReference: ElementConfig by element(Expression) { - visitorParent = declarationReference + val classReference: Element by element(Expression) { + parentInVisitor = declarationReference parent(declarationReference) +symbol(classifierSymbolType, mutable = true) +field("classType", irTypeType) } - val const: ElementConfig by element(Expression) { - visitorParent = expression + val const: Element by element(Expression) { + parentInVisitor = expression val t = +param("T") parent(expression) @@ -991,8 +989,8 @@ object IrTree : AbstractTreeBuilder() { +field("kind", type(Packages.exprs, "IrConstKind").withArgs(t)) +field("value", t) } - val constantValue: ElementConfig by element(Expression) { - visitorParent = expression + val constantValue: Element by element(Expression) { + parentInVisitor = expression transformByChildren = true parent(expression) @@ -1016,15 +1014,15 @@ object IrTree : AbstractTreeBuilder() { println() } } - val constantPrimitive: ElementConfig by element(Expression) { - visitorParent = constantValue + val constantPrimitive: Element by element(Expression) { + parentInVisitor = constantValue parent(constantValue) +field("value", const.withArgs("T" to TypeRef.Star), isChild = true) } - val constantObject: ElementConfig by element(Expression) { - visitorParent = constantValue + val constantObject: Element by element(Expression) { + parentInVisitor = constantValue parent(constantValue) @@ -1032,27 +1030,27 @@ object IrTree : AbstractTreeBuilder() { +listField("valueArguments", constantValue, mutability = List, isChild = true) +listField("typeArguments", irTypeType, mutability = List) } - val constantArray: ElementConfig by element(Expression) { - visitorParent = constantValue + val constantArray: Element by element(Expression) { + parentInVisitor = constantValue parent(constantValue) +listField("elements", constantValue, mutability = List, isChild = true) } - val delegatingConstructorCall: ElementConfig by element(Expression) { - visitorParent = functionAccessExpression + val delegatingConstructorCall: Element by element(Expression) { + parentInVisitor = functionAccessExpression parent(functionAccessExpression) +symbol(constructorSymbolType, mutable = true) } - val dynamicExpression: ElementConfig by element(Expression) { - visitorParent = expression + val dynamicExpression: Element by element(Expression) { + parentInVisitor = expression parent(expression) } - val dynamicOperatorExpression: ElementConfig by element(Expression) { - visitorParent = dynamicExpression + val dynamicOperatorExpression: Element by element(Expression) { + parentInVisitor = dynamicExpression parent(dynamicExpression) @@ -1060,39 +1058,39 @@ object IrTree : AbstractTreeBuilder() { +field("receiver", expression, isChild = true) +listField("arguments", expression, mutability = List, isChild = true) } - val dynamicMemberExpression: ElementConfig by element(Expression) { - visitorParent = dynamicExpression + val dynamicMemberExpression: Element by element(Expression) { + parentInVisitor = dynamicExpression parent(dynamicExpression) +field("memberName", string) +field("receiver", expression, isChild = true) } - val enumConstructorCall: ElementConfig by element(Expression) { - visitorParent = functionAccessExpression + val enumConstructorCall: Element by element(Expression) { + parentInVisitor = functionAccessExpression parent(functionAccessExpression) +symbol(constructorSymbolType, mutable = true) } - val errorExpression: ElementConfig by element(Expression) { - visitorParent = expression - accept = true + val errorExpression: Element by element(Expression) { + parentInVisitor = expression + hasAcceptMethod = true parent(expression) +field("description", string) } - val errorCallExpression: ElementConfig by element(Expression) { - visitorParent = errorExpression + val errorCallExpression: Element by element(Expression) { + parentInVisitor = errorExpression parent(errorExpression) +field("explicitReceiver", expression, nullable = true, isChild = true) +listField("arguments", expression, mutability = List, isChild = true) } - val fieldAccessExpression: ElementConfig by element(Expression) { - visitorParent = declarationReference + val fieldAccessExpression: Element by element(Expression) { + parentInVisitor = declarationReference visitorName = "fieldAccess" ownsChildren = false @@ -1105,20 +1103,20 @@ object IrTree : AbstractTreeBuilder() { } +field("origin", statementOriginType, nullable = true) } - val getField: ElementConfig by element(Expression) { - visitorParent = fieldAccessExpression + val getField: Element by element(Expression) { + parentInVisitor = fieldAccessExpression parent(fieldAccessExpression) } - val setField: ElementConfig by element(Expression) { - visitorParent = fieldAccessExpression + val setField: Element by element(Expression) { + parentInVisitor = fieldAccessExpression parent(fieldAccessExpression) +field("value", expression, isChild = true) } - val functionExpression: ElementConfig by element(Expression) { - visitorParent = expression + val functionExpression: Element by element(Expression) { + parentInVisitor = expression transformerReturnType = rootElement parent(expression) @@ -1126,23 +1124,23 @@ object IrTree : AbstractTreeBuilder() { +field("origin", statementOriginType) +field("function", simpleFunction, isChild = true) } - val getClass: ElementConfig by element(Expression) { - visitorParent = expression + val getClass: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("argument", expression, isChild = true) } - val instanceInitializerCall: ElementConfig by element(Expression) { - visitorParent = expression + val instanceInitializerCall: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("classSymbol", classSymbolType) } - val loop: ElementConfig by element(Expression) { - visitorParent = expression - visitorParam = "loop" + val loop: Element by element(Expression) { + parentInVisitor = expression + visitorParameterName = "loop" ownsChildren = false parent(expression) @@ -1156,36 +1154,36 @@ object IrTree : AbstractTreeBuilder() { baseDefaultValue = "null" } } - val whileLoop: ElementConfig by element(Expression) { - visitorParent = loop - visitorParam = "loop" + val whileLoop: Element by element(Expression) { + parentInVisitor = loop + visitorParameterName = "loop" childrenOrderOverride = listOf("condition", "body") parent(loop) } - val doWhileLoop: ElementConfig by element(Expression) { - visitorParent = loop - visitorParam = "loop" + val doWhileLoop: Element by element(Expression) { + parentInVisitor = loop + visitorParameterName = "loop" parent(loop) } - val `return`: ElementConfig by element(Expression) { - visitorParent = expression + val `return`: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("value", expression, isChild = true) +field("returnTargetSymbol", returnTargetSymbolType) } - val stringConcatenation: ElementConfig by element(Expression) { - visitorParent = expression + val stringConcatenation: Element by element(Expression) { + parentInVisitor = expression parent(expression) +listField("arguments", expression, mutability = List, isChild = true) } - val suspensionPoint: ElementConfig by element(Expression) { - visitorParent = expression + val suspensionPoint: Element by element(Expression) { + parentInVisitor = expression parent(expression) @@ -1193,24 +1191,24 @@ object IrTree : AbstractTreeBuilder() { +field("result", expression, isChild = true) +field("resumeResult", expression, isChild = true) } - val suspendableExpression: ElementConfig by element(Expression) { - visitorParent = expression + val suspendableExpression: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("suspensionPointId", expression, isChild = true) +field("result", expression, isChild = true) } - val `throw`: ElementConfig by element(Expression) { - visitorParent = expression + val `throw`: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("value", expression, isChild = true) } - val `try`: ElementConfig by element(Expression) { - visitorParent = expression - visitorParam = "aTry" + val `try`: Element by element(Expression) { + parentInVisitor = expression + visitorParameterName = "aTry" parent(expression) @@ -1218,17 +1216,17 @@ object IrTree : AbstractTreeBuilder() { +listField("catches", catch, mutability = List, isChild = true) +field("finallyExpression", expression, nullable = true, isChild = true) } - val catch: ElementConfig by element(Expression) { - visitorParent = rootElement - visitorParam = "aCatch" - transform = true + val catch: Element by element(Expression) { + parentInVisitor = rootElement + visitorParameterName = "aCatch" + hasTransformMethod = true transformByChildren = true +field("catchParameter", variable, isChild = true) +field("result", expression, isChild = true) } - val typeOperatorCall: ElementConfig by element(Expression) { - visitorParent = expression + val typeOperatorCall: Element by element(Expression) { + parentInVisitor = expression visitorName = "typeOperator" parent(expression) @@ -1237,8 +1235,8 @@ object IrTree : AbstractTreeBuilder() { +field("argument", expression, isChild = true) +field("typeOperand", irTypeType) } - val valueAccessExpression: ElementConfig by element(Expression) { - visitorParent = declarationReference + val valueAccessExpression: Element by element(Expression) { + parentInVisitor = declarationReference visitorName = "valueAccess" parent(declarationReference) @@ -1246,59 +1244,59 @@ object IrTree : AbstractTreeBuilder() { +symbol(valueSymbolType, mutable = true) +field("origin", statementOriginType, nullable = true) } - val getValue: ElementConfig by element(Expression) { - visitorParent = valueAccessExpression + val getValue: Element by element(Expression) { + parentInVisitor = valueAccessExpression parent(valueAccessExpression) } - val setValue: ElementConfig by element(Expression) { - visitorParent = valueAccessExpression + val setValue: Element by element(Expression) { + parentInVisitor = valueAccessExpression parent(valueAccessExpression) +field("value", expression, isChild = true) } - val varargElement: ElementConfig by element(Expression) - val vararg: ElementConfig by element(Expression) { - visitorParent = expression + val varargElement: Element by element(Expression) + val vararg: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("varargElementType", irTypeType) +listField("elements", varargElement, mutability = List, isChild = true) } - val spreadElement: ElementConfig by element(Expression) { - visitorParent = rootElement - visitorParam = "spread" - transform = true + val spreadElement: Element by element(Expression) { + parentInVisitor = rootElement + visitorParameterName = "spread" + hasTransformMethod = true transformByChildren = true parent(varargElement) +field("expression", expression, isChild = true) } - val `when`: ElementConfig by element(Expression) { - visitorParent = expression + val `when`: Element by element(Expression) { + parentInVisitor = expression parent(expression) +field("origin", statementOriginType, nullable = true) +listField("branches", branch, mutability = List, isChild = true) } - val branch: ElementConfig by element(Expression) { - visitorParent = rootElement - visitorParam = "branch" - accept = true - transform = true + val branch: Element by element(Expression) { + parentInVisitor = rootElement + visitorParameterName = "branch" + hasAcceptMethod = true + hasTransformMethod = true transformByChildren = true +field("condition", expression, isChild = true) +field("result", expression, isChild = true) } - val elseBranch: ElementConfig by element(Expression) { - visitorParent = branch - visitorParam = "branch" - transform = true + val elseBranch: Element by element(Expression) { + parentInVisitor = branch + visitorParameterName = "branch" + hasTransformMethod = true transformByChildren = true parent(branch) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt index bbc50be5561..0347d909b86 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt @@ -5,10 +5,11 @@ package org.jetbrains.kotlin.ir.generator +import org.jetbrains.kotlin.generators.tree.addPureAbstractElement import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.collectPreviouslyGeneratedFiles import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.removeExtraFilesFromPreviousGeneration -import org.jetbrains.kotlin.ir.generator.model.config2model +import org.jetbrains.kotlin.ir.generator.model.* import org.jetbrains.kotlin.ir.generator.print.* import java.io.File @@ -20,8 +21,13 @@ fun main(args: Array) { val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/ir/ir.tree/gen").canonicalFile - val config = IrTree.build() - val model = config2model(config) + val model = IrTree.build() + + configureInterfacesAndAbstractClasses(model.elements) + addPureAbstractElement(model.elements, elementBaseType) + markLeaves(model.elements) + processFieldOverrides(model.elements) + addWalkableChildren(model.elements) val previouslyGeneratedFiles = collectPreviouslyGeneratedFiles(generationPath) val generatedFiles = sequence { diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt index 6282cd73c8b..252f2d45d28 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt @@ -5,30 +5,47 @@ package org.jetbrains.kotlin.ir.generator.config -import org.jetbrains.kotlin.generators.tree.TypeRef -import org.jetbrains.kotlin.generators.tree.TypeRefWithNullability -import org.jetbrains.kotlin.generators.tree.TypeVariable -import org.jetbrains.kotlin.generators.tree.type +import org.jetbrains.kotlin.generators.tree.* +import org.jetbrains.kotlin.ir.generator.model.* +import org.jetbrains.kotlin.ir.generator.model.ElementRef import org.jetbrains.kotlin.types.Variance import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty +import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef abstract class AbstractTreeBuilder { - private val configurationCallbacks = mutableListOf<() -> ElementConfig>() + private val configurationCallbacks = mutableListOf<() -> Element>() - abstract val rootElement: ElementConfig + abstract val rootElement: Element - fun element(category: ElementConfig.Category, name: String? = null, initializer: ElementConfig.() -> Unit = {}): ElementConfigDel { - val del = ElementConfigDel(category, name) + protected fun Field.skipInIrFactory() { + useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.No + } + + protected fun Field.useFieldInIrFactory(defaultValue: String? = null) { + useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue) + } + + fun element(category: Element.Category, name: String? = null, initializer: Element.() -> Unit = {}): ElementDelegate { + val del = ElementDelegate(category, name) configurationCallbacks.add { - del.element!!.apply { initializer() } + del.element!!.apply { + initializer() + if (elementParents.isEmpty() && this != rootElement) { + elementParents.add(ElementRef(rootElement)) + } + } } return del } - protected fun ElementConfig.parent(type: TypeRef) { - parents.add(type) + protected fun Element.parent(type: ClassRef<*>) { + otherParents.add(type) + } + + protected fun Element.parent(type: ElementOrRef) { + elementParents.add(ElementRef(type.element, type.args, type.nullable)) } protected fun param(name: String, vararg bounds: TypeRef, variance: Variance = Variance.INVARIANT): TypeVariable { @@ -41,33 +58,48 @@ abstract class AbstractTreeBuilder { nullable: Boolean = false, mutable: Boolean = true, isChild: Boolean = false, - initializer: SimpleFieldConfig.() -> Unit = {} - ): SimpleFieldConfig { + initializer: SingleField.() -> Unit = {} + ): SingleField { checkChildType(isChild, type, name) - return SimpleFieldConfig(name, type, nullable, mutable, isChild).apply(initializer) + return SingleField(name, type?.copy(nullable) ?: InferredOverriddenType, mutable, isChild).apply(initializer) } protected fun listField( name: String, elementType: TypeRef?, nullable: Boolean = false, - mutability: ListFieldConfig.Mutability = ListFieldConfig.Mutability.Immutable, + mutability: ListField.Mutability = ListField.Mutability.Immutable, isChild: Boolean = false, - initializer: ListFieldConfig.() -> Unit = {} - ): ListFieldConfig { + initializer: ListField.() -> Unit = {} + ): ListField { checkChildType(isChild, elementType, name) - return ListFieldConfig(name, elementType, nullable, mutability, isChild).apply(initializer) + val listType = when (mutability) { + ListField.Mutability.List -> StandardTypes.mutableList + ListField.Mutability.Array -> StandardTypes.array + else -> StandardTypes.list + } + return ListField( + name = name, + elementType = elementType ?: InferredOverriddenType, + listType = listType, + isNullable = nullable, + mutable = mutability == ListField.Mutability.Var, + isChild = isChild, + transformable = mutability != ListField.Mutability.Immutable, + ).apply(initializer) } private fun checkChildType(isChild: Boolean, type: TypeRef?, name: String) { if (isChild) { - require(type == null || type is ElementConfigOrRef) { "Field $name is a child field but has non-element type $type" } + require(type == null || type is GenericElementOrRef<*, *>) { + "Field $name is a child field but has non-element type $type" + } } } - fun build(): Config { + fun build(): Model { val elements = configurationCallbacks.map { it() } - return Config(elements, rootElement) + return Model(elements, rootElement) } companion object { @@ -77,20 +109,20 @@ abstract class AbstractTreeBuilder { } } -class ElementConfigDel( - private val category: ElementConfig.Category, +class ElementDelegate( + private val category: Element.Category, private val name: String? -) : ReadOnlyProperty, PropertyDelegateProvider { - var element: ElementConfig? = null +) : ReadOnlyProperty, PropertyDelegateProvider { + var element: Element? = null private set - override fun getValue(thisRef: AbstractTreeBuilder, property: KProperty<*>): ElementConfig { + override fun getValue(thisRef: AbstractTreeBuilder, property: KProperty<*>): Element { return element!! } - override fun provideDelegate(thisRef: AbstractTreeBuilder, property: KProperty<*>): ElementConfigDel { + override fun provideDelegate(thisRef: AbstractTreeBuilder, property: KProperty<*>): ElementDelegate { val path = thisRef.javaClass.name + "." + property.name - element = ElementConfig(path, name ?: property.name, category) + element = Element(name ?: property.name, path, category) return this } } diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt deleted file mode 100644 index d64607a2c9e..00000000000 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/ConfigModel.kt +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.generator.config - -import org.jetbrains.kotlin.generators.tree.* -import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE -import org.jetbrains.kotlin.ir.generator.model.Element -import org.jetbrains.kotlin.utils.SmartPrinter - -class Config( - val elements: List, - val rootElement: ElementConfig, -) - -class ElementConfig( - val propertyName: String, - val name: String, - val category: Category -) : ElementConfigOrRef { - val params = mutableListOf() - val parents = mutableListOf() - val fields = mutableListOf() - val usedTypes = mutableListOf() - - var visitorName: String? = null - var visitorParent: ElementConfig? = null - var visitorParam: String? = null - var accept = false // By default, accept is generated only for leaves. - var transform = false - var transformByChildren = false - var transformerReturnType: ElementConfig? = null - var childrenOrderOverride: List? = null - - var ownsChildren = true // If false, acceptChildren/transformChildren will NOT be generated. - - var generateIrFactoryMethod = category == Category.Declaration - val additionalIrFactoryMethodParameters = mutableListOf() - val fieldsToSkipInIrFactoryMethod = hashSetOf() - - /** - * Set this to `true` if the element should be a leaf semantically, but technically it's not. - * - * For example, we only generate [IrFactory] methods for leaf elements. If we want to generate a method for this element, but it has - * subclasses, it can be done by setting this property to `true`. - */ - var isForcedLeaf = false - - var typeKind: TypeKind? = null - - var generationCallback: (context(ImportCollector) SmartPrinter.() -> Unit)? = null - var kDoc: String? = null - - override val element get() = this - override val args get() = emptyMap() - override val nullable get() = false - override fun copy(args: Map) = ElementConfigRef(this, args, false) - override fun copy(nullable: Boolean) = ElementConfigRef(this, args, nullable) - - override fun substitute(map: TypeParameterSubstitutionMap): ElementConfig = this - - operator fun TypeVariable.unaryPlus() = apply { - params.add(this) - } - - operator fun FieldConfig.unaryPlus() = apply { - fields.add(this) - } - - override fun toString() = element.name - - override val packageName: String - get() = category.packageName - - override val typeName: String - get() = Element.elementName2typeName(name) - - context(ImportCollector) - override fun renderTo(appendable: Appendable) { - addImport(this) - appendable.append(typeName) - if (params.isNotEmpty()) { - params.joinTo(appendable, prefix = "<", postfix = ">") { it.name } - } - } - - enum class Category(private val packageDir: String, val defaultVisitorParam: String) { - Expression("expressions", "expression"), - Declaration("declarations", "declaration"), - Other("", "element"); - - val packageName: String get() = BASE_PACKAGE + if (packageDir.isNotEmpty()) ".$packageDir" else "" - } -} - -sealed interface ElementConfigOrRef : ParametrizedTypeRef, TypeRefWithNullability, Importable { - val element: ElementConfig -} - -class ElementConfigRef( - override val element: ElementConfig, - override val args: Map, - override val nullable: Boolean -) : ElementConfigOrRef { - - override val packageName: String - get() = element.packageName - - override val typeName: String - get() = element.typeName - - override fun copy(args: Map) = ElementConfigRef(element, args, nullable) - override fun copy(nullable: Boolean) = ElementConfigRef(element, args, nullable) - - override fun toString() = element.name - - context(ImportCollector) - override fun renderTo(appendable: Appendable) { - addImport(element) - appendable.append(element.typeName) - renderArgsTo(appendable) - renderNullabilityTo(appendable) - } -} - -sealed class UseFieldAsParameterInIrFactoryStrategy { - - data object No : UseFieldAsParameterInIrFactoryStrategy() - - data class Yes(val defaultValue: String?) : UseFieldAsParameterInIrFactoryStrategy() -} - -sealed class FieldConfig( - val name: String, - val isChild: Boolean, -) { - var baseDefaultValue: String? = null - var baseGetter: String? = null - var customSetter: String? = null - var optInAnnotation: ClassRef<*>? = null - - var deprecation: Deprecated? = null - - var visibility = Visibility.PUBLIC - - internal var useFieldInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy = - if (isChild) UseFieldAsParameterInIrFactoryStrategy.No else UseFieldAsParameterInIrFactoryStrategy.Yes(null) - - fun useFieldInIrFactory(defaultValue: String? = null) { - useFieldInIrFactoryStrategy = UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue) - } - - fun skipInIrFactory() { - useFieldInIrFactoryStrategy = UseFieldAsParameterInIrFactoryStrategy.No - } - - var kDoc: String? = null - - override fun toString() = name -} - -class SimpleFieldConfig( - name: String, - val type: TypeRefWithNullability?, - val nullable: Boolean, - val mutable: Boolean, - isChildElement: Boolean, -) : FieldConfig(name, isChildElement) - -class ListFieldConfig( - name: String, - val elementType: TypeRef?, - val nullable: Boolean, - val mutability: Mutability, - isChildElement: Boolean, -) : FieldConfig(name, isChildElement) { - enum class Mutability { - Immutable, - Var, - List, - Array - } -} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt index e03d4cf1ee2..9b7e7077d4f 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt @@ -6,23 +6,40 @@ package org.jetbrains.kotlin.ir.generator.model import org.jetbrains.kotlin.generators.tree.* -import org.jetbrains.kotlin.ir.generator.config.ElementConfig -import org.jetbrains.kotlin.ir.generator.config.FieldConfig +import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE +import org.jetbrains.kotlin.utils.SmartPrinter 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, override val name: String, - override val packageName: String, - override val params: List, - override val fields: MutableSet, - val additionalFactoryMethodParameters: MutableList, + override val propertyName: String, + category: Category, ) : AbstractElement() { - override var elementParents: List = emptyList() + + enum class Category(private val packageDir: String, val defaultVisitorParam: String) { + Expression("expressions", "expression"), + Declaration("declarations", "declaration"), + Other("", "element"); + + val packageName: String get() = BASE_PACKAGE + if (packageDir.isNotEmpty()) ".$packageDir" else "" + } + + override val packageName: String = category.packageName + + override val elementParents = mutableListOf() override var otherParents: MutableList> = mutableListOf() + override val params = mutableListOf() + + override val fields = mutableSetOf() + + val additionalIrFactoryMethodParameters = mutableListOf() + var generateIrFactoryMethod = category == Category.Declaration + val fieldsToSkipInIrFactoryMethod = hashSetOf() + + override val allFields: List get() = fields.toList() @@ -38,26 +55,46 @@ class Element( override var parentInVisitor: Element? = null var transformerReturnType: Element? = null - override var kind: ImplementationKind? = when (config.typeKind) { - TypeKind.Class -> ImplementationKind.AbstractClass - TypeKind.Interface -> ImplementationKind.Interface - null -> null - } + var typeKind: TypeKind? = null + set(value) { + kind = when (value) { + TypeKind.Class -> ImplementationKind.AbstractClass + TypeKind.Interface -> ImplementationKind.Interface + null -> null + } + field = value + } + + override var kind: ImplementationKind? = null override val typeName get() = elementName2typeName(name) - var isLeaf = config.isForcedLeaf - val childrenOrderOverride: List? = config.childrenOrderOverride + /** + * Whether this element is semantically a leaf element in the hierarchy. + * + * This is set automatically by the [markLeaves] function for all true leaves, but can also be set manually to `true` if + * this element should be considered a leaf semantically. + * + * For example, we only generate [org.jetbrains.kotlin.ir.declarations.IrFactory] methods for leaf elements. + * If we want to generate a method for this element, but it has subclasses, it can be done by manually setting this property to `true`. + */ + var isLeaf = false + + var childrenOrderOverride: List? = null override var walkableChildren: List = emptyList() override val transformableChildren get() = walkableChildren.filter { it.transformable } - override val visitFunctionName = "visit" + (config.visitorName ?: name).replaceFirstChar(Char::uppercaseChar) - override val visitorParameterName = config.visitorParam ?: config.category.defaultVisitorParam + var visitorName: String? = null - override var hasAcceptMethod = config.accept + override val visitFunctionName: String + get() = "visit" + (visitorName ?: name).replaceFirstChar(Char::uppercaseChar) - override val hasTransformMethod = config.transform + override var visitorParameterName = category.defaultVisitorParam + + override var hasAcceptMethod = false // By default, accept is generated only for leaves. + + override var hasTransformMethod = false override val hasAcceptChildrenMethod: Boolean get() = ownsChildren && (isRootElement || walkableChildren.isNotEmpty()) @@ -65,17 +102,14 @@ class Element( override val hasTransformChildrenMethod: Boolean get() = ownsChildren && (isRootElement || transformableChildren.isNotEmpty()) - val transformByChildren = config.transformByChildren - val ownsChildren = config.ownsChildren - val generateIrFactoryMethod = config.generateIrFactoryMethod - val fieldsToSkipInIrFactoryMethod = config.fieldsToSkipInIrFactoryMethod + var transformByChildren = false + var ownsChildren = true // If false, acceptChildren/transformChildren will NOT be generated. - val generationCallback = config.generationCallback - override val propertyName = config.propertyName + var generationCallback: (context(ImportCollector) SmartPrinter.() -> Unit)? = null - override val kDoc = config.kDoc + override var kDoc: String? = null - val usedTypes: List = config.usedTypes + val usedTypes = mutableListOf() override fun toString() = name @@ -105,38 +139,46 @@ class Element( .distinctBy { it.name } .asReversed() } + + operator fun TypeVariable.unaryPlus() = apply { + params.add(this) + } + + operator fun Field.unaryPlus() = apply { + fields.add(this) + } } typealias ElementRef = GenericElementRef typealias ElementOrRef = GenericElementOrRef -@Suppress("LeakingThis") sealed class Field( - config: FieldConfig, override val name: String, override var isMutable: Boolean, val isChild: Boolean, ) : AbstractField() { - abstract val baseDefaultValue: String? - abstract val baseGetter: String? + var baseDefaultValue: String? = null + var baseGetter: String? = null + abstract val transformable: Boolean - val useInIrFactoryStrategy = config.useFieldInIrFactoryStrategy + sealed class UseFieldAsParameterInIrFactoryStrategy { - init { - kDoc = config.kDoc - optInAnnotation = config.optInAnnotation - deprecation = config.deprecation - visibility = config.visibility + data object No : UseFieldAsParameterInIrFactoryStrategy() + + data class Yes(val defaultValue: String?) : UseFieldAsParameterInIrFactoryStrategy() } + var useInIrFactoryStrategy = + if (isChild) UseFieldAsParameterInIrFactoryStrategy.No else UseFieldAsParameterInIrFactoryStrategy.Yes(null) + override val withGetter: Boolean get() = baseGetter != null override val defaultValueInImplementation: String? get() = baseGetter ?: baseDefaultValue - override val customSetter: String? = config.customSetter + override var customSetter: String? = null override fun toString() = "$name: $typeRef" @@ -154,29 +196,32 @@ sealed class Field( } class SingleField( - config: FieldConfig, name: String, override var typeRef: TypeRefWithNullability, mutable: Boolean, isChild: Boolean, - override val baseDefaultValue: String?, - override val baseGetter: String?, -) : Field(config, name, mutable, isChild) { +) : Field(name, mutable, isChild) { override val transformable: Boolean get() = isMutable } class ListField( - config: FieldConfig, name: String, var elementType: TypeRef, + private val isNullable: Boolean, private val listType: ClassRef, mutable: Boolean, isChild: Boolean, override val transformable: Boolean, - override val baseDefaultValue: String?, - override val baseGetter: String?, -) : Field(config, name, mutable, isChild) { +) : Field(name, mutable, isChild) { + override val typeRef: TypeRefWithNullability - get() = listType.withArgs(elementType) + get() = listType.withArgs(elementType).copy(isNullable) + + enum class Mutability { + Immutable, + Var, + List, + Array + } } diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt index 2473312dd01..9e695448126 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt @@ -6,14 +6,8 @@ package org.jetbrains.kotlin.ir.generator.model import org.jetbrains.kotlin.generators.tree.* -import org.jetbrains.kotlin.ir.generator.config.* -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 : TypeRefWithNullability { +internal object InferredOverriddenType : TypeRefWithNullability { context(ImportCollector) override fun renderTo(appendable: Appendable) { @@ -30,117 +24,7 @@ private object InferredOverriddenType : TypeRefWithNullability { data class Model(val elements: List, val rootElement: Element) -fun config2model(config: Config): Model { - val ec2el = mutableMapOf() - - val elements = config.elements.map { ec -> - Element( - config = ec, - name = ec.name, - packageName = ec.category.packageName, - params = ec.params, - fields = ec.fields.mapTo(mutableSetOf(), ::transformFieldConfig), - additionalFactoryMethodParameters = ec.additionalIrFactoryMethodParameters.mapTo(mutableListOf(), ::transformFieldConfig) - ).also { - ec2el[ec.element] = it - } - } - - val rootElement = replaceElementRefs(config, ec2el) - configureInterfacesAndAbstractClasses(elements) - addPureAbstractElement(elements, elementBaseType) - markLeaves(elements) - processFieldOverrides(elements) - addWalkableChildren(elements) - - return Model(elements, rootElement) -} - -private fun transformFieldConfig(fc: FieldConfig): Field = when (fc) { - is SimpleFieldConfig -> SingleField( - fc, - fc.name, - fc.type?.copy(fc.nullable) ?: InferredOverriddenType, - fc.mutable, - fc.isChild, - fc.baseDefaultValue, - fc.baseGetter, - ) - is ListFieldConfig -> { - val listType = when (fc.mutability) { - ListFieldConfig.Mutability.List -> StandardTypes.mutableList - ListFieldConfig.Mutability.Array -> StandardTypes.array - else -> StandardTypes.list - } - ListField( - fc, - fc.name, - fc.elementType ?: InferredOverriddenType, - listType.copy(fc.nullable), - fc.mutability == ListFieldConfig.Mutability.Var, - fc.isChild, - fc.mutability != ListFieldConfig.Mutability.Immutable, - fc.baseDefaultValue, - fc.baseGetter, - ) - } -} - -@OptIn(UnsafeCastFunction::class) -@Suppress("UNCHECKED_CAST") -private fun replaceElementRefs(config: Config, mapping: Map): Element { - val visited = mutableMapOf() - - fun transform(type: TypeRef): TypeRef { - visited[type]?.let { - return it - } - - return when (type) { - is ElementConfigOrRef -> { - val args = type.args.mapValues { transform(it.value) } - val el = mapping.getValue(type.element) - ElementRef(el, args, type.nullable) - } - is ClassRef<*> -> { - @Suppress("UNCHECKED_CAST") // this is the upper bound, compiler could know that, right? - type as ClassRef - - val args = type.args.mapValues { transform(it.value) } - type.copy(args = args) - } - else -> type - }.also { visited[type] = it } - } - - val rootEl = transform(config.rootElement) as GenericElementRef - - for (ec in config.elements) { - val el = mapping[ec.element]!! - val (elParents, otherParents) = ec.parents - .map { transform(it) } - .partitionIsInstance() - el.elementParents = elParents.takeIf { it.isNotEmpty() || el == rootEl.element } ?: listOf(rootEl) - el.otherParents = otherParents.castAll>().toMutableList() - el.parentInVisitor = (ec.visitorParent?.let(::transform) as GenericElementRef?)?.element - el.transformerReturnType = (ec.transformerReturnType?.let(::transform) as GenericElementRef?)?.element - - for (field in el.fields) { - when (field) { - is SingleField -> { - field.typeRef = transform(field.typeRef) as TypeRefWithNullability - } - is ListField -> { - field.elementType = transform(field.elementType) - } - } - } - } - - return rootEl.element -} - -private fun markLeaves(elements: List) { +internal fun markLeaves(elements: List) { val leaves = elements.toMutableSet() for (el in elements) { @@ -159,7 +43,7 @@ private fun markLeaves(elements: List) { } } -private fun processFieldOverrides(elements: List) { +internal fun processFieldOverrides(elements: List) { for (element in iterateElementsParentFirst(elements)) { for (field in element.fields) { fun visitParents(visited: Element) { @@ -193,7 +77,7 @@ private fun processFieldOverrides(elements: List) { } } -private fun addWalkableChildren(elements: List) { +internal fun addWalkableChildren(elements: List) { for (element in elements) { val walkableChildren = mutableMapOf() diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Factory.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Factory.kt index cba6e679b8f..b68fc207875 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Factory.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Factory.kt @@ -12,9 +12,9 @@ import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType import org.jetbrains.kotlin.ir.generator.IrTree import org.jetbrains.kotlin.ir.generator.TREE_GENERATOR_README -import org.jetbrains.kotlin.ir.generator.config.UseFieldAsParameterInIrFactoryStrategy import org.jetbrains.kotlin.ir.generator.irFactoryType import org.jetbrains.kotlin.ir.generator.model.Element +import org.jetbrains.kotlin.ir.generator.model.Field import org.jetbrains.kotlin.ir.generator.model.Model import org.jetbrains.kotlin.ir.generator.stageControllerType import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly @@ -255,10 +255,10 @@ private class FactoryMethod(val element: Element) { val name = "create" + element.name.capitalizeAsciiOnly() - val parameters = (element.allFieldsRecursively() + element.additionalFactoryMethodParameters) + val parameters = (element.allFieldsRecursively() + element.additionalIrFactoryMethodParameters) .filterNot { it.name in element.fieldsToSkipInIrFactoryMethod } .mapNotNull { field -> - (field.useInIrFactoryStrategy as? UseFieldAsParameterInIrFactoryStrategy.Yes)?.let { + (field.useInIrFactoryStrategy as? Field.UseFieldAsParameterInIrFactoryStrategy.Yes)?.let { FunctionParameter(field.name, field.typeRef, it.defaultValue) } }