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