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

org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.operationInstructions.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2013 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.jet.lang.cfg.pseudocode.instructions.eval

import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValueFactory
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.cfg.pseudocode.TypePredicate
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.MagicKind

public abstract class OperationInstruction protected(
        element: JetElement,
        lexicalScope: LexicalScope,
        override val inputValues: List
) : InstructionWithNext(element, lexicalScope), InstructionWithValue {
    protected var resultValue: PseudoValue? = null

    override val outputValue: PseudoValue?
        get() = resultValue

    protected fun renderInstruction(name: String, desc: String): String =
            "$name($desc" +
            (if (inputValues.notEmpty) "|${inputValues.joinToString(", ")})" else ")") +
            (if (resultValue != null) " -> $resultValue" else "")

    protected fun setResult(value: PseudoValue?): OperationInstruction {
        this.resultValue = value
        return this
    }

    protected fun setResult(factory: PseudoValueFactory?, valueElement: JetElement? = element): OperationInstruction {
        return setResult(factory?.newValue(valueElement, this))
    }
}

trait StrictlyValuedOperationInstruction: OperationInstruction {
    override val outputValue: PseudoValue
        get() = resultValue!!
}

public class CallInstruction private(
        element: JetElement,
        lexicalScope: LexicalScope,
        val resolvedCall: ResolvedCall<*>,
        override val receiverValues: Map,
        public val arguments: Map
) : OperationInstruction(element, lexicalScope, receiverValues.keySet() + arguments.keySet()), InstructionWithReceivers {
    override fun accept(visitor: InstructionVisitor) {
        visitor.visitCallInstruction(this)
    }

    override fun  accept(visitor: InstructionVisitorWithResult): R {
        return visitor.visitCallInstruction(this)
    }

    override fun createCopy() =
            CallInstruction(element, lexicalScope, resolvedCall, receiverValues, arguments).setResult(resultValue)

    override fun toString() =
            renderInstruction("call", "${render(element)}, ${resolvedCall.getResultingDescriptor()!!.getName()}")

    class object {
        fun create (
                element: JetElement,
                lexicalScope: LexicalScope,
                resolvedCall: ResolvedCall<*>,
                receiverValues: Map,
                arguments: Map,
                factory: PseudoValueFactory?
        ): CallInstruction =
                CallInstruction(element, lexicalScope, resolvedCall, receiverValues, arguments).setResult(factory, element) as CallInstruction
    }
}

// Introduces black-box operation
// Used to:
//      consume input values (so that they aren't considered unused)
//      denote value transformation which can't be expressed by other instructions (such as call or read)
//      pass more than one value to instruction which formally requires only one (e.g. jump)
public class MagicInstruction(
        element: JetElement,
        lexicalScope: LexicalScope,
        inputValues: List,
        val expectedTypes: Map,
        val kind: MagicKind
) : OperationInstruction(element, lexicalScope, inputValues), StrictlyValuedOperationInstruction {
    public val synthetic: Boolean get() = outputValue.element == null

    override fun accept(visitor: InstructionVisitor) = visitor.visitMagic(this)

    override fun  accept(visitor: InstructionVisitorWithResult): R = visitor.visitMagic(this)

    override fun createCopy() =
            MagicInstruction(element, lexicalScope, inputValues, expectedTypes, kind).setResult(resultValue)

    override fun toString() = renderInstruction("magic[$kind]", render(element))

    class object {
        fun create(
                element: JetElement,
                valueElement: JetElement?,
                lexicalScope: LexicalScope,
                inputValues: List,
                expectedTypes: Map,
                kind: MagicKind,
                factory: PseudoValueFactory
        ): MagicInstruction = MagicInstruction(
                element, lexicalScope, inputValues, expectedTypes, kind
        ).setResult(factory, valueElement) as MagicInstruction
    }
}

public enum class MagicKind(val sideEffectFree: Boolean = false) {
    // builtin operations
    STRING_TEMPLATE: MagicKind(true)
    AND: MagicKind(true)
    OR: MagicKind(true)
    NOT_NULL_ASSERTION: MagicKind()
    EQUALS_IN_WHEN_CONDITION: MagicKind()
    IS: MagicKind()
    CAST: MagicKind()
    CALLABLE_REFERENCE: MagicKind(true)
    // implicit operations
    LOOP_RANGE_ITERATION: MagicKind()
    IMPLICIT_RECEIVER: MagicKind()
    VALUE_CONSUMER: MagicKind()
    // unrecognized operations
    UNRESOLVED_CALL: MagicKind()
    UNSUPPORTED_ELEMENT: MagicKind()
    UNRECOGNIZED_WRITE_RHS: MagicKind()
    FAKE_INITIALIZER: MagicKind()
}

// Merges values produced by alternative control-flow paths (such as 'if' branches)
class MergeInstruction private(
        element: JetElement,
        lexicalScope: LexicalScope,
        inputValues: List
): OperationInstruction(element, lexicalScope, inputValues), StrictlyValuedOperationInstruction {
    override fun accept(visitor: InstructionVisitor) = visitor.visitMerge(this)

    override fun  accept(visitor: InstructionVisitorWithResult): R = visitor.visitMerge(this)

    override fun createCopy() = MergeInstruction(element, lexicalScope, inputValues).setResult(resultValue)

    override fun toString() = renderInstruction("merge", render(element))

    class object {
        fun create(
                element: JetElement,
                lexicalScope: LexicalScope,
                inputValues: List,
                factory: PseudoValueFactory
        ): MergeInstruction = MergeInstruction(element, lexicalScope, inputValues).setResult(factory) as MergeInstruction
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy