Mercurial > projects > ddmd
comparison dmd/TypeClass.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 51605de93870 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.TypeClass; | |
2 | |
3 import dmd.Type; | |
4 import dmd.ClassDeclaration; | |
5 import dmd.Loc; | |
6 import dmd.Dsymbol; | |
7 import dmd.Scope; | |
8 import dmd.OutBuffer; | |
9 import dmd.HdrGenState; | |
10 import dmd.Expression; | |
11 import dmd.Identifier; | |
12 import dmd.MATCH; | |
13 import dmd.CppMangleState; | |
14 import dmd.ArrayTypes; | |
15 import dmd.TypeInfoDeclaration; | |
16 import dmd.TY; | |
17 import dmd.MOD; | |
18 import dmd.Global; | |
19 import dmd.TypePointer; | |
20 import dmd.Declaration; | |
21 import dmd.VarDeclaration; | |
22 import dmd.TOK; | |
23 import dmd.DotExp; | |
24 import dmd.Id; | |
25 import dmd.ScopeExp; | |
26 import dmd.DotVarExp; | |
27 import dmd.VarExp; | |
28 import dmd.PtrExp; | |
29 import dmd.AddExp; | |
30 import dmd.IntegerExp; | |
31 import dmd.DotIdExp; | |
32 import dmd.EnumMember; | |
33 import dmd.TemplateMixin; | |
34 import dmd.TemplateDeclaration; | |
35 import dmd.TemplateInstance; | |
36 import dmd.OverloadSet; | |
37 import dmd.DotTypeExp; | |
38 import dmd.TupleExp; | |
39 import dmd.ClassInfoDeclaration; | |
40 import dmd.TypeInfoInterfaceDeclaration; | |
41 import dmd.TypeInfoClassDeclaration; | |
42 import dmd.Util; | |
43 import dmd.NullExp; | |
44 import dmd.TypeExp; | |
45 import dmd.DotTemplateExp; | |
46 import dmd.ErrorExp; | |
47 import dmd.ThisExp; | |
48 import dmd.CommaExp; | |
49 | |
50 import dmd.expression.Util; | |
51 import dmd.backend.Symbol; | |
52 import dmd.backend.TYPE; | |
53 import dmd.backend.Util; | |
54 import dmd.backend.SC; | |
55 import dmd.backend.STR; | |
56 import dmd.backend.TYM; | |
57 import dmd.backend.LIST; | |
58 import dmd.backend.Classsym; | |
59 | |
60 import std.string : toStringz; | |
61 | |
62 class TypeClass : Type | |
63 { | |
64 ClassDeclaration sym; | |
65 | |
66 this(ClassDeclaration sym) | |
67 { | |
68 super(TY.Tclass); | |
69 this.sym = sym; | |
70 } | |
71 | |
72 version (DumbClone) { | |
73 } else { | |
74 Type clone() | |
75 { | |
76 assert(false); | |
77 } | |
78 } | |
79 ulong size(Loc loc) | |
80 { | |
81 return PTRSIZE; | |
82 } | |
83 | |
84 string toChars() | |
85 { | |
86 if (mod) | |
87 return Type.toChars(); | |
88 return sym.toPrettyChars(); | |
89 } | |
90 | |
91 Type syntaxCopy() | |
92 { | |
93 assert(false); | |
94 } | |
95 | |
96 Type semantic(Loc loc, Scope sc) | |
97 { | |
98 //printf("TypeClass.semantic(%s)\n", sym.toChars()); | |
99 if (deco) | |
100 return this; | |
101 //printf("\t%s\n", merge().deco); | |
102 return merge(); | |
103 } | |
104 | |
105 Dsymbol toDsymbol(Scope sc) | |
106 { | |
107 return sym; | |
108 } | |
109 | |
110 void toDecoBuffer(OutBuffer buf, int flag) | |
111 { | |
112 string name = sym.mangle(); | |
113 //printf("TypeClass.toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name); | |
114 Type.toDecoBuffer(buf, flag); | |
115 buf.printf("%s", name); | |
116 } | |
117 | |
118 void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) | |
119 { | |
120 if (mod != this.mod) | |
121 { | |
122 toCBuffer3(buf, hgs, mod); | |
123 return; | |
124 } | |
125 buf.writestring(sym.toChars()); | |
126 } | |
127 | |
128 Expression dotExp(Scope sc, Expression e, Identifier ident) | |
129 { | |
130 uint offset; | |
131 | |
132 Expression b; | |
133 VarDeclaration v; | |
134 Dsymbol s; | |
135 | |
136 version (LOGDOTEXP) { | |
137 printf("TypeClass.dotExp(e='%s', ident='%s')\n", e.toChars(), ident.toChars()); | |
138 } | |
139 | |
140 if (e.op == TOK.TOKdotexp) | |
141 { | |
142 DotExp de = cast(DotExp)e; | |
143 | |
144 if (de.e1.op == TOK.TOKimport) | |
145 { | |
146 ScopeExp se = cast(ScopeExp)de.e1; | |
147 | |
148 s = se.sds.search(e.loc, ident, 0); | |
149 e = de.e1; | |
150 goto L1; | |
151 } | |
152 } | |
153 | |
154 if (ident is Id.tupleof_) | |
155 { | |
156 /* Create a TupleExp | |
157 */ | |
158 e = e.semantic(sc); // do this before turning on noaccesscheck | |
159 Expressions exps = new Expressions; | |
160 exps.reserve(sym.fields.dim); | |
161 for (size_t i = 0; i < sym.fields.dim; i++) | |
162 { | |
163 VarDeclaration v2 = cast(VarDeclaration)sym.fields.data[i]; | |
164 Expression fe = new DotVarExp(e.loc, e, v2); | |
165 exps.push(cast(void*)fe); | |
166 } | |
167 e = new TupleExp(e.loc, exps); | |
168 sc = sc.push(); | |
169 sc.noaccesscheck = 1; | |
170 e = e.semantic(sc); | |
171 sc.pop(); | |
172 return e; | |
173 } | |
174 | |
175 s = sym.search(e.loc, ident, 0); | |
176 L1: | |
177 if (!s) | |
178 { | |
179 // See if it's a base class | |
180 ClassDeclaration cbase; | |
181 for (cbase = sym.baseClass; cbase; cbase = cbase.baseClass) | |
182 { | |
183 if (cbase.ident.equals(ident)) | |
184 { | |
185 e = new DotTypeExp(Loc(0), e, cbase); | |
186 return e; | |
187 } | |
188 } | |
189 | |
190 if (ident is Id.classinfo_) | |
191 { | |
192 assert(ClassDeclaration.classinfo); | |
193 Type t = ClassDeclaration.classinfo.type; | |
194 if (e.op == TOK.TOKtype || e.op == TOK.TOKdottype) | |
195 { | |
196 /* For type.classinfo, we know the classinfo | |
197 * at compile time. | |
198 */ | |
199 if (!sym.vclassinfo) | |
200 sym.vclassinfo = new ClassInfoDeclaration(sym); | |
201 | |
202 e = new VarExp(e.loc, sym.vclassinfo); | |
203 e = e.addressOf(sc); | |
204 e.type = t; // do this so we don't get redundant dereference | |
205 } | |
206 else | |
207 { | |
208 /* For class objects, the classinfo reference is the first | |
209 * entry in the vtbl[] | |
210 */ | |
211 e = new PtrExp(e.loc, e); | |
212 e.type = t.pointerTo(); | |
213 if (sym.isInterfaceDeclaration()) | |
214 { | |
215 if (sym.isCPPinterface()) | |
216 { | |
217 /* C++ interface vtbl[]s are different in that the | |
218 * first entry is always pointer to the first virtual | |
219 * function, not classinfo. | |
220 * We can't get a .classinfo for it. | |
221 */ | |
222 error(e.loc, "no .classinfo for C++ interface objects"); | |
223 } | |
224 /* For an interface, the first entry in the vtbl[] | |
225 * is actually a pointer to an instance of struct Interface. | |
226 * The first member of Interface is the .classinfo, | |
227 * so add an extra pointer indirection. | |
228 */ | |
229 e.type = e.type.pointerTo(); | |
230 e = new PtrExp(e.loc, e); | |
231 e.type = t.pointerTo(); | |
232 } | |
233 e = new PtrExp(e.loc, e, t); | |
234 } | |
235 return e; | |
236 } | |
237 | |
238 if (ident is Id.__vptr) | |
239 { | |
240 /* The pointer to the vtbl[] | |
241 * *cast(invariant(void*)**)e | |
242 */ | |
243 e = e.castTo(sc, tvoidptr.invariantOf().pointerTo().pointerTo()); | |
244 e = new PtrExp(e.loc, e); | |
245 e = e.semantic(sc); | |
246 return e; | |
247 } | |
248 | |
249 if (ident is Id.__monitor) | |
250 { /* The handle to the monitor (call it a void*) | |
251 * *(cast(void**)e + 1) | |
252 */ | |
253 e = e.castTo(sc, tvoidptr.pointerTo()); | |
254 e = new AddExp(e.loc, e, new IntegerExp(1)); | |
255 e = new PtrExp(e.loc, e); | |
256 e = e.semantic(sc); | |
257 return e; | |
258 } | |
259 | |
260 if (ident is Id.typeinfo_) | |
261 { | |
262 if (!global.params.useDeprecated) | |
263 error(e.loc, ".typeinfo deprecated, use typeid(type)"); | |
264 | |
265 return getTypeInfo(sc); | |
266 } | |
267 if (ident is Id.outer && sym.vthis) | |
268 { | |
269 s = sym.vthis; | |
270 } | |
271 else | |
272 { | |
273 if (ident !is Id.__sizeof && | |
274 ident !is Id.alignof_ && | |
275 ident !is Id.init_ && | |
276 ident !is Id.mangleof_ && | |
277 ident !is Id.stringof_ && | |
278 ident !is Id.offsetof) | |
279 { | |
280 /* See if we should forward to the alias this. | |
281 */ | |
282 if (sym.aliasthis) | |
283 { | |
284 /* Rewrite e.ident as: | |
285 * e.aliasthis.ident | |
286 */ | |
287 e = new DotIdExp(e.loc, e, sym.aliasthis.ident); | |
288 e = new DotIdExp(e.loc, e, ident); | |
289 return e.semantic(sc); | |
290 } | |
291 | |
292 /* Look for overloaded opDot() to see if we should forward request | |
293 * to it. | |
294 */ | |
295 Dsymbol fd = search_function(sym, Id.opDot); | |
296 if (fd) | |
297 { | |
298 /* Rewrite e.ident as: | |
299 * e.opId().ident | |
300 */ | |
301 e = build_overload(e.loc, sc, e, null, fd.ident); | |
302 e = new DotIdExp(e.loc, e, ident); | |
303 return e.semantic(sc); | |
304 } | |
305 } | |
306 | |
307 return Type.dotExp(sc, e, ident); | |
308 } | |
309 } | |
310 | |
311 if (!s.isFuncDeclaration()) // because of overloading | |
312 s.checkDeprecated(e.loc, sc); | |
313 | |
314 s = s.toAlias(); | |
315 v = s.isVarDeclaration(); | |
316 | |
317 if (v && !v.isDataseg()) | |
318 { | |
319 Expression ei = v.getConstInitializer(); | |
320 | |
321 if (ei) | |
322 { | |
323 e = ei.copy(); // need to copy it if it's a StringExp | |
324 e = e.semantic(sc); | |
325 return e; | |
326 } | |
327 } | |
328 | |
329 if (s.getType()) | |
330 { | |
331 // if (e.op == TOKtype) | |
332 return new TypeExp(e.loc, s.getType()); | |
333 // return new DotTypeExp(e.loc, e, s); | |
334 } | |
335 | |
336 EnumMember em = s.isEnumMember(); | |
337 if (em) | |
338 { | |
339 assert(em.value); | |
340 return em.value.copy(); | |
341 } | |
342 | |
343 TemplateMixin tm = s.isTemplateMixin(); | |
344 if (tm) | |
345 { | |
346 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); | |
347 de.type = e.type; | |
348 return de; | |
349 } | |
350 | |
351 TemplateDeclaration td = s.isTemplateDeclaration(); | |
352 if (td) | |
353 { | |
354 e = new DotTemplateExp(e.loc, e, td); | |
355 e.semantic(sc); | |
356 return e; | |
357 } | |
358 | |
359 TemplateInstance ti = s.isTemplateInstance(); | |
360 if (ti) | |
361 { | |
362 if (!ti.semanticRun) | |
363 ti.semantic(sc); | |
364 s = ti.inst.toAlias(); | |
365 if (!s.isTemplateInstance()) | |
366 goto L1; | |
367 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); | |
368 de.type = e.type; | |
369 return de; | |
370 } | |
371 | |
372 OverloadSet o = s.isOverloadSet(); | |
373 if (o) | |
374 { | |
375 /* We really should allow this | |
376 */ | |
377 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); | |
378 return new ErrorExp(); | |
379 } | |
380 | |
381 Declaration d = s.isDeclaration(); | |
382 if (!d) | |
383 { | |
384 e.error("%s.%s is not a declaration", e.toChars(), ident.toChars()); | |
385 return new ErrorExp(); | |
386 } | |
387 | |
388 if (e.op == TOK.TOKtype) | |
389 { | |
390 /* It's: | |
391 * Class.d | |
392 */ | |
393 if (d.isTupleDeclaration()) | |
394 { | |
395 e = new TupleExp(e.loc, d.isTupleDeclaration()); | |
396 e = e.semantic(sc); | |
397 return e; | |
398 } | |
399 else if (d.needThis() && (hasThis(sc) || !d.isFuncDeclaration())) | |
400 { | |
401 if (sc.func) | |
402 { | |
403 ClassDeclaration thiscd; | |
404 thiscd = sc.func.toParent().isClassDeclaration(); | |
405 | |
406 if (thiscd) | |
407 { | |
408 ClassDeclaration cd = e.type.isClassHandle(); | |
409 | |
410 if (cd is thiscd) | |
411 { | |
412 e = new ThisExp(e.loc); | |
413 e = new DotTypeExp(e.loc, e, cd); | |
414 DotVarExp de = new DotVarExp(e.loc, e, d); | |
415 e = de.semantic(sc); | |
416 return e; | |
417 } | |
418 else if ((!cd || !cd.isBaseOf(thiscd, null)) && !d.isFuncDeclaration()) | |
419 e.error("'this' is required, but %s is not a base class of %s", e.type.toChars(), thiscd.toChars()); | |
420 } | |
421 } | |
422 | |
423 /* Rewrite as: | |
424 * this.d | |
425 */ | |
426 DotVarExp de = new DotVarExp(e.loc, new ThisExp(e.loc), d); | |
427 e = de.semantic(sc); | |
428 return e; | |
429 } | |
430 else | |
431 { | |
432 VarExp ve = new VarExp(e.loc, d, 1); | |
433 return ve; | |
434 } | |
435 } | |
436 | |
437 if (d.isDataseg()) | |
438 { | |
439 // (e, d) | |
440 accessCheck(e.loc, sc, e, d); | |
441 VarExp ve = new VarExp(e.loc, d); | |
442 e = new CommaExp(e.loc, e, ve); | |
443 e.type = d.type; | |
444 return e; | |
445 } | |
446 | |
447 if (d.parent && d.toParent().isModule()) | |
448 { | |
449 // (e, d) | |
450 VarExp ve = new VarExp(e.loc, d, 1); | |
451 e = new CommaExp(e.loc, e, ve); | |
452 e.type = d.type; | |
453 return e; | |
454 } | |
455 | |
456 DotVarExp de = new DotVarExp(e.loc, e, d); | |
457 return de.semantic(sc); | |
458 } | |
459 | |
460 ClassDeclaration isClassHandle() | |
461 { | |
462 return sym; | |
463 } | |
464 | |
465 bool isBaseOf(Type t, int* poffset) | |
466 { | |
467 assert(false); | |
468 } | |
469 | |
470 MATCH implicitConvTo(Type to) | |
471 { | |
472 //printf("TypeClass.implicitConvTo(to = '%s') %s\n", to.toChars(), toChars()); | |
473 MATCH m = constConv(to); | |
474 if (m != MATCH.MATCHnomatch) | |
475 return m; | |
476 | |
477 ClassDeclaration cdto = to.isClassHandle(); | |
478 if (cdto && cdto.isBaseOf(sym, null)) | |
479 { | |
480 //printf("'to' is base\n"); | |
481 return MATCH.MATCHconvert; | |
482 } | |
483 | |
484 if (global.params.Dversion == 1) | |
485 { | |
486 // Allow conversion to (void *) | |
487 if (to.ty == TY.Tpointer && (cast(TypePointer)to).next.ty == TY.Tvoid) | |
488 return MATCH.MATCHconvert; | |
489 } | |
490 | |
491 m = MATCH.MATCHnomatch; | |
492 if (sym.aliasthis) | |
493 { | |
494 Declaration d = sym.aliasthis.isDeclaration(); | |
495 if (d) | |
496 { | |
497 assert(d.type); | |
498 Type t = d.type.addMod(mod); | |
499 m = t.implicitConvTo(to); | |
500 } | |
501 } | |
502 | |
503 return m; | |
504 } | |
505 | |
506 Expression defaultInit(Loc loc) | |
507 { | |
508 version (LOGDEFAULTINIT) { | |
509 printf("TypeClass::defaultInit() '%s'\n", toChars()); | |
510 } | |
511 Expression e = new NullExp(loc); | |
512 e.type = this; | |
513 return e; | |
514 } | |
515 | |
516 bool isZeroInit(Loc loc) | |
517 { | |
518 return true; | |
519 } | |
520 | |
521 MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) | |
522 { | |
523 assert(false); | |
524 } | |
525 | |
526 bool isauto() | |
527 { | |
528 return sym.isauto; | |
529 } | |
530 | |
531 bool checkBoolean() | |
532 { | |
533 return true; | |
534 } | |
535 | |
536 TypeInfoDeclaration getTypeInfoDeclaration() | |
537 { | |
538 if (sym.isInterfaceDeclaration()) | |
539 return new TypeInfoInterfaceDeclaration(this); | |
540 else | |
541 return new TypeInfoClassDeclaration(this); | |
542 } | |
543 | |
544 bool hasPointers() | |
545 { | |
546 return true; | |
547 } | |
548 | |
549 bool builtinTypeInfo() | |
550 { | |
551 /* This is statically put out with the ClassInfo, so | |
552 * claim it is built in so it isn't regenerated by each module. | |
553 */ | |
554 version (DMDV2) { | |
555 return mod ? false : true; | |
556 } else { | |
557 return true; | |
558 } | |
559 } | |
560 | |
561 version (DMDV2) { | |
562 Type toHeadMutable() | |
563 { | |
564 assert(false); | |
565 } | |
566 | |
567 MATCH constConv(Type to) | |
568 { | |
569 if (equals(to)) | |
570 return MATCH.MATCHexact; | |
571 | |
572 if (ty == to.ty && sym == (cast(TypeClass)to).sym && to.mod == MOD.MODconst) | |
573 return MATCH.MATCHconst; | |
574 | |
575 return MATCH.MATCHnomatch; | |
576 } | |
577 | |
578 version (CPP_MANGLE) { | |
579 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
580 { | |
581 assert(false); | |
582 } | |
583 } | |
584 } | |
585 | |
586 type* toCtype() | |
587 { | |
588 type* t; | |
589 Symbol* s; | |
590 | |
591 //printf("TypeClass.toCtype() %s\n", toChars()); | |
592 if (ctype) | |
593 return ctype; | |
594 | |
595 /* Need this symbol to do C++ name mangling | |
596 */ | |
597 string name = sym.isCPPinterface() ? sym.ident.toChars() : sym.toPrettyChars(); | |
598 s = symbol_calloc(toStringz(name)); | |
599 s.Sclass = SC.SCstruct; | |
600 s.Sstruct = struct_calloc(); | |
601 s.Sstruct.Sflags |= STR.STRclass; | |
602 s.Sstruct.Salignsize = sym.alignsize; | |
603 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; | |
604 s.Sstruct.Sstructsize = sym.structsize; | |
605 | |
606 t = type_alloc(TYM.TYstruct); | |
607 t.Ttag = cast(Classsym*)s; // structure tag name | |
608 t.Tcount++; | |
609 s.Stype = t; | |
610 slist_add(s); | |
611 | |
612 t = type_allocn(TYM.TYnptr, t); | |
613 | |
614 t.Tcount++; | |
615 ctype = t; | |
616 | |
617 /* Add in fields of the class | |
618 * (after setting ctype to avoid infinite recursion) | |
619 */ | |
620 if (global.params.symdebug) | |
621 for (int i = 0; i < sym.fields.dim; i++) | |
622 { | |
623 VarDeclaration v = cast(VarDeclaration)sym.fields.data[i]; | |
624 | |
625 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); | |
626 s2.Smemoff = v.offset; | |
627 list_append(&s.Sstruct.Sfldlst, s2); | |
628 } | |
629 | |
630 return t; | |
631 } | |
632 | |
633 Symbol* toSymbol() | |
634 { | |
635 return sym.toSymbol(); | |
636 } | |
637 } |