From: <ag...@us...> - 2011-10-07 17:47:41
|
Revision: 2535 http://zoolib.svn.sourceforge.net/zoolib/?rev=2535&view=rev Author: agreen Date: 2011-10-07 17:47:35 +0000 (Fri, 07 Oct 2011) Log Message: ----------- Add the notion of a terminal cog, one which returns null when called, but is itself distinguishable and thus usable as a marker. Modified Paths: -------------- trunk/zoolib/source/cxx/zoolib/ZCog.h Modified: trunk/zoolib/source/cxx/zoolib/ZCog.h =================================================================== --- trunk/zoolib/source/cxx/zoolib/ZCog.h 2011-10-07 17:46:46 UTC (rev 2534) +++ trunk/zoolib/source/cxx/zoolib/ZCog.h 2011-10-07 17:47:35 UTC (rev 2535) @@ -21,6 +21,8 @@ #ifndef __ZCog__ #define __ZCog__ 1 +#include "zoolib/ZLog.h" + #include "zoolib/ZCallable.h" #include "zoolib/ZCallable_Bind.h" #include "zoolib/ZCallable_Function.h" @@ -115,12 +117,20 @@ { return sCall(iCallable, iCallable, iParam); } template <class Cog> +bool sCallValidCogChanged(Cog& ioCog, const typename Cog::Param iParam) + { return sCompareAndSet(ioCog, ioCog->Call(ioCog, iParam)); } + +template <class Cog> bool sCallCogChanged(Cog& ioCog, const typename Cog::Param iParam) - { return ioCog && sCompareAndSet(ioCog, ioCog->Call(ioCog, iParam)); } + { return ioCog && sCallValidCogChanged(ioCog, iParam); } template <class Cog> +bool sCallValidCogUnchanged(Cog& ioCog, const typename Cog::Param iParam) + { return not sCompareAndSet(ioCog, ioCog->Call(ioCog, iParam)); } + +template <class Cog> bool sCallCogUnchanged(Cog& ioCog, const typename Cog::Param iParam) - { return not ioCog || not sCompareAndSet(ioCog, ioCog->Call(ioCog, iParam)); } + { return not ioCog || sCallValidCogUnchanged(ioCog, iParam); } // ================================================================================================= #pragma mark - @@ -162,13 +172,51 @@ // ================================================================================================= #pragma mark - -#pragma mark * sEither +#pragma mark * sCog_Term template <class Param> -ZCog<Param> sCogFun_Either(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Term(const ZCog<Param>& iSelf, Param iParam) + { + // Shouldn't ever call this. + ZLOGTRACE(eDebug); + return null; + } + +template <class Param> +const ZCog<Param>& sCog_Term() + { + static const ZCog<Param> spCog = sCallable(spCogFun_Term<Param>); + return spCog; + } + +template <class Param> +const ZCog<Param>& sCog_Term + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable) + { return sCog_Term<Param>(); } + +template <class Param> +bool sIsTerm(const ZCog<Param>& iCog) + { return sCog_Term<Param>() == iCog; } + +// ================================================================================================= +#pragma mark - +#pragma mark * sCog_Either + +template <class Param> +ZCog<Param> spCogFun_Either(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1); template <class Param> +ZCog<Param> spCog_Either + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_Either<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> ZCog<Param> sCog_Either (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) @@ -176,27 +224,51 @@ if (iCallable0) { if (iCallable1) - return sBindR(sCallable(sCogFun_Either<Param>), iCallable0, iCallable1); + return spCog_Either(iCallable0, iCallable1); return iCallable0; } return iCallable1; } template <class Param> -ZCog<Param> sCogFun_Either(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Either(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1) { - if (sCallCogUnchanged(lCog0, iParam)) + ZAssert(lCog0 && lCog1); + + if (sIsTerm(lCog0)) { - if (sCallCogUnchanged(lCog1, iParam)) + if (sIsTerm(lCog1)) + return lCog0; + if ((lCog1 = lCog1->Call(lCog1, iParam))) + return lCog1; + return lCog0; + } + else if (sCallValidCogUnchanged(lCog0, iParam)) + { + if (sIsTerm(lCog1)) + return lCog0; + if (sCallValidCogUnchanged(lCog1, iParam)) return iSelf; + if (not lCog1 || sIsTerm(lCog1)) + return lCog0; + return spCog_Either(lCog0, lCog1); } - else if (lCog1) + else if (not lCog0) { - lCog1 = lCog1->Call(lCog1, iParam); + if (sIsTerm(lCog1)) + return lCog1; + + return lCog1->Call(lCog1, iParam); } - - return sCog_Either(lCog0, lCog1); + else if (sIsTerm(lCog1) || (lCog1 = lCog1->Call(lCog1, iParam))) + { + return spCog_Either(lCog0, lCog1); + } + else + { + return lCog0; + } } template <class Param> @@ -216,34 +288,79 @@ #pragma mark * sCog_Both template <class Param> -ZCog<Param> sCogFun_Both(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Both(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1); template <class Param> +ZCog<Param> spCog_Both + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_Both<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> ZCog<Param> sCog_Both (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) { if (iCallable0 && iCallable1) - return sBindR(sCallable(sCogFun_Both<Param>), iCallable0, iCallable1); + return spCog_Both(iCallable0, iCallable1); return null; } template <class Param> -ZCog<Param> sCogFun_Both(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Both(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1) { - if (sCallCogUnchanged(lCog0, iParam)) + ZAssert(lCog0 && lCog1); + + if (sIsTerm(lCog0)) { - if (sCallCogUnchanged(lCog1, iParam)) + if (not sIsTerm(lCog1) && not lCog1->Call(lCog1, iParam)) + return null; + return lCog0; + } + else if (sCallValidCogUnchanged(lCog0, iParam)) + { + if (sIsTerm(lCog1)) + return lCog1; + if (sCallValidCogUnchanged(lCog1, iParam)) return iSelf; + if (not lCog1) + return null; + if (sIsTerm(lCog1)) + return lCog1; + return spCog_Both(lCog0, lCog1); } - else if (lCog0 && lCog1) + else if (not lCog0) { - lCog1 = lCog1->Call(lCog1, iParam); + return null; } - - return sCog_Both(lCog0, lCog1); + else if (sIsTerm(lCog0)) + { + if (sIsTerm(lCog1)) + return lCog1; + if ((lCog1 = lCog1->Call(lCog1, iParam)) && sIsTerm(lCog1)) + return lCog1; + return null; + } + else if (sIsTerm(lCog1)) + { + return lCog1; + } + else if ((lCog1 = lCog1->Call(lCog1, iParam))) + { + if (sIsTerm(lCog1)) + return lCog1; + return spCog_Both(lCog0, lCog1); + } + else + { + return null; + } } template <class Param> @@ -263,10 +380,20 @@ #pragma mark * sCog_Each template <class Param> -ZCog<Param> sCogFun_Each(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Each(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1); template <class Param> +ZCog<Param> spCog_Each + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_Each<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> ZCog<Param> sCog_Each (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) @@ -274,23 +401,50 @@ if (iCallable0) { if (iCallable1) - return sBindR(sCallable(sCogFun_Each<Param>), iCallable0, iCallable1); + return spCog_Each(iCallable0, iCallable1); return iCallable0; } return iCallable1; } template <class Param> -ZCog<Param> sCogFun_Each(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_Each(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1) { - if (lCog0 && not sCompareAndSet(lCog0, lCog0->Call(lCog0, iParam))) - return iSelf; + ZAssert(lCog0 && lCog1); - if (not lCog0 && lCog1) - lCog1 = lCog1->Call(lCog1, iParam); - - return sCog_Each(lCog0, lCog1); + if (sIsTerm(lCog0)) + { + if (sIsTerm(lCog1)) + return lCog1; + return lCog1->Call(lCog1, iParam); + } + else if (sCallValidCogUnchanged(lCog0, iParam)) + { + if (sIsTerm(lCog1) || sCallValidCogUnchanged(lCog1, iParam)) + return iSelf; + if (not lCog1) + return lCog0; + return spCog_Each(lCog0, lCog1); + } + else if (not lCog0) + { + if (sIsTerm(lCog1)) + return lCog1; + return lCog1->Call(lCog1, iParam); + } + else if (sIsTerm(lCog0)) + { + if (sIsTerm(lCog1)) + return lCog1; + if ((lCog1 = lCog1->Call(lCog1, iParam))) + return spCog_Each(lCog0, lCog1); + return lCog0; + } + else + { + return spCog_Each(lCog0, lCog1); + } } template <class Param> @@ -307,34 +461,155 @@ // ================================================================================================= #pragma mark - +#pragma mark * sCog_FollowedBy + +template <class Param> +ZCog<Param> spCogFun_FollowedBy_First(const ZCog<Param>& iSelf, Param iParam, + ZCog<Param> lCog0, const ZCog<Param>& iCog1); + +template <class Param> +ZCog<Param> spCog_FollowedBy_First + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_FollowedBy_First<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> +ZCog<Param> sCog_FollowedBy_First + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + if (iCallable0) + { + if (iCallable1) + return spCog_FollowedBy_First(iCallable0, iCallable1); + return iCallable0; + } + return null; + } + +template <class Param> +ZCog<Param> spCogFun_FollowedBy_Subsequent(const ZCog<Param>& iSelf, Param iParam, + ZCog<Param> lCog0, const ZCog<Param>& iCog1); + +template <class Param> +ZCog<Param> spCog_FollowedBy_Subsequent + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_FollowedBy_Subsequent<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> +ZCog<Param> spCogFun_FollowedBy_Subsequent(const ZCog<Param>& iSelf, Param iParam, + ZCog<Param> lCog0, const ZCog<Param>& iCog1) + { + ZAssert(lCog0 && iCog1); + if (sCallValidCogUnchanged(lCog0, iParam)) + return iSelf; + + if (lCog0 && not sIsTerm(lCog0)) + return spCog_FollowedBy_Subsequent(lCog0, iCog1); + + if (not sIsTerm(iCog1)) + return iCog1->Call(iCog1, iParam); + + return iCog1; + } + +template <class Param> +ZCog<Param> spCogFun_FollowedBy_First(const ZCog<Param>& iSelf, Param iParam, + ZCog<Param> lCog0, const ZCog<Param>& iCog1) + { + ZAssert(lCog0 && iCog1); + if (sIsTerm(lCog0)) + { + if (sIsTerm(iCog1)) + return iCog1; + return iCog1->Call(iCog1, iParam); + } + else if ((lCog0 = lCog0->Call(lCog0, iParam))) + { + if (sIsTerm(lCog0)) + { + if (sIsTerm(iCog1)) + return iCog1; + return iCog1->Call(iCog1, iParam); + } + return spCog_FollowedBy_Subsequent(lCog0, iCog1); + } + else + { + return null; + } + } + +template <class Param> +ZCog<Param> operator/ + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { return sCog_FollowedBy_First<Param>(iCallable0, iCallable1); } + +template <class Param> +ZCog<Param>& operator/= + (ZCog<Param>& ioCog0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { return ioCog0 = sCog_FollowedBy_First<Param>(ioCog0, iCallable1); } + +// ================================================================================================= +#pragma mark - #pragma mark * sCog_WhileUnchanged // Call second cog so long as the calling the first cog is unchanged. template <class Param> -ZCog<Param> sCogFun_WhileUnchanged(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_WhileUnchanged(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> iCog0, ZCog<Param> iCog1); template <class Param> +ZCog<Param> spCog_WhileUnchanged + (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, + const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) + { + ZAssert(iCallable0 && iCallable1); + static ZMACRO_auto(spCallable, sCallable(spCogFun_WhileUnchanged<Param>)); + return sBindR(spCallable, iCallable0, iCallable1); + } + +template <class Param> ZCog<Param> sCog_WhileUnchanged (const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable0, const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable1) { if (iCallable0 && iCallable1) - return sBindR(sCallable(sCogFun_WhileUnchanged<Param>), iCallable0, iCallable1); + return spCog_WhileUnchanged(iCallable0, iCallable1); return null; } template <class Param> -ZCog<Param> sCogFun_WhileUnchanged(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_WhileUnchanged(const ZCog<Param>& iSelf, Param iParam, ZCog<Param> lCog0, ZCog<Param> lCog1) { - if (sCallCogChanged(lCog0, iParam)) + ZAssert(lCog0 && lCog1); + + if (sIsTerm(lCog0)) return lCog0; - if (sCallCogChanged(lCog1, iParam)) - return sCog_WhileUnchanged(lCog0, lCog1); + if (sCallValidCogChanged(lCog0, iParam)) + return lCog0; + if (sCallValidCogChanged(lCog1, iParam)) + { + if (lCog1 && not sIsTerm(lCog1)) + return spCog_WhileUnchanged(lCog0, lCog1); + return lCog0; + } + return iSelf; } @@ -355,45 +630,67 @@ #pragma mark * sCog_Once template <class Param> -ZCog<Param> sCogFun_Once(const ZCog<Param>& iSelf, Param iParam, - ZCog<Param> iCog) - { - sCallCog(iCog, iParam); - return null; - } - -template <class Param> ZCog<Param> sCog_Once(const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable) - { return sBindR(sCallable(sCogFun_Once<Param>), iCallable); } + { return iCallable * sCog_Term<Param>(); } // ================================================================================================= #pragma mark - -#pragma mark * sCog_Repeat +#pragma mark * sCog_While template <class Param> -ZCog<Param> sCogFun_Repeat(const ZCog<Param>& iSelf, Param iParam, - ZCog<Param> iCog_Init, ZCog<Param> lCog) +ZCog<Param> sCog_While(const ZCog<Param>& iCog_Init, const ZCog<Param>& iCog); + +template <class Param> +ZCog<Param> spCogFun_While(const ZCog<Param>& iSelf, Param iParam, + const ZCog<Param>& iCog_Init, ZCog<Param> lCog) { - if (sCallCogUnchanged(lCog, iParam)) + ZAssert(iCog_Init && lCog); + + if (sCallValidCogUnchanged(lCog, iParam)) return iSelf; - if (lCog) - return sBindR(sCallable(sCogFun_Repeat<Param>), iCog_Init, lCog); + if (not lCog) + return null; - return sBindR(sCallable(sCogFun_Repeat<Param>), iCog_Init, iCog_Init); + if (sIsTerm(lCog)) + return sCog_While(iCog_Init, iCog_Init); + else + return sCog_While(iCog_Init, lCog); } template <class Param> +ZCog<Param> sCog_While(const ZCog<Param>& iCog_Init, const ZCog<Param>& iCog) + { + static ZMACRO_auto(spCallable, sCallable(spCogFun_While<Param>)); + return sBindR(spCallable, iCog_Init, iCog); + } + +template <class Param> +ZCog<Param> sCog_While(const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable) + { return sCog_While<Param>(iCallable, iCallable); } + +template <class Param> +ZCog<Param> operator*(const ZCog<Param>& iCog) + { return sCog_While<Param>(iCog); } + +// ================================================================================================= +#pragma mark - +#pragma mark * sCog_Repeat + +template <class Param> ZCog<Param> sCog_Repeat(const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable) - { return sBindR(sCallable(sCogFun_Repeat<Param>), iCallable, iCallable); } + { return sCog_While(iCallable | sCog_Term(iCallable)); } // ================================================================================================= #pragma mark - #pragma mark * sCog_Repeat (count) template <class Param> -ZCog<Param> sCogFun_Repeat_Count(const ZCog<Param>& iSelf, Param iParam, - size_t iCount, ZCog<Param> iCog_Init, ZCog<Param> lCog) +ZCog<Param> sCog_Repeat(size_t iCount, const ZCog<Param>& iCog_Init, const ZCog<Param>& iCog); + +template <class Param> +ZCog<Param> spCogFun_Repeat_Count(const ZCog<Param>& iSelf, Param iParam, + size_t iCount, const ZCog<Param>& iCog_Init, ZCog<Param> lCog) { if (not iCount) return null; @@ -401,26 +698,33 @@ if (sCallCogUnchanged(lCog, iParam)) return iSelf; - if (lCog) - return sBindR(sCallable(sCogFun_Repeat_Count<Param>), iCount, iCog_Init, lCog); + if (lCog && not sIsTerm(lCog)) + return sCog_Repeat(iCount, iCog_Init, lCog); if (--iCount) - return sBindR(sCallable(sCogFun_Repeat_Count<Param>), iCount, iCog_Init, iCog_Init); + return sCog_Repeat(iCount, iCog_Init, iCog_Init); return null; } template <class Param> +ZCog<Param> sCog_Repeat(size_t iCount, const ZCog<Param>& iCog_Init, const ZCog<Param>& iCog) + { + static ZMACRO_auto(spCallable, sCallable(spCogFun_Repeat_Count<Param>)); + return sBindR(spCallable, iCount, iCog_Init, iCog); + } + +template <class Param> ZCog<Param> sCog_Repeat(size_t iCount, const ZRef<ZCallable<ZCog<Param>(const ZCog<Param>&,Param)> >& iCallable) - { return sBindR(sCallable(sCogFun_Repeat_Count<Param>), iCount, iCallable, iCallable); } + { return sCog_Repeat<Param>(iCount, iCallable, iCallable); } // ================================================================================================= #pragma mark - #pragma mark * sCog_DelayUntil template <class Param> -ZCog<Param> sCogFun_DelayUntil(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_DelayUntil(const ZCog<Param>& iSelf, Param iParam, ZTime iSystemTime) { if (ZTime::sSystem() > iSystemTime) @@ -430,20 +734,26 @@ template <class Param> ZCog<Param> sCog_DelayUntil(ZTime iSystemTime) - { return sBindR(sCallable(sCogFun_DelayUntil<Param>), iSystemTime); } + { + static ZMACRO_auto(spCallable, sCallable(spCogFun_DelayUntil<Param>)); + return sBindR(spCallable, iSystemTime); + } // ================================================================================================= #pragma mark - #pragma mark * sCog_DelayFor template <class Param> -ZCog<Param> sCogFun_DelayFor(const ZCog<Param>& iSelf, Param iParam, +ZCog<Param> spCogFun_DelayFor(const ZCog<Param>& iSelf, Param iParam, double iDelay) { return sCallCog(sCog_DelayUntil<Param>(ZTime::sSystem() + iDelay), iParam); } template <class Param> ZCog<Param> sCog_DelayFor(double iDelay) - { return sBindR(sCallable(sCogFun_DelayFor<Param>), iDelay); } + { + static ZMACRO_auto(spCallable, sCallable(spCogFun_DelayFor<Param>)); + return sBindR(spCallable, iDelay); + } // ================================================================================================= #pragma mark - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |