comparison dmdscript_tango/expression.d @ 0:55c2951c07be

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