File Annotation
Not logged in
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;
1c01f44f52 2010-11-13        kinaba: import core.exception;
515502e8d1 2010-11-20        kinaba: import std.array  : appender;
515502e8d1 2010-11-20        kinaba: import std.format : formattedWrite;
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)
515502e8d1 2010-11-20        kinaba: 				if( this.tupleof[i] != (cast(const)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)
515502e8d1 2010-11-20        kinaba: 				if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) {
515502e8d1 2010-11-20        kinaba: 					auto a = (cast(SC_Unqual!(typeof(this)))this).tupleof[i];
078444a806 2010-11-13        kinaba: 					auto b =  rhs.tupleof[i];
515502e8d1 2010-11-20        kinaba: 					return a < b ? -1 : +1;
078444a806 2010-11-13        kinaba: 				}
515502e8d1 2010-11-20        kinaba: // not work well for structures???????
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 {
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;},
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        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;}),
515502e8d1 2010-11-20        kinaba: 		when!(D2, (x){return x.length;})
1c01f44f52 2010-11-13        kinaba: 	), 999);
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: /// Will be used for dynamic overload resolution pattern
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: template firstParam(T)
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	alias ParameterTypeTuple!(T)[0] firstParam;
8de5b49cdf 2010-11-09        kinaba: }