$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61549 - in trunk/libs/spirit/example/scheme: . scheme test test/utree utree utree/detail
From: joel_at_[hidden]
Date: 2010-04-24 20:55:23
Author: djowel
Date: 2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
New Revision: 61549
URL: http://svn.boost.org/trac/boost/changeset/61549
Log:
various updates
Properties modified: 
   trunk/libs/spirit/example/scheme/test/   (props changed)
Text files modified: 
   trunk/libs/spirit/example/scheme/scheme/interpreter.hpp         |    15 +++++-                                  
   trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp        |    94 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/spirit/example/scheme/test/utree/utree_test.cpp      |    22 ++++++++                                
   trunk/libs/spirit/example/scheme/todo.txt                       |     1                                         
   trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp |    11 ++++                                    
   trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp |    49 ++++++++++++++++++++                    
   trunk/libs/spirit/example/scheme/utree/operators.hpp            |    11 ++++                                    
   trunk/libs/spirit/example/scheme/utree/utree.hpp                |    64 +++++++++++++++++++++++++-              
   8 files changed, 257 insertions(+), 10 deletions(-)
Modified: trunk/libs/spirit/example/scheme/scheme/interpreter.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme/interpreter.hpp	(original)
+++ trunk/libs/spirit/example/scheme/scheme/interpreter.hpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -17,6 +17,11 @@
 
 #define SCHEME_COMPOSITE_LIMIT 10
 
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4018)
+#endif
+
 namespace scheme
 {
 ///////////////////////////////////////////////////////////////////////////////
@@ -70,7 +75,7 @@
 
         template <std::size_t n>
         static scope
-        get_range(boost::array<utree, n> const& array)
+        get_range(boost::array<utree, n>& array)
         {
             return scope(array.begin(), array.end());
         }
@@ -121,7 +126,7 @@
         utree val;
         value_function(utree const& val) : val(val) {}
 
-        utree eval(scope /*env*/) const
+        utree eval(scope const& /*env*/) const
         {
             return utree(boost::ref(val));
         }
@@ -506,7 +511,7 @@
                 {
                     fargs[i++] = element(env);
                 }
-                utree const* fi = fargs.get();
+                utree* fi = fargs.get();
                 return f.get()(scope(fi, fi+elements.size(), outer));
             }
             else
@@ -542,4 +547,8 @@
     };
 }
 
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
 #endif
Modified: trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/qi_interpreter.cpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -11,9 +11,103 @@
 #include <input/parse_sexpr_impl.hpp>
 #include <scheme/compiler.hpp>
 #include <utree/io.hpp>
+#include <boost/spirit/include/qi.hpp>
 
 namespace scheme
 {
+    ///////////////////////////////////////////////////////////////////////////
+    // parser
+    ///////////////////////////////////////////////////////////////////////////
+    using boost::spirit::unused;
+    namespace qi = boost::spirit::qi;
+    namespace spirit = boost::spirit;
+
+    typedef boost::iterator_range<char const*> source_type;
+
+    template <typename Parser, bool no_attr>
+    struct qi_parser_function
+      : actor<qi_parser_function<Parser, no_attr> >
+    {
+        Parser p;
+        qi_parser_function(Parser const& p)
+          : p(p) {}
+
+        utree eval(scope const& env) const
+        {
+            // the source input
+            source_type rng = env[0].get<source_type>();
+            char const* iter = rng.begin();
+
+            // the skipper
+            utree const& skipper = env[1];
+
+            // do a pre-skip
+            while (skipper.eval(env) == true)
+                ;
+
+            // the attribute
+            utree& attribute = env[2];
+            bool r = false;
+            if (r = p.parse(iter, rng.end(), unused, unused, attribute))
+                env[0] = source_type(iter, rng.end());
+
+            return r;
+        }
+    };
+
+    template <typename Parser>
+    struct qi_parser_function<Parser, true> // unused attribute
+      : actor<qi_parser_function<Parser, true> >
+    {
+        Parser p;
+        qi_parser_function(Parser const& p)
+          : p(p) {}
+
+        utree eval(scope const& env) const
+        {
+            // the source input
+            source_type rng = env[0].get<source_type>();
+            char const* iter = rng.begin();
+
+            // the skipper
+            utree const& skipper = env[1];
+
+            // do a pre-skip
+            while (skipper.eval(env) == true)
+                ;
+
+            bool r = false;
+            if (r = p.parse(iter, rng.end(), unused, unused, unused))
+                env[0] = source_type(iter, rng.end());
+
+            return r;
+        }
+    };
+
+    struct qi_parser
+    {
+        typedef function result_type;
+
+        template <typename Expression>
+        function operator()(Expression const& expr) const
+        {
+            typedef typename
+                boost::spirit::result_of::compile<
+                    qi::domain, Expression>::type
+            parser_type;
+
+            typedef boost::is_same<
+                typename spirit::traits::attribute_of<parser_type>::type,
+                spirit::unused_type>
+            is_unused;
+
+            return function(qi_parser_function<parser_type, is_unused::value>(
+                qi::compile<qi::domain>(expr)));
+        }
+    };
+
+    qi_parser const primitive_parser = {};
+    function const space = primitive_parser(qi::space);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
Modified: trunk/libs/spirit/example/scheme/test/utree/utree_test.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/utree/utree_test.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/utree/utree_test.cpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -12,6 +12,7 @@
 #include <utree/io.hpp>
 #include <iostream>
 #include <sstream>
+#include <cstdlib>
 
 inline void check(scheme::utree const& val, std::string expected)
 {
@@ -54,6 +55,12 @@
     }
 
     {
+        // single element string
+        utree val('x');
+        check(val, "\"x\"");
+    }
+
+    {
         utree val(123.456);
         check(val, "123.456");
     }
@@ -303,12 +310,13 @@
     }
 
     {
+        // shallow string ranges
+
         using scheme::utf8_string_range;
         using scheme::shallow;
 
-        // shallow string ranges
         char const* s = "Hello, World";
-        utree val(utf8_string_range(s, s + std::strlen(s)), shallow);
+        utree val(utf8_string_range(s, s + strlen(s)), shallow);
         check(val, "\"Hello, World\"");
 
         utf8_string_range r = val.get<utf8_string_range>();
@@ -317,5 +325,15 @@
         check(val, "\"ello, Worl\"");
     }
 
