Mercurial > projects > ddmd
annotate dmd/interpret/Util.d @ 179:cd48cb899aee
Updated to dmd2.040
author | korDen |
---|---|
date | Sun, 17 Oct 2010 20:56:07 +0400 |
parents | fe2e1b93e88f |
children |
rev | line source |
---|---|
63 | 1 module dmd.interpret.Util; |
2 | |
114 | 3 import dmd.common; |
63 | 4 import dmd.StructDeclaration; |
5 import dmd.Expression; | |
107 | 6 import dmd.FuncDeclaration; |
63 | 7 import dmd.InterState; |
8 import dmd.ArrayTypes; | |
179 | 9 import dmd.StringExp; |
63 | 10 import dmd.GlobalExpressions; |
11 import dmd.TOK; | |
12 import dmd.AssocArrayLiteralExp; | |
13 import dmd.IntegerExp; | |
179 | 14 import dmd.Id; |
63 | 15 import dmd.Type; |
16 import dmd.Declaration; | |
17 import dmd.Loc; | |
18 import dmd.ArrayLiteralExp; | |
19 import dmd.TypeAArray; | |
107 | 20 import dmd.TypeFunction; |
63 | 21 import dmd.TypeSArray; |
107 | 22 import dmd.TY; |
63 | 23 import dmd.STC; |
24 import dmd.SymbolDeclaration; | |
25 import dmd.StructLiteralExp; | |
26 import dmd.VarDeclaration; | |
27 import dmd.Util; | |
28 | |
179 | 29 import core.memory; |
30 import core.stdc.string; | |
31 | |
107 | 32 version(DMDV1) |
33 { | |
63 | 34 Expression interpret_aaLen(InterState istate, Expressions arguments) |
35 { | |
107 | 36 if (!arguments || arguments.dim != 1) |
63 | 37 return null; |
107 | 38 auto earg = arguments[0]; |
39 earg = earg.interpret(istate); | |
40 if (earg is EXP_CANT_INTERPRET) | |
63 | 41 return null; |
107 | 42 if (earg.op != TOKassocarrayliteral) |
63 | 43 return null; |
107 | 44 auto aae = cast(AssocArrayLiteralExp)earg; |
45 auto e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t); | |
46 return e; | |
63 | 47 } |
48 | |
49 Expression interpret_aaKeys(InterState istate, Expressions arguments) | |
50 { | |
51 version (LOG) { | |
107 | 52 writef("interpret_aaKeys()\n"); |
63 | 53 } |
107 | 54 if (!arguments || arguments.dim != 2) |
63 | 55 return null; |
107 | 56 auto earg = arguments[0]; |
57 earg = earg.interpret(istate); | |
58 if (earg is EXP_CANT_INTERPRET) | |
63 | 59 return null; |
107 | 60 if (earg.op != TOKassocarrayliteral) |
63 | 61 return null; |
107 | 62 auto aae = cast(AssocArrayLiteralExp)earg; |
63 auto e = new ArrayLiteralExp(aae.loc, aae.keys); | |
64 Type elemType = (cast(TypeAArray)aae.type).index; | |
65 e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); | |
66 return e; | |
63 | 67 } |
68 | |
69 Expression interpret_aaValues(InterState istate, Expressions arguments) | |
70 { | |
107 | 71 //writef("interpret_aaValues()\n"); |
72 if (!arguments || arguments.dim != 3) | |
73 return null; | |
74 auto earg = arguments[0]; | |
75 earg = earg.interpret(istate); | |
76 if (earg is EXP_CANT_INTERPRET) | |
77 return null; | |
78 if (earg.op != TOKassocarrayliteral) | |
63 | 79 return null; |
107 | 80 auto aae = cast(AssocArrayLiteralExp)earg; |
81 auto e = new ArrayLiteralExp(aae.loc, aae.values); | |
82 Type elemType = (cast(TypeAArray)aae.type).next; | |
83 e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); | |
84 //writef("result is %s\n", e.toChars()); | |
85 return e; | |
86 } | |
87 } | |
88 else version(DMDV2) | |
89 { | |
90 Expression interpret_length(InterState istate, Expression earg) | |
91 { | |
92 // writef("interpret_length()\n"); | |
93 earg = earg.interpret(istate); | |
94 if (earg == EXP_CANT_INTERPRET) | |
95 return null; | |
96 if (earg.op != TOKassocarrayliteral) | |
63 | 97 return null; |
107 | 98 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; |
99 Expression e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t); | |
100 return e; | |
101 } | |
102 | |
103 Expression interpret_keys(InterState istate, Expression earg, FuncDeclaration fd) | |
104 { | |
105 version(LOG) | |
106 writef("interpret_keys()\n"); | |
107 | |
108 earg = earg.interpret(istate); | |
109 if (earg == EXP_CANT_INTERPRET) | |
110 return null; | |
111 if (earg.op != TOKassocarrayliteral) | |
112 return null; | |
113 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; | |
114 Expression e = new ArrayLiteralExp(aae.loc, aae.keys); | |
115 assert(fd.type.ty == Tfunction); | |
116 assert(fd.type.nextOf().ty == Tarray); | |
117 Type elemType = (cast(TypeFunction)fd.type).nextOf().nextOf(); | |
118 e.type = new TypeSArray(elemType, new IntegerExp(aae.keys.dim)); | |
119 return e; | |
120 } | |
121 Expression interpret_values(InterState istate, Expression earg, FuncDeclaration fd) | |
122 { | |
123 //writef("interpret_values()\n"); | |
124 earg = earg.interpret(istate); | |
125 if (earg == EXP_CANT_INTERPRET) | |
63 | 126 return null; |
107 | 127 if (earg.op != TOKassocarrayliteral) |
128 return null; | |
129 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; | |
130 Expression e = new ArrayLiteralExp(aae.loc, aae.values); | |
131 assert(fd.type.ty == Tfunction); | |
132 assert(fd.type.nextOf().ty == Tarray); | |
133 Type elemType = (cast(TypeFunction)fd.type).nextOf().nextOf(); | |
134 e.type = new TypeSArray(elemType, new IntegerExp(aae.values.dim)); | |
135 //writef("result is %s\n", e.toChars()); | |
136 return e; | |
137 } | |
63 | 138 } |
139 | |
140 Expression getVarExp(Loc loc, InterState istate, Declaration d) | |
141 { | |
107 | 142 Expression e = EXP_CANT_INTERPRET; |
143 VarDeclaration v = d.isVarDeclaration(); | |
144 SymbolDeclaration s = d.isSymbolDeclaration(); | |
145 if (v) | |
146 { | |
63 | 147 ///version (DMDV2) { |
179 | 148 /* Magic variable __ctfe always returns true when interpreting |
149 */ | |
150 if (v.ident == Id.ctfe) | |
151 return new IntegerExp(loc, 1, Type.tbool); | |
152 | |
135 | 153 if ((v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && v.init && !v.value) |
63 | 154 ///} else { |
155 /// if (v.isConst() && v.init) | |
156 ///} | |
148 | 157 { |
63 | 158 e = v.init.toExpression(); |
159 if (e && !e.type) | |
160 e.type = v.type; | |
161 } | |
179 | 162 else if (v.isCTFE() && !v.value) |
163 { | |
164 if (v.init) | |
165 { | |
166 e = v.init.toExpression(); | |
167 e = e.interpret(istate); | |
168 } | |
169 else // This should never happen | |
170 e = v.type.defaultInitLiteral(Loc(0)); | |
171 } | |
172 | |
63 | 173 else |
148 | 174 { |
63 | 175 e = v.value; |
148 | 176 if (!v.isCTFE()) |
177 { | |
63 | 178 error(loc, "static variable %s cannot be read at compile time", v.toChars()); |
179 e = EXP_CANT_INTERPRET; | |
180 } | |
181 else if (!e) | |
182 error(loc, "variable %s is used before initialization", v.toChars()); | |
183 else if (e !is EXP_CANT_INTERPRET) | |
184 e = e.interpret(istate); | |
185 } | |
186 if (!e) | |
187 e = EXP_CANT_INTERPRET; | |
107 | 188 } |
189 else if (s) | |
190 { | |
63 | 191 if (s.dsym.toInitializer() == s.sym) |
148 | 192 { |
63 | 193 Expressions exps = new Expressions(); |
194 e = new StructLiteralExp(Loc(0), s.dsym, exps); | |
195 e = e.semantic(null); | |
196 } | |
107 | 197 } |
198 return e; | |
63 | 199 } |
200 | |
201 /* Helper functions for BinExp.interpretAssignCommon | |
202 */ | |
203 | |
204 /*************************************** | |
205 * Duplicate the elements array, then set field 'indexToChange' = newelem. | |
206 */ | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
207 Expressions changeOneElement(Expressions oldelems, size_t indexToChange, Expression newelem) |
63 | 208 { |
107 | 209 auto expsx = new Expressions(); |
210 expsx.setDim(oldelems.dim); | |
211 for (size_t j = 0; j < expsx.dim; j++) | |
212 { | |
63 | 213 if (j == indexToChange) |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
214 expsx[j] = newelem; |
63 | 215 else |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
216 expsx[j] = oldelems[j]; |
107 | 217 } |
218 return expsx; | |
63 | 219 } |
220 | |
221 /*************************************** | |
179 | 222 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$] |
63 | 223 */ |
224 Expressions spliceElements(Expressions oldelems, Expressions newelems, size_t insertpoint) | |
225 { | |
107 | 226 auto expsx = new Expressions(); |
227 expsx.setDim(oldelems.dim); | |
228 for (size_t j = 0; j < expsx.dim; j++) | |
229 { | |
63 | 230 if (j >= insertpoint && j < insertpoint + newelems.dim) |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
231 expsx[j] = newelems[j - insertpoint]; |
63 | 232 else |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
233 expsx[j] = oldelems[j]; |
107 | 234 } |
235 return expsx; | |
63 | 236 } |
237 | |
179 | 238 /*************************************** |
239 * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$] | |
240 */ | |
241 StringExp spliceStringExp(StringExp oldstr, StringExp newstr, size_t insertpoint) | |
242 { | |
243 assert(oldstr.sz==newstr.sz); | |
244 char* s; | |
245 size_t oldlen = oldstr.len; | |
246 size_t newlen = newstr.len; | |
247 size_t sz = oldstr.sz; | |
248 s = cast(char*)GC.calloc(oldlen + 1, sz); | |
249 memcpy(s, oldstr.string_, oldlen * sz); | |
250 memcpy(s + insertpoint * sz, newstr.string_, newlen * sz); | |
251 StringExp se2 = new StringExp(oldstr.loc, cast(string)s[0..oldlen]); | |
252 se2.committed = oldstr.committed; | |
253 se2.postfix = oldstr.postfix; | |
254 se2.type = oldstr.type; | |
255 return se2; | |
256 } | |
257 | |
258 /****************************** | |
259 * Create a string literal consisting of 'value' duplicated 'dim' times. | |
260 */ | |
261 StringExp createBlockDuplicatedStringLiteral(Type type, dchar value, size_t dim, int sz) | |
262 { | |
263 char* s; | |
264 s = cast(char*)GC.calloc(dim + 1, sz); | |
265 for (int elemi = 0; elemi < dim; ++elemi) | |
266 { | |
267 switch (sz) | |
268 { | |
269 case 1: s[elemi] = cast(char)value; break; | |
270 case 2: (cast(wchar*)s)[elemi] = cast(wchar)value; break; | |
271 case 4: (cast(dchar*)s)[elemi] = value; break; | |
272 default: assert(0); | |
273 } | |
274 } | |
275 StringExp se = new StringExp(Loc(0), cast(string)s[0..dim]); | |
276 se.type = type; | |
277 return se; | |
278 } | |
279 | |
63 | 280 /****************************** |
281 * Create an array literal consisting of 'elem' duplicated 'dim' times. | |
282 */ | |
283 ArrayLiteralExp createBlockDuplicatedArrayLiteral(Type type, Expression elem, size_t dim) | |
284 { | |
107 | 285 auto elements = new Expressions(); |
286 elements.setDim(dim); | |
287 for (size_t i = 0; i < dim; i++) { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
288 elements[i] = elem; |
63 | 289 } |
290 | |
107 | 291 auto ae = new ArrayLiteralExp(Loc(0), elements); |
292 ae.type = type; | |
293 return ae; | |
63 | 294 } |
295 | |
296 | |
297 /******************************** | |
298 * Add v to the istate list, unless it already exists there. | |
299 */ | |
300 void addVarToInterstate(InterState istate, VarDeclaration v) | |
301 { | |
107 | 302 if (!v.isParameter()) |
303 { | |
63 | 304 for (size_t i = 0; 1; i++) |
305 { | |
306 if (i == istate.vars.dim) | |
307 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
63
diff
changeset
|
308 istate.vars.push(v); |
107 | 309 //writef("\tadding %s to istate\n", v.toChars()); |
63 | 310 break; |
311 } | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
63
diff
changeset
|
312 if (v == cast(VarDeclaration)istate.vars[i]) |
63 | 313 break; |
314 } | |
107 | 315 } |
63 | 316 } |