Pseudocode: Bind result values to elements retrieved from resolved calls
This commit is contained in:
@@ -276,7 +276,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
|
||||
builder.readVariable(expression, expression, resolvedCall, getReceiverValues(expression, resolvedCall, true));
|
||||
builder.readVariable(expression, expression, resolvedCall, getReceiverValues(resolvedCall, true));
|
||||
}
|
||||
|
||||
copyValue(expression, expression.getInstanceReference());
|
||||
@@ -293,9 +293,9 @@ public class JetControlFlowProcessor {
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(expression);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
generateCall(expression, expression, variableAsFunctionResolvedCall.getVariableCall());
|
||||
generateCall(expression, variableAsFunctionResolvedCall.getVariableCall());
|
||||
}
|
||||
else if (!generateCall(expression, expression) && !(expression.getParent() instanceof JetCallExpression)) {
|
||||
else if (!generateCall(expression, true) && !(expression.getParent() instanceof JetCallExpression)) {
|
||||
createNonSyntheticValue(expression, generateAndGetReceiverIfAny(expression));
|
||||
}
|
||||
}
|
||||
@@ -327,19 +327,14 @@ public class JetControlFlowProcessor {
|
||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(operationReference);
|
||||
if (resolvedCall != null) {
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
PseudoValue rhsValue = generateCall(operationReference, resolvedCall).getOutputValue();
|
||||
Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
|
||||
if (descriptor.getName().equals(assignMethodName)) {
|
||||
generateCall(expression, operationReference, resolvedCall);
|
||||
}
|
||||
else {
|
||||
if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) {
|
||||
/* At this point assignment of the form a += b actually means a = a + b
|
||||
* So we first generate call of "+" operation and then use its output pseudo-value
|
||||
* as a right-hand side when generating assignment call
|
||||
*/
|
||||
Function0<PseudoValue> rhsDeferredValue =
|
||||
getValueAsFunction(generateCall(null, operationReference, resolvedCall).getOutputValue());
|
||||
visitAssignment(left, rhsDeferredValue, expression);
|
||||
visitAssignment(left, getValueAsFunction(rhsValue), expression);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -358,7 +353,7 @@ public class JetControlFlowProcessor {
|
||||
mergeValues(Arrays.asList(left, right), expression);
|
||||
}
|
||||
else {
|
||||
if (!generateCall(expression, operationReference)) {
|
||||
if (!generateCall(operationReference, true)) {
|
||||
generateBothArgumentsAndMark(expression);
|
||||
}
|
||||
}
|
||||
@@ -435,7 +430,7 @@ public class JetControlFlowProcessor {
|
||||
if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) {
|
||||
accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left));
|
||||
if (accessTarget instanceof AccessTarget.Call) {
|
||||
receiverValues = getReceiverValues(lhs, ((AccessTarget.Call) accessTarget).getResolvedCall(), true);
|
||||
receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall(), true);
|
||||
}
|
||||
}
|
||||
else if (left instanceof JetProperty) {
|
||||
@@ -473,7 +468,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
generateInstructions(lhs.getArrayExpression());
|
||||
|
||||
Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(lhs, setResolvedCall, false);
|
||||
Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall, false);
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues =
|
||||
getArraySetterArguments(rhsDeferredValue, setResolvedCall);
|
||||
|
||||
@@ -540,7 +535,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) {
|
||||
mark(arrayAccessExpression);
|
||||
if (!checkAndGenerateCall(arrayAccessExpression, arrayAccessExpression, resolvedCall)) {
|
||||
if (!checkAndGenerateCall(arrayAccessExpression, resolvedCall, true)) {
|
||||
generateArrayAccessWithoutCall(arrayAccessExpression);
|
||||
}
|
||||
}
|
||||
@@ -581,7 +576,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
PseudoValue rhsValue;
|
||||
if (resolvedCall != null) {
|
||||
rhsValue = generateCall(incrementOrDecrement ? null : expression, operationSign, resolvedCall).getOutputValue();
|
||||
rhsValue = generateCall(operationSign, resolvedCall).getOutputValue();
|
||||
}
|
||||
else {
|
||||
generateInstructions(baseExpression);
|
||||
@@ -1055,7 +1050,7 @@ public class JetControlFlowProcessor {
|
||||
@Override
|
||||
public void visitCallExpression(@NotNull JetCallExpression expression) {
|
||||
JetExpression calleeExpression = expression.getCalleeExpression();
|
||||
if (!generateCall(expression, calleeExpression)) {
|
||||
if (!generateCall(calleeExpression, true)) {
|
||||
List<JetExpression> inputExpressions = new ArrayList<JetExpression>();
|
||||
for (ValueArgument argument : expression.getValueArguments()) {
|
||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
@@ -1128,7 +1123,7 @@ public class JetControlFlowProcessor {
|
||||
entry,
|
||||
entry,
|
||||
resolvedCall,
|
||||
getReceiverValues(initializer, resolvedCall, false),
|
||||
getReceiverValues(resolvedCall, false),
|
||||
Collections.<PseudoValue, ValueParameterDescriptor>emptyMap()
|
||||
).getOutputValue();
|
||||
}
|
||||
@@ -1182,7 +1177,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
||||
mark(expression);
|
||||
ResolvedCall<FunctionDescriptor> getMethodResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
||||
if (!checkAndGenerateCall(expression, expression, getMethodResolvedCall)) {
|
||||
if (!checkAndGenerateCall(expression, getMethodResolvedCall, true)) {
|
||||
generateArrayAccess(expression, getMethodResolvedCall);
|
||||
}
|
||||
}
|
||||
@@ -1363,29 +1358,32 @@ public class JetControlFlowProcessor {
|
||||
return trace.get(BindingContext.RESOLVED_CALL, expression);
|
||||
}
|
||||
|
||||
private boolean generateCall(JetExpression callExpression, @Nullable JetExpression calleeExpression) {
|
||||
private boolean generateCall(@Nullable JetExpression calleeExpression, boolean bindResultValue) {
|
||||
if (calleeExpression == null) return false;
|
||||
return checkAndGenerateCall(callExpression, calleeExpression, getResolvedCall(calleeExpression));
|
||||
return checkAndGenerateCall(calleeExpression, getResolvedCall(calleeExpression), bindResultValue);
|
||||
}
|
||||
|
||||
private boolean checkAndGenerateCall(JetExpression callExpression, JetExpression calleeExpression, @Nullable ResolvedCall<?> resolvedCall) {
|
||||
private boolean checkAndGenerateCall(JetExpression calleeExpression, @Nullable ResolvedCall<?> resolvedCall, boolean bindResultValue) {
|
||||
if (resolvedCall == null) {
|
||||
builder.compilationError(calleeExpression, "No resolved call");
|
||||
return false;
|
||||
}
|
||||
generateCall(callExpression, calleeExpression, resolvedCall);
|
||||
generateCall(calleeExpression, resolvedCall);
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private InstructionWithValue generateCall(JetExpression callExpression, JetExpression calleeExpression, ResolvedCall<?> resolvedCall) {
|
||||
private InstructionWithValue generateCall(JetExpression calleeExpression, ResolvedCall<?> resolvedCall) {
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
return generateCall(callExpression, calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
|
||||
return generateCall(calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
|
||||
}
|
||||
|
||||
JetElement callElement = resolvedCall.getCall().getCallElement();
|
||||
JetExpression callExpression = callElement instanceof JetExpression ? (JetExpression) callElement : null;
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(callExpression, resolvedCall, true);
|
||||
Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall, true);
|
||||
SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap();
|
||||
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
|
||||
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
|
||||
@@ -1395,8 +1393,10 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
if (resultingDescriptor instanceof VariableDescriptor) {
|
||||
assert callExpression != null
|
||||
: "Variable-based call without call expression: " + callElement.getText();
|
||||
assert parameterValues.isEmpty()
|
||||
: "Variable-based call with non-empty argument list: " + resolvedCall.getCall().getCallElement().getText();
|
||||
: "Variable-based call with non-empty argument list: " + callElement.getText();
|
||||
return builder.readVariable(calleeExpression, callExpression, resolvedCall, receivers);
|
||||
}
|
||||
mark(resolvedCall.getCall().getCallElement());
|
||||
@@ -1405,18 +1405,18 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@NotNull
|
||||
private Map<PseudoValue, ReceiverValue> getReceiverValues(
|
||||
JetExpression callExpression,
|
||||
ResolvedCall<?> resolvedCall,
|
||||
boolean generateInstructions) {
|
||||
SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
|
||||
receiverValues = getReceiverValues(callExpression, resolvedCall.getThisObject(), generateInstructions, receiverValues);
|
||||
receiverValues = getReceiverValues(callExpression, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues);
|
||||
JetElement callElement = resolvedCall.getCall().getCallElement();
|
||||
receiverValues = getReceiverValues(callElement, resolvedCall.getThisObject(), generateInstructions, receiverValues);
|
||||
receiverValues = getReceiverValues(callElement, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues);
|
||||
return receiverValues;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues(
|
||||
JetExpression callExpression,
|
||||
JetElement callElement,
|
||||
ReceiverValue receiver,
|
||||
boolean generateInstructions,
|
||||
SmartFMap<PseudoValue, ReceiverValue> receiverValues
|
||||
@@ -1425,7 +1425,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
if (receiver instanceof ThisReceiver) {
|
||||
if (generateInstructions) {
|
||||
receiverValues = receiverValues.plus(createSyntheticValue(callExpression), receiver);
|
||||
receiverValues = receiverValues.plus(createSyntheticValue(callElement), receiver);
|
||||
}
|
||||
}
|
||||
else if (receiver instanceof ExpressionReceiver) {
|
||||
|
||||
@@ -102,18 +102,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
assert candidate.getDescriptor() instanceof VariableDescriptor;
|
||||
|
||||
boolean hasReceiver = candidate.getReceiverArgument().exists();
|
||||
Call variableCall = stripCallArguments(task);
|
||||
Call variableCall = stripCallArguments(task.call);
|
||||
ResolutionCandidate<CallableDescriptor> variableCandidate = getVariableCallCandidate(candidate, variableCall);
|
||||
if (!hasReceiver) {
|
||||
CallCandidateResolutionContext<CallableDescriptor> context = CallCandidateResolutionContext.create(
|
||||
ResolvedCallImpl.create(candidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
|
||||
ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
|
||||
return Collections.singleton(context);
|
||||
}
|
||||
CallCandidateResolutionContext<CallableDescriptor> contextWithReceiver = createContextWithChainedTrace(
|
||||
candidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
|
||||
variableCandidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
|
||||
|
||||
Call variableCallWithoutReceiver = stripReceiver(variableCall);
|
||||
ResolutionCandidate<CallableDescriptor> candidateWithoutReceiver = ResolutionCandidate.create(
|
||||
candidate.getCall(), candidate.getDescriptor(), candidate.getThisObject(), ReceiverValue.NO_RECEIVER,
|
||||
variableCandidate.getCall(),
|
||||
variableCandidate.getDescriptor(),
|
||||
variableCandidate.getThisObject(),
|
||||
ReceiverValue.NO_RECEIVER,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
|
||||
|
||||
CallCandidateResolutionContext<CallableDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
|
||||
@@ -131,8 +135,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue);
|
||||
}
|
||||
|
||||
private Call stripCallArguments(@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
|
||||
return new DelegatingCall(task.call) {
|
||||
@NotNull
|
||||
private ResolutionCandidate<CallableDescriptor> getVariableCallCandidate(
|
||||
@NotNull ResolutionCandidate<CallableDescriptor> candidate,
|
||||
@NotNull Call variableCall
|
||||
) {
|
||||
return ResolutionCandidate.create(
|
||||
variableCall,
|
||||
candidate.getDescriptor(),
|
||||
candidate.getThisObject(),
|
||||
candidate.getReceiverArgument(),
|
||||
candidate.getExplicitReceiverKind(),
|
||||
candidate.isSafeCall());
|
||||
}
|
||||
|
||||
private Call stripCallArguments(@NotNull Call call) {
|
||||
return new DelegatingCall(call) {
|
||||
@Override
|
||||
public JetValueArgumentList getValueArgumentList() {
|
||||
return null;
|
||||
@@ -160,6 +178,15 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement getCallElement() {
|
||||
JetExpression calleeExpression = getCalleeExpression();
|
||||
assert calleeExpression != null : "No callee expression: " + getCallElement().getText();
|
||||
|
||||
return calleeExpression;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ fun foo() {
|
||||
i++
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
i <v1> NEW()
|
||||
1 <v0> NEW()
|
||||
i <v1> NEW()
|
||||
i++ <v2> NEW(<v1>)
|
||||
{ var i = 1 i++ } <v2> COPY
|
||||
=====================
|
||||
|
||||
@@ -20,25 +20,28 @@ fun assignments() : Unit {
|
||||
t.x += 1
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
2 <v1> NEW()
|
||||
x <v2> NEW()
|
||||
2 <v3> NEW()
|
||||
true <v5> NEW()
|
||||
1 <v6> NEW()
|
||||
2 <v7> NEW()
|
||||
if (true) 1 else 2 <v8> NEW(<v6>, <v7>)
|
||||
true <v9> NEW()
|
||||
false <v10> NEW()
|
||||
true && false <v11> NEW(<v9>, <v10>)
|
||||
false <v12> NEW()
|
||||
true <v13> NEW()
|
||||
false && true <v14> NEW(<v12>, <v13>)
|
||||
Test() <v15> NEW()
|
||||
t <v16> NEW()
|
||||
1 <v17> NEW()
|
||||
t <v22> NEW()
|
||||
x <v19> NEW(<v18>)
|
||||
t.x <v19> COPY
|
||||
1 <v20> NEW()
|
||||
1 <v0> NEW()
|
||||
2 <v1> NEW()
|
||||
x <v2> NEW()
|
||||
2 <v3> NEW()
|
||||
x += 2 <v4> NEW(<v2>, <v3>)
|
||||
true <v5> NEW()
|
||||
1 <v6> NEW()
|
||||
2 <v7> NEW()
|
||||
if (true) 1 else 2 <v8> NEW(<v6>, <v7>)
|
||||
true <v9> NEW()
|
||||
false <v10> NEW()
|
||||
true && false <v11> NEW(<v9>, <v10>)
|
||||
false <v12> NEW()
|
||||
true <v13> NEW()
|
||||
false && true <v14> NEW(<v12>, <v13>)
|
||||
Test() <v15> NEW()
|
||||
t <v16> NEW()
|
||||
1 <v17> NEW()
|
||||
t <v22> NEW()
|
||||
x <v19> NEW(<v18>)
|
||||
t.x <v19> COPY
|
||||
1 <v20> NEW()
|
||||
t.x += 1 <v21> NEW(<v19>, <v20>)
|
||||
{ var x = 1 x = 2 x += 2 x = if (true) 1 else 2 val y = true && false val z = false && true val t = Test(); t.x = 1 t.x += 1 } <v21> COPY
|
||||
=====================
|
||||
|
||||
Reference in New Issue
Block a user