$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61012 - in trunk/libs/spirit/example/scheme: . detail test
From: joel_at_[hidden]
Date: 2010-04-03 03:57:37
Author: djowel
Date: 2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
New Revision: 61012
URL: http://svn.boost.org/trac/boost/changeset/61012
Log:
scheme operators
Added:
   trunk/libs/spirit/example/scheme/test/scheme.cpp   (contents, props changed)
   trunk/libs/spirit/example/scheme/utree_operators.hpp   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/example/scheme/detail/utree_detail1.hpp |     2                                         
   trunk/libs/spirit/example/scheme/detail/utree_detail2.hpp |   217 +++------------------------------------ 
   trunk/libs/spirit/example/scheme/test/utree_test.cpp      |    13 ++                                      
   trunk/libs/spirit/example/scheme/utree.hpp                |    27 ++--                                    
   4 files changed, 51 insertions(+), 208 deletions(-)
Modified: trunk/libs/spirit/example/scheme/detail/utree_detail1.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/detail/utree_detail1.hpp	(original)
+++ trunk/libs/spirit/example/scheme/detail/utree_detail1.hpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -14,6 +14,8 @@
 # pragma warning(disable: 4244)
 #endif
 
+#include <boost/type_traits/alignment_of.hpp>
+
 namespace scheme { namespace detail
 {
     template <typename UTreeX, typename UTreeY>
Modified: trunk/libs/spirit/example/scheme/detail/utree_detail2.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/detail/utree_detail2.hpp	(original)
+++ trunk/libs/spirit/example/scheme/detail/utree_detail2.hpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -315,167 +315,6 @@
         return bind_impl<F, X>(f, x);
     }
 
-    struct utree_is_equal
-    {
-        typedef bool result_type;
-
-        template <typename A, typename B>
-        bool dispatch(const A&, const B&, boost::mpl::false_) const
-        {
-            return false; // cannot compare different types by default
-        }
-
-        template <typename A, typename B>
-        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
-        {
-            return a == b; // for arithmetic types
-        }
-
-        template <typename A, typename B>
-        bool operator()(const A& a, const B& b) const
-        {
-            return dispatch(a, b,
-                boost::mpl::and_<
-                    boost::is_arithmetic<A>,
-                    boost::is_arithmetic<B> >());
-        }
-
-        template <typename T>
-        bool operator()(const T& a, const T& b) const
-        {
-            // This code works for lists
-            return a == b;
-        }
-
-        template <typename Base, utree_type::info type_>
-        bool operator()(
-            basic_string<Base, type_> const& a,
-            basic_string<Base, type_> const& b) const
-        {
-            return static_cast<Base const&>(a) == static_cast<Base const&>(b);
-        }
-
-        bool operator()(nil, nil) const
-        {
-            return true;
-        }
-    };
-
-    struct utree_is_less_than
-    {
-        typedef bool result_type;
-
-        template <typename A, typename B>
-        bool dispatch(const A&, const B&, boost::mpl::false_) const
-        {
-            return false; // cannot compare different types by default
-        }
-
-        template <typename A, typename B>
-        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
-        {
-            return a < b; // for arithmetic types
-        }
-
-        template <typename A, typename B>
-        bool operator()(const A& a, const B& b) const
-        {
-            return dispatch(a, b,
-                boost::mpl::and_<
-                    boost::is_arithmetic<A>,
-                    boost::is_arithmetic<B> >());
-        }
-
-        template <typename T>
-        bool operator()(const T& a, const T& b) const
-        {
-            // This code works for lists
-            return a < b;
-        }
-
-        template <typename Base, utree_type::info type_>
-        bool operator()(
-            basic_string<Base, type_> const& a,
-            basic_string<Base, type_> const& b) const
-        {
-            return static_cast<Base const&>(a) < static_cast<Base const&>(b);
-        }
-
-        bool operator()(nil, nil) const
-        {
-            BOOST_ASSERT(false);
-            return false; // no less than comparison for nil
-        }
-    };
-
-    struct utree_print
-    {
-        typedef void result_type;
-
-        std::ostream& out;
-        utree_print(std::ostream& out) : out(out) {}
-
-        void operator()(scheme::nil) const
-        {
-            out << "nil";
-        }
-
-        template <typename T>
-        void operator()(T val) const
-        {
-            out << val;
-        }
-
-        void operator()(bool b) const
-        {
-            out << (b ? "true" : "false");
-        }
-
-        void operator()(binary_range const& b) const
-        {
-            out << "b";
-            out.width(2);
-            out.fill('0');
-
-            typedef binary_range::const_iterator iterator;
-            for (iterator i = b.begin(); i != b.end(); ++i)
-                out << std::hex << int((unsigned char)*i);
-            out << std::dec;
-        }
-
-        void operator()(utf8_string_range const& str) const
-        {
-            typedef utf8_string_range::const_iterator iterator;
-            iterator i = str.begin();
-            out << '"';
-            for (; i != str.end(); ++i)
-                out << *i;
-            out << '"';
-        }
-
-        void operator()(utf8_symbol_range const& str) const
-        {
-            typedef utf8_symbol_range::const_iterator iterator;
-            iterator i = str.begin();
-            for (; i != str.end(); ++i)
-                out << *i;
-        }
-
-        template <typename Iterator>
-        void operator()(boost::iterator_range<Iterator> const& range) const
-        {
-            typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
-            (*this)('(');
-            for (iterator i = range.begin(); i != range.end(); ++i)
-            {
-                if (i != range.begin())
-                    (*this)(' ');
-                scheme::utree::visit(*i, *this);
-            }
-            (*this)(')');
-        }
-    };
-
     template <typename UTreeX, typename UTreeY = UTreeX>
     struct visit_impl
     {
@@ -524,6 +363,9 @@
 
                 case type::reference_type:
                     return apply(*x.p, f);
+
+                case type::function_type:
+                    return f(x.f);
             }
         }
 
@@ -577,6 +419,9 @@
 
                 case type::reference_type:
                     return apply(*x.p, y, f);
+
+                case type::function_type:
+                    return visit_impl::apply(y, detail::bind(f, x.f));
             }
         }
     };
@@ -657,6 +502,12 @@
         set_type(type::reference_type);
     }
 
+    inline utree::utree(function_ptr fptr)
+      : f(fptr)
+    {
+        set_type(type::function_type);
+    }
+
     inline utree::utree(utree const& other)
     {
         copy(other);
@@ -742,6 +593,14 @@
         return *this;
     }
 
+    inline utree& utree::operator=(function_ptr fptr)
+    {
+        free();
+        f = fptr;
+        set_type(type::function_type);
+        return *this;
+    }
+
     template <typename F>
     typename F::result_type
     inline utree::visit(utree const& x, F f)
@@ -800,42 +659,6 @@
         return detail::index_impl::apply(l.first, i);
     }
 
-    inline bool operator==(utree const& a, utree const& b)
-    {
-        return utree::visit(a, b, detail::utree_is_equal());
-    }
-
-    inline bool operator<(utree const& a, utree const& b)
-    {
-        return utree::visit(a, b, detail::utree_is_less_than());
-    }
-
-    inline bool operator!=(utree const& a, utree const& b)
-    {
-        return !(a == b);
-    }
-
-    inline bool operator>(utree const& a, utree const& b)
-    {
-        return b < a;
-    }
-
-    inline bool operator<=(utree const& a, utree const& b)
-    {
-        return !(b < a);
-    }
-
-    inline bool operator>=(utree const& a, utree const& b)
-    {
-        return !(a < b);
-    }
-
-    inline std::ostream& operator<<(std::ostream& out, utree const& x)
-    {
-        utree::visit(x, detail::utree_print(out));
-        return out;
-    }
-
     template <typename T>
     inline void utree::push_front(T const& val)
     {
Added: trunk/libs/spirit/example/scheme/test/scheme.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/scheme/test/scheme.cpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -0,0 +1,148 @@
+/*=============================================================================
+    Copyright (c) 2001-2010 Joel de Guzman
+
+    Distributed under the Boost Software License, Version 1.0. (See accompanying
+    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+
+#include "../input/sexpr.hpp"
+#include "../input/parse_sexpr_impl.hpp"
+#include <iostream>
+#include <fstream>
+
+inline std::ostream& println(std::ostream& out, scheme::utree const& val)
+{
+    out << val << std::endl;
+    return out;
+}
+
+#include <boost/unordered_map.hpp>
+
+namespace scheme
+{
+    class environment
+    {
+    public:
+
+        environment(environment* parent = 0)
+          : bindings(), parent(parent) {}
+
+        void define(std::string const& name, utree const& def)
+        {
+            // check for duplicate names
+            BOOST_ASSERT(bindings.find(name) == bindings.end());
+            // $$$ TODO Use exceptions $$$
+            bindings[name] = def;
+        }
+
+        utree* find(std::string const& name)
+        {
+            map::iterator i = bindings.find(name);
+            if (i == bindings.end())
+            {
+                if (parent)
+                    return parent->find(name);
+                return 0;
+            }
+            return &i->second;
+        }
+
+    private:
+
+        typedef boost::unordered_map<std::string, utree> map;
+        map bindings;
+        environment* parent;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Intrinsic functions
+    ///////////////////////////////////////////////////////////////////////////
+    struct arithmetic_function
+    {
+        typedef bool result_type;
+
+        template <typename A, typename B>
+        bool dispatch(const A&, const B&, boost::mpl::false_) const
+        {
+            return false; // cannot compare different types by default
+        }
+
+        template <typename A, typename B>
+        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+        {
+            return a == b; // for arithmetic types
+        }
+
+        template <typename A, typename B>
+        bool operator()(const A& a, const B& b) const
+        {
+            return dispatch(a, b,
+                boost::mpl::and_<
+                    boost::is_arithmetic<A>,
+                    boost::is_arithmetic<B> >());
+        }
+    };
+
+    utree plus(environment*, utree& args)
+    {
+
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+    char const* filename;
+    if (argc > 1)
+    {
+        filename = argv[1];
+    }
+    else
+    {
+        std::cerr << "Error: No input file provided." << std::endl;
+        return 1;
+    }
+
+    std::ifstream in(filename, std::ios_base::in);
+
+    if (!in)
+    {
+        std::cerr << "Error: Could not open input file: "
+            << filename << std::endl;
+        return 1;
+    }
+
+    // Ignore the BOM marking the beginning of a UTF-8 file in Windows
+    char c = in.peek();
+    if (c == '\xef')
+    {
+        char s[3];
+        in >> s[0] >> s[1] >> s[2];
+        s[3] = '\0';
+        if (s != std::string("\xef\xbb\xbf"))
+        {
+            std::cerr << "Error: Unexpected characters from input file: "
+                << filename << std::endl;
+            return 1;
+        }
+    }
+
+    scheme::utree result;
+    if (scheme::input::parse_sexpr(in, result))
+    {
+        std::cout << "success: ";
+        println(std::cout, result);
+        std::cout << std::endl;
+    }
+    else
+    {
+        std::cout << "parse error" << std::endl;
+    }
+
+    return 0;
+}
+
+
Modified: trunk/libs/spirit/example/scheme/test/utree_test.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/utree_test.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/utree_test.cpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -8,6 +8,7 @@
 #include <boost/config/warning_disable.hpp>
 
 #include "../utree.hpp"
+#include "../utree_operators.hpp"
 #include <iostream>
 
 inline std::ostream& println(std::ostream& out, scheme::utree const& val)
@@ -194,5 +195,17 @@
         println(std::cout, vals[2]);
     }
 
+    { // arithmetic
+        BOOST_ASSERT((utree(456) + utree(123)) == utree(456 + 123));
+        BOOST_ASSERT((utree(456) + utree(123.456)) == utree(456 + 123.456));
+        BOOST_ASSERT((utree(456) - utree(123)) == utree(456 - 123));
+        BOOST_ASSERT((utree(456) - utree(123.456)) == utree(456 - 123.456));
+        BOOST_ASSERT((utree(456) * utree(123)) == utree(456 * 123));
+        BOOST_ASSERT((utree(456) * utree(123.456)) == utree(456 * 123.456));
+        BOOST_ASSERT((utree(456) / utree(123)) == utree(456 / 123));
+        BOOST_ASSERT((utree(456) / utree(123.456)) == utree(456 / 123.456));
+        BOOST_ASSERT((utree(456) % utree(123)) == utree(456 % 123));
+    }
+
     return 0;
 }
Modified: trunk/libs/spirit/example/scheme/utree.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree.hpp	(original)
+++ trunk/libs/spirit/example/scheme/utree.hpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -16,8 +16,6 @@
 #include <boost/noncopyable.hpp>
 #include <boost/iterator/iterator_facade.hpp>
 #include <boost/range/iterator_range.hpp>
-#include <boost/type_traits/is_pointer.hpp>
-#include <boost/type_traits/alignment_of.hpp>
 #include <boost/ref.hpp>
 #include "detail/utree_detail1.hpp"
 
@@ -39,7 +37,8 @@
             symbol_type,
             binary_type,
             list_type,
-            reference_type
+            reference_type,
+            function_type
         };
     };
 
@@ -49,6 +48,17 @@
     struct nil {};
 
     ///////////////////////////////////////////////////////////////////////////
+    // The environment (this is forward declared)
+    ///////////////////////////////////////////////////////////////////////////
+    class environment;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Function pointer
+    ///////////////////////////////////////////////////////////////////////////
+    class utree; // forward
+    typedef utree (*function_ptr)(environment* env, utree& args);
+
+    ///////////////////////////////////////////////////////////////////////////
     // A typed string with parametric Base storage. The storage can be any
     // range or (stl container) of chars.
     ///////////////////////////////////////////////////////////////////////////
@@ -164,6 +174,7 @@
         explicit utree(char const* str, std::size_t len);
         explicit utree(std::string const& str);
         explicit utree(boost::reference_wrapper<utree> ref);
+        explicit utree(function_ptr fptr);
 
         template <typename Base, utree_type::info type_>
         explicit utree(basic_string<Base, type_> const& bin);
@@ -179,6 +190,7 @@
         utree& operator=(char const* s);
         utree& operator=(std::string const& s);
         utree& operator=(boost::reference_wrapper<utree> ref);
+        utree& operator=(function_ptr fptr);
 
         template <typename Base, utree_type::info type_>
         utree& operator=(basic_string<Base, type_> const& bin);
@@ -278,16 +290,9 @@
             int i;
             double d;
             utree* p;
+            function_ptr f;
         };
     };
-
-    bool operator==(utree const& a, utree const& b);
-    bool operator<(utree const& a, utree const& b);
-    bool operator!=(utree const& a, utree const& b);
-    bool operator>(utree const& a, utree const& b);
-    bool operator<=(utree const& a, utree const& b);
-    bool operator>=(utree const& a, utree const& b);
-    std::ostream& operator<<(std::ostream& out, utree const& x);
 }
 
 #include "detail/utree_detail2.hpp"
Added: trunk/libs/spirit/example/scheme/utree_operators.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/scheme/utree_operators.hpp	2010-04-03 03:57:36 EDT (Sat, 03 Apr 2010)
@@ -0,0 +1,355 @@
+/*=============================================================================
+    Copyright (c) 2001-2010 Joel de Guzman
+
+    Distributed under the Boost Software License, Version 1.0. (See accompanying
+    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
+#define BOOST_SPIRIT_UTREE_OPERATORS
+
+#include "utree.hpp"
+#include <boost/preprocessor/cat.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_integral.hpp>
+
+namespace scheme
+{
+    // Available operators
+    bool operator==(utree const& a, utree const& b);
+    bool operator<(utree const& a, utree const& b);
+    bool operator!=(utree const& a, utree const& b);
+    bool operator>(utree const& a, utree const& b);
+    bool operator<=(utree const& a, utree const& b);
+    bool operator>=(utree const& a, utree const& b);
+    std::ostream& operator<<(std::ostream& out, utree const& x);
+
+    utree operator+(utree const& a, utree const& b);
+    utree operator-(utree const& a, utree const& b);
+    utree operator*(utree const& a, utree const& b);
+    utree operator/(utree const& a, utree const& b);
+    utree operator%(utree const& a, utree const& b);
+
+    // Implementation
+    struct utree_is_equal
+    {
+        typedef bool result_type;
+
+        template <typename A, typename B>
+        bool dispatch(const A&, const B&, boost::mpl::false_) const
+        {
+            return false; // cannot compare different types by default
+        }
+
+        template <typename A, typename B>
+        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+        {
+            return a == b; // for arithmetic types
+        }
+
+        template <typename A, typename B>
+        bool operator()(const A& a, const B& b) const
+        {
+            return dispatch(a, b,
+                boost::mpl::and_<
+                    boost::is_arithmetic<A>,
+                    boost::is_arithmetic<B> >());
+        }
+
+        template <typename T>
+        bool operator()(const T& a, const T& b) const
+        {
+            // This code works for lists
+            return a == b;
+        }
+
+        template <typename Base, utree_type::info type_>
+        bool operator()(
+            basic_string<Base, type_> const& a,
+            basic_string<Base, type_> const& b) const
+        {
+            return static_cast<Base const&>(a) == static_cast<Base const&>(b);
+        }
+
+        bool operator()(nil, nil) const
+        {
+            return true;
+        }
+    };
+
+    struct utree_is_less_than
+    {
+        typedef bool result_type;
+
+        template <typename A, typename B>
+        bool dispatch(const A&, const B&, boost::mpl::false_) const
+        {
+            return false; // cannot compare different types by default
+        }
+
+        template <typename A, typename B>
+        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+        {
+            return a < b; // for arithmetic types
+        }
+
+        template <typename A, typename B>
+        bool operator()(const A& a, const B& b) const
+        {
+            return dispatch(a, b,
+                boost::mpl::and_<
+                    boost::is_arithmetic<A>,
+                    boost::is_arithmetic<B> >());
+        }
+
+        template <typename T>
+        bool operator()(const T& a, const T& b) const
+        {
+            // This code works for lists
+            return a < b;
+        }
+
+        template <typename Base, utree_type::info type_>
+        bool operator()(
+            basic_string<Base, type_> const& a,
+            basic_string<Base, type_> const& b) const
+        {
+            return static_cast<Base const&>(a) < static_cast<Base const&>(b);
+        }
+
+        bool operator()(nil, nil) const
+        {
+            BOOST_ASSERT(false);
+            return false; // no less than comparison for nil
+        }
+    };
+
+    struct utree_print
+    {
+        typedef void result_type;
+
+        std::ostream& out;
+        utree_print(std::ostream& out) : out(out) {}
+
+        void operator()(scheme::nil) const
+        {
+            out << "nil";
+        }
+
+        template <typename T>
+        void operator()(T val) const
+        {
+            out << val;
+        }
+
+        void operator()(bool b) const
+        {
+            out << (b ? "true" : "false");
+        }
+
+        void operator()(binary_range const& b) const
+        {
+            out << "b";
+            out.width(2);
+            out.fill('0');
+
+            typedef binary_range::const_iterator iterator;
+            for (iterator i = b.begin(); i != b.end(); ++i)
+                out << std::hex << int((unsigned char)*i);
+            out << std::dec;
+        }
+
+        void operator()(utf8_string_range const& str) const
+        {
+            typedef utf8_string_range::const_iterator iterator;
+            iterator i = str.begin();
+            out << '"';
+            for (; i != str.end(); ++i)
+                out << *i;
+            out << '"';
+        }
+
+        void operator()(utf8_symbol_range const& str) const
+        {
+            typedef utf8_symbol_range::const_iterator iterator;
+            iterator i = str.begin();
+            for (; i != str.end(); ++i)
+                out << *i;
+        }
+
+        template <typename Iterator>
+        void operator()(boost::iterator_range<Iterator> const& range) const
+        {
+            typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
+            (*this)('(');
+            for (iterator i = range.begin(); i != range.end(); ++i)
+            {
+                if (i != range.begin())
+                    (*this)(' ');
+                scheme::utree::visit(*i, *this);
+            }
+            (*this)(')');
+        }
+    };
+
+    template <typename Base>
+    struct arithmetic_function
+    {
+        typedef utree result_type;
+
+        template <typename A, typename B>
+        utree dispatch(A&, B&, boost::mpl::false_) const
+        {
+            // $$$ Throw exception here? $$$
+            return utree(); // cannot apply to different types
+        }
+
+        template <typename A, typename B>
+        utree dispatch(A& a, B& b, boost::mpl::true_) const
+        {
+            return Base::eval(a, b); // for arithmetic types
+        }
+
+        template <typename A, typename B>
+        utree operator()(A& a, B& b) const
+        {
+            return dispatch(a, b,
+                boost::mpl::and_<
+                    boost::is_arithmetic<A>,
+                    boost::is_arithmetic<B> >());
+        }
+    };
+
+    template <typename Base>
+    struct integral_function
+    {
+        typedef utree result_type;
+
+        template <typename A, typename B>
+        utree dispatch(A&, B&, boost::mpl::false_) const
+        {
+            // $$$ Throw exception here? $$$
+            return utree(); // cannot apply to different types
+        }
+
+        template <typename A, typename B>
+        utree dispatch(A& a, B& b, boost::mpl::true_) const
+        {
+            return Base::eval(a, b); // for integral types
+        }
+
+        template <typename A, typename B>
+        utree operator()(A& a, B& b) const
+        {
+            return dispatch(a, b,
+                boost::mpl::and_<
+                    boost::is_integral<A>,
+                    boost::is_integral<B> >());
+        }
+    };
+
+#define SCHEME_CREATE_FUNCTION(name, expr, base)                                \
+    struct BOOST_PP_CAT(function_impl_, name)                                   \
+    {                                                                           \
+        template <typename A, typename B>                                       \
+        static utree eval(A& a, B& b)                                           \
+        {                                                                       \
+            return utree(expr);                                                 \
+        }                                                                       \
+    };                                                                          \
+    base<BOOST_PP_CAT(function_impl_, name)> const                              \
+        BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {};                         \
+    /***/
+
+#define SCHEME_CREATE_ARITHMETIC_FUNCTION(name, expr)                           \
+    SCHEME_CREATE_FUNCTION(name, expr, arithmetic_function)                     \
+    /***/
+
+#define SCHEME_CREATE_INTEGRAL_FUNCTION(name, expr)                             \
+    SCHEME_CREATE_FUNCTION(name, expr, integral_function)                       \
+    /***/
+
+#define SCHEME_CREATE_ARITHMETIC_OPERATOR(name, op)                             \
+    SCHEME_CREATE_FUNCTION(name, a op b, arithmetic_function)                   \
+    inline utree operator op (utree const& a, utree const& b)                   \
+    {                                                                           \
+        return utree::visit(a, b, BOOST_PP_CAT(arithmetic_function, name));     \
+    }                                                                           \
+    /***/
+
+#define SCHEME_CREATE_INTEGRAL_OPERATOR(name, op)                               \
+    SCHEME_CREATE_FUNCTION(name, a op b, integral_function)                     \
+    inline utree operator op (utree const& a, utree const& b)                   \
+    {                                                                           \
+        return utree::visit(a, b, BOOST_PP_CAT(integral_function, name));       \
+    }                                                                           \
+    /***/
+
+    inline bool operator==(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, utree_is_equal());
+    }
+
+    inline bool operator<(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, utree_is_less_than());
+    }
+
+    inline bool operator!=(utree const& a, utree const& b)
+    {
+        return !(a == b);
+    }
+
+    inline bool operator>(utree const& a, utree const& b)
+    {
+        return b < a;
+    }
+
+    inline bool operator<=(utree const& a, utree const& b)
+    {
+        return !(b < a);
+    }
+
+    inline bool operator>=(utree const& a, utree const& b)
+    {
+        return !(a < b);
+    }
+
+    inline std::ostream& operator<<(std::ostream& out, utree const& x)
+    {
+        utree::visit(x, utree_print(out));
+        return out;
+    }
+
+    SCHEME_CREATE_ARITHMETIC_FUNCTION(plus, a+b);
+    SCHEME_CREATE_ARITHMETIC_FUNCTION(minus, a-b);
+    SCHEME_CREATE_ARITHMETIC_FUNCTION(times, a*b);
+    SCHEME_CREATE_ARITHMETIC_FUNCTION(divides, a/b);
+    SCHEME_CREATE_INTEGRAL_FUNCTION(modulus, a%b);
+
+    inline utree operator+(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, arithmetic_function_plus);
+    }
+
+    inline utree operator-(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, arithmetic_function_minus);
+    }
+
+    inline utree operator*(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, arithmetic_function_times);
+    }
+
+    inline utree operator/(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, arithmetic_function_divides);
+    }
+
+    inline utree operator%(utree const& a, utree const& b)
+    {
+        return utree::visit(a, b, integral_function_modulus);
+    }
+}
+
+#endif