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