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