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 98 assert( !__traits(compiles, {
99 99 class Tamp : Tomp { mixin SimpleConstructor; }
100 100 }) );
101 101 }
102 102
103 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 118 /*mixin*/
106 119 template SimpleCompare()
107 120 {
108 121 override bool opEquals(Object rhs_) const /// member-by-member equality
109 122 {
110 123 if( auto rhs = cast(typeof(this))rhs_ )
111 124 {
................................................................................
113 126 if( this.tupleof[i] != (cast(const)rhs).tupleof[i] )
114 127 return false;
115 128 return true;
116 129 }
117 130 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
118 131 }
119 132
120 - override hash_t toHash() const /// member-by-member hash
121 - {
122 - hash_t h = 0;
123 - foreach(mem; this.tupleof)
124 - h += typeid(mem).getHash(&mem);
125 - return h;
126 - }
133 + mixin SimpleToHash;
127 134
128 135 override int opCmp(Object rhs_) const /// member-by-member compare
129 136 {
130 137 if( auto rhs = cast(typeof(this))rhs_ )
131 138 {
132 139 foreach(i,_; this.tupleof)
133 140 if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) {
................................................................................
215 222 template SimpleClass()
216 223 {
217 224 mixin SimpleConstructor;
218 225 mixin SimpleCompare;
219 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 pts)
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 229 /// Will be used for dynamic overload resolution pattern
397 230
398 231 template firstParam(T)
399 232 {
400 233 alias ParameterTypeTuple!(T)[0] firstParam;
401 234 }