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