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