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

Add material for literals, binding arguments, and static checks.

- xtd/res.hh (xtd_res_0_ et al.): New; versions without typename.
(xtd_internal_res_0, internal::get_res_0_unchecked): New; this
equipment is for use in hierarchies to avoid partial definitions.
- xtd/mexpr.hh: Add static assertions.
- xtd/literal.hh (literal_): Rename as...
(plain_literal_): ...this.
(meta_literal_): New class.
(literal_expr_): Add static assertions.
(lit): New routine.
(bind_1, bind_2, bind_3): New; method implementation for
nary_fun_expr_<n, E>::bind_i. 
- xtd/arg.hh (xtd_nargs): Remove this duplicate.
- xtd/args.hh (xtd_nargs, nargs_): Move to...
- xtd/abstract/fun_expr.hh: ...this file.
(fun_expr_<E>::nargs): Remove; xtd_nargs does it.
(xtd_res_0): Replace by...
(xtd_internal_res_0): ...this.
(bind_1, bind_2, bind_3): New methods.
- xtd/abstract/exact.hh: Remove; the routine exact_of has moved...
- xtd/abstract/fun.hh: ...here.
- xtd/abstract/plain_fun.hh (operator()): Add static check.
- xtd/abstract/meta_fun.hh: Add static checks.
- tests/id.cc: Add xfail tests.
- tests/bind.cc: New.
- tests/lit.cc: New.
- tests/Makefile.am: Update.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@440 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 452aebf2
2006-03-24 Thierry Geraud <theo@lrde.epita.fr>
Add material for literals, binding arguments, and static checks.
* xtd/res.hh (xtd_res_0_ et al.): New; versions without typename.
(xtd_internal_res_0, internal::get_res_0_unchecked): New; this
equipment is for use in hierarchies to avoid partial definitions.
* xtd/mexpr.hh: Add static assertions.
* xtd/literal.hh (literal_): Rename as...
(plain_literal_): ...this.
(meta_literal_): New class.
(literal_expr_): Add static assertions.
(lit): New routine.
(bind_1, bind_2, bind_3): New; method implementation for
nary_fun_expr_<n, E>::bind_i.
* xtd/arg.hh (xtd_nargs): Remove this duplicate.
* xtd/args.hh (xtd_nargs, nargs_): Move to...
* xtd/abstract/fun_expr.hh: ...this file.
(fun_expr_<E>::nargs): Remove; xtd_nargs does it.
(xtd_res_0): Replace by...
(xtd_internal_res_0): ...this.
(bind_1, bind_2, bind_3): New methods.
* xtd/abstract/exact.hh: Remove; the routine exact_of has moved...
* xtd/abstract/fun.hh: ...here.
* xtd/abstract/plain_fun.hh (operator()): Add static check.
* xtd/abstract/meta_fun.hh: Add static checks.
* tests/id.cc: Add xfail tests.
* tests/bind.cc: New.
* tests/lit.cc: New.
* tests/Makefile.am: Update.
2006-03-23 Roland Levillain <roland@lrde.epita.fr>
Add Metalic's include path to Extended's tests.
......
......@@ -9,11 +9,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/extended -I$(top_srcdir)/metalic
check_PROGRAMS = \
id \
bind \
cast \
cos
cos \
lit
id_SOURCES = id.cc
bind_SOURCES = bind.cc
cast_SOURCES = cast.cc
cos_SOURCES = cos.cc
lit_SOURCES = lit.cc
TESTS = $(check_PROGRAMS)
#include <iostream>
#include <xtd/math.hh>
int main()
{
using xtd::_1;
using xtd::_2;
using xtd::lit;
(_1 + _2)(_1, _1);
(_1 + _2)(_1, lit(1.f));
(_1 + _2).bind_2(1.f);
std::cout << (_1 + _2)(5., 1.) << std::endl;
// std::cout << (_1 + _2)(_1, 1.)(5.) << std::endl;
// autre problme :
// std::cout << (_1 + 1)(5.f) << std::endl;
}
......@@ -37,7 +37,9 @@ int main()
xtd::plain_id_<float> id_float;
std::cout << id_float(5.1f) << std::endl;
// xfail tests:
// xtd::id(id_int);
// xtd::id(xtd::id);
}
}
#include <iostream>
#include <xtd/literal.hh>
int main()
{
{
xtd::plain_literal_<double> l(5.1);
}
{
typedef xtd::meta_literal_<double> F;
F l(5.1);
// xtd_res_0_(F) tmp;
// int warning = tmp;
}
{
xtd::literal_expr_<double> l(5.1);
}
std::cout << mlc_is_a_(xtd::meta_literal_<double>, xtd::abstract::meta_fun_)::eval::value << std::endl;
}
// Copyright (C) 2002, 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 EXTENDED_ABSTRACT_EXACT_HH
# define EXTENDED_ABSTRACT_EXACT_HH
namespace xtd
{
namespace abstract
{
template <typename E> class plain_fun_;
template <typename E> class meta_fun_;
template <typename E> class fun_expr_;
} // end of namespace xtd::abstract
// plain_fun_
template <typename E>
const E* exact_of(const abstract::plain_fun_<E>* f)
{
return (const E*)(const void*)(f);
}
template <typename E>
const E& exact_of(const abstract::plain_fun_<E>& f)
{
return *exact_of(&f);
}
// meta_fun_
template <typename E>
const E* exact_of(const abstract::meta_fun_<E>* f)
{
return (const E*)(const void*)(f);
}
template <typename E>
const E& exact_of(const abstract::meta_fun_<E>& f)
{
return *exact_of(&f);
}
// fun_expr_
template <typename E>
const E* exact_of(const abstract::fun_expr_<E>* f)
{
return (const E*)(const void*)(f);
}
template <typename E>
const E& exact_of(const abstract::fun_expr_<E>& f)
{
return *exact_of(&f);
}
} // end of namespace xtd
#endif // ! EXTENDED_ABSTRACT_EXACT_HH
......@@ -51,6 +51,23 @@ namespace xtd
} // end of namespace xtd::abstract
// FIXME: doc
template <typename E>
const E* exact_of(const abstract::fun_<E>* f)
{
return (const E*)(const void*)(f);
}
template <typename E>
const E& exact_of(const abstract::fun_<E>& f)
{
return *(const E*)(const void*)(&f);
}
} // end of namespace xtd
......
......@@ -28,17 +28,23 @@
#ifndef EXTENDED_ABSTRACT_FUN_EXPR_HH
# define EXTENDED_ABSTRACT_FUN_EXPR_HH
# include <mlc/flags.hh>
# include <mlc/bool.hh>
# include <mlc/is_a.hh>
# include <mlc/comma.hh>
# include <xtd/args.hh>
# include <xtd/res.hh>
# include <xtd/abstract/exact.hh>
# include <xtd/abstract/meta_fun.hh>
// FIXME: doc
# define xtd_nargs(F) xtd::internal::get_nargs_<F>::ret
namespace xtd
{
......@@ -47,14 +53,75 @@ namespace xtd
{
struct INTERNAL_ILL_FORMED_CALL_TO_xtd_fun_expr_eval;
struct SPECIALIZATION_OF_xtd_nargs_IS_FOR_xtd_fun_expr_ONLY;
struct SPECIALIZATION_OF_xtd_nargs_NOT_FOUND_FOR_AN_xtd_fun_expr;
} // end of namespace xtd::ERROR
/// Forward declarations.
/// \{
namespace abstract
{
template <typename E> class fun_expr_;
}
template <typename F, typename Expr1, typename Expr2>
struct m2expr_;
template <typename F, typename Expr1, typename Expr2, typename Expr3>
struct m3expr_;
template <typename T>
struct literal_expr_;
template <unsigned i>
struct arg_;
/// \}
/*! \class xtd::nargs_<F>
**
** FIXME: doc
** FIXME: and add a mechanism so that the type of F is checked
** FIXME: Cf. get_res0_ in xtd/abstract/meta_fun.hh
*/
template <typename F>
struct nargs_ : public mlc::undefined
{
};
namespace internal
{
template <typename F>
struct get_nargs_
: // private mlc::assert_< mlc_is_a(F, xtd::abstract::fun_expr_),
// xtd::ERROR::SPECIALIZATION_OF_xtd_nargs_IS_FOR_xtd_fun_expr_ONLY >,
// FIXME: the static assertion above does *not* compile...
private mlc::assert_< mlc_is_not_a(xtd::nargs_<F>, mlc::undefined),
xtd::ERROR::SPECIALIZATION_OF_xtd_nargs_NOT_FOUND_FOR_AN_xtd_fun_expr >
{
static const unsigned ret = xtd::nargs_<F>::ret;
};
} // end of xtd::internal
namespace abstract
{
/*! \class xtd::abstract::fun_expr_<E>
**
** Abstract base class for function expressions. Parameter E is
......@@ -74,26 +141,24 @@ namespace xtd
{
public:
// evaluation:
template <typename Args>
xtd_expr_res(E, Args)
eval(const Args& as) const
eval(const Args& as) const
{
mlc::assert_< mlc_is_a(Args, xtd::abstract::args),
xtd::ERROR::INTERNAL_ILL_FORMED_CALL_TO_xtd_fun_expr_eval >::check();
xtd::ERROR::INTERNAL_ILL_FORMED_CALL_TO_xtd_fun_expr_eval >::check();
return exact_of(this)->impl_eval(as);
}
// FIXME: the get_nargs method is obsolete; remove it!
unsigned nargs() const { return xtd_nargs(E); }
protected:
fun_expr_() {}
};
/*! \class xtd::abstract::nary_fun_expr_<n, E>
**
** Abstract base class for function expressions with an explicit
......@@ -125,10 +190,19 @@ namespace xtd
public meta_nary_fun_<0, E>
{
public:
xtd_res_0(E) impl_calc() const
// the return type here is not xtd_res_0(E)
// the explanations are given with meta_nary_fun_<0, E>::operator()()
// in file xtd/abstract/meta_fun.hh
xtd_internal_res_0(E)
impl_calc() const
{
return this->eval(mk_args());
}
// no bind_i method here
protected:
nary_fun_expr_() {}
};
......@@ -150,12 +224,16 @@ namespace xtd
public meta_nary_fun_<1, E>
{
public:
template <typename A>
xtd_res_1(E, A)
impl_calc(const A& a) const
impl_calc(const A& a) const
{
return this->eval(mk_args(a));
}
// no bind_i method here
protected:
nary_fun_expr_() {}
};
......@@ -177,12 +255,22 @@ namespace xtd
public meta_nary_fun_<2, E>
{
public:
template <typename A1, typename A2>
xtd_res_2(E, A1, A2)
impl_calc(const A1& a1, const A2& a2) const
impl_calc(const A1& a1, const A2& a2) const
{
return this->eval(mk_args(a1, a2));
}
template <typename T>
m2expr_< E, literal_expr_<T>, arg_<2> >
bind_1(const T& value) const;
template <typename T>
m2expr_< E, arg_<1>, literal_expr_<T> >
bind_2(const T& value) const;
protected:
nary_fun_expr_() {}
};
......@@ -204,12 +292,26 @@ namespace xtd
public meta_nary_fun_<3, E>
{
public:
template <typename A1, typename A2, typename A3>
xtd_res_3(E, A1, A2, A3)
impl_calc(const A1& a1, const A2& a2, const A3& a3) const
impl_calc(const A1& a1, const A2& a2, const A3& a3) const
{
return this->eval(mk_args(a1, a2, a3));
}
template <typename T>
m3expr_< E, literal_expr_<T>, arg_<2>, arg_<3> >
bind_1(const T& value) const;
template <typename T>
m3expr_< E, arg_<1>, literal_expr_<T>, arg_<3> >
bind_2(const T& value) const;
template <typename T>
m3expr_< E, arg_<1>, arg_<2>, literal_expr_<T> >
bind_3(const T& value) const;
protected:
nary_fun_expr_() {}
};
......
......@@ -28,10 +28,10 @@
#ifndef EXTENDED_ABSTRACT_META_FUN_HH
# define EXTENDED_ABSTRACT_META_FUN_HH
# include <mlc/flags.hh>
# include <mlc/pair.hh>
# include <mlc/valist.hh>
# include <xtd/abstract/exact.hh>
# include <xtd/abstract/fun.hh>
# include <xtd/abstract/nary_fun.hh>
# include <xtd/args.hh>
......@@ -46,6 +46,23 @@
namespace xtd
{
namespace ERROR
{
struct ARG_SHOULD_NOT_BE_A_PLAIN_FUN;
struct ARG1_SHOULD_NOT_BE_A_PLAIN_FUN;
struct ARG2_SHOULD_NOT_BE_A_PLAIN_FUN;
struct ARG3_SHOULD_NOT_BE_A_PLAIN_FUN;
struct ARG_SHOULD_NOT_BE_A_META_NON_EXPR_FUN;
struct ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN;
struct ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN;
struct ARG3_SHOULD_NOT_BE_A_META_NON_EXPR_FUN;
}// end of namespace xtd
// FIXME: document case stuff...
namespace tag
......@@ -109,6 +126,8 @@ namespace xtd
} // end of namespace xtd
namespace xtd
{
......@@ -131,9 +150,9 @@ namespace xtd
meta_fun_()
{
// FIXME: mlc_is_a does not work with unsigned parameter...
// mlc::assert_< mlc_is_a(E, xtd::abstract::meta_nary_fun_),
// xtd::ERROR::YOU_SHOULD_NOT_DERIVE_DIRECTLY_FROM_xtd_meta_fun_BUT_FROM_xtd_meta_nary_fun_
// >::check();
// mlc::assert_< mlc_is_a(E, xtd::abstract::meta_nary_fun_),
// xtd::ERROR::YOU_SHOULD_NOT_DERIVE_DIRECTLY_FROM_xtd_meta_fun_BUT_FROM_xtd_meta_nary_fun_
// >::check();
}
};
......@@ -169,7 +188,16 @@ namespace xtd
{
public:
xtd_res_0(E)
/*
** This member is not templated so its behavior at compile-time
** is different than meta_nary_fun_<n,E>::operator() where n >
** 0. Here the return type should be known before the hierarchy
** classes are fully compiled thus static assertions in the
** macro xtd_res_0 do *not* work. An alternate macro is thus
** in use.
*/
xtd_internal_res_0(E)
operator()() const
{
return exact_of(this)->impl_calc();
......@@ -198,8 +226,17 @@ namespace xtd
public:
template <typename A>
struct case_ : public xtd::case_< xtd::tag::meta_1ary_fun_operator,
mlc::pair_<E, A> >::ret
struct case_
: private mlc::assert_< mlc_is_not_a(A, xtd::abstract::plain_fun_),
xtd::ERROR::ARG_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A, xtd::abstract::meta_fun_),
mlc_is_a(A, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
public xtd::case_< xtd::tag::meta_1ary_fun_operator,
mlc::pair_<E, A> >::ret
{};
template <typename A>
......@@ -232,8 +269,24 @@ namespace xtd
public:
template <typename A1, typename A2>
struct case_ : public xtd::case_< xtd::tag::meta_2ary_fun_operator,
mlc::valist_<E, A1, A2> >::ret
struct case_
: private mlc::assert_< mlc_is_not_a(A1, xtd::abstract::plain_fun_),
xtd::ERROR::ARG1_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A1, xtd::abstract::meta_fun_),
mlc_is_a(A1, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
private mlc::assert_< mlc_is_not_a(A2, xtd::abstract::plain_fun_),
xtd::ERROR::ARG2_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A2, xtd::abstract::meta_fun_),
mlc_is_a(A2, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
public xtd::case_< xtd::tag::meta_2ary_fun_operator,
mlc::valist_<E, A1, A2> >::ret
{};
template <typename A1, typename A2>
......@@ -265,8 +318,31 @@ namespace xtd
public:
template <typename A1, typename A2, typename A3>
struct case_ : public xtd::case_< xtd::tag::meta_3ary_fun_operator,
mlc::valist_<E, A1, A2, A3> >::ret
struct case_
: private mlc::assert_< mlc_is_not_a(A1, xtd::abstract::plain_fun_),
xtd::ERROR::ARG1_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A1, xtd::abstract::meta_fun_),
mlc_is_a(A1, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
private mlc::assert_< mlc_is_not_a(A2, xtd::abstract::plain_fun_),
xtd::ERROR::ARG2_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A2, xtd::abstract::meta_fun_),
mlc_is_a(A2, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
private mlc::assert_< mlc_is_not_a(A3, xtd::abstract::plain_fun_),
xtd::ERROR::ARG3_SHOULD_NOT_BE_A_PLAIN_FUN >,
private mlc::assert_< mlc::implies_< mlc_is_a(A3, xtd::abstract::meta_fun_),
mlc_is_a(A3, xtd::abstract::fun_expr_) >,
xtd::ERROR::ARG3_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >,
public xtd::case_< xtd::tag::meta_3ary_fun_operator,
mlc::valist_<E, A1, A2, A3> >::ret
{};
template <typename A1, typename A2, typename A3>
......
......@@ -29,11 +29,12 @@
# define EXTENDED_ABSTRACT_PLAIN_FUN_HH
# include <mlc/flags.hh>
# include <mlc/bool.hh> // FIXME: should be assert.hh
# include <mlc/assert.hh>
# include <mlc/is_a.hh>
# include <mlc/typedef.hh>
# include <mlc/assert.hh>
# include <mlc/abort.hh>
# include <xtd/abstract/exact.hh>
# include <xtd/abstract/fun.hh>
# include <xtd/abstract/nary_fun.hh>
......@@ -70,18 +71,24 @@ namespace xtd