001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.cfg;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Sets;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.tree.IElementType;
023 import com.intellij.psi.util.PsiTreeUtil;
024 import com.intellij.util.SmartFMap;
025 import com.intellij.util.containers.ContainerUtil;
026 import com.intellij.util.containers.MultiMap;
027 import kotlin.KotlinPackage;
028 import kotlin.jvm.functions.Function0;
029 import kotlin.jvm.functions.Function1;
030 import org.jetbrains.annotations.NotNull;
031 import org.jetbrains.annotations.Nullable;
032 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
033 import org.jetbrains.kotlin.cfg.pseudocode.*;
034 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget;
035 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValue;
036 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind;
037 import org.jetbrains.kotlin.descriptors.*;
038 import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
039 import org.jetbrains.kotlin.lexer.JetToken;
040 import org.jetbrains.kotlin.lexer.JetTokens;
041 import org.jetbrains.kotlin.name.Name;
042 import org.jetbrains.kotlin.psi.*;
043 import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
044 import org.jetbrains.kotlin.resolve.BindingContext;
045 import org.jetbrains.kotlin.resolve.BindingContextUtils;
046 import org.jetbrains.kotlin.resolve.BindingTrace;
047 import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
048 import org.jetbrains.kotlin.renderer.DescriptorRenderer;
049 import org.jetbrains.kotlin.resolve.*;
050 import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage;
051 import org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper;
052 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
053 import org.jetbrains.kotlin.resolve.calls.model.*;
054 import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
055 import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
056 import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
057 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
058 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
059 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
060 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
061 import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
062 import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
063 import org.jetbrains.kotlin.types.JetType;
064 import org.jetbrains.kotlin.types.expressions.OperatorConventions;
065
066 import java.util.*;
067
068 import static org.jetbrains.kotlin.cfg.JetControlFlowBuilder.PredefinedOperation.*;
069 import static org.jetbrains.kotlin.diagnostics.Errors.*;
070 import static org.jetbrains.kotlin.lexer.JetTokens.*;
071 import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
072
073 public class JetControlFlowProcessor {
074
075 private final JetControlFlowBuilder builder;
076 private final BindingTrace trace;
077
078 public JetControlFlowProcessor(BindingTrace trace) {
079 this.builder = new JetControlFlowInstructionsGenerator();
080 this.trace = trace;
081 }
082
083 @NotNull
084 public Pseudocode generatePseudocode(@NotNull JetElement subroutine) {
085 Pseudocode pseudocode = generate(subroutine);
086 ((PseudocodeImpl) pseudocode).postProcess();
087 return pseudocode;
088 }
089
090 @NotNull
091 private Pseudocode generate(@NotNull JetElement subroutine) {
092 builder.enterSubroutine(subroutine);
093 CFPVisitor cfpVisitor = new CFPVisitor(builder);
094 if (subroutine instanceof JetDeclarationWithBody && !(subroutine instanceof JetSecondaryConstructor)) {
095 JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
096 List<JetParameter> valueParameters = declarationWithBody.getValueParameters();
097 for (JetParameter valueParameter : valueParameters) {
098 cfpVisitor.generateInstructions(valueParameter);
099 }
100 JetExpression bodyExpression = declarationWithBody.getBodyExpression();
101 if (bodyExpression != null) {
102 cfpVisitor.generateInstructions(bodyExpression);
103 if (!declarationWithBody.hasBlockBody()) {
104 generateImplicitReturnValue(bodyExpression, subroutine);
105 }
106 }
107 } else {
108 cfpVisitor.generateInstructions(subroutine);
109 }
110 return builder.exitSubroutine(subroutine);
111 }
112
113 private void generateImplicitReturnValue(@NotNull JetExpression bodyExpression, @NotNull JetElement subroutine) {
114 CallableDescriptor subroutineDescriptor = (CallableDescriptor) trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, subroutine);
115 if (subroutineDescriptor == null) return;
116
117 JetType returnType = subroutineDescriptor.getReturnType();
118 if (returnType != null && KotlinBuiltIns.isUnit(returnType) && subroutineDescriptor instanceof AnonymousFunctionDescriptor) return;
119
120 PseudoValue returnValue = builder.getBoundValue(bodyExpression);
121 if (returnValue == null) return;
122
123 builder.returnValue(bodyExpression, returnValue, subroutine);
124 }
125
126 private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
127 Label afterDeclaration = builder.createUnboundLabel("after local declaration");
128
129 builder.nondeterministicJump(afterDeclaration, subroutine, null);
130 generate(subroutine);
131 builder.bindLabel(afterDeclaration);
132 }
133
134 private class CFPVisitor extends JetVisitorVoid {
135 private final JetControlFlowBuilder builder;
136
137 private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() {
138
139 private JetExpression getSubjectExpression(JetWhenCondition condition) {
140 JetWhenExpression whenExpression = PsiTreeUtil.getParentOfType(condition, JetWhenExpression.class);
141 return whenExpression != null ? whenExpression.getSubjectExpression() : null;
142 }
143
144 @Override
145 public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) {
146 if (!generateCall(condition.getOperationReference())) {
147 JetExpression rangeExpression = condition.getRangeExpression();
148 generateInstructions(rangeExpression);
149 createUnresolvedCall(condition, rangeExpression);
150 }
151 }
152
153 @Override
154 public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) {
155 mark(condition);
156 createNonSyntheticValue(condition, MagicKind.IS, getSubjectExpression(condition));
157 }
158
159 @Override
160 public void visitWhenConditionWithExpression(@NotNull JetWhenConditionWithExpression condition) {
161 mark(condition);
162
163 JetExpression expression = condition.getExpression();
164 generateInstructions(expression);
165
166 JetExpression subjectExpression = getSubjectExpression(condition);
167 if (subjectExpression != null) {
168 // todo: this can be replaced by equals() invocation (when corresponding resolved call is recorded)
169 createNonSyntheticValue(condition, MagicKind.EQUALS_IN_WHEN_CONDITION, subjectExpression, expression);
170 }
171 else {
172 copyValue(expression, condition);
173 }
174 }
175
176 @Override
177 public void visitJetElement(@NotNull JetElement element) {
178 throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
179 }
180 };
181
182 private CFPVisitor(@NotNull JetControlFlowBuilder builder) {
183 this.builder = builder;
184 }
185
186 private void mark(JetElement element) {
187 builder.mark(element);
188 }
189
190 public void generateInstructions(@Nullable JetElement element) {
191 if (element == null) return;
192 element.accept(this);
193 checkNothingType(element);
194 }
195
196 private void checkNothingType(JetElement element) {
197 if (!(element instanceof JetExpression)) return;
198
199 JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element);
200 if (expression == null) return;
201
202 if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression
203 || expression instanceof JetIfExpression || expression instanceof JetWhenExpression) {
204 return;
205 }
206
207 JetType type = trace.getBindingContext().getType(expression);
208 if (type != null && KotlinBuiltIns.isNothing(type)) {
209 builder.jumpToError(expression);
210 }
211 }
212
213 @NotNull
214 private PseudoValue createSyntheticValue(@NotNull JetElement instructionElement, @NotNull MagicKind kind, JetElement... from) {
215 List<PseudoValue> values = elementsToValues(from.length > 0 ? Arrays.asList(from) : Collections.<JetElement>emptyList());
216 return builder.magic(instructionElement, null, values, defaultTypeMap(values), kind).getOutputValue();
217 }
218
219 @NotNull
220 private PseudoValue createNonSyntheticValue(
221 @NotNull JetElement to, @NotNull List<? extends JetElement> from, @NotNull MagicKind kind
222 ) {
223 List<PseudoValue> values = elementsToValues(from);
224 return builder.magic(to, to, values, defaultTypeMap(values), kind).getOutputValue();
225 }
226
227 @NotNull
228 private PseudoValue createNonSyntheticValue(@NotNull JetElement to, @NotNull MagicKind kind, JetElement... from) {
229 return createNonSyntheticValue(to, Arrays.asList(from), kind);
230 }
231
232 @Nullable
233 private Map<PseudoValue, TypePredicate> getTypeMapForUnresolvedCall(@NotNull JetElement to, List<PseudoValue> arguments) {
234 Call call = CallUtilPackage.getCall(to, trace.getBindingContext());
235 if (call == null) return null;
236
237 JetExpression callee = call.getCalleeExpression();
238 if (callee == null) return null;
239
240 Collection<FunctionDescriptor> candidates = KotlinPackage.sortBy(
241 KotlinPackage.filterIsInstance(
242 BindingContextUtilPackage.getReferenceTargets(callee, trace.getBindingContext()),
243 FunctionDescriptor.class
244 ),
245 new Function1<FunctionDescriptor, Comparable>() {
246 @Override
247 public Comparable invoke(FunctionDescriptor descriptor) {
248 return DescriptorRenderer.DEBUG_TEXT.render(descriptor);
249 }
250 }
251 );
252 if (candidates.isEmpty()) return null;
253
254 ReceiverValue explicitReceiver = call.getExplicitReceiver();
255 int argValueOffset = explicitReceiver.exists() ? 1 : 0;
256
257 MultiMap<PseudoValue, TypePredicate> valuesToPredicates = new MultiMap<PseudoValue, TypePredicate>(arguments.size(), 1);
258
259 candidateLoop:
260 for (FunctionDescriptor candidate : candidates) {
261 ResolvedCallImpl<FunctionDescriptor> candidateCall = ResolvedCallImpl.create(
262 ResolutionCandidate.create(call,
263 candidate,
264 call.getDispatchReceiver(),
265 explicitReceiver,
266 ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
267 null),
268 new DelegatingBindingTrace(trace.getBindingContext(), "Compute type predicates for unresolved call arguments"),
269 TracingStrategy.EMPTY,
270 new DataFlowInfoForArgumentsImpl(call)
271 );
272 ValueArgumentsToParametersMapper.Status status = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
273 call,
274 TracingStrategy.EMPTY,
275 candidateCall,
276 Sets.<ValueArgument>newLinkedHashSet()
277 );
278 if (!status.isSuccess()) continue;
279
280 Map<ValueParameterDescriptor, ResolvedValueArgument> candidateArgumentMap = candidateCall.getValueArguments();
281 List<? extends ValueArgument> callArguments = call.getValueArguments();
282 for (int i = 0; i < callArguments.size(); i++) {
283 int valueIndex = i + argValueOffset;
284 if (valueIndex >= arguments.size()) continue candidateLoop;
285 PseudoValue argumentValue = arguments.get(valueIndex);
286
287 ArgumentMapping mapping = candidateCall.getArgumentMapping(callArguments.get(i));
288 if (!(mapping instanceof ArgumentMatch)) continue candidateLoop;
289
290 ValueParameterDescriptor candidateParameter = ((ArgumentMatch) mapping).getValueParameter();
291 ResolvedValueArgument resolvedArgument = candidateArgumentMap.get(candidateParameter);
292 JetType expectedType = resolvedArgument instanceof VarargValueArgument
293 ? candidateParameter.getVarargElementType()
294 : candidateParameter.getType();
295
296 valuesToPredicates.putValue(argumentValue, expectedType != null ? new AllSubtypes(expectedType) : AllTypes.INSTANCE$);
297 }
298 }
299
300 SmartFMap<PseudoValue, TypePredicate> result = SmartFMap.emptyMap();
301 for (Map.Entry<PseudoValue, Collection<TypePredicate>> entry : valuesToPredicates.entrySet()) {
302 result = result.plus(entry.getKey(), PseudocodePackage.or(entry.getValue()));
303 }
304
305 return result;
306 }
307
308 @NotNull
309 private PseudoValue createUnresolvedCallByValues(@NotNull JetElement to, @Nullable JetElement valueElement, List<PseudoValue> arguments) {
310 Map<PseudoValue, TypePredicate> typeMap = getTypeMapForUnresolvedCall(to, arguments);
311 if (typeMap == null) {
312 typeMap = defaultTypeMap(arguments);
313 }
314
315 return builder.magic(to, valueElement, arguments, typeMap, MagicKind.UNRESOLVED_CALL).getOutputValue();
316 }
317
318 @NotNull
319 private PseudoValue createUnresolvedCallByValues(@NotNull JetElement to, List<PseudoValue> arguments) {
320 return createUnresolvedCallByValues(to, to, arguments);
321 }
322
323 @NotNull
324 private PseudoValue createUnresolvedCall(@NotNull JetElement to, List<? extends JetElement> from) {
325 return createUnresolvedCallByValues(to, elementsToValues(from));
326 }
327
328 @NotNull
329 private PseudoValue createUnresolvedCall(@NotNull JetElement to, JetElement... from) {
330 return createUnresolvedCall(to, Arrays.asList(from));
331 }
332
333 @NotNull
334 private Map<PseudoValue, TypePredicate> defaultTypeMap(List<PseudoValue> values) {
335 return PseudocodePackage.expectedTypeFor(AllTypes.INSTANCE$, values);
336 }
337
338 private void mergeValues(@NotNull List<JetExpression> from, @NotNull JetExpression to) {
339 builder.merge(to, elementsToValues(from));
340 }
341
342 private void copyValue(@Nullable JetElement from, @NotNull JetElement to) {
343 PseudoValue value = getBoundOrUnreachableValue(from);
344 if (value != null) {
345 builder.bindValue(value, to);
346 }
347 }
348
349 @Nullable
350 private PseudoValue getBoundOrUnreachableValue(@Nullable JetElement element) {
351 if (element == null) return null;
352
353 PseudoValue value = builder.getBoundValue(element);
354 return value != null || element instanceof JetDeclaration ? value : builder.newValue(element);
355 }
356
357 private List<PseudoValue> elementsToValues(List<? extends JetElement> from) {
358 if (from.isEmpty()) return Collections.emptyList();
359 return KotlinPackage.filterNotNull(
360 KotlinPackage.map(
361 from,
362 new Function1<JetElement, PseudoValue>() {
363 @Override
364 public PseudoValue invoke(JetElement element) {
365 return getBoundOrUnreachableValue(element);
366 }
367 }
368 )
369 );
370 }
371
372 private void generateInitializer(@NotNull JetDeclaration declaration, @NotNull PseudoValue initValue) {
373 builder.write(
374 declaration,
375 declaration,
376 initValue,
377 getDeclarationAccessTarget(declaration),
378 Collections.<PseudoValue, ReceiverValue>emptyMap()
379 );
380 }
381
382 @NotNull
383 private AccessTarget getResolvedCallAccessTarget(JetElement element) {
384 ResolvedCall<?> resolvedCall = getResolvedCall(element, trace.getBindingContext());
385 return resolvedCall != null ? new AccessTarget.Call(resolvedCall) : AccessTarget.BlackBox.INSTANCE$;
386 }
387
388 @NotNull
389 private AccessTarget getDeclarationAccessTarget(JetElement element) {
390 DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
391 return descriptor instanceof VariableDescriptor
392 ? new AccessTarget.Declaration((VariableDescriptor) descriptor)
393 : AccessTarget.BlackBox.INSTANCE$;
394 }
395
396 @Override
397 public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
398 mark(expression);
399 JetExpression innerExpression = expression.getExpression();
400 if (innerExpression != null) {
401 generateInstructions(innerExpression);
402 copyValue(innerExpression, expression);
403 }
404 }
405
406 @Override
407 public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) {
408 JetExpression baseExpression = expression.getBaseExpression();
409 if (baseExpression != null) {
410 generateInstructions(baseExpression);
411 copyValue(baseExpression, expression);
412 }
413 }
414
415 @Override
416 public void visitThisExpression(@NotNull JetThisExpression expression) {
417 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext());
418 if (resolvedCall == null) {
419 createUnresolvedCall(expression);
420 return;
421 }
422
423 CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
424 if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
425 builder.readVariable(expression, resolvedCall, getReceiverValues(resolvedCall));
426 }
427
428 copyValue(expression, expression.getInstanceReference());
429 }
430
431 @Override
432 public void visitConstantExpression(@NotNull JetConstantExpression expression) {
433 CompileTimeConstant<?> constant = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext());
434 builder.loadConstant(expression, constant);
435 }
436
437 @Override
438 public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
439 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext());
440 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
441 VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
442 generateCall(variableAsFunctionResolvedCall.getVariableCall());
443 }
444 else if (!generateCall(expression) && !(expression.getParent() instanceof JetCallExpression)) {
445 createUnresolvedCall(expression, generateAndGetReceiverIfAny(expression));
446 }
447 }
448
449 @Override
450 public void visitLabeledExpression(@NotNull JetLabeledExpression expression) {
451 mark(expression);
452 JetExpression baseExpression = expression.getBaseExpression();
453 if (baseExpression != null) {
454 generateInstructions(baseExpression);
455 copyValue(baseExpression, expression);
456 }
457 }
458
459 @SuppressWarnings("SuspiciousMethodCalls")
460 @Override
461 public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
462 JetSimpleNameExpression operationReference = expression.getOperationReference();
463 IElementType operationType = operationReference.getReferencedNameElementType();
464
465 JetExpression left = expression.getLeft();
466 JetExpression right = expression.getRight();
467 if (operationType == ANDAND || operationType == OROR) {
468 generateBooleanOperation(expression);
469 }
470 else if (operationType == EQ) {
471 visitAssignment(left, getDeferredValue(right), expression);
472 }
473 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
474 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext());
475 if (resolvedCall != null) {
476 PseudoValue rhsValue = generateCall(resolvedCall).getOutputValue();
477 Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
478 if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) {
479 /* At this point assignment of the form a += b actually means a = a + b
480 * So we first generate call of "+" operation and then use its output pseudo-value
481 * as a right-hand side when generating assignment call
482 */
483 visitAssignment(left, getValueAsFunction(rhsValue), expression);
484 }
485 }
486 else {
487 generateBothArgumentsAndMark(expression);
488 }
489 }
490 else if (operationType == ELVIS) {
491 generateInstructions(left);
492 mark(expression);
493 Label afterElvis = builder.createUnboundLabel("after elvis operator");
494 builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left));
495 if (right != null) {
496 generateInstructions(right);
497 }
498 builder.bindLabel(afterElvis);
499 mergeValues(Arrays.asList(left, right), expression);
500 }
501 else {
502 if (!generateCall(expression)) {
503 generateBothArgumentsAndMark(expression);
504 }
505 }
506 }
507
508 private void generateBooleanOperation(JetBinaryExpression expression) {
509 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
510 JetExpression left = expression.getLeft();
511 JetExpression right = expression.getRight();
512
513 Label resultLabel = builder.createUnboundLabel("result of boolean operation");
514 generateInstructions(left);
515 if (operationType == ANDAND) {
516 builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left));
517 }
518 else {
519 builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left));
520 }
521 if (right != null) {
522 generateInstructions(right);
523 }
524 builder.bindLabel(resultLabel);
525 JetControlFlowBuilder.PredefinedOperation operation = operationType == ANDAND ? AND : OR;
526 builder.predefinedOperation(expression, operation, elementsToValues(Arrays.asList(left, right)));
527 }
528
529 private Function0<PseudoValue> getValueAsFunction(final PseudoValue value) {
530 return new Function0<PseudoValue>() {
531 @Override
532 public PseudoValue invoke() {
533 return value;
534 }
535 };
536 }
537
538 private Function0<PseudoValue> getDeferredValue(final JetExpression expression) {
539 return new Function0<PseudoValue>() {
540 @Override
541 public PseudoValue invoke() {
542 generateInstructions(expression);
543 return getBoundOrUnreachableValue(expression);
544 }
545 };
546 }
547
548 private void generateBothArgumentsAndMark(JetBinaryExpression expression) {
549 JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
550 if (left != null) {
551 generateInstructions(left);
552 }
553 JetExpression right = expression.getRight();
554 if (right != null) {
555 generateInstructions(right);
556 }
557 mark(expression);
558 createUnresolvedCall(expression, left, right);
559 }
560
561 private void visitAssignment(
562 JetExpression lhs,
563 @NotNull Function0<PseudoValue> rhsDeferredValue,
564 JetExpression parentExpression
565 ) {
566 JetExpression left = JetPsiUtil.deparenthesize(lhs);
567 if (left == null) {
568 List<PseudoValue> arguments = Collections.singletonList(rhsDeferredValue.invoke());
569 builder.magic(parentExpression, parentExpression, arguments, defaultTypeMap(arguments), MagicKind.UNSUPPORTED_ELEMENT);
570 return;
571 }
572
573 if (left instanceof JetArrayAccessExpression) {
574 generateArrayAssignment((JetArrayAccessExpression) left, rhsDeferredValue, parentExpression);
575 return;
576 }
577
578 Map<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
579 AccessTarget accessTarget = AccessTarget.BlackBox.INSTANCE$;
580 if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) {
581 accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left));
582 if (accessTarget instanceof AccessTarget.Call) {
583 receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall());
584 }
585 }
586 else if (left instanceof JetProperty) {
587 accessTarget = getDeclarationAccessTarget(left);
588 }
589
590 recordWrite(left, accessTarget, rhsDeferredValue.invoke(), receiverValues, parentExpression);
591 }
592
593 private void generateArrayAssignment(
594 JetArrayAccessExpression lhs,
595 @NotNull Function0<PseudoValue> rhsDeferredValue,
596 @NotNull JetExpression parentExpression
597 ) {
598 ResolvedCall<FunctionDescriptor> setResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_SET, lhs);
599
600 if (setResolvedCall == null) {
601 generateArrayAccess(lhs, null);
602
603 List<PseudoValue> arguments = KotlinPackage.filterNotNull(
604 Arrays.asList(getBoundOrUnreachableValue(lhs), rhsDeferredValue.invoke())
605 );
606 createUnresolvedCallByValues(parentExpression, arguments);
607
608 return;
609 }
610
611 // In case of simple ('=') array assignment mark instruction is not generated yet, so we put it before generating "set" call
612 if (((JetOperationExpression) parentExpression).getOperationReference().getReferencedNameElementType() == EQ) {
613 mark(lhs);
614 }
615
616 generateInstructions(lhs.getArrayExpression());
617
618 Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall);
619 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = getArraySetterArguments(rhsDeferredValue, setResolvedCall);
620
621 builder.call(parentExpression, setResolvedCall, receiverValues, argumentValues);
622 }
623
624 /* We assume that assignment right-hand side corresponds to the last argument of the call
625 * So receiver instructions/pseudo-values are generated for all arguments except the last one which is replaced
626 * by pre-generated pseudo-value
627 * For example, assignment a[1, 2] += 3 means a.set(1, 2, a.get(1) + 3), so in order to generate "set" call
628 * we first generate instructions for 1 and 2 whereas 3 is replaced by pseudo-value corresponding to "a.get(1) + 3"
629 */
630 private SmartFMap<PseudoValue, ValueParameterDescriptor> getArraySetterArguments(
631 Function0<PseudoValue> rhsDeferredValue,
632 final ResolvedCall<FunctionDescriptor> setResolvedCall
633 ) {
634 List<ValueArgument> valueArguments = KotlinPackage.flatMapTo(
635 setResolvedCall.getResultingDescriptor().getValueParameters(),
636 new ArrayList<ValueArgument>(),
637 new Function1<ValueParameterDescriptor, Iterable<? extends ValueArgument>>() {
638 @Override
639 public Iterable<? extends ValueArgument> invoke(ValueParameterDescriptor descriptor) {
640 ResolvedValueArgument resolvedValueArgument = setResolvedCall.getValueArguments().get(descriptor);
641 return resolvedValueArgument != null
642 ? resolvedValueArgument.getArguments()
643 : Collections.<ValueArgument>emptyList();
644 }
645 }
646 );
647
648 ValueArgument rhsArgument = KotlinPackage.lastOrNull(valueArguments);
649 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = SmartFMap.emptyMap();
650 for (ValueArgument valueArgument : valueArguments) {
651 ArgumentMapping argumentMapping = setResolvedCall.getArgumentMapping(valueArgument);
652 if (argumentMapping.isError() || (!(argumentMapping instanceof ArgumentMatch))) continue;
653
654 ValueParameterDescriptor parameterDescriptor = ((ArgumentMatch) argumentMapping).getValueParameter();
655 if (valueArgument != rhsArgument) {
656 argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues);
657 }
658 else {
659 PseudoValue rhsValue = rhsDeferredValue.invoke();
660 if (rhsValue != null) {
661 argumentValues = argumentValues.plus(rhsValue, parameterDescriptor);
662 }
663 }
664 }
665 return argumentValues;
666 }
667
668 private void recordWrite(
669 @NotNull JetExpression left,
670 @NotNull AccessTarget target,
671 @Nullable PseudoValue rightValue,
672 @NotNull Map<PseudoValue, ReceiverValue> receiverValues,
673 @NotNull JetExpression parentExpression
674 ) {
675 if (target == AccessTarget.BlackBox.INSTANCE$) {
676 List<PseudoValue> values = ContainerUtil.createMaybeSingletonList(rightValue);
677 builder.magic(parentExpression, parentExpression, values, defaultTypeMap(values), MagicKind.UNSUPPORTED_ELEMENT);
678 }
679 else {
680 PseudoValue rValue =
681 rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS);
682 builder.write(parentExpression, left, rValue, target, receiverValues);
683 }
684 }
685
686 private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) {
687 if (builder.getBoundValue(arrayAccessExpression) != null) return;
688 mark(arrayAccessExpression);
689 if (!checkAndGenerateCall(resolvedCall)) {
690 generateArrayAccessWithoutCall(arrayAccessExpression);
691 }
692 }
693
694 private void generateArrayAccessWithoutCall(JetArrayAccessExpression arrayAccessExpression) {
695 createUnresolvedCall(arrayAccessExpression, generateArrayAccessArguments(arrayAccessExpression));
696 }
697
698 private List<JetExpression> generateArrayAccessArguments(JetArrayAccessExpression arrayAccessExpression) {
699 List<JetExpression> inputExpressions = new ArrayList<JetExpression>();
700
701 JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
702 inputExpressions.add(arrayExpression);
703 generateInstructions(arrayExpression);
704
705 for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
706 generateInstructions(index);
707 inputExpressions.add(index);
708 }
709
710 return inputExpressions;
711 }
712
713 @Override
714 public void visitUnaryExpression(@NotNull JetUnaryExpression expression) {
715 JetSimpleNameExpression operationSign = expression.getOperationReference();
716 IElementType operationType = operationSign.getReferencedNameElementType();
717 JetExpression baseExpression = expression.getBaseExpression();
718 if (baseExpression == null) return;
719 if (JetTokens.EXCLEXCL == operationType) {
720 generateInstructions(baseExpression);
721 builder.predefinedOperation(expression, NOT_NULL_ASSERTION, elementsToValues(Collections.singletonList(baseExpression)));
722 return;
723 }
724
725 boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
726 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext());
727
728 PseudoValue rhsValue;
729 if (resolvedCall != null) {
730 rhsValue = generateCall(resolvedCall).getOutputValue();
731 }
732 else {
733 generateInstructions(baseExpression);
734 rhsValue = createUnresolvedCall(expression, baseExpression);
735 }
736
737 if (incrementOrDecrement) {
738 visitAssignment(baseExpression, getValueAsFunction(rhsValue), expression);
739 if (expression instanceof JetPostfixExpression) {
740 copyValue(baseExpression, expression);
741 }
742 }
743 }
744
745 private boolean isIncrementOrDecrement(IElementType operationType) {
746 return operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS;
747 }
748
749 @Override
750 public void visitIfExpression(@NotNull JetIfExpression expression) {
751 mark(expression);
752 List<JetExpression> branches = new ArrayList<JetExpression>(2);
753 JetExpression condition = expression.getCondition();
754 if (condition != null) {
755 generateInstructions(condition);
756 }
757 Label elseLabel = builder.createUnboundLabel("else branch");
758 builder.jumpOnFalse(elseLabel, expression, builder.getBoundValue(condition));
759 JetExpression thenBranch = expression.getThen();
760 if (thenBranch != null) {
761 branches.add(thenBranch);
762 generateInstructions(thenBranch);
763 }
764 else {
765 builder.loadUnit(expression);
766 }
767 Label resultLabel = builder.createUnboundLabel("'if' expression result");
768 builder.jump(resultLabel, expression);
769 builder.bindLabel(elseLabel);
770 JetExpression elseBranch = expression.getElse();
771 if (elseBranch != null) {
772 branches.add(elseBranch);
773 generateInstructions(elseBranch);
774 }
775 else {
776 builder.loadUnit(expression);
777 }
778 builder.bindLabel(resultLabel);
779 mergeValues(branches, expression);
780 }
781
782 private class FinallyBlockGenerator {
783 private final JetFinallySection finallyBlock;
784 private Label startFinally = null;
785 private Label finishFinally = null;
786
787 private FinallyBlockGenerator(JetFinallySection block) {
788 finallyBlock = block;
789 }
790
791 public void generate() {
792 JetBlockExpression finalExpression = finallyBlock.getFinalExpression();
793 if (finalExpression == null) return;
794 if (startFinally != null) {
795 assert finishFinally != null;
796 builder.repeatPseudocode(startFinally, finishFinally);
797 return;
798 }
799 startFinally = builder.createUnboundLabel("start finally");
800 builder.bindLabel(startFinally);
801 generateInstructions(finalExpression);
802 finishFinally = builder.createUnboundLabel("finish finally");
803 builder.bindLabel(finishFinally);
804 }
805 }
806
807 @Override
808 public void visitTryExpression(@NotNull JetTryExpression expression) {
809 mark(expression);
810
811 JetFinallySection finallyBlock = expression.getFinallyBlock();
812 final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
813 boolean hasFinally = finallyBlock != null;
814 if (hasFinally) {
815 builder.enterTryFinally(new GenerationTrigger() {
816 private boolean working = false;
817
818 @Override
819 public void generate() {
820 // This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
821 if (working) return;
822 working = true;
823 finallyBlockGenerator.generate();
824 working = false;
825 }
826 });
827 }
828
829 Label onExceptionToFinallyBlock = generateTryAndCatches(expression);
830
831 if (hasFinally) {
832 assert onExceptionToFinallyBlock != null : "No finally lable generated: " + expression.getText();
833
834 builder.exitTryFinally();
835
836 Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
837 builder.jump(skipFinallyToErrorBlock, expression);
838 builder.bindLabel(onExceptionToFinallyBlock);
839 finallyBlockGenerator.generate();
840 builder.jumpToError(expression);
841 builder.bindLabel(skipFinallyToErrorBlock);
842
843 finallyBlockGenerator.generate();
844 }
845
846 List<JetExpression> branches = new ArrayList<JetExpression>();
847 branches.add(expression.getTryBlock());
848 for (JetCatchClause catchClause : expression.getCatchClauses()) {
849 branches.add(catchClause.getCatchBody());
850 }
851 mergeValues(branches, expression);
852 }
853
854 // Returns label for 'finally' block
855 @Nullable
856 private Label generateTryAndCatches(@NotNull JetTryExpression expression) {
857 List<JetCatchClause> catchClauses = expression.getCatchClauses();
858 boolean hasCatches = !catchClauses.isEmpty();
859
860 Label onException = null;
861 if (hasCatches) {
862 onException = builder.createUnboundLabel("onException");
863 builder.nondeterministicJump(onException, expression, null);
864 }
865
866 Label onExceptionToFinallyBlock = null;
867 if (expression.getFinallyBlock() != null) {
868 onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock");
869 builder.nondeterministicJump(onExceptionToFinallyBlock, expression, null);
870 }
871
872 JetBlockExpression tryBlock = expression.getTryBlock();
873 generateInstructions(tryBlock);
874
875 if (hasCatches) {
876 Label afterCatches = builder.createUnboundLabel("afterCatches");
877 builder.jump(afterCatches, expression);
878
879 builder.bindLabel(onException);
880 LinkedList<Label> catchLabels = Lists.newLinkedList();
881 int catchClausesSize = catchClauses.size();
882 for (int i = 0; i < catchClausesSize - 1; i++) {
883 catchLabels.add(builder.createUnboundLabel("catch " + i));
884 }
885 if (!catchLabels.isEmpty()) {
886 builder.nondeterministicJump(catchLabels, expression);
887 }
888 boolean isFirst = true;
889 for (JetCatchClause catchClause : catchClauses) {
890 builder.enterLexicalScope(catchClause);
891 if (!isFirst) {
892 builder.bindLabel(catchLabels.remove());
893 }
894 else {
895 isFirst = false;
896 }
897 JetParameter catchParameter = catchClause.getCatchParameter();
898 if (catchParameter != null) {
899 builder.declareParameter(catchParameter);
900 generateInitializer(catchParameter, createSyntheticValue(catchParameter, MagicKind.FAKE_INITIALIZER));
901 }
902 JetExpression catchBody = catchClause.getCatchBody();
903 if (catchBody != null) {
904 generateInstructions(catchBody);
905 }
906 builder.jump(afterCatches, expression);
907 builder.exitLexicalScope(catchClause);
908 }
909
910 builder.bindLabel(afterCatches);
911 }
912
913 return onExceptionToFinallyBlock;
914 }
915
916 @Override
917 public void visitWhileExpression(@NotNull JetWhileExpression expression) {
918 LoopInfo loopInfo = builder.enterLoop(expression);
919
920 builder.bindLabel(loopInfo.getConditionEntryPoint());
921 JetExpression condition = expression.getCondition();
922 if (condition != null) {
923 generateInstructions(condition);
924 }
925 mark(expression);
926 boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
927 if (!conditionIsTrueConstant) {
928 builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition));
929 }
930 else {
931 assert condition != null : "Invalid while condition: " + expression.getText();
932 List<PseudoValue> values = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(condition));
933 Map<PseudoValue, TypePredicate> typePredicates =
934 PseudocodePackage.expectedTypeFor(new SingleType(KotlinBuiltIns.getInstance().getBooleanType()), values);
935 builder.magic(condition, null, values, typePredicates, MagicKind.VALUE_CONSUMER);
936 }
937
938 builder.enterLoopBody(expression);
939 JetExpression body = expression.getBody();
940 if (body != null) {
941 generateInstructions(body);
942 }
943 builder.jump(loopInfo.getEntryPoint(), expression);
944 builder.exitLoopBody(expression);
945 builder.bindLabel(loopInfo.getExitPoint());
946 builder.loadUnit(expression);
947 }
948
949 @Override
950 public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
951 builder.enterLexicalScope(expression);
952 mark(expression);
953 LoopInfo loopInfo = builder.enterLoop(expression);
954
955 builder.enterLoopBody(expression);
956 JetExpression body = expression.getBody();
957 if (body != null) {
958 generateInstructions(body);
959 }
960 builder.exitLoopBody(expression);
961 builder.bindLabel(loopInfo.getConditionEntryPoint());
962 JetExpression condition = expression.getCondition();
963 if (condition != null) {
964 generateInstructions(condition);
965 }
966 builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition));
967 builder.bindLabel(loopInfo.getExitPoint());
968 builder.loadUnit(expression);
969 builder.exitLexicalScope(expression);
970 }
971
972 @Override
973 public void visitForExpression(@NotNull JetForExpression expression) {
974 builder.enterLexicalScope(expression);
975
976 JetExpression loopRange = expression.getLoopRange();
977 if (loopRange != null) {
978 generateInstructions(loopRange);
979 }
980 declareLoopParameter(expression);
981
982 // TODO : primitive cases
983 LoopInfo loopInfo = builder.enterLoop(expression);
984
985 builder.bindLabel(loopInfo.getConditionEntryPoint());
986 builder.nondeterministicJump(loopInfo.getExitPoint(), expression, null);
987
988
989 writeLoopParameterAssignment(expression);
990
991 mark(expression);
992 builder.enterLoopBody(expression);
993 JetExpression body = expression.getBody();
994 if (body != null) {
995 generateInstructions(body);
996 }
997 builder.jump(loopInfo.getEntryPoint(), expression);
998
999 builder.exitLoopBody(expression);
1000 builder.bindLabel(loopInfo.getExitPoint());
1001 builder.loadUnit(expression);
1002 builder.exitLexicalScope(expression);
1003 }
1004
1005 private void declareLoopParameter(JetForExpression expression) {
1006 JetParameter loopParameter = expression.getLoopParameter();
1007 JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
1008 if (loopParameter != null) {
1009 builder.declareParameter(loopParameter);
1010 }
1011 else if (multiDeclaration != null) {
1012 visitMultiDeclaration(multiDeclaration, false);
1013 }
1014 }
1015
1016 private void writeLoopParameterAssignment(JetForExpression expression) {
1017 JetParameter loopParameter = expression.getLoopParameter();
1018 JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
1019 JetExpression loopRange = expression.getLoopRange();
1020
1021 TypePredicate loopRangeTypePredicate =
1022 getTypePredicateByReceiverValue(trace.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange));
1023
1024 PseudoValue loopRangeValue = builder.getBoundValue(loopRange);
1025 PseudoValue value = builder.magic(
1026 loopRange != null ? loopRange : expression,
1027 null,
1028 ContainerUtil.createMaybeSingletonList(loopRangeValue),
1029 loopRangeValue != null
1030 ? Collections.singletonMap(loopRangeValue, loopRangeTypePredicate)
1031 : Collections.<PseudoValue, TypePredicate>emptyMap(),
1032 MagicKind.LOOP_RANGE_ITERATION
1033 ).getOutputValue();
1034
1035 if (loopParameter != null) {
1036 generateInitializer(loopParameter, value);
1037 }
1038 else if (multiDeclaration != null) {
1039 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
1040 generateInitializer(entry, value);
1041 }
1042 }
1043 }
1044
1045 private ReceiverValue getExplicitReceiverValue(ResolvedCall<?> resolvedCall) {
1046 switch(resolvedCall.getExplicitReceiverKind()) {
1047 case DISPATCH_RECEIVER:
1048 return resolvedCall.getDispatchReceiver();
1049 case EXTENSION_RECEIVER:
1050 return resolvedCall.getExtensionReceiver();
1051 default:
1052 return ReceiverValue.NO_RECEIVER;
1053 }
1054 }
1055
1056 @Override
1057 public void visitBreakExpression(@NotNull JetBreakExpression expression) {
1058 JetElement loop = getCorrespondingLoop(expression);
1059 if (loop != null) {
1060 checkJumpDoesNotCrossFunctionBoundary(expression, loop);
1061 builder.jump(builder.getExitPoint(loop), expression);
1062 }
1063 }
1064
1065 @Override
1066 public void visitContinueExpression(@NotNull JetContinueExpression expression) {
1067 JetElement loop = getCorrespondingLoop(expression);
1068 if (loop != null) {
1069 checkJumpDoesNotCrossFunctionBoundary(expression, loop);
1070 builder.jump(builder.getConditionEntryPoint(loop), expression);
1071 }
1072 }
1073
1074 @Nullable
1075 private JetElement getCorrespondingLoop(JetExpressionWithLabel expression) {
1076 String labelName = expression.getLabelName();
1077 JetLoopExpression loop;
1078 if (labelName != null) {
1079 JetSimpleNameExpression targetLabel = expression.getTargetLabel();
1080 assert targetLabel != null;
1081 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel);
1082 if (labeledElement instanceof JetLoopExpression) {
1083 loop = (JetLoopExpression) labeledElement;
1084 }
1085 else {
1086 trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
1087 loop = null;
1088 }
1089 }
1090 else {
1091 loop = builder.getCurrentLoop();
1092 if (loop == null) {
1093 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression));
1094 } else {
1095 JetWhenExpression whenExpression = PsiTreeUtil.getParentOfType(expression, JetWhenExpression.class, true,
1096 JetLoopExpression.class);
1097 if (whenExpression != null) {
1098 trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression));
1099 }
1100 }
1101 }
1102 if (loop != null && loop.getBody() != null
1103 // the faster version of 'isAncestor' check:
1104 && !loop.getBody().getTextRange().contains(expression.getTextRange())) {
1105 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression));
1106 return null;
1107 }
1108 return loop;
1109 }
1110
1111 private void checkJumpDoesNotCrossFunctionBoundary(@NotNull JetExpressionWithLabel jumpExpression, @NotNull JetElement jumpTarget) {
1112 BindingContext bindingContext = trace.getBindingContext();
1113
1114 FunctionDescriptor labelExprEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpExpression);
1115 FunctionDescriptor labelTargetEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpTarget);
1116 if (labelExprEnclosingFunc != labelTargetEnclosingFunc) {
1117 trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression));
1118 }
1119 }
1120
1121 @Override
1122 public void visitReturnExpression(@NotNull JetReturnExpression expression) {
1123 JetExpression returnedExpression = expression.getReturnedExpression();
1124 if (returnedExpression != null) {
1125 generateInstructions(returnedExpression);
1126 }
1127 JetSimpleNameExpression labelElement = expression.getTargetLabel();
1128 JetElement subroutine;
1129 String labelName = expression.getLabelName();
1130 if (labelElement != null && labelName != null) {
1131 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, labelElement);
1132 if (labeledElement != null) {
1133 assert labeledElement instanceof JetElement;
1134 subroutine = (JetElement) labeledElement;
1135 }
1136 else {
1137 subroutine = null;
1138 }
1139 }
1140 else {
1141 subroutine = builder.getReturnSubroutine();
1142 // TODO : a context check
1143 }
1144
1145 if (subroutine instanceof JetFunction || subroutine instanceof JetPropertyAccessor) {
1146 PseudoValue returnValue = returnedExpression != null ? builder.getBoundValue(returnedExpression) : null;
1147 if (returnValue == null) {
1148 builder.returnNoValue(expression, subroutine);
1149 }
1150 else {
1151 builder.returnValue(expression, returnValue, subroutine);
1152 }
1153 }
1154 else {
1155 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression);
1156 }
1157 }
1158
1159 @Override
1160 public void visitParameter(@NotNull JetParameter parameter) {
1161 builder.declareParameter(parameter);
1162 JetExpression defaultValue = parameter.getDefaultValue();
1163 if (defaultValue != null) {
1164 Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName());
1165 builder.nondeterministicJump(skipDefaultValue, defaultValue, null);
1166 generateInstructions(defaultValue);
1167 builder.bindLabel(skipDefaultValue);
1168 }
1169 generateInitializer(parameter, computePseudoValueForParameter(parameter));
1170 }
1171
1172 @NotNull
1173 private PseudoValue computePseudoValueForParameter(@NotNull JetParameter parameter) {
1174 PseudoValue syntheticValue = createSyntheticValue(parameter, MagicKind.FAKE_INITIALIZER);
1175 PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue());
1176 if (defaultValue == null) {
1177 return syntheticValue;
1178 }
1179 return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue();
1180 }
1181
1182 @Override
1183 public void visitBlockExpression(@NotNull JetBlockExpression expression) {
1184 boolean declareLexicalScope = !isBlockInDoWhile(expression);
1185 if (declareLexicalScope) {
1186 builder.enterLexicalScope(expression);
1187 }
1188 mark(expression);
1189 List<JetElement> statements = expression.getStatements();
1190 for (JetElement statement : statements) {
1191 generateInstructions(statement);
1192 }
1193 if (statements.isEmpty()) {
1194 builder.loadUnit(expression);
1195 }
1196 else {
1197 copyValue(KotlinPackage.lastOrNull(statements), expression);
1198 }
1199 if (declareLexicalScope) {
1200 builder.exitLexicalScope(expression);
1201 }
1202 }
1203
1204 private boolean isBlockInDoWhile(@NotNull JetBlockExpression expression) {
1205 PsiElement parent = expression.getParent();
1206 if (parent == null) return false;
1207 return parent.getParent() instanceof JetDoWhileExpression;
1208 }
1209
1210 private void visitFunction(@NotNull JetFunction function) {
1211 processLocalDeclaration(function);
1212 boolean isAnonymousFunction = function instanceof JetFunctionLiteral || function.getName() == null;
1213 if (isAnonymousFunction || (function.isLocal() && !(function.getParent() instanceof JetBlockExpression))) {
1214 builder.createLambda(function);
1215 }
1216 }
1217
1218 @Override
1219 public void visitNamedFunction(@NotNull JetNamedFunction function) {
1220 visitFunction(function);
1221 }
1222
1223 @Override
1224 public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
1225 mark(expression);
1226 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
1227 visitFunction(functionLiteral);
1228 copyValue(functionLiteral, expression);
1229 }
1230
1231 @Override
1232 public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
1233 mark(expression);
1234 JetExpression selectorExpression = expression.getSelectorExpression();
1235 JetExpression receiverExpression = expression.getReceiverExpression();
1236
1237 // todo: replace with selectorExpresion != null after parser is fixed
1238 if (selectorExpression instanceof JetCallExpression || selectorExpression instanceof JetSimpleNameExpression) {
1239 generateInstructions(selectorExpression);
1240 copyValue(selectorExpression, expression);
1241 }
1242 else {
1243 generateInstructions(receiverExpression);
1244 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression);
1245 }
1246 }
1247
1248 @Override
1249 public void visitCallExpression(@NotNull JetCallExpression expression) {
1250 if (!generateCall(expression)) {
1251 List<JetExpression> inputExpressions = new ArrayList<JetExpression>();
1252 for (ValueArgument argument : expression.getValueArguments()) {
1253 JetExpression argumentExpression = argument.getArgumentExpression();
1254 if (argumentExpression != null) {
1255 generateInstructions(argumentExpression);
1256 inputExpressions.add(argumentExpression);
1257 }
1258 }
1259 JetExpression calleeExpression = expression.getCalleeExpression();
1260 generateInstructions(calleeExpression);
1261 inputExpressions.add(calleeExpression);
1262 inputExpressions.add(generateAndGetReceiverIfAny(expression));
1263
1264 mark(expression);
1265 createUnresolvedCall(expression, inputExpressions);
1266 }
1267 }
1268
1269 @Nullable
1270 private JetExpression generateAndGetReceiverIfAny(JetExpression expression) {
1271 PsiElement parent = expression.getParent();
1272 if (!(parent instanceof JetQualifiedExpression)) return null;
1273
1274 JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
1275 if (qualifiedExpression.getSelectorExpression() != expression) return null;
1276
1277 JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
1278 generateInstructions(receiverExpression);
1279
1280 return receiverExpression;
1281 }
1282
1283 @Override
1284 public void visitProperty(@NotNull JetProperty property) {
1285 builder.declareVariable(property);
1286 JetExpression initializer = property.getInitializer();
1287 if (initializer != null) {
1288 visitAssignment(property, getDeferredValue(initializer), property);
1289 }
1290 JetExpression delegate = property.getDelegateExpression();
1291 if (delegate != null) {
1292 generateInstructions(delegate);
1293 generateDelegateConsumer(property, delegate);
1294 }
1295
1296 if (JetPsiUtil.isLocal(property)) {
1297 for (JetPropertyAccessor accessor : property.getAccessors()) {
1298 generateInstructions(accessor);
1299 }
1300 }
1301 }
1302
1303 private void generateDelegateConsumer(@NotNull JetProperty property, @NotNull JetExpression delegate) {
1304 DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
1305 if (!(descriptor instanceof PropertyDescriptor)) return;
1306
1307 PseudoValue delegateValue = builder.getBoundValue(delegate);
1308 if (delegateValue == null) return;
1309
1310 List<TypePredicate> typePredicates = KotlinPackage.map(
1311 ((PropertyDescriptor) descriptor).getAccessors(),
1312 new Function1<PropertyAccessorDescriptor, TypePredicate>() {
1313 @Override
1314 public TypePredicate invoke(PropertyAccessorDescriptor descriptor) {
1315 return getTypePredicateByReceiverValue(trace.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, descriptor));
1316 }
1317 }
1318 );
1319 Map<PseudoValue, TypePredicate> valuesToTypePredicates = SmartFMap
1320 .<PseudoValue, TypePredicate>emptyMap()
1321 .plus(delegateValue, PseudocodePackage.and(KotlinPackage.filterNotNull(typePredicates)));
1322 builder.magic(property, null, Collections.singletonList(delegateValue), valuesToTypePredicates, MagicKind.VALUE_CONSUMER);
1323 }
1324
1325 private TypePredicate getTypePredicateByReceiverValue(@Nullable ResolvedCall<?> resolvedCall) {
1326 if (resolvedCall == null) return AllTypes.INSTANCE$;
1327
1328 ReceiverValue receiverValue = getExplicitReceiverValue(resolvedCall);
1329 if (receiverValue.exists()) {
1330 return PseudocodePackage.getReceiverTypePredicate(resolvedCall, receiverValue);
1331 }
1332
1333 return AllTypes.INSTANCE$;
1334 }
1335
1336 @Override
1337 public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) {
1338 visitMultiDeclaration(declaration, true);
1339 }
1340
1341 private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) {
1342 JetExpression initializer = declaration.getInitializer();
1343 generateInstructions(initializer);
1344 for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
1345 builder.declareVariable(entry);
1346
1347 ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
1348
1349 PseudoValue writtenValue;
1350 if (resolvedCall != null) {
1351 writtenValue = builder.call(
1352 entry,
1353 resolvedCall,
1354 getReceiverValues(resolvedCall),
1355 Collections.<PseudoValue, ValueParameterDescriptor>emptyMap()
1356 ).getOutputValue();
1357 }
1358 else {
1359 List<PseudoValue> arguments = ContainerUtil.createMaybeSingletonList(getBoundOrUnreachableValue(initializer));
1360 writtenValue = createUnresolvedCallByValues(entry, null, arguments);
1361 }
1362
1363 if (generateWriteForEntries) {
1364 generateInitializer(entry, writtenValue != null ? writtenValue : createSyntheticValue(entry, MagicKind.FAKE_INITIALIZER));
1365 }
1366 }
1367 }
1368
1369 @Override
1370 public void visitPropertyAccessor(@NotNull JetPropertyAccessor accessor) {
1371 processLocalDeclaration(accessor);
1372 }
1373
1374 @Override
1375 public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) {
1376 mark(expression);
1377
1378 IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
1379 JetExpression left = expression.getLeft();
1380 if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
1381 generateInstructions(left);
1382 if (getBoundOrUnreachableValue(left) != null) {
1383 createNonSyntheticValue(expression, MagicKind.CAST, left);
1384 }
1385 }
1386 else {
1387 visitJetElement(expression);
1388 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left);
1389 }
1390 }
1391
1392 @Override
1393 public void visitThrowExpression(@NotNull JetThrowExpression expression) {
1394 mark(expression);
1395
1396 JetExpression thrownExpression = expression.getThrownExpression();
1397 if (thrownExpression == null) return;
1398
1399 generateInstructions(thrownExpression);
1400
1401 PseudoValue thrownValue = builder.getBoundValue(thrownExpression);
1402 if (thrownValue == null) return;
1403
1404 builder.throwException(expression, thrownValue);
1405 }
1406
1407 @Override
1408 public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
1409 generateArrayAccess(expression, trace.get(BindingContext.INDEXED_LVALUE_GET, expression));
1410 }
1411
1412 @Override
1413 public void visitIsExpression(@NotNull JetIsExpression expression) {
1414 mark(expression);
1415 JetExpression left = expression.getLeftHandSide();
1416 generateInstructions(left);
1417 createNonSyntheticValue(expression, MagicKind.IS, left);
1418 }
1419
1420 @Override
1421 public void visitWhenExpression(@NotNull JetWhenExpression expression) {
1422 mark(expression);
1423
1424 JetExpression subjectExpression = expression.getSubjectExpression();
1425 if (subjectExpression != null) {
1426 generateInstructions(subjectExpression);
1427 }
1428
1429 List<JetExpression> branches = new ArrayList<JetExpression>();
1430
1431 Label doneLabel = builder.createUnboundLabel("after 'when' expression");
1432
1433 Label nextLabel = null;
1434 for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
1435 JetWhenEntry whenEntry = iterator.next();
1436 mark(whenEntry);
1437
1438 boolean isElse = whenEntry.isElse();
1439 if (isElse) {
1440 if (iterator.hasNext()) {
1441 trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry));
1442 }
1443 }
1444 Label bodyLabel = builder.createUnboundLabel("'when' entry body");
1445
1446 JetWhenCondition[] conditions = whenEntry.getConditions();
1447 for (int i = 0; i < conditions.length; i++) {
1448 JetWhenCondition condition = conditions[i];
1449 condition.accept(conditionVisitor);
1450 if (i + 1 < conditions.length) {
1451 builder.nondeterministicJump(bodyLabel, expression, builder.getBoundValue(condition));
1452 }
1453 }
1454
1455 if (!isElse) {
1456 nextLabel = builder.createUnboundLabel("next 'when' entry");
1457 JetWhenCondition lastCondition = KotlinPackage.lastOrNull(conditions);
1458 builder.nondeterministicJump(nextLabel, expression, builder.getBoundValue(lastCondition));
1459 }
1460
1461 builder.bindLabel(bodyLabel);
1462 JetExpression whenEntryExpression = whenEntry.getExpression();
1463 if (whenEntryExpression != null) {
1464 generateInstructions(whenEntryExpression);
1465 branches.add(whenEntryExpression);
1466 }
1467 builder.jump(doneLabel, expression);
1468
1469 if (!isElse) {
1470 builder.bindLabel(nextLabel);
1471 // For the last entry of exhaustive when,
1472 // attempt to jump further should lead to error, not to "done"
1473 if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) {
1474 builder.jumpToError(expression);
1475 }
1476 }
1477 }
1478 builder.bindLabel(doneLabel);
1479
1480 mergeValues(branches, expression);
1481 }
1482
1483 @Override
1484 public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) {
1485 mark(expression);
1486 JetObjectDeclaration declaration = expression.getObjectDeclaration();
1487 generateInstructions(declaration);
1488
1489 builder.createAnonymousObject(expression);
1490 }
1491
1492 @Override
1493 public void visitObjectDeclaration(@NotNull JetObjectDeclaration objectDeclaration) {
1494 generateHeaderDelegationSpecifiers(objectDeclaration);
1495 generateClassOrObjectInitializers(objectDeclaration);
1496 generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration);
1497 }
1498
1499 @Override
1500 public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) {
1501 mark(expression);
1502
1503 List<JetExpression> inputExpressions = new ArrayList<JetExpression>();
1504 for (JetStringTemplateEntry entry : expression.getEntries()) {
1505 if (entry instanceof JetStringTemplateEntryWithExpression) {
1506 JetExpression entryExpression = entry.getExpression();
1507 generateInstructions(entryExpression);
1508 inputExpressions.add(entryExpression);
1509 }
1510 }
1511 builder.loadStringTemplate(expression, elementsToValues(inputExpressions));
1512 }
1513
1514 @Override
1515 public void visitTypeProjection(@NotNull JetTypeProjection typeProjection) {
1516 // TODO : Support Type Arguments. Companion object may be initialized at this point");
1517 }
1518
1519 @Override
1520 public void visitAnonymousInitializer(@NotNull JetClassInitializer classInitializer) {
1521 generateInstructions(classInitializer.getBody());
1522 }
1523
1524 private void generateHeaderDelegationSpecifiers(@NotNull JetClassOrObject classOrObject) {
1525 for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) {
1526 generateInstructions(specifier);
1527 }
1528 }
1529
1530 private void generateClassOrObjectInitializers(@NotNull JetClassOrObject classOrObject) {
1531 for (JetDeclaration declaration : classOrObject.getDeclarations()) {
1532 if (declaration instanceof JetProperty || declaration instanceof JetClassInitializer) {
1533 generateInstructions(declaration);
1534 }
1535 }
1536 }
1537
1538 @Override
1539 public void visitClass(@NotNull JetClass klass) {
1540 if (klass.hasPrimaryConstructor()) {
1541 processParameters(klass.getPrimaryConstructorParameters());
1542
1543 // delegation specifiers of primary constructor, anonymous class and property initializers
1544 generateHeaderDelegationSpecifiers(klass);
1545 generateClassOrObjectInitializers(klass);
1546 }
1547
1548 generateDeclarationForLocalClassOrObjectIfNeeded(klass);
1549 }
1550
1551 private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull JetClassOrObject classOrObject) {
1552 if (classOrObject.isLocal()) {
1553 for (JetDeclaration declaration : classOrObject.getDeclarations()) {
1554 if (declaration instanceof JetSecondaryConstructor ||
1555 declaration instanceof JetProperty ||
1556 declaration instanceof JetClassInitializer) {
1557 continue;
1558 }
1559 generateInstructions(declaration);
1560 }
1561 }
1562 }
1563
1564 private void processParameters(@NotNull List<JetParameter> parameters) {
1565 for (JetParameter parameter : parameters) {
1566 generateInstructions(parameter);
1567 }
1568 }
1569
1570 @Override
1571 public void visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor) {
1572 JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(constructor, JetClassOrObject.class);
1573 assert classOrObject != null : "Guaranteed by parsing contract";
1574
1575 processParameters(constructor.getValueParameters());
1576 generateCallOrMarkUnresolved(constructor.getDelegationCall());
1577
1578 if (!constructor.getDelegationCall().isCallToThis()) {
1579 generateClassOrObjectInitializers(classOrObject);
1580 }
1581
1582 generateInstructions(constructor.getBodyExpression());
1583 }
1584
1585 @Override
1586 public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
1587 generateCallOrMarkUnresolved(call);
1588 }
1589
1590 private void generateCallOrMarkUnresolved(@Nullable JetCallElement call) {
1591 if (call == null) return;
1592 if (!generateCall(call)) {
1593 List<JetExpression> arguments = KotlinPackage.map(
1594 call.getValueArguments(),
1595 new Function1<ValueArgument, JetExpression>() {
1596 @Override
1597 public JetExpression invoke(ValueArgument valueArgument) {
1598 return valueArgument.getArgumentExpression();
1599 }
1600 }
1601 );
1602
1603 for (JetExpression argument : arguments) {
1604 generateInstructions(argument);
1605 }
1606 createUnresolvedCall(call, arguments);
1607 }
1608 }
1609
1610 @Override
1611 public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) {
1612 generateInstructions(specifier.getDelegateExpression());
1613
1614 List<PseudoValue> arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression()));
1615 JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference());
1616 TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$;
1617 builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments),
1618 MagicKind.VALUE_CONSUMER);
1619 }
1620
1621 @Override
1622 public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) {
1623 // Do not generate UNSUPPORTED_ELEMENT here
1624 }
1625
1626 @Override
1627 public void visitDelegationSpecifierList(@NotNull JetDelegationSpecifierList list) {
1628 list.acceptChildren(this);
1629 }
1630
1631 @Override
1632 public void visitJetFile(@NotNull JetFile file) {
1633 for (JetDeclaration declaration : file.getDeclarations()) {
1634 if (declaration instanceof JetProperty) {
1635 generateInstructions(declaration);
1636 }
1637 }
1638 }
1639
1640 @Override
1641 public void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression) {
1642 mark(expression);
1643 createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE);
1644 }
1645
1646 @Override
1647 public void visitJetElement(@NotNull JetElement element) {
1648 createNonSyntheticValue(element, MagicKind.UNSUPPORTED_ELEMENT);
1649 }
1650
1651 private boolean generateCall(@Nullable JetElement callElement) {
1652 if (callElement == null) return false;
1653 return checkAndGenerateCall(getResolvedCall(callElement, trace.getBindingContext()));
1654 }
1655
1656 private boolean checkAndGenerateCall(@Nullable ResolvedCall<?> resolvedCall) {
1657 if (resolvedCall == null) return false;
1658 generateCall(resolvedCall);
1659 return true;
1660 }
1661
1662 @NotNull
1663 private InstructionWithValue generateCall(@NotNull ResolvedCall<?> resolvedCall) {
1664 JetElement callElement = resolvedCall.getCall().getCallElement();
1665
1666 Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall);
1667
1668 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap();
1669 for (ValueArgument argument : resolvedCall.getCall().getValueArguments()) {
1670 ArgumentMapping argumentMapping = resolvedCall.getArgumentMapping(argument);
1671 JetExpression argumentExpression = argument.getArgumentExpression();
1672 if (argumentMapping instanceof ArgumentMatch) {
1673 parameterValues = generateValueArgument(argument, ((ArgumentMatch) argumentMapping).getValueParameter(), parameterValues);
1674 }
1675 else if (argumentExpression != null) {
1676 generateInstructions(argumentExpression);
1677 createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression);
1678 }
1679 }
1680
1681 if (resolvedCall.getResultingDescriptor() instanceof VariableDescriptor) {
1682 // If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated.
1683 // todo : process arguments for such a case (KT-5387)
1684 JetExpression callExpression = callElement instanceof JetExpression ? (JetExpression) callElement : null;
1685 assert callExpression != null
1686 : "Variable-based call without callee expression: " + callElement.getText();
1687 assert parameterValues.isEmpty()
1688 : "Variable-based call with non-empty argument list: " + callElement.getText();
1689 return builder.readVariable(callExpression, resolvedCall, receivers);
1690 }
1691
1692 mark(resolvedCall.getCall().getCallElement());
1693 return builder.call(callElement, resolvedCall, receivers, parameterValues);
1694 }
1695
1696 @NotNull
1697 private Map<PseudoValue, ReceiverValue> getReceiverValues(ResolvedCall<?> resolvedCall) {
1698 PseudoValue varCallResult = null;
1699 ReceiverValue explicitReceiver = ReceiverValue.NO_RECEIVER;
1700 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
1701 varCallResult = generateCall(((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall()).getOutputValue();
1702
1703 ExplicitReceiverKind kind = resolvedCall.getExplicitReceiverKind();
1704 //noinspection EnumSwitchStatementWhichMissesCases
1705 switch (kind) {
1706 case DISPATCH_RECEIVER:
1707 explicitReceiver = resolvedCall.getDispatchReceiver();
1708 break;
1709 case EXTENSION_RECEIVER:
1710 case BOTH_RECEIVERS:
1711 explicitReceiver = resolvedCall.getExtensionReceiver();
1712 break;
1713 }
1714 }
1715
1716 SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
1717 if (explicitReceiver.exists() && varCallResult != null) {
1718 receiverValues = receiverValues.plus(varCallResult, explicitReceiver);
1719 }
1720 JetElement callElement = resolvedCall.getCall().getCallElement();
1721 receiverValues = getReceiverValues(callElement, resolvedCall.getDispatchReceiver(), receiverValues);
1722 receiverValues = getReceiverValues(callElement, resolvedCall.getExtensionReceiver(), receiverValues);
1723 return receiverValues;
1724 }
1725
1726 @NotNull
1727 private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues(
1728 JetElement callElement,
1729 ReceiverValue receiver,
1730 SmartFMap<PseudoValue, ReceiverValue> receiverValues
1731 ) {
1732 if (!receiver.exists() || receiverValues.containsValue(receiver)) return receiverValues;
1733
1734 if (receiver instanceof ThisReceiver) {
1735 receiverValues = receiverValues.plus(createSyntheticValue(callElement, MagicKind.IMPLICIT_RECEIVER), receiver);
1736 }
1737 else if (receiver instanceof ExpressionReceiver) {
1738 JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
1739 if (builder.getBoundValue(expression) == null) {
1740 generateInstructions(expression);
1741 }
1742
1743 PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression);
1744 if (receiverPseudoValue != null) {
1745 receiverValues = receiverValues.plus(receiverPseudoValue, receiver);
1746 }
1747 }
1748 else if (receiver instanceof TransientReceiver) {
1749 // Do nothing
1750 }
1751 else {
1752 throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
1753 }
1754
1755 return receiverValues;
1756 }
1757
1758 @NotNull
1759 private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument(
1760 ValueArgument valueArgument,
1761 ValueParameterDescriptor parameterDescriptor,
1762 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues) {
1763 JetExpression expression = valueArgument.getArgumentExpression();
1764 if (expression != null) {
1765 if (!valueArgument.isExternal()) {
1766 generateInstructions(expression);
1767 }
1768
1769 PseudoValue argValue = getBoundOrUnreachableValue(expression);
1770 if (argValue != null) {
1771 parameterValues = parameterValues.plus(argValue, parameterDescriptor);
1772 }
1773 }
1774 return parameterValues;
1775 }
1776 }
1777 }