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 }