1 module source.name; 2 3 import source.context; 4 5 struct Name { 6 private: 7 uint id; 8 9 this(uint id) { 10 this.id = id; 11 } 12 13 public: 14 @property 15 bool isEmpty() const { 16 return this == BuiltinName!""; 17 } 18 19 @property 20 bool isReserved() const { 21 return id < (Names.length - Prefill.length); 22 } 23 24 @property 25 bool isDefined() const { 26 return id != 0; 27 } 28 29 auto getFullName(const Context c) const { 30 return FullName(this, c); 31 } 32 33 string toString(const Context c) const { 34 return getFullName(c).toString(); 35 } 36 37 immutable(char)* toStringz(const Context c) const { 38 return getFullName(c).toStringz(); 39 } 40 } 41 42 template BuiltinName(string name) { 43 private enum id = Lookups.get(name, uint.max); 44 static assert(id < uint.max, name ~ " is not a builtin name."); 45 enum BuiltinName = Name(id); 46 } 47 48 struct FullName { 49 private: 50 Name _name; 51 const Context context; 52 53 this(Name name, const Context context) { 54 this._name = name; 55 this.context = context; 56 } 57 58 @property 59 ref nameManager() const { 60 return context.nameManager; 61 } 62 63 public: 64 alias name this; 65 @property name() const { 66 return _name; 67 } 68 69 string toString() const { 70 return nameManager.names[id]; 71 } 72 73 immutable(char)* toStringz() const { 74 auto s = toString(); 75 assert(s.ptr[s.length] == '\0', "Expected a zero terminated string"); 76 return s.ptr; 77 } 78 } 79 80 struct NameManager { 81 private: 82 string[] names; 83 uint[string] lookups; 84 85 // Make it non copyable. 86 @disable this(this); 87 88 package: 89 static get() { 90 return NameManager(Names, Lookups); 91 } 92 93 public: 94 auto getName(const(char)[] str) { 95 if (auto id = str in lookups) { 96 return Name(*id); 97 } 98 99 // As we are cloning, make sure it is 0 terminated as to pass to C. 100 import std.string; 101 auto s = str.toStringz()[0 .. str.length]; 102 103 // Make sure we do not keep around slice of potentially large input. 104 scope(exit) assert(str.ptr !is s.ptr, s); 105 106 auto id = lookups[s] = cast(uint) names.length; 107 names ~= s; 108 109 return Name(id); 110 } 111 112 void dump() { 113 foreach(s; names) { 114 import std.stdio; 115 writeln(lookups[s], "\t=> ", s); 116 } 117 } 118 } 119 120 private: 121 122 enum Reserved = ["__ctor", "__dtor", "__postblit", "__vtbl"]; 123 124 enum Prefill = [ 125 // Linkages 126 "C", "D", "C++", "Windows", "System", "Pascal", "Java", 127 // Version 128 "SDC", "D_LP64", "X86_64", "linux", "OSX", "FreeBSD", "Posix", 129 // Generated 130 "init", "length", "max", "min", "ptr", "sizeof", "alignof", 131 // Scope 132 "exit", "success", "failure", 133 // Main 134 "main", "_Dmain", 135 // Defined in object 136 "object", "size_t", "ptrdiff_t", "string", 137 "Object", 138 "TypeInfo", "ClassInfo", 139 "Throwable", "Exception", "Error", 140 // Attribute 141 "property", "safe", "trusted", "system", "nogc", 142 // Runtime 143 "__sd_assert_fail", 144 "__sd_assert_fail_msg", 145 "__sd_class_downcast", 146 "__sd_eh_throw", 147 "__sd_eh_personality", 148 "__sd_array_concat", 149 "__sd_array_outofbounds", 150 "__sd_gc_tl_malloc", 151 // Generated symbols 152 "__ctx", 153 "__dg", 154 "__lambda", 155 "__unittest", 156 // Used to make IR more comprehensible. 157 "entry", "then", "unwind", "resume", "destroy", "cleanup", 158 "assert.fail", "assert.success", "scope.entry", 159 "endif", "endswitch", "endcatch", "unreachable", 160 "loop.continue", "loop.test", "loop.body", "loop.exit", 161 // Intrinsics 162 "3sdc10intrinsics", "expect", "cas", "casWeak", "popCount", 163 "countLeadingZeros", "countTrailingZeros", "bswap", 164 ]; 165 166 auto getNames() { 167 import source.dlexer; 168 169 auto identifiers = [""]; 170 foreach(k, _; getOperatorsMap()) { 171 identifiers ~= k; 172 } 173 174 foreach(k, _; getKeywordsMap()) { 175 identifiers ~= k; 176 } 177 178 return identifiers ~ Reserved ~ Prefill; 179 } 180 181 enum Names = getNames(); 182 183 static assert(Names[0] == ""); 184 185 auto getLookups() { 186 // XXX: DMD zero terminate here, but I'd like to not rely on it :/ 187 uint[string] lookups; 188 foreach(i, id; Names) { 189 lookups[id] = cast(uint) i; 190 } 191 192 return lookups; 193 } 194 195 enum Lookups = getLookups();