Mercurial > projects > ddmd
comparison dmd/ForeachRangeStatement.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.ForeachRangeStatement; | |
2 | |
3 import dmd.Statement; | |
4 import dmd.TOK; | |
5 import dmd.Argument; | |
6 import dmd.Expression; | |
7 import dmd.Statement; | |
8 import dmd.VarDeclaration; | |
9 import dmd.Scope; | |
10 import dmd.ExpInitializer; | |
11 import dmd.Identifier; | |
12 import dmd.Lexer; | |
13 import dmd.ArrayTypes; | |
14 import dmd.DeclarationStatement; | |
15 import dmd.CompoundDeclarationStatement; | |
16 import dmd.DeclarationExp; | |
17 import dmd.PostExp; | |
18 import dmd.VarExp; | |
19 import dmd.ForStatement; | |
20 import dmd.IntegerExp; | |
21 import dmd.AddAssignExp; | |
22 import dmd.CmpExp; | |
23 import dmd.IRState; | |
24 import dmd.InterState; | |
25 import dmd.OutBuffer; | |
26 import dmd.AddExp; | |
27 import dmd.WANT; | |
28 import dmd.ScopeDsymbol; | |
29 import dmd.HdrGenState; | |
30 import dmd.InlineScanState; | |
31 import dmd.Loc; | |
32 import dmd.BE; | |
33 | |
34 class ForeachRangeStatement : Statement | |
35 { | |
36 TOK op; // TOK.TOKforeach or TOK.TOKforeach_reverse | |
37 Argument arg; // loop index variable | |
38 Expression lwr; | |
39 Expression upr; | |
40 Statement body_; | |
41 | |
42 VarDeclaration key = null; | |
43 | |
44 this(Loc loc, TOK op, Argument arg, Expression lwr, Expression upr, Statement body_) | |
45 { | |
46 super(loc); | |
47 this.op = op; | |
48 this.arg = arg; | |
49 this.lwr = lwr; | |
50 this.upr = upr; | |
51 this.body_ = body_; | |
52 } | |
53 | |
54 Statement syntaxCopy() | |
55 { | |
56 ForeachRangeStatement s = new ForeachRangeStatement(loc, op, | |
57 arg.syntaxCopy(), | |
58 lwr.syntaxCopy(), | |
59 upr.syntaxCopy(), | |
60 body_ ? body_.syntaxCopy() : null); | |
61 | |
62 return s; | |
63 } | |
64 | |
65 Statement semantic(Scope sc) | |
66 { | |
67 //printf("ForeachRangeStatement.semantic() %p\n", this); | |
68 ScopeDsymbol sym; | |
69 Statement s = this; | |
70 | |
71 lwr = lwr.semantic(sc); | |
72 lwr = resolveProperties(sc, lwr); | |
73 lwr = lwr.optimize(WANTvalue); | |
74 if (!lwr.type) | |
75 { | |
76 error("invalid range lower bound %s", lwr.toChars()); | |
77 return this; | |
78 } | |
79 | |
80 upr = upr.semantic(sc); | |
81 upr = resolveProperties(sc, upr); | |
82 upr = upr.optimize(WANTvalue); | |
83 if (!upr.type) | |
84 { | |
85 error("invalid range upper bound %s", upr.toChars()); | |
86 return this; | |
87 } | |
88 | |
89 if (arg.type) | |
90 { | |
91 arg.type = arg.type.semantic(loc, sc); | |
92 lwr = lwr.implicitCastTo(sc, arg.type); | |
93 upr = upr.implicitCastTo(sc, arg.type); | |
94 } | |
95 else | |
96 { | |
97 /* Must infer types from lwr and upr | |
98 */ | |
99 scope AddExp ea = new AddExp(loc, lwr, upr); | |
100 ea.typeCombine(sc); | |
101 arg.type = ea.type.mutableOf(); | |
102 lwr = ea.e1; | |
103 upr = ea.e2; | |
104 } | |
105 static if (true) { | |
106 /* Convert to a for loop: | |
107 * foreach (key; lwr .. upr) => | |
108 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) | |
109 * | |
110 * foreach_reverse (key; lwr .. upr) => | |
111 * for (auto tmp = lwr, auto key = upr; key-- > tmp;) | |
112 */ | |
113 | |
114 ExpInitializer ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); | |
115 key = new VarDeclaration(loc, arg.type, arg.ident, ie); | |
116 | |
117 Identifier id = Lexer.uniqueId("__limit"); | |
118 ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); | |
119 VarDeclaration tmp = new VarDeclaration(loc, arg.type, id, ie); | |
120 | |
121 Statements cs = new Statements(); | |
122 // Keep order of evaluation as lwr, then upr | |
123 if (op == TOKforeach) | |
124 { | |
125 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
126 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
127 } | |
128 else | |
129 { | |
130 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
131 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
132 } | |
133 Statement forinit = new CompoundDeclarationStatement(loc, cs); | |
134 | |
135 Expression cond; | |
136 if (op == TOKforeach_reverse) | |
137 { // key-- > tmp | |
138 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); | |
139 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); | |
140 } | |
141 else | |
142 // key < tmp | |
143 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); | |
144 | |
145 Expression increment = null; | |
146 if (op == TOKforeach) | |
147 // key += 1 | |
148 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); | |
149 | |
150 ForStatement fs = new ForStatement(loc, forinit, cond, increment, body_); | |
151 s = fs.semantic(sc); | |
152 return s; | |
153 } else { | |
154 if (!arg.type.isscalar()) | |
155 error("%s is not a scalar type", arg.type.toChars()); | |
156 | |
157 sym = new ScopeDsymbol(); | |
158 sym.parent = sc.scopesym; | |
159 sc = sc.push(sym); | |
160 | |
161 sc.noctor++; | |
162 | |
163 key = new VarDeclaration(loc, arg.type, arg.ident, null); | |
164 DeclarationExp de = new DeclarationExp(loc, key); | |
165 de.semantic(sc); | |
166 | |
167 if (key.storage_class) | |
168 error("foreach range: key cannot have storage class"); | |
169 | |
170 sc.sbreak = this; | |
171 sc.scontinue = this; | |
172 body_ = body_.semantic(sc); | |
173 | |
174 sc.noctor--; | |
175 sc.pop(); | |
176 return s; | |
177 } | |
178 } | |
179 | |
180 bool hasBreak() | |
181 { | |
182 assert(false); | |
183 } | |
184 | |
185 bool hasContinue() | |
186 { | |
187 assert(false); | |
188 } | |
189 | |
190 bool usesEH() | |
191 { | |
192 assert(false); | |
193 } | |
194 | |
195 BE blockExit() | |
196 { | |
197 assert(false); | |
198 } | |
199 | |
200 bool comeFrom() | |
201 { | |
202 assert(false); | |
203 } | |
204 | |
205 Expression interpret(InterState* istate) | |
206 { | |
207 assert(false); | |
208 } | |
209 | |
210 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
211 { | |
212 assert(false); | |
213 } | |
214 | |
215 Statement inlineScan(InlineScanState* iss) | |
216 { | |
217 assert(false); | |
218 } | |
219 | |
220 void toIR(IRState* irs) | |
221 { | |
222 assert(false); | |
223 } | |
224 } |