Mercurial > projects > ddmd
annotate dmd/TypeAArray.d @ 84:be2ab491772e
Expressions -> Vector!Expression
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 30 Aug 2010 16:12:19 +0100 |
parents | ef02e2e203c2 |
children | acd69f84627e |
rev | line source |
---|---|
0 | 1 module dmd.TypeAArray; |
2 | |
3 import dmd.TypeArray; | |
4 import dmd.MOD; | |
5 import dmd.ArrayTypes; | |
6 import dmd.TypeInfoDeclaration; | |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
7 import dmd.TypeInfoAssociativeArrayDeclaration; |
0 | 8 import dmd.Expression; |
9 import dmd.Scope; | |
10 import dmd.Loc; | |
67 | 11 import dmd.Global; |
0 | 12 import dmd.Dsymbol; |
13 import dmd.Type; | |
14 import dmd.TypeSArray; | |
15 import dmd.OutBuffer; | |
16 import dmd.HdrGenState; | |
17 import dmd.Identifier; | |
18 import dmd.MATCH; | |
19 import dmd.TY; | |
20 import dmd.Id; | |
21 import dmd.CallExp; | |
22 import dmd.IntegerExp; | |
23 import dmd.FuncDeclaration; | |
24 import dmd.VarExp; | |
25 import dmd.TypeFunction; | |
26 import dmd.NullExp; | |
27 import dmd.Array; | |
28 | |
29 import dmd.backend.Symbol; | |
30 import dmd.backend.TYPE; | |
31 import dmd.backend.Util; | |
32 import dmd.backend.SC; | |
33 import dmd.backend.LIST; | |
34 import dmd.backend.TYM; | |
35 import dmd.backend.TF; | |
67 | 36 import dmd.backend.Classsym; |
0 | 37 import dmd.backend.mTYman; |
38 | |
39 import core.stdc.stdio; | |
40 import core.stdc.stdlib; | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
41 version (Bug4054) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
42 import core.memory; |
0 | 43 class TypeAArray : TypeArray |
44 { | |
45 Type index; // key type | |
46 | |
47 this(Type t, Type index) | |
48 { | |
49 super(Taarray, t); | |
50 this.index = index; | |
51 } | |
52 | |
72 | 53 override Type syntaxCopy() |
0 | 54 { |
51 | 55 Type t = next.syntaxCopy(); |
56 Type ti = index.syntaxCopy(); | |
57 if (t == next && ti == index) | |
58 t = this; | |
59 else | |
60 { | |
61 t = new TypeAArray(t, ti); | |
62 t.mod = mod; | |
63 } | |
64 return t; | |
0 | 65 } |
66 | |
67 version (DumbClone) { | |
68 } else { | |
69 Type clone() | |
70 { | |
71 assert(false); | |
72 } | |
73 } | |
72 | 74 override ulong size(Loc loc) |
0 | 75 { |
76 return PTRSIZE /* * 2*/; | |
77 } | |
78 | |
72 | 79 override Type semantic(Loc loc, Scope sc) |
0 | 80 { |
81 //printf("TypeAArray::semantic() %s index.ty = %d\n", toChars(), index.ty); | |
82 | |
83 // Deal with the case where we thought the index was a type, but | |
84 // in reality it was an expression. | |
85 if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray) | |
86 { | |
87 Expression e; | |
88 Type t; | |
89 Dsymbol s; | |
90 | |
91 index.resolve(loc, sc, &e, &t, &s); | |
92 if (e) | |
93 { // It was an expression - | |
94 // Rewrite as a static array | |
95 TypeSArray tsa = new TypeSArray(next, e); | |
96 return tsa.semantic(loc,sc); | |
97 } | |
98 else if (t) | |
99 index = t; | |
100 else | |
101 index.error(loc, "index is not a type or an expression"); | |
102 } | |
103 else | |
104 index = index.semantic(loc,sc); | |
105 | |
106 if (index.nextOf() && !index.nextOf().isInvariant()) | |
107 { | |
108 index = index.constOf().mutableOf(); | |
109 static if (false) { | |
110 printf("index is %p %s\n", index, index.toChars()); | |
111 index.check(); | |
112 printf("index.mod = x%x\n", index.mod); | |
113 printf("index.ito = x%x\n", index.ito); | |
114 if (index.ito) { | |
115 printf("index.ito.mod = x%x\n", index.ito.mod); | |
116 printf("index.ito.ito = x%x\n", index.ito.ito); | |
117 } | |
118 } | |
119 } | |
120 | |
121 switch (index.toBasetype().ty) | |
122 { | |
123 case Tbool: | |
124 case Tfunction: | |
125 case Tvoid: | |
126 case Tnone: | |
73 | 127 case Ttuple: |
0 | 128 error(loc, "can't have associative array key of %s", index.toBasetype().toChars()); |
129 break; | |
130 default: | |
131 break; /// | |
132 } | |
133 next = next.semantic(loc,sc); | |
134 transitive(); | |
135 | |
136 switch (next.toBasetype().ty) | |
137 { | |
138 case Tfunction: | |
139 case Tnone: | |
140 error(loc, "can't have associative array of %s", next.toChars()); | |
141 break; | |
142 default: | |
143 break; /// | |
144 } | |
145 if (next.isauto()) | |
146 error(loc, "cannot have array of auto %s", next.toChars()); | |
147 | |
148 return merge(); | |
149 } | |
150 | |
72 | 151 override void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps) |
0 | 152 { |
51 | 153 //printf("TypeAArray.resolve() %s\n", toChars()); |
154 | |
155 // Deal with the case where we thought the index was a type, but | |
156 // in reality it was an expression. | |
157 if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray) | |
158 { | |
159 Expression e; | |
160 Type t; | |
161 Dsymbol s; | |
162 | |
163 index.resolve(loc, sc, &e, &t, &s); | |
164 if (e) | |
165 { // It was an expression - | |
166 // Rewrite as a static array | |
167 | |
168 TypeSArray tsa = new TypeSArray(next, e); | |
169 return tsa.resolve(loc, sc, pe, pt, ps); | |
170 } | |
171 else if (t) | |
172 index = t; | |
173 else | |
174 index.error(loc, "index is not a type or an expression"); | |
175 } | |
176 Type.resolve(loc, sc, pe, pt, ps); | |
0 | 177 } |
178 | |
72 | 179 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 180 { |
181 Type.toDecoBuffer(buf, flag); | |
182 index.toDecoBuffer(buf); | |
183 next.toDecoBuffer(buf, (flag & 0x100) ? MOD.MODundefined : mod); | |
184 } | |
185 | |
72 | 186 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 187 { |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
188 if (mod != this.mod) |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
189 { |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
190 toCBuffer3(buf, hgs, mod); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
191 return; |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
192 } |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
193 next.toCBuffer2(buf, hgs, this.mod); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
194 buf.writeByte('['); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
195 index.toCBuffer2(buf, hgs, MODundefined); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
196 buf.writeByte(']'); |
0 | 197 } |
198 | |
72 | 199 override Expression dotExp(Scope sc, Expression e, Identifier ident) |
0 | 200 { |
201 version (LOGDOTEXP) { | |
202 printf("TypeAArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); | |
203 } | |
204 if (ident == Id.length) | |
205 { | |
206 Expression ec; | |
207 FuncDeclaration fd; | |
208 Expressions arguments; | |
209 | |
210 fd = FuncDeclaration.genCfunc(Type.tsize_t, Id.aaLen); | |
211 ec = new VarExp(Loc(0), fd); | |
212 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
213 arguments.push(e); |
0 | 214 e = new CallExp(e.loc, ec, arguments); |
215 e.type = (cast(TypeFunction)fd.type).next; | |
216 } | |
217 else if (ident == Id.keys) | |
218 { | |
219 Expression ec; | |
220 FuncDeclaration fd; | |
221 Expressions arguments; | |
222 int size = cast(int)index.size(e.loc); | |
223 | |
224 assert(size); | |
225 fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaKeys); | |
226 ec = new VarExp(Loc(0), fd); | |
227 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
228 arguments.push(e); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
229 arguments.push(new IntegerExp(Loc(0), size, Type.tsize_t)); |
0 | 230 e = new CallExp(e.loc, ec, arguments); |
231 e.type = index.arrayOf(); | |
232 } | |
233 else if (ident == Id.values) | |
234 { | |
235 Expression ec; | |
236 FuncDeclaration fd; | |
237 Expressions arguments; | |
238 | |
239 fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaValues); | |
240 ec = new VarExp(Loc(0), fd); | |
241 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
242 arguments.push(e); |
0 | 243 size_t keysize = cast(size_t)index.size(e.loc); |
244 keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
245 arguments.push(new IntegerExp(Loc(0), keysize, Type.tsize_t)); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
246 arguments.push(new IntegerExp(Loc(0), next.size(e.loc), Type.tsize_t)); |
0 | 247 e = new CallExp(e.loc, ec, arguments); |
248 e.type = next.arrayOf(); | |
249 } | |
250 else if (ident == Id.rehash) | |
251 { | |
252 Expression ec; | |
253 FuncDeclaration fd; | |
254 Expressions arguments; | |
255 | |
256 fd = FuncDeclaration.genCfunc(Type.tint64, Id.aaRehash); | |
257 ec = new VarExp(Loc(0), fd); | |
258 arguments = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
259 arguments.push(e.addressOf(sc)); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
260 arguments.push(index.getInternalTypeInfo(sc)); |
0 | 261 e = new CallExp(e.loc, ec, arguments); |
262 e.type = this; | |
263 } | |
264 else | |
265 { | |
266 e = Type.dotExp(sc, e, ident); | |
267 } | |
268 return e; | |
269 } | |
270 | |
72 | 271 override Expression defaultInit(Loc loc) |
0 | 272 { |
273 version (LOGDEFAULTINIT) { | |
274 printf("TypeAArray.defaultInit() '%s'\n", toChars()); | |
275 } | |
276 Expression e = new NullExp(loc); | |
277 e.type = this; | |
278 return e; | |
279 } | |
280 | |
72 | 281 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 282 { |
51 | 283 static if (false) { |
284 printf("TypeAArray.deduceType()\n"); | |
285 printf("\tthis = %d, ", ty); print(); | |
286 printf("\ttparam = %d, ", tparam.ty); tparam.print(); | |
287 } | |
288 | |
289 // Extra check that index type must match | |
290 if (tparam && tparam.ty == Taarray) | |
291 { | |
292 TypeAArray tp = cast(TypeAArray)tparam; | |
293 if (!index.deduceType(sc, tp.index, parameters, dedtypes)) | |
294 { | |
295 return MATCHnomatch; | |
296 } | |
297 } | |
298 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 299 } |
300 | |
72 | 301 override bool isZeroInit(Loc loc) |
0 | 302 { |
303 assert(false); | |
304 } | |
305 | |
72 | 306 override bool checkBoolean() |
0 | 307 { |
308 assert(false); | |
309 } | |
310 | |
72 | 311 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 312 { |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
67
diff
changeset
|
313 return new TypeInfoAssociativeArrayDeclaration(this); |
0 | 314 } |
315 | |
72 | 316 override bool hasPointers() |
0 | 317 { |
318 return true; | |
319 } | |
320 | |
72 | 321 override MATCH implicitConvTo(Type to) |
0 | 322 { |
51 | 323 //printf("TypeAArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars()); |
324 if (equals(to)) | |
325 return MATCHexact; | |
326 | |
327 if (to.ty == Taarray) | |
328 { | |
329 TypeAArray ta = cast(TypeAArray)to; | |
330 | |
331 if (!(next.mod == ta.next.mod || ta.next.mod == MODconst)) | |
332 return MATCHnomatch; // not const-compatible | |
333 | |
334 if (!(index.mod == ta.index.mod || ta.index.mod == MODconst)) | |
335 return MATCHnomatch; // not const-compatible | |
336 | |
337 MATCH m = next.constConv(ta.next); | |
338 MATCH mi = index.constConv(ta.index); | |
339 if (m != MATCHnomatch && mi != MATCHnomatch) | |
340 { | |
341 if (m == MATCHexact && mod != to.mod) | |
342 m = MATCHconst; | |
343 if (mi < m) | |
344 m = mi; | |
345 return m; | |
346 } | |
347 } | |
348 return Type.implicitConvTo(to); | |
0 | 349 } |
350 | |
72 | 351 override MATCH constConv(Type to) |
0 | 352 { |
353 assert(false); | |
354 } | |
355 | |
356 version (CPP_MANGLE) { | |
357 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
358 { | |
359 assert(false); | |
360 } | |
361 } | |
362 | |
363 // Back end | |
364 /******************************************** | |
365 * Determine the right symbol to look up | |
366 * an associative array element. | |
367 * Input: | |
368 * flags 0 don't add value signature | |
369 * 1 add value signature | |
370 */ | |
371 Symbol* aaGetSymbol(const(char)* func, int flags) | |
372 in | |
373 { | |
374 assert(func); | |
375 assert((flags & ~1) == 0); | |
376 } | |
377 out (result) | |
378 { | |
379 assert(result); | |
380 } | |
381 body | |
382 { | |
383 int sz; | |
384 char* id; | |
385 type* t; | |
386 Symbol* s; | |
387 int i; | |
388 | |
389 // Dumb linear symbol table - should use associative array! | |
390 static Array sarray = null; | |
391 | |
392 //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key); | |
393 static if (false) { | |
394 scope OutBuffer buf = new OutBuffer(); | |
395 key.toKeyBuffer(buf); | |
396 | |
397 sz = next.size(); // it's just data, so we only care about the size | |
398 sz = (sz + 3) & ~3; // reduce proliferation of library routines | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
399 version (Bug4054) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
400 id = cast(char*)GC.malloc(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
401 else |
0 | 402 id = cast(char*)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1); |
403 buf.writeByte(0); | |
404 if (flags & 1) | |
405 sprintf(id, "_aa%s%s%d", func, buf.data, sz); | |
406 else | |
407 sprintf(id, "_aa%s%s", func, buf.data); | |
408 } else { | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
409 version (Bug4054) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
410 id = cast(char*)GC.malloc(3 + strlen(func) + 1); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
411 else |
0 | 412 id = cast(char*)alloca(3 + strlen(func) + 1); |
413 sprintf(id, "_aa%s", func); | |
414 } | |
415 if (!sarray) | |
416 sarray = new Array(); | |
417 | |
418 // See if symbol is already in sarray | |
419 for (i = 0; i < sarray.dim; i++) | |
420 { | |
421 s = cast(Symbol*)sarray.data[i]; | |
422 if (strcmp(id, s.Sident.ptr) == 0) | |
423 return s; // use existing Symbol | |
424 } | |
425 | |
426 // Create new Symbol | |
427 | |
428 s = symbol_calloc(id); | |
429 slist_add(s); | |
430 s.Sclass = SCextern; | |
431 s.Ssymnum = -1; | |
432 symbol_func(s); | |
433 | |
434 t = type_alloc(TYnfunc); | |
435 t.Tflags = TFprototype | TFfixed; | |
436 t.Tmangle = mTYman_c; | |
437 t.Tparamtypes = null; | |
438 t.Tnext = next.toCtype(); | |
439 t.Tnext.Tcount++; | |
440 t.Tcount++; | |
441 s.Stype = t; | |
442 | |
443 sarray.push(s); // remember it | |
444 return s; | |
445 } | |
446 | |
72 | 447 override type* toCtype() |
0 | 448 { |
67 | 449 type* t; |
450 | |
451 if (ctype) | |
452 return ctype; | |
453 | |
454 if (0 && global.params.symdebug) | |
455 { | |
456 /* An associative array is represented by: | |
457 * struct AArray { size_t length; void* ptr; } | |
458 */ | |
459 | |
460 static Symbol* s; | |
461 | |
462 if (!s) | |
463 { | |
464 s = symbol_calloc("_AArray"); | |
465 s.Sclass = SCstruct; | |
466 s.Sstruct = struct_calloc(); | |
467 s.Sstruct.Sflags |= 0; | |
468 s.Sstruct.Salignsize = alignsize(); | |
469 s.Sstruct.Sstructalign = cast(ubyte)global.structalign; | |
470 s.Sstruct.Sstructsize = cast(uint)size(Loc(0)); | |
471 slist_add(s); | |
472 | |
473 Symbol* s1 = symbol_name("length", SCmember, Type.tsize_t.toCtype()); | |
474 list_append(&s.Sstruct.Sfldlst, s1); | |
475 | |
476 Symbol* s2 = symbol_name("data", SCmember, Type.tvoidptr.toCtype()); | |
477 s2.Smemoff = cast(uint)Type.tsize_t.size(); | |
478 list_append(&s.Sstruct.Sfldlst, s2); | |
479 } | |
480 | |
481 t = type_alloc(TYstruct); | |
482 t.Ttag = cast(Classsym*)s; // structure tag name | |
483 t.Tcount++; | |
484 s.Stype = t; | |
485 } | |
486 else | |
487 { | |
488 if (global.params.symdebug == 1) | |
489 { | |
490 /* Generate D symbolic debug info, rather than C | |
491 * Tnext: element type | |
492 * Tkey: key type | |
493 */ | |
494 t = type_allocn(TYaarray, next.toCtype()); | |
495 t.Tkey = index.toCtype(); | |
496 t.Tkey.Tcount++; | |
497 } | |
498 else | |
499 t = type_fake(TYaarray); | |
500 } | |
501 t.Tcount++; | |
502 ctype = t; | |
503 return t; | |
0 | 504 } |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
505 } |