/*
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