Commit b14a413a authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Disambiguate Boolean value types and Boolean expression types.

- tests/ret.cc: Update.
- mlc/ret.hh: Fix missing include.

The Boolean value classes are re-written and internal::value_ is
removed; this class was too ambiguous since precise types, e.g.,
int_<i>, are provided and it was weirdly located in the value class
hierarchy.

- mlc/bool.hh (bool_<true>, bool_<false>): Merge those
specializations into the single and once for all written class
bool_<b>.
(bool_<true>::is_true): Remove since this mark is now factored
in the base class bexpr_is_<b>.
(bool_<b>): Add inheritance so that a Boolean value can be
considered as a Boolean expression type.
(internal::value_<bool, b>): Remove this specialization since
the class internal::value_ is also removed.
(logic.hh): Remove inclusion.
(mlc_bool): Move to...

The Boolean expression types are now handled by special classes.
Yet mlc::true_ and mlc::false_ remain expression types in addition
of value types.

- mlc/bexpr.hh: ...this file.  This macro only applies on Boolean
expression types.
(bexpr_): Remove this obsolete wrapper.
(bexpr_is_<b>): New base class with its couple of specializations
which act as a replacement for bool_<b> for expression types.
(internal::bool_of_): Replace the meta-code for mlc_bool.

Those changes induce a lot of updates described below.

