1 /*============================================================================== 2 Copyright (c) 2001-2010 Joel de Guzman 3 Copyright (c) 2004 Daniel Wallin 4 Copyright (c) 2010 Thomas Heller 5 Copyright (c) 2015 John Fletcher 6 7 Distributed under the Boost Software License, Version 1.0. (See accompanying 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 ==============================================================================*/ 10 #ifndef BOOST_PHOENIX_SCOPE_LET_HPP 11 #define BOOST_PHOENIX_SCOPE_LET_HPP 12 13 //#include <boost/assert.hpp> 14 //#include <sstream> 15 #include <boost/phoenix/core/limits.hpp> 16 #include <boost/fusion/include/transform.hpp> 17 #include <boost/fusion/include/as_vector.hpp> 18 #include <boost/phoenix/core/call.hpp> 19 #include <boost/phoenix/core/expression.hpp> 20 #include <boost/phoenix/core/meta_grammar.hpp> 21 #include <boost/phoenix/scope/scoped_environment.hpp> 22 #include <boost/phoenix/scope/local_variable.hpp> 23 #include <boost/phoenix/support/iterate.hpp> 24 #include <boost/phoenix/support/vector.hpp> 25 26 BOOST_PHOENIX_DEFINE_EXPRESSION( 27 (boost)(phoenix)(let_) 28 , (proto::terminal<proto::_>) // Locals 29 (proto::terminal<proto::_>) // Map 30 (meta_grammar) 31 ) 32 33 namespace boost { namespace phoenix 34 { 35 struct let_eval 36 { 37 template <typename Sig> 38 struct result; 39 40 template <typename This, typename Vars, typename Map, typename Expr, typename Context> 41 struct result<This(Vars, Map, Expr, Context)> 42 { 43 typedef 44 typename proto::detail::uncvref< 45 typename result_of::env<Context>::type 46 >::type 47 env_type; 48 typedef 49 typename proto::detail::uncvref< 50 typename result_of::actions<Context>::type 51 >::type 52 actions_type; 53 typedef 54 typename proto::detail::uncvref< 55 typename proto::result_of::value<Vars>::type 56 >::type 57 vars_type; 58 typedef 59 typename proto::detail::uncvref< 60 typename proto::result_of::value<Map>::type 61 >::type 62 map_type; 63 64 typedef 65 typename proto::detail::uncvref<Expr>::type 66 expr_type; 67 68 typedef typename 69 detail::result_of::initialize_locals< 70 vars_type 71 , Context 72 >::type 73 locals_type; 74 75 typedef typename 76 result_of::eval< 77 expr_type 78 , typename result_of::context< 79 scoped_environment< 80 env_type 81 , env_type 82 , locals_type 83 , map_type 84 > 85 , actions_type 86 >::type 87 >::type 88 type; 89 }; 90 91 template <typename Vars, typename Map, typename Expr, typename Context> 92 typename result<let_eval(Vars const&, Map const&, Expr const &, Context const &)>::type const operator ()boost::phoenix::let_eval93 operator()(Vars const & vars, Map, Expr const & expr, Context const & ctx) const 94 { 95 Vars vars_(vars); 96 97 typedef 98 typename proto::detail::uncvref< 99 typename result_of::env<Context>::type 100 >::type 101 env_type; 102 typedef 103 typename proto::detail::uncvref< 104 typename proto::result_of::value<Vars>::type 105 >::type 106 vars_type; 107 typedef 108 typename proto::detail::uncvref< 109 typename proto::result_of::value<Map>::type 110 >::type 111 map_type; 112 113 typedef typename 114 detail::result_of::initialize_locals< 115 vars_type 116 , Context 117 >::type 118 locals_type; 119 120 locals_type locals = initialize_locals(proto::value(vars_), ctx); 121 122 //typedef typename result<let_eval(Vars const&, Map const&, Expr const &, Context const &)>::type result_type; 123 124 scoped_environment< 125 env_type 126 , env_type 127 , locals_type 128 , map_type 129 > 130 env(phoenix::env(ctx), phoenix::env(ctx), locals); 131 132 // Fix for bugs (trial) 133 // The idea is to do something which will not be optimised away. 134 //int vsize = boost::fusion::size(vars); 135 //std::stringstream strm; 136 //strm << vsize << std::endl; 137 //int size = strm.str().length(); 138 //BOOST_ASSERT(size >= 0); 139 return eval(expr, phoenix::context(env, phoenix::actions(ctx))); 140 // typedef is_value<result_type> is_val; 141 //if(is_val::value) This seems always to be true 142 //{ 143 // std::cout << "let result has value type" << std::endl; 144 // } 145 //if (is_val(r) ) std::cout << "let returns val" << std::endl; 146 //std::cout << "result is " << r << std::endl; 147 //return r; 148 } 149 }; 150 151 template <typename Dummy> 152 struct default_actions::when<rule::let_, Dummy> 153 : call<let_eval, Dummy> 154 {}; 155 156 template <typename Locals, typename Map> 157 struct let_actor_gen 158 { let_actor_genboost::phoenix::let_actor_gen159 let_actor_gen(Locals const & locals_) 160 : locals(locals_) 161 {} 162 let_actor_genboost::phoenix::let_actor_gen163 let_actor_gen(let_actor_gen const & o) 164 : locals(o.locals) 165 {} 166 167 template <typename Expr> 168 typename expression::let_< 169 Locals 170 , Map 171 , Expr 172 >::type const operator []boost::phoenix::let_actor_gen173 operator[](Expr const & expr) const 174 { 175 typedef typename expression::let_< 176 Locals 177 , Map 178 , Expr 179 >::type let_type; 180 //typedef is_value<let_type> is_val; 181 182 let_type let_exp = expression::let_<Locals, Map, Expr>::make(locals, Map(), expr); 183 //if(is_val::value) //This seems always to be true 184 //{ 185 // std::cout << "let has value type" << std::endl; 186 //} 187 return let_exp; 188 } 189 190 Locals locals; 191 }; 192 193 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_NAME let_actor_gen 194 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_FUNCTION let 195 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_CONST 196 #include <boost/phoenix/scope/detail/local_gen.hpp> 197 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_NAME 198 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_FUNCTION 199 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_CONST 200 201 template <typename Dummy> 202 struct is_nullary::when<rule::let_, Dummy> 203 : proto::make< 204 mpl::and_< 205 proto::fold< 206 proto::call<proto::_value(proto::_child_c<0>)> 207 , proto::make<mpl::true_()> 208 , proto::make< 209 mpl::and_< 210 proto::_state 211 , proto::call< 212 evaluator( 213 proto::_ 214 , _context 215 , proto::make<proto::empty_env()> 216 ) 217 > 218 >() 219 > 220 > 221 , evaluator( 222 proto::_child_c<2> 223 , proto::call< 224 functional::context( 225 proto::make< 226 mpl::true_() 227 > 228 , proto::make< 229 detail::scope_is_nullary_actions() 230 > 231 ) 232 > 233 , proto::make< 234 proto::empty_env() 235 > 236 ) 237 >() 238 > 239 {}; 240 }} 241 242 #endif 243