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.collections.ArraysKt; 026 import kotlin.collections.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.ControlFlowInstructionsGenerator; 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.KtPsiUtilKt; 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.ImplicitReceiver; 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.ControlFlowBuilder.PredefinedOperation.*; 065 import static org.jetbrains.kotlin.diagnostics.Errors.*; 066 import static org.jetbrains.kotlin.lexer.KtTokens.*; 067 068 public class ControlFlowProcessor { 069 070 private final ControlFlowBuilder builder; 071 private final BindingTrace trace; 072 073 public ControlFlowProcessor(BindingTrace trace) { 074 this.builder = new ControlFlowInstructionsGenerator(); 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 ControlFlowBuilder 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 visitKtElement(@NotNull KtElement element) { 173 throw new UnsupportedOperationException("[ControlFlowProcessor] " + element.toString()); 174 } 175 }; 176 177 private CFPVisitor(@NotNull ControlFlowBuilder 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 ControlFlowBuilder.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(KtPsiUtilKt.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 if (!CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace.getBindingContext(), true)) { 806 builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition)); 807 } 808 else { 809 assert condition != null : "Invalid while condition: " + expression.getText(); 810 createSyntheticValue(condition, MagicKind.VALUE_CONSUMER, condition); 811 } 812 813 builder.enterLoopBody(expression); 814 KtExpression body = expression.getBody(); 815 if (body != null) { 816 generateInstructions(body); 817 } 818 builder.jump(loopInfo.getEntryPoint(), expression); 819 builder.exitLoopBody(expression); 820 builder.bindLabel(loopInfo.getExitPoint()); 821 builder.loadUnit(expression); 822 } 823 824 @Override 825 public void visitDoWhileExpression(@NotNull KtDoWhileExpression expression) { 826 builder.enterLexicalScope(expression); 827 mark(expression); 828 LoopInfo loopInfo = builder.enterLoop(expression); 829 830 builder.enterLoopBody(expression); 831 KtExpression body = expression.getBody(); 832 if (body != null) { 833 generateInstructions(body); 834 } 835 builder.exitLoopBody(expression); 836 builder.bindLabel(loopInfo.getConditionEntryPoint()); 837 KtExpression condition = expression.getCondition(); 838 if (condition != null) { 839 generateInstructions(condition); 840 } 841 builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition)); 842 builder.bindLabel(loopInfo.getExitPoint()); 843 builder.loadUnit(expression); 844 builder.exitLexicalScope(expression); 845 } 846 847 @Override 848 public void visitForExpression(@NotNull KtForExpression expression) { 849 builder.enterLexicalScope(expression); 850 851 KtExpression loopRange = expression.getLoopRange(); 852 if (loopRange != null) { 853 generateInstructions(loopRange); 854 } 855 declareLoopParameter(expression); 856 857 // TODO : primitive cases 858 LoopInfo loopInfo = builder.enterLoop(expression); 859 860 builder.bindLabel(loopInfo.getConditionEntryPoint()); 861 builder.nondeterministicJump(loopInfo.getExitPoint(), expression, null); 862 863 864 writeLoopParameterAssignment(expression); 865 866 mark(expression); 867 builder.enterLoopBody(expression); 868 KtExpression body = expression.getBody(); 869 if (body != null) { 870 generateInstructions(body); 871 } 872 builder.jump(loopInfo.getEntryPoint(), expression); 873 874 builder.exitLoopBody(expression); 875 builder.bindLabel(loopInfo.getExitPoint()); 876 builder.loadUnit(expression); 877 builder.exitLexicalScope(expression); 878 } 879 880 private void declareLoopParameter(KtForExpression expression) { 881 KtParameter loopParameter = expression.getLoopParameter(); 882 KtDestructuringDeclaration multiDeclaration = expression.getDestructuringParameter(); 883 if (loopParameter != null) { 884 builder.declareParameter(loopParameter); 885 } 886 else if (multiDeclaration != null) { 887 visitDestructuringDeclaration(multiDeclaration, false); 888 } 889 } 890 891 private void writeLoopParameterAssignment(KtForExpression expression) { 892 KtParameter loopParameter = expression.getLoopParameter(); 893 KtDestructuringDeclaration multiDeclaration = expression.getDestructuringParameter(); 894 KtExpression loopRange = expression.getLoopRange(); 895 896 PseudoValue value = builder.magic( 897 loopRange != null ? loopRange : expression, 898 null, 899 ContainerUtil.createMaybeSingletonList(builder.getBoundValue(loopRange)), 900 MagicKind.LOOP_RANGE_ITERATION 901 ).getOutputValue(); 902 903 if (loopParameter != null) { 904 generateInitializer(loopParameter, value); 905 } 906 else if (multiDeclaration != null) { 907 for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) { 908 generateInitializer(entry, value); 909 } 910 } 911 } 912 913 @Override 914 public void visitBreakExpression(@NotNull KtBreakExpression expression) { 915 KtElement loop = getCorrespondingLoop(expression); 916 if (loop != null) { 917 checkJumpDoesNotCrossFunctionBoundary(expression, loop); 918 builder.jump(builder.getExitPoint(loop), expression); 919 } 920 } 921 922 @Override 923 public void visitContinueExpression(@NotNull KtContinueExpression expression) { 924 KtElement loop = getCorrespondingLoop(expression); 925 if (loop != null) { 926 checkJumpDoesNotCrossFunctionBoundary(expression, loop); 927 builder.jump(builder.getConditionEntryPoint(loop), expression); 928 } 929 } 930 931 @Nullable 932 private KtElement getCorrespondingLoop(KtExpressionWithLabel expression) { 933 String labelName = expression.getLabelName(); 934 KtLoopExpression loop; 935 if (labelName != null) { 936 KtSimpleNameExpression targetLabel = expression.getTargetLabel(); 937 assert targetLabel != null; 938 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel); 939 if (labeledElement instanceof KtLoopExpression) { 940 loop = (KtLoopExpression) labeledElement; 941 } 942 else { 943 trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); 944 loop = null; 945 } 946 } 947 else { 948 loop = builder.getCurrentLoop(); 949 if (loop == null) { 950 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); 951 } else { 952 KtWhenExpression whenExpression = PsiTreeUtil.getParentOfType(expression, KtWhenExpression.class, true, 953 KtLoopExpression.class); 954 if (whenExpression != null) { 955 trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression)); 956 } 957 } 958 } 959 if (loop != null && loop.getBody() != null 960 // the faster version of 'isAncestor' check: 961 && !loop.getBody().getTextRange().contains(expression.getTextRange())) { 962 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); 963 return null; 964 } 965 return loop; 966 } 967 968 private void checkJumpDoesNotCrossFunctionBoundary(@NotNull KtExpressionWithLabel jumpExpression, @NotNull KtElement jumpTarget) { 969 BindingContext bindingContext = trace.getBindingContext(); 970 971 FunctionDescriptor labelExprEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpExpression); 972 FunctionDescriptor labelTargetEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpTarget); 973 if (labelExprEnclosingFunc != labelTargetEnclosingFunc) { 974 trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression)); 975 } 976 } 977 978 @Override 979 public void visitReturnExpression(@NotNull KtReturnExpression expression) { 980 KtExpression returnedExpression = expression.getReturnedExpression(); 981 if (returnedExpression != null) { 982 generateInstructions(returnedExpression); 983 } 984 KtSimpleNameExpression labelElement = expression.getTargetLabel(); 985 KtElement subroutine; 986 String labelName = expression.getLabelName(); 987 if (labelElement != null && labelName != null) { 988 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, labelElement); 989 if (labeledElement != null) { 990 assert labeledElement instanceof KtElement; 991 subroutine = (KtElement) labeledElement; 992 } 993 else { 994 subroutine = null; 995 } 996 } 997 else { 998 subroutine = builder.getReturnSubroutine(); 999 // TODO : a context check 1000 } 1001 1002 if (subroutine instanceof KtFunction || subroutine instanceof KtPropertyAccessor) { 1003 PseudoValue returnValue = returnedExpression != null ? builder.getBoundValue(returnedExpression) : null; 1004 if (returnValue == null) { 1005 builder.returnNoValue(expression, subroutine); 1006 } 1007 else { 1008 builder.returnValue(expression, returnValue, subroutine); 1009 } 1010 } 1011 else { 1012 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression); 1013 } 1014 } 1015 1016 @Override 1017 public void visitParameter(@NotNull KtParameter parameter) { 1018 builder.declareParameter(parameter); 1019 KtExpression defaultValue = parameter.getDefaultValue(); 1020 if (defaultValue != null) { 1021 Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName()); 1022 builder.nondeterministicJump(skipDefaultValue, defaultValue, null); 1023 generateInstructions(defaultValue); 1024 builder.bindLabel(skipDefaultValue); 1025 } 1026 generateInitializer(parameter, computePseudoValueForParameter(parameter)); 1027 } 1028 1029 @NotNull 1030 private PseudoValue computePseudoValueForParameter(@NotNull KtParameter parameter) { 1031 PseudoValue syntheticValue = createSyntheticValue(parameter, MagicKind.FAKE_INITIALIZER); 1032 PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue()); 1033 if (defaultValue == null) { 1034 return syntheticValue; 1035 } 1036 return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue(); 1037 } 1038 1039 @Override 1040 public void visitBlockExpression(@NotNull KtBlockExpression expression) { 1041 boolean declareLexicalScope = !isBlockInDoWhile(expression); 1042 if (declareLexicalScope) { 1043 builder.enterLexicalScope(expression); 1044 } 1045 mark(expression); 1046 List<KtExpression> statements = expression.getStatements(); 1047 for (KtExpression statement : statements) { 1048 generateInstructions(statement); 1049 } 1050 if (statements.isEmpty()) { 1051 builder.loadUnit(expression); 1052 } 1053 else { 1054 copyValue(CollectionsKt.lastOrNull(statements), expression); 1055 } 1056 if (declareLexicalScope) { 1057 builder.exitLexicalScope(expression); 1058 } 1059 } 1060 1061 private boolean isBlockInDoWhile(@NotNull KtBlockExpression expression) { 1062 PsiElement parent = expression.getParent(); 1063 if (parent == null) return false; 1064 return parent.getParent() instanceof KtDoWhileExpression; 1065 } 1066 1067 private void visitFunction(@NotNull KtFunction function) { 1068 processLocalDeclaration(function); 1069 boolean isAnonymousFunction = function instanceof KtFunctionLiteral || function.getName() == null; 1070 if (isAnonymousFunction || (function.isLocal() && !(function.getParent() instanceof KtBlockExpression))) { 1071 builder.createLambda(function); 1072 } 1073 } 1074 1075 @Override 1076 public void visitNamedFunction(@NotNull KtNamedFunction function) { 1077 visitFunction(function); 1078 } 1079 1080 @Override 1081 public void visitLambdaExpression(@NotNull KtLambdaExpression lambdaExpression) { 1082 mark(lambdaExpression); 1083 KtFunctionLiteral functionLiteral = lambdaExpression.getFunctionLiteral(); 1084 visitFunction(functionLiteral); 1085 copyValue(functionLiteral, lambdaExpression); 1086 } 1087 1088 @Override 1089 public void visitQualifiedExpression(@NotNull KtQualifiedExpression expression) { 1090 mark(expression); 1091 KtExpression selectorExpression = expression.getSelectorExpression(); 1092 KtExpression receiverExpression = expression.getReceiverExpression(); 1093 1094 // todo: replace with selectorExpresion != null after parser is fixed 1095 if (selectorExpression instanceof KtCallExpression || selectorExpression instanceof KtSimpleNameExpression) { 1096 generateInstructions(selectorExpression); 1097 copyValue(selectorExpression, expression); 1098 } 1099 else { 1100 generateInstructions(receiverExpression); 1101 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression); 1102 } 1103 } 1104 1105 @Override 1106 public void visitCallExpression(@NotNull KtCallExpression expression) { 1107 if (!generateCall(expression)) { 1108 List<KtExpression> inputExpressions = new ArrayList<KtExpression>(); 1109 for (ValueArgument argument : expression.getValueArguments()) { 1110 KtExpression argumentExpression = argument.getArgumentExpression(); 1111 if (argumentExpression != null) { 1112 generateInstructions(argumentExpression); 1113 inputExpressions.add(argumentExpression); 1114 } 1115 } 1116 KtExpression calleeExpression = expression.getCalleeExpression(); 1117 generateInstructions(calleeExpression); 1118 inputExpressions.add(calleeExpression); 1119 inputExpressions.add(generateAndGetReceiverIfAny(expression)); 1120 1121 mark(expression); 1122 createNonSyntheticValue(expression, inputExpressions, MagicKind.UNRESOLVED_CALL); 1123 } 1124 } 1125 1126 @Nullable 1127 private KtExpression generateAndGetReceiverIfAny(KtExpression expression) { 1128 PsiElement parent = expression.getParent(); 1129 if (!(parent instanceof KtQualifiedExpression)) return null; 1130 1131 KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) parent; 1132 if (qualifiedExpression.getSelectorExpression() != expression) return null; 1133 1134 KtExpression receiverExpression = qualifiedExpression.getReceiverExpression(); 1135 generateInstructions(receiverExpression); 1136 1137 return receiverExpression; 1138 } 1139 1140 @Override 1141 public void visitProperty(@NotNull KtProperty property) { 1142 builder.declareVariable(property); 1143 KtExpression initializer = property.getInitializer(); 1144 if (initializer != null) { 1145 visitAssignment(property, getDeferredValue(initializer), property); 1146 } 1147 KtExpression delegate = property.getDelegateExpression(); 1148 if (delegate != null) { 1149 // We do not want to have getDeferredValue(delegate) here, because delegate value will be read anyway later 1150 visitAssignment(property, getDeferredValue(null), property); 1151 generateInstructions(delegate); 1152 if (builder.getBoundValue(delegate) != null) { 1153 createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate); 1154 } 1155 } 1156 1157 if (KtPsiUtil.isLocal(property)) { 1158 for (KtPropertyAccessor accessor : property.getAccessors()) { 1159 generateInstructions(accessor); 1160 } 1161 } 1162 } 1163 1164 @Override 1165 public void visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration declaration) { 1166 visitDestructuringDeclaration(declaration, true); 1167 } 1168 1169 private void visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration declaration, boolean generateWriteForEntries) { 1170 KtExpression initializer = declaration.getInitializer(); 1171 generateInstructions(initializer); 1172 for (KtDestructuringDeclarationEntry entry : declaration.getEntries()) { 1173 builder.declareVariable(entry); 1174 1175 ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry); 1176 1177 PseudoValue writtenValue; 1178 if (resolvedCall != null) { 1179 writtenValue = builder.call( 1180 entry, 1181 resolvedCall, 1182 getReceiverValues(resolvedCall), 1183 Collections.<PseudoValue, ValueParameterDescriptor>emptyMap() 1184 ).getOutputValue(); 1185 } 1186 else { 1187 writtenValue = createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, initializer); 1188 } 1189 1190 if (generateWriteForEntries) { 1191 generateInitializer(entry, writtenValue != null ? writtenValue : createSyntheticValue(entry, MagicKind.FAKE_INITIALIZER)); 1192 } 1193 } 1194 } 1195 1196 @Override 1197 public void visitPropertyAccessor(@NotNull KtPropertyAccessor accessor) { 1198 processLocalDeclaration(accessor); 1199 } 1200 1201 @Override 1202 public void visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression) { 1203 mark(expression); 1204 1205 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 1206 KtExpression left = expression.getLeft(); 1207 if (operationType == KtTokens.AS_KEYWORD || operationType == KtTokens.AS_SAFE) { 1208 generateInstructions(left); 1209 if (getBoundOrUnreachableValue(left) != null) { 1210 createNonSyntheticValue(expression, MagicKind.CAST, left); 1211 } 1212 } 1213 else { 1214 visitKtElement(expression); 1215 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left); 1216 } 1217 } 1218 1219 @Override 1220 public void visitThrowExpression(@NotNull KtThrowExpression expression) { 1221 mark(expression); 1222 1223 KtExpression thrownExpression = expression.getThrownExpression(); 1224 if (thrownExpression == null) return; 1225 1226 generateInstructions(thrownExpression); 1227 1228 PseudoValue thrownValue = builder.getBoundValue(thrownExpression); 1229 if (thrownValue == null) return; 1230 1231 builder.throwException(expression, thrownValue); 1232 } 1233 1234 @Override 1235 public void visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression) { 1236 generateArrayAccess(expression, trace.get(BindingContext.INDEXED_LVALUE_GET, expression)); 1237 } 1238 1239 @Override 1240 public void visitIsExpression(@NotNull KtIsExpression expression) { 1241 mark(expression); 1242 KtExpression left = expression.getLeftHandSide(); 1243 generateInstructions(left); 1244 createNonSyntheticValue(expression, MagicKind.IS, left); 1245 } 1246 1247 @Override 1248 public void visitWhenExpression(@NotNull KtWhenExpression expression) { 1249 mark(expression); 1250 1251 KtExpression subjectExpression = expression.getSubjectExpression(); 1252 if (subjectExpression != null) { 1253 generateInstructions(subjectExpression); 1254 } 1255 1256 List<KtExpression> branches = new ArrayList<KtExpression>(); 1257 1258 Label doneLabel = builder.createUnboundLabel("after 'when' expression"); 1259 1260 Label nextLabel = null; 1261 for (Iterator<KtWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) { 1262 KtWhenEntry whenEntry = iterator.next(); 1263 mark(whenEntry); 1264 1265 boolean isElse = whenEntry.isElse(); 1266 if (isElse) { 1267 if (iterator.hasNext()) { 1268 trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry)); 1269 } 1270 } 1271 Label bodyLabel = builder.createUnboundLabel("'when' entry body"); 1272 1273 KtWhenCondition[] conditions = whenEntry.getConditions(); 1274 for (int i = 0; i < conditions.length; i++) { 1275 KtWhenCondition condition = conditions[i]; 1276 condition.accept(conditionVisitor); 1277 if (i + 1 < conditions.length) { 1278 builder.nondeterministicJump(bodyLabel, expression, builder.getBoundValue(condition)); 1279 } 1280 } 1281 1282 if (!isElse) { 1283 nextLabel = builder.createUnboundLabel("next 'when' entry"); 1284 KtWhenCondition lastCondition = ArraysKt.lastOrNull(conditions); 1285 builder.nondeterministicJump(nextLabel, expression, builder.getBoundValue(lastCondition)); 1286 } 1287 1288 builder.bindLabel(bodyLabel); 1289 KtExpression whenEntryExpression = whenEntry.getExpression(); 1290 if (whenEntryExpression != null) { 1291 generateInstructions(whenEntryExpression); 1292 branches.add(whenEntryExpression); 1293 } 1294 builder.jump(doneLabel, expression); 1295 1296 if (!isElse) { 1297 builder.bindLabel(nextLabel); 1298 // For the last entry of exhaustive when, 1299 // attempt to jump further should lead to error, not to "done" 1300 if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) { 1301 builder.magic(expression, null, Collections.<PseudoValue>emptyList(), MagicKind.EXHAUSTIVE_WHEN_ELSE); 1302 } 1303 } 1304 } 1305 builder.bindLabel(doneLabel); 1306 1307 mergeValues(branches, expression); 1308 } 1309 1310 @Override 1311 public void visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression) { 1312 mark(expression); 1313 KtObjectDeclaration declaration = expression.getObjectDeclaration(); 1314 generateInstructions(declaration); 1315 1316 builder.createAnonymousObject(expression); 1317 } 1318 1319 @Override 1320 public void visitObjectDeclaration(@NotNull KtObjectDeclaration objectDeclaration) { 1321 generateHeaderDelegationSpecifiers(objectDeclaration); 1322 generateInitializersForScriptClassOrObject(objectDeclaration); 1323 generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration); 1324 } 1325 1326 @Override 1327 public void visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression) { 1328 mark(expression); 1329 1330 List<KtExpression> inputExpressions = new ArrayList<KtExpression>(); 1331 for (KtStringTemplateEntry entry : expression.getEntries()) { 1332 if (entry instanceof KtStringTemplateEntryWithExpression) { 1333 KtExpression entryExpression = entry.getExpression(); 1334 generateInstructions(entryExpression); 1335 inputExpressions.add(entryExpression); 1336 } 1337 } 1338 builder.loadStringTemplate(expression, elementsToValues(inputExpressions)); 1339 } 1340 1341 @Override 1342 public void visitTypeProjection(@NotNull KtTypeProjection typeProjection) { 1343 // TODO : Support Type Arguments. Companion object may be initialized at this point"); 1344 } 1345 1346 @Override 1347 public void visitAnonymousInitializer(@NotNull KtAnonymousInitializer classInitializer) { 1348 generateInstructions(classInitializer.getBody()); 1349 } 1350 1351 private void generateHeaderDelegationSpecifiers(@NotNull KtClassOrObject classOrObject) { 1352 for (KtSuperTypeListEntry specifier : classOrObject.getSuperTypeListEntries()) { 1353 generateInstructions(specifier); 1354 } 1355 } 1356 1357 private void generateInitializersForScriptClassOrObject(@NotNull KtDeclarationContainer classOrObject) { 1358 for (KtDeclaration declaration : classOrObject.getDeclarations()) { 1359 if (declaration instanceof KtProperty || declaration instanceof KtAnonymousInitializer) { 1360 generateInstructions(declaration); 1361 } 1362 } 1363 } 1364 1365 @Override 1366 public void visitClass(@NotNull KtClass klass) { 1367 if (klass.hasPrimaryConstructor()) { 1368 processParameters(klass.getPrimaryConstructorParameters()); 1369 1370 // delegation specifiers of primary constructor, anonymous class and property initializers 1371 generateHeaderDelegationSpecifiers(klass); 1372 generateInitializersForScriptClassOrObject(klass); 1373 } 1374 1375 generateDeclarationForLocalClassOrObjectIfNeeded(klass); 1376 } 1377 1378 @Override 1379 public void visitScript(@NotNull KtScript script) { 1380 generateInitializersForScriptClassOrObject(script); 1381 } 1382 1383 private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull KtClassOrObject classOrObject) { 1384 if (classOrObject.isLocal()) { 1385 for (KtDeclaration declaration : classOrObject.getDeclarations()) { 1386 if (declaration instanceof KtSecondaryConstructor || 1387 declaration instanceof KtProperty || 1388 declaration instanceof KtAnonymousInitializer) { 1389 continue; 1390 } 1391 generateInstructions(declaration); 1392 } 1393 } 1394 } 1395 1396 private void processParameters(@NotNull List<KtParameter> parameters) { 1397 for (KtParameter parameter : parameters) { 1398 generateInstructions(parameter); 1399 } 1400 } 1401 1402 @Override 1403 public void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) { 1404 KtClassOrObject classOrObject = PsiTreeUtil.getParentOfType(constructor, KtClassOrObject.class); 1405 assert classOrObject != null : "Guaranteed by parsing contract"; 1406 1407 processParameters(constructor.getValueParameters()); 1408 generateCallOrMarkUnresolved(constructor.getDelegationCall()); 1409 1410 if (!constructor.getDelegationCall().isCallToThis()) { 1411 generateInitializersForScriptClassOrObject(classOrObject); 1412 } 1413 1414 generateInstructions(constructor.getBodyExpression()); 1415 } 1416 1417 @Override 1418 public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) { 1419 generateCallOrMarkUnresolved(call); 1420 } 1421 1422 private void generateCallOrMarkUnresolved(@Nullable KtCallElement call) { 1423 if (call == null) return; 1424 if (!generateCall(call)) { 1425 List<KtExpression> arguments = CollectionsKt.map( 1426 call.getValueArguments(), 1427 new Function1<ValueArgument, KtExpression>() { 1428 @Override 1429 public KtExpression invoke(ValueArgument valueArgument) { 1430 return valueArgument.getArgumentExpression(); 1431 } 1432 } 1433 ); 1434 1435 for (KtExpression argument : arguments) { 1436 generateInstructions(argument); 1437 } 1438 createNonSyntheticValue(call, arguments, MagicKind.UNRESOLVED_CALL); 1439 } 1440 } 1441 1442 @Override 1443 public void visitDelegatedSuperTypeEntry(@NotNull KtDelegatedSuperTypeEntry specifier) { 1444 KtExpression delegateExpression = specifier.getDelegateExpression(); 1445 generateInstructions(delegateExpression); 1446 createSyntheticValue(specifier, MagicKind.VALUE_CONSUMER, delegateExpression); 1447 } 1448 1449 @Override 1450 public void visitSuperTypeEntry(@NotNull KtSuperTypeEntry specifier) { 1451 // Do not generate UNSUPPORTED_ELEMENT here 1452 } 1453 1454 @Override 1455 public void visitSuperTypeList(@NotNull KtSuperTypeList list) { 1456 list.acceptChildren(this); 1457 } 1458 1459 @Override 1460 public void visitKtFile(@NotNull KtFile file) { 1461 for (KtDeclaration declaration : file.getDeclarations()) { 1462 if (declaration instanceof KtProperty) { 1463 generateInstructions(declaration); 1464 } 1465 } 1466 } 1467 1468 @Override 1469 public void visitDoubleColonExpression(@NotNull KtDoubleColonExpression expression) { 1470 mark(expression); 1471 createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE); 1472 } 1473 1474 @Override 1475 public void visitKtElement(@NotNull KtElement element) { 1476 createNonSyntheticValue(element, MagicKind.UNSUPPORTED_ELEMENT); 1477 } 1478 1479 private boolean generateCall(@Nullable KtElement callElement) { 1480 if (callElement == null) return false; 1481 return checkAndGenerateCall(CallUtilKt.getResolvedCall(callElement, trace.getBindingContext())); 1482 } 1483 1484 private boolean checkAndGenerateCall(@Nullable ResolvedCall<?> resolvedCall) { 1485 if (resolvedCall == null) return false; 1486 generateCall(resolvedCall); 1487 return true; 1488 } 1489 1490 @NotNull 1491 private InstructionWithValue generateCall(@NotNull ResolvedCall<?> resolvedCall) { 1492 KtElement callElement = resolvedCall.getCall().getCallElement(); 1493 1494 Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall); 1495 1496 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap(); 1497 for (ValueArgument argument : resolvedCall.getCall().getValueArguments()) { 1498 ArgumentMapping argumentMapping = resolvedCall.getArgumentMapping(argument); 1499 KtExpression argumentExpression = argument.getArgumentExpression(); 1500 if (argumentMapping instanceof ArgumentMatch) { 1501 parameterValues = generateValueArgument(argument, ((ArgumentMatch) argumentMapping).getValueParameter(), parameterValues); 1502 } 1503 else if (argumentExpression != null) { 1504 generateInstructions(argumentExpression); 1505 createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression); 1506 } 1507 } 1508 1509 if (resolvedCall.getResultingDescriptor() instanceof VariableDescriptor) { 1510 // If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated. 1511 // todo : process arguments for such a case (KT-5387) 1512 KtExpression callExpression = callElement instanceof KtExpression ? (KtExpression) callElement : null; 1513 assert callExpression != null 1514 : "Variable-based call without callee expression: " + callElement.getText(); 1515 assert parameterValues.isEmpty() 1516 : "Variable-based call with non-empty argument list: " + callElement.getText(); 1517 return builder.readVariable(callExpression, resolvedCall, receivers); 1518 } 1519 1520 mark(resolvedCall.getCall().getCallElement()); 1521 return builder.call(callElement, resolvedCall, receivers, parameterValues); 1522 } 1523 1524 @NotNull 1525 private Map<PseudoValue, ReceiverValue> getReceiverValues(ResolvedCall<?> resolvedCall) { 1526 PseudoValue varCallResult = null; 1527 ReceiverValue explicitReceiver = null; 1528 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1529 varCallResult = generateCall(((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall()).getOutputValue(); 1530 1531 ExplicitReceiverKind kind = resolvedCall.getExplicitReceiverKind(); 1532 //noinspection EnumSwitchStatementWhichMissesCases 1533 switch (kind) { 1534 case DISPATCH_RECEIVER: 1535 explicitReceiver = resolvedCall.getDispatchReceiver(); 1536 break; 1537 case EXTENSION_RECEIVER: 1538 case BOTH_RECEIVERS: 1539 explicitReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver(); 1540 break; 1541 } 1542 } 1543 1544 SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap(); 1545 if (explicitReceiver != null && varCallResult != null) { 1546 receiverValues = receiverValues.plus(varCallResult, explicitReceiver); 1547 } 1548 KtElement callElement = resolvedCall.getCall().getCallElement(); 1549 receiverValues = getReceiverValues(callElement, resolvedCall.getDispatchReceiver(), receiverValues); 1550 receiverValues = getReceiverValues(callElement, (ReceiverValue) resolvedCall.getExtensionReceiver(), receiverValues); 1551 return receiverValues; 1552 } 1553 1554 @NotNull 1555 private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues( 1556 KtElement callElement, 1557 @Nullable ReceiverValue receiver, 1558 SmartFMap<PseudoValue, ReceiverValue> receiverValues 1559 ) { 1560 if (receiver == null || receiverValues.containsValue(receiver)) return receiverValues; 1561 1562 if (receiver instanceof ImplicitReceiver) { 1563 receiverValues = receiverValues.plus(createSyntheticValue(callElement, MagicKind.IMPLICIT_RECEIVER), receiver); 1564 } 1565 else if (receiver instanceof ExpressionReceiver) { 1566 KtExpression expression = ((ExpressionReceiver) receiver).getExpression(); 1567 if (builder.getBoundValue(expression) == null) { 1568 generateInstructions(expression); 1569 } 1570 1571 PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression); 1572 if (receiverPseudoValue != null) { 1573 receiverValues = receiverValues.plus(receiverPseudoValue, receiver); 1574 } 1575 } 1576 else if (receiver instanceof TransientReceiver) { 1577 // Do nothing 1578 } 1579 else { 1580 throw new IllegalArgumentException("Unknown receiver kind: " + receiver); 1581 } 1582 1583 return receiverValues; 1584 } 1585 1586 @NotNull 1587 private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument( 1588 ValueArgument valueArgument, 1589 ValueParameterDescriptor parameterDescriptor, 1590 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues) { 1591 KtExpression expression = valueArgument.getArgumentExpression(); 1592 if (expression != null) { 1593 if (!valueArgument.isExternal()) { 1594 generateInstructions(expression); 1595 } 1596 1597 PseudoValue argValue = getBoundOrUnreachableValue(expression); 1598 if (argValue != null) { 1599 parameterValues = parameterValues.plus(argValue, parameterDescriptor); 1600 } 1601 } 1602 return parameterValues; 1603 } 1604 } 1605 }