1 /* Digital Mars DMDScript source code. 2 * Copyright (c) 2000-2002 by Chromium Communications 3 * D version Copyright (c) 2004-2010 by Digital Mars 4 * Distributed under the Boost Software License, Version 1.0. 5 * (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 * written by Walter Bright 7 * http://www.digitalmars.com 8 * 9 * D2 port by Dmitry Olshansky 10 * 11 * DMDScript is implemented in the D Programming Language, 12 * http://www.digitalmars.com/d/ 13 * 14 * For a C++ implementation of DMDScript, including COM support, see 15 * http://www.digitalmars.com/dscript/cppscript.html 16 */ 17 18 module dmdscript.statement; 19 20 import std.stdio; 21 import std..string; 22 import std.math; 23 24 import dmdscript.script; 25 import dmdscript.value; 26 import dmdscript.scopex; 27 import dmdscript.expression; 28 import dmdscript.irstate; 29 import dmdscript.symbol; 30 import dmdscript.identifier; 31 import dmdscript.ir; 32 import dmdscript.lexer; 33 import dmdscript.errmsgs; 34 import dmdscript.functiondefinition; 35 import dmdscript.opcodes; 36 37 enum 38 { 39 TOPSTATEMENT, 40 FUNCTIONDEFINITION, 41 EXPSTATEMENT, 42 VARSTATEMENT, 43 } 44 45 46 /******************************** TopStatement ***************************/ 47 48 class TopStatement 49 { 50 enum uint TOPSTATEMENT_SIGNATURE = 0xBA3FE1F3; 51 uint signature = TOPSTATEMENT_SIGNATURE; 52 53 Loc loc; 54 int done; // 0: parsed 55 // 1: semantic 56 // 2: toIR 57 int st; 58 59 this(Loc loc) 60 { 61 this.loc = loc; 62 this.done = 0; 63 this.st = TOPSTATEMENT; 64 } 65 66 invariant() 67 { 68 assert(signature == TOPSTATEMENT_SIGNATURE); 69 } 70 71 void toBuffer(ref tchar[] buf) 72 { 73 buf ~= "TopStatement.toBuffer()\n"; 74 } 75 76 Statement semantic(Scope *sc) 77 { 78 writefln("TopStatement.semantic(%p)", this); 79 return null; 80 } 81 82 void toIR(IRstate *irs) 83 { 84 writefln("TopStatement.toIR(%p)", this); 85 } 86 87 void error(ARGS...)(Scope *sc, int msgnum, ARGS args) 88 { 89 error(sc, errmsgtbl[msgnum], args); 90 } 91 92 void error(ARGS...)(Scope *sc, string fmt, ARGS args) 93 { 94 static import dmdscript.utf; 95 import std.format : formattedWrite; 96 97 d_string buf; 98 d_string sourcename; 99 100 if(sc.funcdef) 101 { 102 if(sc.funcdef.isAnonymous) 103 sourcename = "anonymous"; 104 else if(sc.funcdef.name) 105 sourcename ~= sc.funcdef.name.toString(); 106 } 107 buf = std..string.format("%s(%d) : Error: ", sourcename, loc); 108 109 void putc(dchar c) 110 { 111 dmdscript.utf.encode(buf, c); 112 } 113 114 formattedWrite(&putc, fmt, args); 115 116 117 if(!sc.errinfo.message) 118 { 119 sc.errinfo.message = buf; 120 sc.errinfo.linnum = loc; 121 sc.errinfo.srcline = Lexer.locToSrcline(sc.getSource().ptr, loc); 122 } 123 } 124 125 TopStatement ImpliedReturn() 126 { 127 return this; 128 } 129 } 130 131 /******************************** Statement ***************************/ 132 133 class Statement : TopStatement 134 { 135 LabelSymbol *label; 136 137 this(Loc loc) 138 { 139 super(loc); 140 this.loc = loc; 141 } 142 143 override void toBuffer(ref tchar[] buf) 144 { 145 buf ~= "Statement.toBuffer()\n"; 146 } 147 148 override Statement semantic(Scope *sc) 149 { 150 writef("Statement.semantic(%p)\n", this); 151 return this; 152 } 153 154 override void toIR(IRstate *irs) 155 { 156 writef("Statement.toIR(%p)\n", this); 157 } 158 159 uint getBreak() 160 { 161 assert(0); 162 } 163 164 uint getContinue() 165 { 166 assert(0); 167 } 168 169 uint getGoto() 170 { 171 assert(0); 172 } 173 174 uint getTarget() 175 { 176 assert(0); 177 } 178 179 ScopeStatement getScope() 180 { 181 return null; 182 } 183 } 184 185 /******************************** EmptyStatement ***************************/ 186 187 class EmptyStatement : Statement 188 { 189 this(Loc loc) 190 { 191 super(loc); 192 this.loc = loc; 193 } 194 195 override void toBuffer(ref tchar[] buf) 196 { 197 buf ~= ";\n"; 198 } 199 200 override Statement semantic(Scope *sc) 201 { 202 //writef("EmptyStatement.semantic(%p)\n", this); 203 return this; 204 } 205 206 override void toIR(IRstate *irs) 207 { 208 } 209 } 210 211 /******************************** ExpStatement ***************************/ 212 213 class ExpStatement : Statement 214 { 215 Expression exp; 216 217 this(Loc loc, Expression exp) 218 { 219 //writef("ExpStatement.ExpStatement(this = %x, exp = %x)\n", this, exp); 220 super(loc); 221 st = EXPSTATEMENT; 222 this.exp = exp; 223 } 224 225 override void toBuffer(ref tchar[] buf) 226 { 227 if(exp) 228 exp.toBuffer(buf); 229 buf ~= ";\n"; 230 } 231 232 override Statement semantic(Scope *sc) 233 { 234 //writef("exp = '%s'\n", exp.toString()); 235 //writef("ExpStatement.semantic(this = %x, exp = %x, exp.vptr = %x, %x, %x)\n", this, exp, ((uint *)exp)[0], /*(*(uint **)exp)[12],*/ *(uint *)(*(uint **)exp)[12]); 236 if(exp) 237 exp = exp.semantic(sc); 238 //writef("-semantic()\n"); 239 return this; 240 } 241 242 override TopStatement ImpliedReturn() 243 { 244 return new ImpliedReturnStatement(loc, exp); 245 } 246 247 override void toIR(IRstate *irs) 248 { 249 //writef("ExpStatement.toIR(%p)\n", exp); 250 if(exp) 251 { 252 uint marksave = irs.mark(); 253 254 assert(exp); 255 exp.toIR(irs, 0); 256 irs.release(marksave); 257 258 exp = null; // release to garbage collector 259 } 260 } 261 } 262 263 /****************************** VarDeclaration ******************************/ 264 265 class VarDeclaration 266 { 267 Loc loc; 268 Identifier *name; 269 Expression init; 270 271 this(Loc loc, Identifier * name, Expression init) 272 { 273 this.loc = loc; 274 this.init = init; 275 this.name = name; 276 } 277 } 278 279 /******************************** VarStatement ***************************/ 280 281 class VarStatement : Statement 282 { 283 VarDeclaration[] vardecls; 284 285 this(Loc loc) 286 { 287 super(loc); 288 st = VARSTATEMENT; 289 } 290 291 override Statement semantic(Scope *sc) 292 { 293 FunctionDefinition fd; 294 uint i; 295 296 // Collect all the Var statements in order in the function 297 // declaration, this is so it is easy to instantiate them 298 fd = sc.funcdef; 299 //fd.varnames.reserve(vardecls.length); 300 301 for(i = 0; i < vardecls.length; i++) 302 { 303 VarDeclaration vd; 304 305 vd = vardecls[i]; 306 if(vd.init) 307 vd.init = vd.init.semantic(sc); 308 fd.varnames ~= vd.name; 309 } 310 311 return this; 312 } 313 314 override void toBuffer(ref tchar[] buf) 315 { 316 uint i; 317 318 if(vardecls.length) 319 { 320 buf ~= "var "; 321 322 for(i = 0; i < vardecls.length; i++) 323 { 324 VarDeclaration vd; 325 326 vd = vardecls[i]; 327 buf ~= vd.name.toString(); 328 if(vd.init) 329 { 330 buf ~= " = "; 331 vd.init.toBuffer(buf); 332 } 333 } 334 buf ~= ";\n"; 335 } 336 } 337 338 override void toIR(IRstate *irs) 339 { 340 uint i; 341 uint ret; 342 343 if(vardecls.length) 344 { 345 uint marksave; 346 347 marksave = irs.mark(); 348 ret = irs.alloc(1); 349 350 for(i = 0; i < vardecls.length; i++) 351 { 352 VarDeclaration vd; 353 354 vd = vardecls[i]; 355 356 // This works like assignment statements: 357 // name = init; 358 IR property; 359 360 if(vd.init) 361 { 362 vd.init.toIR(irs, ret); 363 property.id = Identifier.build(vd.name.toString()); 364 irs.gen2(loc, IRputthis, ret, property.index); 365 } 366 } 367 irs.release(marksave); 368 vardecls[] = null; // help gc 369 } 370 } 371 } 372 373 /******************************** BlockStatement ***************************/ 374 375 class BlockStatement : Statement 376 { 377 TopStatement[] statements; 378 379 this(Loc loc) 380 { 381 super(loc); 382 } 383 384 override Statement semantic(Scope *sc) 385 { 386 uint i; 387 388 //writefln("BlockStatement.semantic()"); 389 for(i = 0; i < statements.length; i++) 390 { 391 TopStatement s; 392 393 s = statements[i]; 394 assert(s); 395 statements[i] = s.semantic(sc); 396 } 397 398 return this; 399 } 400 401 override TopStatement ImpliedReturn() 402 { 403 size_t i = statements.length; 404 405 if(i) 406 { 407 TopStatement ts = statements[i - 1]; 408 ts = ts.ImpliedReturn(); 409 statements[i - 1] = cast(Statement)ts; 410 } 411 return this; 412 } 413 414 415 override void toBuffer(ref tchar[] buf) 416 { 417 buf ~= "{\n"; 418 419 foreach(TopStatement s; statements) 420 { 421 s.toBuffer(buf); 422 } 423 424 buf ~= "}\n"; 425 } 426 427 override void toIR(IRstate *irs) 428 { 429 foreach(TopStatement s; statements) 430 { 431 s.toIR(irs); 432 } 433 434 // Release to garbage collector 435 statements[] = null; 436 statements = null; 437 } 438 } 439 440 /******************************** LabelStatement ***************************/ 441 442 class LabelStatement : Statement 443 { 444 Identifier* ident; 445 Statement statement; 446 uint gotoIP; 447 uint breakIP; 448 ScopeStatement scopeContext; 449 Scope whichScope; 450 451 this(Loc loc, Identifier * ident, Statement statement) 452 { 453 //writef("LabelStatement.LabelStatement(%p, '%s', %p)\n", this, ident.toChars(), statement); 454 super(loc); 455 this.ident = ident; 456 this.statement = statement; 457 gotoIP = ~0u; 458 breakIP = ~0u; 459 scopeContext = null; 460 } 461 462 override Statement semantic(Scope *sc) 463 { 464 LabelSymbol ls; 465 466 //writef("LabelStatement.semantic('%ls')\n", ident.toString()); 467 scopeContext = sc.scopeContext; 468 whichScope = *sc; 469 ls = sc.searchLabel(ident); 470 if(ls) 471 { 472 // Ignore multiple definition errors 473 //if (ls.statement) 474 //error(sc, "label '%s' is already defined", ident.toString()); 475 ls.statement = this; 476 } 477 else 478 { 479 ls = new LabelSymbol(loc, ident, this); 480 sc.insertLabel(ls); 481 } 482 if(statement) 483 statement = statement.semantic(sc); 484 return this; 485 } 486 487 override TopStatement ImpliedReturn() 488 { 489 if(statement) 490 statement = cast(Statement)statement.ImpliedReturn(); 491 return this; 492 } 493 494 override void toBuffer(ref tchar[] buf) 495 { 496 buf ~= ident.toString(); 497 buf ~= ": "; 498 if(statement) 499 statement.toBuffer(buf); 500 else 501 buf ~= '\n'; 502 } 503 504 override void toIR(IRstate *irs) 505 { 506 gotoIP = irs.getIP(); 507 statement.toIR(irs); 508 breakIP = irs.getIP(); 509 } 510 511 override uint getGoto() 512 { 513 return gotoIP; 514 } 515 516 override uint getBreak() 517 { 518 return breakIP; 519 } 520 521 override uint getContinue() 522 { 523 return statement.getContinue(); 524 } 525 526 override ScopeStatement getScope() 527 { 528 return scopeContext; 529 } 530 } 531 532 /******************************** IfStatement ***************************/ 533 534 class IfStatement : Statement 535 { 536 Expression condition; 537 Statement ifbody; 538 Statement elsebody; 539 540 this(Loc loc, Expression condition, Statement ifbody, Statement elsebody) 541 { 542 super(loc); 543 this.condition = condition; 544 this.ifbody = ifbody; 545 this.elsebody = elsebody; 546 } 547 548 override Statement semantic(Scope *sc) 549 { 550 //writef("IfStatement.semantic(%p)\n", sc); 551 assert(condition); 552 condition = condition.semantic(sc); 553 ifbody = ifbody.semantic(sc); 554 if(elsebody) 555 elsebody = elsebody.semantic(sc); 556 557 return this; 558 } 559 560 override TopStatement ImpliedReturn() 561 { 562 assert(condition); 563 ifbody = cast(Statement)ifbody.ImpliedReturn(); 564 if(elsebody) 565 elsebody = cast(Statement)elsebody.ImpliedReturn(); 566 return this; 567 } 568 569 570 571 override void toIR(IRstate *irs) 572 { 573 uint c; 574 uint u1; 575 uint u2; 576 577 assert(condition); 578 c = irs.alloc(1); 579 condition.toIR(irs, c); 580 u1 = irs.getIP(); 581 irs.gen2(loc, (condition.isBooleanResult() ? IRjfb : IRjf), 0, c); 582 irs.release(c, 1); 583 ifbody.toIR(irs); 584 if(elsebody) 585 { 586 u2 = irs.getIP(); 587 irs.gen1(loc, IRjmp, 0); 588 irs.patchJmp(u1, irs.getIP()); 589 elsebody.toIR(irs); 590 irs.patchJmp(u2, irs.getIP()); 591 } 592 else 593 { 594 irs.patchJmp(u1, irs.getIP()); 595 } 596 597 // Help GC 598 condition = null; 599 ifbody = null; 600 elsebody = null; 601 } 602 } 603 604 /******************************** SwitchStatement ***************************/ 605 606 class SwitchStatement : Statement 607 { 608 Expression condition; 609 Statement bdy; 610 uint breakIP; 611 ScopeStatement scopeContext; 612 613 DefaultStatement swdefault; 614 CaseStatement[] cases; 615 616 this(Loc loc, Expression c, Statement b) 617 { 618 super(loc); 619 condition = c; 620 bdy = b; 621 breakIP = ~0u; 622 scopeContext = null; 623 624 swdefault = null; 625 cases = null; 626 } 627 628 override Statement semantic(Scope *sc) 629 { 630 condition = condition.semantic(sc); 631 632 SwitchStatement switchSave = sc.switchTarget; 633 Statement breakSave = sc.breakTarget; 634 635 scopeContext = sc.scopeContext; 636 sc.switchTarget = this; 637 sc.breakTarget = this; 638 639 bdy = bdy.semantic(sc); 640 641 sc.switchTarget = switchSave; 642 sc.breakTarget = breakSave; 643 644 return this; 645 } 646 647 override void toIR(IRstate *irs) 648 { 649 uint c; 650 uint udefault; 651 uint marksave; 652 653 //writef("SwitchStatement.toIR()\n"); 654 marksave = irs.mark(); 655 c = irs.alloc(1); 656 condition.toIR(irs, c); 657 658 // Generate a sequence of cmp-jt 659 // Not the most efficient, but we await a more formal 660 // specification of switch before we attempt to optimize 661 662 if(cases.length) 663 { 664 uint x; 665 666 x = irs.alloc(1); 667 for(uint i = 0; i < cases.length; i++) 668 { 669 CaseStatement cs; 670 671 x = irs.alloc(1); 672 cs = cases[i]; 673 cs.exp.toIR(irs, x); 674 irs.gen3(loc, IRcid, x, c, x); 675 cs.patchIP = irs.getIP(); 676 irs.gen2(loc, IRjt, 0, x); 677 } 678 } 679 udefault = irs.getIP(); 680 irs.gen1(loc, IRjmp, 0); 681 682 Statement breakSave = irs.breakTarget; 683 irs.breakTarget = this; 684 bdy.toIR(irs); 685 686 irs.breakTarget = breakSave; 687 breakIP = irs.getIP(); 688 689 // Patch jump addresses 690 if(cases.length) 691 { 692 for(uint i = 0; i < cases.length; i++) 693 { 694 CaseStatement cs; 695 696 cs = cases[i]; 697 irs.patchJmp(cs.patchIP, cs.caseIP); 698 } 699 } 700 if(swdefault) 701 irs.patchJmp(udefault, swdefault.defaultIP); 702 else 703 irs.patchJmp(udefault, breakIP); 704 irs.release(marksave); 705 706 // Help gc 707 condition = null; 708 bdy = null; 709 } 710 711 override uint getBreak() 712 { 713 return breakIP; 714 } 715 716 override ScopeStatement getScope() 717 { 718 return scopeContext; 719 } 720 } 721 722 723 /******************************** CaseStatement ***************************/ 724 725 class CaseStatement : Statement 726 { 727 Expression exp; 728 uint caseIP; 729 uint patchIP; 730 731 this(Loc loc, Expression exp) 732 { 733 super(loc); 734 this.exp = exp; 735 caseIP = ~0u; 736 patchIP = ~0u; 737 } 738 739 override Statement semantic(Scope *sc) 740 { 741 //writef("CaseStatement.semantic(%p)\n", sc); 742 exp = exp.semantic(sc); 743 if(sc.switchTarget) 744 { 745 SwitchStatement sw = sc.switchTarget; 746 uint i; 747 748 // Look for duplicate 749 for(i = 0; i < sw.cases.length; i++) 750 { 751 CaseStatement cs = sw.cases[i]; 752 753 if(exp == cs.exp) 754 { 755 error(sc, errmsgtbl[ERR_SWITCH_REDUNDANT_CASE], exp.toString()); 756 return null; 757 } 758 } 759 sw.cases ~= this; 760 } 761 else 762 { 763 error(sc, errmsgtbl[ERR_MISPLACED_SWITCH_CASE], exp.toString()); 764 return null; 765 } 766 return this; 767 } 768 769 override void toIR(IRstate *irs) 770 { 771 caseIP = irs.getIP(); 772 } 773 } 774 775 /******************************** DefaultStatement ***************************/ 776 777 class DefaultStatement : Statement 778 { 779 uint defaultIP; 780 781 this(Loc loc) 782 { 783 super(loc); 784 defaultIP = ~0u; 785 } 786 787 override Statement semantic(Scope *sc) 788 { 789 if(sc.switchTarget) 790 { 791 SwitchStatement sw = sc.switchTarget; 792 793 if(sw.swdefault) 794 { 795 error(sc, ERR_SWITCH_REDUNDANT_DEFAULT); 796 return null; 797 } 798 sw.swdefault = this; 799 } 800 else 801 { 802 error(sc, ERR_MISPLACED_SWITCH_DEFAULT); 803 return null; 804 } 805 return this; 806 } 807 808 override void toIR(IRstate *irs) 809 { 810 defaultIP = irs.getIP(); 811 } 812 } 813 814 /******************************** DoStatement ***************************/ 815 816 class DoStatement : Statement 817 { 818 Statement bdy; 819 Expression condition; 820 uint breakIP; 821 uint continueIP; 822 ScopeStatement scopeContext; 823 824 this(Loc loc, Statement b, Expression c) 825 { 826 super(loc); 827 bdy = b; 828 condition = c; 829 breakIP = ~0u; 830 continueIP = ~0u; 831 scopeContext = null; 832 } 833 834 override Statement semantic(Scope *sc) 835 { 836 Statement continueSave = sc.continueTarget; 837 Statement breakSave = sc.breakTarget; 838 839 scopeContext = sc.scopeContext; 840 sc.continueTarget = this; 841 sc.breakTarget = this; 842 843 bdy = bdy.semantic(sc); 844 condition = condition.semantic(sc); 845 846 sc.continueTarget = continueSave; 847 sc.breakTarget = breakSave; 848 849 return this; 850 } 851 852 override TopStatement ImpliedReturn() 853 { 854 if(bdy) 855 bdy = cast(Statement)bdy.ImpliedReturn(); 856 return this; 857 } 858 859 override void toIR(IRstate *irs) 860 { 861 uint c; 862 uint u1; 863 Statement continueSave = irs.continueTarget; 864 Statement breakSave = irs.breakTarget; 865 uint marksave; 866 867 irs.continueTarget = this; 868 irs.breakTarget = this; 869 870 marksave = irs.mark(); 871 u1 = irs.getIP(); 872 bdy.toIR(irs); 873 c = irs.alloc(1); 874 continueIP = irs.getIP(); 875 condition.toIR(irs, c); 876 irs.gen2(loc, (condition.isBooleanResult() ? IRjtb : IRjt), u1 - irs.getIP(), c); 877 breakIP = irs.getIP(); 878 irs.release(marksave); 879 880 irs.continueTarget = continueSave; 881 irs.breakTarget = breakSave; 882 883 // Help GC 884 condition = null; 885 bdy = null; 886 } 887 888 override uint getBreak() 889 { 890 return breakIP; 891 } 892 893 override uint getContinue() 894 { 895 return continueIP; 896 } 897 898 override ScopeStatement getScope() 899 { 900 return scopeContext; 901 } 902 } 903 904 /******************************** WhileStatement ***************************/ 905 906 class WhileStatement : Statement 907 { 908 Expression condition; 909 Statement bdy; 910 uint breakIP; 911 uint continueIP; 912 ScopeStatement scopeContext; 913 914 this(Loc loc, Expression c, Statement b) 915 { 916 super(loc); 917 condition = c; 918 bdy = b; 919 breakIP = ~0u; 920 continueIP = ~0u; 921 scopeContext = null; 922 } 923 924 override Statement semantic(Scope *sc) 925 { 926 Statement continueSave = sc.continueTarget; 927 Statement breakSave = sc.breakTarget; 928 929 scopeContext = sc.scopeContext; 930 sc.continueTarget = this; 931 sc.breakTarget = this; 932 933 condition = condition.semantic(sc); 934 bdy = bdy.semantic(sc); 935 936 sc.continueTarget = continueSave; 937 sc.breakTarget = breakSave; 938 939 return this; 940 } 941 942 override TopStatement ImpliedReturn() 943 { 944 if(bdy) 945 bdy = cast(Statement)bdy.ImpliedReturn(); 946 return this; 947 } 948 949 override void toIR(IRstate *irs) 950 { 951 uint c; 952 uint u1; 953 uint u2; 954 955 Statement continueSave = irs.continueTarget; 956 Statement breakSave = irs.breakTarget; 957 uint marksave = irs.mark(); 958 959 irs.continueTarget = this; 960 irs.breakTarget = this; 961 962 u1 = irs.getIP(); 963 continueIP = u1; 964 c = irs.alloc(1); 965 condition.toIR(irs, c); 966 u2 = irs.getIP(); 967 irs.gen2(loc, (condition.isBooleanResult() ? IRjfb : IRjf), 0, c); 968 bdy.toIR(irs); 969 irs.gen1(loc, IRjmp, u1 - irs.getIP()); 970 irs.patchJmp(u2, irs.getIP()); 971 breakIP = irs.getIP(); 972 973 irs.release(marksave); 974 irs.continueTarget = continueSave; 975 irs.breakTarget = breakSave; 976 977 // Help GC 978 condition = null; 979 bdy = null; 980 } 981 982 override uint getBreak() 983 { 984 return breakIP; 985 } 986 987 override uint getContinue() 988 { 989 return continueIP; 990 } 991 992 override ScopeStatement getScope() 993 { 994 return scopeContext; 995 } 996 } 997 998 /******************************** ForStatement ***************************/ 999 1000 class ForStatement : Statement 1001 { 1002 Statement init; 1003 Expression condition; 1004 Expression increment; 1005 Statement bdy; 1006 uint breakIP; 1007 uint continueIP; 1008 ScopeStatement scopeContext; 1009 1010 this(Loc loc, Statement init, Expression condition, Expression increment, Statement bdy) 1011 { 1012 super(loc); 1013 this.init = init; 1014 this.condition = condition; 1015 this.increment = increment; 1016 this.bdy = bdy; 1017 breakIP = ~0u; 1018 continueIP = ~0u; 1019 scopeContext = null; 1020 } 1021 1022 override Statement semantic(Scope *sc) 1023 { 1024 Statement continueSave = sc.continueTarget; 1025 Statement breakSave = sc.breakTarget; 1026 1027 if(init) 1028 init = init.semantic(sc); 1029 if(condition) 1030 condition = condition.semantic(sc); 1031 if(increment) 1032 increment = increment.semantic(sc); 1033 1034 scopeContext = sc.scopeContext; 1035 sc.continueTarget = this; 1036 sc.breakTarget = this; 1037 1038 bdy = bdy.semantic(sc); 1039 1040 sc.continueTarget = continueSave; 1041 sc.breakTarget = breakSave; 1042 1043 return this; 1044 } 1045 1046 override TopStatement ImpliedReturn() 1047 { 1048 if(bdy) 1049 bdy = cast(Statement)bdy.ImpliedReturn(); 1050 return this; 1051 } 1052 1053 override void toIR(IRstate *irs) 1054 { 1055 uint u1; 1056 uint u2 = 0; // unneeded initialization keeps lint happy 1057 1058 Statement continueSave = irs.continueTarget; 1059 Statement breakSave = irs.breakTarget; 1060 uint marksave = irs.mark(); 1061 1062 irs.continueTarget = this; 1063 irs.breakTarget = this; 1064 1065 if(init) 1066 init.toIR(irs); 1067 u1 = irs.getIP(); 1068 if(condition) 1069 { 1070 if(condition.op == TOKless || condition.op == TOKlessequal) 1071 { 1072 BinExp be = cast(BinExp)condition; 1073 RealExpression re; 1074 uint b; 1075 uint c; 1076 1077 b = irs.alloc(1); 1078 be.e1.toIR(irs, b); 1079 re = cast(RealExpression )be.e2; 1080 if(be.e2.op == TOKreal && !isNaN(re.value)) 1081 { 1082 u2 = irs.getIP(); 1083 irs.genX(loc, (condition.op == TOKless) ? IRjltc : IRjlec, 0, b, re.value); 1084 } 1085 else 1086 { 1087 c = irs.alloc(1); 1088 be.e2.toIR(irs, c); 1089 u2 = irs.getIP(); 1090 irs.gen3(loc, (condition.op == TOKless) ? IRjlt : IRjle, 0, b, c); 1091 } 1092 } 1093 else 1094 { 1095 uint c; 1096 1097 c = irs.alloc(1); 1098 condition.toIR(irs, c); 1099 u2 = irs.getIP(); 1100 irs.gen2(loc, (condition.isBooleanResult() ? IRjfb : IRjf), 0, c); 1101 } 1102 } 1103 bdy.toIR(irs); 1104 continueIP = irs.getIP(); 1105 if(increment) 1106 increment.toIR(irs, 0); 1107 irs.gen1(loc, IRjmp, u1 - irs.getIP()); 1108 if(condition) 1109 irs.patchJmp(u2, irs.getIP()); 1110 1111 breakIP = irs.getIP(); 1112 1113 irs.release(marksave); 1114 irs.continueTarget = continueSave; 1115 irs.breakTarget = breakSave; 1116 1117 // Help GC 1118 init = null; 1119 condition = null; 1120 bdy = null; 1121 increment = null; 1122 } 1123 1124 override uint getBreak() 1125 { 1126 return breakIP; 1127 } 1128 1129 override uint getContinue() 1130 { 1131 return continueIP; 1132 } 1133 1134 override ScopeStatement getScope() 1135 { 1136 return scopeContext; 1137 } 1138 } 1139 1140 /******************************** ForInStatement ***************************/ 1141 1142 class ForInStatement : Statement 1143 { 1144 Statement init; 1145 Expression inexp; 1146 Statement bdy; 1147 uint breakIP; 1148 uint continueIP; 1149 ScopeStatement scopeContext; 1150 1151 this(Loc loc, Statement init, Expression inexp, Statement bdy) 1152 { 1153 super(loc); 1154 this.init = init; 1155 this.inexp = inexp; 1156 this.bdy = bdy; 1157 breakIP = ~0u; 1158 continueIP = ~0u; 1159 scopeContext = null; 1160 } 1161 1162 override Statement semantic(Scope *sc) 1163 { 1164 Statement continueSave = sc.continueTarget; 1165 Statement breakSave = sc.breakTarget; 1166 1167 init = init.semantic(sc); 1168 1169 if(init.st == EXPSTATEMENT) 1170 { 1171 ExpStatement es; 1172 1173 es = cast(ExpStatement)(init); 1174 es.exp.checkLvalue(sc); 1175 } 1176 else if(init.st == VARSTATEMENT) 1177 { 1178 } 1179 else 1180 { 1181 error(sc, ERR_INIT_NOT_EXPRESSION); 1182 return null; 1183 } 1184 1185 inexp = inexp.semantic(sc); 1186 1187 scopeContext = sc.scopeContext; 1188 sc.continueTarget = this; 1189 sc.breakTarget = this; 1190 1191 bdy = bdy.semantic(sc); 1192 1193 sc.continueTarget = continueSave; 1194 sc.breakTarget = breakSave; 1195 1196 return this; 1197 } 1198 1199 override TopStatement ImpliedReturn() 1200 { 1201 bdy = cast(Statement)bdy.ImpliedReturn(); 1202 return this; 1203 } 1204 1205 override void toIR(IRstate *irs) 1206 { 1207 uint e; 1208 uint iter; 1209 ExpStatement es; 1210 VarStatement vs; 1211 uint base; 1212 IR property; 1213 int opoff; 1214 uint marksave = irs.mark(); 1215 1216 e = irs.alloc(1); 1217 inexp.toIR(irs, e); 1218 iter = irs.alloc(1); 1219 irs.gen2(loc, IRiter, iter, e); 1220 1221 Statement continueSave = irs.continueTarget; 1222 Statement breakSave = irs.breakTarget; 1223 1224 irs.continueTarget = this; 1225 irs.breakTarget = this; 1226 1227 if(init.st == EXPSTATEMENT) 1228 { 1229 es = cast(ExpStatement)(init); 1230 es.exp.toLvalue(irs, base, &property, opoff); 1231 } 1232 else if(init.st == VARSTATEMENT) 1233 { 1234 VarDeclaration vd; 1235 1236 vs = cast(VarStatement)(init); 1237 assert(vs.vardecls.length == 1); 1238 vd = vs.vardecls[0]; 1239 1240 property.id = Identifier.build(vd.name.toString()); 1241 opoff = 2; 1242 base = ~0u; 1243 } 1244 else 1245 { // Error already reported by semantic() 1246 return; 1247 } 1248 1249 continueIP = irs.getIP(); 1250 if(opoff == 2) 1251 irs.gen3(loc, IRnextscope, 0, property.index, iter); 1252 else 1253 irs.genX(loc, IRnext + opoff, 0, base, property.index, iter); 1254 bdy.toIR(irs); 1255 irs.gen1(loc, IRjmp, continueIP - irs.getIP()); 1256 irs.patchJmp(continueIP, irs.getIP()); 1257 1258 breakIP = irs.getIP(); 1259 1260 irs.continueTarget = continueSave; 1261 irs.breakTarget = breakSave; 1262 irs.release(marksave); 1263 1264 // Help GC 1265 init = null; 1266 inexp = null; 1267 bdy = null; 1268 } 1269 1270 override uint getBreak() 1271 { 1272 return breakIP; 1273 } 1274 1275 override uint getContinue() 1276 { 1277 return continueIP; 1278 } 1279 1280 override ScopeStatement getScope() 1281 { 1282 return scopeContext; 1283 } 1284 } 1285 1286 /******************************** ScopeStatement ***************************/ 1287 1288 class ScopeStatement : Statement 1289 { 1290 ScopeStatement enclosingScope; 1291 int depth; // syntactical nesting level of ScopeStatement's 1292 int npops; // how many items added to scope chain 1293 1294 this(Loc loc) 1295 { 1296 super(loc); 1297 enclosingScope = null; 1298 depth = 1; 1299 npops = 1; 1300 } 1301 } 1302 1303 /******************************** WithStatement ***************************/ 1304 1305 class WithStatement : ScopeStatement 1306 { 1307 Expression exp; 1308 Statement bdy; 1309 1310 this(Loc loc, Expression exp, Statement bdy) 1311 { 1312 super(loc); 1313 this.exp = exp; 1314 this.bdy = bdy; 1315 } 1316 1317 override Statement semantic(Scope *sc) 1318 { 1319 exp = exp.semantic(sc); 1320 1321 enclosingScope = sc.scopeContext; 1322 sc.scopeContext = this; 1323 1324 // So enclosing FunctionDeclaration knows how deep the With's 1325 // can nest 1326 if(enclosingScope) 1327 depth = enclosingScope.depth + 1; 1328 if(depth > sc.funcdef.withdepth) 1329 sc.funcdef.withdepth = depth; 1330 1331 sc.nestDepth++; 1332 bdy = bdy.semantic(sc); 1333 sc.nestDepth--; 1334 1335 sc.scopeContext = enclosingScope; 1336 return this; 1337 } 1338 1339 override TopStatement ImpliedReturn() 1340 { 1341 bdy = cast(Statement)bdy.ImpliedReturn(); 1342 return this; 1343 } 1344 1345 1346 1347 override void toIR(IRstate *irs) 1348 { 1349 uint c; 1350 uint marksave = irs.mark(); 1351 1352 irs.scopeContext = this; 1353 1354 c = irs.alloc(1); 1355 exp.toIR(irs, c); 1356 irs.gen1(loc, IRpush, c); 1357 bdy.toIR(irs); 1358 irs.gen0(loc, IRpop); 1359 1360 irs.scopeContext = enclosingScope; 1361 irs.release(marksave); 1362 1363 // Help GC 1364 exp = null; 1365 bdy = null; 1366 } 1367 } 1368 1369 /******************************** ContinueStatement ***************************/ 1370 1371 class ContinueStatement : Statement 1372 { 1373 Identifier *ident; 1374 Statement target; 1375 1376 this(Loc loc, Identifier * ident) 1377 { 1378 super(loc); 1379 this.ident = ident; 1380 target = null; 1381 } 1382 1383 override Statement semantic(Scope *sc) 1384 { 1385 if(ident == null) 1386 { 1387 target = sc.continueTarget; 1388 if(!target) 1389 { 1390 error(sc, ERR_MISPLACED_CONTINUE); 1391 return null; 1392 } 1393 } 1394 else 1395 { 1396 LabelSymbol ls; 1397 1398 ls = sc.searchLabel(ident); 1399 if(!ls || !ls.statement) 1400 { 1401 error(sc, errmsgtbl[ERR_UNDEFINED_STATEMENT_LABEL], ident.toString()); 1402 return null; 1403 } 1404 else 1405 target = ls.statement; 1406 } 1407 return this; 1408 } 1409 1410 override void toIR(IRstate *irs) 1411 { 1412 ScopeStatement w; 1413 ScopeStatement tw; 1414 1415 tw = target.getScope(); 1416 for(w = irs.scopeContext; !(w is tw); w = w.enclosingScope) 1417 { 1418 assert(w); 1419 irs.pops(w.npops); 1420 } 1421 irs.addFixup(irs.getIP()); 1422 irs.gen1(loc, IRjmp, cast(IRstate.Op)cast(void*)this); 1423 } 1424 1425 override uint getTarget() 1426 { 1427 assert(target); 1428 return target.getContinue(); 1429 } 1430 } 1431 1432 /******************************** BreakStatement ***************************/ 1433 1434 class BreakStatement : Statement 1435 { 1436 Identifier *ident; 1437 Statement target; 1438 1439 this(Loc loc, Identifier * ident) 1440 { 1441 super(loc); 1442 this.ident = ident; 1443 target = null; 1444 } 1445 1446 override Statement semantic(Scope *sc) 1447 { 1448 // writef("BreakStatement.semantic(%p)\n", sc); 1449 if(ident == null) 1450 { 1451 target = sc.breakTarget; 1452 if(!target) 1453 { 1454 error(sc, ERR_MISPLACED_BREAK); 1455 return null; 1456 } 1457 } 1458 else 1459 { 1460 LabelSymbol ls; 1461 1462 ls = sc.searchLabel(ident); 1463 if(!ls || !ls.statement) 1464 { 1465 error(sc, errmsgtbl[ERR_UNDEFINED_STATEMENT_LABEL], ident.toString()); 1466 return null; 1467 } 1468 else if(!sc.breakTarget) 1469 { 1470 error(sc, errmsgtbl[ERR_MISPLACED_BREAK]); 1471 } 1472 else{ 1473 //Scope* s; 1474 //for(s = sc; s && s != ls.statement.whichScope; s = s.enclosing){ } 1475 if(ls.statement.whichScope == *sc) 1476 error(sc,errmsgtbl[ERR_CANT_BREAK_INTERNAL],ls.ident.value..string); 1477 target = ls.statement; 1478 } 1479 } 1480 return this; 1481 } 1482 1483 override void toIR(IRstate *irs) 1484 { 1485 ScopeStatement w; 1486 ScopeStatement tw; 1487 1488 assert(target); 1489 tw = target.getScope(); 1490 for(w = irs.scopeContext; !(w is tw); w = w.enclosingScope) 1491 { 1492 assert(w); 1493 irs.pops(w.npops); 1494 } 1495 1496 irs.addFixup(irs.getIP()); 1497 irs.gen1(loc, IRjmp, cast(IRstate.Op)cast(void*)this); 1498 } 1499 1500 override uint getTarget() 1501 { 1502 assert(target); 1503 return target.getBreak(); 1504 } 1505 } 1506 1507 /******************************** GotoStatement ***************************/ 1508 1509 class GotoStatement : Statement 1510 { 1511 Identifier *ident; 1512 LabelSymbol label; 1513 1514 this(Loc loc, Identifier * ident) 1515 { 1516 super(loc); 1517 this.ident = ident; 1518 label = null; 1519 } 1520 1521 override Statement semantic(Scope *sc) 1522 { 1523 LabelSymbol ls; 1524 1525 ls = sc.searchLabel(ident); 1526 if(!ls) 1527 { 1528 ls = new LabelSymbol(loc, ident, null); 1529 sc.insertLabel(ls); 1530 } 1531 label = ls; 1532 return this; 1533 } 1534 1535 override void toIR(IRstate *irs) 1536 { 1537 assert(label); 1538 1539 // Determine how many with pops we need to do 1540 for(ScopeStatement w = irs.scopeContext;; w = w.enclosingScope) 1541 { 1542 if(!w) 1543 { 1544 if(label.statement.scopeContext) 1545 { 1546 assert(0); // BUG: should do next statement instead 1547 //script.error(errmsgtbl[ERR_GOTO_INTO_WITH]); 1548 } 1549 break; 1550 } 1551 if(w is label.statement.scopeContext) 1552 break; 1553 irs.pops(w.npops); 1554 } 1555 1556 irs.addFixup(irs.getIP()); 1557 irs.gen1(loc, IRjmp, cast(IRstate.Op)cast(void*)this); 1558 } 1559 1560 override uint getTarget() 1561 { 1562 return label.statement.getGoto(); 1563 } 1564 } 1565 1566 /******************************** ReturnStatement ***************************/ 1567 1568 class ReturnStatement : Statement 1569 { 1570 Expression exp; 1571 1572 this(Loc loc, Expression exp) 1573 { 1574 super(loc); 1575 this.exp = exp; 1576 } 1577 1578 override Statement semantic(Scope *sc) 1579 { 1580 if(exp) 1581 exp = exp.semantic(sc); 1582 1583 // Don't allow return from eval functions or global function 1584 if(sc.funcdef.iseval || sc.funcdef.isglobal) 1585 error(sc, ERR_MISPLACED_RETURN); 1586 1587 return this; 1588 } 1589 1590 override void toBuffer(ref tchar[] buf) 1591 { 1592 //writef("ReturnStatement.toBuffer()\n"); 1593 buf ~= "return "; 1594 if(exp) 1595 exp.toBuffer(buf); 1596 buf ~= ";\n"; 1597 } 1598 1599 override void toIR(IRstate *irs) 1600 { 1601 ScopeStatement w; 1602 int npops; 1603 1604 npops = 0; 1605 for(w = irs.scopeContext; w; w = w.enclosingScope) 1606 npops += w.npops; 1607 1608 if(exp) 1609 { 1610 uint e; 1611 1612 e = irs.alloc(1); 1613 exp.toIR(irs, e); 1614 if(npops) 1615 { 1616 irs.gen1(loc, IRimpret, e); 1617 irs.pops(npops); 1618 irs.gen0(loc, IRret); 1619 } 1620 else 1621 irs.gen1(loc, IRretexp, e); 1622 irs.release(e, 1); 1623 } 1624 else 1625 { 1626 if(npops) 1627 irs.pops(npops); 1628 irs.gen0(loc, IRret); 1629 } 1630 1631 // Help GC 1632 exp = null; 1633 } 1634 } 1635 1636 /******************************** ImpliedReturnStatement ***************************/ 1637 1638 // Same as ReturnStatement, except that the return value is set but the 1639 // function does not actually return. Useful for setting the return 1640 // value for loop bodies. 1641 1642 class ImpliedReturnStatement : Statement 1643 { 1644 Expression exp; 1645 1646 this(Loc loc, Expression exp) 1647 { 1648 super(loc); 1649 this.exp = exp; 1650 } 1651 1652 override Statement semantic(Scope *sc) 1653 { 1654 if(exp) 1655 exp = exp.semantic(sc); 1656 return this; 1657 } 1658 1659 override void toBuffer(ref tchar[] buf) 1660 { 1661 if(exp) 1662 exp.toBuffer(buf); 1663 buf ~= ";\n"; 1664 } 1665 1666 override void toIR(IRstate *irs) 1667 { 1668 if(exp) 1669 { 1670 uint e; 1671 1672 e = irs.alloc(1); 1673 exp.toIR(irs, e); 1674 irs.gen1(loc, IRimpret, e); 1675 irs.release(e, 1); 1676 1677 // Help GC 1678 exp = null; 1679 } 1680 } 1681 } 1682 1683 /******************************** ThrowStatement ***************************/ 1684 1685 class ThrowStatement : Statement 1686 { 1687 Expression exp; 1688 1689 this(Loc loc, Expression exp) 1690 { 1691 super(loc); 1692 this.exp = exp; 1693 } 1694 1695 override Statement semantic(Scope *sc) 1696 { 1697 if(exp) 1698 exp = exp.semantic(sc); 1699 else 1700 { 1701 error(sc, ERR_NO_THROW_EXPRESSION); 1702 return new EmptyStatement(loc); 1703 } 1704 return this; 1705 } 1706 1707 override void toBuffer(ref tchar[] buf) 1708 { 1709 buf ~= "throw "; 1710 if(exp) 1711 exp.toBuffer(buf); 1712 buf ~= ";\n"; 1713 } 1714 1715 override void toIR(IRstate *irs) 1716 { 1717 uint e; 1718 1719 assert(exp); 1720 e = irs.alloc(1); 1721 exp.toIR(irs, e); 1722 irs.gen1(loc, IRthrow, e); 1723 irs.release(e, 1); 1724 1725 // Help GC 1726 exp = null; 1727 } 1728 } 1729 1730 /******************************** TryStatement ***************************/ 1731 1732 class TryStatement : ScopeStatement 1733 { 1734 Statement bdy; 1735 Identifier* catchident; 1736 Statement catchbdy; 1737 Statement finalbdy; 1738 1739 this(Loc loc, Statement bdy, 1740 Identifier * catchident, Statement catchbdy, 1741 Statement finalbdy) 1742 { 1743 super(loc); 1744 this.bdy = bdy; 1745 this.catchident = catchident; 1746 this.catchbdy = catchbdy; 1747 this.finalbdy = finalbdy; 1748 if(catchbdy && finalbdy) 1749 npops = 2; // 2 items in scope chain 1750 } 1751 1752 override Statement semantic(Scope *sc) 1753 { 1754 enclosingScope = sc.scopeContext; 1755 sc.scopeContext = this; 1756 1757 // So enclosing FunctionDeclaration knows how deep the With's 1758 // can nest 1759 if(enclosingScope) 1760 depth = enclosingScope.depth + 1; 1761 if(depth > sc.funcdef.withdepth) 1762 sc.funcdef.withdepth = depth; 1763 1764 bdy.semantic(sc); 1765 if(catchbdy) 1766 catchbdy.semantic(sc); 1767 if(finalbdy) 1768 finalbdy.semantic(sc); 1769 1770 sc.scopeContext = enclosingScope; 1771 return this; 1772 } 1773 1774 override void toBuffer(ref tchar[] buf) 1775 { 1776 buf ~= "try\n"; 1777 bdy.toBuffer(buf); 1778 if(catchident) 1779 { 1780 buf ~= "catch (" ~ 1781 catchident.toString() ~ 1782 ")\n"; 1783 } 1784 if(catchbdy) 1785 catchbdy.toBuffer(buf); 1786 if(finalbdy) 1787 { 1788 buf ~= "finally\n"; 1789 finalbdy.toBuffer(buf); 1790 } 1791 } 1792 1793 override void toIR(IRstate *irs) 1794 { 1795 uint f; 1796 uint c; 1797 uint e; 1798 uint e2; 1799 uint marksave = irs.mark(); 1800 1801 irs.scopeContext = this; 1802 if(finalbdy) 1803 { 1804 f = irs.getIP(); 1805 irs.gen1(loc, IRtryfinally, 0); 1806 if(catchbdy) 1807 { 1808 c = irs.getIP(); 1809 irs.gen2(loc, IRtrycatch, 0, cast(IRstate.Op)Identifier.build(catchident.toString())); 1810 bdy.toIR(irs); 1811 irs.gen0(loc, IRpop); // remove catch clause 1812 irs.gen0(loc, IRpop); // call finalbdy 1813 1814 e = irs.getIP(); 1815 irs.gen1(loc, IRjmp, 0); 1816 irs.patchJmp(c, irs.getIP()); 1817 catchbdy.toIR(irs); 1818 irs.gen0(loc, IRpop); // remove catch object 1819 irs.gen0(loc, IRpop); // call finalbdy code 1820 e2 = irs.getIP(); 1821 irs.gen1(loc, IRjmp, 0); // jmp past finalbdy 1822 1823 irs.patchJmp(f, irs.getIP()); 1824 irs.scopeContext = enclosingScope; 1825 finalbdy.toIR(irs); 1826 irs.gen0(loc, IRfinallyret); 1827 irs.patchJmp(e, irs.getIP()); 1828 irs.patchJmp(e2, irs.getIP()); 1829 } 1830 else // finalbdy only 1831 { 1832 bdy.toIR(irs); 1833 irs.gen0(loc, IRpop); 1834 e = irs.getIP(); 1835 irs.gen1(loc, IRjmp, 0); 1836 irs.patchJmp(f, irs.getIP()); 1837 irs.scopeContext = enclosingScope; 1838 finalbdy.toIR(irs); 1839 irs.gen0(loc, IRfinallyret); 1840 irs.patchJmp(e, irs.getIP()); 1841 } 1842 } 1843 else // catchbdy only 1844 { 1845 c = irs.getIP(); 1846 irs.gen2(loc, IRtrycatch, 0, cast(IRstate.Op)Identifier.build(catchident.toString())); 1847 bdy.toIR(irs); 1848 irs.gen0(loc, IRpop); 1849 e = irs.getIP(); 1850 irs.gen1(loc, IRjmp, 0); 1851 irs.patchJmp(c, irs.getIP()); 1852 catchbdy.toIR(irs); 1853 irs.gen0(loc, IRpop); 1854 irs.patchJmp(e, irs.getIP()); 1855 } 1856 irs.scopeContext = enclosingScope; 1857 irs.release(marksave); 1858 1859 // Help GC 1860 bdy = null; 1861 catchident = null; 1862 catchbdy = null; 1863 finalbdy = null; 1864 } 1865 }