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 017package org.jetbrains.jet.lang.cfg; 018 019import com.google.common.collect.Lists; 020import com.intellij.psi.PsiElement; 021import com.intellij.psi.tree.IElementType; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.annotations.Nullable; 024import org.jetbrains.jet.JetNodeTypes; 025import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator; 026import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction; 027import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; 028import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; 029import org.jetbrains.jet.lang.psi.*; 030import org.jetbrains.jet.lang.resolve.BindingContext; 031import org.jetbrains.jet.lang.resolve.BindingContextUtils; 032import org.jetbrains.jet.lang.resolve.BindingTrace; 033import org.jetbrains.jet.lang.resolve.constants.BooleanValue; 034import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; 035import org.jetbrains.jet.lang.types.JetType; 036import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 037import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 038import org.jetbrains.jet.lexer.JetTokens; 039 040import java.util.Collection; 041import java.util.Iterator; 042import java.util.LinkedList; 043import java.util.List; 044 045import static org.jetbrains.jet.lang.diagnostics.Errors.*; 046 047public class JetControlFlowProcessor { 048 049 private final JetControlFlowBuilder builder; 050 private final BindingTrace trace; 051 052 public JetControlFlowProcessor(BindingTrace trace) { 053 this.builder = new JetControlFlowInstructionsGenerator(); 054 this.trace = trace; 055 } 056 057 public Pseudocode generatePseudocode(@NotNull JetElement subroutine) { 058 Pseudocode pseudocode = generate(subroutine); 059 ((PseudocodeImpl) pseudocode).postProcess(); 060 for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { 061 ((PseudocodeImpl)localDeclarationInstruction.getBody()).postProcess(); 062 } 063 return pseudocode; 064 } 065 066 private Pseudocode generate(@NotNull JetElement subroutine) { 067 builder.enterSubroutine(subroutine); 068 CFPVisitor cfpVisitor = new CFPVisitor(false); 069 if (subroutine instanceof JetDeclarationWithBody) { 070 JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; 071 List<JetParameter> valueParameters = declarationWithBody.getValueParameters(); 072 for (JetParameter valueParameter : valueParameters) { 073 valueParameter.accept(cfpVisitor); 074 } 075 JetExpression bodyExpression = declarationWithBody.getBodyExpression(); 076 if (bodyExpression != null) { 077 bodyExpression.accept(cfpVisitor); 078 } 079 } else { 080 subroutine.accept(cfpVisitor); 081 } 082 return builder.exitSubroutine(subroutine); 083 } 084 085 private void processLocalDeclaration(@NotNull JetDeclaration subroutine) { 086 Label afterDeclaration = builder.createUnboundLabel(); 087 builder.nondeterministicJump(afterDeclaration); 088 generate(subroutine); 089 builder.bindLabel(afterDeclaration); 090 } 091 092 093 private class CFPVisitor extends JetVisitorVoid { 094 private final boolean inCondition; 095 private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() { 096 097 @Override 098 public void visitWhenConditionInRange(JetWhenConditionInRange condition) { 099 generateInstructions(condition.getRangeExpression(), CFPVisitor.this.inCondition); // TODO : inCondition? 100 generateInstructions(condition.getOperationReference(), CFPVisitor.this.inCondition); // TODO : inCondition? 101 // TODO : read the call to contains()... 102 } 103 104 @Override 105 public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { 106 // TODO: types in CF? 107 } 108 109 @Override 110 public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) { 111 generateInstructions(condition.getExpression(), inCondition); 112 } 113 114 @Override 115 public void visitJetElement(JetElement element) { 116 throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); 117 } 118 }; 119 private final JetVisitorVoid patternVisitor = new JetVisitorVoid() { 120 121 @Override 122 public void visitJetElement(JetElement element) { 123 throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); 124 } 125 }; 126 127 private CFPVisitor(boolean inCondition) { 128 this.inCondition = inCondition; 129 } 130 131 private void generateInstructions(@Nullable JetElement element, boolean inCondition) { 132 if (element == null) return; 133 CFPVisitor visitor; 134 if (this.inCondition == inCondition) { 135 visitor = this; 136 } 137 else { 138 visitor = new CFPVisitor(inCondition); 139 } 140 element.accept(visitor); 141 } 142 143 @Override 144 public void visitParenthesizedExpression(JetParenthesizedExpression expression) { 145 builder.read(expression); 146 147 JetExpression innerExpression = expression.getExpression(); 148 if (innerExpression != null) { 149 generateInstructions(innerExpression, inCondition); 150 } 151 } 152 153 @Override 154 public void visitThisExpression(JetThisExpression expression) { 155 builder.read(expression); 156 } 157 158 @Override 159 public void visitConstantExpression(JetConstantExpression expression) { 160 builder.read(expression); 161 } 162 163 @Override 164 public void visitSimpleNameExpression(JetSimpleNameExpression expression) { 165 builder.read(expression); 166 if (trace.get(BindingContext.PROCESSED, expression)) { 167 JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 168 if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) { 169 builder.jumpToError(); 170 } 171 } 172 } 173 174 @Override 175 public void visitLabelQualifiedExpression(JetLabelQualifiedExpression expression) { 176 String labelName = expression.getLabelName(); 177 JetExpression labeledExpression = expression.getLabeledExpression(); 178 if (labelName != null && labeledExpression != null) { 179 visitLabeledExpression(labelName, labeledExpression); 180 } 181 } 182 183 private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) { 184 JetExpression deparenthesized = JetPsiUtil.deparenthesizeWithNoTypeResolution(labeledExpression); 185 if (deparenthesized != null) { 186 generateInstructions(labeledExpression, inCondition); 187 } 188 } 189 190 @SuppressWarnings("SuspiciousMethodCalls") @Override 191 public void visitBinaryExpression(JetBinaryExpression expression) { 192 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 193 JetExpression right = expression.getRight(); 194 if (operationType == JetTokens.ANDAND) { 195 generateInstructions(expression.getLeft(), true); 196 Label resultLabel = builder.createUnboundLabel(); 197 builder.jumpOnFalse(resultLabel); 198 if (right != null) { 199 generateInstructions(right, true); 200 } 201 builder.bindLabel(resultLabel); 202 if (!inCondition) { 203 builder.read(expression); 204 } 205 } 206 else if (operationType == JetTokens.OROR) { 207 generateInstructions(expression.getLeft(), true); 208 Label resultLabel = builder.createUnboundLabel(); 209 builder.jumpOnTrue(resultLabel); 210 if (right != null) { 211 generateInstructions(right, true); 212 } 213 builder.bindLabel(resultLabel); 214 if (!inCondition) { 215 builder.read(expression); 216 } 217 } 218 else if (operationType == JetTokens.EQ) { 219 JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft()); 220 if (right != null) { 221 generateInstructions(right, false); 222 } 223 if (left instanceof JetSimpleNameExpression) { 224 builder.write(expression, left); 225 } 226 else if (left instanceof JetArrayAccessExpression) { 227 JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left; 228 visitAssignToArrayAccess(expression, arrayAccessExpression); 229 } 230 else if (left instanceof JetQualifiedExpression) { 231 JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) left; 232 generateInstructions(qualifiedExpression.getReceiverExpression(), false); 233 generateInstructions(expression.getOperationReference(), false); 234 builder.write(expression, left); 235 } 236 else { 237 builder.unsupported(expression); // TODO 238 } 239 } 240 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { 241 JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft()); 242 if (left != null) { 243 generateInstructions(left, false); 244 } 245 if (right != null) { 246 generateInstructions(right, false); 247 } 248 if (left instanceof JetSimpleNameExpression || left instanceof JetArrayAccessExpression) { 249 generateInstructions(expression.getOperationReference(), false); 250 builder.write(expression, left); 251 } 252 else if (left != null) { 253 builder.unsupported(expression); // TODO 254 } 255 } 256 else if (operationType == JetTokens.ELVIS) { 257 builder.read(expression); 258 generateInstructions(expression.getLeft(), false); 259 generateInstructions(expression.getOperationReference(), false); 260 Label afterElvis = builder.createUnboundLabel(); 261 builder.jumpOnTrue(afterElvis); 262 if (right != null) { 263 generateInstructions(right, false); 264 } 265 builder.bindLabel(afterElvis); 266 } 267 else { 268 generateInstructions(expression.getLeft(), false); 269 if (right != null) { 270 generateInstructions(right, false); 271 } 272 generateInstructions(expression.getOperationReference(), false); 273 builder.read(expression); 274 } 275 } 276 277 private void visitAssignToArrayAccess(JetBinaryExpression expression, JetArrayAccessExpression arrayAccessExpression) { 278 for (JetExpression index : arrayAccessExpression.getIndexExpressions()) { 279 generateInstructions(index, false); 280 } 281 generateInstructions(arrayAccessExpression.getArrayExpression(), false); 282 generateInstructions(expression.getOperationReference(), false); 283 builder.write(expression, arrayAccessExpression); // TODO : ??? 284 } 285 286 @Override 287 public void visitUnaryExpression(JetUnaryExpression expression) { 288 JetSimpleNameExpression operationSign = expression.getOperationReference(); 289 IElementType operationType = operationSign.getReferencedNameElementType(); 290 JetExpression baseExpression = expression.getBaseExpression(); 291 if (baseExpression == null) return; 292 if (JetTokens.LABELS.contains(operationType)) { 293 String referencedName = operationSign.getReferencedName(); 294 visitLabeledExpression(referencedName.substring(1), baseExpression); 295 } 296 else { 297 generateInstructions(baseExpression, false); 298 generateInstructions(operationSign, false); 299 300 boolean incrementOrDecrement = isIncrementOrDecrement(operationType); 301 if (incrementOrDecrement) { 302 builder.write(expression, baseExpression); 303 } 304 305 builder.read(expression); 306 } 307 } 308 309 private boolean isIncrementOrDecrement(IElementType operationType) { 310 return operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS; 311 } 312 313 314 @Override 315 public void visitIfExpression(JetIfExpression expression) { 316 JetExpression condition = expression.getCondition(); 317 if (condition != null) { 318 generateInstructions(condition, true); 319 } 320 Label elseLabel = builder.createUnboundLabel(); 321 builder.jumpOnFalse(elseLabel); 322 JetExpression thenBranch = expression.getThen(); 323 if (thenBranch != null) { 324 generateInstructions(thenBranch, inCondition); 325 } 326 else { 327 builder.readUnit(expression); 328 } 329 Label resultLabel = builder.createUnboundLabel(); 330 builder.jump(resultLabel); 331 builder.bindLabel(elseLabel); 332 JetExpression elseBranch = expression.getElse(); 333 if (elseBranch != null) { 334 generateInstructions(elseBranch, inCondition); 335 } 336 else { 337 builder.readUnit(expression); 338 } 339 builder.bindLabel(resultLabel); 340 } 341 342 private class FinallyBlockGenerator { 343 private final JetFinallySection finallyBlock; 344 private Label startFinally = null; 345 private Label finishFinally = null; 346 347 private FinallyBlockGenerator(JetFinallySection block) { 348 finallyBlock = block; 349 } 350 351 public void generate() { 352 JetBlockExpression finalExpression = finallyBlock.getFinalExpression(); 353 if (finalExpression == null) return; 354 if (startFinally != null) { 355 assert finishFinally != null; 356 builder.repeatPseudocode(startFinally, finishFinally); 357 return; 358 } 359 startFinally = builder.createUnboundLabel("start finally"); 360 builder.bindLabel(startFinally); 361 generateInstructions(finalExpression, inCondition); 362 finishFinally = builder.createUnboundLabel("finish finally"); 363 builder.bindLabel(finishFinally); 364 } 365 } 366 367 368 @Override 369 public void visitTryExpression(JetTryExpression expression) { 370 builder.read(expression); 371 JetFinallySection finallyBlock = expression.getFinallyBlock(); 372 final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock); 373 if (finallyBlock != null) { 374 builder.enterTryFinally(new GenerationTrigger() { 375 private boolean working = false; 376 377 @Override 378 public void generate() { 379 // This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}' 380 if (working) return; 381 working = true; 382 finallyBlockGenerator.generate(); 383 working = false; 384 } 385 }); 386 } 387 388 List<JetCatchClause> catchClauses = expression.getCatchClauses(); 389 boolean hasCatches = !catchClauses.isEmpty(); 390 Label onException = null; 391 if (hasCatches) { 392 onException = builder.createUnboundLabel("onException"); 393 builder.nondeterministicJump(onException); 394 } 395 Label onExceptionToFinallyBlock = null; 396 if (finallyBlock != null) { 397 onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock"); 398 builder.nondeterministicJump(onExceptionToFinallyBlock); 399 } 400 generateInstructions(expression.getTryBlock(), inCondition); 401 402 Collection<Label> allowDeadLabels = Lists.newArrayList(); 403 if (hasCatches) { 404 Label afterCatches = builder.createUnboundLabel("afterCatches"); 405 builder.jump(afterCatches); 406 407 builder.bindLabel(onException); 408 LinkedList<Label> catchLabels = Lists.newLinkedList(); 409 int catchClausesSize = catchClauses.size(); 410 for (int i = 0; i < catchClausesSize - 1; i++) { 411 catchLabels.add(builder.createUnboundLabel("catch " + i)); 412 } 413 if (!catchLabels.isEmpty()) { 414 builder.nondeterministicJump(catchLabels); 415 } 416 boolean isFirst = true; 417 for (JetCatchClause catchClause : catchClauses) { 418 if (!isFirst) { 419 builder.bindLabel(catchLabels.remove()); 420 } 421 else { 422 isFirst = false; 423 } 424 JetParameter catchParameter = catchClause.getCatchParameter(); 425 if (catchParameter != null) { 426 builder.declare(catchParameter); 427 builder.write(catchParameter, catchParameter); 428 } 429 JetExpression catchBody = catchClause.getCatchBody(); 430 if (catchBody != null) { 431 generateInstructions(catchBody, false); 432 } 433 builder.jump(afterCatches); 434 } 435 436 builder.bindLabel(afterCatches); 437 } 438 439 if (finallyBlock != null) { 440 builder.exitTryFinally(); 441 442 Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock"); 443 builder.jump(skipFinallyToErrorBlock); 444 builder.bindLabel(onExceptionToFinallyBlock); 445 finallyBlockGenerator.generate(); 446 builder.jumpToError(); 447 builder.bindLabel(skipFinallyToErrorBlock); 448 449 finallyBlockGenerator.generate(); 450 } 451 } 452 453 @Override 454 public void visitWhileExpression(JetWhileExpression expression) { 455 builder.read(expression); 456 LoopInfo loopInfo = builder.enterLoop(expression, null, null); 457 458 builder.bindLabel(loopInfo.getConditionEntryPoint()); 459 JetExpression condition = expression.getCondition(); 460 if (condition != null) { 461 generateInstructions(condition, true); 462 } 463 boolean conditionIsTrueConstant = false; 464 if (condition instanceof JetConstantExpression && condition.getNode().getElementType() == JetNodeTypes.BOOLEAN_CONSTANT) { 465 if (BooleanValue.TRUE == new CompileTimeConstantResolver().getBooleanValue(condition.getText(), KotlinBuiltIns.getInstance().getBooleanType())) { 466 conditionIsTrueConstant = true; 467 } 468 } 469 if (!conditionIsTrueConstant) { 470 builder.jumpOnFalse(loopInfo.getExitPoint()); 471 } 472 473 builder.bindLabel(loopInfo.getBodyEntryPoint()); 474 JetExpression body = expression.getBody(); 475 if (body != null) { 476 generateInstructions(body, false); 477 } 478 builder.jump(loopInfo.getEntryPoint()); 479 builder.exitLoop(expression); 480 builder.readUnit(expression); 481 } 482 483 @Override 484 public void visitDoWhileExpression(JetDoWhileExpression expression) { 485 builder.read(expression); 486 LoopInfo loopInfo = builder.enterLoop(expression, null, null); 487 488 builder.bindLabel(loopInfo.getBodyEntryPoint()); 489 JetExpression body = expression.getBody(); 490 if (body != null) { 491 generateInstructions(body, false); 492 } 493 builder.bindLabel(loopInfo.getConditionEntryPoint()); 494 JetExpression condition = expression.getCondition(); 495 if (condition != null) { 496 generateInstructions(condition, true); 497 } 498 builder.jumpOnTrue(loopInfo.getEntryPoint()); 499 builder.exitLoop(expression); 500 builder.readUnit(expression); 501 } 502 503 @Override 504 public void visitForExpression(JetForExpression expression) { 505 builder.read(expression); 506 JetExpression loopRange = expression.getLoopRange(); 507 if (loopRange != null) { 508 generateInstructions(loopRange, false); 509 } 510 JetParameter loopParameter = expression.getLoopParameter(); 511 if (loopParameter != null) { 512 generateInstructions(loopParameter, inCondition); 513 } 514 else { 515 JetMultiDeclaration multiParameter = expression.getMultiParameter(); 516 generateInstructions(multiParameter, inCondition); 517 } 518 519 // TODO : primitive cases 520 Label loopExitPoint = builder.createUnboundLabel(); 521 Label conditionEntryPoint = builder.createUnboundLabel(); 522 523 builder.bindLabel(conditionEntryPoint); 524 builder.nondeterministicJump(loopExitPoint); 525 526 LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint); 527 528 builder.bindLabel(loopInfo.getBodyEntryPoint()); 529 JetExpression body = expression.getBody(); 530 if (body != null) { 531 generateInstructions(body, false); 532 } 533 534 builder.nondeterministicJump(loopInfo.getEntryPoint()); 535 builder.exitLoop(expression); 536 builder.readUnit(expression); 537 } 538 539 @Override 540 public void visitBreakExpression(JetBreakExpression expression) { 541 JetElement loop = getCorrespondingLoop(expression); 542 if (loop != null) { 543 builder.jump(builder.getExitPoint(loop)); 544 } 545 } 546 547 @Override 548 public void visitContinueExpression(JetContinueExpression expression) { 549 JetElement loop = getCorrespondingLoop(expression); 550 if (loop != null) { 551 builder.jump(builder.getEntryPoint(loop)); 552 } 553 } 554 555 private JetElement getCorrespondingLoop(JetLabelQualifiedExpression expression) { 556 String labelName = expression.getLabelName(); 557 JetElement loop; 558 if (labelName != null) { 559 JetSimpleNameExpression targetLabel = expression.getTargetLabel(); 560 assert targetLabel != null; 561 PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), targetLabel); 562 if (labeledElement instanceof JetLoopExpression) { 563 loop = (JetLoopExpression) labeledElement; 564 } 565 else { 566 trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); 567 loop = null; 568 } 569 } 570 else { 571 loop = builder.getCurrentLoop(); 572 if (loop == null) { 573 trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); 574 } 575 } 576 return loop; 577 } 578 579 @Override 580 public void visitReturnExpression(JetReturnExpression expression) { 581 JetExpression returnedExpression = expression.getReturnedExpression(); 582 if (returnedExpression != null) { 583 generateInstructions(returnedExpression, false); 584 } 585 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 586 JetElement subroutine; 587 String labelName = expression.getLabelName(); 588 if (labelElement != null) { 589 assert labelName != null; 590 PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), labelElement); 591 if (labeledElement != null) { 592 assert labeledElement instanceof JetElement; 593 subroutine = (JetElement) labeledElement; 594 } 595 else { 596 subroutine = null; 597 } 598 } 599 else { 600 subroutine = builder.getReturnSubroutine(); 601 // TODO : a context check 602 } 603 604 if (subroutine instanceof JetFunction || subroutine instanceof JetPropertyAccessor) { 605 if (returnedExpression == null) { 606 builder.returnNoValue(expression, subroutine); 607 } 608 else { 609 builder.returnValue(expression, subroutine); 610 } 611 } 612 } 613 614 @Override 615 public void visitParameter(JetParameter parameter) { 616 builder.declare(parameter); 617 JetExpression defaultValue = parameter.getDefaultValue(); 618 if (defaultValue != null) { 619 generateInstructions(defaultValue, inCondition); 620 } 621 builder.write(parameter, parameter); 622 } 623 624 @Override 625 public void visitBlockExpression(JetBlockExpression expression) { 626 List<JetElement> statements = expression.getStatements(); 627 for (JetElement statement : statements) { 628 generateInstructions(statement, false); 629 } 630 if (statements.isEmpty()) { 631 builder.readUnit(expression); 632 } 633 } 634 635 @Override 636 public void visitNamedFunction(JetNamedFunction function) { 637 processLocalDeclaration(function); 638 } 639 640 @Override 641 public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { 642 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); 643 processLocalDeclaration(functionLiteral); 644 builder.read(expression); 645 } 646 647 @Override 648 public void visitQualifiedExpression(JetQualifiedExpression expression) { 649 generateInstructions(expression.getReceiverExpression(), false); 650 JetExpression selectorExpression = expression.getSelectorExpression(); 651 if (selectorExpression != null) { 652 generateInstructions(selectorExpression, false); 653 } 654 builder.read(expression); 655 if (trace.get(BindingContext.PROCESSED, expression)) { 656 JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 657 if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) { 658 builder.jumpToError(); 659 } 660 } 661 } 662 663 private void visitCall(JetCallElement call) { 664 for (ValueArgument argument : call.getValueArguments()) { 665 JetExpression argumentExpression = argument.getArgumentExpression(); 666 if (argumentExpression != null) { 667 generateInstructions(argumentExpression, false); 668 } 669 } 670 671 for (JetExpression functionLiteral : call.getFunctionLiteralArguments()) { 672 generateInstructions(functionLiteral, false); 673 } 674 } 675 676 @Override 677 public void visitCallExpression(JetCallExpression expression) { 678 //inline functions after M1 679// ResolvedCall<? extends CallableDescriptor> resolvedCall = trace.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); 680// assert resolvedCall != null; 681// CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); 682// PsiElement element = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, resultingDescriptor); 683// if (element instanceof JetNamedFunction) { 684// JetNamedFunction namedFunction = (JetNamedFunction) element; 685// if (namedFunction.hasModifier(JetTokens.INLINE_KEYWORD)) { 686// } 687// } 688 689 for (JetTypeProjection typeArgument : expression.getTypeArguments()) { 690 generateInstructions(typeArgument, false); 691 } 692 693 visitCall(expression); 694 695 generateInstructions(expression.getCalleeExpression(), false); 696 builder.read(expression); 697 if (trace.get(BindingContext.PROCESSED, expression)) { 698 JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); 699 if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) { 700 builder.jumpToError(); 701 } 702 } 703 } 704 705// @Override 706// public void visitNewExpression(JetNewExpression expression) { 707// // TODO : Instantiated class is loaded 708// // TODO : type arguments? 709// visitCall(expression); 710// builder.read(expression); 711// } 712 713 @Override 714 public void visitProperty(JetProperty property) { 715 builder.declare(property); 716 JetExpression initializer = property.getInitializer(); 717 if (initializer != null) { 718 generateInstructions(initializer, false); 719 builder.write(property, property); 720 } 721 JetExpression delegate = property.getDelegateExpression(); 722 if (delegate != null) { 723 generateInstructions(delegate, false); 724 } 725 for (JetPropertyAccessor accessor : property.getAccessors()) { 726 generateInstructions(accessor, false); 727 } 728 } 729 730 @Override 731 public void visitMultiDeclaration(JetMultiDeclaration declaration) { 732 JetExpression initializer = declaration.getInitializer(); 733 if (initializer != null) { 734 generateInstructions(initializer, false); 735 } 736 List<JetMultiDeclarationEntry> entries = declaration.getEntries(); 737 for (JetMultiDeclarationEntry entry : entries) { 738 builder.declare(entry); 739 builder.write(entry, entry); 740 } 741 } 742 743 @Override 744 public void visitPropertyAccessor(JetPropertyAccessor accessor) { 745 processLocalDeclaration(accessor); 746 } 747 748 @Override 749 public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { 750 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 751 if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { 752 generateInstructions(expression.getLeft(), false); 753 builder.read(expression); 754 } 755 else { 756 visitJetElement(expression); 757 } 758 } 759 760 @Override 761 public void visitThrowExpression(JetThrowExpression expression) { 762 JetExpression thrownExpression = expression.getThrownExpression(); 763 if (thrownExpression != null) { 764 generateInstructions(thrownExpression, false); 765 } 766 builder.throwException(expression); 767 } 768 769 @Override 770 public void visitArrayAccessExpression(JetArrayAccessExpression expression) { 771 for (JetExpression index : expression.getIndexExpressions()) { 772 generateInstructions(index, false); 773 } 774 generateInstructions(expression.getArrayExpression(), false); 775 // TODO : read 'get' or 'set' function 776 builder.read(expression); 777 } 778 779 @Override 780 public void visitIsExpression(JetIsExpression expression) { 781 generateInstructions(expression.getLeftHandSide(), inCondition); 782 // no CF for types 783 // TODO : builder.read(expression.getPattern()); 784 builder.read(expression); 785 } 786 787 @Override 788 public void visitWhenExpression(JetWhenExpression expression) { 789 JetExpression subjectExpression = expression.getSubjectExpression(); 790 if (subjectExpression != null) { 791 generateInstructions(subjectExpression, inCondition); 792 } 793 boolean hasElseOrIrrefutableBranch = false; 794 795 Label doneLabel = builder.createUnboundLabel(); 796 797 Label nextLabel = null; 798 Collection<Label> allowDeadLabels = Lists.newArrayList(); 799 for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) { 800 JetWhenEntry whenEntry = iterator.next(); 801 802 builder.read(whenEntry); 803 804 if (whenEntry.isElse()) { 805 hasElseOrIrrefutableBranch = true; 806 if (iterator.hasNext()) { 807 trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry)); 808 } 809 } 810 boolean isIrrefutable = whenEntry.isElse(); 811 if (isIrrefutable) { 812 hasElseOrIrrefutableBranch = true; 813 } 814 815 Label bodyLabel = builder.createUnboundLabel(); 816 817 JetWhenCondition[] conditions = whenEntry.getConditions(); 818 for (int i = 0; i < conditions.length; i++) { 819 JetWhenCondition condition = conditions[i]; 820 condition.accept(conditionVisitor); 821 if (i + 1 < conditions.length) { 822 builder.nondeterministicJump(bodyLabel); 823 } 824 } 825 826 if (!isIrrefutable) { 827 nextLabel = builder.createUnboundLabel(); 828 builder.nondeterministicJump(nextLabel); 829 } 830 831 builder.bindLabel(bodyLabel); 832 generateInstructions(whenEntry.getExpression(), inCondition); 833 builder.jump(doneLabel); 834 835 if (!isIrrefutable) { 836 builder.bindLabel(nextLabel); 837 } 838 } 839 builder.bindLabel(doneLabel); 840 boolean isWhenExhaust = WhenChecker.isWhenExhaustive(expression, trace); 841 if (!hasElseOrIrrefutableBranch && !isWhenExhaust) { 842 trace.report(NO_ELSE_IN_WHEN.on(expression)); 843 } 844 } 845 846 @Override 847 public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { 848 JetObjectDeclaration declaration = expression.getObjectDeclaration(); 849 generateInstructions(declaration, inCondition); 850 851 List<JetDeclaration> declarations = declaration.getDeclarations(); 852 List<JetDeclaration> functions = Lists.newArrayList(); 853 for (JetDeclaration localDeclaration : declarations) { 854 if (!(localDeclaration instanceof JetProperty) && !(localDeclaration instanceof JetClassInitializer)) { 855 functions.add(localDeclaration); 856 } 857 } 858 for (JetDeclaration function : functions) { 859 generateInstructions(function, inCondition); 860 } 861 builder.read(expression); 862 } 863 864 @Override 865 public void visitObjectDeclaration(JetObjectDeclaration objectDeclaration) { 866 visitClassOrObject(objectDeclaration); 867 } 868 869 @Override 870 public void visitStringTemplateExpression(JetStringTemplateExpression expression) { 871 for (JetStringTemplateEntry entry : expression.getEntries()) { 872 if (entry instanceof JetStringTemplateEntryWithExpression) { 873 JetStringTemplateEntryWithExpression entryWithExpression = (JetStringTemplateEntryWithExpression) entry; 874 generateInstructions(entryWithExpression.getExpression(), false); 875 } 876 } 877 builder.read(expression); 878 } 879 880 @Override 881 public void visitTypeProjection(JetTypeProjection typeProjection) { 882 // TODO : Support Type Arguments. Class object may be initialized at this point"); 883 } 884 885 @Override 886 public void visitAnonymousInitializer(JetClassInitializer classInitializer) { 887 generateInstructions(classInitializer.getBody(), inCondition); 888 } 889 890 private void visitClassOrObject(JetClassOrObject classOrObject) { 891 for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) { 892 generateInstructions(specifier, inCondition); 893 } 894 List<JetDeclaration> declarations = classOrObject.getDeclarations(); 895 for (JetDeclaration declaration : declarations) { 896 if (declaration instanceof JetProperty || declaration instanceof JetClassInitializer) { 897 generateInstructions(declaration, inCondition); 898 } 899 } 900 } 901 902 @Override 903 public void visitClass(JetClass klass) { 904 List<JetParameter> parameters = klass.getPrimaryConstructorParameters(); 905 for (JetParameter parameter : parameters) { 906 generateInstructions(parameter, inCondition); 907 } 908 visitClassOrObject(klass); 909 } 910 911 @Override 912 public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { 913 List<? extends ValueArgument> valueArguments = call.getValueArguments(); 914 for (ValueArgument valueArgument : valueArguments) { 915 generateInstructions(valueArgument.getArgumentExpression(), inCondition); 916 } 917 } 918 919 @Override 920 public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { 921 generateInstructions(specifier.getDelegateExpression(), inCondition); 922 } 923 924 @Override 925 public void visitJetFile(JetFile file) { 926 for (JetDeclaration declaration : file.getDeclarations()) { 927 if (declaration instanceof JetProperty) { 928 generateInstructions(declaration, inCondition); 929 } 930 } 931 } 932 933 @Override 934 public void visitJetElement(JetElement element) { 935 builder.unsupported(element); 936 } 937 } 938}