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