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

org.jetbrains.kotlin.psi2ir.intermediate.ArrayAccessAssignmentReceiver.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
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.psi2ir.intermediate

import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.inlineStatement
import org.jetbrains.kotlin.ir.expressions.isAssignmentOperatorWithResult
import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
import org.jetbrains.kotlin.types.KotlinType
import java.lang.AssertionError

class ArrayAccessAssignmentReceiver(
        val irArray: IrExpression,
        val irIndices: List,
        val indexedGetCall: CallBuilder?,
        val indexedSetCall: CallBuilder?,
        val callGenerator: CallGenerator,
        val startOffset: Int,
        val endOffset: Int,
        val origin: IrStatementOrigin
) : AssignmentReceiver {
    private val type: KotlinType = indexedGetCall?.run { descriptor.returnType!! } ?:
                                   indexedSetCall?.run { descriptor.valueParameters.last().type } ?:
                                   throw AssertionError("Array access should have either indexed-get call or indexed-set call")

    override fun assign(withLValue: (LValue) -> IrExpression): IrExpression {
        val hasResult = origin.isAssignmentOperatorWithResult()
        val resultType = if (hasResult) type else callGenerator.context.builtIns.unitType
        val irBlock = IrBlockImpl(startOffset, endOffset, resultType, origin)

        val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(irArray, irBlock, "array")

        val irIndexValues = irIndices.mapIndexed { i, irIndex ->
            callGenerator.scope.createTemporaryVariableInBlock(irIndex, irBlock, "index$i")
        }

        indexedGetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
        indexedSetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
        val irLValue = LValueWithGetterAndSetterCalls(callGenerator, indexedGetCall, indexedSetCall, type, startOffset, endOffset, origin)
        irBlock.inlineStatement(withLValue(irLValue))

        return irBlock
    }

    override fun assign(value: IrExpression): IrExpression {
        if (indexedSetCall == null) throw AssertionError("Array access without indexed-get call")
        indexedSetCall.setExplicitReceiverValue(OnceExpressionValue(irArray))
        irIndices.forEachIndexed { i, irIndex ->
            indexedSetCall.irValueArgumentsByIndex[i] = irIndex
        }
        indexedSetCall.lastArgument = value
        return callGenerator.generateCall(startOffset, endOffset, indexedSetCall, IrStatementOrigin.EQ)
    }

    private fun CallBuilder.fillArrayAndIndexArguments(arrayValue: IntermediateValue, indexValues: List) {
        setExplicitReceiverValue(arrayValue)
        indexValues.forEachIndexed { i, irIndexValue ->
            irValueArgumentsByIndex[i] = irIndexValue.load()
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy