Diff
Not logged in

Differences From Artifact [004818c087feff6a]:

To Artifact [cc1b586b87325960]:


98 assert( !__traits(compiles, { 98 assert( !__traits(compiles, { 99 class Tamp : Tomp { mixin SimpleConstructor; } 99 class Tamp : Tomp { mixin SimpleConstructor; } 100 }) ); 100 }) ); 101 } 101 } 102 102 103 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 103 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 104 104 > 105 template SimpleToHash() > 106 { > 107 override hash_t toHash() const /// member-by-member hash > 108 { > 109 hash_t h = 0; > 110 foreach(mem; this.tupleof) > 111 h += typeid(mem).getHash(&mem); > 112 return h; > 113 } > 114 } > 115 > 116 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class > 117 105 /*mixin*/ 118 /*mixin*/ 106 template SimpleCompare() 119 template SimpleCompare() 107 { 120 { 108 override bool opEquals(Object rhs_) const /// member-by-member equality 121 override bool opEquals(Object rhs_) const /// member-by-member equality 109 { 122 { 110 if( auto rhs = cast(typeof(this))rhs_ ) 123 if( auto rhs = cast(typeof(this))rhs_ ) 111 { 124 { ................................................................................................................................................................................ 113 if( this.tupleof[i] != (cast(const)rhs).tupleof[ 126 if( this.tupleof[i] != (cast(const)rhs).tupleof[ 114 return false; 127 return false; 115 return true; 128 return true; 116 } 129 } 117 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 130 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 118 } 131 } 119 132 120 override hash_t toHash() const /// member-by-member hash | 133 mixin SimpleToHash; 121 { < 122 hash_t h = 0; < 123 foreach(mem; this.tupleof) < 124 h += typeid(mem).getHash(&mem); < 125 return h; < 126 } < 127 134 128 override int opCmp(Object rhs_) const /// member-by-member compare 135 override int opCmp(Object rhs_) const /// member-by-member compare 129 { 136 { 130 if( auto rhs = cast(typeof(this))rhs_ ) 137 if( auto rhs = cast(typeof(this))rhs_ ) 131 { 138 { 132 foreach(i,_; this.tupleof) 139 foreach(i,_; this.tupleof) 133 if( this.tupleof[i] != (cast(const)rhs).tupleof[ 140 if( this.tupleof[i] != (cast(const)rhs).tupleof[ ................................................................................................................................................................................ 215 template SimpleClass() 222 template SimpleClass() 216 { 223 { 217 mixin SimpleConstructor; 224 mixin SimpleConstructor; 218 mixin SimpleCompare; 225 mixin SimpleCompare; 219 mixin SimpleToString; 226 mixin SimpleToString; 220 } 227 } 221 228 222 /// Simple PatternMatcher < 223 < 224 /*mixin*/ < 225 template SimplePatternMatch() < 226 { < 227 SPM_Return!(PP) match(string fn=__FILE__, size_t ln=__LINE__, PP...)(PP < 228 { < 229 foreach(i,_; pts) < 230 { < 231 alias pts[i] pt; // bug? pts[i]-->pt do not work < 232 static if(__traits(compiles, SPM_isMatchTag(pt))) < 233 { < 234 if( auto v = cast(pt.dynamicType)this ) < 235 return pt(v.tupleof); < 236 } < 237 else < 238 static if(__traits(compiles, SPM_isMatchAny(pt))) < 239 { < 240 return pt(); < 241 } < 242 else < 243 { < 244 if( auto v = cast(SPM_PTT!(pt)[0])this ) < 245 return pt(v); < 246 } < 247 } < 248 SPM_throwAssertError(fn, ln, "pattern matching failure"); < 249 assert(false); < 250 } < 251 } < 252 < 253 /// Pattern case clause < 254 < 255 SPM_MatchTag!(T, fn) when(T, alias fn)() < 256 { < 257 SPM_MatchTag!(T, fn) m; < 258 return m; < 259 } < 260 < 261 /// Pattern case clause < 262 < 263 SPM_MatchAny!(fn) otherwise(alias fn)() < 264 { < 265 SPM_MatchAny!(fn) m; < 266 return m; < 267 } < 268 < 269 // implementation detail of SimplePatternMatch < 270 < 271 void SPM_throwAssertError(T...)(T t) { core.exception.onAssertErrorMsg(t); } < 272 < 273 struct SPM_MatchTag(T, alias fn) < 274 { < 275 alias T dynamicType; < 276 auto opCall(typeof(T.tupleof) s) { return fn(s); } < 277 } < 278 < 279 struct SPM_MatchAny(alias fn) < 280 { < 281 auto opCall() { return fn(); } < 282 } < 283 < 284 template SPM_PTT(alias p) < 285 { < 286 alias ParameterTypeTuple!(p) SPM_PTT; < 287 } < 288 < 289 template SPM_Each(P) < 290 { < 291 static if(__traits(compiles, SPM_isMatchTag(P.init))) < 292 alias typeof(P(P.dynamicType.tupleof)) SPM_Each; < 293 else < 294 static if(__traits(compiles, SPM_isMatchAny(P.init))) < 295 alias typeof(P()) SPM_Each; < 296 else < 297 alias ReturnType!(P) SPM_Each; < 298 } < 299 < 300 template SPM_aVoid(T:void, TS...) { alias SPM_aVoid!(TS) SPM_aVoid; } < 301 template SPM_aVoid(T, TS...) { alias TypeTuple!(T,SPM_aVoid!(TS)) SPM_aVoid; } < 302 template SPM_aVoid() { alias TypeTuple!() SPM_aVoid; } < 303 < 304 template SPM_Return(PP...) < 305 { < 306 alias CommonType!(SPM_aVoid!(staticMap!(SPM_Each, PP))) SPM_Return; < 307 } < 308 < 309 void SPM_isMatchTag(T,alias fn)(SPM_MatchTag!(T,fn)){} < 310 void SPM_isMatchAny(alias fn)(SPM_MatchAny!(fn)){} < 311 < 312 unittest < 313 { < 314 static abstract class Base { < 315 mixin SimplePatternMatch; < 316 } < 317 class D1 : Base { < 318 int x; < 319 real y; < 320 mixin SimpleConstructor; < 321 } < 322 class D2 : Base { < 323 string s; < 324 mixin SimpleConstructor; < 325 } < 326 class D3 : Base { < 327 int[int] m; < 328 mixin SimpleConstructor; < 329 } < 330 < 331 Base d1 = new D1(1, 2.3); < 332 Base d2 = new D2("foobar"); < 333 Base d3 = new D3(null); (cast(D3)d3).m[1]=10; < 334 < 335 // normal dispatch < 336 assert_eq( d1.match( < 337 (D1 x){return 1;}, < 338 (D2 x){return 2;} < 339 ), 1); < 340 assert_eq( d2.match( < 341 (D1 x){return 1;}, < 342 (D2 x){return 2;} < 343 ), 2); < 344 assert_throw!AssertError( d3.match( < 345 (D1 x){return 1;}, < 346 (D2 x){return 2;} < 347 )); < 348 assert_eq( d3.match( < 349 (D1 x){return 1;}, < 350 (D2 x){return 2;}, < 351 (Base x){return 3;} < 352 ), 3); < 353 assert_eq( d2.match( < 354 (D1 x){return 1;}, < 355 (D2 x){return 2;}, < 356 (Base x){return 3;} < 357 ), 2); < 358 assert_eq( d2.match( < 359 (D1 x){return 1;}, < 360 (Base x){return 3;}, < 361 (D2 x){return 2;} < 362 ), 3); < 363 < 364 // member decomposing match < 365 assert_eq( d1.match( < 366 when!(D1, (x, y){return x + cast(int)y;}), < 367 when!(D2, (x){return x.length;}), < 368 when!(D3, (x){return x[1];}) < 369 ), 3); < 370 assert_eq( d2.match( < 371 when!(D1, (x, y){return x + cast(int)y;}), < 372 when!(D2, (x){return x.length;}), < 373 when!(D3, (x){return x[1];}) < 374 ), 6); < 375 assert_eq( d3.match( < 376 when!(D1, (x, y){return x + cast(int)y;}), < 377 when!(D2, (x){return x.length;}), < 378 when!(D3, (x){return x[1];}) < 379 ), 10); < 380 assert_throw!AssertError( d3.match( < 381 when!(D1, (x, y){return x + cast(int)y;}), < 382 when!(D2, (x){return x.length;}) < 383 )); < 384 assert_eq( d2.match( < 385 when!(D1, (x, y){return x + cast(int)y;}), < 386 when!(D2, (x){return x.length;}), < 387 otherwise!({return 999;}) < 388 ), 6); < 389 assert_eq( d2.match( < 390 when!(D1, (x, y){return x + cast(int)y;}), < 391 otherwise!({return 999;}), < 392 when!(D2, (x){return x.length;}) < 393 ), 999); < 394 } < 395 < 396 /// Will be used for dynamic overload resolution pattern 229 /// Will be used for dynamic overload resolution pattern 397 230 398 template firstParam(T) 231 template firstParam(T) 399 { 232 { 400 alias ParameterTypeTuple!(T)[0] firstParam; 233 alias ParameterTypeTuple!(T)[0] firstParam; 401 } 234 }