1 /** 2 * Copyright: Enalye 3 * License: Zlib 4 * Authors: Enalye 5 */ 6 module grimoire.compiler.mangle; 7 8 import std.conv : to; 9 import std..string : indexOf; 10 import grimoire.compiler.type; 11 12 /** 13 Mangle a signature of types. 14 15 Example: 16 --- 17 [int, string, func(bool, float)] 18 --- 19 Will be mangled as `$i$s$f($b$f)()` 20 21 The return type is not conserved in the mangled form as its not part of its signature. 22 But function. passed as parameters have theirs. 23 */ 24 string grMangleSignature(GrType[] signature) { 25 string mangledName; 26 foreach (type; signature) { 27 mangledName ~= "$"; 28 final switch (type.baseType) with (GrBaseType) { 29 case void_: 30 mangledName ~= "*"; 31 break; 32 case null_: 33 mangledName ~= "0"; 34 break; 35 case int_: 36 mangledName ~= "i"; 37 break; 38 case float_: 39 mangledName ~= "r"; 40 break; 41 case bool_: 42 mangledName ~= "b"; 43 break; 44 case string_: 45 mangledName ~= "s"; 46 break; 47 case array_: 48 mangledName ~= "n(" ~ type.mangledType ~ ")"; 49 break; 50 case class_: 51 mangledName ~= "p(" ~ type.mangledType ~ ")"; 52 break; 53 case enum_: 54 mangledName ~= "e(" ~ type.mangledType ~ ")"; 55 break; 56 case foreign: 57 mangledName ~= "u(" ~ type.mangledType ~ ")"; 58 break; 59 case function_: 60 mangledName ~= "f(" ~ type.mangledType ~ ")(" ~ type.mangledReturnType ~ ")"; 61 break; 62 case task: 63 mangledName ~= "t(" ~ type.mangledType ~ ")"; 64 break; 65 case chan: 66 mangledName ~= "c(" ~ type.mangledType ~ ")"; 67 break; 68 case reference: 69 mangledName ~= "h(" ~ type.mangledType ~ ")"; 70 break; 71 case internalTuple: 72 throw new Exception("Trying to mangle a tuple. Tuples should not exist here."); 73 } 74 } 75 return mangledName; 76 } 77 78 /// Reverse the mangling operation for a signature. 79 GrType[] grUnmangleSignature(string mangledSignature) { 80 GrType[] unmangledSignature; 81 82 int i; 83 while (i < mangledSignature.length) { 84 //Type separator 85 if (mangledSignature[i] != '$') { 86 throw new Exception("Invalid unmangle signature mangling format, missing $"); 87 } 88 i++; 89 90 //Value 91 GrType currentType = GrBaseType.void_; 92 switch (mangledSignature[i]) { 93 case '*': 94 currentType.baseType = GrBaseType.void_; 95 break; 96 case 'i': 97 currentType.baseType = GrBaseType.int_; 98 break; 99 case 'r': 100 currentType.baseType = GrBaseType.float_; 101 break; 102 case 'b': 103 currentType.baseType = GrBaseType.bool_; 104 break; 105 case 's': 106 currentType.baseType = GrBaseType.string_; 107 break; 108 case 'n': 109 i++; 110 currentType.baseType = GrBaseType.array_; 111 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 112 break; 113 case 'e': 114 currentType.baseType = GrBaseType.enum_; 115 string enumName; 116 if ((i + 2) >= mangledSignature.length) 117 throw new Exception("Invalid mangling format"); 118 i++; 119 if (mangledSignature[i] != '(') 120 throw new Exception("Invalid mangling format"); 121 i++; 122 while (mangledSignature[i] != ')') { 123 enumName ~= mangledSignature[i]; 124 i++; 125 if (i >= mangledSignature.length) 126 throw new Exception("Invalid mangling format"); 127 } 128 currentType.mangledType = enumName; 129 break; 130 case 'p': 131 currentType.baseType = GrBaseType.class_; 132 if ((i + 2) >= mangledSignature.length) 133 throw new Exception("Invalid mangling format"); 134 i++; 135 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 136 break; 137 case 'u': 138 currentType.baseType = GrBaseType.foreign; 139 if ((i + 2) >= mangledSignature.length) 140 throw new Exception("Invalid mangling format"); 141 i++; 142 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 143 break; 144 case 'f': 145 i++; 146 currentType.baseType = GrBaseType.function_; 147 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 148 i++; 149 currentType.mangledReturnType = grUnmangleBlock(mangledSignature, i); 150 break; 151 case 't': 152 i++; 153 currentType.baseType = GrBaseType.task; 154 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 155 break; 156 case 'c': 157 i++; 158 currentType.baseType = GrBaseType.chan; 159 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 160 break; 161 default: 162 break; 163 } 164 unmangledSignature ~= currentType; 165 i++; 166 } 167 return unmangledSignature; 168 } 169 170 /** 171 Can be used to mangle a named function or a templated type. 172 173 Example: 174 --- 175 func test(int i, string s, func(bool, float)) float {} 176 --- 177 Will be mangled as `test$i$s$f($b$f)()` 178 179 The return type is not conserved in the mangled form as its not part of its signature. 180 But function. passed as parameters have theirs. 181 */ 182 string grMangleComposite(string name, GrType[] signature) { 183 return name ~ grMangleSignature(signature); 184 } 185 186 /// Reverses the grMangleComposite operation. 187 /// Returns a struct containing the name and the signature. 188 auto grUnmangleComposite(string mangledSignature) { 189 struct UnmangleCompositeResult { 190 string name; 191 GrType[] signature; 192 } 193 194 UnmangleCompositeResult result; 195 size_t index = mangledSignature.indexOf('$'); 196 if (index == -1) { 197 result.name = mangledSignature; 198 return result; 199 } 200 result.name = mangledSignature[0 .. index]; 201 result.signature = grUnmangleSignature(mangledSignature[index .. $]); 202 return result; 203 } 204 205 /// Reverse the mangling operation for a function passed as a parameter. 206 string grUnmangleBlock(string mangledSignature, ref int i) { 207 string subString; 208 int blockCount = 1; 209 if (i >= mangledSignature.length || mangledSignature[i] != '(') 210 throw new Exception("Invalid subType mangling format, missing ("); 211 i++; 212 213 for (; i < mangledSignature.length; i++) { 214 switch (mangledSignature[i]) { 215 case '(': 216 blockCount++; 217 break; 218 case ')': 219 blockCount--; 220 if (blockCount == 0) { 221 return subString; 222 } 223 break; 224 default: 225 break; 226 } 227 subString ~= mangledSignature[i]; 228 } 229 throw new Exception("Invalid subType mangling format, missing )"); 230 } 231 232 /// Reverse the mangling operation for a single type. 233 GrType grUnmangle(string mangledSignature) { 234 GrType currentType = GrBaseType.void_; 235 236 int i; 237 if (i < mangledSignature.length) { 238 //Type separator 239 if (mangledSignature[i] != '$') 240 throw new Exception("Invalid unmangle mangling format, missing $"); 241 i++; 242 243 //Value 244 switch (mangledSignature[i]) { 245 case '*': 246 currentType.baseType = GrBaseType.void_; 247 break; 248 case 'i': 249 currentType.baseType = GrBaseType.int_; 250 break; 251 case 'r': 252 currentType.baseType = GrBaseType.float_; 253 break; 254 case 'b': 255 currentType.baseType = GrBaseType.bool_; 256 break; 257 case 's': 258 currentType.baseType = GrBaseType.string_; 259 break; 260 case 'n': 261 i++; 262 currentType.baseType = GrBaseType.array_; 263 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 264 i++; 265 break; 266 case 'e': 267 currentType.baseType = GrBaseType.enum_; 268 string enumName; 269 if ((i + 2) >= mangledSignature.length) 270 throw new Exception("Invalid unmangle mangling format in struct"); 271 i++; 272 if (mangledSignature[i] != '(') 273 throw new Exception("Invalid unmangle mangling format in struct"); 274 i++; 275 while (mangledSignature[i] != ')') { 276 enumName ~= mangledSignature[i]; 277 i++; 278 if (i >= mangledSignature.length) 279 throw new Exception("Invalid unmangle mangling format in struct"); 280 } 281 currentType.mangledType = enumName; 282 break; 283 case 'p': 284 currentType.baseType = GrBaseType.class_; 285 string structName; 286 if ((i + 2) >= mangledSignature.length) 287 throw new Exception("Invalid unmangle mangling format in struct"); 288 i++; 289 if (mangledSignature[i] != '(') 290 throw new Exception("Invalid unmangle mangling format in struct"); 291 i++; 292 while (mangledSignature[i] != ')') { 293 structName ~= mangledSignature[i]; 294 i++; 295 if (i >= mangledSignature.length) 296 throw new Exception("Invalid unmangle mangling format in struct"); 297 } 298 currentType.mangledType = structName; 299 break; 300 case 'u': 301 currentType.baseType = GrBaseType.foreign; 302 string foreignName; 303 if ((i + 2) >= mangledSignature.length) 304 throw new Exception("Invalid unmangle mangling format in foreign"); 305 i++; 306 if (mangledSignature[i] != '(') 307 throw new Exception("Invalid unmangle mangling format in foreign"); 308 i++; 309 while (mangledSignature[i] != ')') { 310 foreignName ~= mangledSignature[i]; 311 i++; 312 if (i >= mangledSignature.length) 313 throw new Exception("Invalid unmangle mangling format in foreign"); 314 } 315 currentType.mangledType = foreignName; 316 break; 317 case 'f': 318 i++; 319 currentType.baseType = GrBaseType.function_; 320 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 321 i++; 322 currentType.mangledReturnType = grUnmangleBlock(mangledSignature, i); 323 i++; 324 break; 325 case 't': 326 i++; 327 currentType.baseType = GrBaseType.task; 328 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 329 i++; 330 break; 331 case 'c': 332 i++; 333 currentType.baseType = GrBaseType.chan; 334 currentType.mangledType = grUnmangleBlock(mangledSignature, i); 335 i++; 336 break; 337 default: 338 break; 339 } 340 } 341 342 return currentType; 343 }