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