Mercurial > projects > ddmd
annotate dmd/TypeStruct.d @ 168:ceed63f310fb
stringtable, stringbuffer and freelist moved to Global
author | korDen |
---|---|
date | Thu, 30 Sep 2010 12:57:13 +0400 |
parents | 14feb7ae01a6 |
children | af724d3510d7 |
rev | line source |
---|---|
0 | 1 module dmd.TypeStruct; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Type; |
55 | 5 import dmd.TypeInstance; |
0 | 6 import dmd.StructDeclaration; |
7 import dmd.Declaration; | |
8 import dmd.STC; | |
9 import dmd.MOD; | |
10 import dmd.OutBuffer; | |
11 import dmd.DotVarExp; | |
12 import dmd.TemplateMixin; | |
13 import dmd.DotTemplateExp; | |
14 import dmd.DsymbolExp; | |
15 import dmd.TypeExp; | |
16 import dmd.EnumMember; | |
17 import dmd.Id; | |
18 import dmd.DotIdExp; | |
19 import dmd.ScopeExp; | |
20 import dmd.TupleExp; | |
21 import dmd.TemplateDeclaration; | |
22 import dmd.OverloadSet; | |
23 import dmd.Import; | |
24 import dmd.DotExp; | |
25 import dmd.ErrorExp; | |
26 import dmd.Loc; | |
27 import dmd.Scope; | |
28 import dmd.Dsymbol; | |
29 import dmd.HdrGenState; | |
30 import dmd.Expression; | |
31 import dmd.Identifier; | |
32 import dmd.MATCH; | |
33 import dmd.ArrayTypes; | |
55 | 34 import dmd.DYNCAST; |
0 | 35 import dmd.TemplateInstance; |
36 import dmd.FuncDeclaration; | |
37 import dmd.VarExp; | |
38 import dmd.CommaExp; | |
39 import dmd.ThisExp; | |
135 | 40 import dmd.StructLiteralExp; |
0 | 41 import dmd.SymbolDeclaration; |
42 import dmd.TypeInfoDeclaration; | |
43 import dmd.TypeInfoStructDeclaration; | |
44 import dmd.TY; | |
45 import dmd.TOK; | |
46 import dmd.Global; | |
47 import dmd.VarDeclaration; | |
48 import dmd.Util; | |
49 import dmd.expression.Util; | |
50 | |
51 import dmd.backend.TYPE; | |
52 import dmd.backend.dt_t; | |
53 import dmd.backend.Symbol; | |
54 import dmd.backend.Util; | |
55 import dmd.backend.STR; | |
56 import dmd.backend.TYM; | |
57 import dmd.backend.Classsym; | |
58 import dmd.backend.SC; | |
59 import dmd.backend.LIST; | |
60 | |
61 import std.string : toStringz; | |
62 | |
63 class TypeStruct : Type | |
64 { | |
65 StructDeclaration sym; | |
66 | |
67 this(StructDeclaration sym) | |
68 { | |
69 super(TY.Tstruct); | |
70 this.sym = sym; | |
71 } | |
72 version (DumbClone) { | |
73 } else { | |
74 final TypeStruct cloneTo(TypeStruct t) | |
75 { | |
76 super.cloneTo(t); | |
77 assert(t.sym is sym); | |
78 return t; | |
79 } | |
80 | |
81 TypeStruct clone() | |
82 { | |
83 assert(this.classinfo == TypeStruct.classinfo); | |
84 return cloneTo(new TypeStruct(sym)); | |
85 } | |
86 } | |
72 | 87 override ulong size(Loc loc) |
0 | 88 { |
89 return sym.size(loc); | |
90 } | |
91 | |
72 | 92 override uint alignsize() |
0 | 93 { |
94 uint sz; | |
95 | |
96 sym.size(Loc(0)); // give error for forward references | |
97 sz = sym.alignsize; | |
98 if (sz > sym.structalign) | |
99 sz = sym.structalign; | |
100 return sz; | |
101 } | |
102 | |
72 | 103 override string toChars() |
0 | 104 { |
55 | 105 //printf("sym.parent: %s, deco = %s\n", sym.parent.toChars(), deco); |
106 if (mod) | |
107 return Type.toChars(); | |
108 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
109 if (ti && ti.toAlias() == sym) | |
110 { | |
111 return ti.toChars(); | |
112 } | |
113 return sym.toChars(); | |
0 | 114 } |
115 | |
72 | 116 override Type syntaxCopy() |
0 | 117 { |
118 assert(false); | |
119 } | |
120 | |
72 | 121 override Type semantic(Loc loc, Scope sc) |
0 | 122 { |
123 //printf("TypeStruct.semantic('%s')\n", sym.toChars()); | |
124 | |
125 /* Cannot do semantic for sym because scope chain may not | |
126 * be right. | |
127 */ | |
128 //sym.semantic(sc); | |
129 | |
130 return merge(); | |
131 } | |
132 | |
72 | 133 override Dsymbol toDsymbol(Scope sc) |
0 | 134 { |
135 return sym; | |
136 } | |
137 | |
72 | 138 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 139 { |
140 string name = sym.mangle(); | |
141 //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", toChars(), name); | |
142 Type.toDecoBuffer(buf, flag); | |
143 buf.printf("%s", name); | |
144 } | |
145 | |
72 | 146 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 147 { |
148 if (mod != this.mod) | |
149 { | |
150 toCBuffer3(buf, hgs, mod); | |
151 return; | |
152 } | |
153 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
154 if (ti && ti.toAlias() == sym) | |
155 buf.writestring(ti.toChars()); | |
156 else | |
157 buf.writestring(sym.toChars()); | |
158 } | |
159 | |
72 | 160 override Expression dotExp(Scope sc, Expression e, Identifier ident) |
0 | 161 { |
162 uint offset; | |
163 | |
164 VarDeclaration v; | |
165 Dsymbol s; | |
166 DotVarExp de; | |
167 Declaration d; | |
168 | |
169 version (LOGDOTEXP) { | |
170 printf("TypeStruct.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); | |
171 } | |
172 if (!sym.members) | |
173 { | |
174 error(e.loc, "struct %s is forward referenced", sym.toChars()); | |
175 return new ErrorExp(); | |
176 } | |
177 | |
178 /* If e.tupleof | |
179 */ | |
180 if (ident is Id.tupleof_) | |
181 { | |
182 /* Create a TupleExp out of the fields of the struct e: | |
183 * (e.field0, e.field1, e.field2, ...) | |
184 */ | |
185 e = e.semantic(sc); // do this before turning on noaccesscheck | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
186 auto exps = new Expressions; |
0 | 187 exps.reserve(sym.fields.dim); |
188 for (size_t i = 0; i < sym.fields.dim; i++) | |
189 { | |
79 | 190 VarDeclaration v2 = cast(VarDeclaration)sym.fields[i]; |
0 | 191 Expression fe = new DotVarExp(e.loc, e, v2); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
192 exps.push(fe); |
0 | 193 } |
194 e = new TupleExp(e.loc, exps); | |
195 sc = sc.push(); | |
196 sc.noaccesscheck = 1; | |
197 e = e.semantic(sc); | |
198 sc.pop(); | |
199 return e; | |
200 } | |
201 | |
202 if (e.op == TOK.TOKdotexp) | |
203 { | |
204 DotExp de2 = cast(DotExp)e; | |
205 | |
206 if (de2.e1.op == TOK.TOKimport) | |
207 { | |
208 assert(0); // cannot find a case where this happens; leave | |
209 // assert in until we do | |
210 ScopeExp se = cast(ScopeExp)de2.e1; | |
211 | |
212 s = se.sds.search(e.loc, ident, 0); | |
213 e = de2.e1; | |
214 goto L1; | |
215 } | |
216 } | |
217 | |
218 s = sym.search(e.loc, ident, 0); | |
219 L1: | |
220 if (!s) | |
221 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
222 return noMember(sc, e, ident); |
0 | 223 } |
224 | |
225 if (!s.isFuncDeclaration()) // because of overloading | |
226 s.checkDeprecated(e.loc, sc); | |
227 | |
228 s = s.toAlias(); | |
229 | |
230 v = s.isVarDeclaration(); | |
231 if (v && !v.isDataseg()) | |
232 { | |
233 Expression ei = v.getConstInitializer(); | |
234 if (ei) | |
235 { | |
236 e = ei.copy(); // need to copy it if it's a StringExp | |
237 e = e.semantic(sc); | |
238 return e; | |
239 } | |
240 } | |
241 | |
242 if (s.getType()) | |
243 { | |
244 //return new DotTypeExp(e.loc, e, s); | |
245 return new TypeExp(e.loc, s.getType()); | |
246 } | |
247 | |
248 EnumMember em = s.isEnumMember(); | |
249 if (em) | |
250 { | |
251 assert(em.value); | |
252 return em.value.copy(); | |
253 } | |
254 | |
255 TemplateMixin tm = s.isTemplateMixin(); | |
256 if (tm) | |
257 { | |
258 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); | |
259 de2.type = e.type; | |
260 return de2; | |
261 } | |
262 | |
263 TemplateDeclaration td = s.isTemplateDeclaration(); | |
264 if (td) | |
265 { | |
266 e = new DotTemplateExp(e.loc, e, td); | |
267 e.semantic(sc); | |
268 return e; | |
269 } | |
270 | |
271 TemplateInstance ti = s.isTemplateInstance(); | |
272 if (ti) | |
273 { | |
274 if (!ti.semanticRun) | |
275 ti.semantic(sc); | |
276 s = ti.inst.toAlias(); | |
277 if (!s.isTemplateInstance()) | |
278 goto L1; | |
279 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); | |
280 de2.type = e.type; | |
281 return de2; | |
282 } | |
283 | |
284 Import timp = s.isImport(); | |
285 if (timp) | |
286 { | |
287 e = new DsymbolExp(e.loc, s, 0); | |
288 e = e.semantic(sc); | |
289 return e; | |
290 } | |
291 | |
292 OverloadSet o = s.isOverloadSet(); | |
293 if (o) | |
294 { | |
295 /* We really should allow this, triggered by: | |
296 * template c() | |
297 * { | |
298 * void a(); | |
299 * void b () { this.a(); } | |
300 * } | |
301 * struct S | |
302 * { | |
303 * mixin c; | |
304 * mixin c; | |
305 * } | |
306 * alias S e; | |
307 */ | |
308 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); | |
309 return new ErrorExp(); | |
310 } | |
311 | |
312 d = s.isDeclaration(); | |
313 | |
314 debug { | |
315 if (!d) | |
316 writef("d = %s '%s'\n", s.kind(), s.toChars()); | |
317 } | |
318 assert(d); | |
319 | |
320 if (e.op == TOK.TOKtype) | |
321 { | |
322 FuncDeclaration fd = sc.func; | |
323 | |
324 if (d.isTupleDeclaration()) | |
325 { | |
326 e = new TupleExp(e.loc, d.isTupleDeclaration()); | |
327 e = e.semantic(sc); | |
328 return e; | |
329 } | |
330 | |
331 if (d.needThis() && fd && fd.vthis) | |
332 { | |
333 e = new DotVarExp(e.loc, new ThisExp(e.loc), d); | |
334 e = e.semantic(sc); | |
335 return e; | |
336 } | |
337 | |
338 return new VarExp(e.loc, d, 1); | |
339 } | |
340 | |
341 if (d.isDataseg()) | |
342 { | |
343 // (e, d) | |
344 accessCheck(e.loc, sc, e, d); | |
345 VarExp ve = new VarExp(e.loc, d); | |
346 e = new CommaExp(e.loc, e, ve); | |
347 e.type = d.type; | |
348 return e; | |
349 } | |
350 | |
351 if (v) | |
352 { | |
353 if (v.toParent() != sym) | |
354 sym.error(e.loc, "'%s' is not a member", v.toChars()); | |
355 | |
356 // *(&e + offset) | |
357 accessCheck(e.loc, sc, e, d); | |
358 static if (false) { | |
359 Expression b = new AddrExp(e.loc, e); | |
360 b.type = e.type.pointerTo(); | |
361 b = new AddExp(e.loc, b, new IntegerExp(e.loc, v.offset, Type.tint32)); | |
362 b.type = v.type.pointerTo(); | |
363 b = new PtrExp(e.loc, b); | |
364 b.type = v.type.addMod(e.type.mod); | |
365 return b; | |
366 } | |
367 } | |
368 | |
369 de = new DotVarExp(e.loc, e, d); | |
370 return de.semantic(sc); | |
371 } | |
372 | |
72 | 373 override uint memalign(uint salign) |
0 | 374 { |
375 sym.size(Loc(0)); // give error for forward references | |
376 return sym.structalign; | |
377 } | |
378 | |
72 | 379 override Expression defaultInit(Loc loc) |
0 | 380 { |
381 version (LOGDEFAULTINIT) { | |
382 printf("TypeStruct::defaultInit() '%s'\n", toChars()); | |
383 } | |
135 | 384 Symbol *s = sym.toInitializer(); |
385 Declaration d = new SymbolDeclaration(sym.loc, s, sym); | |
0 | 386 assert(d); |
387 d.type = this; | |
388 return new VarExp(sym.loc, d); | |
389 } | |
135 | 390 |
391 /*************************************** | |
392 * Use when we prefer the default initializer to be a literal, | |
393 * rather than a global immutable variable. | |
394 */ | |
154
14feb7ae01a6
* changed the build system to build a release version if the debug one compiles
trass3r
parents:
135
diff
changeset
|
395 override Expression defaultInitLiteral(Loc loc) |
135 | 396 { |
397 version (LOGDEFAULTINIT) { | |
398 printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); | |
399 } | |
400 auto structelems = new Expressions(); | |
401 structelems.setDim(sym.fields.dim); | |
402 for (size_t j = 0; j < structelems.dim; j++) | |
403 { | |
404 auto vd = cast(VarDeclaration)(sym.fields[j]); | |
405 Expression e; | |
406 if (vd.init) | |
407 e = vd.init.toExpression(); | |
408 else | |
409 e = vd.type.defaultInitLiteral(); | |
410 structelems[j] = e; | |
411 } | |
412 auto structinit = new StructLiteralExp(loc, cast(StructDeclaration)sym, structelems); | |
413 // Why doesn't the StructLiteralExp constructor do this, when | |
414 // sym->type != NULL ? | |
415 structinit.type = sym.type; | |
416 return structinit; | |
417 } | |
418 | |
0 | 419 |
72 | 420 override bool isZeroInit(Loc loc) |
0 | 421 { |
422 return sym.zeroInit; | |
423 } | |
424 | |
73 | 425 override bool isAssignable() |
0 | 426 { |
427 /* If any of the fields are const or invariant, | |
428 * then one cannot assign this struct. | |
429 */ | |
430 for (size_t i = 0; i < sym.fields.dim; i++) | |
431 { | |
79 | 432 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
135 | 433 if (v.isConst() || v.isImmutable()) |
0 | 434 return false; |
435 } | |
436 return true; | |
437 } | |
438 | |
72 | 439 override bool checkBoolean() |
0 | 440 { |
441 return false; | |
442 } | |
443 | |
72 | 444 override dt_t** toDt(dt_t** pdt) |
0 | 445 { |
446 sym.toDt(pdt); | |
447 return pdt; | |
448 } | |
449 | |
72 | 450 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 451 { |
55 | 452 //printf("TypeStruct.deduceType()\n"); |
453 //printf("\tthis.parent = %s, ", sym.parent.toChars()); print(); | |
454 //printf("\ttparam = %d, ", tparam.ty); tparam.print(); | |
455 | |
456 /* If this struct is a template struct, and we're matching | |
457 * it against a template instance, convert the struct type | |
458 * to a template instance, too, and try again. | |
459 */ | |
460 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
461 | |
462 if (tparam && tparam.ty == Tinstance) | |
463 { | |
464 if (ti && ti.toAlias() == sym) | |
465 { | |
466 TypeInstance t = new TypeInstance(Loc(0), ti); | |
467 return t.deduceType(sc, tparam, parameters, dedtypes); | |
468 } | |
469 | |
470 /* Match things like: | |
471 * S!(T).foo | |
472 */ | |
473 TypeInstance tpi = cast(TypeInstance)tparam; | |
474 if (tpi.idents.dim) | |
475 { Identifier id = cast(Identifier)tpi.idents.data[tpi.idents.dim - 1]; | |
476 if (id.dyncast() == DYNCAST.DYNCAST_IDENTIFIER && sym.ident.equals(id)) | |
477 { | |
478 Type tparent = sym.parent.getType(); | |
479 if (tparent) | |
480 { | |
481 /* Slice off the .foo in S!(T).foo | |
482 */ | |
483 tpi.idents.dim--; | |
484 MATCH m = tparent.deduceType(sc, tpi, parameters, dedtypes); | |
485 tpi.idents.dim++; | |
486 return m; | |
487 } | |
488 } | |
489 } | |
490 } | |
491 | |
492 // Extra check | |
493 if (tparam && tparam.ty == Tstruct) | |
494 { | |
495 TypeStruct tp = cast(TypeStruct)tparam; | |
496 | |
497 if (sym != tp.sym) | |
498 return MATCHnomatch; | |
499 } | |
500 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 501 } |
502 | |
72 | 503 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 504 { |
505 return new TypeInfoStructDeclaration(this); | |
506 } | |
507 | |
72 | 508 override bool hasPointers() |
0 | 509 { |
135 | 510 // Probably should cache this information in sym rather than recompute |
0 | 511 StructDeclaration s = sym; |
512 | |
513 sym.size(Loc(0)); // give error for forward references | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
514 foreach (VarDeclaration sm; s.fields) |
0 | 515 { |
516 Declaration d = sm.isDeclaration(); | |
517 if (d.storage_class & STC.STCref || d.hasPointers()) | |
518 return true; | |
519 } | |
520 | |
521 return false; | |
522 } | |
523 | |
72 | 524 override MATCH implicitConvTo(Type to) |
0 | 525 { |
526 MATCH m; | |
527 | |
528 //printf("TypeStruct.implicitConvTo(%s => %s)\n", toChars(), to.toChars()); | |
529 if (ty == to.ty && sym == (cast(TypeStruct)to).sym) | |
530 { | |
531 m = MATCHexact; // exact match | |
532 if (mod != to.mod) | |
533 { | |
135 | 534 if (MODimplicitConv(mod, to.mod)) |
0 | 535 m = MATCHconst; |
536 else | |
537 { /* Check all the fields. If they can all be converted, | |
538 * allow the conversion. | |
539 */ | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
540 foreach (VarDeclaration v; sym.fields) |
0 | 541 { |
542 assert(v && v.storage_class & STCfield); | |
543 | |
544 // 'from' type | |
545 Type tvf = v.type.addMod(mod); | |
546 | |
547 // 'to' type | |
548 Type tv = v.type.castMod(to.mod); | |
549 | |
550 //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), tvf.implicitConvTo(tv)); | |
551 if (tvf.implicitConvTo(tv) < MATCHconst) | |
552 return MATCHnomatch; | |
553 } | |
554 m = MATCHconst; | |
555 } | |
556 } | |
557 } | |
558 else if (sym.aliasthis) | |
559 { | |
560 m = MATCHnomatch; | |
561 Declaration d = sym.aliasthis.isDeclaration(); | |
562 if (d) | |
563 { | |
564 assert(d.type); | |
565 Type t = d.type.addMod(mod); | |
566 m = t.implicitConvTo(to); | |
567 } | |
568 } | |
569 else | |
570 m = MATCHnomatch; // no match | |
571 return m; | |
572 } | |
573 | |
72 | 574 override MATCH constConv(Type to) |
0 | 575 { |
576 if (equals(to)) | |
577 return MATCHexact; | |
135 | 578 if (ty == to.ty && sym == (cast(TypeStruct)to).sym && |
579 MODimplicitConv(mod, to.mod)) | |
0 | 580 return MATCHconst; |
581 return MATCHnomatch; | |
582 } | |
583 | |
72 | 584 override Type toHeadMutable() |
0 | 585 { |
586 assert(false); | |
587 } | |
588 | |
589 version (CPP_MANGLE) { | |
590 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
591 { | |
592 assert(false); | |
593 } | |
594 } | |
595 | |
72 | 596 override type* toCtype() |
0 | 597 { |
598 type* t; | |
599 Symbol* s; | |
600 | |
601 if (ctype) | |
602 return ctype; | |
603 | |
604 //printf("TypeStruct.toCtype() '%s'\n", sym.toChars()); | |
605 s = symbol_calloc(toStringz(sym.toPrettyChars())); | |
606 s.Sclass = SC.SCstruct; | |
607 s.Sstruct = struct_calloc(); | |
608 s.Sstruct.Sflags |= 0; /// huh? | |
609 s.Sstruct.Salignsize = sym.alignsize; | |
610 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; | |
611 s.Sstruct.Sstructsize = sym.structsize; | |
612 | |
613 if (sym.isUnionDeclaration()) | |
614 s.Sstruct.Sflags |= STR.STRunion; | |
615 | |
616 t = type_alloc(TYM.TYstruct); | |
617 t.Ttag = cast(Classsym*)s; // structure tag name | |
618 t.Tcount++; | |
619 s.Stype = t; | |
620 slist_add(s); | |
621 ctype = t; | |
622 | |
623 /* Add in fields of the struct | |
624 * (after setting ctype to avoid infinite recursion) | |
625 */ | |
626 if (global.params.symdebug) { | |
627 for (int i = 0; i < sym.fields.dim; i++) | |
628 { | |
79 | 629 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
0 | 630 |
631 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); | |
632 s2.Smemoff = v.offset; | |
633 list_append(&s.Sstruct.Sfldlst, s2); | |
634 } | |
635 } | |
636 | |
637 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); | |
638 return t; | |
639 } | |
72 | 640 } |