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