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