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

org.jetbrains.kotlin.ir.IrElementBase.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2016 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.ir

import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor

abstract class IrElementBase : IrElement {
    /**
     * The array stores dense pairs of keys and values, followed by remaining nulls.
     * This is, the layout may look like this: `[key, value, key, value, null, null, null, ...]`
     * Keys are of type [IrAttribute].
     * Values are arbitrary objects but cannot be null.
     */
    private var attributeMap: Array? = null


    override fun  transform(transformer: IrElementTransformer, data: D): IrElement =
        accept(transformer, data)

    override fun  acceptChildren(visitor: IrElementVisitor, data: D) {
        // No children by default
    }

    override fun  transformChildren(transformer: IrElementTransformer, data: D) {
        // No children by default
    }


    /**
     * Returns a snapshot of all attributes held by this element.
     * Designated mainly for debugging.
     */
    val allAttributes: Map, Any>
        get() {
            val attributeMap = attributeMap
                ?: return emptyMap()
            return buildMap(attributeMap.size / 2) {
                for (i in attributeMap.indices step 2) {
                    val key = attributeMap[i] as IrAttribute<*, *>?
                        ?: break
                    val value = attributeMap[i + 1]!!
                    put(key, value)
                }
            }
        }

    internal fun  getAttributeInternal(key: IrAttribute<*, T>): T? {
        val foundIndex = findAttributeIndex(key)
        if (foundIndex < 0) {
            return null
        } else {
            @Suppress("UNCHECKED_CAST")
            return attributeMap!![foundIndex + 1] as T
        }
    }

    internal fun  setAttributeInternal(key: IrAttribute<*, T>, value: T?): T? {
        val foundIndex = findAttributeIndex(key)
        val previousValue: T? = if (foundIndex >= 0) {
            @Suppress("UNCHECKED_CAST")
            attributeMap!![foundIndex + 1] as T
        } else null

        putAttribute(foundIndex, key, value)
        return previousValue
    }

    private fun findAttributeIndex(key: IrAttribute<*, *>): Int {
        val attributeMap = attributeMap
            ?: return -1

        var i = 0
        while (i < attributeMap.size) {
            val foundKey = attributeMap[i]
                ?: break
            if (foundKey === key) {
                return i
            }

            i += 2
        }
        return i.inv()
    }

    private fun  initializeAttributes(firstKey: IrAttribute<*, T>, firstValue: T) {
        val initialSlots = 1
        val attributeMap = arrayOfNulls(initialSlots * 2)
        attributeMap[0] = firstKey
        attributeMap[1] = firstValue
        this.attributeMap = attributeMap
    }

    private fun  putAttribute(existingIndex: Int, key: IrAttribute<*, T>, value: T?) {
        if (existingIndex >= 0) {
            if (value == null) {
                removeAttributeAt(existingIndex)
            } else {
                attributeMap!![existingIndex + 1] = value
            }
        } else if (value != null) {
            if (attributeMap == null) {
                initializeAttributes(key, value)
            } else {
                val newEntryIndex = existingIndex.inv()
                addAttributeAt(newEntryIndex, key, value)
            }
        }
    }

    private fun  addAttributeAt(index: Int, key: IrAttribute<*, T>, value: T) {
        var attributeMap = attributeMap!!
        if (attributeMap.size <= index) {
            val newSlots = 2
            attributeMap = attributeMap.copyOf(attributeMap.size + newSlots * 2)
            this.attributeMap = attributeMap
        }

        attributeMap[index] = key
        attributeMap[index + 1] = value
    }

    private fun removeAttributeAt(keyIndex: Int) {
        // It is expected that during the compilation process, attributes are mostly appended
        // and rarely removed, hence no need to shrink the array.

        val attributeMap = attributeMap!!

        var lastKeyIndex = attributeMap.size - 2
        while (lastKeyIndex > keyIndex && attributeMap[lastKeyIndex] == null) {
            lastKeyIndex -= 2
        }

        if (lastKeyIndex > keyIndex) {
            attributeMap[keyIndex] = attributeMap[lastKeyIndex]
            attributeMap[keyIndex + 1] = attributeMap[lastKeyIndex + 1]
        }
        attributeMap[lastKeyIndex] = null
        attributeMap[lastKeyIndex + 1] = null
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy