// // Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is granted without fee, // provided that the above copyright notice and this permission notice // appear in all source code copies and supporting documentation. The // software is provided "as is" without any express or implied // warranty. #ifndef FCPP_PRE_LAMBDA_DOT_H #define FCPP_PRE_LAMBDA_DOT_H // Some of the stuff here is needed as forward declarations for full.h. // A lot of the stuff here is just handy helpers for lambda.h. #ifdef FCPP_ENABLE_LAMBDA namespace fcpp { // Here is a 'cute' kludge to make "_*_" represent a 'nothing' argument struct PlaceholderForZeroArguments {}; inline PlaceholderForZeroArguments operator*( AutoCurryType, AutoCurryType ) { return PlaceholderForZeroArguments(); } namespace fcpp_lambda { ////////////////////////////////////////////////////////////////////// // A lot of small helpers that will be useful throughout lambda... ////////////////////////////////////////////////////////////////////// template struct ImplicitlyConvertibleHelper { typedef char Small; struct Big { char dummy[2]; }; static Small Test( const U ); static Big Test(...); static const T MakeT(); }; template // T converts to U struct ImplicitlyConvertible { typedef ImplicitlyConvertibleHelper H; //static const int lhs = sizeof(H::Test((const T) H::MakeT())); static const int lhs = sizeof(H::Test((T) H::MakeT())); static const int rhs = sizeof(typename H::Small); static const bool value = (lhs==rhs); }; ////////////////////////////////////////////////////////////////////// // See operator, overloads in lambda.h for namespace explanation namespace exp { struct NIL {}; template struct CONS { H head; T tail; CONS( const H& h ) : head(h) {} CONS( const H& h, const T& t ) : head(h), tail(t) {} }; } using exp::NIL; using exp::CONS; ////////////////////////////////////////////////////////////////////// template struct AppendList; template struct AppendList { typedef LB Result; static inline Result go( const NIL&, const LB& x ) { return x; } }; template struct AppendList,LB> { typedef CONS::Result> Result; static inline Result go( const CONS& x, const LB& y ) { return Result( x.head, AppendList::go(x.tail,y) ); } }; ////////////////////////////////////////////////////////////////////// template struct Length; template <> struct Length { static const int value = 0; }; template struct Length< CONS > { static const int value = 1 + Length::value; }; ////////////////////////////////////////////////////////////////////// // remove every T element from the list A template struct Remove; template struct Remove { typedef NIL Result; }; template struct Remove,T> { typedef CONS::Result> Result; }; template struct Remove,T> { typedef typename Remove::Result Result; }; /////////////////////////////////////////////////////////////////////// // for each element in the list B, remove that element from list A template struct ListDifference; template struct ListDifference { typedef A Result; }; template struct ListDifference > { typedef typename Remove::Result APrime; typedef typename ListDifference::Result Result; }; ////////////////////////////////////////////////////////////////////// template struct RemoveDuplicates; template <> struct RemoveDuplicates { typedef NIL Result; }; template struct RemoveDuplicates > { typedef CONS::Result> Result; }; ////////////////////////////////////////////////////////////////////// struct LEBase {}; // Base type for all LEs ////////////////////////////////////////////////////////////////////// template struct EnsureLEHelper { static inline void go() {} }; template struct EnsureLEHelper {}; template struct EnsureLE { static inline void go() { EnsureLEHelper::value>::go(); } }; ////////////////////////////////////////////////////////////////////// template struct EnsureLEList; template <> struct EnsureLEList { static inline void go() {} }; template struct EnsureLEList > { static inline void go() { EnsureLE::go(); EnsureLEList::go(); } }; ////////////////////////////////////////////////////////////////////// template struct TEPair { static const int my_lv = i; typedef TypeThunk MyTypeThunk; }; // TE is a type environment; a list of TEPair template struct BEPair { static const int my_lv = i; typedef LE MyLE; LE value; BEPair( const LE& x ) : value(x) { EnsureLE::go(); } }; // BE is a value environment; a list of BEPair ////////////////////////////////////////////////////////////////////// template struct AccumFreeVars; template <> struct AccumFreeVars { typedef NIL Result; }; template struct AccumFreeVars > { typedef typename AppendList::Result>::Result Result; }; ////////////////////////////////////////////////////////////////////// // forward decls namespace exp { template struct Value; template struct Call; } ////////////////////////////////////////////////////////////////////// template struct Binder { static const int lvnum = i; LE exp; Binder( const LE& e ) : exp(e) { EnsureLE::go(); } }; ////////////////////////////////////////////////////////////////////// template struct EnsureBinderList; template <> struct EnsureBinderList { static inline void go() {} }; template struct EnsureBinderList,Rest> > { static inline void go() { EnsureBinderList::go(); } }; ////////////////////////////////////////////////////////////////////// template struct Gets { static const int lvnum = i; LE exp; Gets( const LE& e ) : exp(e) { EnsureLE::go(); } }; ////////////////////////////////////////////////////////////////////// template struct AlwaysFirst { typedef X Type; }; ////////////////////////////////////////////////////////////////////// typedef enum { IfNormal, IfTrue, IfFalse } IfKind; ////////////////////////////////////////////////////////////////////// template struct LEifyHelper { typedef T Type; static inline Type go( const T& x ) { return x; } }; template struct LEifyHelper { typedef exp::Value Type; static inline Type go( const T& x ) { return Type(x); } }; template struct LEify { static const bool b = Inherits::value; typedef typename LEifyHelper::Type Type; static inline Type go( const T& x ) { return LEifyHelper::go(x); } }; ////////////////////////////////////////////////////////////////////// // 4 cases: normal value (LE or otherwise), _*_, NIL, CONS template struct LEListify { typedef typename LEify::Type LE; typedef CONS Type; static inline Type go( const T& x ) { return Type( LEify::go(x) ); } }; template <> struct LEListify { typedef NIL Type; static inline Type go( const PlaceholderForZeroArguments& ) { return Type(); } }; template <> struct LEListify { typedef NIL Type; static inline Type go( const NIL& ) { return Type(); } }; template struct LEListify > { typedef CONS Type; static inline Type go( const Type& x ) { EnsureLEList::go(); return x; } }; ////////////////////////////////////////////////////////////////////// template struct BinderListify; template struct BinderListify > { typedef CONS,NIL> Type; static inline Type go( const Binder& b ) { return Type(b); } }; template struct BinderListify > { typedef CONS Type; static inline Type go( const Type& x ) { return x; } }; ////////////////////////////////////////////////////////////////////// template struct BracketCallable { typedef typename LEify::Type ThisLE; typedef exp::Call::Type> Result; static inline Result go( const This& me, const Arg& arg ) { return Result( LEify::go(me), LEListify::go(arg) ); } }; ////////////////////////////////////////////////////////////////////// template struct FilterHelp; template struct FilterHelp > { typedef CONS Result; static inline Result go( const CONS& x ) { return x; } }; template struct FilterHelp > { typedef T Result; static inline Result go( const CONS& x ) { return x.tail; } }; template struct Filter; template struct Filter { typedef NIL Result; static inline Result go( const NIL& x ) { return x; } }; template struct Filter > { static const bool b = PT::template Go::value; typedef FilterHelp > Help; typedef typename Help::Result Result; static inline Result go( const CONS& x ) { return Help::go(x); } }; ////////////////////////////////////////////////////////////////////// template struct Contains; template struct Contains { static const bool value = false; }; template struct Contains,E> { static const bool value = Contains::value; }; template struct Contains,E> { static const bool value = true; }; ////////////////////////////////////////////////////////////////////// template struct Map; template struct Map { typedef NIL Result; static inline Result go( const NIL& x ) { return x; } }; template struct Map > { typedef CONS::Result, typename Map::Result> Result; static inline Result go( const CONS& x ) { return Result( F::template Go::go( x.head ), Map::go( x.tail ) ); } }; ////////////////////////////////////////////////////////////////////// template struct Foldr; template struct Foldr { typedef E Result; }; template struct Foldr > { typedef typename Foldr::Result Tmp; typedef typename Op::template Go::Result Result; }; ////////////////////////////////////////////////////////////////////// } // end namespace fcpp_lambda } // end namespace fcpp #endif #endif