[SIR] Auto-generate the Swift IR tree

Co-authored-by: Gleb Lukianets <gleb.lukianets@jetbrains.com>
This commit is contained in:
Sergej Jaskiewicz
2023-12-06 13:07:46 +01:00
committed by Space Team
parent 39c84bca06
commit 0d2032f3ef
34 changed files with 968 additions and 2 deletions
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Generate SwiftIR tree" type="GradleRunConfiguration" factoryName="Gradle" folderName="Generators">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/native/swift/sir" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="generateTree" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+1
View File
@@ -485,6 +485,7 @@ val projectsWithEnabledContextReceivers by extra {
":compiler:fir:raw-fir:light-tree2fir",
":compiler:fir:tree:tree-generator",
":compiler:ir.tree:tree-generator",
":native:swift:sir:tree-generator",
":generators:tree-generator-common",
":kotlin-lombok-compiler-plugin.k1",
":kotlinx-serialization-compiler-plugin.k2",
@@ -6,7 +6,11 @@
package org.jetbrains.kotlin.generators.tree
/**
* A class representing a FIR or IR tree element.
* Represents an abstract class/interface for a tree node in the tree generator.
*
* Examples: `IrElement`, `FirRegularClass`.
*
* Subclasses may contain additional properties/logic specific to a particular tree.
*/
abstract class AbstractElement<Element, Field, Implementation>(
val name: String,
@@ -49,7 +49,8 @@ abstract class AbstractVisitorPrinter<Element : AbstractElement<Element, Field,
* If `true`, visitor methods for generic tree elements will be parameterized correspondingly.
* Otherwise, type arguments of generic tree elements will be replaced with `*`.
*/
abstract val allowTypeParametersInVisitorMethods: Boolean
open val allowTypeParametersInVisitorMethods: Boolean
get() = false
/**
* Allows to customize the default element to visit if the method for visiting this [element] is not overridden.
+43
View File
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.ideaExt.idea
plugins {
kotlin("jvm")
}
@@ -7,6 +9,10 @@ description = "Swift Intermediate Representation"
dependencies {
compileOnly(kotlinStdlib())
if (kotlinBuildProperties.isInIdeaSync) {
compileOnly(project("tree-generator")) // Provided, so that IDEA can recognize references to this module in KDoc.
}
testImplementation(kotlin("test-junit5"))
testImplementation(platform(libs.junit.bom))
testImplementation(libs.junit.jupiter.api)
@@ -25,3 +31,40 @@ projectTest(jUnitMode = JUnitMode.JUnit5) {
workingDir = rootDir
useJUnitPlatform { }
}
val generatorClasspath by configurations.creating
dependencies {
generatorClasspath(project("tree-generator"))
}
val generationRoot = projectDir.resolve("gen")
val generateTree by tasks.registering(NoDebugJavaExec::class) {
val generatorRoot = "$projectDir/tree-generator/src/"
val generatorConfigurationFiles = fileTree(generatorRoot) {
include("**/*.kt")
}
inputs.files(generatorConfigurationFiles)
outputs.dirs(generationRoot)
args(generationRoot)
workingDir = rootDir
classpath = generatorClasspath
mainClass.set("org.jetbrains.kotlin.sir.tree.generator.MainKt")
systemProperties["line.separator"] = "\n"
}
tasks.named("compileKotlin") {
dependsOn(generateTree)
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
}
}
@@ -40,3 +40,17 @@ inline fun buildEnum(init: SirEnumBuilder.() -> Unit): SirEnum {
}
return SirEnumBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildEnumCopy(original: SirEnum, init: SirEnumBuilder.() -> Unit): SirEnum {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = SirEnumBuilder()
copyBuilder.origin = original.origin
copyBuilder.visibility = original.visibility
copyBuilder.name = original.name
copyBuilder.declarations.addAll(original.declarations)
copyBuilder.cases.addAll(original.cases)
return copyBuilder.apply(init).build()
}
@@ -37,3 +37,14 @@ inline fun buildForeignFunction(init: SirForeignFunctionBuilder.() -> Unit = {})
}
return SirForeignFunctionBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildForeignFunctionCopy(original: SirForeignFunction, init: SirForeignFunctionBuilder.() -> Unit = {}): SirForeignFunction {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = SirForeignFunctionBuilder()
copyBuilder.origin = original.origin
copyBuilder.visibility = original.visibility
return copyBuilder.apply(init).build()
}
@@ -40,3 +40,17 @@ inline fun buildFunction(init: SirFunctionBuilder.() -> Unit): SirFunction {
}
return SirFunctionBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildFunctionCopy(original: SirFunction, init: SirFunctionBuilder.() -> Unit): SirFunction {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = SirFunctionBuilder()
copyBuilder.origin = original.origin
copyBuilder.visibility = original.visibility
copyBuilder.name = original.name
copyBuilder.parameters.addAll(original.parameters)
copyBuilder.returnType = original.returnType
return copyBuilder.apply(init).build()
}
@@ -36,3 +36,14 @@ inline fun buildModule(init: SirModuleBuilder.() -> Unit): SirModule {
}
return SirModuleBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildModuleCopy(original: SirModule, init: SirModuleBuilder.() -> Unit): SirModule {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = SirModuleBuilder()
copyBuilder.declarations.addAll(original.declarations)
copyBuilder.name = original.name
return copyBuilder.apply(init).build()
}
@@ -38,3 +38,16 @@ inline fun buildStruct(init: SirStructBuilder.() -> Unit): SirStruct {
}
return SirStructBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildStructCopy(original: SirStruct, init: SirStructBuilder.() -> Unit): SirStruct {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = SirStructBuilder()
copyBuilder.origin = original.origin
copyBuilder.visibility = original.visibility
copyBuilder.name = original.name
copyBuilder.declarations.addAll(original.declarations)
return copyBuilder.apply(init).build()
}
@@ -6,6 +6,8 @@
// This file was generated automatically. See native/swift/sir/tree-generator/Readme.md.
// DO NOT MODIFY IT MANUALLY.
@file:Suppress("DuplicatedCode", "unused")
package org.jetbrains.kotlin.sir.impl
import org.jetbrains.kotlin.sir.*
@@ -6,6 +6,8 @@
// This file was generated automatically. See native/swift/sir/tree-generator/Readme.md.
// DO NOT MODIFY IT MANUALLY.
@file:Suppress("DuplicatedCode", "unused")
package org.jetbrains.kotlin.sir.impl
import org.jetbrains.kotlin.sir.SirDeclarationParent
@@ -6,6 +6,8 @@
// This file was generated automatically. See native/swift/sir/tree-generator/Readme.md.
// DO NOT MODIFY IT MANUALLY.
@file:Suppress("DuplicatedCode", "unused")
package org.jetbrains.kotlin.sir.impl
import org.jetbrains.kotlin.sir.*
@@ -6,6 +6,8 @@
// This file was generated automatically. See native/swift/sir/tree-generator/Readme.md.
// DO NOT MODIFY IT MANUALLY.
@file:Suppress("DuplicatedCode", "unused")
package org.jetbrains.kotlin.sir.impl
import org.jetbrains.kotlin.sir.SirDeclaration
@@ -6,6 +6,8 @@
// This file was generated automatically. See native/swift/sir/tree-generator/Readme.md.
// DO NOT MODIFY IT MANUALLY.
@file:Suppress("DuplicatedCode", "unused")
package org.jetbrains.kotlin.sir.impl
import org.jetbrains.kotlin.sir.*
+13
View File
@@ -0,0 +1,13 @@
# Swift IR tree generator
This directory contains a code generator for generating Swift IR classes.
We reuse the infrastructure for tree generators that is also used for generating [IR](../../../../compiler/ir/ir.tree/tree-generator) and
[FIR](../../../../compiler/fir/tree/tree-generator) trees.
- All tree elements are declared in [`SwiftIrTree.kt`](src/org/jetbrains/kotlin/sir/tree/generator/SwiftIrTree.kt)
- Types commonly used in configuration are listed in [`Types.kt`](src/org/jetbrains/kotlin/sir/tree/generator/Types.kt)
- If an element has no inheritors, then it will have a default implementation.
Otherwise, you should declare an implementation that you want in
[`ImplementationConfigurator.kt`](src/org/jetbrains/kotlin/sir/tree/generator/ImplementationConfigurator.kt).
- The same is true for builders. For each leaf element in the hierarchy, there is a corresponding builder class.
- Builders are configured in [`BuilderConfigurator.kt`](src/org/jetbrains/kotlin/sir/tree/generator/BuilderConfigurator.kt).
@@ -0,0 +1,24 @@
plugins {
kotlin("jvm")
id("jps-compatible")
application
}
val runtimeOnly by configurations
val compileOnly by configurations
runtimeOnly.extendsFrom(compileOnly)
dependencies {
implementation(project(":generators:tree-generator-common"))
}
application {
mainClass.set("org.jetbrains.kotlin.sir.tree.generator.MainKt")
}
sourceSets {
"main" {
projectDefault()
}
"test" {}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2023 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.sir.tree.generator
import org.jetbrains.kotlin.sir.tree.generator.config.AbstractSwiftIrTreeBuilderConfigurator
import org.jetbrains.kotlin.sir.tree.generator.model.Element
class BuilderConfigurator(elements: List<Element>) : AbstractSwiftIrTreeBuilderConfigurator(elements) {
override fun configureBuilders() = with(SwiftIrTree) {
configureAllLeafBuilders {
withCopy()
}
configureFieldInAllLeafBuilders("origin") {
default(it, "SirOrigin.Unknown")
}
configureFieldInAllLeafBuilders("visibility") {
default(it, "SirVisibility.PUBLIC")
}
}
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2023 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.sir.tree.generator
import org.jetbrains.kotlin.sir.tree.generator.config.AbstractSwiftIrTreeImplementationConfigurator
object ImplementationConfigurator : AbstractSwiftIrTreeImplementationConfigurator() {
override fun configure() = with(SwiftIrTree) {
// Declare custom implementation classes, see org.jetbrains.kotlin.fir.tree.generator.ImplementationConfigurator
}
override fun configureAllImplementations() {
// Use configureFieldInAllImplementations to customize certain fields in all implementation classes
configureFieldInAllImplementations(
field = "parent",
) {
isMutable(it)
isLateinit(it)
}
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2023 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.sir.tree.generator
import org.jetbrains.kotlin.generators.tree.bind
import org.jetbrains.kotlin.generators.tree.printer.generateTree
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.printer.*
import java.io.File
internal const val BASE_PACKAGE = "org.jetbrains.kotlin.sir"
typealias Model = org.jetbrains.kotlin.generators.tree.Model<Element>
fun main(args: Array<String>) {
val generationPath = args.firstOrNull()?.let { File(it) }
?: File("../../tree/gen").canonicalFile
val model = SwiftIrTree.build()
generateTree(
generationPath,
"native/swift/sir/tree-generator/Readme.md",
model,
pureAbstractElementType,
::ElementPrinter,
listOf(
elementVisitorType to ::VisitorPrinter,
elementTransformerType to ::TransformerPrinter.bind(model.rootElement),
),
ImplementationConfigurator,
BuilderConfigurator(model.elements),
::ImplementationPrinter,
::BuilderPrinter,
)
}
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2023 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.
*/
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package org.jetbrains.kotlin.sir.tree.generator
import org.jetbrains.kotlin.generators.tree.StandardTypes.string
import org.jetbrains.kotlin.sir.tree.generator.config.AbstractSwiftIrTreeBuilder
import org.jetbrains.kotlin.sir.tree.generator.model.Element
object SwiftIrTree : AbstractSwiftIrTreeBuilder() {
override val rootElement by sealedElement(name = "Element") {
kDoc = "The root interface of the Swift IR tree."
}
val module by element {
customParentInVisitor = rootElement
parent(declarationContainer)
parent(named)
}
val declarationParent by sealedElement()
val declarationContainer by sealedElement {
parent(declarationParent)
customParentInVisitor = rootElement
+listField("declarations", declaration)
}
val declaration by sealedElement {
customParentInVisitor = rootElement
+field("origin", originType)
+field("visibility", swiftVisibilityType)
+field("parent", declarationParent, mutable = true, isChild = false) {
useInBaseTransformerDetection = false
}
}
val foreignDeclaration by sealedElement {
parent(declaration)
}
val named by sealedElement {
+field("name", string)
}
val namedDeclaration by sealedElement {
customParentInVisitor = declaration
parent(declaration)
parent(named)
}
val enum: Element by element {
customParentInVisitor = namedDeclaration
parent(namedDeclaration)
parent(declarationContainer)
+listField("cases", enumCaseType)
}
val struct: Element by element {
customParentInVisitor = namedDeclaration
parent(namedDeclaration)
parent(declarationContainer)
}
val callable by sealedElement {
parent(declaration)
}
val function by element {
customParentInVisitor = callable
parent(callable)
+field("name", string)
+listField("parameters", parameterType)
+field("returnType", typeType)
}
val foreignFunction by element {
customParentInVisitor = callable
parent(callable)
parent(foreignDeclaration)
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2023 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.sir.tree.generator
import org.jetbrains.kotlin.generators.tree.TypeKind
import org.jetbrains.kotlin.generators.tree.type
val pureAbstractElementType = type(BASE_PACKAGE, "SirElementBase", TypeKind.Class)
val swiftVisibilityType = type(BASE_PACKAGE, "SirVisibility", TypeKind.Class)
val originType = type(BASE_PACKAGE, "SirOrigin", TypeKind.Class)
val parameterType = type(BASE_PACKAGE, "SirParameter", TypeKind.Class)
val typeType = type(BASE_PACKAGE, "SirType", TypeKind.Class)
val enumCaseType = type(BASE_PACKAGE, "SirEnumCase", TypeKind.Class)
private const val VISITORS_PACKAGE = "$BASE_PACKAGE.visitors"
val elementVisitorType = type(VISITORS_PACKAGE, "SirVisitor", TypeKind.Class)
val elementTransformerType = type(VISITORS_PACKAGE, "SirTransformer", TypeKind.Class)
val swiftIrImplementationDetailAnnotation = type(BASE_PACKAGE, "SirImplementationDetail", TypeKind.Class)
val swiftIrBuilderDslAnnotation = type(BASE_PACKAGE, "SirBuilderDsl", TypeKind.Class)
@@ -0,0 +1,110 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.config
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.sir.tree.generator.Model
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.sir.tree.generator.model.ListField
import org.jetbrains.kotlin.sir.tree.generator.model.SimpleField
import org.jetbrains.kotlin.types.Variance
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
// TODO: This class was copy-pasted from the IR tree generator. It'd be good to factor out common parts.
abstract class AbstractSwiftIrTreeBuilder {
private val configurationCallbacks = mutableListOf<() -> Element>()
abstract val rootElement: Element
private fun createElement(name: String? = null, isSealed: Boolean, initializer: Element.() -> Unit = {}): ElementDelegate {
val del = ElementDelegate(name, isSealed)
configurationCallbacks.add {
del.element!!.apply {
initializer()
if (elementParents.isEmpty() && this != rootElement) {
elementParents.add(ElementRef(rootElement))
}
}
}
return del
}
fun element(name: String? = null, initializer: Element.() -> Unit = {}) =
createElement(name, isSealed = false, initializer)
fun sealedElement(name: String? = null, initializer: Element.() -> Unit = {}) =
createElement(name, isSealed = true, initializer)
protected fun Element.parent(type: ClassRef<*>) {
otherParents.add(type)
}
protected fun Element.parent(type: ElementOrRef<Element>) {
elementParents.add(ElementRef(type.element, type.args, type.nullable))
}
protected fun param(name: String, vararg bounds: TypeRef, variance: Variance = Variance.INVARIANT): TypeVariable {
return TypeVariable(name, bounds.toList(), variance)
}
protected fun field(
name: String,
type: TypeRefWithNullability,
nullable: Boolean = false,
mutable: Boolean = false,
isChild: Boolean = true,
initializer: SimpleField.() -> Unit = {}
): SimpleField {
return SimpleField(name, type.copy(nullable), mutable).apply {
this.isChild = isChild
initializer()
}
}
protected fun listField(
name: String,
baseType: TypeRef,
isChild: Boolean = true,
initializer: ListField.() -> Unit = {}
): ListField {
return ListField(
name = name,
baseType = baseType,
isMutable = false,
).apply {
this.isChild = isChild
initializer()
}
}
fun build(): Model {
val elements = configurationCallbacks.map { it() }
return Model(elements, rootElement)
}
}
class ElementDelegate(
private val name: String?,
private val isSealed: Boolean,
) : ReadOnlyProperty<AbstractSwiftIrTreeBuilder, Element>, PropertyDelegateProvider<AbstractSwiftIrTreeBuilder, ElementDelegate> {
var element: Element? = null
private set
override fun getValue(thisRef: AbstractSwiftIrTreeBuilder, property: KProperty<*>): Element {
return element!!
}
override fun provideDelegate(thisRef: AbstractSwiftIrTreeBuilder, property: KProperty<*>): ElementDelegate {
val path = thisRef.javaClass.name + "." + property.name
element = Element(name ?: property.name.replaceFirstChar(Char::uppercaseChar), path).also {
it.isSealed = isSealed
}
return this
}
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.config
import org.jetbrains.kotlin.generators.tree.config.AbstractBuilderConfigurator
import org.jetbrains.kotlin.sir.tree.generator.BASE_PACKAGE
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.sir.tree.generator.model.Implementation
abstract class AbstractSwiftIrTreeBuilderConfigurator(
elements: List<Element>
) : AbstractBuilderConfigurator<Element, Implementation, Field, Field>(elements) {
override val namePrefix: String
get() = "Sir"
override val defaultBuilderPackage: String
get() = "$BASE_PACKAGE.builder"
override fun builderFieldFromElementField(elementField: Field) = elementField.copy()
}
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.config
import org.jetbrains.kotlin.generators.tree.config.AbstractImplementationConfigurator
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.sir.tree.generator.model.Implementation
abstract class AbstractSwiftIrTreeImplementationConfigurator : AbstractImplementationConfigurator<Implementation, Element, Field>() {
override fun createImplementation(element: Element, name: String?) = Implementation(element, name)
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.model
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.sir.tree.generator.BASE_PACKAGE
class Element(name: String, override val propertyName: String) : AbstractElement<Element, Field, Implementation>(name) {
override var kDoc: String? = null
override val fields: MutableSet<Field> = mutableSetOf()
override val params: MutableList<TypeVariable> = mutableListOf()
override val elementParents: MutableList<ElementRef<Element>> = mutableListOf()
override val otherParents: MutableList<ClassRef<*>> = mutableListOf()
override val visitorParameterName: String = when (val parameterName = name.replaceFirstChar(Char::lowercaseChar)) {
"class" -> "klass"
else -> parameterName
}
override val hasAcceptMethod: Boolean
get() = true
override val hasTransformMethod: Boolean
get() = true
override val hasAcceptChildrenMethod: Boolean
get() = isRootElement
override val hasTransformChildrenMethod: Boolean
get() = isRootElement
override var kind: ImplementationKind? = null
override val namePrefix: String
get() = "Sir"
override val packageName: String
get() = BASE_PACKAGE
override val element: Element
get() = this
override val nullable: Boolean
get() = false
override val args: Map<NamedTypeParameterRef, TypeRef>
get() = emptyMap()
operator fun Field.unaryPlus(): Field {
fields.add(this)
return this
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.model
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.ListField
abstract class Field(
override val name: String,
override var isMutable: Boolean
) : AbstractField<Field>(), AbstractFieldWithDefaultValue<Field> {
override val origin: Field
get() = this
override var withGetter: Boolean = false
override var customSetter: String? = null
override var defaultValueInImplementation: String? = null
override var defaultValueInBuilder: String? = null
override val isVolatile: Boolean
get() = false
override var isFinal: Boolean = false
override val isParameter: Boolean
get() = false
abstract fun internalCopy(): Field
override fun copy() = internalCopy().also(::updateFieldsInCopy)
override fun updateFieldsInCopy(copy: Field) {
super.updateFieldsInCopy(copy)
copy.withGetter = withGetter
copy.customSetter = customSetter
copy.defaultValueInImplementation = defaultValueInImplementation
copy.isFinal = isFinal
}
}
class SimpleField(
name: String,
override val typeRef: TypeRefWithNullability,
isMutable: Boolean,
) : Field(name, isMutable) {
override fun internalCopy() = SimpleField(name, typeRef, isMutable)
override fun replaceType(newType: TypeRefWithNullability) = SimpleField(name, newType, isMutable).also(::updateFieldsInCopy)
}
class ListField(
name: String,
override val baseType: TypeRef,
isMutable: Boolean,
) : Field(name, isMutable), ListField {
override val typeRef: ClassRef<PositionTypeParameterRef>
get() = super.typeRef
override val listType: ClassRef<PositionTypeParameterRef>
get() = StandardTypes.list
override fun internalCopy() = ListField(name, baseType, isMutable)
override fun replaceType(newType: TypeRefWithNullability) = internalCopy().also(::updateFieldsInCopy)
}
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.model
import org.jetbrains.kotlin.generators.tree.AbstractImplementation
class Implementation(element: Element, name: String?) : AbstractImplementation<Implementation, Element, Field>(element, name) {
override val allFields: List<Field> = element.allFields.map { it.copy() }
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.printer
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.sir.tree.generator.model.Implementation
import org.jetbrains.kotlin.sir.tree.generator.model.ListField
import org.jetbrains.kotlin.sir.tree.generator.swiftIrBuilderDslAnnotation
import org.jetbrains.kotlin.sir.tree.generator.swiftIrImplementationDetailAnnotation
import org.jetbrains.kotlin.utils.SmartPrinter
internal class BuilderPrinter(printer: SmartPrinter) : AbstractBuilderPrinter<Element, Implementation, Field, Field>(printer) {
override val implementationDetailAnnotation: ClassRef<*>
get() = swiftIrImplementationDetailAnnotation
override val builderDslAnnotation: ClassRef<*>
get() = swiftIrBuilderDslAnnotation
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.printer
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.*
import org.jetbrains.kotlin.sir.tree.generator.BASE_PACKAGE
import org.jetbrains.kotlin.sir.tree.generator.SwiftIrTree
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.sir.tree.generator.elementTransformerType
import org.jetbrains.kotlin.sir.tree.generator.elementVisitorType
import org.jetbrains.kotlin.sir.tree.generator.model.SimpleField
import org.jetbrains.kotlin.utils.SmartPrinter
internal class ElementPrinter(printer: SmartPrinter) : AbstractElementPrinter<Element, Field>(printer) {
override fun makeFieldPrinter(printer: SmartPrinter) = object : AbstractFieldPrinter<Field>(printer) {
override fun forceMutable(field: Field): Boolean = field.isMutable
}
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods(element: Element) {
val treeName = "Swift IR"
if (element.isRootElement || element.parentInVisitor != null) {
printAcceptMethod(element, elementVisitorType, hasImplementation = !element.isRootElement, treeName)
printTransformMethod(
element,
elementTransformerType,
implementation = "transformer.transform${element.name}(this, data)",
returnType = TypeVariable("E", listOf(SwiftIrTree.rootElement)),
treeName
)
}
if (element.isRootElement) {
printAcceptChildrenMethod(element, elementVisitorType, TypeVariable("R"))
println()
printTransformChildrenMethod(element, elementTransformerType, StandardTypes.unit)
println()
}
}
}
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.printer
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.printAcceptChildrenMethod
import org.jetbrains.kotlin.generators.tree.printer.printBlock
import org.jetbrains.kotlin.generators.tree.printer.printTransformChildrenMethod
import org.jetbrains.kotlin.sir.tree.generator.BASE_PACKAGE
import org.jetbrains.kotlin.sir.tree.generator.elementTransformerType
import org.jetbrains.kotlin.sir.tree.generator.elementVisitorType
import org.jetbrains.kotlin.sir.tree.generator.model.*
import org.jetbrains.kotlin.sir.tree.generator.model.ListField
import org.jetbrains.kotlin.sir.tree.generator.swiftIrImplementationDetailAnnotation
import org.jetbrains.kotlin.utils.SmartPrinter
internal class ImplementationPrinter(printer: SmartPrinter) : AbstractImplementationPrinter<Implementation, Element, Field>(printer) {
companion object {
private val transformInPlace = ArbitraryImportable("$BASE_PACKAGE.util", "transformInPlace")
}
override val implementationOptInAnnotation: ClassRef<*>
get() = swiftIrImplementationDetailAnnotation
override val pureAbstractElementType: ClassRef<*>
get() = org.jetbrains.kotlin.sir.tree.generator.pureAbstractElementType
override fun makeFieldPrinter(printer: SmartPrinter) = object : AbstractFieldPrinter<Field>(printer) {
override fun forceMutable(field: Field) = field.isMutable
override fun actualTypeOfField(field: Field): TypeRefWithNullability {
if (field is ListField) return StandardTypes.mutableList.withArgs(field.baseType)
return field.typeRef
}
}
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {
if (implementation.hasAcceptChildrenMethod) {
printAcceptChildrenMethod(implementation, elementVisitorType, TypeVariable("R"), override = true)
printBlock {
// TODO: This is copy-pasted from the IR generator. Factor this out.
for (child in implementation.walkableChildren) {
print(child.name)
if (child.nullable) {
print("?")
}
when (child) {
is SimpleField -> println(".accept(visitor, data)")
is ListField -> {
print(".forEach { it")
if (child.baseType.nullable) {
print("?")
}
println(".accept(visitor, data) }")
}
}
}
}
}
if (implementation.hasTransformChildrenMethod) {
printTransformChildrenMethod(implementation, elementTransformerType, StandardTypes.unit, override = true)
printBlock {
// TODO: This is copy-pasted from the IR generator. Factor this out.
for (child in implementation.transformableChildren) {
print(child.name)
when (child) {
is SimpleField -> {
print(" = ", child.name)
if (child.nullable) {
print("?")
}
print(".transform(transformer, data)")
val elementRef = child.typeRef as ElementRef<*>
if (!elementRef.element.hasTransformMethod) {
print(" as ", elementRef.render())
}
println()
}
is ListField -> {
addImport(transformInPlace)
println(".transformInPlace(transformer, data)")
}
}
}
}
}
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.printer
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter
import org.jetbrains.kotlin.generators.tree.printer.printBlock
import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration
import org.jetbrains.kotlin.generators.tree.printer.printFunctionWithBlockBody
import org.jetbrains.kotlin.sir.tree.generator.elementVisitorType
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.utils.SmartPrinter
internal class TransformerPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>,
private val rootElement: Element,
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorSuperType: ClassRef<PositionTypeParameterRef>
get() = elementVisitorType.withArgs(rootElement, dataTypeVariable)
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = element.transformerClass
context(ImportCollector)
override fun printMethodsForElement(element: Element) {
// FIXME: This code is copy-pasted from the FIR generator. Factor it out.
printer.run {
println()
val elementParameterName = element.visitorParameterName
if (element.isRootElement) {
val elementTP = TypeVariable("E", listOf(element))
printFunctionDeclaration(
name = "transformElement",
parameters = listOf(
FunctionParameter(elementParameterName, elementTP),
FunctionParameter("data", dataTypeVariable)
),
returnType = elementTP,
typeParameters = listOf(elementTP),
modality = Modality.ABSTRACT,
)
println()
} else {
if (element.parentInVisitor == null) return
printFunctionWithBlockBody(
name = "transform" + element.name,
parameters = listOf(
FunctionParameter(elementParameterName, element),
FunctionParameter("data", dataTypeVariable)
),
returnType = visitMethodReturnType(element),
typeParameters = element.params,
modality = Modality.OPEN,
) {
println("return transformElement(", elementParameterName, ", data)")
}
}
println()
printVisitMethodDeclaration(
element = element,
modality = Modality.FINAL,
override = true,
)
printBlock {
println(
"return transform",
element.name,
"(",
elementParameterName,
", ",
"data)"
)
}
}
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2023 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.sir.tree.generator.printer
import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.sir.tree.generator.model.Element
import org.jetbrains.kotlin.sir.tree.generator.model.Field
import org.jetbrains.kotlin.utils.SmartPrinter
internal class VisitorPrinter(
printer: SmartPrinter,
override val visitorType: ClassRef<*>
) : AbstractVisitorPrinter<Element, Field>(printer) {
override val visitorTypeParameters: List<TypeVariable>
get() = listOf(resultTypeVariable, dataTypeVariable)
override val visitorDataType: TypeRef
get() = dataTypeVariable
override fun visitMethodReturnType(element: Element) = resultTypeVariable
override val visitorSuperType: ClassRef<PositionTypeParameterRef>?
get() = null
}
+1
View File
@@ -401,6 +401,7 @@ include ":plugins:compose-compiler-plugin:compiler",
// Swift Export modules
include ":native:swift:sir",
":native:swift:sir:tree-generator",
":native:swift:sir-passes",
":native:swift:sir-printer",
":native:swift:sir-analysis-api",