Differences From Artifact [004818c087feff6a]:
- File
tricks/tricks.d
- 2010-11-23 07:42:13 - part of checkin [6ac127ddd0] on branch trunk - new evaluator (user: kinaba) [annotate]
To Artifact [cc1b586b87325960]:
- File
tricks/tricks.d
- 2010-11-23 09:36:27 - part of checkin [b97bd4f713] on branch trunk - automatic AST to table encoder (user: kinaba) [annotate]
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 }