Mercurial > projects > ddmd
annotate dmd/ContinueStatement.d @ 187:b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
author | Abscissa |
---|---|
date | Tue, 07 Jun 2011 23:37:34 -0400 |
parents | e3afd1303184 |
children |
rev | line source |
---|---|
0 | 1 module dmd.ContinueStatement; |
2 | |
114 | 3 import dmd.common; |
155 | 4 import dmd.interpret.Util; |
0 | 5 import dmd.Statement; |
6 import dmd.FuncDeclaration; | |
155 | 7 import dmd.GlobalExpressions; |
0 | 8 import dmd.IntegerExp; |
9 import dmd.ReturnStatement; | |
10 import dmd.LabelStatement; | |
11 import dmd.Identifier; | |
12 import dmd.Loc; | |
13 import dmd.Scope; | |
14 import dmd.Expression; | |
15 import dmd.InterState; | |
16 import dmd.HdrGenState; | |
17 import dmd.OutBuffer; | |
18 import dmd.IRState; | |
19 import dmd.BE; | |
20 | |
21 import dmd.backend.Util; | |
22 import dmd.backend.BC; | |
23 import dmd.backend.block; | |
24 import dmd.backend.Blockx; | |
25 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
26 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
27 |
0 | 28 class ContinueStatement : Statement |
29 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
30 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
31 |
0 | 32 Identifier ident; |
33 | |
34 this(Loc loc, Identifier ident) | |
35 { | |
178 | 36 register(); |
0 | 37 super(loc); |
38 this.ident = ident; | |
39 } | |
40 | |
72 | 41 override Statement syntaxCopy() |
0 | 42 { |
43 ContinueStatement s = new ContinueStatement(loc, ident); | |
44 return s; | |
45 } | |
46 | |
72 | 47 override Statement semantic(Scope sc) |
0 | 48 { |
49 //printf("ContinueStatement.semantic() %p\n", this); | |
50 if (ident) | |
51 { | |
52 Scope scx; | |
53 FuncDeclaration thisfunc = sc.func; | |
54 | |
55 for (scx = sc; scx; scx = scx.enclosing) | |
56 { | |
57 LabelStatement ls; | |
58 | |
59 if (scx.func != thisfunc) // if in enclosing function | |
60 { | |
61 if (sc.fes) // if this is the body of a foreach | |
62 { | |
63 for (; scx; scx = scx.enclosing) | |
64 { | |
65 ls = scx.slabel; | |
66 if (ls && ls.ident == ident && ls.statement == sc.fes) | |
67 { | |
68 // Replace continue ident; with return 0; | |
69 return new ReturnStatement(Loc(0), new IntegerExp(0)); | |
70 } | |
71 } | |
72 | |
73 /* Post this statement to the fes, and replace | |
74 * it with a return value that caller will put into | |
75 * a switch. Caller will figure out where the break | |
76 * label actually is. | |
77 * Case numbers start with 2, not 0, as 0 is continue | |
78 * and 1 is break. | |
79 */ | |
80 Statement s; | |
81 sc.fes.cases.push(cast(void*)this); | |
82 s = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1)); | |
83 return s; | |
84 } | |
85 break; // can't continue to it | |
86 } | |
87 | |
88 ls = scx.slabel; | |
89 if (ls && ls.ident == ident) | |
90 { | |
91 Statement s = ls.statement; | |
92 | |
93 if (!s.hasContinue()) | |
94 error("label '%s' has no continue", ident.toChars()); | |
95 if (ls.tf != sc.tf) | |
96 error("cannot continue out of finally block"); | |
97 return this; | |
98 } | |
99 } | |
100 error("enclosing label '%s' for continue not found", ident.toChars()); | |
101 } | |
102 else if (!sc.scontinue) | |
103 { | |
104 if (sc.fes) | |
105 { | |
106 Statement s; | |
107 | |
108 // Replace continue; with return 0; | |
109 s = new ReturnStatement(Loc(0), new IntegerExp(0)); | |
110 return s; | |
111 } | |
112 error("continue is not inside a loop"); | |
113 } | |
114 return this; | |
115 } | |
116 | |
72 | 117 override Expression interpret(InterState istate) |
0 | 118 { |
155 | 119 version(LOG) |
120 writef("ContinueStatement::interpret()\n"); | |
121 | |
122 mixin(START); | |
123 if (ident) | |
124 return EXP_CANT_INTERPRET; | |
125 else | |
126 return EXP_CONTINUE_INTERPRET; | |
0 | 127 } |
128 | |
72 | 129 override BE blockExit() |
0 | 130 { |
131 return ident ? BE.BEgoto : BE.BEcontinue; | |
132 } | |
133 | |
72 | 134 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 135 { |
136 buf.writestring("continue"); | |
137 if (ident) | |
138 { | |
139 buf.writebyte(' '); | |
140 buf.writestring(ident.toChars()); | |
141 } | |
142 buf.writebyte(';'); | |
143 buf.writenl(); | |
144 } | |
145 | |
72 | 146 override void toIR(IRState* irs) |
0 | 147 { |
148 block* bcont; | |
149 block* b; | |
150 Blockx* blx = irs.blx; | |
151 | |
152 //printf("ContinueStatement.toIR() %p\n", this); | |
153 bcont = irs.getContBlock(ident); | |
154 assert(bcont); | |
155 b = blx.curblock; | |
156 incUsage(irs, loc); | |
157 | |
158 // Adjust exception handler scope index if in different try blocks | |
159 if (b.Btry != bcont.Btry) | |
160 { | |
161 //setScopeIndex(blx, b, bcont.Btry ? bcont.Btry.Bscope_index : -1); | |
162 } | |
163 | |
164 /* Nothing more than a 'goto' to the current continue destination | |
165 */ | |
166 list_append(&b.Bsucc, bcont); | |
167 block_next(blx, BCgoto, null); | |
168 } | |
72 | 169 } |