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