Mercurial > projects > dmdscript-tango
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 |