// Boost Lambda Library -- loops.hpp ----------------------------------------



// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)

// Copyright (C) 2000 Gary Powell (powellg@amazon.com)

// Copyright (c) 2001-2002 Joel de Guzman

//

// Distributed under the Boost Software License, Version 1.0. (See

// accompanying file LICENSE_1_0.txt or copy at

// http://www.boost.org/LICENSE_1_0.txt)

//

// For more information, see www.boost.org



// --------------------------------------------------------------------------



#if !defined(BOOST_LAMBDA_LOOPS_HPP)

#define BOOST_LAMBDA_LOOPS_HPP



#include "boost/lambda/core.hpp"



namespace boost { 

namespace lambda {



// -- loop control structure actions ----------------------



class forloop_action {};

class forloop_no_body_action {};

class whileloop_action {};

class whileloop_no_body_action {};

class dowhileloop_action {};

class dowhileloop_no_body_action {};





// For loop

template <class Arg1, class Arg2, class Arg3, class Arg4>

inline const 

lambda_functor<

  lambda_functor_base<

    forloop_action, 

    tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, 

          lambda_functor<Arg3>, lambda_functor<Arg4> >

  > 

>

for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, 

         const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) { 

  return 

      lambda_functor_base<

        forloop_action, 

        tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, 

              lambda_functor<Arg3>, lambda_functor<Arg4> >

      > 

    ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, 

            lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)

    );

}



// No body case.

template <class Arg1, class Arg2, class Arg3>

inline const 

lambda_functor<

  lambda_functor_base<

    forloop_no_body_action, 

    tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >

  > 

>

for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, 

         const lambda_functor<Arg3>& a3) { 

  return 

      lambda_functor_base<

        forloop_no_body_action, 

        tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, 

              lambda_functor<Arg3> >

      > 

      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, 

               lambda_functor<Arg3> >(a1, a2, a3) );

}



// While loop

template <class Arg1, class Arg2>

inline const 

lambda_functor<

  lambda_functor_base<

    whileloop_action, 

    tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >

  > 

>

while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) { 

  return 

      lambda_functor_base<

        whileloop_action, 

        tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >

      > 

      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));

}



// No body case.

template <class Arg1>

inline const 

lambda_functor<

  lambda_functor_base<

    whileloop_no_body_action, 

    tuple<lambda_functor<Arg1> >

  > 

>

while_loop(const lambda_functor<Arg1>& a1) { 

  return 

      lambda_functor_base<

        whileloop_no_body_action, 

        tuple<lambda_functor<Arg1> >

      > 

      ( tuple<lambda_functor<Arg1> >(a1) );

}





// Do While loop

template <class Arg1, class Arg2>

inline const 

lambda_functor<

  lambda_functor_base<

    dowhileloop_action, 

    tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >

  > 

>

do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {

  return 

      lambda_functor_base<

        dowhileloop_action, 

        tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >

      > 

      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));

}



// No body case.

template <class Arg1>

inline const 

lambda_functor<

  lambda_functor_base<

    dowhileloop_no_body_action, 

    tuple<lambda_functor<Arg1> >

  > 

>

do_while_loop(const lambda_functor<Arg1>& a1) { 

  return 

      lambda_functor_base<

        dowhileloop_no_body_action, 

        tuple<lambda_functor<Arg1> >

      > 

      ( tuple<lambda_functor<Arg1> >(a1));

}





// Control loop lambda_functor_base specializations.



// Specialization for for_loop.

template<class Args>

class 

lambda_functor_base<forloop_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

    for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); 

        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 

        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS))

      

      detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS);

  }

};



// No body case

template<class Args>

class 

lambda_functor_base<forloop_no_body_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

    for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); 

        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 

        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {}

   }

};





// Specialization for while_loop.

template<class Args>

class 

lambda_functor_base<whileloop_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

    while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))

      

      detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);

  }

};



// No body case

template<class Args> 

class 

lambda_functor_base<whileloop_no_body_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

          while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {}

  }

};



// Specialization for do_while_loop.

// Note that the first argument is the condition.

template<class Args>

class 

lambda_functor_base<dowhileloop_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

    do {

      detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);      

    } while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );

  }

};



// No body case

template<class Args>

class 

lambda_functor_base<dowhileloop_no_body_action, Args> {

public:

  Args args;

  template <class T> struct sig { typedef void type; };

public:

  explicit lambda_functor_base(const Args& a) : args(a) {}



  template<class RET, CALL_TEMPLATE_ARGS>

  RET call(CALL_FORMAL_ARGS) const {

          do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );

  }

};



  // The code below is from Joel de Guzman, some name changes etc. 

  // has been made.



///////////////////////////////////////////////////////////////////////////////

//

//  while_composite

//

//      This composite has the form:

//

//          while_(condition)

//          [

//              statement

//          ]

//

//      While the condition (an lambda_functor) evaluates to true, statement

//      (another lambda_functor) is executed. The result type of this is void.

//      Note the trailing underscore after while_.

//

///////////////////////////////////////////////////////////////////////////////

template <typename CondT, typename DoT>

struct while_composite {



    typedef while_composite<CondT, DoT> self_t;



    template <class SigArgs>

    struct sig { typedef void type; };



    while_composite(CondT const& cond_, DoT const& do__)

    :   cond(cond_), do_(do__) {}



    template <class Ret, CALL_TEMPLATE_ARGS>

    Ret call(CALL_FORMAL_ARGS) const

    {

        while (cond.internal_call(CALL_ACTUAL_ARGS))

            do_.internal_call(CALL_ACTUAL_ARGS);

    }



    CondT cond;

    DoT do_;

};



//////////////////////////////////

template <typename CondT>

struct while_gen {



    while_gen(CondT const& cond_)

    :   cond(cond_) {}



    template <typename DoT>

    lambda_functor<while_composite<

        typename as_lambda_functor<CondT>::type,

        typename as_lambda_functor<DoT>::type> >

    operator[](DoT const& do_) const

    {

        typedef while_composite<

            typename as_lambda_functor<CondT>::type,

            typename as_lambda_functor<DoT>::type>

        result;



        return result(

            to_lambda_functor(cond),

            to_lambda_functor(do_));

    }



    CondT cond;

};



//////////////////////////////////

template <typename CondT>

inline while_gen<CondT>

while_(CondT const& cond)

{

    return while_gen<CondT>(cond);

}



///////////////////////////////////////////////////////////////////////////////

//

//  do_composite

//

//      This composite has the form:

//

//          do_

//          [

//              statement

//          ]

//          .while_(condition)

//

//      While the condition (an lambda_functor) evaluates to true, statement

//      (another lambda_functor) is executed. The statement is executed at least

//      once. The result type of this is void. Note the trailing

//      underscore after do_ and the the leading dot and the trailing

//      underscore before and after .while_.

//

///////////////////////////////////////////////////////////////////////////////

template <typename DoT, typename CondT>

struct do_composite {



    typedef do_composite<DoT, CondT> self_t;



    template <class SigArgs>

    struct sig { typedef void type; };



    do_composite(DoT const& do__, CondT const& cond_)

    :   do_(do__), cond(cond_) {}



    template <class Ret, CALL_TEMPLATE_ARGS>

    Ret call(CALL_FORMAL_ARGS) const

    {

        do

            do_.internal_call(CALL_ACTUAL_ARGS);

        while (cond.internal_call(CALL_ACTUAL_ARGS));

    }



    DoT do_;

    CondT cond;

};



////////////////////////////////////

template <typename DoT>

struct do_gen2 {



    do_gen2(DoT const& do__)

    :   do_(do__) {}



    template <typename CondT>

    lambda_functor<do_composite<

        typename as_lambda_functor<DoT>::type,

        typename as_lambda_functor<CondT>::type> >

    while_(CondT const& cond) const

    {

        typedef do_composite<

            typename as_lambda_functor<DoT>::type,

            typename as_lambda_functor<CondT>::type>

        result;



        return result(

            to_lambda_functor(do_),

            to_lambda_functor(cond));

    }



    DoT do_;

};



////////////////////////////////////

struct do_gen {



    template <typename DoT>

    do_gen2<DoT>

    operator[](DoT const& do_) const

    {

        return do_gen2<DoT>(do_);

    }

};



do_gen const do_ = do_gen();



///////////////////////////////////////////////////////////////////////////////

//

//  for_composite

//

//      This statement has the form:

//

//          for_(init, condition, step)

//          [

//              statement

//          ]

//

//      Where init, condition, step and statement are all lambda_functors. init

//      is executed once before entering the for-loop. The for-loop

//      exits once condition evaluates to false. At each loop iteration,

//      step and statement is called. The result of this statement is

//      void. Note the trailing underscore after for_.

//

///////////////////////////////////////////////////////////////////////////////

template <typename InitT, typename CondT, typename StepT, typename DoT>

struct for_composite {



    template <class SigArgs>

    struct sig { typedef void type; };



    for_composite(

        InitT const& init_,

        CondT const& cond_,

        StepT const& step_,

        DoT const& do__)

    :   init(init_), cond(cond_), step(step_), do_(do__) {}



    template <class Ret, CALL_TEMPLATE_ARGS>

    Ret

    call(CALL_FORMAL_ARGS) const

    {

        for (init.internal_call(CALL_ACTUAL_ARGS); cond.internal_call(CALL_ACTUAL_ARGS); step.internal_call(CALL_ACTUAL_ARGS))

            do_.internal_call(CALL_ACTUAL_ARGS);

    }



    InitT init; CondT cond; StepT step; DoT do_; //  lambda_functors

};



//////////////////////////////////

template <typename InitT, typename CondT, typename StepT>

struct for_gen {



    for_gen(

        InitT const& init_,

        CondT const& cond_,

        StepT const& step_)

    :   init(init_), cond(cond_), step(step_) {}



    template <typename DoT>

    lambda_functor<for_composite<

        typename as_lambda_functor<InitT>::type,

        typename as_lambda_functor<CondT>::type,

        typename as_lambda_functor<StepT>::type,

        typename as_lambda_functor<DoT>::type> >

    operator[](DoT const& do_) const

    {

        typedef for_composite<

            typename as_lambda_functor<InitT>::type,

            typename as_lambda_functor<CondT>::type,

            typename as_lambda_functor<StepT>::type,

            typename as_lambda_functor<DoT>::type>

        result;



        return result(

            to_lambda_functor(init),

            to_lambda_functor(cond),

            to_lambda_functor(step),

            to_lambda_functor(do_));

    }



    InitT init; CondT cond; StepT step;

};



//////////////////////////////////

template <typename InitT, typename CondT, typename StepT>

inline for_gen<InitT, CondT, StepT>

for_(InitT const& init, CondT const& cond, StepT const& step)

{

    return for_gen<InitT, CondT, StepT>(init, cond, step);

}



} // lambda

} // boost



#endif // BOOST_LAMBDA_LOOPS_HPP

