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.expression; 19 20 import std.string; 21 import std.algorithm; 22 import std.string; 23 import std.range; 24 import std.exception; 25 import std.stdio; 26 27 import dmdscript.script; 28 import dmdscript.lexer; 29 import dmdscript.scopex; 30 import dmdscript.text; 31 import dmdscript.errmsgs; 32 import dmdscript.functiondefinition; 33 import dmdscript.irstate; 34 import dmdscript.ir; 35 import dmdscript.opcodes; 36 import dmdscript.identifier; 37 38 /******************************** Expression **************************/ 39 40 class Expression 41 { 42 enum uint EXPRESSION_SIGNATURE = 0x3AF31E3F; 43 uint signature = EXPRESSION_SIGNATURE; 44 45 Loc loc; // file location 46 TOK op; 47 48 this(Loc loc, TOK op) 49 { 50 this.loc = loc; 51 this.op = op; 52 signature = EXPRESSION_SIGNATURE; 53 } 54 55 invariant() 56 { 57 assert(signature == EXPRESSION_SIGNATURE); 58 assert(op != TOKreserved && op < TOKmax); 59 } 60 61 /************************** 62 * Semantically analyze Expression. 63 * Determine types, fold constants, e 64 */ 65 66 Expression semantic(Scope *sc) 67 { 68 return this; 69 } 70 71 override d_string toString() 72 { 73 char[] buf; 74 75 toBuffer(buf); 76 return assumeUnique(buf); 77 } 78 79 void toBuffer(ref char[] buf) 80 { 81 buf ~= toString(); 82 } 83 84 void checkLvalue(Scope *sc) 85 { 86 d_string buf; 87 88 //writefln("checkLvalue(), op = %d", op); 89 if(sc.funcdef) 90 { 91 if(sc.funcdef.isAnonymous) 92 buf = "anonymous"; 93 else if(sc.funcdef.name) 94 buf = sc.funcdef.name.toString(); 95 } 96 buf ~= std..string.format("(%d) : Error: ", loc); 97 buf ~= std..string.format(errmsgtbl[ERR_CANNOT_ASSIGN_TO], toString()); 98 99 if(!sc.errinfo.message) 100 { 101 sc.errinfo.message = buf; 102 sc.errinfo.linnum = loc; 103 sc.errinfo.srcline = Lexer.locToSrcline(sc.getSource().ptr, loc); 104 } 105 } 106 107 // Do we match for purposes of optimization? 108 109 int match(Expression e) 110 { 111 return false; 112 } 113 114 // Is the result of the expression guaranteed to be a boolean? 115 116 int isBooleanResult() 117 { 118 return false; 119 } 120 121 void toIR(IRstate *irs, uint ret) 122 { 123 writef("Expression::toIR('%s')\n", toString()); 124 } 125 126 void toLvalue(IRstate *irs, out uint base, IR *property, out int opoff) 127 { 128 base = irs.alloc(1); 129 toIR(irs, base); 130 property.index = 0; 131 opoff = 3; 132 } 133 } 134 135 /******************************** RealExpression **************************/ 136 137 class RealExpression : Expression 138 { 139 real_t value; 140 141 this(Loc loc, real_t value) 142 { 143 super(loc, TOKreal); 144 this.value = value; 145 } 146 147 override d_string toString() 148 { 149 d_string buf; 150 long i; 151 152 i = cast(long)value; 153 if(i == value) 154 buf = std..string.format("%d", i); 155 else 156 buf = std..string.format("%g", value); 157 return buf; 158 } 159 160 override void toBuffer(ref tchar[] buf) 161 { 162 buf ~= std..string.format("%g", value); 163 } 164 165 override void toIR(IRstate *irs, uint ret) 166 { 167 //writef("RealExpression::toIR(%g)\n", value); 168 169 static assert(value.sizeof == 2 * uint.sizeof); 170 if(ret) 171 irs.genX(loc, IRnumber, ret, value); 172 } 173 } 174 175 /******************************** IdentifierExpression **************************/ 176 177 class IdentifierExpression : Expression 178 { 179 Identifier *ident; 180 181 this(Loc loc, Identifier * ident) 182 { 183 super(loc, TOKidentifier); 184 this.ident = ident; 185 } 186 187 override Expression semantic(Scope *sc) 188 { 189 return this; 190 } 191 192 override d_string toString() 193 { 194 return ident.toString(); 195 } 196 197 override void checkLvalue(Scope *sc) 198 { 199 } 200 201 override int match(Expression e) 202 { 203 if(e.op != TOKidentifier) 204 return 0; 205 206 IdentifierExpression ie = cast(IdentifierExpression)(e); 207 208 return ident == ie.ident; 209 } 210 211 override void toIR(IRstate *irs, uint ret) 212 { 213 Identifier* id = ident; 214 215 assert(id.sizeof == IRstate.Op.sizeof); 216 if(ret) 217 irs.gen2(loc, IRgetscope, ret, cast(IRstate.Op)id); 218 else 219 irs.gen1(loc,IRcheckref, cast(IRstate.Op)id); 220 } 221 222 override void toLvalue(IRstate *irs, out uint base, IR *property, out int opoff) 223 { 224 //irs.gen1(loc, IRthis, base); 225 property.id = ident; 226 opoff = 2; 227 base = ~0u; 228 } 229 } 230 231 /******************************** ThisExpression **************************/ 232 233 class ThisExpression : Expression 234 { 235 this(Loc loc) 236 { 237 super(loc, TOKthis); 238 } 239 240 override d_string toString() 241 { 242 return TEXT_this; 243 } 244 245 override Expression semantic(Scope *sc) 246 { 247 return this; 248 } 249 250 override void toIR(IRstate *irs, uint ret) 251 { 252 if(ret) 253 irs.gen1(loc, IRthis, ret); 254 } 255 } 256 257 /******************************** NullExpression **************************/ 258 259 class NullExpression : Expression 260 { 261 this(Loc loc) 262 { 263 super(loc, TOKnull); 264 } 265 266 override d_string toString() 267 { 268 return TEXT_null; 269 } 270 271 override void toIR(IRstate *irs, uint ret) 272 { 273 if(ret) 274 irs.gen1(loc, IRnull, ret); 275 } 276 } 277 278 /******************************** StringExpression **************************/ 279 280 class StringExpression : Expression 281 { 282 static import std.ascii; 283 import std.format : format; 284 285 d_string string; 286 287 this(Loc loc, d_string string) 288 { 289 //writefln("StringExpression('%s')", string); 290 super(loc, TOKstring); 291 this.string = string; 292 } 293 294 override void toBuffer(ref tchar[] buf) 295 { 296 buf ~= '"'; 297 foreach(dchar c; string) 298 { 299 switch(c) 300 { 301 case '"': 302 buf ~= '\\'; 303 goto Ldefault; 304 305 default: 306 Ldefault: 307 if(c & ~0xFF) 308 buf ~= format("\\u%04x", c); 309 else if(std.ascii.isPrintable(c)) 310 buf ~= cast(tchar)c; 311 else 312 buf ~= format("\\x%02x", c); 313 break; 314 } 315 } 316 buf ~= '"'; 317 } 318 319 override void toIR(IRstate *irs, uint ret) 320 { 321 static assert((Identifier*).sizeof == IRstate.Op.sizeof); 322 if(ret) 323 { 324 auto u = cast(IRstate.Op)Identifier.build(string); 325 irs.gen2(loc, IRstring, ret, u); 326 } 327 } 328 } 329 330 /******************************** RegExpLiteral **************************/ 331 332 class RegExpLiteral : Expression 333 { 334 d_string string; 335 336 this(Loc loc, d_string string) 337 { 338 //writefln("RegExpLiteral('%s')", string); 339 super(loc, TOKregexp); 340 this.string = string; 341 } 342 343 override void toBuffer(ref tchar[] buf) 344 { 345 buf ~= string; 346 } 347 348 override void toIR(IRstate *irs, uint ret) 349 { 350 d_string pattern; 351 d_string attribute = null; 352 sizediff_t e; 353 354 uint argc; 355 uint argv; 356 uint b; 357 358 // Regular expression is of the form: 359 // /pattern/attribute 360 361 // Parse out pattern and attribute strings 362 assert(string[0] == '/'); 363 e = std..string.lastIndexOf(string, '/'); 364 assert(e != -1); 365 pattern = string[1 .. e]; 366 argc = 1; 367 if(e + 1 < string.length) 368 { 369 attribute = string[e + 1 .. $]; 370 argc++; 371 } 372 373 // Generate new Regexp(pattern [, attribute]) 374 375 b = irs.alloc(1); 376 Identifier* re = Identifier.build(TEXT_RegExp); 377 irs.gen2(loc, IRgetscope, b, cast(IRstate.Op)re); 378 argv = irs.alloc(argc); 379 irs.gen2(loc, IRstring, argv, cast(IRstate.Op)Identifier.build(pattern)); 380 if(argc == 2) 381 irs.gen2(loc, IRstring, argv + 1 * INDEX_FACTOR, cast(IRstate.Op)Identifier.build(attribute)); 382 irs.gen4(loc, IRnew, ret, b, argc, argv); 383 irs.release(b, argc + 1); 384 } 385 } 386 387 /******************************** BooleanExpression **************************/ 388 389 class BooleanExpression : Expression 390 { 391 int boolean; 392 393 this(Loc loc, int boolean) 394 { 395 super(loc, TOKboolean); 396 this.boolean = boolean; 397 } 398 399 override d_string toString() 400 { 401 return boolean ? "true" : "false"; 402 } 403 404 override void toBuffer(ref tchar[] buf) 405 { 406 buf ~= toString(); 407 } 408 409 override int isBooleanResult() 410 { 411 return true; 412 } 413 414 override void toIR(IRstate *irs, uint ret) 415 { 416 if(ret) 417 irs.gen2(loc, IRboolean, ret, boolean); 418 } 419 } 420 421 /******************************** ArrayLiteral **************************/ 422 423 class ArrayLiteral : Expression 424 { 425 Expression[] elements; 426 427 this(Loc loc, Expression[] elements) 428 { 429 super(loc, TOKarraylit); 430 this.elements = elements; 431 } 432 433 override Expression semantic(Scope *sc) 434 { 435 foreach(ref Expression e; elements) 436 { 437 if(e) 438 e = e.semantic(sc); 439 } 440 return this; 441 } 442 443 override void toBuffer(ref tchar[] buf) 444 { 445 uint i; 446 447 buf ~= '['; 448 foreach(Expression e; elements) 449 { 450 if(i) 451 buf ~= ','; 452 i = 1; 453 if(e) 454 e.toBuffer(buf); 455 } 456 buf ~= ']'; 457 } 458 459 override void toIR(IRstate *irs, uint ret) 460 { 461 uint argc; 462 uint argv; 463 uint b; 464 uint v; 465 466 b = irs.alloc(1); 467 static Identifier* ar; 468 if(!ar) 469 ar = Identifier.build(TEXT_Array); 470 irs.gen2(loc, IRgetscope, b, cast(IRstate.Op)ar); 471 if(elements.length) 472 { 473 Expression e; 474 475 argc = cast(uint)elements.length; 476 argv = irs.alloc(argc); 477 if(argc > 1) 478 { 479 uint i; 480 481 // array literal [a, b, c] is equivalent to: 482 // new Array(a,b,c) 483 for(i = 0; i < argc; i++) 484 { 485 e = elements[i]; 486 if(e) 487 { 488 e.toIR(irs, argv + i * INDEX_FACTOR); 489 } 490 else 491 irs.gen1(loc, IRundefined, argv + i * INDEX_FACTOR); 492 } 493 irs.gen4(loc, IRnew, ret, b, argc, argv); 494 } 495 else 496 { // [a] translates to: 497 // ret = new Array(1); 498 // ret[0] = a 499 irs.genX(loc, IRnumber, argv, 1.0); 500 irs.gen4(loc, IRnew, ret, b, argc, argv); 501 502 e = elements[0]; 503 v = irs.alloc(1); 504 if(e) 505 e.toIR(irs, v); 506 else 507 irs.gen1(loc, IRundefined, v); 508 irs.gen3(loc, IRputs, v, ret, cast(IRstate.Op)Identifier.build(TEXT_0)); 509 irs.release(v, 1); 510 } 511 irs.release(argv, argc); 512 } 513 else 514 { 515 // Generate new Array() 516 irs.gen4(loc, IRnew, ret, b, 0, 0); 517 } 518 irs.release(b, 1); 519 } 520 } 521 522 /******************************** FieldLiteral **************************/ 523 524 class Field 525 { 526 Identifier* ident; 527 Expression exp; 528 529 this(Identifier * ident, Expression exp) 530 { 531 this.ident = ident; 532 this.exp = exp; 533 } 534 } 535 536 /******************************** ObjectLiteral **************************/ 537 538 class ObjectLiteral : Expression 539 { 540 Field[] fields; 541 542 this(Loc loc, Field[] fields) 543 { 544 super(loc, TOKobjectlit); 545 this.fields = fields; 546 } 547 548 override Expression semantic(Scope *sc) 549 { 550 foreach(Field f; fields) 551 { 552 f.exp = f.exp.semantic(sc); 553 } 554 return this; 555 } 556 557 override void toBuffer(ref tchar[] buf) 558 { 559 uint i; 560 561 buf ~= '{'; 562 foreach(Field f; fields) 563 { 564 if(i) 565 buf ~= ','; 566 i = 1; 567 buf ~= f.ident.toString(); 568 buf ~= ':'; 569 f.exp.toBuffer(buf); 570 } 571 buf ~= '}'; 572 } 573 574 override void toIR(IRstate *irs, uint ret) 575 { 576 uint b; 577 578 b = irs.alloc(1); 579 //irs.gen2(loc, IRstring, b, TEXT_Object); 580 Identifier* ob = Identifier.build(TEXT_Object); 581 irs.gen2(loc, IRgetscope, b, cast(IRstate.Op)ob); 582 // Generate new Object() 583 irs.gen4(loc, IRnew, ret, b, 0, 0); 584 if(fields.length) 585 { 586 uint x; 587 588 x = irs.alloc(1); 589 foreach(Field f; fields) 590 { 591 f.exp.toIR(irs, x); 592 irs.gen3(loc, IRputs, x, ret, cast(IRstate.Op)(f.ident)); 593 } 594 } 595 } 596 } 597 598 /******************************** FunctionLiteral **************************/ 599 600 class FunctionLiteral : Expression 601 { FunctionDefinition func; 602 603 this(Loc loc, FunctionDefinition func) 604 { 605 super(loc, TOKobjectlit); 606 this.func = func; 607 } 608 609 override Expression semantic(Scope *sc) 610 { 611 func = cast(FunctionDefinition)(func.semantic(sc)); 612 return this; 613 } 614 615 override void toBuffer(ref tchar[] buf) 616 { 617 func.toBuffer(buf); 618 } 619 620 override void toIR(IRstate *irs, uint ret) 621 { 622 func.toIR(null); 623 irs.gen2(loc, IRobject, ret, cast(IRstate.Op)cast(void*)func); 624 } 625 } 626 627 /***************************** UnaExp *************************************/ 628 629 class UnaExp : Expression 630 { 631 Expression e1; 632 633 this(Loc loc, TOK op, Expression e1) 634 { 635 super(loc, op); 636 this.e1 = e1; 637 } 638 639 override Expression semantic(Scope *sc) 640 { 641 e1 = e1.semantic(sc); 642 return this; 643 } 644 645 override void toBuffer(ref tchar[] buf) 646 { 647 buf ~= Token.toString(op); 648 buf ~= ' '; 649 e1.toBuffer(buf); 650 } 651 } 652 653 /***************************** BinExp *************************************/ 654 655 class BinExp : Expression 656 { 657 Expression e1; 658 Expression e2; 659 660 this(Loc loc, TOK op, Expression e1, Expression e2) 661 { 662 super(loc, op); 663 this.e1 = e1; 664 this.e2 = e2; 665 } 666 667 override Expression semantic(Scope *sc) 668 { 669 e1 = e1.semantic(sc); 670 e2 = e2.semantic(sc); 671 return this; 672 } 673 674 override void toBuffer(ref tchar[] buf) 675 { 676 e1.toBuffer(buf); 677 buf ~= ' '; 678 buf ~= Token.toString(op); 679 buf ~= ' '; 680 e2.toBuffer(buf); 681 } 682 683 void binIR(IRstate *irs, uint ret, uint ircode) 684 { 685 uint b; 686 uint c; 687 688 if(ret) 689 { 690 b = irs.alloc(1); 691 e1.toIR(irs, b); 692 if(e1.match(e2)) 693 { 694 irs.gen3(loc, ircode, ret, b, b); 695 } 696 else 697 { 698 c = irs.alloc(1); 699 e2.toIR(irs, c); 700 irs.gen3(loc, ircode, ret, b, c); 701 irs.release(c, 1); 702 } 703 irs.release(b, 1); 704 } 705 else 706 { 707 e1.toIR(irs, 0); 708 e2.toIR(irs, 0); 709 } 710 } 711 } 712 713 /************************************************************/ 714 715 /* Handle ++e and --e 716 */ 717 718 class PreExp : UnaExp 719 { 720 uint ircode; 721 722 this(Loc loc, uint ircode, Expression e) 723 { 724 super(loc, TOKplusplus, e); 725 this.ircode = ircode; 726 } 727 728 override Expression semantic(Scope *sc) 729 { 730 super.semantic(sc); 731 e1.checkLvalue(sc); 732 return this; 733 } 734 735 override void toBuffer(ref tchar[] buf) 736 { 737 e1.toBuffer(buf); 738 buf ~= Token.toString(op); 739 } 740 741 override void toIR(IRstate *irs, uint ret) 742 { 743 uint base; 744 IR property; 745 int opoff; 746 747 //writef("PreExp::toIR('%s')\n", toChars()); 748 e1.toLvalue(irs, base, &property, opoff); 749 assert(opoff != 3); 750 if(opoff == 2) 751 { 752 //irs.gen2(loc, ircode + 2, ret, property.index); 753 irs.gen3(loc, ircode + 2, ret, property.index, property.id.toHash()); 754 } 755 else 756 irs.gen3(loc, ircode + opoff, ret, base, property.index); 757 } 758 } 759 760 /************************************************************/ 761 762 class PostIncExp : UnaExp 763 { 764 this(Loc loc, Expression e) 765 { 766 super(loc, TOKplusplus, e); 767 } 768 769 override Expression semantic(Scope *sc) 770 { 771 super.semantic(sc); 772 e1.checkLvalue(sc); 773 return this; 774 } 775 776 override void toBuffer(ref tchar[] buf) 777 { 778 e1.toBuffer(buf); 779 buf ~= Token.toString(op); 780 } 781 782 override void toIR(IRstate *irs, uint ret) 783 { 784 uint base; 785 IR property; 786 int opoff; 787 788 //writef("PostIncExp::toIR('%s')\n", toChars()); 789 e1.toLvalue(irs, base, &property, opoff); 790 assert(opoff != 3); 791 if(opoff == 2) 792 { 793 if(ret) 794 { 795 irs.gen2(loc, IRpostincscope, ret, property.index); 796 } 797 else 798 { 799 //irs.gen2(loc, IRpreincscope, ret, property.index); 800 irs.gen3(loc, IRpreincscope, ret, property.index, property.id.toHash()); 801 } 802 } 803 else 804 irs.gen3(loc, (ret ? IRpostinc : IRpreinc) + opoff, ret, base, property.index); 805 } 806 } 807 808 /****************************************************************/ 809 810 class PostDecExp : UnaExp 811 { 812 this(Loc loc, Expression e) 813 { 814 super(loc, TOKplusplus, e); 815 } 816 817 override Expression semantic(Scope *sc) 818 { 819 super.semantic(sc); 820 e1.checkLvalue(sc); 821 return this; 822 } 823 824 override void toBuffer(ref tchar[] buf) 825 { 826 e1.toBuffer(buf); 827 buf ~= Token.toString(op); 828 } 829 830 override void toIR(IRstate *irs, uint ret) 831 { 832 uint base; 833 IR property; 834 int opoff; 835 836 //writef("PostDecExp::toIR('%s')\n", toChars()); 837 e1.toLvalue(irs, base, &property, opoff); 838 assert(opoff != 3); 839 if(opoff == 2) 840 { 841 if(ret) 842 { 843 irs.gen2(loc, IRpostdecscope, ret, property.index); 844 } 845 else 846 { 847 //irs.gen2(loc, IRpredecscope, ret, property.index); 848 irs.gen3(loc, IRpredecscope, ret, property.index, property.id.toHash()); 849 } 850 } 851 else 852 irs.gen3(loc, (ret ? IRpostdec : IRpredec) + opoff, ret, base, property.index); 853 } 854 } 855 856 /************************************************************/ 857 858 class DotExp : UnaExp 859 { 860 Identifier *ident; 861 862 this(Loc loc, Expression e, Identifier * ident) 863 { 864 super(loc, TOKdot, e); 865 this.ident = ident; 866 } 867 868 override void checkLvalue(Scope *sc) 869 { 870 } 871 872 override void toBuffer(ref tchar[] buf) 873 { 874 e1.toBuffer(buf); 875 buf ~= '.'; 876 buf ~= ident.toString(); 877 } 878 879 override void toIR(IRstate *irs, uint ret) 880 { 881 uint base; 882 883 //writef("DotExp::toIR('%s')\n", toChars()); 884 version(all) 885 { 886 // Some test cases depend on things like: 887 // foo.bar; 888 // generating a property get even if the result is thrown away. 889 base = irs.alloc(1); 890 e1.toIR(irs, base); 891 irs.gen3(loc, IRgets, ret, base, cast(IRstate.Op)ident); 892 } 893 else 894 { 895 if(ret) 896 { 897 base = irs.alloc(1); 898 e1.toIR(irs, base); 899 irs.gen3(loc, IRgets, ret, base, cast(IRstate.Op)ident); 900 } 901 else 902 e1.toIR(irs, 0); 903 } 904 } 905 906 override void toLvalue(IRstate *irs, out uint base, IR *property, out int opoff) 907 { 908 base = irs.alloc(1); 909 e1.toIR(irs, base); 910 property.id = ident; 911 opoff = 1; 912 } 913 } 914 915 /************************************************************/ 916 917 class CallExp : UnaExp 918 { 919 Expression[] arguments; 920 921 this(Loc loc, Expression e, Expression[] arguments) 922 { 923 //writef("CallExp(e1 = %x)\n", e); 924 super(loc, TOKcall, e); 925 this.arguments = arguments; 926 } 927 928 override Expression semantic(Scope *sc) 929 { 930 IdentifierExpression ie; 931 932 //writef("CallExp(e1=%x, %d, vptr=%x)\n", e1, e1.op, *(uint *)e1); 933 //writef("CallExp(e1='%s')\n", e1.toString()); 934 e1 = e1.semantic(sc); 935 /*if(e1.op != TOKcall) 936 e1.checkLvalue(sc); 937 */ 938 foreach(ref Expression e; arguments) 939 { 940 e = e.semantic(sc); 941 } 942 if(arguments.length == 1) 943 { 944 if(e1.op == TOKidentifier) 945 { 946 ie = cast(IdentifierExpression )e1; 947 if(ie.ident.toString() == "assert") 948 { 949 return new AssertExp(loc, arguments[0]); 950 } 951 } 952 } 953 return this; 954 } 955 956 override void toBuffer(ref tchar[] buf) 957 { 958 e1.toBuffer(buf); 959 buf ~= '('; 960 for(size_t u = 0; u < arguments.length; u++) 961 { 962 if(u) 963 buf ~= ", "; 964 arguments[u].toBuffer(buf); 965 } 966 buf ~= ')'; 967 } 968 969 override void toIR(IRstate *irs, uint ret) 970 { 971 // ret = base.property(argc, argv) 972 // CALL ret,base,property,argc,argv 973 uint base; 974 uint argc; 975 uint argv; 976 IR property; 977 int opoff; 978 979 //writef("CallExp::toIR('%s')\n", toChars()); 980 e1.toLvalue(irs, base, &property, opoff); 981 982 if(arguments.length) 983 { 984 uint u; 985 986 argc = cast(uint)arguments.length; 987 argv = irs.alloc(argc); 988 for(u = 0; u < argc; u++) 989 { 990 Expression e; 991 992 e = arguments[u]; 993 e.toIR(irs, argv + u * INDEX_FACTOR); 994 } 995 arguments[] = null; // release to GC 996 arguments = null; 997 } 998 else 999 { 1000 argc = 0; 1001 argv = 0; 1002 } 1003 1004 if(opoff == 3) 1005 irs.gen4(loc, IRcallv, ret, base, argc, argv); 1006 else if(opoff == 2) 1007 irs.gen4(loc, IRcallscope, ret, property.index, argc, argv); 1008 else 1009 irs.genX(loc, IRcall + opoff, ret, base, property, argc, argv); 1010 irs.release(argv, argc); 1011 } 1012 } 1013 1014 /************************************************************/ 1015 1016 class AssertExp : UnaExp 1017 { 1018 this(Loc loc, Expression e) 1019 { 1020 super(loc, TOKassert, e); 1021 } 1022 1023 override void toBuffer(ref tchar[] buf) 1024 { 1025 buf ~= "assert("; 1026 e1.toBuffer(buf); 1027 buf ~= ')'; 1028 } 1029 1030 override void toIR(IRstate *irs, uint ret) 1031 { 1032 uint linnum; 1033 uint u; 1034 uint b; 1035 1036 b = ret ? ret : irs.alloc(1); 1037 1038 e1.toIR(irs, b); 1039 u = irs.getIP(); 1040 irs.gen2(loc, IRjt, 0, b); 1041 linnum = cast(uint)loc; 1042 irs.gen1(loc, IRassert, linnum); 1043 irs.patchJmp(u, irs.getIP()); 1044 1045 if(!ret) 1046 irs.release(b, 1); 1047 } 1048 } 1049 1050 /************************* NewExp ***********************************/ 1051 1052 class NewExp : UnaExp 1053 { 1054 Expression[] arguments; 1055 1056 this(Loc loc, Expression e, Expression[] arguments) 1057 { 1058 super(loc, TOKnew, e); 1059 this.arguments = arguments; 1060 } 1061 1062 override Expression semantic(Scope *sc) 1063 { 1064 e1 = e1.semantic(sc); 1065 for(size_t a = 0; a < arguments.length; a++) 1066 { 1067 arguments[a] = arguments[a].semantic(sc); 1068 } 1069 return this; 1070 } 1071 1072 override void toBuffer(ref tchar[] buf) 1073 { 1074 buf ~= Token.toString(op); 1075 buf ~= ' '; 1076 1077 e1.toBuffer(buf); 1078 buf ~= '('; 1079 for(size_t a = 0; a < arguments.length; a++) 1080 { 1081 arguments[a].toBuffer(buf); 1082 } 1083 buf ~= ')'; 1084 } 1085 1086 override void toIR(IRstate *irs, uint ret) 1087 { 1088 // ret = new b(argc, argv) 1089 // CALL ret,b,argc,argv 1090 uint b; 1091 uint argc; 1092 uint argv; 1093 1094 //writef("NewExp::toIR('%s')\n", toChars()); 1095 b = irs.alloc(1); 1096 e1.toIR(irs, b); 1097 if(arguments.length) 1098 { 1099 uint u; 1100 1101 argc = cast(uint)arguments.length; 1102 argv = irs.alloc(argc); 1103 for(u = 0; u < argc; u++) 1104 { 1105 Expression e; 1106 1107 e = arguments[u]; 1108 e.toIR(irs, argv + u * INDEX_FACTOR); 1109 } 1110 } 1111 else 1112 { 1113 argc = 0; 1114 argv = 0; 1115 } 1116 1117 irs.gen4(loc, IRnew, ret, b, argc, argv); 1118 irs.release(argv, argc); 1119 irs.release(b, 1); 1120 } 1121 } 1122 1123 /************************************************************/ 1124 1125 class XUnaExp : UnaExp 1126 { 1127 uint ircode; 1128 1129 this(Loc loc, TOK op, uint ircode, Expression e) 1130 { 1131 super(loc, op, e); 1132 this.ircode = ircode; 1133 } 1134 1135 override void toIR(IRstate *irs, uint ret) 1136 { 1137 e1.toIR(irs, ret); 1138 if(ret) 1139 irs.gen1(loc, ircode, ret); 1140 } 1141 } 1142 1143 class NotExp : XUnaExp 1144 { 1145 this(Loc loc, Expression e) 1146 { 1147 super(loc, TOKnot, IRnot, e); 1148 } 1149 1150 override int isBooleanResult() 1151 { 1152 return true; 1153 } 1154 } 1155 1156 class DeleteExp : UnaExp 1157 { 1158 bool lval; 1159 this(Loc loc, Expression e) 1160 { 1161 super(loc, TOKdelete, e); 1162 } 1163 1164 override Expression semantic(Scope *sc) 1165 { 1166 e1.checkLvalue(sc); 1167 lval = sc.errinfo.message == null; 1168 //delete don't have to operate on Lvalue, while slightly stupid but perfectly by the standard 1169 if(!lval) 1170 sc.errinfo.message = null; 1171 return this; 1172 } 1173 1174 override void toIR(IRstate *irs, uint ret) 1175 { 1176 uint base; 1177 IR property; 1178 int opoff; 1179 1180 if(lval){ 1181 e1.toLvalue(irs, base, &property, opoff); 1182 1183 assert(opoff != 3); 1184 if(opoff == 2) 1185 irs.gen2(loc, IRdelscope, ret, property.index); 1186 else 1187 irs.gen3(loc, IRdel + opoff, ret, base, property.index); 1188 }else{ 1189 //e1.toIR(irs,ret); 1190 irs.gen2(loc,IRboolean,ret,true); 1191 } 1192 } 1193 } 1194 1195 /************************* CommaExp ***********************************/ 1196 1197 class CommaExp : BinExp 1198 { 1199 this(Loc loc, Expression e1, Expression e2) 1200 { 1201 super(loc, TOKcomma, e1, e2); 1202 } 1203 1204 override void checkLvalue(Scope *sc) 1205 { 1206 e2.checkLvalue(sc); 1207 } 1208 1209 override void toIR(IRstate *irs, uint ret) 1210 { 1211 e1.toIR(irs, 0); 1212 e2.toIR(irs, ret); 1213 } 1214 } 1215 1216 /************************* ArrayExp ***********************************/ 1217 1218 class ArrayExp : BinExp 1219 { 1220 this(Loc loc, Expression e1, Expression e2) 1221 { 1222 super(loc, TOKarray, e1, e2); 1223 } 1224 1225 override Expression semantic(Scope *sc) 1226 { 1227 checkLvalue(sc); 1228 return this; 1229 } 1230 1231 override void checkLvalue(Scope *sc) 1232 { 1233 } 1234 1235 override void toBuffer(ref tchar[] buf) 1236 { 1237 e1.toBuffer(buf); 1238 buf ~= '['; 1239 e2.toBuffer(buf); 1240 buf ~= ']'; 1241 } 1242 1243 override void toIR(IRstate *irs, uint ret) 1244 { 1245 uint base; 1246 IR property; 1247 int opoff; 1248 1249 if(ret) 1250 { 1251 toLvalue(irs, base, &property, opoff); 1252 assert(opoff != 3); 1253 if(opoff == 2) 1254 irs.gen2(loc, IRgetscope, ret, property.index); 1255 else 1256 irs.gen3(loc, IRget + opoff, ret, base, property.index); 1257 } 1258 else 1259 { 1260 e1.toIR(irs, 0); 1261 e2.toIR(irs, 0); 1262 } 1263 } 1264 1265 override void toLvalue(IRstate *irs, out uint base, IR *property, out int opoff) 1266 { 1267 uint index; 1268 1269 base = irs.alloc(1); 1270 e1.toIR(irs, base); 1271 index = irs.alloc(1); 1272 e2.toIR(irs, index); 1273 property.index = index; 1274 opoff = 0; 1275 } 1276 } 1277 1278 /************************* AssignExp ***********************************/ 1279 1280 class AssignExp : BinExp 1281 { 1282 this(Loc loc, Expression e1, Expression e2) 1283 { 1284 super(loc, TOKassign, e1, e2); 1285 } 1286 1287 override Expression semantic(Scope *sc) 1288 { 1289 //writefln("AssignExp.semantic()"); 1290 super.semantic(sc); 1291 if(e1.op != TOKcall) // special case for CallExp lvalue's 1292 e1.checkLvalue(sc); 1293 return this; 1294 } 1295 1296 override void toIR(IRstate *irs, uint ret) 1297 { 1298 uint b; 1299 1300 //writef("AssignExp::toIR('%s')\n", toChars()); 1301 if(e1.op == TOKcall) // if CallExp 1302 { 1303 assert(cast(CallExp)(e1)); // make sure we got it right 1304 1305 // Special case a function call as an lvalue. 1306 // This can happen if: 1307 // foo() = 3; 1308 // A Microsoft extension, it means to assign 3 to the default property of 1309 // the object returned by foo(). It only has meaning for com objects. 1310 // This functionality should be worked into toLvalue() if it gets used 1311 // elsewhere. 1312 1313 uint base; 1314 uint argc; 1315 uint argv; 1316 IR property; 1317 int opoff; 1318 CallExp ec = cast(CallExp)e1; 1319 1320 if(ec.arguments.length) 1321 argc = cast(uint)ec.arguments.length + 1; 1322 else 1323 argc = 1; 1324 1325 argv = irs.alloc(argc); 1326 1327 e2.toIR(irs, argv + (argc - 1) * INDEX_FACTOR); 1328 1329 ec.e1.toLvalue(irs, base, &property, opoff); 1330 1331 if(ec.arguments.length) 1332 { 1333 uint u; 1334 1335 for(u = 0; u < ec.arguments.length; u++) 1336 { 1337 Expression e; 1338 1339 e = ec.arguments[u]; 1340 e.toIR(irs, argv + (u + 0) * INDEX_FACTOR); 1341 } 1342 ec.arguments[] = null; // release to GC 1343 ec.arguments = null; 1344 } 1345 1346 if(opoff == 3) 1347 irs.gen4(loc, IRputcallv, ret, base, argc, argv); 1348 else if(opoff == 2) 1349 irs.gen4(loc, IRputcallscope, ret, property.index, argc, argv); 1350 else 1351 irs.genX(loc, IRputcall + opoff, ret, base, property, argc, argv); 1352 irs.release(argv, argc); 1353 } 1354 else 1355 { 1356 uint base; 1357 IR property; 1358 int opoff; 1359 1360 b = ret ? ret : irs.alloc(1); 1361 e2.toIR(irs, b); 1362 1363 e1.toLvalue(irs, base, &property, opoff); 1364 assert(opoff != 3); 1365 if(opoff == 2) 1366 irs.gen2(loc, IRputscope, b, property.index); 1367 else 1368 irs.gen3(loc, IRput + opoff, b, base, property.index); 1369 if(!ret) 1370 irs.release(b, 1); 1371 } 1372 } 1373 } 1374 1375 /************************* AddAssignExp ***********************************/ 1376 1377 class AddAssignExp : BinExp 1378 { 1379 this(Loc loc, Expression e1, Expression e2) 1380 { 1381 super(loc, TOKplusass, e1, e2); 1382 } 1383 1384 override Expression semantic(Scope *sc) 1385 { 1386 super.semantic(sc); 1387 e1.checkLvalue(sc); 1388 return this; 1389 } 1390 1391 override void toIR(IRstate *irs, uint ret) 1392 { 1393 /*if(ret == 0 && e2.op == TOKreal && 1394 (cast(RealExpression)e2).value == 1)//disabled for better standard conformance 1395 { 1396 uint base; 1397 IR property; 1398 int opoff; 1399 1400 //writef("AddAssign to PostInc('%s')\n", toChars()); 1401 e1.toLvalue(irs, base, &property, opoff); 1402 assert(opoff != 3); 1403 if(opoff == 2) 1404 irs.gen2(loc, IRpostincscope, ret, property.index); 1405 else 1406 irs.gen3(loc, IRpostinc + opoff, ret, base, property.index); 1407 } 1408 else*/ 1409 { 1410 uint r; 1411 uint base; 1412 IR property; 1413 int opoff; 1414 1415 //writef("AddAssignExp::toIR('%s')\n", toChars()); 1416 e1.toLvalue(irs, base, &property, opoff); 1417 assert(opoff != 3); 1418 r = ret ? ret : irs.alloc(1); 1419 e2.toIR(irs, r); 1420 if(opoff == 2) 1421 irs.gen3(loc, IRaddassscope, r, property.index, property.id.toHash()); 1422 else 1423 irs.gen3(loc, IRaddass + opoff, r, base, property.index); 1424 if(!ret) 1425 irs.release(r, 1); 1426 } 1427 } 1428 } 1429 1430 /************************* BinAssignExp ***********************************/ 1431 1432 class BinAssignExp : BinExp 1433 { 1434 uint ircode = IRerror; 1435 1436 this(Loc loc, TOK op, uint ircode, Expression e1, Expression e2) 1437 { 1438 super(loc, op, e1, e2); 1439 this.ircode = ircode; 1440 } 1441 1442 override Expression semantic(Scope *sc) 1443 { 1444 super.semantic(sc); 1445 e1.checkLvalue(sc); 1446 return this; 1447 } 1448 1449 override void toIR(IRstate *irs, uint ret) 1450 { 1451 uint b; 1452 uint c; 1453 uint r; 1454 uint base; 1455 IR property; 1456 int opoff; 1457 1458 //writef("BinExp::binAssignIR('%s')\n", toChars()); 1459 e1.toLvalue(irs, base, &property, opoff); 1460 assert(opoff != 3); 1461 b = irs.alloc(1); 1462 if(opoff == 2) 1463 irs.gen2(loc, IRgetscope, b, property.index); 1464 else 1465 irs.gen3(loc, IRget + opoff, b, base, property.index); 1466 c = irs.alloc(1); 1467 e2.toIR(irs, c); 1468 r = ret ? ret : irs.alloc(1); 1469 irs.gen3(loc, ircode, r, b, c); 1470 if(opoff == 2) 1471 irs.gen2(loc, IRputscope, r, property.index); 1472 else 1473 irs.gen3(loc, IRput + opoff, r, base, property.index); 1474 if(!ret) 1475 irs.release(r, 1); 1476 } 1477 } 1478 1479 /************************* AddExp *****************************/ 1480 1481 class AddExp : BinExp 1482 { 1483 this(Loc loc, Expression e1, Expression e2) 1484 { 1485 super(loc, TOKplus, e1, e2); 1486 } 1487 1488 override Expression semantic(Scope *sc) 1489 { 1490 return this; 1491 } 1492 1493 override void toIR(IRstate *irs, uint ret) 1494 { 1495 binIR(irs, ret, IRadd); 1496 } 1497 } 1498 1499 /************************* XBinExp ***********************************/ 1500 1501 class XBinExp : BinExp 1502 { 1503 uint ircode = IRerror; 1504 1505 this(Loc loc, TOK op, uint ircode, Expression e1, Expression e2) 1506 { 1507 super(loc, op, e1, e2); 1508 this.ircode = ircode; 1509 } 1510 1511 override void toIR(IRstate *irs, uint ret) 1512 { 1513 binIR(irs, ret, ircode); 1514 } 1515 } 1516 1517 /************************* OrOrExp ***********************************/ 1518 1519 class OrOrExp : BinExp 1520 { 1521 this(Loc loc, Expression e1, Expression e2) 1522 { 1523 super(loc, TOKoror, e1, e2); 1524 } 1525 1526 override void toIR(IRstate *irs, uint ret) 1527 { 1528 uint u; 1529 uint b; 1530 1531 if(ret) 1532 b = ret; 1533 else 1534 b = irs.alloc(1); 1535 1536 e1.toIR(irs, b); 1537 u = irs.getIP(); 1538 irs.gen2(loc, IRjt, 0, b); 1539 e2.toIR(irs, ret); 1540 irs.patchJmp(u, irs.getIP()); 1541 1542 if(!ret) 1543 irs.release(b, 1); 1544 } 1545 } 1546 1547 /************************* AndAndExp ***********************************/ 1548 1549 class AndAndExp : BinExp 1550 { 1551 this(Loc loc, Expression e1, Expression e2) 1552 { 1553 super(loc, TOKandand, e1, e2); 1554 } 1555 1556 override void toIR(IRstate *irs, uint ret) 1557 { 1558 uint u; 1559 uint b; 1560 1561 if(ret) 1562 b = ret; 1563 else 1564 b = irs.alloc(1); 1565 1566 e1.toIR(irs, b); 1567 u = irs.getIP(); 1568 irs.gen2(loc, IRjf, 0, b); 1569 e2.toIR(irs, ret); 1570 irs.patchJmp(u, irs.getIP()); 1571 1572 if(!ret) 1573 irs.release(b, 1); 1574 } 1575 } 1576 1577 /************************* CmpExp ***********************************/ 1578 1579 1580 1581 class CmpExp : BinExp 1582 { 1583 uint ircode = IRerror; 1584 1585 this(Loc loc, TOK tok, uint ircode, Expression e1, Expression e2) 1586 { 1587 super(loc, tok, e1, e2); 1588 this.ircode = ircode; 1589 } 1590 1591 override int isBooleanResult() 1592 { 1593 return true; 1594 } 1595 1596 override void toIR(IRstate *irs, uint ret) 1597 { 1598 binIR(irs, ret, ircode); 1599 } 1600 } 1601 1602 /*************************** InExp **************************/ 1603 1604 class InExp : BinExp 1605 { 1606 this(Loc loc, Expression e1, Expression e2) 1607 { 1608 super(loc, TOKin, e1, e2); 1609 } 1610 override void toIR(IRstate *irs, uint ret) 1611 { 1612 binIR(irs, ret, IRin); 1613 } 1614 } 1615 1616 /****************************************************************/ 1617 1618 class CondExp : BinExp 1619 { 1620 Expression econd; 1621 1622 this(Loc loc, Expression econd, Expression e1, Expression e2) 1623 { 1624 super(loc, TOKquestion, e1, e2); 1625 this.econd = econd; 1626 } 1627 1628 override void toIR(IRstate *irs, uint ret) 1629 { 1630 uint u1; 1631 uint u2; 1632 uint b; 1633 1634 if(ret) 1635 b = ret; 1636 else 1637 b = irs.alloc(1); 1638 1639 econd.toIR(irs, b); 1640 u1 = irs.getIP(); 1641 irs.gen2(loc, IRjf, 0, b); 1642 e1.toIR(irs, ret); 1643 u2 = irs.getIP(); 1644 irs.gen1(loc, IRjmp, 0); 1645 irs.patchJmp(u1, irs.getIP()); 1646 e2.toIR(irs, ret); 1647 irs.patchJmp(u2, irs.getIP()); 1648 1649 if(!ret) 1650 irs.release(b, 1); 1651 } 1652 } 1653