1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity average)
4 module dil.semantic.Symbols;
5 
6 import dil.ast.Expression;
7 import dil.semantic.Symbol,
8        dil.semantic.SymbolTable,
9        dil.semantic.Types;
10 import dil.lexer.IdTable;
11 import dil.Enums,
12        dil.String;
13 import common;
14 
15 /// Declaration symbol.
16 abstract class DeclarationSymbol : Symbol
17 {
18   Protection prot; /// The protection.
19   StorageClass stcs; /// The storage classes.
20   LinkageType linkage; /// The linkage type.
21 
22   this(SYM sid, Identifier* name, SLoc loc)
23   {
24     super(sid, name, loc);
25   }
26 
27   override cstring toMangle()
28   {
29     return toMangle(this, linkage);
30   }
31 
32   static cstring toMangle(Symbol s, LinkageType linkage)
33   {
34     cstring toCppMangle(Symbol s){ /+TODO+/ return ""; }
35 
36     cstring m;
37     if (!s.parent || s.parent.isModule())
38       switch (linkage)
39       {
40       case LinkageType.D:
41         break;
42       case LinkageType.C,
43            LinkageType.Windows,
44            LinkageType.Pascal:
45         m = s.name.str;
46         break;
47       case LinkageType.Cpp:
48         version(D2)version(Windows)
49         goto case LinkageType.C; // D2 on Windows
50 
51         m = toCppMangle(s);
52         break;
53       case LinkageType.None:
54         // TODO: issue forward declaration error?
55         goto case LinkageType.C;
56       default: assert(0);
57       }
58     if (!m)
59       m = "_D" ~ toMangle2(s);
60     return m;
61   }
62 
63   static cstring toMangle2(Symbol s)
64   { // Recursive function.
65     cstring m;
66     Symbol s2 = s;
67     for (; s2; s2 = s2.parent)
68       if (s2.name is Ident.Empty)
69         m = "0" ~ m;
70       else if (s2 !is s && s2.isFunction())
71       {
72         m = toMangle2(s2) ~ m; // Recursive call.
73         break;
74       }
75       else
76       {
77         auto id = s2.name.str;
78         m = itoa(id.length) ~ id ~ m;
79       }
80 
81     auto fs = s.isFunction() ? s.to!(FunctionSymbol) : null;
82 
83     if (fs /+&& (fs.needThis() || fs.isNested())+/) // FIXME:
84       m ~= 'M'; // Mangle char for member/nested functions.
85     if (auto t = cast(Type)s.getType())
86       if (t.mangled)
87         m ~= t.mangled;
88 
89     return m;
90   }
91 }
92 
93 /// A symbol that has its own scope with a symbol table.
94 class ScopeSymbol : Symbol
95 {
96   SymbolTable symbolTable; /// The symbol table.
97   Symbol[] members; /// The member symbols (in lexical order.)
98 
99   /// Constructs a ScopeSymbol object.
100   this(SYM sid, Identifier* name, SLoc loc)
101   {
102     super(sid, name, loc);
103   }
104 
105   /// Constructs a ScopeSymbol object with the SYM.Scope ID.
106   this(Identifier* name = Ident.Empty, SLoc loc = SLoc.init)
107   {
108     super(SYM.Scope, name, loc);
109   }
110 
111   /// Looks up name in the table.
112   Symbol lookup(Identifier* name)
113   {
114     return symbolTable.lookup(name);
115   }
116 
117   /// Looks up a symbol in the table using its string hash.
118   Symbol lookup(hash_t hash)
119   {
120     return symbolTable.lookup(hash);
121   }
122 
123   /// Inserts a symbol into the table.
124   void insert(Symbol s, Identifier* name)
125   {
126     symbolTable.insert(s, name);
127     members ~= s;
128   }
129 }
130 
131 /// A module symbol.
132 class ModuleSymbol : ScopeSymbol
133 {
134   ModuleInfoSymbol varminfo; /// The ModuleInfo for this module.
135 
136   this(Identifier* name = null, SLoc loc = SLoc.init)
137   {
138     super(SYM.Module, name, loc);
139   }
140 }
141 
142 /// A package symbol.
143 class PackageSymbol : ScopeSymbol
144 {
145   this(Identifier* name = null, SLoc loc = SLoc.init)
146   {
147     super(SYM.Package, name, loc);
148   }
149 }
150 
151 /// Aggregates have function and field members.
152 abstract class AggregateSymbol : ScopeSymbol
153 {
154   Type type;
155   FunctionSymbol[] funcs;
156   VariableSymbol[] fields;
157   AliasSymbol[] aliases; /// AliasThis symbols.
158 
159   this(SYM sid, Identifier* name, SLoc loc)
160   {
161     super(sid, name, loc);
162   }
163 
164 override:
165   void insert(Symbol s, Identifier* ident)
166   {
167     if (s.isVariable())
168       // Append variable to fields.
169       fields ~= s.to!(VariableSymbol);
170     else if (s.isFunction())
171       // Append function to funcs.
172       funcs ~= s.to!(FunctionSymbol);
173     super.insert(s, ident);
174   }
175 
176   Type getType()
177   {
178     return type;
179   }
180 
181   cstring toMangle()
182   {
183     return Symbol.toMangle(this);
184   }
185 }
186 
187 /// A class symbol.
188 class ClassSymbol : AggregateSymbol
189 {
190   ClassSymbol base; /// The inherited base class.
191   InterfaceSymbol[] ifaces; /// The inherited interfaces.
192 
193   TypeInfoSymbol vartinfo; /// The TypeInfo of this class.
194 
195   this(Identifier* name, SLoc loc)
196   {
197     super(SYM.Class, name, loc);
198     this.type = new TypeClass(this);
199   }
200 }
201 
202 /// Special classes, e.g.: Object, ClassInfo, ModuleInfo etc.
203 class SpecialClassSymbol : ClassSymbol
204 {
205   this(Identifier* name, SLoc loc)
206   {
207     super(name, loc);
208   }
209 
210   /// Handle mangling differently for special classes.
211   override cstring toMangle()
212   {
213     auto parent_save = parent;
214     parent = null;
215     auto m = super.toMangle();
216     parent = parent_save;
217     return m;
218   }
219 }
220 
221 /// An interface symbol.
222 class InterfaceSymbol : ClassSymbol
223 {
224   this(Identifier* name, SLoc loc)
225   {
226     super(name, loc);
227     this.sid = SYM.Interface;
228     this.type = new TypeClass(this);
229   }
230 }
231 
232 /// A struct symbol.
233 class StructSymbol : AggregateSymbol
234 {
235   bool isAnonymous;
236   this(Identifier* name, SLoc loc)
237   {
238     super(SYM.Struct, name, loc);
239     this.type = new TypeStruct(this);
240     this.isAnonymous = name is null;
241   }
242 }
243 
244 /// A union symbol.
245 class UnionSymbol : StructSymbol
246 {
247   bool isAnonymous;
248   this(Identifier* name, SLoc loc)
249   {
250     super(name, loc);
251     this.sid = SYM.Union;
252     this.type = new TypeStruct(this);
253     this.isAnonymous = name is null;
254   }
255 }
256 
257 /// An enum symbol.
258 class EnumSymbol : ScopeSymbol
259 {
260   TypeEnum type;
261   bool isAnonymous;
262   this(Identifier* name, SLoc loc)
263   {
264     super(SYM.Enum, name, loc);
265     this.type = new TypeEnum(this);
266     this.isAnonymous = name is null;
267   }
268 
269   void setType(TypeEnum type)
270   {
271     this.type = type;
272   }
273 
274   override Type getType()
275   {
276     return type;
277   }
278 }
279 
280 /// A function symbol.
281 class FunctionSymbol : ScopeSymbol
282 {
283   Protection prot; /// The protection.
284   StorageClass stcs; /// The storage classes.
285   LinkageType linkage; /// The linkage type.
286   TypeFunction type; /// The type of this function.
287   ParametersSymbol params; /// The parameters of this function.
288 
289   this(Identifier* name, SLoc loc)
290   {
291     super(SYM.Function, name, loc);
292   }
293 
294   override Type getType()
295   {
296     return type;
297   }
298 
299   cstring toText()
300   { // := ReturnType Name ParameterList
301     return type.retType.toString() ~ name.str ~ params.toString();
302   }
303 
304   override cstring toMangle()
305   {
306     if (isDMain())
307       return "_Dmain";
308     if (isWinMain() || isDllMain())
309       return name.str;
310     return DeclarationSymbol.toMangle(this, linkage);
311   }
312 
313   bool isDMain()
314   {
315     return name is Ident.main && linkage != LinkageType.C && !isMember();
316   }
317 
318   bool isWinMain()
319   {
320     return name is Ident.WinMain && linkage != LinkageType.C && !isMember();
321   }
322 
323   bool isDllMain()
324   {
325     return name is Ident.DllMain && linkage != LinkageType.C && !isMember();
326   }
327 
328   bool isMember()
329   { // TODO
330     return false;
331   }
332 }
333 
334 /// The parameter symbol.
335 class ParameterSymbol : Symbol
336 {
337   StorageClass stcs; /// Storage classes.
338   VariadicStyle variadic; /// Variadic style.
339   Type ptype; /// The parameter's type.
340   Expression defValue; /// The default initialization value.
341 
342   TypeParameter type; /// Type of this symbol.
343 
344   this(Type ptype, Identifier* name,
345     StorageClass stcs, VariadicStyle variadic, SLoc loc)
346   {
347     super(SYM.Parameter, name, loc);
348     this.stcs = stcs;
349     this.variadic = variadic;
350     this.ptype = ptype;
351     this.type = new TypeParameter(ptype, stcs, variadic);
352   }
353 
354   cstring toText()
355   { // := StorageClasses? ParamType? ParamName? (" = " DefaultValue)? "..."?
356     char[] s;
357     foreach (stc; EnumString.all(stcs))
358       s ~= stc ~ " ";
359     if (type)
360       s ~= type.toString();
361     if (name !is Ident.Empty)
362       s ~= name.str;
363     if (defValue)
364       s ~= " = " ~ defValue.toText();
365     else if (variadic)
366       s ~= "...";
367     assert(s.length, "empty parameter?");
368     return s;
369   }
370 
371   override cstring toMangle()
372   {
373     return type.toMangle();
374   }
375 }
376 
377 /// A list of ParameterSymbol objects.
378 class ParametersSymbol : Symbol
379 {
380   ParameterSymbol[] params; /// The parameters.
381   TypeParameters type; /// Type of this symbol.
382 
383   this(ParameterSymbol[] params, SLoc loc = SLoc.init)
384   {
385     super(SYM.Parameters, Ident.Empty, loc);
386     this.params = params;
387     auto ptypes = new TypeParameter[params.length];
388     foreach (i, p; params)
389       ptypes[i] = p.type;
390     this.type = new TypeParameters(ptypes);
391   }
392 
393   /// Returns the variadic style of the last parameter.
394   VariadicStyle getVariadic()
395   {
396     return type.getVariadic();
397   }
398 
399   cstring toText()
400   { // := "(" ParameterList ")"
401     char[] s;
402     s ~= "(";
403     foreach (i, p; params) {
404       if (i) s ~= ", "; // Append comma if more than one param.
405       s ~= p.toString();
406     }
407     s ~= ")";
408     return s;
409   }
410 
411   override cstring toMangle()
412   {
413     return type.toMangle();
414   }
415 }
416 
417 /// A variable symbol.
418 class VariableSymbol : Symbol
419 {
420   Protection prot; /// The protection.
421   StorageClass stcs; /// The storage classes.
422   LinkageType linkage; /// The linkage type.
423 
424   Type type; /// The type of this variable.
425   Expression value; /// The value of this variable.
426 
427   this(Identifier* name,
428        Protection prot, StorageClass stcs, LinkageType linkage,
429        SLoc loc)
430   {
431     super(SYM.Variable, name, loc);
432 
433     this.prot = prot;
434     this.stcs = stcs;
435     this.linkage = linkage;
436   }
437 
438   this(Identifier* name, SLoc loc)
439   {
440     this(name, Protection.None, StorageClass.None, LinkageType.None, loc);
441   }
442 
443   override cstring toMangle()
444   {
445     return DeclarationSymbol.toMangle(this, linkage);
446   }
447 }
448 
449 /// An enum member symbol.
450 class EnumMemberSymbol : VariableSymbol
451 {
452   this(Identifier* name,
453        Protection prot, StorageClass stcs, LinkageType linkage,
454        SLoc loc)
455   {
456     super(name, prot, stcs, linkage, loc);
457     this.sid = SYM.EnumMember;
458   }
459 }
460 
461 /// A this-pointer symbol for member functions (or frame pointers.)
462 class ThisSymbol : VariableSymbol
463 {
464   this(Type type, SLoc loc)
465   {
466     super(Keyword.This, loc);
467     this.type = type;
468   }
469 }
470 
471 /// A ClassInfo variable symbol.
472 class ClassInfoSymbol : VariableSymbol
473 {
474   ClassSymbol clas; /// The class to provide info for.
475   /// Constructs a ClassInfoSymbol object.
476   ///
477   /// Params:
478   ///   clas = ClassInfo for this class.
479   ///   classClassInfo = The global ClassInfo class from object.d.
480   this(ClassSymbol clas, ClassSymbol classClassInfo)
481   {
482     super(clas.name, clas.loc);
483     this.type = classClassInfo.type;
484     this.clas = clas;
485     this.stcs = StorageClass.Static;
486   }
487 
488 //   Something toSomething() // TODO:
489 //   { return null; }
490 }
491 
492 /// A ModuleInfo variable symbol.
493 class ModuleInfoSymbol : VariableSymbol
494 {
495   ModuleSymbol modul; /// The module to provide info for.
496   /// Constructs a ModuleInfoSymbol object.
497   ///
498   /// Params:
499   ///   modul = ModuleInfo for this module.
500   ///   classModuleInfo = The global ModuleInfo class from object.d.
501   this(ModuleSymbol modul, ClassSymbol classModuleInfo)
502   {
503     super(modul.name, modul.loc);
504     this.type = classModuleInfo.type;
505     this.modul = modul;
506     this.stcs = StorageClass.Static;
507   }
508 
509 //   Something toSomething() // TODO:
510 //   { return null; }
511 }
512 
513 /// A TypeInfo variable symbol.
514 class TypeInfoSymbol : VariableSymbol
515 {
516   Type titype; /// The type to provide info for.
517   /// Constructs a TypeInfo object.
518   ///
519   /// The variable is of type TypeInfo and its name is mangled.
520   /// E.g.:
521   /// ---
522   /// TypeInfo _D10TypeInfo_a6__initZ; // For type "char".
523   /// ---
524   /// Params:
525   ///   titype = TypeInfo for this type.
526   ///   name  = The mangled name of this variable.
527   ///   classTypeInfo = The global TypeInfo class from object.d.
528   this(Type titype, Identifier* name, ClassSymbol classTypeInfo)
529   { // FIXME: provide the node of TypeInfo for now.
530     // titype has no node; should every Type get one?
531     super(name, classTypeInfo.loc);
532     this.type = classTypeInfo.type;
533     this.titype = titype;
534     this.stcs = StorageClass.Static;
535     this.prot = Protection.Public;
536     this.linkage = LinkageType.C;
537   }
538 
539 //   Something toSomething() // TODO:
540 //   {
541 //     switch (titype.tid)
542 //     {
543 //     case TYP.Char: break;
544 //     case TYP.Function: break;
545 //     // etc.
546 //     default:
547 //     }
548 //     return null;
549 //   }
550 }
551 
552 // TODO: let dil.semantic.Types.Type inherit from Symbol?
553 /// A type symbol.
554 class TypeSymbol : Symbol
555 {
556   Type type; /// Wrapper around this type.
557 
558   this(Type type)
559   {
560     super(SYM.Type, null, SLoc.init);
561     this.type = type;
562   }
563 }
564 
565 /// A tuple symbol.
566 class TupleSymbol : Symbol
567 {
568   TypeTuple type; /// The type of this tuple.
569   Symbol[] items; /// The items in this tuple.
570 
571   this(Symbol[] items, Identifier* name, SLoc loc)
572   {
573     super(SYM.Tuple, name, loc);
574   }
575 
576   /// Returns the type only when all elements are types, otherwise null.
577   override Type getType()
578   {
579     if (!type && hasOnlyTypes())
580       type = makeTypeTuple();
581     return type;
582   }
583 
584   /// Returns true if all elements are types (also if the tuple is empty.)
585   bool hasOnlyTypes()
586   {
587     foreach (item; items)
588       if (!item.isType())
589         return false;
590     return true;
591   }
592 
593   /// Creates a TypeTuple instance from the items of this tuple.
594   TypeTuple makeTypeTuple()
595   in { assert(hasOnlyTypes()); }
596   body
597   {
598     auto types = new Type[items.length]; // Allocate exact amount of types.
599     foreach (i, item; items)
600       types[i] = item.to!(TypeSymbol).type;
601     return new TypeTuple(types);
602   }
603 
604   override cstring toMangle()
605   {
606     return DeclarationSymbol.toMangle(this, LinkageType.D /+FIXME+/);
607   }
608 }
609 
610 // class ExprTupleSymbol : TupleSymbol
611 // {
612 //   // TODO:
613 // }
614 
615 /// An alias symbol.
616 class AliasSymbol : Symbol
617 {
618   Type aliasType;
619   Symbol aliasSym;
620 
621   this(Identifier* name, SLoc loc)
622   {
623     super(SYM.Alias, name, loc);
624   }
625 
626   override cstring toMangle()
627   {
628     return DeclarationSymbol.toMangle(this, LinkageType.D /+FIXME+/);
629   }
630 }
631 
632 /// A typedef symbol.
633 class TypedefSymbol : Symbol
634 {
635   this(Identifier* name, SLoc loc)
636   {
637     super(SYM.Typedef, name, loc);
638   }
639 
640   override cstring toMangle()
641   {
642     return Symbol.toMangle(this);
643   }
644 }
645 
646 /// A template symbol.
647 class TemplateSymbol : ScopeSymbol
648 {
649   AliasSymbol[] aliases; /// AliasThis symbols.
650   this(Identifier* name, SLoc loc)
651   {
652     super(SYM.Template, name, loc);
653   }
654 }
655 
656 /// A template instance symbol.
657 class TemplInstanceSymbol : ScopeSymbol
658 {
659   // TemplArgSymbol[] tiArgs;
660   TemplateSymbol tplSymbol;
661   this(Identifier* name, SLoc loc)
662   {
663     super(SYM.TemplateInstance, name, loc);
664   }
665 
666   override cstring toMangle()
667   { // := ParentMangle? NameMangleLength NameMangle
668     if (name is Ident.Empty)
669     {} // TODO: ?
670     cstring pm; // Parent mangle.
671     if (!tplSymbol)
672     {} // Error: undefined
673     else if (tplSymbol.parent)
674     {
675       pm = tplSymbol.parent.toMangle();
676       if (pm.length >= 2 && pm[0..2] == "_D")
677         pm = pm[2..$]; // Skip the prefix.
678     }
679     cstring id = name.str;
680     return pm ~ itoa(id.length) ~ id;
681   }
682 }
683 
684 /// A template mixin symbol.
685 class TemplMixinSymbol : TemplInstanceSymbol
686 {
687   this(Identifier* name, SLoc loc)
688   {
689     super(name, loc);
690     this.sid = SYM.TemplateMixin;
691   }
692 
693   override cstring toMangle()
694   {
695     return Symbol.toMangle(this);
696   }
697 }
698 
699 /// A list of symbols that share the same identifier.
700 ///
701 /// These can be functions, templates and aggregates with template parameter lists.
702 class OverloadSet : Symbol
703 {
704   Symbol[] symbols;
705 
706   this(Identifier* name, SLoc loc)
707   {
708     super(SYM.OverloadSet, name, loc);
709   }
710 
711   void add(Symbol s)
712   {
713     symbols ~= s;
714   }
715 }