Changeset 210
- Timestamp:
- 07/06/06 15:25:30 (2 years ago)
- Files:
-
- trunk/meta/demangle.d (modified) (21 diffs)
- trunk/meta/nameof.d (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/meta/demangle.d
r209 r210 4 4 */ 5 5 6 /* Implementation is via pairs of metafunctions: 6 module meta.demangle; 7 private import meta.ctype; 8 /* 9 Implementation is via pairs of metafunctions: 7 10 a 'demangle' metafunction, which returns a const char [], 8 11 and a 'Consumed' metafunction, which returns an integer, the number of characters which … … 10 13 */ 11 14 12 module meta.demangle; 13 private import meta.ctype; 14 15 /***************************************** 16 * How should the name be displayed? 17 */ 15 18 enum MangledNameType 16 19 { 17 PrettyName, 18 QualifiedName, 19 SymbolName 20 } 21 22 /*************************** 20 PrettyName, // With full type information 21 QualifiedName, // No type information, just identifiers seperated by dots 22 SymbolName // Only the ultimate identifier 23 } 24 25 /***************************************** 23 26 * Pretty-prints a mangled type string. 24 27 */ 25 28 template demangleType(char[] str, MangledNameType wantQualifiedNames = MangledNameType.PrettyName) 26 29 { 27 static if (wantQualifiedNames != MangledNameType.PrettyName) {28 // Deal with symbolnameof!(), qualifiednameof!().29 static if (str[0]=='C' || str[0]=='S' || str[0]=='E' || str[0]=='T')30 const char [] demangleType = prettyLname!(str[1..$], wantQualifiedNames);31 else static assert(0, "Demangle error: type '" ~ str ~ "' does not contain a qualified name");32 } else static if (str[0] == 'A') // dynamic array30 static if (wantQualifiedNames != MangledNameType.PrettyName) { 31 // Deal with symbolnameof!(), qualifiednameof!(). 32 static if (str[0]=='C' || str[0]=='S' || str[0]=='E' || str[0]=='T') 33 const char [] demangleType = prettyLname!(str[1..$], wantQualifiedNames); 34 else static assert(0, "Demangle error: type '" ~ str ~ "' does not contain a qualified name"); 35 } else static if (str[0] == 'A') // dynamic array 33 36 const char [] demangleType = demangleType!(str[1..$], wantQualifiedNames) ~ "[]"; 34 37 else static if (str[0] == 'H') // associative array 35 38 const char [] demangleType 36 = demangleType!(str[1+demangleTypeConsumed!(str[1..$])..$], wantQualifiedNames)37 ~ "[" ~ demangleType!(str[1..1+(demangleTypeConsumed!(str[1..$]))], wantQualifiedNames) ~ "]";39 = demangleType!(str[1+demangleTypeConsumed!(str[1..$])..$], wantQualifiedNames) 40 ~ "[" ~ demangleType!(str[1..1+(demangleTypeConsumed!(str[1..$]))], wantQualifiedNames) ~ "]"; 38 41 else static if (str[0] == 'G') // static array 39 42 const char [] demangleType 40 = demangleType!(str[1+countLeadingDigits!(str[1..$])..$], wantQualifiedNames)41 ~ "[" ~ str[1..1+countLeadingDigits!(str[1..$]) ] ~ "]";43 = demangleType!(str[1+countLeadingDigits!(str[1..$])..$], wantQualifiedNames) 44 ~ "[" ~ str[1..1+countLeadingDigits!(str[1..$]) ] ~ "]"; 42 45 else static if (str[0]=='C') 43 const char [] demangleType = "class " ~ prettyLname!(str[1..$], wantQualifiedNames);46 const char [] demangleType = "class " ~ prettyLname!(str[1..$], wantQualifiedNames); 44 47 else static if (str[0]=='S') 45 48 const char [] demangleType = "struct " ~ prettyLname!(str[1..$], wantQualifiedNames); … … 49 52 const char [] demangleType = "typedef " ~ prettyLname!(str[1..$], wantQualifiedNames); 50 53 else static if (str[0]=='D' && str.length>2 && isMangledFunction!(( str[1] )) ) // delegate 51 const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "delegate ", wantQualifiedNames);54 const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "delegate ", wantQualifiedNames); 52 55 else static if (str[0]=='P' && str.length>2 && isMangledFunction!(( str[1] )) ) // function pointer 53 const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "function ", wantQualifiedNames);56 const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "function ", wantQualifiedNames); 54 57 else static if (str[0]=='P') // only after we've dealt with function pointers 55 58 const char [] demangleType = demangleType!(str[1..$], wantQualifiedNames) ~ "*"; 56 59 else static if (str[0]=='F') 57 const char [] demangleType = demangleFunctionOrDelegate!(str, "", wantQualifiedNames);60 const char [] demangleType = demangleFunctionOrDelegate!(str, "", wantQualifiedNames); 58 61 else const char [] demangleType = demangleBasicType!(str); 59 62 } … … 103 106 else static if (str[0]=='H') 104 107 const int demangleTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]) 105 + demangleTypeConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]);108 + demangleTypeConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]); 106 109 else static if (str[0]=='G') 107 110 const int demangleTypeConsumed = 1 + countLeadingDigits!(str[1..$]) … … 112 115 const int demangleTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]); 113 116 else static if (str[0]=='C' || str[0]=='S' || str[0]=='E' || str[0]=='T') 114 const int demangleTypeConsumed = 1 + getDotNameConsumed!(str[1..$]); 115 else static if (str[0]=='F') { 116 static assert(str.length>1); 117 const int demangleTypeConsumed = 1 + getQualifiedNameConsumed!(str[1..$]); 118 else static if (str[0]=='F' && str.length>1) 117 119 const int demangleTypeConsumed = 1 + demangleParamListAndRetValConsumed!(str[1..$]); 118 }else // it's a Basic Type119 const int demangleTypeConsumed = 1;120 else // it's a Basic Type 121 const int demangleTypeConsumed = 1; 120 122 } 121 123 … … 154 156 template pretty_Dname(char [] str, int dotnameconsumed, MangledNameType wantQualifiedNames) 155 157 { 156 static if ( isMangledFunction!( (str[2+dotnameconsumed]))) { 157 const char [] pretty_Dname = pretty_Dfunction!(str, dotnameconsumed, demangleParamListAndRetValConsumed!(str[3+dotnameconsumed..$]), wantQualifiedNames); 158 } else { 159 static if (wantQualifiedNames == MangledNameType.PrettyName) { 160 const char [] pretty_Dname = 161 demangleType!(str[2+dotnameconsumed..$], wantQualifiedNames) 162 ~ " " ~ getDotName!(str[2..$], wantQualifiedNames); 158 static if ( isMangledFunction!( (str[2+dotnameconsumed]))) { 159 const char [] pretty_Dname = pretty_Dfunction!(str, dotnameconsumed, 160 demangleParamListAndRetValConsumed!(str[3+dotnameconsumed..$]), wantQualifiedNames); 163 161 } else { 164 const char [] pretty_Dname = getDotName!(str[2..$], wantQualifiedNames); 165 } 166 } 162 static if (wantQualifiedNames == MangledNameType.PrettyName) { 163 const char [] pretty_Dname = 164 demangleType!(str[2+dotnameconsumed..$], wantQualifiedNames) 165 ~ " " ~ getQualifiedName!(str[2..$], wantQualifiedNames); 166 } else { 167 const char [] pretty_Dname = getQualifiedName!(str[2..$], wantQualifiedNames); 168 } 169 } 167 170 } 168 171 169 172 // Deal with the case where an Lname contains an embedded ("__D") function. 170 173 // Split into a seperate function because it's so complicated. 171 template pretty_Dfunction(char [] str, int dotnameconsumed, int paramlistconsumed, MangledNameType wantQualifiedNames) 172 { 173 static if (wantQualifiedNames == MangledNameType.PrettyName) { 174 const char [] pretty_Dfunction = 175 demangleFunctionOrDelegate!(str[2 + dotnameconsumed .. 3 + dotnameconsumed + paramlistconsumed], 176 getDotName!(str[2..$], wantQualifiedNames), wantQualifiedNames) 177 ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, "."); 174 template pretty_Dfunction(char [] str, int dotnameconsumed, int paramlistconsumed, 175 MangledNameType wantQualifiedNames) 176 { 177 static if (wantQualifiedNames == MangledNameType.PrettyName) { 178 const char [] pretty_Dfunction = 179 demangleFunctionOrDelegate!(str[2 + dotnameconsumed .. 3 + dotnameconsumed + paramlistconsumed], 180 getQualifiedName!(str[2..$], wantQualifiedNames), wantQualifiedNames) 181 ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, "."); 178 182 } else static if (wantQualifiedNames == MangledNameType.QualifiedName) { 179 // Qualified names180 const char [] pretty_Dfunction = getDotName!(str[2..$], wantQualifiedNames)181 ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, ".");183 // Qualified name 184 const char [] pretty_Dfunction = getQualifiedName!(str[2..$], wantQualifiedNames) 185 ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, "."); 182 186 } else { // symbol name 183 static if (3 + dotnameconsumed + paramlistconsumed == str.length)184 const char [] pretty_Dfunction = getDotName!(str[2..$], wantQualifiedNames);185 else const char [] pretty_Dfunction = getQualifiedName!(186 str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames);187 }187 static if (3 + dotnameconsumed + paramlistconsumed == str.length) 188 const char [] pretty_Dfunction = getQualifiedName!(str[2..$], wantQualifiedNames); 189 else const char [] pretty_Dfunction = getQualifiedName!( 190 str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames); 191 } 188 192 } 189 193 … … 191 195 template get_DnameConsumed(char [] str) 192 196 { 193 const int get_DnameConsumed = 2 + getDotNameConsumed!(str[2..$])194 + demangleTypeConsumed!(str[2+getDotNameConsumed!(str[2..$])..$]);197 const int get_DnameConsumed = 2 + getQualifiedNameConsumed!(str[2..$]) 198 + demangleTypeConsumed!(str[2+getQualifedNameConsumed!(str[2..$])..$]); 195 199 } 196 200 … … 199 203 template prettyLname(char [] str, MangledNameType wantQualifiedNames) 200 204 { 201 static if (str.length>3 && str[0..3] == "__T") // Template instance name 202 static if (wantQualifiedNames == MangledNameType.PrettyName) { 203 const char [] prettyLname = 204 prettyLname!(str[3..$], wantQualifiedNames) ~ "!(" 205 ~ prettyTemplateArgList!(str[3+getDotNameConsumed!(str[3..$])..$], wantQualifiedNames) ~ ")"; 206 } else { 207 const char [] prettyLname = 208 prettyLname!(str[3..$], wantQualifiedNames); 209 } 210 else static if (str.length>2 && str[0..2] == "_D") { 211 const char [] prettyLname = pretty_Dname!(str, getDotNameConsumed!(str[2..$]), wantQualifiedNames); 212 } else static if ( isdigit!( (str[0]) ) ) 213 const char [] prettyLname = getDotName!(str[0..getDotNameConsumed!(str)], wantQualifiedNames); 214 else const char [] prettyLname = str; 205 static if (str.length>3 && str[0..3] == "__T") // Template instance name 206 static if (wantQualifiedNames == MangledNameType.PrettyName) { 207 const char [] prettyLname = 208 prettyLname!(str[3..$], wantQualifiedNames) ~ "!(" 209 ~ prettyTemplateArgList!(str[3+getQualifiedNameConsumed!(str[3..$])..$], wantQualifiedNames) 210 ~ ")"; 211 } else { 212 const char [] prettyLname = 213 prettyLname!(str[3..$], wantQualifiedNames); 214 } 215 else static if (str.length>2 && str[0..2] == "_D") { 216 const char [] prettyLname = pretty_Dname!(str, getQualifiedNameConsumed!(str[2..$]), wantQualifiedNames); 217 } else static if ( isdigit!( (str[0]) ) ) 218 const char [] prettyLname = getQualifiedName!(str[0..getQualifiedNameConsumed!(str)], wantQualifiedNames); 219 else const char [] prettyLname = str; 215 220 } 216 221 … … 220 225 { 221 226 static if (str.length==0) 222 const int getLnameConsumed=0;227 const int getLnameConsumed=0; 223 228 else static if (str.length<=10 || !isdigit!( (str[1]) ) ) 224 229 const int getLnameConsumed = 1 + str[0]-'0'; … … 226 231 const int getLnameConsumed = (str[0]-'0')*10 + str[1]-'0' + 2; 227 232 else 228 const int getLnameConsumed = (str[0]-'0')*100 + (str[1]-'0')*10 + str[0]-'0' + 3;233 const int getLnameConsumed = (str[0]-'0')*100 + (str[1]-'0')*10 + str[0]-'0' + 3; 229 234 } 230 235 231 236 template getQualifiedName(char [] str, MangledNameType wantQualifiedNames, char [] dotstr = "") 232 237 { 233 // main() is a special case, it isn't qualified by a module.234 // static if (str.length>4 && dotstr="" && str[0..4] == "main")235 238 static if (str.length==0) const char [] getQualifiedName=""; 239 else static if (str.length>2 && str[0]=='_' && str[1]=='D') 240 const char [] getDotName = getQualifiedName!(str[2..$], wantQualifiedNames); 236 241 else static if (isdigit!(( str[0] ))) { 237 242 static if (str[getLnameConsumed!(str)..$].length>0) { 238 static if (wantQualifiedNames == MangledNameType.SymbolName) { 239 static if (getLnameConsumed!(str)==str.length) { 240 const char [] getQualifiedName = prettyLname!(getLname!(str), wantQualifiedNames); 241 } else static if ( isdigit!(( str[getLnameConsumed!(str)] ))) { 242 const char [] getQualifiedName = getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, ""); 243 } else const char [] getQualifiedName = prettyLname!(getLname!(str), wantQualifiedNames); 244 } else { 245 // Qualified and pretty names 246 const char [] getQualifiedName = dotstr ~ prettyLname!(getLname!(str), wantQualifiedNames) 247 ~ getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, "."); 248 } 249 } else const char [] getQualifiedName = dotstr ~ prettyLname!(getLname!(str), wantQualifiedNames); 243 static if (wantQualifiedNames == MangledNameType.SymbolName) { 244 static if (getLnameConsumed!(str)==str.length) { 245 const char [] getQualifiedName = prettyLname!(getLname!(str), wantQualifiedNames); 246 } else static if ( isdigit!(( str[getLnameConsumed!(str)] ))) { 247 const char [] getQualifiedName = 248 getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, ""); 249 } else { 250 const char [] getQualifiedName = prettyLname!(getLname!(str), wantQualifiedNames); 251 } 252 } else { 253 // Qualified and pretty names 254 const char [] getQualifiedName = dotstr 255 ~ prettyLname!(getLname!(str), wantQualifiedNames) 256 ~ getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, "."); 257 } 258 } else { 259 const char [] getQualifiedName = dotstr ~ prettyLname!(getLname!(str), wantQualifiedNames); 260 } 250 261 } else const char [] getQualifiedName = ""; 251 // static assert(0, "Demangle error, Unrecognized qualified name " ~ str); 252 } 253 254 template getDotName(char [] str, MangledNameType wantQualifiedNames) 255 { 256 static if (str.length>2 && str[0]=='_' && str[1]=='D') { 257 const char [] getDotName = getDotName!(str[2..$], wantQualifiedNames); 258 } else //static if (wantQualifiedNames != MangledNameType.SymbolName) 259 const char [] getDotName = getQualifiedName!(str, wantQualifiedNames); 260 // else const char [] getDotName = getSymbolName!(str); 261 } 262 263 // how much of the str is taken up with a qualified name? 264 template getDotNameConsumed (char [] str) 265 { 266 static if (str.length>1) { 267 static if ( isdigit!(( str[0] )) ) { 268 static if (getLnameConsumed!(str) <= str.length) 269 const int getDotNameConsumed = getLnameConsumed!(str) 270 + getDotNameConsumed!(str[getLnameConsumed!(str) .. $]); 271 else const int getDotNameConsumed = str.length; 272 } else static if (str[0]=='_' && str[1]=='D') { 273 const int getDotNameConsumed = get_DnameConsumed!(str) 274 + getDotNameConsumed!(str[get_DnameConsumed!(str)..$]); 275 } 276 else const int getDotNameConsumed=0; 277 } else const int getDotNameConsumed=0; 262 } 263 264 // BUG: This isn't correct. It's making getQualifiedName() unnecessarily complicated. 265 template getQualifiedNameConsumed (char [] str) 266 { 267 static if (str.length>1 && isdigit!(( str[0] )) ) { 268 static if (getLnameConsumed!(str) <= str.length) { 269 const int getQualifiedNameConsumed = getLnameConsumed!(str) 270 + getQualifiedNameConsumed!(str[getLnameConsumed!(str) .. $]); 271 } else { 272 const int getQualifiedNameConsumed = str.length; 273 } 274 } else static if (str.length>1 && str[0]=='_' && str[1]=='D') { 275 const int getQualifiedNameConsumed = get_DnameConsumed!(str) 276 + getQualifiedNameConsumed!(str[get_DnameConsumed!(str)..$]); 277 } else const int getQualifiedNameConsumed=0; 278 278 } 279 279 … … 286 286 template demangleFunctionOrDelegate(char [] str, char [] funcOrDelegStr, MangledNameType wantQualifiedNames) 287 287 { 288 const char [] demangleFunctionOrDelegate = demangleExtern!(( str[0] ))289 ~ demangleReturnValue!(str[1..$], wantQualifiedNames)290 ~ " " ~ funcOrDelegStr ~ "("291 ~ demangleParamList!(str[1..1+demangleParamListAndRetValConsumed!(str[1..$])], wantQualifiedNames)292 ~ ")";288 const char [] demangleFunctionOrDelegate = demangleExtern!(( str[0] )) 289 ~ demangleReturnValue!(str[1..$], wantQualifiedNames) 290 ~ " " ~ funcOrDelegStr ~ "(" 291 ~ demangleParamList!(str[1..1+demangleParamListAndRetValConsumed!(str[1..$])], wantQualifiedNames) 292 ~ ")"; 293 293 } 294 294 … … 297 297 template demangleFunctionParamType(char[] str, MangledNameType wantQualifiedNames) 298 298 { 299 static if (str[0]=='K')300 const char [] demangleFunctionParamType = "inout " ~ demangleType!(str[1..$], wantQualifiedNames);301 else static if (str[0]=='J')302 const char [] demangleFunctionParamType = "out " ~ demangleType!(str[1..$], wantQualifiedNames);303 else const char [] demangleFunctionParamType = demangleType!(str, wantQualifiedNames);299 static if (str[0]=='K') 300 const char [] demangleFunctionParamType = "inout " ~ demangleType!(str[1..$], wantQualifiedNames); 301 else static if (str[0]=='J') 302 const char [] demangleFunctionParamType = "out " ~ demangleType!(str[1..$], wantQualifiedNames); 303 else const char [] demangleFunctionParamType = demangleType!(str, wantQualifiedNames); 304 304 } 305 305 … … 307 307 template demangleFunctionParamTypeConsumed(char[] str) 308 308 { 309 static if (str[0]=='K' || str[0]=='J')310 const int demangleFunctionParamTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]);311 else const int demangleFunctionParamTypeConsumed = demangleTypeConsumed!(str);309 static if (str[0]=='K' || str[0]=='J') 310 const int demangleFunctionParamTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]); 311 else const int demangleFunctionParamTypeConsumed = demangleTypeConsumed!(str); 312 312 } 313 313 … … 315 315 template isMangledFunction(char c) 316 316 { 317 const bool isMangledFunction = (c=='F' || c=='U' || c=='W' || c=='V' || c=='R');317 const bool isMangledFunction = (c=='F' || c=='U' || c=='W' || c=='V' || c=='R'); 318 318 } 319 319 320 320 template demangleExtern(char c) 321 321 { 322 static if (c=='F') const char [] demangleExtern = "";323 else static if (c=='U') const char [] demangleExtern = "extern (C) ";324 else static if (c=='W') const char [] demangleExtern = "extern (Windows) ";325 else static if (c=='V') const char [] demangleExtern = "extern (Pascal) ";326 else static if (c=='R') const char [] demangleExtern = "extern (C++) ";327 else static assert(0, "Unrecognized extern function.");322 static if (c=='F') const char [] demangleExtern = ""; 323 else static if (c=='U') const char [] demangleExtern = "extern (C) "; 324 else static if (c=='W') const char [] demangleExtern = "extern (Windows) "; 325 else static if (c=='V') const char [] demangleExtern = "extern (Pascal) "; 326 else static if (c=='R') const char [] demangleExtern = "extern (C++) "; 327 else static assert(0, "Unrecognized extern function."); 328 328 } 329 329 … … 333 333 { 334 334 static assert(str.length>=1, "Demangle error(Function): No return value found"); 335 static if (str[0]=='Z' || str[0]=='Y')335 static if (str[0]=='Z' || str[0]=='Y') 336 336 const char[] demangleReturnValue = demangleType!(str[1..$], wantQualifiedNames); 337 337 else const char [] demangleReturnValue = demangleReturnValue!(str[demangleFunctionParamTypeConsumed!(str)..$], wantQualifiedNames); … … 346 346 const char [] demangleParamList = commastr ~ "..."; 347 347 else 348 const char [] demangleParamList = commastr ~ demangleFunctionParamType!(str[0..demangleFunctionParamTypeConsumed!(str)], wantQualifiedNames) 348 const char [] demangleParamList = commastr ~ 349 demangleFunctionParamType!(str[0..demangleFunctionParamTypeConsumed!(str)], wantQualifiedNames) 349 350 ~ demangleParamList!(str[demangleFunctionParamTypeConsumed!(str)..$], wantQualifiedNames, ", "); 350 351 } … … 393 394 else static if (str[0]=='V') // value 394 395 const char [] prettyTemplateArg = 395 demangleType!(str[1..1+demangleTypeConsumed!(str[1..$])], wantQualifiedNames)396 ~ " = " ~ prettyValueArg!(str[1+demangleTypeConsumed!(str[1..$])..$]);396 demangleType!(str[1..1+demangleTypeConsumed!(str[1..$])], wantQualifiedNames) 397 ~ " = " ~ prettyValueArg!(str[1+demangleTypeConsumed!(str[1..$])..$]); 397 398 else static if (str[0]=='T') // type 398 399 const char [] prettyTemplateArg = demangleType!(str[1..$], wantQualifiedNames); … … 406 407 else static if (str[0]=='V') // value 407 408 const int templateArgConsumed = 1 + demangleTypeConsumed!(str[1..$]) + 408 templateValueArgConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]);409 templateValueArgConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]); 409 410 else static if (str[0]=='T') // type 410 411 const int templateArgConsumed = 1 + demangleTypeConsumed!(str[1..$]); … … 427 428 { 428 429 static assert(str.length>0, "No Z found at end of template argument list"); 429 static if (str[0]=='Z')430 static if (str[0]=='Z') 430 431 const int templateArgListConsumed = 1; 431 432 else … … 449 450 450 451 extern (Windows) { 451 typedef void function (double, long) WinFunc;452 typedef void function (double, long) WinFunc; 452 453 } 453 454 extern (Pascal) { 454 typedef short[wchar] delegate (bool, ...) PascFunc;455 typedef short[wchar] delegate (bool, ...) PascFunc; 455 456 } 456 457 extern (C) { 457 typedef dchar delegate () CFunc;458 typedef dchar delegate () CFunc; 458 459 } 459 460 extern (C++) { 460 typedef cfloat function (wchar) CPPFunc;461 typedef cfloat function (wchar) CPPFunc; 461 462 } 462 463 … … 471 472 template ComplexTemplate(real a, creal b) 472 473 { 473 class ComplexTemplate {}474 class ComplexTemplate {} 474 475 } 475 476 trunk/meta/nameof.d
r209 r210 1 1 /** 2 * Given any D symbol (class, template, function, module name, 3 * or non-local variable), convert it to a compile-time string literal, 4 * optionally containing the fully qualified and decorated name. 2 * Convert any D symbol or type to a human-readable string, at compile time. 3 * 4 * Given any D symbol (class, template, function, module name, or non-local variable) 5 * or any D type, convert it to a compile-time string literal, 6 * optionally containing the fully qualified and decorated name. 7 * 8 * Limitations (as of DMD 0.162): 9 * 1. Names of local variables cannot be determined, because they are not permitted 10 * as template alias parameters. Technically, it's possible to determine the name by using 11 * a mixin hack, but it's so ugly that it cannot be recommended. 12 * 2. The name mangling for symbols declared inside extern(Windows), extern(C) and extern(Pascal) 13 * functions is inherently ambiguous, so such inner symbols are not always correctly displayed. 5 14 */ 6 15 module meta.nameof; … … 27 36 } 28 37 29 // We will get the .mangleof for a pointer to this function pointer.30 template rawmanglednameof(alias A)31 {32 const char [] rawmanglednameof =33 typeof(&outer!(A)).mangleof;34 }38 // We will get the .mangleof for a pointer to this function pointer. 39 template rawmanglednameof(alias A) 40 { 41 const char [] rawmanglednameof = 42 typeof(&outer!(A)).mangleof; 43 } 35 44 36 45 // If the identifier is "MyIdentifier" and this module is "QualModule" … … 71 80 72 81 73 /** Like .mangleof, except that it works for an alias template parameter instead of a type. 82 /** 83 * Like .mangleof, except that it works for an alias template parameter instead of a type. 74 84 */ 75 85 template manglednameof(alias A) 76 86 { 77 static if (rawmanglednameof!(A).length - pointerstartlength - pointerendlength <= 99+2) {78 // the length of the template argument requires 2 bytes79 const char [] manglednameof =87 static if (rawmanglednameof!(A).length - pointerstartlength <= 100 + 1) { 88 // the length of the template argument requires 2 characters 89 const char [] manglednameof = 80 90 rawmanglednameof!(A)[ pointerstartlength + 2 .. $ - pointerendlength]; 81 } else82 const char [] manglednameof =91 } else 92 const char [] manglednameof = 83 93 rawmanglednameof!(A)[ pointerstartlength + 3 .. $ - pointerendlength]; 84 94 } 85 95 86 // The symbol as it was declared (but fully qualified). 87 // example: "int mymodule.myclass.myfunc(uint, class otherclass)" 96 /** 97 * The symbol as it was declared, but including full type qualification. 98 * 99 * example: "int mymodule.myclass.myfunc(uint, class otherclass)" 100 */ 88 101 template prettynameof(alias A) 89 102 { … … 91 104 } 92 105 93 /** The textual representation of a type 106 /** Convert any D type to a human-readable string literal 107 * 94 108 * example: "int function(double, char[])" 95 109 */ … … 111 125 } 112 126 113 /** Returns the unqualified name, as a single text string. 127 /** 128 * Returns the unqualified name, as a single text string. 114 129 * 115 130 * eg. "myfunc" … … 121 136 122 137 //---------------------------------------------- 123 // Unit Tests138 // Unit Tests 124 139 //---------------------------------------------- 125 140 … … 164 179 165 180 static assert( prettynameof!(SomeInt) 166 == "enum " ~ THISFILE ~ ".SomeEnum " ~ THISFILE ~ ".SomeInt");181 == "enum " ~ THISFILE ~ ".SomeEnum " ~ THISFILE ~ ".SomeInt"); 167 182 static assert( qualifiednameof!(OuterClass) == THISFILE ~".OuterClass"); 168 183 static assert( symbolnameof!(SomeInt) == "SomeInt"); 169 184 170 185 static assert( prettynameof!(inner!( MyInt!(68u) )) 171 == "class " ~ THISFILE ~ ".inner!(" ~ THISFILE ~ ".MyInt!(uint = 68)).inner");172 static assert( symbolnameof!(inner!( MyInt!(68u) )) == "inner");186 == "class " ~ THISFILE ~ ".inner!(" ~ THISFILE ~ ".MyInt!(uint = 68)).inner"); 187 static assert( symbolnameof!(inner!( MyInt!(68u) )) == "inner"); 173 188 static assert( prettynameof!(ClassTemplate!(OuterClass.SomeClass)) 174 == "class "~ THISFILE ~ ".ClassTemplate!(class "~ THISFILE ~ ".OuterClass.SomeClass).ClassTemplate");175 static assert( symbolnameof!(ClassTemplate!(OuterClass.SomeClass)) == "ClassTemplate");189 == "class "~ THISFILE ~ ".ClassTemplate!(class "~ THISFILE ~ ".OuterClass.SomeClass).ClassTemplate"); 190 static assert( symbolnameof!(ClassTemplate!(OuterClass.SomeClass)) == "ClassTemplate"); 176 191 177 192 // Extern(D) declarations have full type information. … … 184 199 // Extern(Windows) declarations contain no type information. 185 200 extern (Windows) { 186 extern int dog();187 extern int dig;201 extern int dog(); 202 extern int dig; 188 203 } 189 204 … … 195 210 196 211 extern (Windows) { 197 // "Gad! You think of everything." - Ned Seagoon198 // "No! Sometimes I forget aardvarks." - Major Denis Bloodnok.199 212 template aardvark(X) { 200 int aardvark(short goon) {201 class wolf {}202 static assert(prettynameof!(wolf)== "class extern (Windows) int " ~ THISFILE ~ ".aardvark!(struct "203 ~ THISFILE ~ ".OuterClass).aardvark(short).wolf");204 static assert(qualifiednameof!(wolf)== THISFILE ~ ".aardvark.aardvark.wolf");205 static assert( symbolnameof!(wolf) == "wolf");206 return 3;207 }208 }213 int aardvark(short goon) { 214 class wolf {} 215 static assert(prettynameof!(wolf)== "class extern (Windows) int " ~ THISFILE ~ ".aardvark!(struct " 216 ~ THISFILE ~ ".OuterClass).aardvark(short).wolf"); 217 static assert(qualifiednameof!(wolf)== THISFILE ~ ".aardvark.aardvark.wolf"); 218 static assert( symbolnameof!(wolf) == "wolf"); 219 return 3; 220 } 221 } 209 222 } 210 223 … … 214 227 // Corner case #2: template inside function. This is currently possible only with mixins. 215 228 template fox(B, ushort C) { 216 class fox {}229 class fox {} 217 230 } 218 231 219 232 void wolf() { 220 mixin fox!(cfloat, 21);221 static assert(prettynameof!(fox)== "class void " ~ THISFILE ~ ".wolf().fox!(cfloat, int = 21).fox");222 static assert(qualifiednameof!(fox)== THISFILE ~ ".wolf.fox.fox");223 static assert(symbolnameof!(fox)== "fox");224 } 225 226 } 233 mixin fox!(cfloat, 21); 234 static assert(prettynameof!(fox)== "class void " ~ THISFILE ~ ".wolf().fox!(cfloat, int = 21).fox"); 235 static assert(qualifiednameof!(fox)== THISFILE ~ ".wolf.fox.fox"); 236 static assert(symbolnameof!(fox)== "fox"); 237 } 238 239 }
