Mercurial > projects > ddmd
annotate dmd/TypeSArray.d @ 12:832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
Some unittest-specific functions implemented
author | korDen |
---|---|
date | Mon, 12 Apr 2010 15:13:00 +0400 |
parents | 10317f0c89a5 |
children | f23312cb6f2e |
rev | line source |
---|---|
0 | 1 module dmd.TypeSArray; |
2 | |
3 import dmd.TypeArray; | |
4 import dmd.MOD; | |
5 import dmd.Argument; | |
6 import dmd.TypeStruct; | |
7 import dmd.TypeTuple; | |
8 import dmd.VarExp; | |
9 import dmd.IntegerExp; | |
10 import dmd.Expression; | |
11 import dmd.Type; | |
12 import dmd.TupleDeclaration; | |
13 import dmd.TOK; | |
14 import dmd.Loc; | |
15 import dmd.STC; | |
16 import dmd.Scope; | |
17 import dmd.Dsymbol; | |
18 import dmd.OutBuffer; | |
19 import dmd.HdrGenState; | |
20 import dmd.Identifier; | |
21 import dmd.MATCH; | |
22 import dmd.TypeDArray; | |
23 import dmd.TypePointer; | |
24 import dmd.ArrayTypes; | |
25 import dmd.WANT; | |
26 import dmd.TypeInfoDeclaration; | |
27 import dmd.TY; | |
28 import dmd.Util; | |
29 import dmd.Id; | |
30 | |
31 import dmd.type.Util; | |
32 | |
33 import dmd.backend.dt_t; | |
34 import dmd.backend.TYPE; | |
35 import dmd.backend.Util; | |
36 import dmd.backend.TYM; | |
37 import dmd.backend.DT; | |
38 | |
39 // Static array, one with a fixed dimension | |
40 class TypeSArray : TypeArray | |
41 { | |
42 Expression dim; | |
43 | |
44 this(Type t, Expression dim) | |
45 { | |
46 super(TY.Tsarray, t); | |
47 //printf("TypeSArray(%s)\n", dim.toChars()); | |
48 this.dim = dim; | |
49 } | |
50 | |
51 version (DumbClone) { | |
52 } else { | |
53 Type clone() | |
54 { | |
55 assert(false); | |
56 } | |
57 } | |
58 | |
59 Type syntaxCopy() | |
60 { | |
61 assert(false); | |
62 } | |
63 | |
64 ulong size(Loc loc) | |
65 { | |
66 if (!dim) | |
67 return Type.size(loc); | |
68 | |
69 long sz = dim.toInteger(); | |
70 | |
71 { | |
72 long n, n2; | |
73 n = next.size(); | |
74 n2 = n * sz; | |
75 if (n && (n2 / n) != sz) | |
76 goto Loverflow; | |
77 | |
78 sz = n2; | |
79 } | |
80 return sz; | |
81 | |
82 Loverflow: | |
83 error(loc, "index %jd overflow for static array", sz); | |
84 return 1; | |
85 } | |
86 | |
87 uint alignsize() | |
88 { | |
89 return next.alignsize(); | |
90 } | |
91 | |
92 Type semantic(Loc loc, Scope sc) | |
93 { | |
94 //printf("TypeSArray.semantic() %s\n", toChars()); | |
95 | |
96 Type t; | |
97 Expression e; | |
98 Dsymbol s; | |
99 next.resolve(loc, sc, &e, &t, &s); | |
100 if (dim && s && s.isTupleDeclaration()) | |
101 { | |
102 TupleDeclaration sd = s.isTupleDeclaration(); | |
103 | |
104 dim = semanticLength(sc, sd, dim); | |
105 dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
106 ulong d = dim.toUInteger(); | |
107 | |
108 if (d >= sd.objects.dim) | |
109 { error(loc, "tuple index %ju exceeds %u", d, sd.objects.dim); | |
110 return Type.terror; | |
111 } | |
112 ///Object o = cast(Object)sd.objects.data[(size_t)d]; | |
113 ///if (o.dyncast() != DYNCAST_TYPE) | |
114 ///{ | |
115 /// error(loc, "%s is not a type", toChars()); | |
116 /// return Type.terror; | |
117 ///} | |
118 ///t = cast(Type)o; | |
119 | |
120 t = cast(Type)sd.objects.data[cast(size_t)d]; | |
121 if (t is null) { | |
122 error(loc, "%s is not a type", toChars()); | |
123 return Type.terror; | |
124 } | |
125 return t; | |
126 } | |
127 | |
128 next = next.semantic(loc,sc); | |
129 transitive(); | |
130 | |
131 Type tbn = next.toBasetype(); | |
132 | |
133 if (dim) | |
134 { | |
135 long n, n2; | |
136 | |
137 dim = semanticLength(sc, tbn, dim); | |
138 | |
139 dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
140 if (sc && sc.parameterSpecialization && dim.op == TOK.TOKvar && | |
141 (cast(VarExp)dim).var.storage_class & STC.STCtemplateparameter) | |
142 { | |
143 /* It could be a template parameter N which has no value yet: | |
144 * template Foo(T : T[N], size_t N); | |
145 */ | |
146 return this; | |
147 } | |
148 long d1 = dim.toInteger(); | |
149 dim = dim.castTo(sc, tsize_t); | |
150 dim = dim.optimize(WANT.WANTvalue); | |
151 long d2 = dim.toInteger(); | |
152 | |
153 if (d1 != d2) | |
154 goto Loverflow; | |
155 | |
156 if (tbn.isintegral() || | |
157 tbn.isfloating() || | |
158 tbn.ty == TY.Tpointer || | |
159 tbn.ty == TY.Tarray || | |
160 tbn.ty == TY.Tsarray || | |
161 tbn.ty == TY.Taarray || | |
162 tbn.ty == TY.Tclass) | |
163 { | |
164 /* Only do this for types that don't need to have semantic() | |
165 * run on them for the size, since they may be forward referenced. | |
166 */ | |
167 n = tbn.size(loc); | |
168 n2 = n * d2; | |
169 if (cast(int)n2 < 0) | |
170 goto Loverflow; | |
171 if (n2 >= 0x1000000) // put a 'reasonable' limit on it | |
172 goto Loverflow; | |
173 if (n && n2 / n != d2) | |
174 { | |
175 Loverflow: | |
176 error(loc, "index %jd overflow for static array", d1); | |
177 dim = new IntegerExp(Loc(0), 1, tsize_t); | |
178 } | |
179 } | |
180 } | |
181 switch (tbn.ty) | |
182 { | |
183 case TY.Ttuple: | |
184 { // Index the tuple to get the type | |
185 assert(dim); | |
186 TypeTuple tt = cast(TypeTuple)tbn; | |
187 ulong d = dim.toUInteger(); | |
188 | |
189 if (d >= tt.arguments.dim) | |
190 { | |
191 error(loc, "tuple index %ju exceeds %u", d, tt.arguments.dim); | |
192 return Type.terror; | |
193 } | |
194 Argument arg = cast(Argument)tt.arguments.data[cast(size_t)d]; | |
195 return arg.type; | |
196 } | |
197 case TY.Tstruct: | |
198 { TypeStruct ts = cast(TypeStruct)tbn; | |
199 if (ts.sym.isnested) | |
200 error(loc, "cannot have array of inner structs %s", ts.toChars()); | |
201 break; | |
202 } | |
203 case TY.Tfunction: | |
204 case TY.Tnone: | |
205 error(loc, "can't have array of %s", tbn.toChars()); | |
206 tbn = next = tint32; | |
207 break; | |
208 default: /// | |
209 break; | |
210 } | |
211 if (tbn.isauto()) | |
212 error(loc, "cannot have array of auto %s", tbn.toChars()); | |
213 return merge(); | |
214 } | |
215 | |
216 void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps) | |
217 { | |
218 assert(false); | |
219 } | |
220 | |
221 void toDecoBuffer(OutBuffer buf, int flag) | |
222 { | |
223 Type.toDecoBuffer(buf, flag); | |
224 if (dim) | |
225 //buf.printf("%ju", dim.toInteger()); /// | |
226 buf.printf("%s", dim.toInteger()); | |
227 if (next) | |
228 /* Note that static arrays are value types, so | |
229 * for a parameter, propagate the 0x100 to the next | |
230 * level, since for T[4][3], any const should apply to the T, | |
231 * not the [4]. | |
232 */ | |
233 next.toDecoBuffer(buf, (flag & 0x100) ? flag : mod); | |
234 } | |
235 | |
236 void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) | |
237 { | |
238 assert(false); | |
239 } | |
240 | |
241 Expression dotExp(Scope sc, Expression e, Identifier ident) | |
242 { | |
243 version (LOGDOTEXP) { | |
244 printf("TypeSArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); | |
245 } | |
246 if (ident == Id.length) | |
247 { | |
248 e = dim; | |
249 } | |
250 else if (ident == Id.ptr) | |
251 { | |
252 e = e.castTo(sc, next.pointerTo()); | |
253 } | |
254 else | |
255 { | |
256 e = TypeArray.dotExp(sc, e, ident); | |
257 } | |
258 return e; | |
259 } | |
260 | |
12
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
261 bool isString() |
0 | 262 { |
263 assert(false); | |
264 } | |
265 | |
266 bool isZeroInit(Loc loc) | |
267 { | |
268 return next.isZeroInit(loc); | |
269 } | |
270 | |
271 uint memalign(uint salign) | |
272 { | |
273 return next.memalign(salign); | |
274 } | |
275 | |
276 MATCH constConv(Type to) | |
277 { | |
278 assert(false); | |
279 } | |
280 | |
281 MATCH implicitConvTo(Type to) | |
282 { | |
283 //printf("TypeSArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars()); | |
284 | |
285 // Allow implicit conversion of static array to pointer or dynamic array | |
286 if (IMPLICIT_ARRAY_TO_PTR && to.ty == Tpointer) | |
287 { | |
288 TypePointer tp = cast(TypePointer)to; | |
289 | |
290 if (next.mod != tp.next.mod && tp.next.mod != MODconst) | |
291 return MATCHnomatch; | |
292 | |
293 if (tp.next.ty == Tvoid || next.constConv(tp.next) != MATCHnomatch) | |
294 { | |
295 return MATCHconvert; | |
296 } | |
297 return MATCHnomatch; | |
298 } | |
299 if (to.ty == Tarray) | |
300 { | |
301 int offset = 0; | |
302 TypeDArray ta = cast(TypeDArray)to; | |
303 | |
304 if (next.mod != ta.next.mod && ta.next.mod != MODconst) | |
305 return MATCHnomatch; | |
306 | |
307 if (next.equals(ta.next) || | |
308 next.implicitConvTo(ta.next) >= MATCHconst || | |
309 (ta.next.isBaseOf(next, &offset) && offset == 0) || | |
310 ta.next.ty == Tvoid | |
311 ) | |
312 return MATCHconvert; | |
313 | |
314 return MATCHnomatch; | |
315 } | |
316 if (to.ty == Tsarray) | |
317 { | |
318 if (this == to) | |
319 return MATCHexact; | |
320 | |
321 TypeSArray tsa = cast(TypeSArray)to; | |
322 | |
323 if (dim.equals(tsa.dim)) | |
324 { | |
325 /* Since static arrays are value types, allow | |
326 * conversions from const elements to non-const | |
327 * ones, just like we allow conversion from const int | |
328 * to int. | |
329 */ | |
330 MATCH m = next.implicitConvTo(tsa.next); | |
331 if (m >= MATCHconst) | |
332 { | |
333 if (mod != to.mod) | |
334 m = MATCHconst; | |
335 return m; | |
336 } | |
337 } | |
338 } | |
339 return MATCHnomatch; | |
340 } | |
341 | |
342 Expression defaultInit(Loc loc) | |
343 { | |
344 version (LOGDEFAULTINIT) { | |
345 printf("TypeSArray.defaultInit() '%s'\n", toChars()); | |
346 } | |
347 return next.defaultInit(loc); | |
348 } | |
349 | |
350 dt_t** toDt(dt_t** pdt) | |
351 { | |
352 return toDtElem(pdt, null); | |
353 } | |
354 | |
355 dt_t** toDtElem(dt_t** pdt, Expression e) | |
356 { | |
357 int i; | |
358 | |
359 //printf("TypeSArray::toDtElem()\n"); | |
360 uint len = cast(uint)dim.toInteger(); | |
361 if (len) | |
362 { | |
363 while (*pdt) | |
364 pdt = &((*pdt).DTnext); | |
365 Type tnext = next; | |
366 Type tbn = tnext.toBasetype(); | |
367 while (tbn.ty == Tsarray) | |
368 { | |
369 TypeSArray tsa = cast(TypeSArray)tbn; | |
370 | |
371 len *= tsa.dim.toInteger(); | |
372 tnext = tbn.nextOf(); | |
373 tbn = tnext.toBasetype(); | |
374 } | |
375 if (!e) // if not already supplied | |
376 e = tnext.defaultInit(Loc(0)); // use default initializer | |
377 if (tbn.ty == Tstruct) | |
378 tnext.toDt(pdt); | |
379 else | |
380 e.toDt(pdt); | |
381 dt_optimize(*pdt); | |
382 if ((*pdt).dt == DT_azeros && !(*pdt).DTnext) | |
383 { | |
384 (*pdt).DTazeros *= len; | |
385 pdt = &((*pdt).DTnext); | |
386 } | |
387 else if ((*pdt).dt == DT_1byte && (*pdt).DTonebyte == 0 && !(*pdt).DTnext) | |
388 { | |
389 (*pdt).dt = DT_azeros; | |
390 (*pdt).DTazeros = len; | |
391 pdt = &((*pdt).DTnext); | |
392 } | |
393 else if (e.op != TOKstring) | |
394 { | |
395 for (i = 1; i < len; i++) | |
396 { | |
397 if (tbn.ty == Tstruct) | |
398 { | |
399 pdt = tnext.toDt(pdt); | |
400 while (*pdt) | |
401 pdt = &((*pdt).DTnext); | |
402 } | |
403 else | |
404 pdt = e.toDt(pdt); | |
405 } | |
406 } | |
407 } | |
408 return pdt; | |
409 } | |
410 | |
411 MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) | |
412 { | |
413 assert(false); | |
414 } | |
415 | |
416 TypeInfoDeclaration getTypeInfoDeclaration() | |
417 { | |
418 assert(false); | |
419 } | |
420 | |
421 Expression toExpression() | |
422 { | |
423 assert(false); | |
424 } | |
425 | |
426 bool hasPointers() | |
427 { | |
428 return next.hasPointers(); | |
429 } | |
430 | |
431 version (CPP_MANGLE) { | |
432 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
433 { | |
434 assert(false); | |
435 } | |
436 } | |
437 | |
438 type* toCtype() | |
439 { | |
440 if (!ctype) | |
441 { | |
442 type* tn = next.toCtype(); | |
443 ctype = type_allocn(TYarray, tn); | |
444 ctype.Tdim = cast(uint)dim.toInteger(); | |
445 } | |
446 | |
447 return ctype; | |
448 } | |
449 | |
450 type* toCParamtype() | |
451 { | |
452 // arrays are passed as pointers | |
453 return next.pointerTo().toCtype(); | |
454 } | |
455 } |