/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file contains default rule implementations #ifndef CXX_DEFAULT_RULES_H #define CXX_DEFAULT_RULES_H #include "mp.h" #include "expression.h" // because we want to reuse binary_op_helper etc #include "expression_traits.h" #include "evaluation_tools.h" namespace flint { namespace rules { // Composite binary operators // These rules implement binary operators by implementing both arguments // separately, then performing the operation on the evaluated types by // instantiating the appropriate rule again. // // Hence to evaluate expressions like a + (b + c), it suffices to write // rules for composition of two immediates. namespace rdetail { template struct can_evaluate_tuple : traits::is_implemented< typename mp::find_evaluation::type, true>::type> { }; template struct should_evaluate_tuple : can_evaluate_tuple { }; template struct should_evaluate_tuple >::type> : mp::false_ { }; template struct binary_should_enable { typedef mp::enable_if::type> > enable; }; } template struct evaluation >::type> { typedef tools::evaluate_n evn_t; typedef typename evn_t::evtup_t evtup_t; typedef typename evn_t::temporaries_t temporaries_t; typedef typename mp::find_evaluation< Op, evtup_t, result_is_temporary>::type rule_t; typedef typename rule_t::return_t return_t; template static void doit(const Data& input, temporaries_t temps, Return* output) { evn_t ev(input, temps); rule_t::doit(ev.gettuple(), empty_tuple(), output); } }; // Automatically invoke binary_expression or commutative_binary_expression namespace rdetail { template struct inverted_binary_expression { typedef commutative_binary_expression wrapped_t; typedef typename wrapped_t::return_t return_t; template static void doit(Return& to, const Expr1& e1, const Expr2& e2) { return wrapped_t::doit(to, e2, e1); } }; template class BE, class Data1, class Op, class Data2> struct binary_expr_helper { typedef typename traits::basetype::type data1_t; typedef typename traits::basetype::type data2_t; typedef BE wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, input.first(), input.second()); } }; } // rdetail template struct evaluation< Op, tuple >, result_is_temporary, 0, typename mp::enable_if< mp::and_< traits::is_immediate::type>, mp::and_< traits::is_immediate::type>, mp::or_< traits::is_implemented::type, Op, typename traits::basetype::type > >, mp::or_< traits::is_implemented::type, Op, typename traits::basetype::type > >, traits::is_implemented::type, Op, typename traits::basetype::type > > > > > > >::type> : mp::if_< traits::is_implemented::type, Op, typename traits::basetype::type > >, rdetail::binary_expr_helper, typename mp::if_< traits::is_implemented::type, Op, typename traits::basetype::type > >, rdetail::binary_expr_helper< commutative_binary_expression, Data1, Op, Data2>, rdetail::binary_expr_helper< rdetail::inverted_binary_expression, Data1, Op, Data2> >::type >::type { }; // Automatically invoke unary_expression template struct evaluation, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< unary_expression::type> > >::type> { typedef unary_expression::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, input.head); } }; // Automatically invoke threeary_expression template struct evaluation > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< threeary_expression::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef threeary_expression::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke fourary_expression template struct evaluation > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< fourary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef fourary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke fiveary_expression template struct evaluation > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< fiveary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef fiveary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke sixary_expression template struct evaluation > > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< sixary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef sixary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke sevenary_expression template struct evaluation > > > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< sevenary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef sevenary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Instantiating temporaries namespace rdetail { template struct evaluated_type_pred { template struct type : mp::equal_types< typename tools::evaluation_helper::type, T> { }; }; } template struct use_default_temporary_instantiation : mp::true_ { }; template struct instantiate_temporaries { static T get(const Expr& e) { return T(); } }; template struct instantiate_temporaries, traits::is_expression, tools::has_subexpr, Expr> > >::type> { static T get(const Expr& e) { return tools::find_subexpr >(e) .create_temporary(); } }; } // rules } // flint #endif