All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.seskar.compiler.union.backend.UnionTransformer.kt Maven / Gradle / Ivy

package seskar.compiler.union.backend

import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.declarations.addGetter
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer

internal class UnionTransformer(
    private val context: IrPluginContext,
) : IrElementTransformer {
    override fun visitClass(
        declaration: IrClass,
        data: ValueMode?,
    ): IrStatement {
        val mode = when {
            declaration.isJsUnion()
            -> ValueMode.ROOT

            data == ValueMode.ROOT && declaration.isCompanion
            -> ValueMode.COMPANION

            else -> null
        }

        if (mode == ValueMode.ROOT)
            declaration.annotations += JsName(context, declaration, "0")

        return super.visitClass(declaration, mode)
    }

    override fun visitProperty(
        declaration: IrProperty,
        data: ValueMode?,
    ): IrStatement {
        if (data != ValueMode.COMPANION)
            return declaration

        val getter = declaration.addGetter {
            isInline = true
            returnType = context.irBuiltIns.stringType
        }

        getter.addDispatchReceiver {
            type = context.irBuiltIns.nothingNType
        }

        getter.body = context.irFactory.createBlockBody(
            startOffset = declaration.startOffset,
            endOffset = declaration.endOffset,
            statements = listOf(
                IrReturnImpl(
                    startOffset = declaration.startOffset,
                    endOffset = declaration.endOffset,
                    type = context.irBuiltIns.nothingNType,
                    returnTargetSymbol = getter.symbol,
                    value = valueConstant(declaration),
                )
            )
        )

        return super.visitProperty(declaration, data)
    }

    private fun valueConstant(
        declaration: IrDeclarationWithName,
    ): IrExpression {
        val value = declaration.value()

        return when (value) {
            is IntValue ->
                IrConstImpl.int(
                    startOffset = declaration.startOffset,
                    endOffset = declaration.endOffset,
                    type = context.irBuiltIns.intType,
                    value = value.value,
                )

            is StringValue ->
                IrConstImpl.string(
                    startOffset = declaration.startOffset,
                    endOffset = declaration.endOffset,
                    type = context.irBuiltIns.stringType,
                    value = value.value,
                )
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy