Pseudocode: Add receiver values to call instructions. Refactor InstructionWithReceiver
This commit is contained in:
@@ -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<PseudoValue> inputValues);
|
||||
PseudoValue call(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||
@NotNull Map<PseudoValue, ValueParameterDescriptor> arguments
|
||||
);
|
||||
|
||||
enum PredefinedOperation {
|
||||
AND,
|
||||
|
||||
@@ -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<PseudoValue> inputValues) {
|
||||
return getDelegateBuilder().call(expression, resolvedCall, inputValues);
|
||||
public PseudoValue call(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||
@NotNull Map<PseudoValue, ValueParameterDescriptor> arguments
|
||||
) {
|
||||
return getDelegateBuilder().call(expression, resolvedCall, receiverValues, arguments);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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<JetExpression> inputExpressions = new ArrayList<JetExpression>();
|
||||
inputExpressions.add(lhs.getArrayExpression());
|
||||
inputExpressions.addAll(lhs.getIndexExpressions());
|
||||
Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall, false);
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues =
|
||||
getArraySetterArguments(rhsDeferredValue, setResolvedCall);
|
||||
|
||||
List<PseudoValue> 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<PseudoValue, ValueParameterDescriptor> getArraySetterArguments(
|
||||
Function0<PseudoValue> rhsDeferredValue,
|
||||
final ResolvedCall<FunctionDescriptor> setResolvedCall
|
||||
) {
|
||||
List<ValueArgument> valueArguments = KotlinPackage.flatMapTo(
|
||||
setResolvedCall.getResultingDescriptor().getValueParameters(),
|
||||
new ArrayList<ValueArgument>(),
|
||||
new Function1<ValueParameterDescriptor, Iterable<? extends ValueArgument>>() {
|
||||
@Override
|
||||
public Iterable<? extends ValueArgument> invoke(ValueParameterDescriptor descriptor) {
|
||||
ResolvedValueArgument resolvedValueArgument = setResolvedCall.getValueArguments().get(descriptor);
|
||||
return resolvedValueArgument != null
|
||||
? resolvedValueArgument.getArguments()
|
||||
: Collections.<ValueArgument>emptyList();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ValueArgument rhsArgument = KotlinPackage.lastOrNull(valueArguments);
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> 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<PseudoValue> inputValues = elementsToValues(Collections.singletonList(initializer));
|
||||
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
|
||||
builder.declareVariable(entry);
|
||||
ResolvedCall<FunctionDescriptor> 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.<PseudoValue, ValueParameterDescriptor>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<PseudoValue> inputValues = new ArrayList<PseudoValue>();
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
|
||||
generateReceiver(resolvedCall.getThisObject(), inputValues);
|
||||
generateReceiver(resolvedCall.getReceiverArgument(), inputValues);
|
||||
|
||||
Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall, true);
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> 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<PseudoValue> values) {
|
||||
if (!receiver.exists()) return;
|
||||
@NotNull
|
||||
private Map<PseudoValue, ReceiverValue> getReceiverValues(ResolvedCall<?> resolvedCall, boolean generateInstructions) {
|
||||
SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
|
||||
receiverValues = getReceiverValues(resolvedCall.getThisObject(), generateInstructions, receiverValues);
|
||||
receiverValues = getReceiverValues(resolvedCall.getReceiverArgument(), generateInstructions, receiverValues);
|
||||
return receiverValues;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues(
|
||||
ReceiverValue receiver,
|
||||
boolean generateInstructions,
|
||||
SmartFMap<PseudoValue, ReceiverValue> 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<PseudoValue> values) {
|
||||
@NotNull
|
||||
private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument(
|
||||
ResolvedValueArgument argument,
|
||||
ValueParameterDescriptor parameterDescriptor,
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> 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<PseudoValue, ValueParameterDescriptor> generateValueArgument(
|
||||
ValueArgument valueArgument,
|
||||
ValueParameterDescriptor parameterDescriptor,
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -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<PseudoValue> inputValues
|
||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||
@NotNull Map<PseudoValue, ValueParameterDescriptor> 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);
|
||||
|
||||
+2
-6
@@ -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) {
|
||||
|
||||
+2
-6
@@ -24,12 +24,8 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.*
|
||||
public abstract class InstructionVisitorWithResult<R>() {
|
||||
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<R>() {
|
||||
}
|
||||
|
||||
public open fun visitWriteValue(instruction: WriteValueInstruction): R {
|
||||
return visitInstructionWithReceiver(instruction)
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
|
||||
public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R {
|
||||
|
||||
+3
-10
@@ -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<PseudoValue> = ContainerUtil.createMaybeSingletonList(receiverValue)
|
||||
public trait InstructionWithReceivers: Instruction {
|
||||
public val receiverValues: List<PseudoValue>
|
||||
}
|
||||
+11
-2
@@ -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<PseudoValue>
|
||||
get() = ContainerUtil.createMaybeSingletonList(receiverValue)
|
||||
|
||||
override val inputValues: List<PseudoValue>
|
||||
get() = receiverValues
|
||||
|
||||
override val outputValue: PseudoValue
|
||||
get() = _outputValue!!
|
||||
|
||||
|
||||
+7
-2
@@ -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<PseudoValue>
|
||||
get() = ContainerUtil.createMaybeSingletonList(receiverValue)
|
||||
|
||||
override val inputValues: List<PseudoValue>
|
||||
get() = receiverValue?.let{ receiverValue -> Arrays.asList(receiverValue, rValue) } ?: Collections.singletonList(rValue)
|
||||
|
||||
|
||||
+13
-5
@@ -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<PseudoValue>
|
||||
) : OperationInstruction(element, lexicalScope, inputValues) {
|
||||
public val receiverValueMap: Map<PseudoValue, ReceiverValue>,
|
||||
public val arguments: Map<PseudoValue, ValueParameterDescriptor>
|
||||
) : OperationInstruction(element, lexicalScope, receiverValueMap.keySet() + arguments.keySet()), InstructionWithReceivers {
|
||||
override val receiverValues: List<PseudoValue>
|
||||
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<PseudoValue>,
|
||||
receiverValues: Map<PseudoValue, ReceiverValue>,
|
||||
arguments: Map<PseudoValue, ValueParameterDescriptor>,
|
||||
factory: PseudoValueFactory?
|
||||
): CallInstruction = CallInstruction(element, lexicalScope, resolvedCall, inputValues).setResult(factory) as CallInstruction
|
||||
): CallInstruction =
|
||||
CallInstruction(element, lexicalScope, resolvedCall, receiverValues, arguments).setResult(factory) as CallInstruction
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user