Changeset 160
- Timestamp:
- 03/09/06 08:25:20 (2 years ago)
- Files:
-
- trunk/meta/conv.d (modified) (5 diffs)
- trunk/meta/ctype.d (modified) (1 diff)
- trunk/meta/demangle.d (modified) (6 diffs)
- trunk/meta/demo/calcpi.d (modified) (2 diffs)
- trunk/meta/demo/tabledemo.d (modified) (2 diffs)
- trunk/meta/feqtest.d (added)
- trunk/meta/math.d (modified) (1 diff)
- trunk/meta/nameof.d (moved) (moved from trunk/meta/qualifiedname.d) (6 diffs)
- trunk/meta/qualtest.d (modified) (3 diffs)
- trunk/meta/strhacks.d (modified) (3 diffs)
- trunk/meta/string.d (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/meta/conv.d
r126 r160 6 6 * Author: Don Clugston. License: Public domain. 7 7 */ 8 /* 9 Normally, a function which processes the first part of a string 10 would return the part which was not consumed (the 'tail'). 11 This doesn't work very well for D templates, so for such functions, 12 we supply a seperate metafunction with the suffix 'Consumed' which returns 13 the number of characters consumed. (This is the same as the index of the first 14 character in the string which was not consumed). 15 This results in some code duplication, but seems to results in a much cleaner design. 16 */ 8 17 9 18 module meta.conv; … … 20 29 template itoa(long n) 21 30 { 22 static if (n<0) {23 const char [] itoa = "-" ~ .itoa!(-n);24 } else static if (n<10L) {31 static if (n<0) 32 const char [] itoa = "-" ~ itoa!(-n); 33 else static if (n<10L) 25 34 const char [] itoa = decimaldigit!(n); 26 } else {35 else 27 36 const char [] itoa = itoa!(n/10L) ~ decimaldigit!(n%10L); 28 }29 37 } 30 38 31 39 template toHexString(ulong n) 32 40 { 33 static if (n<16L) {41 static if (n<16L) 34 42 const char [] toHexString = hexdigit!(n); 35 } else {43 else 36 44 const char [] toHexString = toHexString!(n >> 4) ~ hexdigit!(n&0xF); 37 }38 45 } 39 46 … … 41 48 * long atoi!(char [] s); 42 49 */ 43 template atoi(char [] s, long sofar=0, int indx=0) 44 { 45 static if (s.length==indx) const long atoi=sofar; 46 else static if (indx==0 && s[indx]=='-') const long atoi = -.atoi!(s, 0, 1); 47 else static if (!isdigit!( (s[indx]) ) ) const long atoi = sofar; 48 else const long atoi = .atoi!(s, sofar * 10 + s[indx]-'0', indx+1); 50 template atoi(char [] s, long result=0, int indx=0) 51 { 52 static if (s.length==indx) 53 const long atoi = result; 54 else static if (indx==0 && s[indx]=='-') 55 const long atoi = - atoi!(s, 0, 1); 56 else static if (!isdigit!( (s[indx]) ) ) 57 const long atoi = result; 58 else 59 const long atoi = atoi!(s, result * 10 + s[indx]-'0', indx+1); 49 60 } 50 61 … … 52 63 * the number of characters in s[] which would be 'consumed' by atoi!(). 53 64 */ 54 template countleadingdigits(char [] s, int indx=0) 55 { 56 static if (s.length==indx) { 57 const int countleadingdigits=indx; 58 } else static if (indx==0 && s[indx]=='-') { 59 const int countleadingdigits = countleadingdigits!(s, indx+1); 60 } else static if (!isdigit!( (s[indx]) )) { 61 const int countleadingdigits=indx; 62 } else { 63 const int countleadingdigits = countleadingdigits!(s, indx+1); 64 } 65 } 66 67 /* ***************************** 68 * int sigFigs!(char [] s) 69 * 70 * Returns the number of significant figures in the decimal number s. 71 * Leading zeros do not count towards the number of significant figures; 72 * eg, sigFigs!(0.000003) == 1. 73 * sigFigs!(0.00000) == 0. 74 */ 75 template sigFigs(char [] s, int p=0, bool stillzero=true) 76 { 77 static if ( s.length ==p ) { 78 static if (p>0 && stillzero) { 79 const int sigFigs = 1; // the number was zero 80 } else { 81 const int sigFigs = 0; 82 } 83 } else static if ( s[p]=='.'|| (p==0 && s[p]=='-') ) { 84 const int sigFigs = sigFigs!(s, p+1, stillzero); 85 } else static if (s[p]=='0' && stillzero) { 86 const int sigFigs = sigFigs!(s, p+1, stillzero); 87 } else static if ( isdigit!((s[p])) ) { 88 const int sigFigs = 1 + sigFigs!(s, p+1, false); 89 } else static if ( s[p]=='e' || s[p]=='E' ) { 90 // abort once we reach the exponent 91 const int sigFigs=0; 92 } else { 93 static assert(0); // invalid character in string 94 } 95 } 96 97 65 template atoiConsumed(char [] s, int indx=0) 66 { 67 static if(s.length==indx) 68 const int atoiConsumed = indx; 69 else static if ((indx==0 && s[indx]=='-') || isdigit!( (s[indx]) ) ) 70 const int atoiConsumed = atoiConsumed!(s,indx + 1); 71 else // invalid character 72 const int atoiConsumed = indx; 73 } 74 75 private enum EFloatParseState { START=0, GOTSIGN, WAITDOT, WAITEXP=3, GOTEXPCHAR, GOTEXPSIGN, EXPDIG }; 76 77 78 // Like atoi!(), except that internal underscores are allowable 79 template parseInt(char [] s, long result=0, EFloatParseState state =0 /* start*/) 80 { 81 static if (s.length==0) 82 const long parseInt = result; 83 else static if (state == EFloatParseState.START && s[0]=='-') 84 const long parseInt = - parseInt!(s[1..$], 0, GOTSIGN); 85 else static if (state == EFloatParseState.WAITDOT && s[0]=='_') 86 const long parseInt = parseInt!(s[1..$], result, state); 87 else static if (isdigit!( (s[0]) ) ) 88 const long parseInt = parseInt!(s[1..$], result*10 + s[0]-'0', WAITDOT); 89 } 90 91 // Returns the value of the exponent. 92 // must be of the form "" or "e-543" or "E+2_453" etc 93 template parseExponent(char [] s, int result = 0, EFloatParseState state = EFloatParseState.WAITEXP) 94 { 95 static if (s.length == 0) { 96 // an empty string is acceptable 97 static if (state == EFloatParseState.WAITEXP || state == EFloatParseState.EXPDIG) 98 const int parseExponent = result; 99 else { 100 pragma(msg, "Error: No exponent found in floating-point literal."); 101 static assert(0); 102 } 103 } else static if (state == EFloatParseState.WAITEXP && (s[0]=='e' || s[0]=='E') ) 104 const int parseExponent = parseExponent!(s[1..$], 0, EFloatParseState.GOTEXPCHAR); 105 else static if (state == EFloatParseState.GOTEXPCHAR && s[0]=='-') 106 const int parseExponent = -parseExponent!(s[1..$], 0, EFloatParseState.GOTEXPSIGN); 107 else static if (state == EFloatParseState.GOTEXPCHAR && s[0]=='+') 108 const int parseExponent = parseExponent!(s[1..$], 0, EFloatParseState.GOTEXPSIGN); 109 else static if (state == EFloatParseState.EXPDIG && s[0]=='_') 110 // embedded underscores are allowed after the first digit 111 const int parseExponent = parseExponent!(s[1..$], result, state); 112 else static if (isdigit!( (s[0]) ) ) 113 const int parseExponent = parseExponent!(s[1..$], result*10 + (s[0]-'0'), EFloatParseState.EXPDIG); 114 else { 115 pragma(msg, "Error: Invalid characters found in floating-point literal."); 116 static assert(0); 117 } 118 } 119 120 // parse a %f-style floating-point number, returning the result as a real. 121 // A minus sign is allowed as the first character. 122 // Embedded underscores are allowed any time after the first digit. 123 template parseMantissa(char [] s, EFloatParseState state = EFloatParseState.START, real result=0.0L) 124 { 125 static if (s.length==0) 126 const real parseMantissa = result; 127 else static if (state==EFloatParseState.START && s[0]=='-') 128 const real parseMantissa = - parseMantissa!(s[1..$], EFloatParseState.GOTSIGN, 0.0L); 129 else static if (state==EFloatParseState.WAITDOT && s[0]=='.') 130 const real parseMantissa = result + parseMantissa!(s[1..$], EFloatParseState.WAITEXP, 0.0L); 131 else static if (state!=EFloatParseState.START && state!=EFloatParseState.GOTSIGN && s[0]=='_') 132 // allow embedded underscores, but not before the first digit 133 const real parseMantissa = parseMantissa!(s[1..$], state, result); 134 else static if (isdigit!( (s[0]) )) { 135 static if (state == EFloatParseState.WAITEXP) 136 // fractional part 137 const real parseMantissa = result + (s[0]-'0')/10.0L + parseMantissa!(s[1..$], state, 0.0L) /10.0L; 138 else 139 const real parseMantissa = parseMantissa!(s[1..$], EFloatParseState.WAITDOT, result*10.0L + (s[0]-'0') ); 140 } else static if (state == EFloatParseState.WAITDOT || state == EFloatParseState.WAITEXP) 141 const real parseMantissa = result; 142 else { 143 pragma(msg, "Error: No digits found in floating-point literal."); 144 static assert(0); 145 } 146 } 147 148 template parseMantissaConsumed(char [] s, EFloatParseState state = EFloatParseState.START) 149 { 150 static if (s.length == 0) 151 const int parseMantissaConsumed = 0; 152 else static if (state==EFloatParseState.START && s[0]=='-') 153 const int parseMantissaConsumed = 1 + parseMantissaConsumed!(s[1..$], EFloatParseState.GOTSIGN); 154 else static if (state==EFloatParseState.WAITDOT && s[0]=='.') 155 const int parseMantissaConsumed = 1 + parseMantissaConsumed!(s[1..$], EFloatParseState.WAITEXP); 156 else static if (state!=EFloatParseState.START && state!=EFloatParseState.GOTSIGN && s[0]=='_') 157 // allow embedded underscores, but not before the first digit 158 const int parseMantissaConsumed = 1 + parseMantissaConsumed!(s[1..$], state); 159 else static if (isdigit!( (s[0]) )) 160 const int parseMantissaConsumed = 1 + parseMantissaConsumed!(s[1..$], 161 (state == EFloatParseState.WAITEXP) ? state : EFloatParseState.WAITDOT ); 162 else // found first offending character. 163 //static assert(state != EFloatParseState.START && state!= EFloatParseState.GOTSIGN); 164 const int parseMantissaConsumed = 0; 165 } 166 167 168 // accepts %f or %e format. 169 template atof(char [] s) 170 { 171 const real atof = parseMantissa!(s) * meta.math.pow!(10.0L, 172 parseExponent!(s[parseMantissaConsumed!(s)..$])); 173 } 174 175 // returns number of decimal places in s. 176 // s must be a valid floating-point literal 177 template decimalplaces(char [] s, bool gotDot = false) 178 { 179 static if (s.length==0) 180 const int decimalplaces = 0; 181 else static if ( !gotDot && s[0]=='.') 182 const int decimalplaces = decimalplaces!(s[1..$], true); 183 else static if (s[0]=='_' || !gotDot) { 184 const int decimalplaces = decimalplaces!(s[1..$], gotDot); 185 } else { 186 static if (isdigit!( (s[0]) ) ) 187 const int decimalplaces = 1 + decimalplaces!(s[1..$], true); 188 else // we've finished 189 const int decimalplaces = 0; 190 } 191 } 192 193 194 //------------------------------------------------ 98 195 // Given a number x, where 0<= x <1, 99 196 // returns the first 'maxdigs' digits after the decimal point. 100 197 template afterdec(real x, int maxdigs=real.dig) 101 198 { 102 static if (maxdigs==0 || x==0) const char [] afterdec = "";199 static if (maxdigs==0 || x==0) const char [] afterdec = ""; 103 200 else const char [] afterdec = decimaldigit!(cast(int)(x*10)) ~ afterdec!(x*10-cast(int)(x*10), maxdigs-1); 104 201 } … … 138 235 139 236 version(testmeta) { 140 private import meta.strhacks; 141 142 static assert( streq!(pcvt!(0x1.12345p954L), "0x1.123450p+954") ); 143 static assert( streq!(fcvt!(12.345), "12.345") ); 237 238 239 static assert(parseMantissa!("3.34") == 3.34); 240 static assert(parseMantissa!("-548_29.317_1abc") == -548_29.317_1); 241 static assert( isPositiveZero!(parseMantissa!("0.0"))); 242 static assert( isNegativeZero!(parseMantissa!("-0.0"))); 243 static assert(parseMantissaConsumed!("-31_4.3252e34") == 10); 244 static assert(parseMantissaConsumed!("_23e112") == 0); 245 246 static assert( pcvt!(0x1.12345p954L) == "0x1.123450p+954" ); 247 static assert( fcvt!(12.345) == "12.345" ); 144 248 145 249 static assert( atoi!("3580abc")==3580); 146 250 static assert( atoi!("-0326")==-326); 147 static assert( countleadingdigits!("325827wip")==6); 148 static assert( countleadingdigits!("abc")==0); 149 static assert( sigFigs!("1.2500")==5); 150 static assert( sigFigs!("-380.0")==4); 151 static assert( sigFigs!("0")==1); 152 static assert( sigFigs!("0.0025")==2); 153 static assert( sigFigs!("-1.20e49")==3); 154 } 251 static assert( atoiConsumed!("325827wip")==6); 252 static assert( atoiConsumed!("abc")==0); 253 } trunk/meta/ctype.d
r93 r160 1 /* 2 * Written by Don Clugston 3 * Placed into the Public Domain 4 */ 1 5 /** 2 6 * Simple ASCII character classification functions. Compile-time equivalents of std.ctype 7 * All these functions return false if presented with a non-ASCII character. 3 8 */ 4 9 module meta.ctype; trunk/meta/demangle.d
r126 r160 20 20 { 21 21 static if (str[0] == 'T') { 22 const char [] extractQualifiedNameFromAliasParameter = convertToDotName!(str[2..$], onlyWantLastPart); 22 const char [] extractQualifiedNameFromAliasParameter = 23 extractQualifiedNameFromStatic!(str[2..$], onlyWantLastPart); 24 //convertToDotName!(str[2..$], onlyWantLastPart); 23 25 } else { 24 26 const char [] extractQualifiedNameFromAliasParameter = extractQualifiedNameFromStatic!(demanglegethead!(str[1..$]), onlyWantLastPart); … … 69 71 static if (getDotNameTail!(str[2..$])[0]=='F') { 70 72 // it's a function (not a function pointer) 71 const char [] demangleStatic = demangleFunction!( 73 static if (getParamListTail!(getDotNameTail!(str[2..$])).length==0) { 74 const char [] demangleStatic = demangleFunction!(getDotNameTail!(str[2..$]), 75 convertToDotName!(str[2..$]) ); 76 } else { 77 const char [] demangleStatic = " <<" ~ getParamListTail!(str[2..$]) ~ ">> " ~ demangleFunction!( 72 78 getDotNameTail!(str[2..$]), 73 79 convertToDotName!(str[2..$]) 74 80 ); 75 76 /* 77 demangleReturnValue!(str[1..(str.length)]) ~ " name ("78 ~ demangleParamList!(str[1.. (str.length)]) ~ ")";81 } 82 /* 83 const char [] demangleStatic = demangleReturnValue!(str[2..$]) ~ getDotNameTail!(str[2..$]) 84 ~ demangleParamList!(str[1..$]) ~ ")"; 79 85 */ 80 86 } else { … … 162 168 static if(str.length == 0) { 163 169 const char [] convertToDotName=""; 164 } else static if (isdigit!((str[0])) ) {170 } else static if (isdigit!((str[0])) || (str.length>=4 && str[0..4]=="main") ) { 165 171 static if (onlyWantLastPart && demanglegettail!(str).length > 0) { 166 172 static if (isdigit!((demanglegettail!(str)[0]))) { … … 175 181 ~ .convertToDotName!(demanglegettail!(str), onlyWantLastPart, "."); 176 182 } 177 } 178 else const char [] convertToDotName=""; // ignore the tail 183 } else static if (str[0]=='F') { 184 const char [] convertToDotName = convertToDotName!(getParamListTail!(str), onlyWantLastPart, "()."); 185 } else 186 const char [] convertToDotName="--TAIL["~ str ~ "]"; // ignore the tail 179 187 } 180 188 … … 184 192 const char [] getDotNameTail=""; 185 193 } else static if (isdigit!((str[0]))) { 186 const char [] getDotNameTail = .getDotNameTail!(demanglegettail!(str)); 187 } else const char [] getDotNameTail = str; 194 const char [] getDotNameTail = getDotNameTail!(demanglegettail!(str)); 195 } else static if (str.length>4 && str[0..4]=="main") { 196 const char [] getDotNameTail = getDotNameTail!(str[4..$]); 197 } else { 198 const char [] getDotNameTail = str; 199 } 188 200 } 189 201 190 202 template demanglegethead(char [] str) 191 203 { 192 static if (str.length<=10 || !isdigit!( (str[1]) ) ) { 204 static if (str.length>4 && str[0..4]=="main") { 205 const char [] demanglegethead = "main"; 206 } else static if (str.length<=10 || !isdigit!( (str[1]) ) ) { 193 207 const char [] demanglegethead = str[1..(str[0]-'0' + 1)]; 194 208 } else static if (str.length<=100 || !isdigit!( (str[2]) )) { … … 202 216 template demanglegettail(char [] str) 203 217 { 204 static if (str.length<=10 || !isdigit!( (str[1]) ) ) { 218 static if (str.length>4 && str[0..4]=="main") { 219 const char [] demanglegettail = str[4..$]; 220 } else static if (str.length<=10 || !isdigit!( (str[1]) ) ) { 205 221 const char [] demanglegettail = str[(str[0]-'0'+1) .. $]; 206 222 } else static if (str.length<=100 || !isdigit!( (str[2]) )) { trunk/meta/demo/calcpi.d
r115 r160 7 7 import meta.math; 8 8 import meta.conv; 9 10 import std.math;11 9 12 10 /** real evaluateSeries!(real x, real metafunction!(real y, int n) term) … … 26 24 const real evaluateSeries = sumsofar; 27 25 } else { 28 const real evaluateSeries = .evaluateSeries!(x, term, n+1, sumsofar + term!(x, n));26 const real evaluateSeries = evaluateSeries!(x, term, n+1, sumsofar + term!(x, n)); 29 27 } 30 28 } trunk/meta/demo/tabledemo.d
r126 r160 3 3 // Create a constant array of long or ulong-sized items. Needs to be cast back to 4 4 // long[] or ulong[]. 5 template generateArray (alias entry, int n)5 template generateArrayAsChar(alias entry, int n) 6 6 { 7 7 static if ( entry!(0).sizeof == dchar.sizeof) { 8 8 // int or uint sized items 9 9 static if (n==0) { 10 const dchar [] generateArray = ""d ~ cast(dchar)entry!(n);10 const dchar [] generateArrayAsChar = ""d ~ cast(dchar)entry!(n); 11 11 } else { 12 const dchar[] generateArray = generateArray!(entry, n-1) ~ cast(dchar)entry!(n);12 const dchar[] generateArrayAsChar = generateArrayAsChar!(entry, n-1) ~ cast(dchar)entry!(n); 13 13 } 14 14 } else static if ( entry!(0).sizeof == 2*dchar.sizeof) { 15 15 // long or ulong sized items 16 16 static if (n==0) { 17 const dchar [] generateArray = ""d17 const dchar [] generateArrayAsChar = ""d 18 18 ~ cast(dchar)entry!(n) ~ cast(dchar)(entry!(n)>>>32); 19 19 } else { 20 const dchar[] generateArray = generateArray!(entry, n-1)20 const dchar[] generateArrayAsChar = generateArrayAsChar!(entry, n-1) 21 21 ~ cast(dchar)entry!(n) ~ cast(dchar)(entry!(n)>>32); 22 22 } … … 24 24 } 25 25 26 template generateArray(alias entry, int n) 27 { 28 const typeof(entry!(0)) [] generateArray = cast(typeof(entry!(0)) [])generateArrayAsChar!(entry, n); 29 } 30 31 // The ubiquitous factorial function 32 // 26 33 // Returns correct value for n=0 (factorial!(0)=1). 27 34 template factorial(int n) 28 35 { 29 static if (n<2) const u longfactorial = 1;30 else const u long factorial = n * .factorial!(n-1);36 static if (n<2) const uint factorial = 1; 37 else const uint factorial = n * factorial!(n-1); 31 38 } 32 39 40 // Make an array of all the factorials from 0 to 13 (14!> ulong.max) 41 const smallfactorials = generateArray!(factorial, 13); 33 42 43 44 /+ 34 45 // Make an array of all the factorials from 0 to 20 (21!> ulong.max) 35 46 const ulong [] smallfactorials; 36 37 47 static this() 38 48 { 39 smallfactorials = cast(u long []) generateArray!(factorial, 20);49 smallfactorials = cast(uint []) generateArrayAsChar!(factorial, 20); 40 50 } 41 51 +/ 42 52 import std.stdio; 43 53 44 intmain()54 void main() 45 55 { 46 56 for (int i=0; i<smallfactorials.length; ++i) { 47 57 writefln(i, " ", smallfactorials[i]); 48 58 } 49 return 0;50 59 } 51 52 /+53 // ---------- array literals version -----------54 55 template generateArray(alias entry, int n)56 {57 static if (n==0) {58 const typeof(entry!(0)) [] generateArray = [ entry!(n) ];59 } else {60 const typeof(entry!(0)) [] generateArray = generateArray!(entry, n-1) ~ [ entry!(n) ];61 }62 }63 64 const smallfactorials = generateArray!(factorial, 20);65 +/trunk/meta/math.d
r114 r160 13 13 { 14 14 const bool isnan = (x!<>=0); 15 } 16 17 template isPositiveZero(real x) 18 { 19 static if (x==0 && 1.0L/x > 0) 20 const bool isPositiveZero = true; 21 else 22 const bool isPositiveZero = false; 23 } 24 25 template isNegativeZero(real x) 26 { 27 static if (x==0 && 1.0L/x < 0) 28 const bool isNegativeZero = true; 29 else 30 const bool isNegativeZero = false; 31 } 32 33 version(testmeta) { 34 35 static assert( isPositiveZero!(0.0L)); 36 static assert( !isPositiveZero!(-0.0L)); 37 static assert( !isPositiveZero!(real.nan)); 38 static assert( isNegativeZero!(-0.0L)); 39 static assert( !isNegativeZero!(0.0L)); 15 40 } 16 41 trunk/meta/nameof.d
r126 r160 6 6 // with a method that it does not use the identifier in any way. 7 7 8 module meta. qualifiedname;8 module meta.nameof; 9 9 private import meta.demangle; 10 10 … … 18 18 } 19 19 20 // You can't .mangleof a type, only of an rvalue. But, we can 21 // put the type as a function parameter. 20 // If you take the .mangleof an alias parameter, you are only 21 // told that it is an alias. 22 // So, we put the type as a function parameter. 22 23 template outer(alias B) 23 24 { … … 28 29 // If the identifier is "MyIdentifier" and this module is "QualModule" 29 30 // The return value will be: 30 // "P PF" -- because it's a pointer to a pointer to a function31 // "PF" -- because it's a pointer to a pointer to a function 31 32 // "C" -- because the first parameter is a class 32 33 // "10QualModule" -- the name of this module … … 51 52 52 53 // Get the number of chars at the start relating to the pointer 53 const int pointerstartlength = "P PFC".length + modulemanglelength + "__T5innerT".length;54 const int pointerstartlength = "PFC".length + modulemanglelength + "__T5innerT".length; 54 55 // And the number of chars at the end 55 56 const int pointerendlength = "Z5innerZv".length; 57 } 58 59 template rawmanglednameof(alias A) 60 { 61 const char [] rawmanglednameof = 62 typeof(outer!(A)).mangleof; 56 63 } 57 64 … … 63 70 { 64 71 const char [] manglednameof = 65 typeof( &outer!(A)).mangleof[ pointerstartlength + 1 .. $ - pointerendlength];72 typeof(outer!(A)).mangleof[ pointerstartlength + 1 .. $ - pointerendlength]; 66 73 } 67 74 … … 71 78 // Returns the unqualified name, as a single text string. 72 79 // eg. "myfunc" 73 template basicnameof(alias A)80 template symbolnameof(alias A) 74 81 { 75 const char [] basicnameof = extractQualifiedNameFromAliasParameter!(manglednameof!(A), true);82 const char [] symbolnameof = extractQualifiedNameFromAliasParameter!(manglednameof!(A), true); 76 83 } 77 84 trunk/meta/qualtest.d
r126 r160 1 import meta.qualifiedname; 1 class HaveFun {} 2 3 import meta.nameof; 2 4 3 5 … … 5 7 { 6 8 const char [] describe = 7 \n "Mangled : " ~ manglednameof!(A) ~8 \n "Basic : " ~ basicnameof!(A)9 ~ \n "Qualified: " ~ qualifiednameof!(A) 10 ~ \n "Pretty : " ~ prettynameof!(A);9 \n "Mangled : " ~ manglednameof!(A) 10 ~ \n "Symbol : " ~ symbolnameof!(A) 11 ;// ~ \n "Qualified: " ~ qualifiednameof!(A) 12 // ~ \n "Pretty : " ~ prettynameof!(A); 11 13 } 12 14 … … 100 102 } 101 103 102 pragma(msg, "\n-------\n Local symbols are not yet supported, but there is hope...\n-------");103 104 104 void main() 105 import std.demangle; 106 import std.stdio; 107 108 void fmain() //(int a, int b) 105 109 { 110 106 111 class LocalClass { 112 class InnerClass {} 107 113 void LocalFunc() {} 108 114 } 109 115 pragma(msg, describe!(LocalClass.LocalFunc)); 110 116 117 118 119 writefln(LocalClass.mangleof); 120 writefln(LocalClass.InnerClass.mangleof); 121 122 pragma(msg, "\n-------\n Local symbols are not yet supported, but there is hope...\n-------"); 123 124 mixin ClassTemplate!(int, uint) localMixin; 125 pragma(msg, describe!(localMixin)); 111 126 112 127 int LocalVar; 113 128 mixin getname!(LocalVar); 114 129 pragma(msg, describe!(getname)); 130 // writefln(getname.mangleof); 115 131 116 132 } 133 134 void main() 135 { 136 fmain(); 137 // fmain(3, 4); 138 } trunk/meta/strhacks.d
r115 r160 1 /** Workarounds required for DMD 0.14 31 /** Workarounds required for DMD 0.141 - 0.144. 2 2 * 3 3 * Most of these are only required when they are used as a template value parameter. 4 4 */ 5 5 6 module meta.strhacks; 7 version(none) { 6 8 7 // return true if str1 == str2/8 template streq(char [] str1, char[] str2)9 {10 static if (str1.length!=str2.length) const bool streq=false;11 else static if (str1[0]!=str2[0]) const bool streq=false;12 else static if (str1.length==1) const bool streq=true;13 else const bool streq = .streq!(str1[1..(str1.length)], str2[1..(str2.length)]);14 }15 16 /// converts a single char to a char[]17 template makechar(int c)18 {19 const char [] makechar=x"000102030405060708090a0b0c0d0e0f20 101112131415161718191a1b1c1d1e1f21 202122232425262728292a1b2c2d2e2f22 303132333435363738393a3b3c3d3e3f23 404142434445464748494a4b4c4d4e4f24 505152535455565758595a5b5c5d5e5f25 606162636465666768696a6b6c6d6e6f26 707172737475767778797a7b7c7d7e7f27 808182838485868788898a8b8c8d8e8f28 909192939495969798999a9b9c9d9e9f29 a0a1a2a3a4a5a6a7a8a9aaabacadaeaf30 b0b1b2b3b4b5b6b7b8b9babbbcbdbebf31 c0c1c2c3c4c5c6c7c8c9cacbcccdcecf32 d0d1d2d3d4d5d6d7d8d9dadbdcdddedf33 e0e1e2e3e4e5e6e7e8e9eaebecedeeef34 f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"[c..c+1];35 }36 37 version(testmeta) {38 static assert( streq!("abc", "abc"));39 static assert(!streq!("abc", "axc") );40 static assert(!streq!("abc", "abcd") );41 // static assert(streq!("abcdef", "abc" ~ "def")); // this crashes DMD 0.14242 static assert(streq!("abcdef", concat!("abc", "def")));43 }44 9 45 10 //----------------------------------------------------------------- … … 60 25 61 26 //----------------------------------------------------------------- 62 // Workarounds for DMD 0.141, almost work in DMD 0.143 (need to add parentheses)27 // Workarounds for DMD 0.141, fixed in DMD 0.144 63 28 64 29 /// = str[from..to] … … 85 50 const char getcharat = str[n]; 86 51 } 52 //----------------------------------------------------------------- 53 // Workarounds fixed in DMD 0.145 87 54 55 // return true if str1 == str2 56 template streq(char [] str1, char[] str2) 57 { 58 static if (str1.length!=str2.length) const bool streq=false; 59 else static if (str1[0]!=str2[0]) const bool streq=false; 60 else static if (str1.length==1) const bool streq=true; 61 else const bool streq = .streq!(str1[1..(str1.length)], str2[1..(str2.length)]); 62 } 63 64 65 version(testmeta) { 66 static assert( streq!("abc", "abc")); 67 static assert(!streq!("abc", "axc") ); 68 static assert(!streq!("abc", "abcd") ); 69 // static assert(streq!("abcdef", "abc" ~ "def")); // this crashes DMD 0.142 70 static assert(streq!("abcdef", concat!("abc", "def"))); 71 } 72 73 /// converts a single char to a char[] 74 template makechar(int c) 75 { 76 const char [] makechar=x"000102030405060708090a0b0c0d0e0f 77 101112131415161718191a1b1c1d1e1f 78 202122232425262728292a1b2c2d2e2f 79 303132333435363738393a3b3c3d3e3f 80 404142434445464748494a4b4c4d4e4f 81 505152535455565758595a5b5c5d5e5f 82 606162636465666768696a6b6c6d6e6f 83 707172737475767778797a7b7c7d7e7f 84 808182838485868788898a8b8c8d8e8f 85 909192939495969798999a9b9c9d9e9f 86 a0a1a2a3a4a5a6a7a8a9aaabacadaeaf 87 b0b1b2b3b4b5b6b7b8b9babbbcbdbebf 88 c0c1c2c3c4c5c6c7c8c9cacbcccdcecf 89 d0d1d2d3d4d5d6d7d8d9dadbdcdddedf 90 e0e1e2e3e4e5e6e7e8e9eaebecedeeef 91 f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"[c..c+1]; 92 } 93 94 } trunk/meta/string.d
r115 r160 9 9 static if (str.length==0) const char[] chomp=str; 10 10 else static if (str[str.length - 1]==delimiter) 11 const char [] chomp = .chomp!( str[0..(str.length-1)], delimiter);11 const char [] chomp = chomp!( str[0..$-1], delimiter); 12 12 else const char [] chomp = str; 13 13 } … … 22 22 static if (str.length==n) const int find = -1; 23 23 else static if( c==str[n]) const int find = n; 24 else const int find = .find!(str, c, n + 1);24 else const int find = find!(str, c, n + 1); 25 25 } 26 26 … … 34 34 static if (str.length==n) const int rfind = -1; 35 35 else static if( c==str[str.length - n - 1]) const int rfind = str.length - n - 1; 36 else const int rfind = .rfind!(str, c, n + 1);36 else const int rfind = rfind!(str, c, n + 1); 37 37 } 38 38 … … 44 44 static if (n==0) const char [] repeat=""; 45 45 else static if (n==1) const char [] repeat = str; 46 else const char [] repeat = str ~ .repeat!(str, n-1);46 else const char [] repeat = str ~ repeat!(str, n-1); 47 47 } 48 48 … … 53 53 static assert( -1 == rfind!("not in here either", 'z')); 54 54 static assert( 4 == rfind!("but this is ok", 't')); 55 static assert( streq!(repeat!("abc", 4), "abcabcabcabc"));55 static assert(repeat!("abc", 4) == "abcabcabcabc"); 56 56 }
