comparison dmd/TypeSArray.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 832f71e6f96c
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
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
261 int isString()
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 }