+    {
+        // any pointer
+
+        using scheme::any_ptr;
+
+        int n = 123;
+        utree up = any_ptr(&n);
+        BOOST_TEST(*up.get<int*>() == 123);
+    }
+
     return boost::report_errors();
 }
Modified: trunk/libs/spirit/example/scheme/todo.txt
==============================================================================
--- trunk/libs/spirit/example/scheme/todo.txt	(original)
+++ trunk/libs/spirit/example/scheme/todo.txt	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -2,3 +2,4 @@
 - allow scheme-ish #t and #f
 - write parser and generator for binary on disk representation of sexpr
 - implement quote in sexpr grammar (e.g. 'sym '(1 2 3 4 5))
+- investigate storing and retrieving polymorphic pointers from utree
Modified: trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp	(original)
+++ trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -13,7 +13,9 @@
 {
     template <typename UTreeX, typename UTreeY>
     struct visit_impl;
+
     struct index_impl;
+
     template <typename T>
     struct get_impl;
 
@@ -74,6 +76,15 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    // A void* plus type_info
+    ///////////////////////////////////////////////////////////////////////////
+    struct void_ptr
+    {
+        void* p;
+        std::type_info const* i;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     // Our POD fast string. This implementation is very primitive and is not
     // meant to be used stand-alone. This is the internal data representation
     // of strings in our utree. This is deliberately a POD to allow it to be
Modified: trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp	(original)
+++ trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -13,6 +13,10 @@
 # pragma warning(disable: 4800)
 #endif
 
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+
 namespace scheme { namespace detail
 {
     inline char& fast_string::info()
@@ -480,6 +484,9 @@
                 case type::reference_type:
                     return apply(*x.p, f);
 
+                case type::any_type:
+                    return f(any_ptr(x.v.p, x.v.i));
+
                 case type::function_type:
                     return f(*x.pf);
             }
@@ -545,6 +552,10 @@
                 case type::reference_type:
                     return apply(*x.p, y, f);
 
+                case type::any_type:
+                    return visit_impl::apply(
+                        y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
+
                 case type::function_type:
                     return visit_impl::apply(y, detail::bind(f, *x.pf));
 
@@ -606,6 +617,13 @@
         set_type(type::bool_type);
     }
 
+    inline utree::utree(char c)
+    {
+        // char constructs a single element string
+        s.construct(&c, &c+1);
+        set_type(type::string_type);
+    }
+
     inline utree::utree(unsigned int i) : i(i)
     {
         set_type(type::int_type);
@@ -652,6 +670,13 @@
         set_type(type::reference_type);
     }
 
+    inline utree::utree(any_ptr const& p)
+    {
+        v.p = p.p;
+        v.i = p.i;
+        set_type(type::any_type);
+    }
+
     template <typename F>
     inline utree::utree(stored_function<F> const& pf)
       : pf(new stored_function<F>(pf))
@@ -1214,6 +1239,9 @@
             case type::reference_type:
                 p = other.p;
                 break;
+            case type::any_type:
+                v = other.v;
+                break;
             case type::range_type:
                 r = other.r;
                 break;
@@ -1260,7 +1288,7 @@
         To dispatch(From const& val, boost::mpl::false_) const
         {
             // From is NOT convertible to To !!!
-            BOOST_ASSERT(false);
+            throw std::bad_cast();
             return To();
         }
 
@@ -1278,6 +1306,25 @@
     };
 
     template <typename T>
+    struct utree_cast<T*>
+    {
+        typedef T* result_type;
+
+        template <typename From>
+        T* operator()(From const& val) const
+        {
+            // From is NOT convertible to T !!!
+            throw std::bad_cast();
+            return 0;
+        }
+
+        T* operator()(any_ptr const& p) const
+        {
+            return p.get<T*>();
+        }
+    };
+
+    template <typename T>
     inline T utree::get() const
     {
         return utree::visit(*this, utree_cast<T>());
Modified: trunk/libs/spirit/example/scheme/utree/operators.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/operators.hpp	(original)
+++ trunk/libs/spirit/example/scheme/utree/operators.hpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -177,6 +177,12 @@
             return false; // no less than comparison for nil
         }
 
+        bool operator()(any_ptr const& a, any_ptr const& b) const
+        {
+            BOOST_ASSERT(false);
+            return false; // no less than comparison for any_ptr
+        }
+
         bool operator()(function_base const& a, function_base const& b) const
         {
             BOOST_ASSERT(false);
@@ -251,6 +257,11 @@
             (*this)(')');
         }
 
+        void operator()(any_ptr const& p) const
+        {
+            return (*this)("<pointer>");
+        }
+
         void operator()(function_base const& pf) const
         {
             return (*this)("<function>");
Modified: trunk/libs/spirit/example/scheme/utree/utree.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/utree.hpp	(original)
+++ trunk/libs/spirit/example/scheme/utree/utree.hpp	2010-04-24 20:55:21 EDT (Sat, 24 Apr 2010)
@@ -12,12 +12,17 @@
 #include <algorithm>
 #include <string>
 #include <ostream>
+#include <typeinfo>
 
 #include <boost/assert.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/iterator/iterator_facade.hpp>
 #include <boost/range/iterator_range.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/utility/enable_if.hpp>
 #include <boost/ref.hpp>
+
 #include <utree/detail/utree_detail1.hpp>
 
 #if defined(BOOST_MSVC)
@@ -48,6 +53,7 @@
             list_type,
             range_type,
             reference_type,
+            any_type,
             function_type
         };
     };
@@ -163,6 +169,52 @@
     shallow_tag const shallow = {};
 
     ///////////////////////////////////////////////////////////////////////////
+    // A void* plus type_info
+    ///////////////////////////////////////////////////////////////////////////
+    class any_ptr
+    {
+    public:
+
+        template <typename Ptr>
+        typename boost::disable_if<
+            boost::is_polymorphic<
+                typename boost::remove_pointer<Ptr>::type>,
+            Ptr>::type
+        get() const
+        {
+            if (*i == typeid(Ptr))
+            {
+                return static_cast<Ptr>(p);
+            }
+            throw std::bad_cast();
+        }
+
+        template <typename T>
+        any_ptr(T* p)
+          : p(p), i(&typeid(T*))
+        {}
+
+        friend bool operator==(any_ptr const& a, any_ptr const& b)
+        {
+            return (a.p == b.p) && (*a.i == *b.i);
+        }
+
+    private:
+
+        // constructor is private
+        any_ptr(void* p, std::type_info const* i)
+          : p(p), i(i) {}
+
+        template <typename UTreeX, typename UTreeY>
+        friend struct detail::visit_impl;
+
+        friend class utree;
+
+        void* p;
+        std::type_info const* i;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     // The main utree (Universal Tree) class
     // The utree is a hierarchical, dynamic type that can store:
     //  - a nil
@@ -176,6 +228,7 @@
     //  - a (doubly linked) list of utree
     //  - an iterator_range of list::iterator
     //  - a reference to a utree
+    //  - a pointer or reference to any type
     //  - a function
     //
     // The utree has minimal memory footprint. The data structure size is
@@ -201,6 +254,7 @@
 
         utree();
         utree(bool b);
+        utree(char c);
         utree(unsigned int i);
         utree(int i);
         utree(double d);
@@ -208,6 +262,7 @@
         utree(char const* str, std::size_t len);
         utree(std::string const& str);
         utree(boost::reference_wrapper<utree> ref);
+        utree(any_ptr const& p);
 
         template <typename Iter>
         utree(boost::iterator_range<Iter> r);
@@ -347,6 +402,7 @@
             detail::list l;
             detail::range r;
             detail::string_range sr;
+            detail::void_ptr v;
             bool b;
             int i;
             double d;
@@ -358,14 +414,14 @@
     ///////////////////////////////////////////////////////////////////////////
     // The scope
     ///////////////////////////////////////////////////////////////////////////
-    class scope : public boost::iterator_range<utree const*>
+    class scope : public boost::iterator_range<utree*>
     {
     public:
 
-        scope(utree const* first = 0,
-            utree const* last = 0,
+        scope(utree* first = 0,
+            utree* last = 0,
             scope const* parent = 0)
-          : boost::iterator_range<utree const*>(first, last),
+          : boost::iterator_range<utree*>(first, last),
             parent(parent),
             depth(parent? parent->depth + 1 : 0)
         {}