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 }