- mlc/pair.hh: Update includes.
- mlc/logic.hh: Update.  Instead of deriving from bool_<b>
Boolean expression types now derive from bexpr_is_<b>.
(and_list_, or_list_): Comment to postpone updating while keeping
code compile.
- mlc/implies.hh: Update inheritance.
- mlc/if.hh: Update includes and add assertion.
- mlc/assert.hh: Update includes.
- mlc/valist.hh: Likewise.
- mlc/wrap.hh: Remove obsolete code.
- mlc/is_a.hh: Update inheritance.
(bexpr_): Replace by wrap_.
- mlc/case.hh: Update.  Now use mlc_bool instead of ::value.
- mlc/cmp.hh: Update inheritance.
(eq_::ensure): Remove this obsolete feature.
- mlc/value.hh: Move sub-classes of value to...
- mlc/int.hh, mlc/char.hh: ...these new files.
- mlc/values.hh: New file that includes the whole value types material.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@429 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 7a02f045
2006-03-21 Thierry Geraud <theo@lrde.epita.fr>
Disambiguate Boolean value types and Boolean expression types.
* tests/ret.cc: Update.
* mlc/ret.hh: Fix missing include.
The Boolean value classes are re-written and internal::value_ is
removed; this class was too ambiguous since precise types, e.g.,
int_<i>, are provided and it was weirdly located in the value class
hierarchy.
* mlc/bool.hh (bool_<true>, bool_<false>): Merge those
specializations into the single and once for all written class
bool_<b>.
(bool_<true>::is_true): Remove since this mark is now factored
in the base class bexpr_is_<b>.
(bool_<b>): Add inheritance so that a Boolean value can be
considered as a Boolean expression type.
(internal::value_<bool, b>): Remove this specialization since
the class internal::value_ is also removed.
(logic.hh): Remove inclusion.
(mlc_bool): Move to...
The Boolean expression types are now handled by special classes.
Yet mlc::true_ and mlc::false_ remain expression types in addition
of value types.
* mlc/bexpr.hh: ...this file. This macro only applies on Boolean
expression types.
(bexpr_): Remove this obsolete wrapper.
(bexpr_is_<b>): New base class with its couple of specializations
which act as a replacement for bool_<b> for expression types.
(internal::bool_of_): Replace the meta-code for mlc_bool.
Those changes induce a lot of updates described below.
* mlc/pair.hh: Update includes.
* mlc/logic.hh: Update. Instead of deriving from bool_<b>
Boolean expression types now derive from bexpr_is_<b>.
(and_list_, or_list_): Comment to postpone updating while keeping
code compile.
* mlc/implies.hh: Update inheritance.
* mlc/if.hh: Update includes and add assertion.
* mlc/assert.hh: Update includes.
* mlc/valist.hh: Likewise.
* mlc/wrap.hh: Remove obsolete code.
* mlc/is_a.hh: Update inheritance.
(bexpr_): Replace by wrap_.
* mlc/case.hh: Update. Now use mlc_bool instead of ::value.
* mlc/cmp.hh: Update inheritance.
(eq_::ensure): Remove this obsolete feature.
* mlc/value.hh: Move sub-classes of value to...
* mlc/int.hh, mlc/char.hh: ...these new files.
* mlc/values.hh: New file that includes the whole value types material.
2006-03-21 Thierry Geraud <theo@lrde.epita.fr>
First step towards explicit bexpr.
......
......@@ -28,8 +28,6 @@
#ifndef METALIC_ASSERT_HH
# define METALIC_ASSERT_HH
# include <mlc/bool.hh>
namespace mlc
......@@ -228,7 +226,4 @@ namespace mlc
} // end of namespace mlc
# include <mlc/logic.hh>
#endif // ! METALIC_BOOL_HH
#endif // ! METALIC_ASSERT_HH
......@@ -28,25 +28,152 @@
#ifndef METALIC_BEXPR_HH
# define METALIC_BEXPR_HH
# include <mlc/type.hh>
# include <mlc/flags.hh>
namespace mlc
{
/*! \class mlc::bexpr_<T>
/// Forward declarations for Booleans value type and their aliases.
/// \{
template <bool b> struct bool_;
typedef bool_<true> true_;
typedef bool_<false> false_;
/// \}
namespace abstract {
/*! \class mlc::abstract::bexpr
**
** Abstract base class for mlc Boolean expression types.
**
** When you define a new class for a Boolean expression type, you
** should not directly derive from this class from fom its
** subclass: bexpr_is_<b>.
**
** \see bexpr_is_<b>
*/
struct bexpr : public type
{
// typedef void eval;
};
} // end of namespace mlc::abstract
/*! \class mlc::bexpr_is_<b>
**
** Base class for any class of mlc Boolean expression types.
** When you define a new class for a Boolean expression type, you
** should directly derive from this class.
**
** This class provides the typedef 'eval' which evaluates to either
** mlc::true_ or mlc::false_ the expression.
**
** This class is a wrapper for Boolean expression types. FIXME: doc
** \see mlc::bexpr_is_<true>, mlc::bexpr_is_<false>
*/
template <bool b> struct bexpr_is_;
/*! \class mlc::bexpr_is_<true>
**
** \see mlc::wrap_<T>
** Specialization of mlc::bexpr_is_<b> when b is 'true'. This class
** provides the typedef member 'is_true' to every Boolean expression
** type that evaluates to true_.
**
** \see mlc::bexpr_is_<b>, mlc::bexpr_is_<false>
*/
template <class T>
struct bexpr_ : public T
template <>
struct bexpr_is_ < true > : public abstract::bexpr
{
typedef typename T::eval eval;
typedef mlc::true_ eval;
/*! \typedef is_true
**
** This member is inherited in every Boolean expression type that
** evaluates to true_. Conversely, such member does not appear in
** bexpr_is_<false> so it does not exist in every Boolean
** expression type that evaluates to false_.
*/
typedef mlc::dummy is_true;
};
/*! \class mlc::bexpr_is_<false>
**
** Specialization of mlc::bexpr_is_<b> when b is 'false'. This class
** does not provide the typedef member 'is_true' to every Boolean expression
** type that evaluates to false_.
**
** \see mlc::bexpr_is_<b>, mlc::bexpr_is_<true>
*/
template <>
struct bexpr_is_ < false > : public abstract::bexpr
{
typedef mlc::false_ eval;
};
namespace internal
{
/// \class mlc::internal::bool_of_<bexpr>
/// \brief Returns the bool value corresponding to a Boolean expression type.
/// \note Internal class, don't use it directly.
template <typename bexpr>
struct bool_of_
// FIXME: commented below to avoid circular dependances
// : private assert_< mlc_is_a(bexpr, mlc::abstract::bexpr) >
{
// 1) the bexpr evaluates to either mlc::true_ or mlc::false_
// so the expected result comes from the value of b in
// mlc::bool_<b>
// 2) retrieving b is performed by the specialization of
// internal::bool_of_ provided few lines below
static const bool ret = internal::bool_of_<typename bexpr::eval>::ret;
};
/// \class mlc::internal::bool_of_< mlc::bool_<b> >
/// \brief Specialization of mlc::internal::bool_of_<bexpr>
/// \note Internal class, don't use it directly.
/// \see mlc::internal::bool_of_<bexpr>
template <bool b>
struct bool_of_ < mlc::bool_<b> >
{
static const bool ret = b;
};
} // end of namespace mlc::internal
} // end of namespace mlc
/** \def mlc_bool(Bexpr)
**
** Returns the bool value corresponding to a Boolean expression type.
**
** \note Value retrieval is performed by
** mlc::internal::bool_of_<Bexpr>
*/
# define mlc_bool(Bexpr) mlc::internal::bool_of_<Bexpr>::ret
#endif // ! METALIC_BEXPR_HH
......@@ -29,17 +29,7 @@
# define METALIC_BOOL_HH
# include <mlc/value.hh>
# include <mlc/flags.hh>
/*! \def mlc_bool(Bexpr)
**
** Macro that retrieves a Boolean value from a Boolean expression type.
** Its result is either true or false.
*/
# define mlc_bool(Bexpr) mlc::internal::get_bool<Bexpr>::value
# include <mlc/bexpr.hh>
namespace mlc
......@@ -49,12 +39,10 @@ namespace mlc
/*! \class mlc::abstract::boolean
**
** Abstract base class for Booleans represented as types. This
** class has two important sub-classes: mlc::true_ and
** mlc::false_.
**
** Any mlc Boolean expression type derives from either mlc::true_
** or mlc::false_ so derives from mlc::abstract::boolean.
** Abstract base class for Boolean values represented as types.
** This class has exactly one sub-class: mlc::bool_<b> where b is
** either true or false. Thanks to aliases, mlc::bool_<true> and
** mlc::bool_<false> are respectively mlc::true_ and mlc::false_.
*/
struct boolean : public value {};
......@@ -62,179 +50,55 @@ namespace mlc
} // end of mlc::abstract
// fwd decl
template <bool> struct bool_;
namespace internal
/*! \class mlc::bool_<b>
**
** Value type corresponding to bool.
*/
template <bool b>
struct bool_ : public bexpr_is_<b>,
public abstract::boolean
{
/*! \class mlc::get_bool<T>
/*! \typedef type
**
** Internal class so do not use it. This class gives access to a
** Boolean value from a Boolean expression type; it is used in the
** mlc_bool(T) macro.
**
** \see mlc_bool(T)
** Gives the regular type, that is bool, corresponding to this
** class.
*/
template <typename T>
struct get_bool
{
static const bool value = T::bool_value_;
};
typedef bool type;
/*! \class mlc::value_<bool, b>
/*! \member value
**
** Specialization of value_<T, val> for the Boolean case.
** Gives the regular value of the Boolean represented by this
** class. The result is either true or false.
**
** Design notes: 1) This specialization is defined so that mlc
** Booleans derive from mlc::abstract::boolean. 2) This
** specialization conforms to the interface of the generic version
** of mlc::internal::value_.
** This member is provided for any mlc value class such as
** mlc::int_<51> and mlc::char_<'c'>. However, to access the
** regular value of a type T that you know to be a mlc Boolean
** expression, you should prefer to use the macro mlc_value(T).
** This macro also ensures that T is a mlc value type.
**
*/
static const bool value = b;
};
template <bool b>
struct value_ <bool, b> : public abstract::boolean
{
/*! \typedef type
**
** Gives the regular type, that is bool, corresponding to this
** class.
*/
typedef bool type;
/*! \member value
**
** Gives the regular value of the Boolean represented by this
** class. The result is either true or false.
**
** This member is provided for any mlc value class such as
** mlc::int_<51> and mlc::char_<'c'>. However, to access the
** regular value of a type T that you know to be a mlc Boolean
** expression, you should prefer to use the macro mlc_bool(T).
** This macro also ensures that T really is an expression.
**
*/
static const bool value = b;
/*! \typedef eval
**
** Returns mlc::true_ or mlc::false_.
**
** Since Boolean expression types derive from either mlc::true_
** or mlc::false_, these expression types are never exactly
** mlc::true_ nor mlc::false_. This typedef thus allows for the
** expression evaluation.
**
** Please note that, however, we usually do not need expression
** evaluation. The most common use of a Boolean expression is
** to check that it is verified (true) and, for that, we provide
** "assert_<bexpr, errmsg>::check()". For instance:
** assert_< or_<mlc_is_a(T, int), mlc_is_a(T, unsigned)> >::check();
** ensures that T is int or unsigned without using ::eval.
**
** \see mlc::true_, mlc::false_, mlc::assert_<bexpr, errmsg>.
*/
typedef bool_<b> eval;
private:
/*! \member bool_value_
**
** This member is redundant with the member 'value'. It is used
** by the mlc_bool(T) macro to ensure that T actually derives
** from mlc::true_ or mlc::false_.
*/
static const bool bool_value_ = b;
template <typename T> friend class get_bool;
};
} // end of namespace mlc::internal
/*! \class mlc::bool_<true>
**
** Specialization of mlc::bool_<b> for b set to true. This type
** is also known as mlc::true_. Every Boolean expression types
** derive either from this type or from mlc::false_.
**
** Design notes: 1) This specialization is defined so that mlc
** Booleans derive from mlc::abstract::boolean. 2) This
** specialization conforms to the interface of the generic version
** of mlc::internal::value_.
/*! \def mlc::true_
**
** \see mlc::bool_<false>
** This is an alias (typedef) for mlc::bool_<true>.
*/
template <>
struct bool_<true> : public internal::value_<bool, true>
{
// FIXME: doc
using internal::value_<bool, true>::value;
using internal::value_<bool, true>::eval;
/*! \typedef is_true
**
** You should not use this typedef.
**
** This typedef is inherited in every Boolean expression types
** that derive from mlc::true_. This typedef is not provided in
** mlc::false_. The type returned by this typedef has no meaning
** (and thus no significant value). Static checks via
** "mlc::assert_<bexpr, err>" rely on the presence or absence of
** this typedef.
**
** \see mlc::assert_<bexpr, err>
*/
typedef dummy is_true;
};
typedef bool_<true> true_;
/*! \class mlc::bool_<false>
**
** Specialization of mlc::bool_<b> for b set to false. This type
** is also known as mlc::false_. Every Boolean expression types
** derive either from this type or from mlc::true_.
/*! \def mlc::false_
**
** Conversely to mlc::true_, this class does not feature the typedef
** "is_true". So, when a Boolean expression type, say Expr, is
** evaluated to false, the static checks via "assert_<Expr>"
** do not compile.
**
** Design notes: 1) This specialization is defined so that mlc
** Booleans derive from mlc::abstract::boolean. 2) This
** specialization conforms to the interface of the generic version
** of mlc::internal::value_.
**
** \see mlc::bool_<true>, mlc::assert_<bexpr, errmsg>
** This is an alias (typedef) for mlc::bool_<false>.
*/
template <>
struct bool_<false> : public internal::value_<bool, false>
{
// FIXME: doc
private:
typedef internal::value_<bool, false> super_type;
public:
using super_type::value;
using super_type::eval;
};
typedef bool_<false> false_;
} // end of namespace mlc
# include <mlc/logic.hh>
#endif // ! METALIC_BOOL_HH
......@@ -170,7 +170,7 @@ namespace NAMESPACE \
mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, i>), \
mlc::undefined) >, \
mlc::ERROR::A_case_STATEMENT_SHOULD_DERIVE_FROM_mlc_where_ >, \
\
\
private mlc::assert_< mlc::implies_< mlc::and_< mlc::eq_<use, mlc::internal::a_switch_case>, \
mlc_is_not_a(mlc_comma_2(NAMESPACE::case_<context, data, i>), \
mlc::undefined) >, \
......@@ -198,33 +198,36 @@ namespace NAMESPACE \
mlc::ret_found_in_< NAMESPACE::case_<context, data, i> > >, \
mlc::ERROR::A_case_STATEMENT_IN_A_switch_SHOULD_HAVE_A_ret > \
{ \
typedef handle_case_ < \
use, \
context, data, i+1, \
mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, i+1>), \
mlc::case_selected)::value, \
mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, i+1>), \
mlc::case_not_selected)::value > next_t; \
typedef typename next_t::ret ret; \
typedef mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, i+1>), \
mlc::case_selected) next_case_is_selected; \
typedef mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, i+1>), \
mlc::case_not_selected) next_case_is_not_selected; \
\
typedef handle_case_ < use, \
context, data, i+1, \
mlc_bool(next_case_is_selected), mlc_bool(next_case_is_not_selected) \
> handle_next_case_t; \
typedef typename handle_next_case_t::ret ret; \
}; \
\
\
\
template <typename use, typename context, typename data> \
struct select_case_ \
\
\
: private mlc::assert_< mlc::eq_< mlc_ret(mlc_comma_2(NAMESPACE::case_<context, data, 0>)), \
mlc::locked >, \
mlc::ERROR::A_case_STATEMENT_SHOULD_NOT_START_AT_INDEX_0_BUT_1 > \
{ \
typedef handle_case_ < \
use, \
context, data, 1, \
mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, 1>), \
mlc::case_selected)::value, \
mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, 1>), \
mlc::case_not_selected)::value > handle_t; \
typedef typename handle_t::ret ret; \
typedef mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, 1>), \
mlc::case_selected) first_case_is_selected; \
typedef mlc_is_a(mlc_comma_2(NAMESPACE::case_<context, data, 1>), \
mlc::case_not_selected) first_case_is_not_selected; \
typedef handle_case_ < use, \
context, data, 1, \
mlc_bool(first_case_is_selected), mlc_bool(first_case_is_not_selected) \
> handle_first_case_t; \
typedef typename handle_first_case_t::ret ret; \
}; \
\
\
......@@ -260,7 +263,7 @@ namespace NAMESPACE \
\
} \
\
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n \
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
......
// Copyright (C) 2005, 2006 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
// MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef METALIC_CHAR_HH
# define METALIC_CHAR_HH
# include <mlc/value.hh>
namespace mlc
{
// char
template <char c>
struct char_ : public abstract::value
{
typedef char type;
static const char value = c;
};
} // end of namespace mlc
#endif // ! METALIC_CHAR_HH
......@@ -28,8 +28,9 @@
#ifndef METALIC_CMP_HH
# define METALIC_CMP_HH
# include <mlc/bool.hh>
# include <mlc/bexpr.hh>
# include <mlc/is_a.hh>
# include <mlc/logic.hh>
/// Macros mlc_eq and mlc_neq.
......@@ -59,17 +60,14 @@ namespace mlc
template <typename T1, typename T2>
struct eq_ : private multiple_assert_< is_not_value<T1>,
is_not_value<T2> >,
public false_
public bexpr_is_<false>
{
};
template <typename T>
struct eq_ <T, T> : private assert_< is_not_value<T> >,
public true_
public bexpr_is_<true>
{
// Solve the ambiguity on ensure(), a static member function
// inherited both from true_ and assert_.
using true_::ensure;
};
/// \}
......@@ -78,13 +76,13 @@ namespace mlc
template <typename T1, typename T2>
struct neq_ : private multiple_assert_< is_not_value<T1>,
is_not_value<T2> >,
public true_
public bexpr_is_<true>
{
};
template <typename T>
struct neq_ <T, T> : private