Mercurial > projects > dang
comparison ast/Stmt.d @ 150:6c5a3c0bb4fb
Make switch work again
Also added locations to statements (only filled out for switch)
Added a verification pass
Removed some comments
author | Anders Halager <halager@gmail.com> |
---|---|
date | Mon, 21 Jul 2008 20:35:03 +0200 |
parents | d76cc5cad4fc |
children | ee202c72cd30 |
comparison
equal
deleted
inserted
replaced
147:060b6eb16db9 | 150:6c5a3c0bb4fb |
---|---|
6 | 6 |
7 import ast.Exp, | 7 import ast.Exp, |
8 ast.Decl; | 8 ast.Decl; |
9 | 9 |
10 import sema.Scope, | 10 import sema.Scope, |
11 sema.VC, | |
12 basic.Message, | |
11 basic.SourceLocation; | 13 basic.SourceLocation; |
12 | 14 |
13 enum StmtType | 15 enum StmtType |
14 { | 16 { |
15 Stmt, | 17 Stmt, |
20 If, | 22 If, |
21 While, | 23 While, |
22 Switch, | 24 Switch, |
23 } | 25 } |
24 | 26 |
25 class Stmt | 27 abstract class Stmt |
26 { | 28 { |
27 this(StmtType stmtType = StmtType.Stmt) | 29 this(StmtType stmtType = StmtType.Stmt) |
28 { | 30 { |
29 this.stmtType = stmtType; | 31 this.stmtType = stmtType; |
30 } | 32 } |
31 | 33 |
32 void simplify() | 34 void simplify() |
33 { | 35 { |
34 } | 36 } |
37 | |
38 void verify(VC vc) {} | |
39 | |
40 /// The "main" location of the expression. | |
41 SourceLocation loc; | |
42 | |
43 /// Return the starting location of this statement | |
44 SourceLocation startLoc() { return loc; } | |
45 | |
46 /// Get the full extents of the expression | |
47 SourceRange sourceRange() { return SourceRange(loc, loc + 1); } | |
35 | 48 |
36 StmtType stmtType; | 49 StmtType stmtType; |
37 Scope env; | 50 Scope env; |
38 int stmtIndex; | 51 int stmtIndex; |
39 } | 52 } |
167 Stmt whileBody; | 180 Stmt whileBody; |
168 } | 181 } |
169 | 182 |
170 class SwitchStmt : Stmt | 183 class SwitchStmt : Stmt |
171 { | 184 { |
172 this(Exp target) | 185 this(SourceLocation loc, Exp target) |
173 { | 186 { |
174 super(StmtType.Switch); | 187 super(StmtType.Switch); |
175 cond = target; | 188 cond = target; |
176 } | 189 this.loc = loc; |
177 | 190 } |
178 void addCase(Exp[] values, Stmt[] stmts) | 191 |
179 { | 192 void addCase(SourceLocation _case, Exp[] values, Stmt[] stmts) |
180 // long[] new_values; | 193 { |
181 // foreach (lit; values) | 194 cases ~= Case(_case, values, stmts); |
182 // new_values ~= Integer.parse(lit.get); | 195 } |
183 // cases ~= Case(values, stmts, new_values); | 196 |
184 cases ~= Case(values, stmts); | 197 void setDefault(SourceLocation _default, Stmt[] stmts) |
185 | 198 { |
186 // Make sure there is no two cases with the same value | 199 if (defaultBlock !is null) |
187 // Does it belong here? | 200 extraDefaultBlocks = true; |
188 /+ new_values = new_values.dup; | 201 |
189 Array.sort(new_values); | |
190 long[] all_values = Array.unionOf(old_values, new_values); | |
191 if (all_values.length != old_values.length + new_values.length) | |
192 { | |
193 // overlap! | |
194 // TODO: Move this to another sema file where it can be enforced. | |
195 /+ auto e = new Error( | |
196 "Can't have multiple cases with the same value." | |
197 " Values appearing in multiple cases: %0"); | |
198 | |
199 //e.loc(values[0].token.location); | |
200 | |
201 all_values = Array.intersectionOf(old_values, new_values); | |
202 char[][] vals; | |
203 foreach (val; all_values) | |
204 vals ~= Integer.toString(val); | |
205 e.arg(vals); | |
206 /* | |
207 foreach (c; cases) | |
208 foreach (i, v; c.values_converted) | |
209 if (Array.bsearch(all_values, v)) | |
210 e.tok(c.values[i].token); | |
211 */ | |
212 throw e;+/ | |
213 } | |
214 old_values = all_values; | |
215 +/ | |
216 } | |
217 | |
218 void setDefault(Stmt[] stmts) | |
219 { | |
220 // TODO: Move this to another sema file where it can be enforced. | |
221 /* | |
222 if (defaultBlock.length != 0) | |
223 throw new Error("Switch statements can't have multiple defaults"); | |
224 */ | |
225 defaultBlock = stmts; | 202 defaultBlock = stmts; |
203 defaultLoc = _default; | |
226 if (cases.length > 0) | 204 if (cases.length > 0) |
227 cases[$ - 1].followedByDefault = true; | 205 cases[$ - 1].followedByDefault = true; |
228 } | 206 } |
229 | 207 |
230 override void simplify() | 208 override void simplify() |
235 foreach ( c ; cases ) | 213 foreach ( c ; cases ) |
236 foreach ( stmt ; c.stmts ) | 214 foreach ( stmt ; c.stmts ) |
237 stmt.simplify(); | 215 stmt.simplify(); |
238 } | 216 } |
239 | 217 |
218 override void verify(VC vc) | |
219 { | |
220 if (extraDefaultBlocks) | |
221 vc.msg.report(MultipleDefaults, defaultLoc); | |
222 | |
223 if (cases.length == 0) | |
224 return; | |
225 | |
226 scope long[] all_values; | |
227 foreach (ref Case; cases) | |
228 { | |
229 long[] new_values; | |
230 foreach (exp; Case.values) | |
231 if (auto lit = cast(IntegerLit)exp) | |
232 new_values ~= Integer.parse(lit.get); | |
233 else | |
234 // We flag all non-literals and ignore them | |
235 vc.msg.report(InvalidCaseValue, exp.loc); | |
236 Case.values_converted = new_values; | |
237 all_values ~= new_values; | |
238 } | |
239 | |
240 Array.sort(all_values); | |
241 char[][] overlapping; | |
242 size_t i = 0; | |
243 while ((i = Array.findAdj(all_values)) < all_values.length | |
244 && all_values.length > 0) | |
245 { | |
246 overlapping ~= Integer.toString(all_values[i]); | |
247 auto similar = Array.count(all_values, all_values[i]); | |
248 all_values = all_values[i + similar .. $]; | |
249 } | |
250 if (overlapping.length > 0) | |
251 vc.msg.report(OverlappingCases, loc).arg(overlapping); | |
252 } | |
253 | |
240 Exp cond; | 254 Exp cond; |
241 Case[] cases; | 255 Case[] cases; |
242 Stmt[] defaultBlock; | 256 Stmt[] defaultBlock; |
257 private bool extraDefaultBlocks = false; | |
258 private SourceLocation defaultLoc; | |
243 | 259 |
244 struct Case | 260 struct Case |
245 { | 261 { |
262 SourceLocation caseLoc; | |
246 Exp[] values; | 263 Exp[] values; |
247 Stmt[] stmts; | 264 Stmt[] stmts; |
248 long[] values_converted; | 265 long[] values_converted; |
249 bool followedByDefault = false; | 266 bool followedByDefault = false; |
250 } | 267 } |
251 | 268 } |
252 private long[] old_values; | 269 |
253 } | |
254 |