8de5b49cdf 2010-11-09 kinaba: /** 8de5b49cdf 2010-11-09 kinaba: * Authors: k.inaba 8de5b49cdf 2010-11-09 kinaba: * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 8de5b49cdf 2010-11-09 kinaba: * 8de5b49cdf 2010-11-09 kinaba: * Common tricks and utilities for programming in D. 8de5b49cdf 2010-11-09 kinaba: */ 8de5b49cdf 2010-11-09 kinaba: module tricks.tricks; 8de5b49cdf 2010-11-09 kinaba: import tricks.test; 8de5b49cdf 2010-11-09 kinaba: import std.array : appender; 8de5b49cdf 2010-11-09 kinaba: import std.format : formattedWrite; 1c01f44f52 2010-11-13 kinaba: import core.exception; 1c01f44f52 2010-11-13 kinaba: import std.traits; 1c01f44f52 2010-11-13 kinaba: import std.typetuple; 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Simple Wrapper for std.format.doFormat 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: string sprintf(string fmt, T...)(T params) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: auto writer = appender!string(); 8de5b49cdf 2010-11-09 kinaba: formattedWrite(writer, fmt, params); 8de5b49cdf 2010-11-09 kinaba: return writer.data; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: unittest 8de5b49cdf 2010-11-09 kinaba: { 7de80acfb8 2010-11-09 kinaba: assert_eq( sprintf!"%s == %04d"("1+2", 3), "1+2 == 0003" ); 7de80acfb8 2010-11-09 kinaba: assert_eq( sprintf!"%2$s == %1$s"("1+2", 5, 8), "5 == 1+2" ); 7de80acfb8 2010-11-09 kinaba: assert_throw!Error( sprintf!"%s%s"(1) ); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Create an exception with automatically completed filename and lineno information 8de5b49cdf 2010-11-09 kinaba: 38fcc662be 2010-11-10 kinaba: ExceptionType genex(ExceptionType, string fn=__FILE__, int ln=__LINE__, T...)(T params) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: static if( T.length > 0 && is(T[$-1] : Throwable) ) 8de5b49cdf 2010-11-09 kinaba: return new ExceptionType(params[0..$-1], fn, ln, params[$-1]); 8de5b49cdf 2010-11-09 kinaba: else 8de5b49cdf 2010-11-09 kinaba: return new ExceptionType(params, fn, ln); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: unittest 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: assert_ne( genex!Exception("msg").file, "" ); 8de5b49cdf 2010-11-09 kinaba: assert_ne( genex!Exception("msg").line, 0 ); 8de5b49cdf 2010-11-09 kinaba: assert_ne( genex!Exception("msg",new Exception("bar")).next, Exception.init ); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Mixing-in the bean constructor for a class 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /*mixin*/ 8de5b49cdf 2010-11-09 kinaba: template SimpleConstructor() 8de5b49cdf 2010-11-09 kinaba: { 38fcc662be 2010-11-10 kinaba: /// member-by-member constructor 8de5b49cdf 2010-11-09 kinaba: static if( is(typeof(super) == Object) || super.tupleof.length==0 ) 8de5b49cdf 2010-11-09 kinaba: this( typeof(this.tupleof) params ) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: static if(this.tupleof.length>0) 8de5b49cdf 2010-11-09 kinaba: this.tupleof = params; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: else 8de5b49cdf 2010-11-09 kinaba: this( typeof(super.tupleof) ps, typeof(this.tupleof) params ) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: // including (only) the direct super class members 8de5b49cdf 2010-11-09 kinaba: // may not always be a desirable choice, but should work for many cases 8de5b49cdf 2010-11-09 kinaba: super(ps); 8de5b49cdf 2010-11-09 kinaba: static if(this.tupleof.length>0) 8de5b49cdf 2010-11-09 kinaba: this.tupleof = params; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: unittest 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: class Temp 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: int x; 8de5b49cdf 2010-11-09 kinaba: string y; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Temp(1,"foo")).x, 1 ); 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Temp(1,"foo")).y, "foo" ); 8de5b49cdf 2010-11-09 kinaba: assert( !__traits(compiles, new Temp) ); 8de5b49cdf 2010-11-09 kinaba: assert( !__traits(compiles, new Temp(1)) ); 8de5b49cdf 2010-11-09 kinaba: assert( !__traits(compiles, new Temp("foo",1)) ); 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: class Tomp : Temp 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: real z; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Tomp(1,"foo",2.5)).x, 1 ); 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Tomp(1,"foo",2.5)).y, "foo" ); 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Tomp(1,"foo",2.5)).z, 2.5 ); 8de5b49cdf 2010-11-09 kinaba: assert( !__traits(compiles, new Tomp(3.14)) ); 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: // shiyo- desu. Don't use in this way. 8de5b49cdf 2010-11-09 kinaba: // Tamp tries to call new Tomp(real) (because it only sees Tomp's members), 8de5b49cdf 2010-11-09 kinaba: // but it fails because Tomp takes (int,string,real). 8de5b49cdf 2010-11-09 kinaba: assert( !__traits(compiles, { 38fcc662be 2010-11-10 kinaba: class Tamp : Tomp { mixin SimpleConstructor; } 8de5b49cdf 2010-11-09 kinaba: }) ); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /*mixin*/ 8de5b49cdf 2010-11-09 kinaba: template SimpleCompare() 8de5b49cdf 2010-11-09 kinaba: { 38fcc662be 2010-11-10 kinaba: override bool opEquals(Object rhs_) const /// member-by-member equality 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: foreach(i,_; this.tupleof) 8de5b49cdf 2010-11-09 kinaba: if( this.tupleof[i] != rhs.tupleof[i] ) 8de5b49cdf 2010-11-09 kinaba: return false; 8de5b49cdf 2010-11-09 kinaba: return true; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 38fcc662be 2010-11-10 kinaba: override hash_t toHash() const /// member-by-member hash 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: hash_t h = 0; 8de5b49cdf 2010-11-09 kinaba: foreach(mem; this.tupleof) 8de5b49cdf 2010-11-09 kinaba: h += typeid(mem).getHash(&mem); 8de5b49cdf 2010-11-09 kinaba: return h; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 38fcc662be 2010-11-10 kinaba: override int opCmp(Object rhs_) const /// member-by-member compare 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: foreach(i,_; this.tupleof) 078444a806 2010-11-13 kinaba: if( this.tupleof[i] != rhs.tupleof[i] ) { 078444a806 2010-11-13 kinaba: auto a = this.tupleof[i]; 078444a806 2010-11-13 kinaba: auto b = rhs.tupleof[i]; 078444a806 2010-11-13 kinaba: return cast(SC_Unqual!(typeof(a)))a < b ? -1 : +1; 078444a806 2010-11-13 kinaba: } 078444a806 2010-11-13 kinaba: // if(auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i])) 078444a806 2010-11-13 kinaba: // return c; 8de5b49cdf 2010-11-09 kinaba: return 0; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: } 078444a806 2010-11-13 kinaba: 078444a806 2010-11-13 kinaba: alias std.traits.Unqual SC_Unqual; 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: unittest 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: class Temp 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: int x; 8de5b49cdf 2010-11-09 kinaba: string y; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleCompare; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert_eq( new Temp(1,"foo"), new Temp(1,"foo") ); 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash ); 8de5b49cdf 2010-11-09 kinaba: assert_ne( new Temp(1,"foo"), new Temp(2,"foo") ); 8de5b49cdf 2010-11-09 kinaba: assert_ne( new Temp(1,"foo"), new Temp(1,"bar") ); 8de5b49cdf 2010-11-09 kinaba: assert_gt( new Temp(1,"foo"), new Temp(1,"bar") ); 8de5b49cdf 2010-11-09 kinaba: assert_lt( new Temp(1,"foo"), new Temp(2,"bar") ); 8de5b49cdf 2010-11-09 kinaba: assert_ge( new Temp(1,"foo"), new Temp(1,"foo") ); 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: class TempDummy 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: int x; 8de5b49cdf 2010-11-09 kinaba: string y; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleCompare; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") ); 8de5b49cdf 2010-11-09 kinaba: assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") ); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Mixing-in a simple toString method 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /*mixin*/ 8de5b49cdf 2010-11-09 kinaba: template SimpleToString() 8de5b49cdf 2010-11-09 kinaba: { 38fcc662be 2010-11-10 kinaba: /// member-by-member toString 8de5b49cdf 2010-11-09 kinaba: override string toString() 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: string str = sprintf!"%s("(typeof(this).stringof); 8de5b49cdf 2010-11-09 kinaba: foreach(i,mem; this.tupleof) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: if(i) str ~= ","; 8de5b49cdf 2010-11-09 kinaba: static if( is(typeof(mem) == std.bigint.BigInt) ) 8de5b49cdf 2010-11-09 kinaba: str ~= std.bigint.toDecimalString(mem); 8de5b49cdf 2010-11-09 kinaba: else 8de5b49cdf 2010-11-09 kinaba: str ~= sprintf!"%s"(mem); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: return str ~ ")"; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: version(unittest) import std.bigint; 8de5b49cdf 2010-11-09 kinaba: unittest 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: class Temp 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: int x; 8de5b49cdf 2010-11-09 kinaba: string y; 8de5b49cdf 2010-11-09 kinaba: BigInt z; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleToString; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: assert_eq( (new Temp(1,"foo",BigInt(42))).toString(), "Temp(1,foo,42)" ); 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /// Everything is in 8de5b49cdf 2010-11-09 kinaba: 8de5b49cdf 2010-11-09 kinaba: /*mixin*/ 8de5b49cdf 2010-11-09 kinaba: template SimpleClass() 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: mixin SimpleConstructor; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleCompare; 8de5b49cdf 2010-11-09 kinaba: mixin SimpleToString; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: /// Simple PatternMatcher 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: /*mixin*/ 1c01f44f52 2010-11-13 kinaba: template SimplePatternMatch() 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: SPM_Return!(PP) match(string fn=__FILE__, size_t ln=__LINE__, PP...)(PP pts) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: foreach(i,_; pts) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: alias pts[i] pt; // bug? pts[i]-->pt do not work 1c01f44f52 2010-11-13 kinaba: static if(__traits(compiles, SPM_isMatchTag(pt))) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: if( auto v = cast(pt.dynamicType)this ) 1c01f44f52 2010-11-13 kinaba: return pt(v.tupleof); 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: else 1c01f44f52 2010-11-13 kinaba: static if(__traits(compiles, SPM_isMatchAny(pt))) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: return pt(); 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: else 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: if( auto v = cast(SPM_PTT!(pt)[0])this ) 1c01f44f52 2010-11-13 kinaba: return pt(v); 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: SPM_throwAssertError(fn, ln, "pattern matching failure"); 1c01f44f52 2010-11-13 kinaba: assert(false); 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: /// Pattern case clause 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: SPM_MatchTag!(T, fn) when(T, alias fn)() 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: SPM_MatchTag!(T, fn) m; 1c01f44f52 2010-11-13 kinaba: return m; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: /// Pattern case clause 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: SPM_MatchAny!(fn) otherwise(alias fn)() 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: SPM_MatchAny!(fn) m; 1c01f44f52 2010-11-13 kinaba: return m; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: // implementation detail of SimplePatternMatch 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: void SPM_throwAssertError(T...)(T t) { core.exception.onAssertErrorMsg(t); } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: struct SPM_MatchTag(T, alias fn) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: alias T dynamicType; 1c01f44f52 2010-11-13 kinaba: auto opCall(typeof(T.tupleof) s) { return fn(s); } 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: struct SPM_MatchAny(alias fn) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: auto opCall() { return fn(); } 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: template SPM_PTT(alias p) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: alias ParameterTypeTuple!(p) SPM_PTT; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: template SPM_Each(P) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: static if(__traits(compiles, SPM_isMatchTag(P.init))) 1c01f44f52 2010-11-13 kinaba: alias typeof(P(P.dynamicType.tupleof)) SPM_Each; 1c01f44f52 2010-11-13 kinaba: else 1c01f44f52 2010-11-13 kinaba: static if(__traits(compiles, SPM_isMatchAny(P.init))) 1c01f44f52 2010-11-13 kinaba: alias typeof(P()) SPM_Each; 1c01f44f52 2010-11-13 kinaba: else 1c01f44f52 2010-11-13 kinaba: alias ReturnType!(P) SPM_Each; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: template SPM_aVoid(T:void, TS...) { alias SPM_aVoid!(TS) SPM_aVoid; } 1c01f44f52 2010-11-13 kinaba: template SPM_aVoid(T, TS...) { alias TypeTuple!(T,SPM_aVoid!(TS)) SPM_aVoid; } 1c01f44f52 2010-11-13 kinaba: template SPM_aVoid() { alias TypeTuple!() SPM_aVoid; } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: template SPM_Return(PP...) 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: alias CommonType!(SPM_aVoid!(staticMap!(SPM_Each, PP))) SPM_Return; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: void SPM_isMatchTag(T,alias fn)(SPM_MatchTag!(T,fn)){} 1c01f44f52 2010-11-13 kinaba: void SPM_isMatchAny(alias fn)(SPM_MatchAny!(fn)){} 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: unittest 1c01f44f52 2010-11-13 kinaba: { 1c01f44f52 2010-11-13 kinaba: static abstract class Base { 1c01f44f52 2010-11-13 kinaba: mixin SimplePatternMatch; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: class D1 : Base { 1c01f44f52 2010-11-13 kinaba: int x; 1c01f44f52 2010-11-13 kinaba: real y; 1c01f44f52 2010-11-13 kinaba: mixin SimpleConstructor; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: class D2 : Base { 1c01f44f52 2010-11-13 kinaba: string s; 1c01f44f52 2010-11-13 kinaba: mixin SimpleConstructor; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: class D3 : Base { 1c01f44f52 2010-11-13 kinaba: int[int]m; 1c01f44f52 2010-11-13 kinaba: mixin SimpleConstructor; 1c01f44f52 2010-11-13 kinaba: } 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: Base d1 = new D1(1, 2.3); 1c01f44f52 2010-11-13 kinaba: Base d2 = new D2("foobar"); 1c01f44f52 2010-11-13 kinaba: Base d3 = new D3(null); (cast(D3)d3).m[1]=10; 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: // normal dispatch 1c01f44f52 2010-11-13 kinaba: assert_eq( d1.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: ), 1); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: ), 2); 1c01f44f52 2010-11-13 kinaba: assert_throw!AssertError( d3.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: )); 1c01f44f52 2010-11-13 kinaba: assert_eq( d3.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: (Base x){return 3;}, 1c01f44f52 2010-11-13 kinaba: ), 3); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: (Base x){return 3;}, 1c01f44f52 2010-11-13 kinaba: ), 2); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: (D1 x){return 1;}, 1c01f44f52 2010-11-13 kinaba: (Base x){return 3;}, 1c01f44f52 2010-11-13 kinaba: (D2 x){return 2;}, 1c01f44f52 2010-11-13 kinaba: ), 3); 1c01f44f52 2010-11-13 kinaba: 1c01f44f52 2010-11-13 kinaba: // member decomposing match 1c01f44f52 2010-11-13 kinaba: assert_eq( d1.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: when!(D3, (x){return x[1];}), 1c01f44f52 2010-11-13 kinaba: ), 3); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: when!(D3, (x){return x[1];}), 1c01f44f52 2010-11-13 kinaba: ), 6); 1c01f44f52 2010-11-13 kinaba: assert_eq( d3.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: when!(D3, (x){return x[1];}), 1c01f44f52 2010-11-13 kinaba: ), 10); 1c01f44f52 2010-11-13 kinaba: assert_throw!AssertError( d3.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: )); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: otherwise!({return 999;}), 1c01f44f52 2010-11-13 kinaba: ), 6); 1c01f44f52 2010-11-13 kinaba: assert_eq( d2.match( 1c01f44f52 2010-11-13 kinaba: when!(D1, (x, y){return x + cast(int)y;}), 1c01f44f52 2010-11-13 kinaba: otherwise!({return 999;}), 1c01f44f52 2010-11-13 kinaba: when!(D2, (x){return x.length;}), 1c01f44f52 2010-11-13 kinaba: ), 999); 8de5b49cdf 2010-11-09 kinaba: }