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.PseudoValue;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
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.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface JetControlFlowBuilder {
|
public interface JetControlFlowBuilder {
|
||||||
// Subroutines
|
// Subroutines
|
||||||
@@ -123,7 +126,12 @@ public interface JetControlFlowBuilder {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@Nullable
|
@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 {
|
enum PredefinedOperation {
|
||||||
AND,
|
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.PseudoValue;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
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.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||||
|
|
||||||
@@ -90,8 +93,13 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public PseudoValue call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall, @NotNull List<PseudoValue> inputValues) {
|
public PseudoValue call(
|
||||||
return getDelegateBuilder().call(expression, resolvedCall, inputValues);
|
@NotNull JetExpression expression,
|
||||||
|
@NotNull ResolvedCall<?> resolvedCall,
|
||||||
|
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||||
|
@NotNull Map<PseudoValue, ValueParameterDescriptor> arguments
|
||||||
|
) {
|
||||||
|
return getDelegateBuilder().call(expression, resolvedCall, receiverValues, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import com.google.common.collect.Lists;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import com.intellij.util.SmartFMap;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.Function0;
|
import kotlin.Function0;
|
||||||
import kotlin.Function1;
|
import kotlin.Function1;
|
||||||
import kotlin.KotlinPackage;
|
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.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils;
|
import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
@@ -438,25 +438,64 @@ public class JetControlFlowProcessor {
|
|||||||
mark(lhs);
|
mark(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateArrayAccessArguments(lhs);
|
generateInstructions(lhs.getArrayExpression(), NOT_IN_CONDITION);
|
||||||
|
|
||||||
List<JetExpression> inputExpressions = new ArrayList<JetExpression>();
|
Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall, false);
|
||||||
inputExpressions.add(lhs.getArrayExpression());
|
SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues =
|
||||||
inputExpressions.addAll(lhs.getIndexExpressions());
|
getArraySetterArguments(rhsDeferredValue, setResolvedCall);
|
||||||
|
|
||||||
List<PseudoValue> inputValues = elementsToValues(inputExpressions);
|
builder.call(parentExpression, setResolvedCall, receiverValues, argumentValues);
|
||||||
PseudoValue rhsValue = rhsDeferredValue.invoke();
|
}
|
||||||
if (rhsValue != null) {
|
|
||||||
inputValues.add(rhsValue);
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return argumentValues;
|
||||||
builder.call(parentExpression, setResolvedCall, inputValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordWrite(JetExpression left, PseudoValue rightValue, PseudoValue receiverValue, JetExpression parentExpression) {
|
private void recordWrite(JetExpression left, PseudoValue rightValue, PseudoValue receiverValue, JetExpression parentExpression) {
|
||||||
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
|
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
|
||||||
if (descriptor != null) {
|
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) {
|
private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) {
|
||||||
JetExpression initializer = declaration.getInitializer();
|
JetExpression initializer = declaration.getInitializer();
|
||||||
generateInstructions(initializer, NOT_IN_CONDITION);
|
generateInstructions(initializer, NOT_IN_CONDITION);
|
||||||
List<PseudoValue> inputValues = elementsToValues(Collections.singletonList(initializer));
|
|
||||||
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
|
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
|
||||||
builder.declareVariable(entry);
|
builder.declareVariable(entry);
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
|
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
|
||||||
PseudoValue writtenValue = resolvedCall != null
|
PseudoValue writtenValue = resolvedCall != null
|
||||||
? builder.call(entry, resolvedCall, inputValues)
|
? builder.call(
|
||||||
: builder.magic(entry, null, inputValues, true);
|
entry,
|
||||||
|
resolvedCall,
|
||||||
|
getReceiverValues(resolvedCall, false),
|
||||||
|
Collections.<PseudoValue, ValueParameterDescriptor>emptyMap()
|
||||||
|
)
|
||||||
|
: builder.magic(entry, null,
|
||||||
|
ContainerUtil.createMaybeSingletonList(builder.getBoundValue(initializer)), true);
|
||||||
if (generateWriteForEntries) {
|
if (generateWriteForEntries) {
|
||||||
builder.write(entry, entry, writtenValue != null ? writtenValue : createSyntheticValue(entry), null);
|
builder.write(entry, entry, writtenValue != null ? writtenValue : createSyntheticValue(entry), null);
|
||||||
}
|
}
|
||||||
@@ -1286,41 +1330,54 @@ public class JetControlFlowProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PseudoValue> inputValues = new ArrayList<PseudoValue>();
|
|
||||||
|
|
||||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall, true);
|
||||||
generateReceiver(resolvedCall.getThisObject(), inputValues);
|
SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap();
|
||||||
generateReceiver(resolvedCall.getReceiverArgument(), inputValues);
|
|
||||||
|
|
||||||
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
|
||||||
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
|
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
|
||||||
if (argument == null) continue;
|
if (argument == null) continue;
|
||||||
|
|
||||||
generateValueArgument(argument, inputValues);
|
parameterValues = generateValueArgument(argument, parameterDescriptor, parameterValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultingDescriptor instanceof VariableDescriptor) {
|
if (resultingDescriptor instanceof VariableDescriptor) {
|
||||||
assert inputValues.size() <= 1 : "Wrong input values for variable-based call (must be at most 1): " + resolvedCall.getCall().getCallElement();
|
assert parameterValues.isEmpty() && receivers.size() <= 1
|
||||||
builder.readVariable(calleeExpression, (VariableDescriptor) resultingDescriptor, KotlinPackage.firstOrNull(inputValues));
|
: "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 {
|
else {
|
||||||
builder.call(calleeExpression, resolvedCall, inputValues);
|
builder.call(calleeExpression, resolvedCall, receivers, parameterValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateReceiver(ReceiverValue receiver, List<PseudoValue> values) {
|
@NotNull
|
||||||
if (!receiver.exists()) return;
|
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) {
|
if (receiver instanceof ThisReceiver) {
|
||||||
// TODO: Receiver is passed implicitly: no expression to tie the read to
|
// TODO: Receiver is passed implicitly: no expression to tie the read to
|
||||||
}
|
}
|
||||||
else if (receiver instanceof ExpressionReceiver) {
|
else if (receiver instanceof ExpressionReceiver) {
|
||||||
JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
|
JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
|
||||||
generateInstructions(expression, NOT_IN_CONDITION);
|
if (generateInstructions) {
|
||||||
|
generateInstructions(expression, NOT_IN_CONDITION);
|
||||||
|
}
|
||||||
|
|
||||||
PseudoValue receiverValue = builder.getBoundValue(expression);
|
PseudoValue receiverPseudoValue = builder.getBoundValue(expression);
|
||||||
if (receiverValue != null) {
|
if (receiverPseudoValue != null) {
|
||||||
values.add(receiverValue);
|
receiverValues = receiverValues.plus(receiverPseudoValue, receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (receiver instanceof TransientReceiver) {
|
else if (receiver instanceof TransientReceiver) {
|
||||||
@@ -1329,20 +1386,38 @@ public class JetControlFlowProcessor {
|
|||||||
else {
|
else {
|
||||||
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
|
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()) {
|
for (ValueArgument valueArgument : argument.getArguments()) {
|
||||||
JetExpression expression = valueArgument.getArgumentExpression();
|
parameterValues = generateValueArgument(valueArgument, parameterDescriptor, parameterValues);
|
||||||
if (expression != null) {
|
}
|
||||||
generateInstructions(expression, NOT_IN_CONDITION);
|
|
||||||
|
|
||||||
PseudoValue argValue = builder.getBoundValue(expression);
|
return parameterValues;
|
||||||
if (argValue != null) {
|
}
|
||||||
values.add(argValue);
|
|
||||||
}
|
@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.jumps.*;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.*;
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
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.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
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.JetType;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
@@ -456,14 +458,16 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
public PseudoValue call(
|
public PseudoValue call(
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
@NotNull ResolvedCall<?> resolvedCall,
|
@NotNull ResolvedCall<?> resolvedCall,
|
||||||
@NotNull List<PseudoValue> inputValues
|
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||||
|
@NotNull Map<PseudoValue, ValueParameterDescriptor> arguments
|
||||||
) {
|
) {
|
||||||
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||||
OperationInstruction instruction = CallInstruction.object$.create(
|
OperationInstruction instruction = CallInstruction.object$.create(
|
||||||
expression,
|
expression,
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
resolvedCall,
|
resolvedCall,
|
||||||
inputValues,
|
receiverValues,
|
||||||
|
arguments,
|
||||||
returnType != null && KotlinBuiltIns.getInstance().isNothing(returnType) ? null : valueFactory
|
returnType != null && KotlinBuiltIns.getInstance().isNothing(returnType) ? null : valueFactory
|
||||||
);
|
);
|
||||||
add(instruction);
|
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.*
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.*
|
||||||
|
|
||||||
public open class InstructionVisitor() {
|
public open class InstructionVisitor() {
|
||||||
public open fun visitInstructionWithReceiver(instruction: InstructionWithReceiver) {
|
|
||||||
visitInstructionWithNext(instruction)
|
|
||||||
}
|
|
||||||
|
|
||||||
public open fun visitReadValue(instruction: ReadValueInstruction) {
|
public open fun visitReadValue(instruction: ReadValueInstruction) {
|
||||||
visitInstructionWithReceiver(instruction)
|
visitInstructionWithNext(instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction) {
|
public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction) {
|
||||||
@@ -90,7 +86,7 @@ public open class InstructionVisitor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitWriteValue(instruction: WriteValueInstruction) {
|
public open fun visitWriteValue(instruction: WriteValueInstruction) {
|
||||||
visitInstructionWithReceiver(instruction)
|
visitInstructionWithNext(instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction) {
|
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 class InstructionVisitorWithResult<R>() {
|
||||||
public abstract fun visitInstruction(instruction: Instruction): 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 {
|
public open fun visitReadValue(instruction: ReadValueInstruction): R {
|
||||||
return visitInstructionWithReceiver(instruction)
|
return visitInstructionWithNext(instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction): R {
|
public open fun visitLocalFunctionDeclarationInstruction(instruction: LocalFunctionDeclarationInstruction): R {
|
||||||
@@ -89,7 +85,7 @@ public abstract class InstructionVisitorWithResult<R>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitWriteValue(instruction: WriteValueInstruction): R {
|
public open fun visitWriteValue(instruction: WriteValueInstruction): R {
|
||||||
return visitInstructionWithReceiver(instruction)
|
return visitInstructionWithNext(instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R {
|
public open fun visitLoadUnitValue(instruction: LoadUnitValueInstruction): R {
|
||||||
|
|||||||
+3
-10
@@ -16,16 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval
|
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 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(
|
public trait InstructionWithReceivers: Instruction {
|
||||||
element: JetElement,
|
public val receiverValues: List<PseudoValue>
|
||||||
lexicalScope: LexicalScope,
|
|
||||||
protected val receiverValue: PseudoValue?
|
|
||||||
) : InstructionWithNext(element, lexicalScope) {
|
|
||||||
override val inputValues: List<PseudoValue> = ContainerUtil.createMaybeSingletonList(receiverValue)
|
|
||||||
}
|
}
|
||||||
+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.InstructionVisitor
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
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.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 (
|
public class ReadValueInstruction private (
|
||||||
element: JetElement,
|
element: JetElement,
|
||||||
lexicalScope: LexicalScope,
|
lexicalScope: LexicalScope,
|
||||||
receiverValue: PseudoValue?,
|
public val receiverValue: PseudoValue?,
|
||||||
private var _outputValue: PseudoValue?
|
private var _outputValue: PseudoValue?
|
||||||
) : InstructionWithReceiver(element, lexicalScope, receiverValue), InstructionWithValue {
|
) : InstructionWithNext(element, lexicalScope), InstructionWithReceivers, InstructionWithValue {
|
||||||
private fun newResultValue(factory: PseudoValueFactory) {
|
private fun newResultValue(factory: PseudoValueFactory) {
|
||||||
_outputValue = factory.newValue(element, this)
|
_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
|
override val outputValue: PseudoValue
|
||||||
get() = _outputValue!!
|
get() = _outputValue!!
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -25,14 +25,19 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
|
|||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
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.InstructionImpl
|
||||||
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext
|
||||||
|
import com.intellij.util.containers.ContainerUtil
|
||||||
|
|
||||||
public class WriteValueInstruction(
|
public class WriteValueInstruction(
|
||||||
assignment: JetElement,
|
assignment: JetElement,
|
||||||
public val lValue: JetElement,
|
public val lValue: JetElement,
|
||||||
public val rValue: PseudoValue,
|
public val rValue: PseudoValue,
|
||||||
receiverValue: PseudoValue?,
|
public val receiverValue: PseudoValue?,
|
||||||
lexicalScope: LexicalScope
|
lexicalScope: LexicalScope
|
||||||
) : InstructionWithReceiver(assignment, lexicalScope, receiverValue) {
|
) : InstructionWithNext(assignment, lexicalScope), InstructionWithReceivers {
|
||||||
|
override val receiverValues: List<PseudoValue>
|
||||||
|
get() = ContainerUtil.createMaybeSingletonList(receiverValue)
|
||||||
|
|
||||||
override val inputValues: List<PseudoValue>
|
override val inputValues: List<PseudoValue>
|
||||||
get() = receiverValue?.let{ receiverValue -> Arrays.asList(receiverValue, rValue) } ?: Collections.singletonList(rValue)
|
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.InstructionWithNext
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
|
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.InstructionVisitorWithResult
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||||
|
|
||||||
public abstract class OperationInstruction protected(
|
public abstract class OperationInstruction protected(
|
||||||
element: JetElement,
|
element: JetElement,
|
||||||
@@ -54,8 +56,12 @@ public class CallInstruction private(
|
|||||||
element: JetElement,
|
element: JetElement,
|
||||||
lexicalScope: LexicalScope,
|
lexicalScope: LexicalScope,
|
||||||
val resolvedCall: ResolvedCall<*>,
|
val resolvedCall: ResolvedCall<*>,
|
||||||
inputValues: List<PseudoValue>
|
public val receiverValueMap: Map<PseudoValue, ReceiverValue>,
|
||||||
) : OperationInstruction(element, lexicalScope, inputValues) {
|
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) {
|
override fun accept(visitor: InstructionVisitor) {
|
||||||
visitor.visitCallInstruction(this)
|
visitor.visitCallInstruction(this)
|
||||||
}
|
}
|
||||||
@@ -65,7 +71,7 @@ public class CallInstruction private(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createCopy() =
|
override fun createCopy() =
|
||||||
CallInstruction(element, lexicalScope, resolvedCall, inputValues).setResult(resultValue)
|
CallInstruction(element, lexicalScope, resolvedCall, receiverValueMap, arguments).setResult(resultValue)
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
renderInstruction("call", "${render(element)}, ${resolvedCall.getResultingDescriptor()!!.getName()}")
|
renderInstruction("call", "${render(element)}, ${resolvedCall.getResultingDescriptor()!!.getName()}")
|
||||||
@@ -75,9 +81,11 @@ public class CallInstruction private(
|
|||||||
element: JetElement,
|
element: JetElement,
|
||||||
lexicalScope: LexicalScope,
|
lexicalScope: LexicalScope,
|
||||||
resolvedCall: ResolvedCall<*>,
|
resolvedCall: ResolvedCall<*>,
|
||||||
inputValues: List<PseudoValue>,
|
receiverValues: Map<PseudoValue, ReceiverValue>,
|
||||||
|
arguments: Map<PseudoValue, ValueParameterDescriptor>,
|
||||||
factory: PseudoValueFactory?
|
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