comparison dmd/Dsymbol.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 427f8aa74d28 2cc604139636
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.Dsymbol;
2
3 import dmd.Loc;
4 import dmd.STC;
5 import dmd.Scope;
6 import dmd.Lexer;
7 import dmd.Module;
8 import dmd.Array;
9 import dmd.ScopeDsymbol;
10 import dmd.OutBuffer;
11 import dmd.Id;
12 import dmd.Identifier;
13 import dmd.TemplateInstance;
14 import dmd.HdrGenState;
15 import dmd.AggregateDeclaration;
16 import dmd.ClassDeclaration;
17 import dmd.LabelDsymbol;
18 import dmd.Type;
19 import dmd.PROT;
20 import dmd.ArrayTypes;
21 import dmd.Package;
22 import dmd.EnumMember;
23 import dmd.TemplateDeclaration;
24 import dmd.TemplateMixin;
25 import dmd.Declaration;
26 import dmd.ThisDeclaration;
27 import dmd.TupleDeclaration;
28 import dmd.TypedefDeclaration;
29 import dmd.AliasDeclaration;
30 import dmd.FuncDeclaration;
31 import dmd.FuncAliasDeclaration;
32 import dmd.FuncLiteralDeclaration;
33 import dmd.CtorDeclaration;
34 import dmd.PostBlitDeclaration;
35 import dmd.DtorDeclaration;
36 import dmd.StaticCtorDeclaration;
37 import dmd.StaticDtorDeclaration;
38 import dmd.InvariantDeclaration;
39 import dmd.UnitTestDeclaration;
40 import dmd.NewDeclaration;
41 import dmd.VarDeclaration;
42 import dmd.StructDeclaration;
43 import dmd.UnionDeclaration;
44 import dmd.InterfaceDeclaration;
45 import dmd.WithScopeSymbol;
46 import dmd.ArrayScopeSymbol;
47 import dmd.Import;
48 import dmd.EnumDeclaration;
49 import dmd.DeleteDeclaration;
50 import dmd.SymbolDeclaration;
51 import dmd.AttribDeclaration;
52 import dmd.OverloadSet;
53 import dmd.DYNCAST;
54 import dmd.Global;
55 import dmd.Expression;
56 import dmd.TOK;
57 import dmd.VarExp;
58 import dmd.FuncExp;
59
60 import dmd.backend.Symbol;
61 import dmd.backend.TYPE;
62 import dmd.backend.Util;
63 import dmd.backend.mTYman;
64 import dmd.backend.TYFL;
65 import dmd.backend.TYM;
66 import dmd.backend.mTY;
67 import dmd.backend.SC;
68 import dmd.backend.FL;
69 import dmd.backend.LIST;
70
71 import core.stdc.string : strcmp, memcpy, strlen;
72 import core.stdc.stdlib : alloca;
73
74 import std.stdio;
75
76 // TODO: remove dependencies on these
77 Expression isExpression(Object o)
78 {
79 return cast(Expression)o;
80 }
81
82 Dsymbol isDsymbol(Object o)
83 {
84 return cast(Dsymbol)o;
85 }
86
87 Type isType(Object o)
88 {
89 return cast(Type)o;
90 }
91
92 Dsymbol getDsymbol(Object oarg)
93 {
94 Dsymbol sa;
95 Expression ea = isExpression(oarg);
96 if (ea)
97 { // Try to convert Expression to symbol
98 if (ea.op == TOK.TOKvar)
99 sa = (cast(VarExp)ea).var;
100 else if (ea.op == TOK.TOKfunction)
101 sa = (cast(FuncExp)ea).fd;
102 else
103 sa = null;
104 }
105 else
106 { // Try to convert Type to symbol
107 Type ta = isType(oarg);
108 if (ta)
109 sa = ta.toDsymbol(null);
110 else
111 sa = isDsymbol(oarg); // if already a symbol
112 }
113 return sa;
114 }
115
116 class Dsymbol
117 {
118 Identifier ident;
119 Identifier c_ident;
120 Dsymbol parent;
121 Symbol* csym; // symbol for code generator
122 Symbol* isym; // import version of csym
123 ubyte* comment; // documentation comment for this Dsymbol
124 Loc loc; // where defined
125 Scope scope_; // !=null means context to use for semantic()
126
127 this()
128 {
129 // do nothing
130 }
131
132 this(Identifier ident)
133 {
134 this.ident = ident;
135 }
136
137 string toChars()
138 {
139 return ident ? ident.toChars() : "__anonymous";
140 }
141
142 string locToChars()
143 {
144 scope OutBuffer buf = new OutBuffer();
145 Module m = getModule();
146
147 if (m && m.srcfile)
148 loc.filename = m.srcfile.toChars();
149
150 return loc.toChars();
151 }
152
153 int equals(Object o)
154 {
155 assert(false);
156 }
157
158 bool isAnonymous()
159 {
160 return ident ? 0 : 1;
161 }
162
163 void error(T...)(Loc loc, string format, T t)
164 {
165 if (!global.gag)
166 {
167 string p = loc.toChars();
168 if (p.length == 0)
169 p = locToChars();
170
171 if (p.length != 0) {
172 writef("%s: ", p);
173 }
174
175 write("Error: ");
176 writef("%s %s ", kind(), toPrettyChars());
177
178 writefln(format, t);
179 }
180
181 global.errors++;
182
183 //fatal();
184 }
185
186 void error(T...)(string format, T t)
187 {
188 //printf("Dsymbol.error()\n");
189 if (!global.gag)
190 {
191 string p = loc.toChars();
192
193 if (p.length != 0) {
194 writef("%s: ", p);
195 }
196
197 write("Error: ");
198 if (isAnonymous()) {
199 writef("%s ", kind());
200 } else {
201 writef("%s %s ", kind(), toPrettyChars());
202 }
203
204 writefln(format, t);
205 }
206 global.errors++;
207
208 //fatal();
209 }
210
211 void checkDeprecated(Loc loc, Scope sc)
212 {
213 if (!global.params.useDeprecated && isDeprecated())
214 {
215 // Don't complain if we're inside a deprecated symbol's scope
216 for (Dsymbol sp = sc.parent; sp; sp = sp.parent)
217 {
218 if (sp.isDeprecated())
219 return;
220 }
221
222 for (; sc; sc = sc.enclosing)
223 {
224 if (sc.scopesym && sc.scopesym.isDeprecated())
225 return;
226
227 // If inside a StorageClassDeclaration that is deprecated
228 if (sc.stc & STC.STCdeprecated)
229 return;
230 }
231
232 error(loc, "is deprecated");
233 }
234 }
235
236 Module getModule()
237 {
238 //printf("Dsymbol.getModule()\n");
239 Dsymbol s = this;
240 while (s)
241 {
242 //printf("\ts = '%s'\n", s.toChars());
243 Module m = s.isModule();
244 if (m)
245 return m;
246 s = s.parent;
247 }
248
249 return null;
250 }
251
252 Dsymbol pastMixin()
253 {
254 Dsymbol s = this;
255 //printf("Dsymbol::pastMixin() %s\n", toChars());
256 while (s && s.isTemplateMixin())
257 s = s.parent;
258 return s;
259 }
260
261 Dsymbol toParent()
262 {
263 return parent ? parent.pastMixin() : null;
264 }
265
266 /**********************************
267 * Use this instead of toParent() when looking for the
268 * 'this' pointer of the enclosing function/class.
269 */
270 Dsymbol toParent2()
271 {
272 Dsymbol s = parent;
273 while (s && s.isTemplateInstance())
274 s = s.parent;
275 return s;
276 }
277
278 TemplateInstance inTemplateInstance()
279 {
280 for (Dsymbol parent = this.parent; parent; parent = parent.parent)
281 {
282 TemplateInstance ti = parent.isTemplateInstance();
283 if (ti)
284 return ti;
285 }
286
287 return null;
288 }
289
290 DYNCAST dyncast() { return DYNCAST.DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
291
292 /*************************************
293 * Do syntax copy of an array of Dsymbol's.
294 */
295 static Array arraySyntaxCopy(Array a)
296 {
297 Array b = null;
298 if (a)
299 {
300 b = a.copy();
301 for (int i = 0; i < b.dim; i++)
302 {
303 Dsymbol s = cast(Dsymbol)b.data[i];
304
305 s = s.syntaxCopy(null);
306 b.data[i] = cast(void*)s;
307 }
308 }
309 return b;
310 }
311
312 string toPrettyChars()
313 {
314 //printf("Dsymbol.toPrettyChars() '%s'\n", toChars());
315 if (!parent) {
316 return toChars();
317 }
318
319 size_t len = 0;
320 for (Dsymbol p = this; p; p = p.parent) {
321 len += p.toChars().length + 1;
322 }
323 --len;
324
325 char* s = cast(char*)alloca(len);
326 char* q = s + len;
327
328 for (Dsymbol p = this; p; p = p.parent)
329 {
330 string t = p.toChars();
331 size_t length = t.length;
332 q -= length;
333
334 memcpy(q, t.ptr, length);
335 if (q is s)
336 break;
337
338 q--;
339 version (TARGET_NET) {
340 if (AggregateDeclaration ad = p.isAggregateDeclaration())
341 {
342 if (ad.isNested() && p.parent && p.parent.isAggregateDeclaration())
343 {
344 *q = '/';
345 continue;
346 }
347 }
348 }
349 *q = '.';
350 }
351
352 return s[0..len].idup;
353 }
354
355 string kind()
356 {
357 assert(false);
358 }
359
360 /*********************************
361 * If this symbol is really an alias for another,
362 * return that other.
363 */
364 Dsymbol toAlias() // resolve real symbol
365 {
366 return this;
367 }
368
369 bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
370 {
371 //printf("Dsymbol.addMember('%s')\n", toChars());
372 //printf("Dsymbol.addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd.toChars());
373 assert(sd !is null);
374 parent = sd;
375 if (!isAnonymous()) // no name, so can't add it to symbol table
376 {
377 if (!sd.symtab.insert(this)) // if name is already defined
378 {
379 Dsymbol s2 = sd.symtab.lookup(ident);
380 if (!s2.overloadInsert(this))
381 {
382 sd.multiplyDefined(Loc(0), this, s2);
383 }
384 }
385 if (sd.isAggregateDeclaration() || sd.isEnumDeclaration())
386 {
387 if (ident is Id.__sizeof || ident is Id.alignof_ || ident is Id.mangleof_)
388 error(".%s property cannot be redefined", ident.toChars());
389 }
390 return true;
391 }
392
393 return false;
394 }
395
396 void setScope(Scope sc)
397 {
398 //printf("Dsymbol.setScope() %p %s\n", this, toChars());
399 if (!sc.nofree)
400 sc.setNoFree(); // may need it even after semantic() finishes
401 scope_ = sc;
402 }
403
404 void semantic(Scope sc)
405 {
406 assert(false);
407 }
408
409 /*************************************
410 * Does semantic analysis on initializers and members of aggregates.
411 */
412 void semantic2(Scope sc)
413 {
414 // Most Dsymbols have no further semantic analysis needed
415 }
416
417 /*************************************
418 * Does semantic analysis on function bodies.
419 */
420 void semantic3(Scope sc)
421 {
422 // Most Dsymbols have no further semantic analysis needed
423 }
424
425 /*************************************
426 * Look for function inlining possibilities.
427 */
428 void inlineScan()
429 {
430 // Most Dsymbols aren't functions
431 }
432
433 Dsymbol search(Loc loc, Identifier ident, int flags)
434 {
435 assert(false);
436 }
437
438 /***************************************
439 * Search for identifier id as a member of 'this'.
440 * id may be a template instance.
441 * Returns:
442 * symbol found, null if not
443 */
444 Dsymbol searchX(Loc loc, Scope sc, Identifier id)
445 {
446 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
447 Dsymbol s = toAlias();
448 Dsymbol sm;
449
450 /// HUH????
451 switch (id.dyncast())
452 {
453 case DYNCAST.DYNCAST_IDENTIFIER:
454 sm = s.search(loc, id, 0);
455 break;
456
457 case DYNCAST.DYNCAST_DSYMBOL:
458 {
459 assert(false); /// how can it happen?
460 // It's a template instance
461 //printf("\ttemplate instance id\n");
462 Dsymbol st = cast(Dsymbol)id;
463 TemplateInstance ti = st.isTemplateInstance();
464 id = ti.name;
465 sm = s.search(loc, id, 0);
466 if (!sm)
467 {
468 error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.toChars());
469 return null;
470 }
471 sm = sm.toAlias();
472 TemplateDeclaration td = sm.isTemplateDeclaration();
473 if (!td)
474 {
475 error("%s is not a template, it is a %s", id.toChars(), sm.kind());
476 return null;
477 }
478
479 ti.tempdecl = td;
480 if (!ti.semanticRun)
481 ti.semantic(sc);
482
483 sm = ti.toAlias();
484 break;
485 }
486
487 default:
488 assert(0);
489 }
490 return sm;
491 }
492
493 bool overloadInsert(Dsymbol s)
494 {
495 assert(false);
496 }
497
498 version (_DH) {
499 char* toHChars()
500 {
501 assert(false);
502 }
503
504 void toHBuffer(OutBuffer buf, HdrGenState* hgs)
505 {
506 assert(false);
507 }
508 }
509 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
510 {
511 assert(false);
512 }
513
514 void toDocBuffer(OutBuffer buf)
515 {
516 assert(false);
517 }
518
519 uint size(Loc loc)
520 {
521 assert(false);
522 }
523
524 int isforwardRef()
525 {
526 assert(false);
527 }
528
529 void defineRef(Dsymbol s)
530 {
531 assert(false);
532 }
533
534 AggregateDeclaration isThis() // is a 'this' required to access the member
535 {
536 assert(false);
537 }
538
539 ClassDeclaration isClassMember() // are we a member of a class?
540 {
541 Dsymbol parent = toParent();
542 if (parent && parent.isClassDeclaration())
543 return cast(ClassDeclaration)parent;
544 return null;
545 }
546
547 bool isExport() // is Dsymbol exported?
548 {
549 return false;
550 }
551
552 bool isImportedSymbol() // is Dsymbol imported?
553 {
554 return false;
555 }
556
557 bool isDeprecated() // is Dsymbol deprecated?
558 {
559 return false;
560 }
561
562 version (DMDV2) {
563 bool isOverloadable()
564 {
565 return false;
566 }
567 }
568
569 LabelDsymbol isLabel() // is this a LabelDsymbol?
570 {
571 return null;
572 }
573
574 AggregateDeclaration isMember() // is this symbol a member of an AggregateDeclaration?
575 {
576 //printf("Dsymbol::isMember() %s\n", toChars());
577 Dsymbol parent = toParent();
578 //printf("parent is %s %s\n", parent.kind(), parent.toChars());
579 return parent ? parent.isAggregateDeclaration() : null;
580 }
581
582 Type getType() // is this a type?
583 {
584 return null;
585 }
586
587 string mangle()
588 {
589 OutBuffer buf = new OutBuffer();
590 string id;
591
592 static if (false) {
593 printf("Dsymbol::mangle() '%s'", toChars());
594 if (parent)
595 printf(" parent = %s %s", parent.kind(), parent.toChars());
596 printf("\n");
597 }
598 id = ident ? ident.toChars() : toChars();
599 if (parent)
600 {
601 string p = parent.mangle();
602 if (p[0] == '_' && p[1] == 'D')
603 p = p[2..$];
604 buf.writestring(p);
605 }
606 ///buf.printf("%zu%s", id.length, id);
607 buf.printf("%d%s", id.length, id);
608 id = buf.toChars();
609 buf.data = null;
610 //printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
611 return id;
612 }
613
614 bool needThis() // need a 'this' pointer?
615 {
616 return false;
617 }
618
619 PROT prot()
620 {
621 assert(false);
622 }
623
624 Dsymbol syntaxCopy(Dsymbol s) // copy only syntax trees
625 {
626 assert(false);
627 }
628
629 /**************************************
630 * Determine if this symbol is only one.
631 * Returns:
632 * false, *ps = null: There are 2 or more symbols
633 * true, *ps = null: There are zero symbols
634 * true, *ps = symbol: The one and only one symbol
635 */
636 bool oneMember(Dsymbol* ps)
637 {
638 //printf("Dsymbol::oneMember()\n");
639 *ps = this;
640 return true;
641 }
642
643 /*****************************************
644 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
645 */
646 static bool oneMembers(Array members, Dsymbol* ps)
647 {
648 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
649 Dsymbol s = null;
650
651 if (members)
652 {
653 for (int i = 0; i < members.dim; i++)
654 {
655 Dsymbol sx = cast(Dsymbol)members.data[i];
656
657 bool x = sx.oneMember(ps);
658 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
659 if (!x)
660 {
661 //printf("\tfalse 1\n");
662 assert(*ps is null);
663 return false;
664 }
665 if (*ps)
666 {
667 if (s) // more than one symbol
668 {
669 *ps = null;
670 //printf("\tfalse 2\n");
671 return false;
672 }
673 s = *ps;
674 }
675 }
676 }
677
678 *ps = s; // s is the one symbol, null if none
679 //printf("\ttrue\n");
680 return true;
681 }
682
683 /*****************************************
684 * Is Dsymbol a variable that contains pointers?
685 */
686 bool hasPointers()
687 {
688 //printf("Dsymbol::hasPointers() %s\n", toChars());
689 return 0;
690 }
691
692 void addLocalClass(ClassDeclarations) { }
693 void checkCtorConstInit() { }
694
695 void addComment(ubyte* comment)
696 {
697 //if (comment)
698 //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
699
700 if (this.comment is null) {
701 this.comment = comment;
702 } else {
703 static if (true) {
704 if (comment !is null && strcmp(cast(char*)comment, cast(char*)this.comment) != 0)
705 { // Concatenate the two
706 this.comment = Lexer.combineComments(this.comment, comment);
707 }
708 }
709 }
710 }
711
712 void emitComment(Scope sc)
713 {
714 assert(false);
715 }
716
717 void emitDitto(Scope sc)
718 {
719 assert(false);
720 }
721
722 // Backend
723
724 Symbol* toSymbol() // to backend symbol
725 {
726 assert(false);
727 }
728
729 void toObjFile(int multiobj) // compile to .obj file
730 {
731 //printf("Dsymbol::toObjFile('%s')\n", toChars());
732 // ignore
733 }
734
735 int cvMember(ubyte* p) // emit cv debug info for member
736 {
737 assert(false);
738 }
739
740 /*********************************
741 * Generate import symbol from symbol.
742 */
743 Symbol* toImport() // to backend import symbol
744 {
745 if (!isym)
746 {
747 if (!csym)
748 csym = toSymbol();
749 isym = toImport(csym);
750 }
751
752 return isym;
753 }
754
755 static Symbol* toImport(Symbol* sym) // to backend import symbol
756 {
757 char* id;
758 char* n;
759 Symbol* s;
760 type* t;
761
762 //printf("Dsymbol::toImport('%s')\n", sym->Sident);
763 n = sym.Sident.ptr;
764 id = cast(char*) alloca(6 + strlen(n) + 1 + (type_paramsize_i(sym.Stype)).sizeof*3 + 1);
765 if (sym.Stype.Tmangle == mTYman_std && tyfunc(sym.Stype.Tty))
766 {
767 sprintf(id, "_imp__%s@%lu", n, type_paramsize_i(sym.Stype));
768 }
769 else if (sym.Stype.Tmangle == mTYman_d)
770 sprintf(id,"_imp_%s",n);
771 else
772 sprintf(id,"_imp__%s",n);
773 t = type_alloc(TYnptr | mTYconst);
774 t.Tnext = sym.Stype;
775 t.Tnext.Tcount++;
776 t.Tmangle = mTYman_c;
777 t.Tcount++;
778 s = symbol_calloc(id);
779 s.Stype = t;
780 s.Sclass = SCextern;
781 s.Sfl = FLextern;
782 slist_add(s);
783
784 return s;
785 }
786
787 Symbol* toSymbolX(string prefix, int sclass, TYPE* t, string suffix) // helper
788 {
789 Symbol* s;
790 char* id;
791 string n;
792 size_t nlen;
793
794 //writef("Dsymbol::toSymbolX('%s', '%s')\n", prefix, this.classinfo.name);
795 n = mangle();
796 assert(n.length != 0);
797
798 nlen = n.length;
799 static if (false) {
800 if (nlen > 2 && n[0] == '_' && n[1] == 'D')
801 {
802 nlen -= 2;
803 n += 2;
804 }
805 }
806 id = cast(char*) alloca(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1);
807 sprintf(id, "_D%.*s%lu%.*s%.*s", n, prefix.length, prefix, suffix);
808
809 static if (false) {
810 if (global.params.isWindows && (type_mangle(t) == mTYman.mTYman_c || type_mangle(t) == mTYman.mTYman_std))
811 id++; // Windows C mangling will put the '_' back in
812 }
813 s = symbol_name(id, sclass, t);
814
815 //printf("-Dsymbol::toSymbolX() %s\n", id);
816 return s;
817 }
818
819 // Eliminate need for dynamic_cast
820 Package isPackage() { return null; }
821 Module isModule() { return null; }
822 EnumMember isEnumMember() { return null; }
823 TemplateDeclaration isTemplateDeclaration() { return null; }
824 TemplateInstance isTemplateInstance() { return null; }
825 TemplateMixin isTemplateMixin() { return null; }
826 Declaration isDeclaration() { return null; }
827 ThisDeclaration isThisDeclaration() { return null; }
828 TupleDeclaration isTupleDeclaration() { return null; }
829 TypedefDeclaration isTypedefDeclaration() { return null; }
830 AliasDeclaration isAliasDeclaration() { return null; }
831 AggregateDeclaration isAggregateDeclaration() { return null; }
832 FuncDeclaration isFuncDeclaration() { return null; }
833 FuncAliasDeclaration isFuncAliasDeclaration() { return null; }
834 FuncLiteralDeclaration isFuncLiteralDeclaration() { return null; }
835 CtorDeclaration isCtorDeclaration() { return null; }
836 PostBlitDeclaration isPostBlitDeclaration() { return null; }
837 DtorDeclaration isDtorDeclaration() { return null; }
838 StaticCtorDeclaration isStaticCtorDeclaration() { return null; }
839 StaticDtorDeclaration isStaticDtorDeclaration() { return null; }
840 InvariantDeclaration isInvariantDeclaration() { return null; }
841 UnitTestDeclaration isUnitTestDeclaration() { return null; }
842 NewDeclaration isNewDeclaration() { return null; }
843 VarDeclaration isVarDeclaration() { return null; }
844 ClassDeclaration isClassDeclaration() { return null; }
845 StructDeclaration isStructDeclaration() { return null; }
846 UnionDeclaration isUnionDeclaration() { return null; }
847 InterfaceDeclaration isInterfaceDeclaration() { return null; }
848 ScopeDsymbol isScopeDsymbol() { return null; }
849 WithScopeSymbol isWithScopeSymbol() { return null; }
850 ArrayScopeSymbol isArrayScopeSymbol() { return null; }
851 Import isImport() { return null; }
852 EnumDeclaration isEnumDeclaration() { return null; }
853 version (_DH) {
854 DeleteDeclaration isDeleteDeclaration() { return null; }
855 }
856 SymbolDeclaration isSymbolDeclaration() { return null; }
857 AttribDeclaration isAttribDeclaration() { return null; }
858 OverloadSet isOverloadSet() { return null; }
859 version (TARGET_NET) {
860 PragmaScope isPragmaScope() { return null; }
861 }
862 }