413: Enhance error handling in mlc::switch_.

https://svn.lrde.epita.fr/svn/oln/trunk/metalic Index: ChangeLog from Thierry Geraud <theo@lrde.epita.fr> Enhance error handling in mlc::switch_. * tests/switch.cc: New file. * mlc/switch.hh (case_true, case_false): New classes. (case_type): New typedef in classes. (case_, switch_): Modify error handling. mlc/switch.hh | 107 +++++++++++++++++++++++++++++++++++++++++++++++--------- tests/switch.cc | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 17 deletions(-) Index: tests/switch.cc --- tests/switch.cc (revision 0) +++ tests/switch.cc (revision 0) @@ -0,0 +1,78 @@ +#include <mlc/is_a.hh> +#include <mlc/switch.hh> + + +struct test; + + +namespace mlc +{ + + template <class T> + struct case_ <test, T, 1> : public where_< mlc_is_a(T, short) > + { + typedef float ret; + }; + + template <class T> + struct case_ <test, T, 2> : public where_< mlc_is_a(T, int) > + { + typedef double ret; + }; + + +// // ok + +// template <class T> +// struct case_ <test, T, 3> : public where_< mlc_is_a(T, char) > +// { +// typedef int ret; +// }; + + +// // ko + +// template <class T> +// struct case_ <test, T, 3> : public where_< mlc_is_a(T, char) > +// { +// typedef not_found ret; +// }; + +// template <class T> +// struct case_ <test, T, 3> : public where_< mlc_is_a(T, char) > +// { +// }; + +// template <class T> +// struct case_ <test, T, 3> +// { +// typedef int ret; +// }; + +// template <class T> +// struct default_case_ <test, T> : public where_< mlc::true_ > +// { +// typedef int ret; +// }; + +// template <class T> +// struct default_case_ <test, T> +// { +// }; + + +} // end of namespace mlc + + +template <class T> +void print() +{ + int tmp; +} + + + +int main() +{ + print< mlc::switch_<test, char>::ret >(); +} Index: mlc/switch.hh --- mlc/switch.hh (revision 412) +++ mlc/switch.hh (working copy) @@ -34,6 +34,7 @@ # include <mlc/implies.hh> # include <mlc/comma.hh> # include <mlc/cmp.hh> +# include <mlc/if.hh> namespace mlc @@ -41,11 +42,36 @@ // FIXME: doc + namespace internal + { + struct case_true {}; + struct case_false {}; + + } // end of namespace mlc::internal + + template <typename bexpr> - struct where_ : public bexpr::eval + struct where_ : public mlc_if_( typename bexpr::eval, + internal::case_true, + internal::case_false ) { }; +// template <typename bexpr> +// struct where_ : public where_<typename bexpr::eval> +// { +// }; + +// template <> +// struct where_<true_> +// { +// }; + +// template <> +// struct where_<false_> +// { +// }; + // FIXME: doc @@ -57,6 +83,7 @@ { }; + template <typename context, typename data> struct case_ <context, data, 0>; @@ -73,7 +100,9 @@ { struct A_case_STATEMENT_IN_mlc_switch_SHOULD_DERIVE_FROM_mlc_where_; struct A_default_case_STATEMENT_IN_mlc_switch_SHOULD_NOT_DERIVE_FROM_mlc_where_; - struct RESULT_NOT_FOUND; + struct SWITCH_DOES_NOT_HAVE_A_CASE_FOR_YOUR_DATA; + struct RESULT_IS_NOT_FOUND_IN_default_case_; + template <unsigned i> struct RESULT_IS_NOT_FOUND_IN_case_; } // end of namespace mlc::ERROR @@ -87,81 +116,124 @@ struct handle_case_; + // impossible situation + template <typename context, typename data, unsigned i> struct handle_case_ <context, data, i, 1, 1>; + + + // default case + template <typename context, typename data> struct handle_default_case_ + : private assert_< implies_< mlc_is_not_a(mlc_comma_1(default_case_<context, data>), undefined), mlc_is_not_a(mlc_comma_1(default_case_<context, data>), where_) >, - ERROR::A_default_case_STATEMENT_IN_mlc_switch_SHOULD_NOT_DERIVE_FROM_mlc_where_ > + ERROR::A_default_case_STATEMENT_IN_mlc_switch_SHOULD_NOT_DERIVE_FROM_mlc_where_ >, + + private assert_< implies_< mlc_is_not_a(mlc_comma_1(default_case_<context, data>), + undefined), + neq_<mlc_ret(mlc_comma_1(default_case_<context, data>)), + not_found> >, + ERROR::RESULT_IS_NOT_FOUND_IN_default_case_ > + { - typedef mlc_ret( mlc_comma_1(default_case_<context, data>) ) ret; + typedef default_case_<context, data> current_t; + typedef typename mlc::if_<mlc_is_a(current_t, undefined), + none, + current_t>::ret case_type; + typedef mlc_ret(current_t) ret; }; + + // there is no more user-defined cases - // so go to the default case + // so go to the default case (the last case handled here) + template <typename context, typename data, unsigned i> struct handle_case_ <context, data, i, 0, 0> + : private assert_< implies_< mlc_is_not_a(mlc_comma_2(case_<context, data, i>), undefined), mlc_is_a(mlc_comma_2(case_<context, data, i>), where_) >, ERROR::A_case_STATEMENT_IN_mlc_switch_SHOULD_DERIVE_FROM_mlc_where_ > + { - typedef mlc_ret( mlc_comma_1(handle_default_case_<context, data>) ) ret; + typedef handle_default_case_<context, data> last_t; + typedef typename last_t::case_type case_type; + typedef typename last_t::ret ret; }; // current case is the one + template <typename context, typename data, unsigned i> struct handle_case_ <context, data, i, 1, 0> + : private assert_< or_< mlc_is_a(mlc_comma_2(case_<context, data, i>), where_), mlc_is_a(mlc_comma_2(case_<context, data, i>), undefined) >, - ERROR::A_case_STATEMENT_IN_mlc_switch_SHOULD_DERIVE_FROM_mlc_where_ > + ERROR::A_case_STATEMENT_IN_mlc_switch_SHOULD_DERIVE_FROM_mlc_where_ >, + + private assert_< implies_< mlc_is_not_a(mlc_comma_2(case_<context, data, i>), + undefined), + neq_<mlc_ret(mlc_comma_2(case_<context, data, i>)), + not_found> >, + ERROR::RESULT_IS_NOT_FOUND_IN_case_<i> > + { - typedef mlc_ret( mlc_comma_2(case_<context, data, i>) ) ret; + typedef case_<context, data, i> case_type; + typedef mlc_ret(case_type) ret; }; + // current case is not the one // so go to the next case + template <typename context, typename data, unsigned i> struct handle_case_ <context, data, i, 0, 1> + : private assert_< or_< mlc_is_a(mlc_comma_2(case_<context, data, i>), where_), mlc_is_a(mlc_comma_2(case_<context, data, i>), undefined) >, ERROR::A_case_STATEMENT_IN_mlc_switch_SHOULD_DERIVE_FROM_mlc_where_ > + { typedef handle_case_ < context, data, i+1, mlc_is_a(mlc_comma_2(case_<context, data, i+1>), - true_)::value, + internal::case_true)::value, mlc_is_a(mlc_comma_2(case_<context, data, i+1>), - false_)::value > next_t; + internal::case_false)::value > next_t; + typedef typename next_t::case_type case_type; typedef typename next_t::ret ret; }; + // switch_ + template <typename context, typename data> struct switch_ { - typedef typename internal::handle_case_ < context, data, 1, + typedef internal::handle_case_ < context, data, 1, mlc_is_a(mlc_comma_2(case_<context, data, 1>), - true_)::value, + internal::case_true)::value, mlc_is_a(mlc_comma_2(case_<context, data, 1>), - false_)::value - >::ret ret; + internal::case_false)::value > handle_t; + typedef typename handle_t::case_type case_type; + typedef typename handle_t::ret ret; }; @@ -173,10 +245,11 @@ template <typename context, typename data> struct switch_ - : private assert_< neq_<typename internal::switch_<context, data>::ret, - not_found>, - ERROR::RESULT_NOT_FOUND > + : private assert_< neq_< mlc_comma_1(typename internal::switch_<context, data>::case_type), + none >, + ERROR::SWITCH_DOES_NOT_HAVE_A_CASE_FOR_YOUR_DATA > { + typedef typename internal::switch_<context, data>::case_type case_type; typedef typename internal::switch_<context, data>::ret ret; };
participants (1)
-
Thierry Geraud