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