1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.semantic.Symbol; 5 6 import dil.ast.Node; 7 import dil.lexer.Identifier, 8 dil.lexer.IdTable; 9 import dil.String : itoa; 10 import common; 11 12 /// Enumeration of Symbol IDs. 13 enum SYM 14 { 15 Module, 16 Package, 17 Class, 18 Interface, 19 Struct, 20 Union, 21 Enum, 22 EnumMember, 23 Template, 24 TemplateInstance, 25 TemplateMixin, 26 Variable, 27 Function, 28 Alias, 29 Typedef, 30 OverloadSet, 31 Scope, 32 Parameter, 33 Parameters, 34 Tuple, 35 Type, 36 } 37 38 /// Info on a symbol's source code location. 39 struct SLoc 40 { 41 Token* t; /// Gives a precise location. Usually the name of a symbol. 42 Node n; /// For Ddoc comments other possibly other info. 43 } 44 45 /// A symbol represents an object with semantic code information. 46 class Symbol 47 { /// Enumeration of symbol statuses. 48 enum Status : ushort 49 { 50 Declared, /// The symbol has been declared. 51 Completing, /// The symbol is being processed. 52 Complete /// The symbol is complete. 53 } 54 55 SYM sid; /// The ID of this symbol. 56 Status status; /// The semantic status of this symbol. 57 Symbol parent; /// The parent this symbol belongs to. 58 /// The name of this symbol. 59 /// If the symbol is nameless Ident.Empty is assigned to it. 60 Identifier* name; 61 SLoc loc; /// For locating a symbol. 62 63 /// Constructs a Symbol object. 64 /// Params: 65 /// sid = The symbol's ID. 66 /// name = The symbol's name. 67 /// node = The symbol's node. 68 this(SYM sid, Identifier* name, SLoc loc) 69 { 70 this.sid = sid; 71 this.name = name ? name : Ident.Empty; 72 this.loc = loc; 73 } 74 75 /// Change the status to Status.Completing. 76 void setCompleting() 77 { status = Status.Completing; } 78 79 /// Change the status to Status.Complete. 80 void setComplete() 81 { status = Status.Complete; } 82 83 /// Returns true if the symbol is being completed. 84 bool isCompleting() 85 { return status == Status.Completing; } 86 87 /// Returns true if the symbols is complete. 88 bool isComplete() 89 { return status == Status.Complete; } 90 91 /// A template for building isXYZ() methods. 92 private static string is_()(string kind) 93 { 94 return `bool is`~kind~`(){ return sid == SYM.`~kind~`; }`; 95 } 96 97 mixin(is_("Module")); 98 mixin(is_("Package")); 99 mixin(is_("Class")); 100 mixin(is_("Interface")); 101 mixin(is_("Struct")); 102 mixin(is_("Union")); 103 mixin(is_("Enum")); 104 mixin(is_("EnumMember")); 105 mixin(is_("Template")); 106 mixin(is_("TemplateInstance")); 107 mixin(is_("TemplateMixin")); 108 mixin(is_("Variable")); 109 mixin(is_("Function")); 110 mixin(is_("Alias")); 111 mixin(is_("Typedef")); 112 mixin(is_("OverloadSet")); 113 mixin(is_("Scope")); 114 mixin(is_("Parameter")); 115 mixin(is_("Parameters")); 116 mixin(is_("Tuple")); 117 mixin(is_("Type")); 118 119 /// Casts the symbol to Class. 120 Class to(Class)() 121 { 122 assert(mixin(`this.sid == mixin("SYM." ~ 123 { const N = Class.stringof; // Slice off "Symbol" from the name. 124 return N[$-6..$] == "Symbol" ? N[0..$-6] : N; }())`)); 125 return cast(Class)cast(void*)this; 126 } 127 128 /// Returns: the fully qualified name of this symbol. 129 /// E.g.: dil.semantic.Symbol.Symbol.getFQN 130 cstring getFQN() 131 { 132 cstring fqn = name.str; 133 if (parent) // Iter upwards until the root package is reached. 134 for (auto s = parent; s.parent; s = s.parent) 135 fqn = s.name.str ~ '.' ~ fqn; 136 return fqn; 137 } 138 139 /// Returns the module this symbol belongs to or null if orphaned. 140 Symbol getModule() 141 { 142 auto s = this; 143 for (; s && !s.isModule(); s = s.parent) 144 {} 145 return s; 146 } 147 148 /// Returns the type of this symbol or null if inexistent. 149 /// The return type is Object to avoid circular imports. 150 Object getType() 151 { 152 return null; 153 } 154 155 /// Returns the mangled name of this symbol. 156 cstring toMangle() 157 { // := ParentMangle? NameMangleLength NameMangle 158 if (name is Ident.Empty) 159 {} // TODO: ? 160 cstring pm; // Parent mangle. 161 if (parent) 162 { 163 pm = parent.toMangle(); 164 if (pm.length >= 2 && pm[0..2] == "_D") 165 pm = pm[2..$]; // Skip the prefix. 166 } 167 cstring id = name.str; 168 return pm ~ itoa(id.length) ~ id; 169 } 170 171 static cstring toMangle(Symbol s) 172 { 173 return s.toMangle(); 174 } 175 176 cstring toCppMangle() 177 { // TODO: 178 return null; 179 } 180 181 /// Returns the string representation of this symbol. 182 override string toString() 183 { 184 return name.str; 185 } 186 }