From 9ddfc32cdc63ef82455a7d98ef0f2d1b8e150b1e Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 3 Jun 2014 18:55:11 +0400 Subject: [PATCH] Pseudocode: Add receiver values to call instructions. Refactor InstructionWithReceiver --- .../jet/lang/cfg/JetControlFlowBuilder.java | 10 +- .../cfg/JetControlFlowBuilderAdapter.java | 12 +- .../jet/lang/cfg/JetControlFlowProcessor.java | 157 +++++++++++++----- .../JetControlFlowInstructionsGenerator.java | 8 +- .../instructions/InstructionVisitor.kt | 8 +- .../InstructionVisitorWithResult.kt | 8 +- ...eceiver.kt => InstructionWithReceivers.kt} | 13 +- .../instructions/eval/ReadValueInstruction.kt | 13 +- .../eval/WriteValueInstruction.kt | 9 +- .../eval/operationInstructions.kt | 18 +- 10 files changed, 179 insertions(+), 77 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/{InstructionWithReceiver.kt => InstructionWithReceivers.kt} (61%) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index 0728b81efdf..672b097361f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -21,12 +21,15 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import java.util.List; +import java.util.Map; public interface JetControlFlowBuilder { // Subroutines @@ -123,7 +126,12 @@ public interface JetControlFlowBuilder { ); @Nullable - PseudoValue call(@NotNull JetExpression expression, @NotNull ResolvedCall resolvedCall, @NotNull List inputValues); + PseudoValue call( + @NotNull JetExpression expression, + @NotNull ResolvedCall resolvedCall, + @NotNull Map receiverValues, + @NotNull Map arguments + ); enum PredefinedOperation { AND, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index 9f3b7bd5fbd..359e3e24ac8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -21,12 +21,15 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import java.util.List; +import java.util.Map; public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { @@ -90,8 +93,13 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil @Nullable @Override - public PseudoValue call(@NotNull JetExpression expression, @NotNull ResolvedCall resolvedCall, @NotNull List inputValues) { - return getDelegateBuilder().call(expression, resolvedCall, inputValues); + public PseudoValue call( + @NotNull JetExpression expression, + @NotNull ResolvedCall resolvedCall, + @NotNull Map receiverValues, + @NotNull Map arguments + ) { + return getDelegateBuilder().call(expression, resolvedCall, receiverValues, arguments); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index c51966d1c0b..d5d18a27af4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -21,6 +21,8 @@ import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.SmartFMap; +import com.intellij.util.containers.ContainerUtil; import kotlin.Function0; import kotlin.Function1; import kotlin.KotlinPackage; @@ -36,9 +38,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; -import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; @@ -438,25 +438,64 @@ public class JetControlFlowProcessor { mark(lhs); } - generateArrayAccessArguments(lhs); + generateInstructions(lhs.getArrayExpression(), NOT_IN_CONDITION); - List inputExpressions = new ArrayList(); - inputExpressions.add(lhs.getArrayExpression()); - inputExpressions.addAll(lhs.getIndexExpressions()); + Map receiverValues = getReceiverValues(setResolvedCall, false); + SmartFMap argumentValues = + getArraySetterArguments(rhsDeferredValue, setResolvedCall); - List inputValues = elementsToValues(inputExpressions); - PseudoValue rhsValue = rhsDeferredValue.invoke(); - if (rhsValue != null) { - inputValues.add(rhsValue); + builder.call(parentExpression, setResolvedCall, receiverValues, argumentValues); + } + + /* We assume that assignment right-hand side corresponds to the last argument of the call + * So receiver instructions/pseudo-values are generated for all arguments except the last one which is replaced + * by pre-generated pseudo-value + * For example, assignment a[1, 2] += 3 means a.set(1, 2, a.get(1) + 3), so in order to generate "set" call + * we first generate instructions for 1 and 2 whereas 3 is replaced by pseudo-value corresponding to "a.get(1) + 3" + */ + private SmartFMap getArraySetterArguments( + Function0 rhsDeferredValue, + final ResolvedCall setResolvedCall + ) { + List valueArguments = KotlinPackage.flatMapTo( + setResolvedCall.getResultingDescriptor().getValueParameters(), + new ArrayList(), + new Function1>() { + @Override + public Iterable invoke(ValueParameterDescriptor descriptor) { + ResolvedValueArgument resolvedValueArgument = setResolvedCall.getValueArguments().get(descriptor); + return resolvedValueArgument != null + ? resolvedValueArgument.getArguments() + : Collections.emptyList(); + } + } + ); + + ValueArgument rhsArgument = KotlinPackage.lastOrNull(valueArguments); + SmartFMap argumentValues = SmartFMap.emptyMap(); + for (ValueArgument valueArgument : valueArguments) { + ArgumentMapping argumentMapping = setResolvedCall.getArgumentMapping(valueArgument); + if (argumentMapping.isError() || (!(argumentMapping instanceof ArgumentMatch))) continue; + + ValueParameterDescriptor parameterDescriptor = ((ArgumentMatch) argumentMapping).getValueParameter(); + if (valueArgument != rhsArgument) { + argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues); + } + else { + PseudoValue rhsValue = rhsDeferredValue.invoke(); + if (rhsValue != null) { + argumentValues = argumentValues.plus(rhsValue, parameterDescriptor); + } + } } - - builder.call(parentExpression, setResolvedCall, inputValues); + return argumentValues; } private void recordWrite(JetExpression left, PseudoValue rightValue, PseudoValue receiverValue, JetExpression parentExpression) { VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false); if (descriptor != null) { - builder.write(parentExpression, left, rightValue != null ? rightValue : createSyntheticValue(parentExpression), receiverValue); + builder.write(parentExpression, left, rightValue != null ? rightValue : createSyntheticValue(parentExpression), + receiverValue); } } @@ -1027,13 +1066,18 @@ public class JetControlFlowProcessor { private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) { JetExpression initializer = declaration.getInitializer(); generateInstructions(initializer, NOT_IN_CONDITION); - List inputValues = elementsToValues(Collections.singletonList(initializer)); for (JetMultiDeclarationEntry entry : declaration.getEntries()) { builder.declareVariable(entry); ResolvedCall resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry); PseudoValue writtenValue = resolvedCall != null - ? builder.call(entry, resolvedCall, inputValues) - : builder.magic(entry, null, inputValues, true); + ? builder.call( + entry, + resolvedCall, + getReceiverValues(resolvedCall, false), + Collections.emptyMap() + ) + : builder.magic(entry, null, + ContainerUtil.createMaybeSingletonList(builder.getBoundValue(initializer)), true); if (generateWriteForEntries) { builder.write(entry, entry, writtenValue != null ? writtenValue : createSyntheticValue(entry), null); } @@ -1286,41 +1330,54 @@ public class JetControlFlowProcessor { return; } - List inputValues = new ArrayList(); - CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); - - generateReceiver(resolvedCall.getThisObject(), inputValues); - generateReceiver(resolvedCall.getReceiverArgument(), inputValues); - + Map receivers = getReceiverValues(resolvedCall, true); + SmartFMap parameterValues = SmartFMap.emptyMap(); for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) { ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor); if (argument == null) continue; - generateValueArgument(argument, inputValues); + parameterValues = generateValueArgument(argument, parameterDescriptor, parameterValues); } if (resultingDescriptor instanceof VariableDescriptor) { - assert inputValues.size() <= 1 : "Wrong input values for variable-based call (must be at most 1): " + resolvedCall.getCall().getCallElement(); - builder.readVariable(calleeExpression, (VariableDescriptor) resultingDescriptor, KotlinPackage.firstOrNull(inputValues)); + assert parameterValues.isEmpty() && receivers.size() <= 1 + : "Wrong input values for variable-based call (must be at most 1 receiver): " + resolvedCall.getCall().getCallElement().getText(); + builder.readVariable(calleeExpression, (VariableDescriptor) resultingDescriptor, KotlinPackage.firstOrNull(receivers.keySet())); } else { - builder.call(calleeExpression, resolvedCall, inputValues); + builder.call(calleeExpression, resolvedCall, receivers, parameterValues); } } - private void generateReceiver(ReceiverValue receiver, List values) { - if (!receiver.exists()) return; + @NotNull + private Map getReceiverValues(ResolvedCall resolvedCall, boolean generateInstructions) { + SmartFMap receiverValues = SmartFMap.emptyMap(); + receiverValues = getReceiverValues(resolvedCall.getThisObject(), generateInstructions, receiverValues); + receiverValues = getReceiverValues(resolvedCall.getReceiverArgument(), generateInstructions, receiverValues); + return receiverValues; + } + + @NotNull + private SmartFMap getReceiverValues( + ReceiverValue receiver, + boolean generateInstructions, + SmartFMap receiverValues + ) { + if (!receiver.exists()) return receiverValues; + if (receiver instanceof ThisReceiver) { // TODO: Receiver is passed implicitly: no expression to tie the read to } else if (receiver instanceof ExpressionReceiver) { JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); - generateInstructions(expression, NOT_IN_CONDITION); + if (generateInstructions) { + generateInstructions(expression, NOT_IN_CONDITION); + } - PseudoValue receiverValue = builder.getBoundValue(expression); - if (receiverValue != null) { - values.add(receiverValue); + PseudoValue receiverPseudoValue = builder.getBoundValue(expression); + if (receiverPseudoValue != null) { + receiverValues = receiverValues.plus(receiverPseudoValue, receiver); } } else if (receiver instanceof TransientReceiver) { @@ -1329,20 +1386,38 @@ public class JetControlFlowProcessor { else { throw new IllegalArgumentException("Unknown receiver kind: " + receiver); } + + return receiverValues; } - private void generateValueArgument(ResolvedValueArgument argument, List values) { + @NotNull + private SmartFMap generateValueArgument( + ResolvedValueArgument argument, + ValueParameterDescriptor parameterDescriptor, + SmartFMap parameterValues + ) { for (ValueArgument valueArgument : argument.getArguments()) { - JetExpression expression = valueArgument.getArgumentExpression(); - if (expression != null) { - generateInstructions(expression, NOT_IN_CONDITION); + parameterValues = generateValueArgument(valueArgument, parameterDescriptor, parameterValues); + } - PseudoValue argValue = builder.getBoundValue(expression); - if (argValue != null) { - values.add(argValue); - } + return parameterValues; + } + + @NotNull + private SmartFMap generateValueArgument( + ValueArgument valueArgument, + ValueParameterDescriptor parameterDescriptor, + SmartFMap parameterValues) { + JetExpression expression = valueArgument.getArgumentExpression(); + if (expression != null) { + generateInstructions(expression, NOT_IN_CONDITION); + + PseudoValue argValue = builder.getBoundValue(expression); + if (argValue != null) { + parameterValues = parameterValues.plus(argValue, parameterDescriptor); } } + return parameterValues; } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 9b3862d040c..7ec2c8cd7f8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -26,10 +26,12 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.*; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.*; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.*; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; @@ -456,14 +458,16 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd public PseudoValue call( @NotNull JetExpression expression, @NotNull ResolvedCall resolvedCall, - @NotNull List inputValues + @NotNull Map receiverValues, + @NotNull Map arguments ) { JetType returnType = resolvedCall.getResultingDescriptor().getReturnType(); OperationInstruction instruction = CallInstruction.object$.create( expression, getCurrentScope(), resolvedCall, - inputValues, + receiverValues, + arguments, returnType != null && KotlinBuiltIns.getInstance().isNothing(returnType) ? null : valueFactory ); add(instruction); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitor.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitor.kt index 7089b660f5e..8f41cee9d88 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitor.kt @@ -22,12 +22,8 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.* import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.* public open class InstructionVisitor() { - public open fun visitInstructionWithReceiver(instruction: InstructionWithReceiver) { - visitInstructionWithNext(instruction) - } - public open fun visitReadValue(instruction: ReadValueInstruction) { - visitInstructionWithReceiver(instruction) + visitInstructionWithNext(instruction) } public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction) { @@ -90,7 +86,7 @@ public open class InstructionVisitor() { } public open fun visitWriteValue(instruction: WriteValueInstruction) { - visitInstructionWithReceiver(instruction) + visitInstructionWithNext(instruction) } public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitorWithResult.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitorWithResult.kt index 6170cbf4a56..43afa1f88ab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitorWithResult.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionVisitorWithResult.kt @@ -24,12 +24,8 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.* public abstract class InstructionVisitorWithResult() { public abstract fun visitInstruction(instruction: Instruction): R - public open fun visitInstructionWithReceiver(instruction: InstructionWithReceiver): R { - return visitInstructionWithNext(instruction) - } - public open fun visitReadValue(instruction: ReadValueInstruction): R { - return visitInstructionWithReceiver(instruction) + return visitInstructionWithNext(instruction) } public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction): R { @@ -89,7 +85,7 @@ public abstract class InstructionVisitorWithResult() { } public open fun visitWriteValue(instruction: WriteValueInstruction): R { - return visitInstructionWithReceiver(instruction) + return visitInstructionWithNext(instruction) } public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceiver.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceivers.kt similarity index 61% rename from compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceiver.kt rename to compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceivers.kt index be5038b5732..2d7bec994d1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceiver.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/InstructionWithReceivers.kt @@ -16,16 +16,9 @@ package org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext -import org.jetbrains.jet.lang.psi.JetElement -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue -import com.intellij.util.containers.ContainerUtil +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.Instruction -public abstract class InstructionWithReceiver( - element: JetElement, - lexicalScope: LexicalScope, - protected val receiverValue: PseudoValue? -) : InstructionWithNext(element, lexicalScope) { - override val inputValues: List = ContainerUtil.createMaybeSingletonList(receiverValue) +public trait InstructionWithReceivers: Instruction { + public val receiverValues: List } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/ReadValueInstruction.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/ReadValueInstruction.kt index b1de88899a3..70eebf36e1f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/ReadValueInstruction.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/ReadValueInstruction.kt @@ -23,17 +23,26 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionImpl +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext +import com.intellij.util.containers.ContainerUtil +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue public class ReadValueInstruction private ( element: JetElement, lexicalScope: LexicalScope, - receiverValue: PseudoValue?, + public val receiverValue: PseudoValue?, private var _outputValue: PseudoValue? -) : InstructionWithReceiver(element, lexicalScope, receiverValue), InstructionWithValue { +) : InstructionWithNext(element, lexicalScope), InstructionWithReceivers, InstructionWithValue { private fun newResultValue(factory: PseudoValueFactory) { _outputValue = factory.newValue(element, this) } + override val receiverValues: List + get() = ContainerUtil.createMaybeSingletonList(receiverValue) + + override val inputValues: List + get() = receiverValues + override val outputValue: PseudoValue get() = _outputValue!! diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/WriteValueInstruction.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/WriteValueInstruction.kt index 0e7a40bfe7d..286190f12b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/WriteValueInstruction.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/WriteValueInstruction.kt @@ -25,14 +25,19 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor import java.util.Arrays import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionImpl +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext +import com.intellij.util.containers.ContainerUtil public class WriteValueInstruction( assignment: JetElement, public val lValue: JetElement, public val rValue: PseudoValue, - receiverValue: PseudoValue?, + public val receiverValue: PseudoValue?, lexicalScope: LexicalScope -) : InstructionWithReceiver(assignment, lexicalScope, receiverValue) { +) : InstructionWithNext(assignment, lexicalScope), InstructionWithReceivers { + override val receiverValues: List + get() = ContainerUtil.createMaybeSingletonList(receiverValue) + override val inputValues: List get() = receiverValue?.let{ receiverValue -> Arrays.asList(receiverValue, rValue) } ?: Collections.singletonList(rValue) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt index ae7634e4c29..0c9e34274c6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt @@ -24,6 +24,8 @@ 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 public abstract class OperationInstruction protected( element: JetElement, @@ -54,8 +56,12 @@ public class CallInstruction private( element: JetElement, lexicalScope: LexicalScope, val resolvedCall: ResolvedCall<*>, - inputValues: List -) : OperationInstruction(element, lexicalScope, inputValues) { + public val receiverValueMap: Map, + public val arguments: Map +) : OperationInstruction(element, lexicalScope, receiverValueMap.keySet() + arguments.keySet()), InstructionWithReceivers { + override val receiverValues: List + get() = receiverValueMap.keySet().toList() + override fun accept(visitor: InstructionVisitor) { visitor.visitCallInstruction(this) } @@ -65,7 +71,7 @@ public class CallInstruction private( } override fun createCopy() = - CallInstruction(element, lexicalScope, resolvedCall, inputValues).setResult(resultValue) + CallInstruction(element, lexicalScope, resolvedCall, receiverValueMap, arguments).setResult(resultValue) override fun toString() = renderInstruction("call", "${render(element)}, ${resolvedCall.getResultingDescriptor()!!.getName()}") @@ -75,9 +81,11 @@ public class CallInstruction private( element: JetElement, lexicalScope: LexicalScope, resolvedCall: ResolvedCall<*>, - inputValues: List, + receiverValues: Map, + arguments: Map, factory: PseudoValueFactory? - ): CallInstruction = CallInstruction(element, lexicalScope, resolvedCall, inputValues).setResult(factory) as CallInstruction + ): CallInstruction = + CallInstruction(element, lexicalScope, resolvedCall, receiverValues, arguments).setResult(factory) as CallInstruction } }