1 28 29 package com.caucho.es.parser; 30 31 import com.caucho.es.ESBase; 32 import com.caucho.es.ESException; 33 import com.caucho.es.ESId; 34 import com.caucho.util.CharBuffer; 35 36 import java.util.ArrayList ; 37 import java.util.HashMap ; 38 39 42 class Block { 43 private static HashMap specialNames; 44 45 Function function; 46 private Block parent; 47 private Expr lastExpr; 48 boolean isDead; 49 private boolean hasStatementValue; 50 private Parser parser; 51 private boolean isLoop; 52 private boolean canExit; 53 private boolean hasDefault; 54 private int withDepth; 55 private ESId id; 56 private Expr mark; 57 58 private Object switchTop; 59 private Object top; 60 private int topMark; 61 62 63 private Block() 64 { 65 } 66 67 Block create() 68 throws ESException 69 { 70 evalExpr(); 71 72 Block block = new Block(); 73 74 block.function = function; 75 block.parent = this; 76 block.lastExpr = null; 77 block.isDead = false; 78 block.hasStatementValue = hasStatementValue; 79 block.parser = parser; 80 block.isLoop = false; 81 block.canExit = false; 82 block.withDepth = withDepth; 83 block.id = null; 84 block.mark = null; 85 block.switchTop = null; 86 block.top = null; 87 88 block.setTop(); 89 90 return block; 91 } 92 93 static Block create(Parser parser, Function function) 94 { 95 Block block = new Block(); 96 97 block.function = function; 98 block.parent = null; 99 block.lastExpr = null; 100 block.isDead = false; 101 block.hasStatementValue = function.needsStatementResults(); 102 block.parser = parser; 103 block.isLoop = false; 104 block.canExit = false; 105 block.withDepth = 0; 106 block.id = null; 107 108 block.top = null; 109 block.topMark = 0; 110 111 function.setVars(); 112 113 return block; 114 } 115 116 ClassLoader getClassLoader() 117 { 118 return parser.getClassLoader(); 119 } 120 121 void setTop() 122 { 123 top = function.getTop(); 124 if (top instanceof CharBuffer) { 125 CharBuffer cb = (CharBuffer) top; 126 topMark = cb.length(); 127 } 128 else 129 topMark = 0; 130 } 131 132 Block pop() 133 { 134 Block parent = this.parent; 135 function.setVars(); 136 free(); 137 138 return parent; 139 } 140 141 boolean isGlobal() 142 { 143 return function.isGlobal(); 144 } 145 146 int getDepth() 147 { 148 return withDepth; 149 } 150 151 boolean allowSpecial() 152 { 153 return parent == null; 154 } 155 156 String getFilename() 157 { 158 String filename = parser.lexer.getLastFilename(); 159 int p = filename.lastIndexOf('/'); 160 if (p > 0) 161 filename = filename.substring(p + 1); 162 p = filename.lastIndexOf('\\'); 163 if (p > 0) 164 filename = filename.substring(p + 1); 165 166 return filename; 167 } 168 169 int getLine() 170 { 171 int line = parser.lexer.getLastLine(); 172 173 return line; 174 } 175 176 void setLine(int line) 177 { 178 } 179 180 183 boolean hasVar(ESId name) 184 { 185 return function.hasVar(name) || specialNames.get(name) != null; 186 } 187 188 191 IdExpr newVar(ESId name) 192 { 193 return newVar(name, null); 194 } 195 196 IdExpr newVar(ESId name, Expr type) 197 { 198 if (withDepth > 0) 199 return new IdExpr(this, new Variable(this, name, type, false)); 200 201 IdExpr expr = function.newVar(this, name, type); 202 203 if (parent != null) 205 expr.getType(); 206 207 return expr; 208 } 209 210 213 void defVar(ESId name) 214 { 215 function.addVariable(this, name, null); 216 } 217 218 221 void defVar(ESId name, Expr type) 222 { 223 function.addVariable(this, name, type); 224 } 225 226 Expr newLiteral(ESBase value) 227 { 228 return new LiteralExpr(this, value); 229 } 230 231 Expr newRegexp(ESBase value, String flags) 232 throws ESException 233 { 234 return new RegexpExpr(this, value, flags); 235 } 236 237 Expr newThis() 238 { 239 return new SpecialExpr(this, SpecialExpr.THIS); 240 } 241 242 Expr newArray(Expr expr) 243 { 244 return new SpecialExpr(this, SpecialExpr.ARRAY, expr); 245 } 246 247 Expr hasNext(String iter) 248 { 249 return new SpecialExpr(this, SpecialExpr.HAS_NEXT, iter); 250 } 251 252 Expr newType(ESId name) 253 { 254 return TypeExpr.create(this, name); 255 } 256 257 void addExpr(Expr expr) 258 throws ESException 259 { 260 if (isDead) 261 throw error("Statement is unreachable."); 262 if (lastExpr != null) 263 lastExpr.exprStatement(function); 264 265 if (hasStatementValue && ! void.class.equals(expr.getJavaClass())) 266 lastExpr = expr; 267 else { 268 lastExpr = null; 269 expr.exprStatement(function); 270 } 271 } 272 273 Block startBlock() 274 throws ESException 275 { 276 evalExpr(); 277 function.println("{"); 278 return create(); 279 } 280 281 Block startBlock(ESId id) 282 throws ESException 283 { 284 if (findBlock(id) != null) 285 throw error("duplicate label `" + id + "'"); 286 287 evalExpr(); 288 Block block = create(); 289 block.id = id; 290 function.println(id + ": {"); 291 block.setTop(); 292 return block; 293 } 294 295 Block finishBlock() 296 throws ESException 297 { 298 evalExpr(); 299 function.println("}"); 300 this.id = null; 301 Block old = pop(); 302 if (isDead && ! canExit) 303 old.isDead = true; 304 305 return old; 306 } 307 308 void endBlock() 309 throws ESException 310 { 311 evalExpr(); 312 function.println("}"); 313 this.id = null; 314 } 315 316 void startIf(Expr expr, boolean isElse) 317 throws ESException 318 { 319 evalExpr(); 320 if (isElse) 321 function.print(" else "); 322 function.print("if ("); 323 function.addBoolean(expr); 324 function.println(") {"); 325 setTop(); 326 } 327 328 void startElse() 329 throws ESException 330 { 331 evalExpr(); 332 function.println(" else {"); 333 setTop(); 334 } 335 336 Block startWhile(ESId id, Expr expr) 337 throws ESException 338 { 339 evalExpr(); 340 if (id != null) 341 function.println(id + ":"); 342 function.print("while ("); 343 function.addBoolean(expr); 344 function.println(") {"); 345 346 Block block = create(); 347 startLoop(id); 348 349 if (! (expr instanceof LiteralExpr) || 350 ! ((LiteralExpr) expr).getLiteral().toBoolean()) 351 canExit = true; 352 353 return block; 354 } 355 356 Block startFor(ESId id, Expr test, Expr incr) 357 throws ESException 358 { 359 evalExpr(); 360 if (id != null) 361 function.println(id + ":"); 362 function.print("for (;"); 363 if (test != null) 364 function.addBoolean(test); 365 function.print(";"); 366 if (incr != null) 367 function.addExpr(incr); 368 function.println(") {"); 369 function.cl.pushDepth(); 370 371 Block block = create(); 372 startLoop(id); 373 374 if (test == null) 375 canExit = false; 376 else if (! (test instanceof LiteralExpr) || 377 ! ((LiteralExpr) test).getLiteral().toBoolean()) 378 canExit = true; 379 380 return block; 381 } 382 383 Block startDo(ESId id) 384 throws ESException 385 { 386 evalExpr(); 387 if (id != null) 388 function.println(id + ":"); 389 function.print("do {"); 390 391 Block block = create(); 392 startLoop(id); 393 return block; 394 } 395 396 Block endDo(Expr expr) 397 throws ESException 398 { 399 evalExpr(); 400 401 Block old = endLoop(); 402 403 if (! (expr instanceof LiteralExpr) || 404 ! ((LiteralExpr) expr).getLiteral().toBoolean()) 405 old.canExit = true; 406 407 if (old.canExit) 408 old.isDead = false; 409 410 function.print("while ("); 411 function.addBoolean(expr); 412 function.println(");"); 413 414 return old; 415 } 416 417 void startLoop(ESId id) 418 { 419 String oldVar = function.getStatementVar(); 420 function.pushStatementLoop(); 421 String newVar = function.getStatementVar(); 422 if (oldVar != null) 423 function.println(newVar + " = " + oldVar + ";"); 424 this.id = id; 425 isLoop = true; 426 canExit = false; 427 } 428 429 Block endLoop() 430 throws ESException 431 { 432 evalExpr(); 433 String newVar = function.getStatementVar(); 434 function.popStatementLoop(); 435 String oldVar = function.getStatementVar(); 436 if (oldVar != null && ! isDead) 437 function.println(oldVar + " = " + newVar + ";"); 438 function.cl.popDepth(); 439 function.println("}"); 440 441 Block old = pop(); 442 if (! old.canExit) 443 old.isDead = true; 444 445 return old; 446 } 447 448 Block startSwitch(Expr test) 449 throws ESException 450 { 451 ESId id = ESId.intern("_switchtemp"); 452 453 function.print("_switchtemp = "); 454 function.addExpr(test); 455 function.println(";"); 456 457 Block block = create(); 458 block.switchTop = function.getSwitch(); 459 block.isLoop = true; 460 block.hasDefault = false; 461 462 function.println("switch (_switchcode) {"); 463 return block; 464 } 465 466 void doCase(int i) 467 throws ESException 468 { 469 isDead = false; 470 evalExpr(); 471 function.println("case " + i + ":"); 472 } 473 474 void doDefault() 475 throws ESException 476 { 477 isDead = false; 478 hasDefault = true; 479 evalExpr(); 480 function.println("default:"); 481 } 482 483 Block fillSwitch(ArrayList exprs) 484 throws ESException 485 { 486 evalExpr(); 487 if (! hasDefault && ! isDead) { 488 function.println("default:"); 489 function.println(" break;"); 490 } 491 else if (! isDead) 492 function.println("break;"); 493 function.println("}"); 494 495 int mark = function.mark(); 496 497 for (int i = 0; i < exprs.size(); i++) { 498 if (i != 0) 499 function.print("else "); 500 501 Expr test = (Expr) exprs.get(i); 502 503 function.print("if (_switchtemp.equals("); 504 function.addExpr(test); 505 function.println(")) _switchcode = " + i + ";"); 506 } 507 if (exprs.size() > 0) 508 function.print("else "); 509 function.println("_switchcode = -1;"); 510 511 function.moveChunk(switchTop, mark); 512 513 Block old = pop(); 514 if (isDead && ! canExit && hasDefault) 515 old.isDead = true; 516 517 return old; 518 } 519 520 void doBreak(ESId id) 521 throws ESException 522 { 523 Block block = this; 524 for (; block != null; block = block.parent) { 525 if (block.id == id) { 526 block.canExit = true; 527 break; 528 } 529 } 530 531 if (block == null) 532 throw error("break needs enclosing loop"); 533 534 function.setVars(); 535 evalExpr(); 536 function.println("break " + id + ";"); 537 isDead = true; 538 } 539 540 void doBreak() 541 throws ESException 542 { 543 Block block = this; 544 for (; block != null; block = block.parent) { 545 if (block.isLoop) { 546 block.canExit = true; 547 break; 548 } 549 } 550 551 if (block == null) 552 throw error("break needs enclosing loop"); 553 554 function.setVars(); 555 evalExpr(); 556 function.println("break;"); 557 isDead = true; 558 } 559 560 void doContinue(ESId id) 561 throws ESException 562 { 563 Block block = this; 564 for (; block != null; block = block.parent) { 565 if (block.id == id && block.isLoop) 566 break; 567 571 } 572 if (block == null) 573 throw error("continue needs enclosing loop"); 574 575 function.setVars(); 576 evalExpr(); 577 function.println("continue " + id + ";"); 578 isDead = true; 579 } 580 581 void doContinue() 582 throws ESException 583 { 584 if (findBlock(null) == null) 585 throw error("continue needs enclosing loop"); 586 587 function.setVars(); 588 evalExpr(); 589 function.println("continue;"); 590 isDead = true; 591 } 592 593 private Block findBlock(ESId id) 594 { 595 for (Block block = this; block != null; block = block.parent) { 596 if (id != null && block.id == id) 597 return block; 598 else if (id == null && block.isLoop) 599 return block; 600 } 601 602 return null; 603 } 604 605 Block startWith(Expr expr) 606 throws ESException 607 { 608 function.setArguments(); 609 function.setUseAllVariables(); 610 evalExpr(); 611 withDepth++; 612 function.println("try {"); 613 function.print("_env.pushScope("); 614 function.addExpr(expr); 615 function.println(");"); 616 setTop(); 617 618 return this; 619 } 620 621 Block endWith() 622 throws ESException 623 { 624 evalExpr(); 625 withDepth--; 626 function.println("} finally {"); 627 function.println("_env.popScope();"); 628 function.println("}"); 629 630 return this; 631 } 632 633 int getWithDepth() 634 { 635 return withDepth; 636 } 637 638 Block startTry() 639 throws ESException 640 { 641 function.setVars(); 642 evalExpr(); 643 function.println("try {"); 644 return this; 645 } 646 647 Block endTry() 648 throws ESException 649 { 650 function.setVars(); 651 evalExpr(); 652 function.println("}"); 653 654 return this; 655 } 656 657 void doTry() 658 throws ESException 659 { 660 evalExpr(); 661 662 int i = 0; 663 for (; i < function.data.size(); i++) { 664 Object o = function.data.get(i); 665 if (o != top) { 666 } 667 else if (o instanceof CharBuffer) { 668 CharBuffer cb = (CharBuffer) o; 669 cb.insert(topMark, " try {\n"); 670 break; 671 } 672 else { 673 function.data.add(i + 1, new CharBuffer(" try {\n")); 674 break; 675 } 676 } 677 if (i < function.data.size()) { 678 } 679 else if (function.tail != null && top == function.tail) 680 function.tail.insert(topMark, " try {\n"); 681 else 682 function.data.add(0, new CharBuffer(" try {\n")); 683 684 function.println("}"); 685 } 686 687 Block startCatch(String exn, Expr var) 688 throws ESException 689 { 690 evalExpr(); 691 String temp = "_e" + function.getTemp(); 692 function.println("catch (" + exn + " " + temp + ") {"); 693 if (var != null) { 694 Expr expr = new SpecialExpr(this, SpecialExpr.EXCEPTION, temp); 695 var.assign(expr).exprStatement(function); 696 } 697 698 isDead = false; 699 setTop(); 700 701 return this; 702 } 703 704 Block endCatch() 705 throws ESException 706 { 707 evalExpr(); 708 function.println("}"); 709 return this; 710 } 711 712 Block startFinally() 713 throws ESException 714 { 715 evalExpr(); 716 Block block = create(); 717 function.println("finally {"); 718 function.pushStatementLoop(); 719 block.setTop(); 720 721 return block; 722 } 723 724 Block endFinally() 725 throws ESException 726 { 727 evalExpr(); 728 function.println("}"); 729 function.popStatementLoop(); 730 return pop(); 731 } 732 733 Block startSynchronized(Expr expr) 734 throws ESException 735 { 736 evalExpr(); 737 function.print("synchronized ("); 738 function.addExpr(expr); 739 function.println(".toJavaObject()) {"); 740 741 return create(); 742 } 743 744 Block endSynchronized() 745 throws ESException 746 { 747 evalExpr(); 748 749 function.println("}"); 750 751 Block old = pop(); 752 old.isDead = isDead; 753 754 return old; 755 } 756 757 void doThrow(Expr expr) 758 throws ESException 759 { 760 function.print("throw (Exception)"); 761 function.addExpr(expr); 762 function.println(".toJavaObject();"); 763 isDead = true; 764 } 765 766 void doReturn(Expr value) 767 throws ESException 768 { 769 evalExpr(); 770 function.print("return "); 771 772 value.setUsed(); 773 if (function.getReturnType() != null) 774 function.addExpr(new TopExpr(this, value, 775 function.getReturnType())); 776 else 777 function.addExpr(value); 778 779 function.println(";"); 780 isDead = true; 781 785 } 786 787 void doReturn() 788 throws ESException 789 { 790 evalExpr(); 791 792 if (function.getReturnType() != null) 793 function.print("return 0;"); 794 else 795 function.print("return ESBase.esUndefined;"); 796 isDead = true; 797 801 } 802 803 void finish() 804 throws ESException 805 { 806 if (isDead) 807 return; 808 809 if (lastExpr != null) { 810 function.print("return "); 811 function.addExpr(lastExpr); 812 function.println(";"); 813 lastExpr = null; 814 } 815 else if (hasStatementValue) 816 function.println("return _val0;"); 817 else 818 function.println("return ESBase.esUndefined;"); 819 } 820 821 String newIterator(ESId id, Expr expr) 822 throws ESException 823 { 824 evalExpr(); 825 826 String iter = "iter" + function.getIter(); 827 function.print(iter + " = "); 828 function.addExpr(expr); 829 function.println(".keys();"); 830 831 return iter; 832 } 833 834 void evalExpr() throws ESException 835 { 836 if (lastExpr == null) 837 return; 838 839 function.print(function.getStatementVar() + " = "); 840 function.addExpr(lastExpr); 841 function.println(";"); 842 843 lastExpr = null; 844 } 845 846 private static Block allocate() 847 { 848 Block block = new Block(); 849 850 return block; 851 } 852 853 ESException error(String message) 854 { 855 return parser.lexer.error(message); 856 } 857 858 void free() 859 { 860 } 861 862 static { 863 specialNames = new HashMap (); 864 specialNames.put(ESId.intern("Object"), "Object"); 865 specialNames.put(ESId.intern("Date"), "Date"); 866 specialNames.put(ESId.intern("String"), "String"); 867 specialNames.put(ESId.intern("Number"), "Number"); 868 specialNames.put(ESId.intern("Array"), "Array"); 869 specialNames.put(ESId.intern("Boolean"), "Boolean"); 870 specialNames.put(ESId.intern("Math"), "Math"); 871 }; 872 } 873 | Popular Tags |