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.KotlinPackage; 026 import kotlin.jvm.functions.Function0; 027 import kotlin.jvm.functions.Function1; 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.JetControlFlowInstructionsGenerator; 032 import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue; 033 import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode; 034 import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeImpl; 035 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget; 036 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValue; 037 import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind; 038 import org.jetbrains.kotlin.descriptors.*; 039 import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; 040 import org.jetbrains.kotlin.lexer.JetToken; 041 import org.jetbrains.kotlin.lexer.JetTokens; 042 import org.jetbrains.kotlin.name.Name; 043 import org.jetbrains.kotlin.psi.*; 044 import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; 045 import org.jetbrains.kotlin.resolve.BindingContext; 046 import org.jetbrains.kotlin.resolve.BindingContextUtils; 047 import org.jetbrains.kotlin.resolve.BindingTrace; 048 import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils; 049 import org.jetbrains.kotlin.resolve.calls.model.*; 050 import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind; 051 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 052 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 053 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; 054 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; 055 import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver; 056 import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver; 057 import org.jetbrains.kotlin.types.JetType; 058 import org.jetbrains.kotlin.types.expressions.OperatorConventions; 059 060 import java.util.*; 061 062 import static org.jetbrains.kotlin.cfg.JetControlFlowBuilder.PredefinedOperation.*; 063 import static org.jetbrains.kotlin.diagnostics.Errors.*; 064 import static org.jetbrains.kotlin.lexer.JetTokens.*; 065 import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall; 066 067 public class JetControlFlowProcessor { 068 069 private final JetControlFlowBuilder builder; 070 private final BindingTrace trace; 071 072 public JetControlFlowProcessor(BindingTrace trace) { 073 this.builder = new JetControlFlowInstructionsGenerator(); 074 this.trace = trace; 075 } 076 077 @NotNull 078 public Pseudocode generatePseudocode(@NotNull JetElement subroutine) { 079 Pseudocode pseudocode = generate(subroutine); 080 ((PseudocodeImpl) pseudocode).postProcess(); 081 return pseudocode; 082 } 083 084 @NotNull 085 private Pseudocode generate(@NotNull JetElement subroutine) { 086 builder.enterSubroutine(subroutine); 087 CFPVisitor cfpVisitor = new CFPVisitor(builder); 088 if (subroutine instanceof JetDeclarationWithBody && !(subroutine instanceof JetSecondaryConstructor)) { 089 JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; 090 List<JetParameter> valueParameters = declarationWithBody.getValueParameters(); 091 for (JetParameter valueParameter : valueParameters) { 092 cfpVisitor.generateInstructions(valueParameter); 093 } 094 JetExpression bodyExpression = declarationWithBody.getBodyExpression(); 095 if (bodyExpression != null) { 096 cfpVisitor.generateInstructions(bodyExpression); 097 if (!declarationWithBody.hasBlockBody()) { 098 generateImplicitReturnValue(bodyExpression, subroutine); 099 } 100 } 101 } else { 102 cfpVisitor.generateInstructions(subroutine); 103 } 104 return builder.exitSubroutine(subroutine); 105 } 106 107 private void generateImplicitReturnValue(@NotNull JetExpression bodyExpression, @NotNull JetElement subroutine) { 108 CallableDescriptor subroutineDescriptor = (CallableDescriptor) trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, subroutine); 109 if (subroutineDescriptor == null) return; 110 111 JetType returnType = subroutineDescriptor.getReturnType(); 112 if (returnType != null && KotlinBuiltIns.isUnit(returnType) && subroutineDescriptor instanceof AnonymousFunctionDescriptor) return; 113 114 PseudoValue returnValue = builder.getBoundValue(bodyExpression); 115 if (returnValue == null) return; 116 117 builder.returnValue(bodyExpression, returnValue, subroutine); 118 } 119 120 private void processLocalDeclaration(@NotNull JetDeclaration subroutine) { 121 Label afterDeclaration = builder.createUnboundLabel("after local declaration"); 122 123 builder.nondeterministicJump(afterDeclaration, subroutine, null); 124 generate(subroutine); 125 builder.bindLabel(afterDeclaration); 126 } 127 128 private class CFPVisitor extends JetVisitorVoid { 129 private final JetControlFlowBuilder builder; 130 131 private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() { 132 133 private JetExpression getSubjectExpression(JetWhenCondition condition) { 134 JetWhenExpression whenExpression = PsiTreeUtil.getParentOfType(condition, JetWhenExpression.class); 135 return whenExpression != null ? whenExpression.getSubjectExpression() : null; 136 } 137 138 @Override 139 public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) { 140 if (!generateCall(condition.getOperationReference())) { 141 JetExpression rangeExpression = condition.getRangeExpression(); 142 generateInstructions(rangeExpression); 143 createNonSyntheticValue(condition, MagicKind.UNRESOLVED_CALL, rangeExpression); 144 } 145 } 146 147 @Override 148 public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) { 149 mark(condition); 150 createNonSyntheticValue(condition, MagicKind.IS, getSubjectExpression(condition)); 151 } 152 153 @Override 154 public void visitWhenConditionWithExpression(@NotNull JetWhenConditionWithExpression condition) { 155 mark(condition); 156 157 JetExpression expression = condition.getExpression(); 158 generateInstructions(expression); 159 160 JetExpression subjectExpression = getSubjectExpression(condition); 161 if (subjectExpression != null) { 162 // todo: this can be replaced by equals() invocation (when corresponding resolved call is recorded) 163 createNonSyntheticValue(condition, MagicKind.EQUALS_IN_WHEN_CONDITION, subjectExpression, expression); 164 } 165 else { 166 copyValue(expression, condition); 167 } 168 } 169 170 @Override 171 public void visitJetElement(@NotNull JetElement element) { 172 throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); 173 } 174 }; 175 176 private CFPVisitor(@NotNull JetControlFlowBuilder builder) { 177 this.builder = builder; 178 } 179 180 private void mark(JetElement element) { 181 builder.mark(element); 182 } 183 184 public void generateInstructions(@Nullable JetElement element) { 185 if (element == null) return; 186 element.accept(this); 187 checkNothingType(element); 188 } 189 190 private void checkNothingType(JetElement element) { 191 if (!(element instanceof JetExpression)) return; 192 193 JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element); 194 if (expression == null) return; 195 196 if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression 197 || expression instanceof JetIfExpression || expression instanceof JetWhenExpression) { 198 return; 199 } 200 201 JetType type = trace.getBindingContext().getType(expression); 202 if (type != null && KotlinBuiltIns.isNothing(type)) { 203 builder.jumpToError(expression); 204 } 205 } 206 207 @NotNull 208 private PseudoValue createSyntheticValue(@NotNull JetElement instructionElement, @NotNull MagicKind kind, JetElement... from) { 209 List<PseudoValue> values = elementsToValues(from.length > 0 ? Arrays.asList(from) : Collections.<JetElement>emptyList()); 210 return builder.magic(instructionElement, null, values, kind).getOutputValue(); 211 } 212 213 @NotNull 214 private PseudoValue createNonSyntheticValue( 215 @NotNull JetElement to, @NotNull List<? extends JetElement> from, @NotNull MagicKind kind 216 ) { 217 List<PseudoValue> values = elementsToValues(from); 218 return builder.magic(to, to, values, kind).getOutputValue(); 219 } 220 221 @NotNull 222 private PseudoValue createNonSyntheticValue(@NotNull JetElement to, @NotNull MagicKind kind, JetElement... from) { 223 return createNonSyntheticValue(to, Arrays.asList(from), kind); 224 } 225 226 private void mergeValues(@NotNull List<JetExpression> from, @NotNull JetExpression to) { 227 builder.merge(to, elementsToValues(from)); 228 } 229 230 private void copyValue(@Nullable JetElement from, @NotNull JetElement to) { 231 PseudoValue value = getBoundOrUnreachableValue(from); 232 if (value != null) { 233 builder.bindValue(value, to); 234 } 235 } 236 237 @Nullable 238 private PseudoValue getBoundOrUnreachableValue(@Nullable JetElement element) { 239 if (element == null) return null; 240 241 PseudoValue value = builder.getBoundValue(element); 242 return value != null || element instanceof JetDeclaration ? value : builder.newValue(element); 243 } 244 245 private List<PseudoValue> elementsToValues(List<? extends JetElement> from) { 246 if (from.isEmpty()) return Collections.emptyList(); 247 return KotlinPackage.filterNotNull( 248 KotlinPackage.map( 249 from, 250 new Function1<JetElement, PseudoValue>() { 251 @Override 252 public PseudoValue invoke(JetElement element) { 253 return getBoundOrUnreachableValue(element); 254 } 255 } 256 ) 257 ); 258 } 259 260 private void generateInitializer(@NotNull JetDeclaration declaration, @NotNull PseudoValue initValue) { 261 builder.write( 262 declaration, 263 declaration, 264 initValue, 265 getDeclarationAccessTarget(declaration), 266 Collections.<PseudoValue, ReceiverValue>emptyMap() 267 ); 268 } 269 270 @NotNull 271 private AccessTarget getResolvedCallAccessTarget(JetElement element) { 272 ResolvedCall<?> resolvedCall = getResolvedCall(element, trace.getBindingContext()); 273 return resolvedCall != null ? new AccessTarget.Call(resolvedCall) : AccessTarget.BlackBox.INSTANCE$; 274 } 275 276 @NotNull 277 private AccessTarget getDeclarationAccessTarget(JetElement element) { 278 DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); 279 return descriptor instanceof VariableDescriptor 280 ? new AccessTarget.Declaration((VariableDescriptor) descriptor) 281 : AccessTarget.BlackBox.INSTANCE$; 282 } 283 284 @Override 285 public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) { 286 mark(expression); 287 JetExpression innerExpression = expression.getExpression(); 288 if (innerExpression != null) { 289 generateInstructions(innerExpression); 290 copyValue(innerExpression, expression); 291 } 292 } 293 294 @Override 295 public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) { 296 JetExpression baseExpression = expression.getBaseExpression(); 297 if (baseExpression != null) { 298 generateInstructions(baseExpression); 299 copyValue(baseExpression, expression); 300 } 301 } 302 303 @Override 304 public void visitThisExpression(@NotNull JetThisExpression expression) { 305 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext()); 306 if (resolvedCall == null) { 307 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL); 308 return; 309 } 310 311 CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); 312 if (resultingDescriptor instanceof ReceiverParameterDescriptor) { 313 builder.readVariable(expression, resolvedCall, getReceiverValues(resolvedCall)); 314 } 315 316 copyValue(expression, expression.getInstanceReference()); 317 } 318 319 @Override 320 public void visitConstantExpression(@NotNull JetConstantExpression expression) { 321 CompileTimeConstant<?> constant = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext()); 322 builder.loadConstant(expression, constant); 323 } 324 325 @Override 326 public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) { 327 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext()); 328 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 329 VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; 330 generateCall(variableAsFunctionResolvedCall.getVariableCall()); 331 } 332 else if (!generateCall(expression) && !(expression.getParent() instanceof JetCallExpression)) { 333 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, generateAndGetReceiverIfAny(expression)); 334 } 335 } 336 337 @Override 338 public void visitLabeledExpression(@NotNull JetLabeledExpression expression) { 339 mark(expression); 340 JetExpression baseExpression = expression.getBaseExpression(); 341 if (baseExpression != null) { 342 generateInstructions(baseExpression); 343 copyValue(baseExpression, expression); 344 } 345 } 346 347 @SuppressWarnings("SuspiciousMethodCalls") 348 @Override 349 public void visitBinaryExpression(@NotNull JetBinaryExpression expression) { 350 JetSimpleNameExpression operationReference = expression.getOperationReference(); 351 IElementType operationType = operationReference.getReferencedNameElementType(); 352 353 JetExpression left = expression.getLeft(); 354 JetExpression right = expression.getRight(); 355 if (operationType == ANDAND || operationType == OROR) { 356 generateBooleanOperation(expression); 357 } 358 else if (operationType == EQ) { 359 visitAssignment(left, getDeferredValue(right), expression); 360 } 361 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { 362 ResolvedCall<?> resolvedCall = getResolvedCall(expression, trace.getBindingContext()); 363 if (resolvedCall != null) { 364 PseudoValue rhsValue = generateCall(resolvedCall).getOutputValue(); 365 Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken()); 366 if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) { 367 /* At this point assignment of the form a += b actually means a = a + b 368 * So we first generate call of "+" operation and then use its output pseudo-value 369 * as a right-hand side when generating assignment call 370 */ 371 visitAssignment(left, getValueAsFunction(rhsValue), expression); 372 } 373 } 374 else { 375 generateBothArgumentsAndMark(expression); 376 } 377 } 378 else if (operationType == ELVIS) { 379 generateInstructions(left); 380 mark(expression); 381 Label afterElvis = builder.createUnboundLabel("after elvis operator"); 382 builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left)); 383 if (right != null) { 384 generateInstructions(right); 385 } 386 builder.bindLabel(afterElvis); 387 mergeValues(Arrays.asList(left, right), expression); 388 } 389 else { 390 if (!generateCall(expression)) { 391 generateBothArgumentsAndMark(expression); 392 } 393 } 394 } 395 396 private void generateBooleanOperation(JetBinaryExpression expression) { 397 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 398 JetExpression left = expression.getLeft(); 399 JetExpression right = expression.getRight(); 400 401 Label resultLabel = builder.createUnboundLabel("result of boolean operation"); 402 generateInstructions(left); 403 if (operationType == ANDAND) { 404 builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left)); 405 } 406 else { 407 builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left)); 408 } 409 if (right != null) { 410 generateInstructions(right); 411 } 412 builder.bindLabel(resultLabel); 413 JetControlFlowBuilder.PredefinedOperation operation = operationType == ANDAND ? AND : OR; 414 builder.predefinedOperation(expression, operation, elementsToValues(Arrays.asList(left, right))); 415 } 416 417 private Function0<PseudoValue> getValueAsFunction(final PseudoValue value) { 418 return new Function0<PseudoValue>() { 419 @Override 420 public PseudoValue invoke() { 421 return value; 422 } 423 }; 424 } 425 426 private Function0<PseudoValue> getDeferredValue(final JetExpression expression) { 427 return new Function0<PseudoValue>() { 428 @Override 429 public PseudoValue invoke() { 430 generateInstructions(expression); 431 return getBoundOrUnreachableValue(expression); 432 } 433 }; 434 } 435 436 private void generateBothArgumentsAndMark(JetBinaryExpression expression) { 437 JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); 438 if (left != null) { 439 generateInstructions(left); 440 } 441 JetExpression right = expression.getRight(); 442 if (right != null) { 443 generateInstructions(right); 444 } 445 mark(expression); 446 createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, left, right); 447 } 448 449 private void visitAssignment( 450 JetExpression lhs, 451 @NotNull Function0<PseudoValue> rhsDeferredValue, 452 JetExpression parentExpression 453 ) { 454 JetExpression left = JetPsiUtil.deparenthesize(lhs); 455 if (left == null) { 456 List<PseudoValue> arguments = Collections.singletonList(rhsDeferredValue.invoke()); 457 builder.magic(parentExpression, parentExpression, arguments, MagicKind.UNSUPPORTED_ELEMENT); 458 return; 459 } 460 461 if (left instanceof JetArrayAccessExpression) { 462 generateArrayAssignment((JetArrayAccessExpression) left, rhsDeferredValue, parentExpression); 463 return; 464 } 465 466 Map<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap(); 467 AccessTarget accessTarget = AccessTarget.BlackBox.INSTANCE$; 468 if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) { 469 accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left)); 470 if (accessTarget instanceof AccessTarget.Call) { 471 receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall()); 472 } 473 } 474 else if (left instanceof JetProperty) { 475 accessTarget = getDeclarationAccessTarget(left); 476 } 477 478 if (accessTarget == AccessTarget.BlackBox.INSTANCE$ && !(left instanceof JetProperty)) { 479 generateInstructions(left); 480 createSyntheticValue(left, MagicKind.VALUE_CONSUMER, left); 481 } 482 483 PseudoValue rightValue = rhsDeferredValue.invoke(); 484 PseudoValue rValue = 485 rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS); 486 builder.write(parentExpression, left, rValue, accessTarget, receiverValues); 487 } 488 489 private void generateArrayAssignment( 490 JetArrayAccessExpression lhs, 491 @NotNull Function0<PseudoValue> rhsDeferredValue, 492 @NotNull JetExpression parentExpression 493 ) { 494 ResolvedCall<FunctionDescriptor> setResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_SET, lhs); 495 496 if (setResolvedCall == null) { 497 generateArrayAccess(lhs, null); 498 499 List<PseudoValue> arguments = KotlinPackage.filterNotNull( 500 Arrays.asList(getBoundOrUnreachableValue(lhs), rhsDeferredValue.invoke()) 501 ); 502 builder.magic(parentExpression, parentExpression, arguments, MagicKind.UNRESOLVED_CALL); 503 504 return; 505 } 506 507 // In case of simple ('=') array assignment mark instruction is not generated yet, so we put it before generating "set" call 508 if (((JetOperationExpression) parentExpression).getOperationReference().getReferencedNameElementType() == EQ) { 509 mark(lhs); 510 } 511 512 generateInstructions(lhs.getArrayExpression()); 513 514 Map<PseudoValue, ReceiverValue> receiverValues = getReceiverValues(setResolvedCall); 515 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = getArraySetterArguments(rhsDeferredValue, setResolvedCall); 516 517 builder.call(parentExpression, setResolvedCall, receiverValues, argumentValues); 518 } 519 520 /* We assume that assignment right-hand side corresponds to the last argument of the call 521 * So receiver instructions/pseudo-values are generated for all arguments except the last one which is replaced 522 * by pre-generated pseudo-value 523 * For example, assignment a[1, 2] += 3 means a.set(1, 2, a.get(1) + 3), so in order to generate "set" call 524 * we first generate instructions for 1 and 2 whereas 3 is replaced by pseudo-value corresponding to "a.get(1) + 3" 525 */ 526 private SmartFMap<PseudoValue, ValueParameterDescriptor> getArraySetterArguments( 527 Function0<PseudoValue> rhsDeferredValue, 528 final ResolvedCall<FunctionDescriptor> setResolvedCall 529 ) { 530 List<ValueArgument> valueArguments = KotlinPackage.flatMapTo( 531 setResolvedCall.getResultingDescriptor().getValueParameters(), 532 new ArrayList<ValueArgument>(), 533 new Function1<ValueParameterDescriptor, Iterable<? extends ValueArgument>>() { 534 @Override 535 public Iterable<? extends ValueArgument> invoke(ValueParameterDescriptor descriptor) { 536 ResolvedValueArgument resolvedValueArgument = setResolvedCall.getValueArguments().get(descriptor); 537 return resolvedValueArgument != null 538 ? resolvedValueArgument.getArguments() 539 : Collections.<ValueArgument>emptyList(); 540 } 541 } 542 ); 543 544 ValueArgument rhsArgument = KotlinPackage.lastOrNull(valueArguments); 545 SmartFMap<PseudoValue, ValueParameterDescriptor> argumentValues = SmartFMap.emptyMap(); 546 for (ValueArgument valueArgument : valueArguments) { 547 ArgumentMapping argumentMapping = setResolvedCall.getArgumentMapping(valueArgument); 548 if (argumentMapping.isError() || (!(argumentMapping instanceof ArgumentMatch))) continue; 549 550 ValueParameterDescriptor parameterDescriptor = ((ArgumentMatch) argumentMapping).getValueParameter(); 551 if (valueArgument != rhsArgument) { 552 argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues); 553 } 554 else { 555 PseudoValue rhsValue = rhsDeferredValue.invoke(); 556 if (rhsValue != null) { 557 argumentValues = argumentValues.plus(rhsValue, parameterDescriptor); 558 } 559 } 560 } 561 return argumentValues; 562 } 563 564 private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) { 565 if (builder.getBoundValue(arrayAccessExpression) != null) return; 566 mark(arrayAccessExpression); 567 if (!checkAndGenerateCall(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("else branch"); 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("'if' expression result"); 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); 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 createSyntheticValue(condition, MagicKind.VALUE_CONSUMER, condition); 811 } 812 813 builder.enterLoopBody(expression); 814 JetExpression body = expression.getBody(); 815 if (body != null) { 816 generateInstructions(body); 817 } 818 builder.jump(loopInfo.getEntryPoint(), expression); 819 builder.exitLoopBody(expression); 820 builder.bindLabel(loopInfo.getExitPoint()); 821 builder.loadUnit(expression); 822 } 823 824 @Override 825 public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) { 826 builder.enterLexicalScope(expression); 827 mark(expression); 828 LoopInfo loopInfo = builder.enterLoop(expression); 829 830 builder.enterLoopBody(expression); 831 JetExpression body = expression.getBody(); 832 if (body != null) { 833 generateInstructions(body); 834 } 835 builder.exitLoopBody(expression); 836 builder.bindLabel(loopInfo.getConditionEntryPoint()); 837 JetExpression condition = expression.getCondition(); 838 if (condition != null) { 839 generateInstructions(condition); 840 } 841 builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition)); 842 builder.bindLabel(loopInfo.getExitPoint()); 843 builder.loadUnit(expression); 844 builder.exitLexicalScope(expression); 845 } 846 847 @Override 848 public void visitForExpression(@NotNull JetForExpression expression) { 849 builder.enterLexicalScope(expression); 850 851 JetExpression loopRange = expression.getLoopRange(); 852 if (loopRange != null) { 853 generateInstructions(loopRange); 854 } 855 declareLoopParameter(expression); 856 857 // TODO : primitive cases 858 LoopInfo loopInfo = builder.enterLoop(expression); 859 860 builder.bindLabel(loopInfo.getConditionEntryPoint()); 861 builder.nondeterministicJump(loopInfo.getExitPoint(), expression, null); 862 863 864 writeLoopParameterAssignment(expression); 865 866 mark(expression); 867 builder.enterLoopBody(expression); 868 JetExpression body = expression.getBody(); 869 if (body != null) { 870 generateInstructions(body); 871 } 872 builder.jump(loopInfo.getEntryPoint(), expression); 873 874 builder.exitLoopBody(expression); 875 builder.bindLabel(loopInfo.getExitPoint()); 876 builder.loadUnit(expression); 877 builder.exitLexicalScope(expression); 878 } 879 880 private void declareLoopParameter(JetForExpression expression) { 881 JetParameter loopParameter = expression.getLoopParameter(); 882 JetMultiDeclaration multiDeclaration = expression.getMultiParameter(); 883 if (loopParameter != null) { 884 builder.declareParameter(loopParameter); 885 } 886 else if (multiDeclaration != null) { 887 visitMultiDeclaration(multiDeclaration, false); 888 } 889 } 890 891 private void writeLoopParameterAssignment(JetForExpression expression) { 892 JetParameter loopParameter = expression.getLoopParameter(); 893 JetMultiDeclaration multiDeclaration = expression.getMultiParameter(); 894 JetExpression loopRange = expression.getLoopRange(); 895 896 PseudoValue value = builder.magic( 897 loopRange != null ? loopRange : expression, 898 null, 899 ContainerUtil.createMaybeSingletonList(builder.getBoundValue(loopRange)), 900 MagicKind.LOOP_RANGE_ITERATION 901 ).getOutputValue(); 902 903 if (loopParameter != null) { 904 generateInitializer(loopParameter, value); 905 } 906 else if (multiDeclaration != null) { 907 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 908 generateInitializer(entry, value); 909 } 910 } 911 } 912 913 @Override 914 public void visitBreakExpression(@NotNull JetBreakExpression expression) { 915 JetElement loop = getCorrespondingLoop(expression); 916 if (loop != null) { 917 checkJumpDoesNotCrossFunctionBoundary(expression, loop); 918 builder.jump(builder.getExitPoint(loop), expression); 919 } 920 } 921 922 @Override 923 public void visitContinueExpression(@NotNull JetContinueExpression expression) { 924 JetElement loop = getCorrespondingLoop(expression); 925 if (loop != null) { 926 checkJumpDoesNotCrossFunctionBoundary(expression, loop); 927 builder.jump(builder.getConditionEntryPoint(loop), expression); 928 } 929 } 930 931 @Nullable 932 private JetElement getCorrespondingLoop(JetExpressionWithLabel expression) { 933 String labelName = expression.getLabelName(); 934 JetLoopExpression loop; 935 if (labelName != null) { 936 JetSimpleNameExpression targetLabel = expression.getTargetLabel(); 937 assert targetLabel != null; 938 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel); 939 if (labeledElement instanceof JetLoopExpression) { 940 loop = (JetLoopExpression) labeledElement; 941 } 942 else { 943 trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); 944 loop = null; 945 } 946 } 947 else { 948 loop = builder.getCurrentLoop(); 949 if (loop == null) { 950 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); 951 } else { 952 JetWhenExpression whenExpression = PsiTreeUtil.getParentOfType(expression, JetWhenExpression.class, true, 953 JetLoopExpression.class); 954 if (whenExpression != null) { 955 trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression)); 956 } 957 } 958 } 959 if (loop != null && loop.getBody() != null 960 // the faster version of 'isAncestor' check: 961 && !loop.getBody().getTextRange().contains(expression.getTextRange())) { 962 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); 963 return null; 964 } 965 return loop; 966 } 967 968 private void checkJumpDoesNotCrossFunctionBoundary(@NotNull JetExpressionWithLabel jumpExpression, @NotNull JetElement jumpTarget) { 969 BindingContext bindingContext = trace.getBindingContext(); 970 971 FunctionDescriptor labelExprEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpExpression); 972 FunctionDescriptor labelTargetEnclosingFunc = BindingContextUtils.getEnclosingFunctionDescriptor(bindingContext, jumpTarget); 973 if (labelExprEnclosingFunc != labelTargetEnclosingFunc) { 974 trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression)); 975 } 976 } 977 978 @Override 979 public void visitReturnExpression(@NotNull JetReturnExpression expression) { 980 JetExpression returnedExpression = expression.getReturnedExpression(); 981 if (returnedExpression != null) { 982 generateInstructions(returnedExpression); 983 } 984 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 985 JetElement subroutine; 986 String labelName = expression.getLabelName(); 987 if (labelElement != null && labelName != null) { 988 PsiElement labeledElement = trace.get(BindingContext.LABEL_TARGET, labelElement); 989 if (labeledElement != null) { 990 assert labeledElement instanceof JetElement; 991 subroutine = (JetElement) labeledElement; 992 } 993 else { 994 subroutine = null; 995 } 996 } 997 else { 998 subroutine = builder.getReturnSubroutine(); 999 // TODO : a context check 1000 } 1001 1002 if (subroutine instanceof JetFunction || subroutine instanceof JetPropertyAccessor) { 1003 PseudoValue returnValue = returnedExpression != null ? builder.getBoundValue(returnedExpression) : null; 1004 if (returnValue == null) { 1005 builder.returnNoValue(expression, subroutine); 1006 } 1007 else { 1008 builder.returnValue(expression, returnValue, subroutine); 1009 } 1010 } 1011 else { 1012 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression); 1013 } 1014 } 1015 1016 @Override 1017 public void visitParameter(@NotNull JetParameter parameter) { 1018 builder.declareParameter(parameter); 1019 JetExpression defaultValue = parameter.getDefaultValue(); 1020 if (defaultValue != null) { 1021 Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName()); 1022 builder.nondeterministicJump(skipDefaultValue, defaultValue, null); 1023 generateInstructions(defaultValue); 1024 builder.bindLabel(skipDefaultValue); 1025 } 1026 generateInitializer(parameter, computePseudoValueForParameter(parameter)); 1027 } 1028 1029 @NotNull 1030 private PseudoValue computePseudoValueForParameter(@NotNull JetParameter parameter) { 1031 PseudoValue syntheticValue = createSyntheticValue(parameter, MagicKind.FAKE_INITIALIZER); 1032 PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue()); 1033 if (defaultValue == null) { 1034 return syntheticValue; 1035 } 1036 return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue(); 1037 } 1038 1039 @Override 1040 public void visitBlockExpression(@NotNull JetBlockExpression expression) { 1041 boolean declareLexicalScope = !isBlockInDoWhile(expression); 1042 if (declareLexicalScope) { 1043 builder.enterLexicalScope(expression); 1044 } 1045 mark(expression); 1046 List<JetExpression> statements = expression.getStatements(); 1047 for (JetExpression statement : statements) { 1048 generateInstructions(statement); 1049 } 1050 if (statements.isEmpty()) { 1051 builder.loadUnit(expression); 1052 } 1053 else { 1054 copyValue(KotlinPackage.lastOrNull(statements), expression); 1055 } 1056 if (declareLexicalScope) { 1057 builder.exitLexicalScope(expression); 1058 } 1059 } 1060 1061 private boolean isBlockInDoWhile(@NotNull JetBlockExpression expression) { 1062 PsiElement parent = expression.getParent(); 1063 if (parent == null) return false; 1064 return parent.getParent() instanceof JetDoWhileExpression; 1065 } 1066 1067 private void visitFunction(@NotNull JetFunction function) { 1068 processLocalDeclaration(function); 1069 boolean isAnonymousFunction = function instanceof JetFunctionLiteral || function.getName() == null; 1070 if (isAnonymousFunction || (function.isLocal() && !(function.getParent() instanceof JetBlockExpression))) { 1071 builder.createLambda(function); 1072 } 1073 } 1074 1075 @Override 1076 public void visitNamedFunction(@NotNull JetNamedFunction function) { 1077 visitFunction(function); 1078 } 1079 1080 @Override 1081 public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) { 1082 mark(expression); 1083 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); 1084 visitFunction(functionLiteral); 1085 copyValue(functionLiteral, 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 if (builder.getBoundValue(delegate) != null) { 1151 createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate); 1152 } 1153 } 1154 1155 if (JetPsiUtil.isLocal(property)) { 1156 for (JetPropertyAccessor accessor : property.getAccessors()) { 1157 generateInstructions(accessor); 1158 } 1159 } 1160 } 1161 1162 @Override 1163 public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) { 1164 visitMultiDeclaration(declaration, true); 1165 } 1166 1167 private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) { 1168 JetExpression initializer = declaration.getInitializer(); 1169 generateInstructions(initializer); 1170 for (JetMultiDeclarationEntry entry : declaration.getEntries()) { 1171 builder.declareVariable(entry); 1172 1173 ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry); 1174 1175 PseudoValue writtenValue; 1176 if (resolvedCall != null) { 1177 writtenValue = builder.call( 1178 entry, 1179 resolvedCall, 1180 getReceiverValues(resolvedCall), 1181 Collections.<PseudoValue, ValueParameterDescriptor>emptyMap() 1182 ).getOutputValue(); 1183 } 1184 else { 1185 writtenValue = createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, initializer); 1186 } 1187 1188 if (generateWriteForEntries) { 1189 generateInitializer(entry, writtenValue != null ? writtenValue : createSyntheticValue(entry, MagicKind.FAKE_INITIALIZER)); 1190 } 1191 } 1192 } 1193 1194 @Override 1195 public void visitPropertyAccessor(@NotNull JetPropertyAccessor accessor) { 1196 processLocalDeclaration(accessor); 1197 } 1198 1199 @Override 1200 public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) { 1201 mark(expression); 1202 1203 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 1204 JetExpression left = expression.getLeft(); 1205 if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { 1206 generateInstructions(left); 1207 if (getBoundOrUnreachableValue(left) != null) { 1208 createNonSyntheticValue(expression, MagicKind.CAST, left); 1209 } 1210 } 1211 else { 1212 visitJetElement(expression); 1213 createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left); 1214 } 1215 } 1216 1217 @Override 1218 public void visitThrowExpression(@NotNull JetThrowExpression expression) { 1219 mark(expression); 1220 1221 JetExpression thrownExpression = expression.getThrownExpression(); 1222 if (thrownExpression == null) return; 1223 1224 generateInstructions(thrownExpression); 1225 1226 PseudoValue thrownValue = builder.getBoundValue(thrownExpression); 1227 if (thrownValue == null) return; 1228 1229 builder.throwException(expression, thrownValue); 1230 } 1231 1232 @Override 1233 public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) { 1234 generateArrayAccess(expression, trace.get(BindingContext.INDEXED_LVALUE_GET, expression)); 1235 } 1236 1237 @Override 1238 public void visitIsExpression(@NotNull JetIsExpression expression) { 1239 mark(expression); 1240 JetExpression left = expression.getLeftHandSide(); 1241 generateInstructions(left); 1242 createNonSyntheticValue(expression, MagicKind.IS, left); 1243 } 1244 1245 @Override 1246 public void visitWhenExpression(@NotNull JetWhenExpression expression) { 1247 mark(expression); 1248 1249 JetExpression subjectExpression = expression.getSubjectExpression(); 1250 if (subjectExpression != null) { 1251 generateInstructions(subjectExpression); 1252 } 1253 1254 List<JetExpression> branches = new ArrayList<JetExpression>(); 1255 1256 Label doneLabel = builder.createUnboundLabel("after 'when' expression"); 1257 1258 Label nextLabel = null; 1259 for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) { 1260 JetWhenEntry whenEntry = iterator.next(); 1261 mark(whenEntry); 1262 1263 boolean isElse = whenEntry.isElse(); 1264 if (isElse) { 1265 if (iterator.hasNext()) { 1266 trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry)); 1267 } 1268 } 1269 Label bodyLabel = builder.createUnboundLabel("'when' entry body"); 1270 1271 JetWhenCondition[] conditions = whenEntry.getConditions(); 1272 for (int i = 0; i < conditions.length; i++) { 1273 JetWhenCondition condition = conditions[i]; 1274 condition.accept(conditionVisitor); 1275 if (i + 1 < conditions.length) { 1276 builder.nondeterministicJump(bodyLabel, expression, builder.getBoundValue(condition)); 1277 } 1278 } 1279 1280 if (!isElse) { 1281 nextLabel = builder.createUnboundLabel("next 'when' entry"); 1282 JetWhenCondition lastCondition = KotlinPackage.lastOrNull(conditions); 1283 builder.nondeterministicJump(nextLabel, expression, builder.getBoundValue(lastCondition)); 1284 } 1285 1286 builder.bindLabel(bodyLabel); 1287 JetExpression whenEntryExpression = whenEntry.getExpression(); 1288 if (whenEntryExpression != null) { 1289 generateInstructions(whenEntryExpression); 1290 branches.add(whenEntryExpression); 1291 } 1292 builder.jump(doneLabel, expression); 1293 1294 if (!isElse) { 1295 builder.bindLabel(nextLabel); 1296 // For the last entry of exhaustive when, 1297 // attempt to jump further should lead to error, not to "done" 1298 if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) { 1299 builder.jumpToError(expression); 1300 } 1301 } 1302 } 1303 builder.bindLabel(doneLabel); 1304 1305 mergeValues(branches, expression); 1306 } 1307 1308 @Override 1309 public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) { 1310 mark(expression); 1311 JetObjectDeclaration declaration = expression.getObjectDeclaration(); 1312 generateInstructions(declaration); 1313 1314 builder.createAnonymousObject(expression); 1315 } 1316 1317 @Override 1318 public void visitObjectDeclaration(@NotNull JetObjectDeclaration objectDeclaration) { 1319 generateHeaderDelegationSpecifiers(objectDeclaration); 1320 generateClassOrObjectInitializers(objectDeclaration); 1321 generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration); 1322 } 1323 1324 @Override 1325 public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) { 1326 mark(expression); 1327 1328 List<JetExpression> inputExpressions = new ArrayList<JetExpression>(); 1329 for (JetStringTemplateEntry entry : expression.getEntries()) { 1330 if (entry instanceof JetStringTemplateEntryWithExpression) { 1331 JetExpression entryExpression = entry.getExpression(); 1332 generateInstructions(entryExpression); 1333 inputExpressions.add(entryExpression); 1334 } 1335 } 1336 builder.loadStringTemplate(expression, elementsToValues(inputExpressions)); 1337 } 1338 1339 @Override 1340 public void visitTypeProjection(@NotNull JetTypeProjection typeProjection) { 1341 // TODO : Support Type Arguments. Companion object may be initialized at this point"); 1342 } 1343 1344 @Override 1345 public void visitAnonymousInitializer(@NotNull JetClassInitializer classInitializer) { 1346 generateInstructions(classInitializer.getBody()); 1347 } 1348 1349 private void generateHeaderDelegationSpecifiers(@NotNull JetClassOrObject classOrObject) { 1350 for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) { 1351 generateInstructions(specifier); 1352 } 1353 } 1354 1355 private void generateClassOrObjectInitializers(@NotNull JetClassOrObject classOrObject) { 1356 for (JetDeclaration declaration : classOrObject.getDeclarations()) { 1357 if (declaration instanceof JetProperty || declaration instanceof JetClassInitializer) { 1358 generateInstructions(declaration); 1359 } 1360 } 1361 } 1362 1363 @Override 1364 public void visitClass(@NotNull JetClass klass) { 1365 if (klass.hasPrimaryConstructor()) { 1366 processParameters(klass.getPrimaryConstructorParameters()); 1367 1368 // delegation specifiers of primary constructor, anonymous class and property initializers 1369 generateHeaderDelegationSpecifiers(klass); 1370 generateClassOrObjectInitializers(klass); 1371 } 1372 1373 generateDeclarationForLocalClassOrObjectIfNeeded(klass); 1374 } 1375 1376 private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull JetClassOrObject classOrObject) { 1377 if (classOrObject.isLocal()) { 1378 for (JetDeclaration declaration : classOrObject.getDeclarations()) { 1379 if (declaration instanceof JetSecondaryConstructor || 1380 declaration instanceof JetProperty || 1381 declaration instanceof JetClassInitializer) { 1382 continue; 1383 } 1384 generateInstructions(declaration); 1385 } 1386 } 1387 } 1388 1389 private void processParameters(@NotNull List<JetParameter> parameters) { 1390 for (JetParameter parameter : parameters) { 1391 generateInstructions(parameter); 1392 } 1393 } 1394 1395 @Override 1396 public void visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor) { 1397 JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(constructor, JetClassOrObject.class); 1398 assert classOrObject != null : "Guaranteed by parsing contract"; 1399 1400 processParameters(constructor.getValueParameters()); 1401 generateCallOrMarkUnresolved(constructor.getDelegationCall()); 1402 1403 if (!constructor.getDelegationCall().isCallToThis()) { 1404 generateClassOrObjectInitializers(classOrObject); 1405 } 1406 1407 generateInstructions(constructor.getBodyExpression()); 1408 } 1409 1410 @Override 1411 public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) { 1412 generateCallOrMarkUnresolved(call); 1413 } 1414 1415 private void generateCallOrMarkUnresolved(@Nullable JetCallElement call) { 1416 if (call == null) return; 1417 if (!generateCall(call)) { 1418 List<JetExpression> arguments = KotlinPackage.map( 1419 call.getValueArguments(), 1420 new Function1<ValueArgument, JetExpression>() { 1421 @Override 1422 public JetExpression invoke(ValueArgument valueArgument) { 1423 return valueArgument.getArgumentExpression(); 1424 } 1425 } 1426 ); 1427 1428 for (JetExpression argument : arguments) { 1429 generateInstructions(argument); 1430 } 1431 createNonSyntheticValue(call, arguments, MagicKind.UNRESOLVED_CALL); 1432 } 1433 } 1434 1435 @Override 1436 public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) { 1437 JetExpression delegateExpression = specifier.getDelegateExpression(); 1438 generateInstructions(delegateExpression); 1439 createSyntheticValue(specifier, MagicKind.VALUE_CONSUMER, delegateExpression); 1440 } 1441 1442 @Override 1443 public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) { 1444 // Do not generate UNSUPPORTED_ELEMENT here 1445 } 1446 1447 @Override 1448 public void visitDelegationSpecifierList(@NotNull JetDelegationSpecifierList list) { 1449 list.acceptChildren(this); 1450 } 1451 1452 @Override 1453 public void visitJetFile(@NotNull JetFile file) { 1454 for (JetDeclaration declaration : file.getDeclarations()) { 1455 if (declaration instanceof JetProperty) { 1456 generateInstructions(declaration); 1457 } 1458 } 1459 } 1460 1461 @Override 1462 public void visitDoubleColonExpression(@NotNull JetDoubleColonExpression expression) { 1463 mark(expression); 1464 createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE); 1465 } 1466 1467 @Override 1468 public void visitJetElement(@NotNull JetElement element) { 1469 createNonSyntheticValue(element, MagicKind.UNSUPPORTED_ELEMENT); 1470 } 1471 1472 private boolean generateCall(@Nullable JetElement callElement) { 1473 if (callElement == null) return false; 1474 return checkAndGenerateCall(getResolvedCall(callElement, trace.getBindingContext())); 1475 } 1476 1477 private boolean checkAndGenerateCall(@Nullable ResolvedCall<?> resolvedCall) { 1478 if (resolvedCall == null) return false; 1479 generateCall(resolvedCall); 1480 return true; 1481 } 1482 1483 @NotNull 1484 private InstructionWithValue generateCall(@NotNull ResolvedCall<?> resolvedCall) { 1485 JetElement callElement = resolvedCall.getCall().getCallElement(); 1486 1487 Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall); 1488 1489 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap(); 1490 for (ValueArgument argument : resolvedCall.getCall().getValueArguments()) { 1491 ArgumentMapping argumentMapping = resolvedCall.getArgumentMapping(argument); 1492 JetExpression argumentExpression = argument.getArgumentExpression(); 1493 if (argumentMapping instanceof ArgumentMatch) { 1494 parameterValues = generateValueArgument(argument, ((ArgumentMatch) argumentMapping).getValueParameter(), parameterValues); 1495 } 1496 else if (argumentExpression != null) { 1497 generateInstructions(argumentExpression); 1498 createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression); 1499 } 1500 } 1501 1502 if (resolvedCall.getResultingDescriptor() instanceof VariableDescriptor) { 1503 // If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated. 1504 // todo : process arguments for such a case (KT-5387) 1505 JetExpression callExpression = callElement instanceof JetExpression ? (JetExpression) callElement : null; 1506 assert callExpression != null 1507 : "Variable-based call without callee expression: " + callElement.getText(); 1508 assert parameterValues.isEmpty() 1509 : "Variable-based call with non-empty argument list: " + callElement.getText(); 1510 return builder.readVariable(callExpression, resolvedCall, receivers); 1511 } 1512 1513 mark(resolvedCall.getCall().getCallElement()); 1514 return builder.call(callElement, resolvedCall, receivers, parameterValues); 1515 } 1516 1517 @NotNull 1518 private Map<PseudoValue, ReceiverValue> getReceiverValues(ResolvedCall<?> resolvedCall) { 1519 PseudoValue varCallResult = null; 1520 ReceiverValue explicitReceiver = ReceiverValue.NO_RECEIVER; 1521 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1522 varCallResult = generateCall(((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall()).getOutputValue(); 1523 1524 ExplicitReceiverKind kind = resolvedCall.getExplicitReceiverKind(); 1525 //noinspection EnumSwitchStatementWhichMissesCases 1526 switch (kind) { 1527 case DISPATCH_RECEIVER: 1528 explicitReceiver = resolvedCall.getDispatchReceiver(); 1529 break; 1530 case EXTENSION_RECEIVER: 1531 case BOTH_RECEIVERS: 1532 explicitReceiver = resolvedCall.getExtensionReceiver(); 1533 break; 1534 } 1535 } 1536 1537 SmartFMap<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap(); 1538 if (explicitReceiver.exists() && varCallResult != null) { 1539 receiverValues = receiverValues.plus(varCallResult, explicitReceiver); 1540 } 1541 JetElement callElement = resolvedCall.getCall().getCallElement(); 1542 receiverValues = getReceiverValues(callElement, resolvedCall.getDispatchReceiver(), receiverValues); 1543 receiverValues = getReceiverValues(callElement, resolvedCall.getExtensionReceiver(), receiverValues); 1544 return receiverValues; 1545 } 1546 1547 @NotNull 1548 private SmartFMap<PseudoValue, ReceiverValue> getReceiverValues( 1549 JetElement callElement, 1550 ReceiverValue receiver, 1551 SmartFMap<PseudoValue, ReceiverValue> receiverValues 1552 ) { 1553 if (!receiver.exists() || receiverValues.containsValue(receiver)) return receiverValues; 1554 1555 if (receiver instanceof ThisReceiver) { 1556 receiverValues = receiverValues.plus(createSyntheticValue(callElement, MagicKind.IMPLICIT_RECEIVER), receiver); 1557 } 1558 else if (receiver instanceof ExpressionReceiver) { 1559 JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); 1560 if (builder.getBoundValue(expression) == null) { 1561 generateInstructions(expression); 1562 } 1563 1564 PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression); 1565 if (receiverPseudoValue != null) { 1566 receiverValues = receiverValues.plus(receiverPseudoValue, receiver); 1567 } 1568 } 1569 else if (receiver instanceof TransientReceiver) { 1570 // Do nothing 1571 } 1572 else { 1573 throw new IllegalArgumentException("Unknown receiver kind: " + receiver); 1574 } 1575 1576 return receiverValues; 1577 } 1578 1579 @NotNull 1580 private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument( 1581 ValueArgument valueArgument, 1582 ValueParameterDescriptor parameterDescriptor, 1583 SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues) { 1584 JetExpression expression = valueArgument.getArgumentExpression(); 1585 if (expression != null) { 1586 if (!valueArgument.isExternal()) { 1587 generateInstructions(expression); 1588 } 1589 1590 PseudoValue argValue = getBoundOrUnreachableValue(expression); 1591 if (argValue != null) { 1592 parameterValues = parameterValues.plus(argValue, parameterDescriptor); 1593 } 1594 } 1595 return parameterValues; 1596 } 1597 } 1598 }