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