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 }