$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61480 - in trunk/libs/spirit/example/scheme: example/scheme scheme test/utree utree utree/detail
From: joel_at_[hidden]
Date: 2010-04-22 04:50:27
Author: djowel
Date: 2010-04-22 04:50:25 EDT (Thu, 22 Apr 2010)
New Revision: 61480
URL: http://svn.boost.org/trac/boost/changeset/61480
Log:
variable args support
Added:
   trunk/libs/spirit/example/scheme/example/scheme/more_scheme.scm   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm |     5                                         
   trunk/libs/spirit/example/scheme/scheme/compiler.hpp            |   117 ++++++++++++++++------                  
   trunk/libs/spirit/example/scheme/scheme/interpreter.hpp         |     1                                         
   trunk/libs/spirit/example/scheme/scheme/intrinsics.hpp          |   204 ++++++++++++++++++++++++--------------- 
   trunk/libs/spirit/example/scheme/test/utree/utree_test.cpp      |    14 ++                                      
   trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp |    66 +++++++-----                            
   trunk/libs/spirit/example/scheme/utree/utree.hpp                |    19 +++                                     
   7 files changed, 287 insertions(+), 139 deletions(-)
Added: trunk/libs/spirit/example/scheme/example/scheme/more_scheme.scm
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/scheme/example/scheme/more_scheme.scm	2010-04-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -0,0 +1,24 @@
+(define (apply x f) (display (f x)))
+
+(apply 5 (lambda (x) (* x 5)))
+
+(display (quote (1 2 3 4 5)))
+
+(display (quote ()))
+
+
+(define for_each
+    lambda (x f)
+        f()
+
+
+(define (display-all . args)
+    (display args))
+
+(display-all 123 456 999 666)
+
+(display (+ 1 2 3 4 5 6))
+
+(define (display-all first . rest) (display first) (display rest))
+
+(display-all 123 456 999 666)
\ No newline at end of file
Modified: trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm
==============================================================================
--- trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm	(original)
+++ trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm	2010-04-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -1 +1,4 @@
-(display (xxx 2 3 4 5))
\ No newline at end of file
+(define (display-all . args)
+    (display args))
+
+(display-all 123 456 999 666)
\ No newline at end of file
Modified: trunk/libs/spirit/example/scheme/scheme/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme/compiler.hpp	(original)
+++ trunk/libs/spirit/example/scheme/scheme/compiler.hpp	2010-04-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -10,10 +10,10 @@
 #include <vector>
 #include <map>
 #include <exception>
-#include <cstdlib>
 
 #include <boost/bind.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <boost/lexical_cast.hpp>
 #include <scheme/intrinsics.hpp>
 #include <scheme/interpreter.hpp>
 #include <input/parse_sexpr.hpp>
@@ -27,6 +27,7 @@
 
     struct compilation_error : std::exception
     {
+        ~compilation_error() throw() {}
         virtual const char* what() const throw()
         {
             return "scheme: Compilation error.";
@@ -35,6 +36,7 @@
 
     struct identifier_expected : scheme_exception
     {
+        ~identifier_expected() throw() {}
         virtual const char* what() const throw()
         {
             return "scheme: Identifier expected.";
@@ -46,6 +48,7 @@
         std::string msg;
         identifier_not_found(std::string const& id)
           : msg("scheme: Identifier (" + id + ") not found.") {}
+        ~identifier_not_found() throw() {}
 
         virtual const char* what() const throw()
         {
@@ -58,6 +61,7 @@
         std::string msg;
         duplicate_identifier(std::string const& id)
           : msg("scheme: Duplicate identifier (" + id + ").") {}
+        ~duplicate_identifier() throw() {}
 
         virtual const char* what() const throw()
         {
@@ -77,9 +81,9 @@
             else
                 msg += std::string(" Expecting ");
 
-            char buff[std::numeric_limits<int>::digits10];
-            msg += std::string(ltoa(arity, buff, 10)) + " arguments.";
+            msg += boost::lexical_cast<std::string>(arity) + " arguments.";
         }
+        ~incorrect_arity() throw() {}
 
         virtual const char* what() const throw()
         {
@@ -95,6 +99,7 @@
             // $$$ TODO: add got to message $$$
             msg = "scheme: Function application expected";
         }
+        ~function_application_expected() throw() {}
 
         virtual const char* what() const throw()
         {
@@ -227,27 +232,35 @@
 
         function make_lambda(
             std::vector<std::string> const& args,
+            bool fixed_arity,
             utree const& body) const
         {
             environment local_env(&this->env);
             for (std::size_t i = 0; i < args.size(); ++i)
-                local_env.define(args[i], boost::bind(arg, i), 0, false);
-            return protect(compile(body, local_env, fragments, line, source_file));
+            {
+                if (!fixed_arity && (args.size() - 1) == i)
+                    local_env.define(args[i], boost::bind(varg, i), 0, false);
+                else
+                    local_env.define(args[i], boost::bind(arg, i), 0, false);
+            }
+            return protect(compile(body[0], local_env, fragments, line, source_file));
         }
 
         function define_function(
             std::string const& name,
-            std::vector<std::string> const& args,
+            std::vector<std::string>& args,
+            bool fixed_arity,
             utree const& body) const
         {
             try
             {
                 if (env.defined(name))
                     throw duplicate_identifier(name);
+
                 fragments.push_back(function());
                 function& f = fragments.back();
-                env.define(name, external_function(f), args.size(), true); // $$$ fixed arity for now $$$
-                f = make_lambda(args, body)(); // unprotect (evaluate returns a function)
+                env.define(name, external_function(f), args.size(), fixed_arity);
+                f = make_lambda(args, fixed_arity, body)(); // unprotect (evaluate returns a function)
                 return f;
             }
             catch (compilation_error const&)
@@ -257,9 +270,10 @@
             }
         }
 
-        template <typename Iterator>
-        function operator()(boost::iterator_range<Iterator> const& range) const
+        function operator()(utree::const_range const& range) const
         {
+            typedef utree::const_range::iterator iterator;
+
             if (range.begin()->which() != utree_type::symbol_type)
                 throw function_application_expected(*range.begin());
 
@@ -267,7 +281,7 @@
 
             if (name == "quote")
             {
-                Iterator i = range.begin(); ++i;
+                iterator i = range.begin(); ++i;
                 return scheme::val(*i);
             }
 
@@ -275,16 +289,24 @@
             {
                 std::string fname;
                 std::vector<std::string> args;
+                bool fixed_arity = true;
 
-                Iterator i = range.begin(); ++i;
+                iterator i = range.begin(); ++i;
                 if (i->which() == utree_type::list_type)
                 {
                     // (define (f x) ...body...)
                     utree const& decl = *i++;
-                    Iterator di = decl.begin();
+                    iterator di = decl.begin();
                     fname = get_symbol(*di++);
                     while (di != decl.end())
-                        args.push_back(get_symbol(*di++));
+                    {
+                        std::string sym = get_symbol(*di++);
+                        if (sym == ".")
+                           // check that . is one pos behind the last arg
+                           fixed_arity = false;
+                        else
+                            args.push_back(sym);
+                    }
                 }
                 else
                 {
@@ -296,51 +318,79 @@
                         && get_symbol((*i)[0]) == "lambda")
                     {
                         utree const& arg_names = (*i)[1];
-                        Iterator ai = arg_names.begin();
+                        iterator ai = arg_names.begin();
                         while (ai != arg_names.end())
-                            args.push_back(get_symbol(*ai++));
-
-                        return define_function(fname, args, (*i)[2]);
+                        {
+                            std::string sym = get_symbol(*ai++);
+                            if (sym == ".")
+                                // check that . is one pos behind the last arg
+                                fixed_arity = false;
+                            else
+                                args.push_back(sym);
+                        };
+
+                        iterator bi = i->begin(); ++bi; ++bi; // (*i)[2]
+                        utree body(utree::const_range(bi, i->end()), shallow);
+                        return define_function(fname, args, fixed_arity, body);
                     }
                 }
 
-                return define_function(fname, args, *i);
+                utree body(utree::const_range(i, range.end()), shallow);
+                return define_function(fname, args, fixed_arity, body);
             }
 
             if (name == "lambda")
             {
                 // (lambda (x) ...body...)
-                Iterator i = range.begin(); ++i;
+                iterator i = range.begin(); ++i;
                 utree const& arg_names = *i++;
-                Iterator ai = arg_names.begin();
+                iterator ai = arg_names.begin();
                 std::vector<std::string> args;
+                bool fixed_arity = true;
+
                 while (ai != arg_names.end())
-                    args.push_back(get_symbol(*ai++));
-                return make_lambda(args, *i);
+                {
+                    std::string sym = get_symbol(*ai++);
+                    if (sym == ".")
+                        // check that . is one pos behind the last arg
+                        fixed_arity = false;
+                    else
+                        args.push_back(sym);
+                }
+
+                utree body(utree::const_range(i, range.end()), shallow);
+                return make_lambda(args, fixed_arity, body);
             }
 
             // (f x)
             boost::tuple<compiled_function*, int, bool> r = env.find(name);
             if (boost::get<0>(r))
             {
+                compiled_function* cf = boost::get<0>(r);
+                int arity = boost::get<1>(r);
+                bool fixed_arity = boost::get<2>(r);
+
                 actor_list flist;
-                Iterator i = range.begin(); ++i;
-                for (; i != range.end(); ++i)
+                iterator i = range.begin(); ++i;
+                int size = 0;
+                for (; i != range.end(); ++i, ++size)
+                {
                     flist.push_back(
                         compile(*i, env, fragments, line, source_file));
+                }
 
                 // Arity check
-                if (!boost::get<2>(r)) // non-fixed arity
+                if (!fixed_arity) // non-fixed arity
                 {
-                    if (int(flist.size()) < boost::get<1>(r))
-                        throw incorrect_arity(name, boost::get<1>(r), false);
+                    if (size < arity)
+                        throw incorrect_arity(name, arity, false);
                 }
                 else // fixed arity
                 {
-                    if (int(flist.size()) != boost::get<1>(r))
-                        throw incorrect_arity(name, boost::get<1>(r), true);
+                    if (size != arity)
+                        throw incorrect_arity(name, arity, true);
                 }
-                return (*boost::get<0>(r))(flist);
+                return (*cf)(flist);
             }
             else
             {
@@ -426,12 +476,17 @@
     void build_basic_environment(environment& env)
     {
         env.define("if", if_, 3, true);
+        env.define("begin", block, 1, false);
         env.define("display", display, 1, true);
+        env.define("front", front, 1, true);
+        env.define("back", back, 1, true);
+        env.define("rest", rest, 1, true);
         env.define("<", less_than, 2, true);
         env.define("<=", less_than_equal, 2, true);
         env.define("+", plus, 2, false);
         env.define("-", minus, 2, false);
         env.define("*", times, 2, false);
+        env.define("/", divide, 2, false);
     }
 
     ///////////////////////////////////////////////////////////////////////////
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-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -366,6 +366,7 @@
 
         utree eval(args_type args) const
         {
+            BOOST_ASSERT(!elements.empty());
             actor_list::const_iterator i = elements.begin();
             utree result = (*i++)(args);
             boost::iterator_range<actor_list::const_iterator>
Modified: trunk/libs/spirit/example/scheme/scheme/intrinsics.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme/intrinsics.hpp	(original)
+++ trunk/libs/spirit/example/scheme/scheme/intrinsics.hpp	2010-04-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -51,122 +51,166 @@
     if_composite const if_ = if_composite();
 
     ///////////////////////////////////////////////////////////////////////////
-    // less_than
+    // list
     ///////////////////////////////////////////////////////////////////////////
-    struct less_than_function
-      : binary_function<less_than_function>
+    struct list_function : actor<list_function>
     {
-        less_than_function(function const& a, function const& b)
-          : base_type(a, b) {}
+        actor_list elements;
+        list_function(actor_list const& elements)
+          : elements(elements)
+        {
+            BOOST_FOREACH(function const& element, elements)
+            {
+                BOOST_ASSERT(!element.empty());
+            }
+        }
 
-        typedef utree result_type;
-        utree eval(utree const& a, utree const& b) const
+        utree eval(args_type args) const
         {
-            return a < b;
+			utree result;
+            BOOST_FOREACH(function const& element, elements)
+            {
+                result.push_back(element(args));
+            }
+            return result;
         }
     };
 
-    struct less_than_composite
-      : binary_composite<less_than_function> {};
-
-    less_than_composite const less_than
-        = less_than_composite();
-    less_than_composite const lt = less_than; // synonym
-
-    ///////////////////////////////////////////////////////////////////////////
-    // less_than_equal
-    ///////////////////////////////////////////////////////////////////////////
-    struct less_than_equal_function
-      : binary_function<less_than_equal_function>
+    struct list_composite : composite<list_composite>
     {
-        less_than_equal_function(function const& a, function const& b)
-          : base_type(a, b) {}
-
-        typedef utree result_type;
-        utree eval(utree const& a, utree const& b) const
+        function compose(actor_list const& elements) const
         {
-            return a <= b;
+            return function(list_function(elements));
         }
     };
 
-    struct less_than_equal_composite
-      : binary_composite<less_than_equal_function> {};
-
-    less_than_equal_composite const less_than_equal
-        = less_than_equal_composite();
-    less_than_equal_composite const lte = less_than_equal; // synonym
+    list_composite const list = list_composite();
 
     ///////////////////////////////////////////////////////////////////////////
-    // plus
+    // block
     ///////////////////////////////////////////////////////////////////////////
-    struct plus_function : nary_function<plus_function>
+    struct block_function : actor<block_function>
     {
-        plus_function(actor_list const& elements)
-          : base_type(elements) {}
+        actor_list elements;
+        block_function(actor_list const& elements)
+          : elements(elements)
+        {
+            BOOST_FOREACH(function const& element, elements)
+            {
+                BOOST_ASSERT(!element.empty());
+            }
+        }
 
-        bool eval(utree& result, utree const& element) const
+        utree eval(args_type args) const
         {
-            result = result + element;
-            return true;
+            BOOST_ASSERT(!elements.empty());
+            actor_list::const_iterator end = elements.end();
+            boost::iterator_range<actor_list::const_iterator>
+                head_elements(elements.begin(), end--);
+            BOOST_FOREACH(function const& element, head_elements)
+            {
+                element(args);
+            }
+            return (*end)(args);
         }
     };
 
-    struct plus_composite : nary_composite<plus_function> {};
-    plus_composite const plus = plus_composite();
-
-    ///////////////////////////////////////////////////////////////////////////
-    // minus
-    ///////////////////////////////////////////////////////////////////////////
-    struct minus_function : nary_function<minus_function>
+    struct block_composite : composite<block_composite>
     {
-        minus_function(actor_list const& elements)
-          : base_type(elements) {}
-
-        bool eval(utree& result, utree const& element) const
+        function compose(actor_list const& elements) const
         {
-            result = result - element;
-            return true;
+            return function(block_function(elements));
         }
     };
 
-    struct minus_composite : nary_composite<minus_function> {};
-    minus_composite const minus = minus_composite();
+    block_composite const block = block_composite();
 
     ///////////////////////////////////////////////////////////////////////////
-    // times
+    // SCHEME_UNARY_INTRINSIC
     ///////////////////////////////////////////////////////////////////////////
-    struct times_function : nary_function<times_function>
-    {
-        times_function(actor_list const& elements)
-          : base_type(elements) {}
+#define SCHEME_UNARY_INTRINSIC(name, expression)                                \
+    struct name##_function : unary_function<name##_function>                    \
+    {                                                                           \
+        name##_function(function const& a)                                      \
+          : base_type(a) {}                                                     \
+                                                                                \
+        utree eval(utree const& element) const                                  \
+        {                                                                       \
+            return expression;                                                  \
+        }                                                                       \
+    };                                                                          \
+                                                                                \
+    struct name##_composite : unary_composite<name##_function> {};              \
+    name##_composite const name = name##_composite()                            \
+    /***/
 
-        bool eval(utree& result, utree const& element) const
-        {
-            result = result * element;
-            return true;
-        }
-    };
+    ///////////////////////////////////////////////////////////////////////////
+    // SCHEME_BINARY_INTRINSIC
+    ///////////////////////////////////////////////////////////////////////////
+#define SCHEME_BINARY_INTRINSIC(name, expression)                               \
+    struct name##_function                                                      \
+      : binary_function<name##_function>                                        \
+    {                                                                           \
+        name##_function(function const& a, function const& b)                   \
+          : base_type(a, b) {}                                                  \
+                                                                                \
+        typedef utree result_type;                                              \
+        utree eval(utree const& a, utree const& b) const                        \
+        {                                                                       \
+            return expression;                                                  \
+        }                                                                       \
+    };                                                                          \
+                                                                                \
+    struct name##_composite                                                     \
+      : binary_composite<name##_function> {};                                   \
+                                                                                \
+    name##_composite const name = name##_composite()                            \
+    /***/
 
-    struct times_composite : nary_composite<times_function> {};
-    times_composite const times = times_composite();
+    ///////////////////////////////////////////////////////////////////////////
+    // SCHEME_NARY_INTRINSIC
+    ///////////////////////////////////////////////////////////////////////////
+#define SCHEME_NARY_INTRINSIC(name, expression)                                 \
+    struct name##_function : nary_function<name##_function>                     \
+    {                                                                           \
+        name##_function(actor_list const& elements)                             \
+          : base_type(elements) {}                                              \
+                                                                                \
+        bool eval(utree& result, utree const& element) const                    \
+        {                                                                       \
+            expression;                                                         \
+            return true;                                                        \
+        }                                                                       \
+    };                                                                          \
+                                                                                \
+    struct name##_composite : nary_composite<name##_function> {};               \
+    name##_composite const name = name##_composite()                            \
+    /***/
 
     ///////////////////////////////////////////////////////////////////////////
-    // display
+    // unary intrinsics
     ///////////////////////////////////////////////////////////////////////////
-    struct display_function : unary_function<display_function>
-    {
-        display_function(function const& a)
-          : base_type(a) {}
+    SCHEME_UNARY_INTRINSIC(display, (std::cout << element, utree()));
+    SCHEME_UNARY_INTRINSIC(front, element.front());
+    SCHEME_UNARY_INTRINSIC(back, element.back());
+    SCHEME_UNARY_INTRINSIC(rest, utree_functions::rest(element));
 
-        utree eval(utree const& element) const
-        {
-            std::cout << element;
-            return utree();
-        }
-    };
+    ///////////////////////////////////////////////////////////////////////////
+    // binary intrinsics
+    ///////////////////////////////////////////////////////////////////////////
+    SCHEME_BINARY_INTRINSIC(less_than, a < b);
+    less_than_composite const lt = less_than; // synonym
 
-    struct display_composite : unary_composite<display_function> {};
-    display_composite const display = display_composite();
+    SCHEME_BINARY_INTRINSIC(less_than_equal, a <= b);
+    less_than_equal_composite const lte = less_than_equal; // synonym
+
+    ///////////////////////////////////////////////////////////////////////////
+    // nary intrinsics
+    ///////////////////////////////////////////////////////////////////////////
+    SCHEME_NARY_INTRINSIC(plus, result = result + element);
+    SCHEME_NARY_INTRINSIC(minus, result = result - element);
+    SCHEME_NARY_INTRINSIC(times, result = result * element);
+    SCHEME_NARY_INTRINSIC(divide, result = result / element);
 }
 
 #endif
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-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -181,6 +181,20 @@
         BOOST_TEST(a[11] == utree(12));
     }
 
+    {
+        // test empty list
+        utree a;
+        a.push_back(1);
+        a.pop_front();
+        check(a, "( )");
+
+        // the other way around
+        utree b;
+        b.push_front(1);
+        b.pop_back();
+        check(b, "( )");
+    }
+
     { // test references
         utree val(123);
         utree ref(boost::ref(val));
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-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -148,9 +148,6 @@
         node_iterator()
           : node(0) {}
 
-        explicit node_iterator(list::node* node)
-          : node(node), prev(node->prev) {}
-
         node_iterator(list::node* node, list::node* prev)
           : node(node), prev(prev) {}
 
@@ -204,9 +201,6 @@
         node_iterator()
           : node(0), prev(0), curr(nil_node) {}
 
-        explicit node_iterator(list::node* node)
-          : node(node), prev(node->prev), curr(node->val) {}
-
         node_iterator(list::node* node, list::node* prev)
           : node(node), prev(prev), curr(node ? node->val : nil_node) {}
 
@@ -340,21 +334,39 @@
     inline void list::pop_front()
     {
         BOOST_ASSERT(size != 0);
-        node* np = first;
-        first = first->next;
-        first->prev = 0;
-        delete np;
-        --size;
+        if (first == last) // there's only one item
+        {
+            delete first;
+            size = 0;
+            first = last = 0;
+        }
+        else
+        {
+            node* np = first;
+            first = first->next;
+            first->prev = 0;
+            delete np;
+            --size;
+        }
     }
 
     inline void list::pop_back()
     {
         BOOST_ASSERT(size != 0);
-        node* np = last;
-        last = last->prev;
-        last->next = 0;
-        delete np;
-        --size;
+        if (first == last) // there's only one item
+        {
+            delete first;
+            size = 0;
+            first = last = 0;
+        }
+        else
+        {
+            node* np = last;
+            last = last->prev;
+            last->next = 0;
+            delete np;
+            --size;
+        }
     }
 
     inline list::node* list::erase(node* pos)
@@ -448,10 +460,10 @@
                     return f(x.d);
 
                 case type::list_type:
-                    return f(list_range(iterator(x.l.first), iterator(0, x.l.last)));
+                    return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
 
                 case type::range_type:
-                    return f(list_range(iterator(x.r.first), iterator(0, x.r.last)));
+                    return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
 
                 case type::string_type:
                     return f(utf8_string_range(x.s.str(), x.s.size()));
@@ -504,12 +516,12 @@
                 case type::list_type:
                     return visit_impl::apply(
                         y, detail::bind<F, list_range>(f,
-                        list_range(iterator(x.l.first), iterator(0, x.l.last))));
+                        list_range(iterator(x.l.first, 0), iterator(0, x.l.last))));
 
                 case type::range_type:
                     return visit_impl::apply(
                         y, detail::bind<F, list_range>(f,
-                        list_range(iterator(x.r.first), iterator(0, x.r.last))));
+                        list_range(iterator(x.r.first, 0), iterator(0, x.r.last))));
 
                 case type::string_type:
                     return visit_impl::apply(y, detail::bind(
@@ -861,7 +873,7 @@
         else
         {
             l.insert_before(val, pos.node);
-            return utree::iterator(pos.node->prev);
+            return utree::iterator(pos.node->prev, pos.node->prev->prev);
         }
     }
 
@@ -943,11 +955,11 @@
         if (get_type() == type::reference_type)
             return p->begin();
         else if (get_type() == type::range_type)
-            return iterator(r.first);
+            return iterator(r.first, 0);
 
         // otherwise...
         ensure_list_type();
-        return iterator(l.first);
+        return iterator(l.first, 0);
     }
 
     inline utree::iterator utree::end()
@@ -967,11 +979,11 @@
         if (get_type() == type::reference_type)
             return p->ref_begin();
         else if (get_type() == type::range_type)
-            return ref_iterator(r.first);
+            return ref_iterator(r.first, 0);
 
         // otherwise...
         ensure_list_type();
-        return ref_iterator(l.first);
+        return ref_iterator(l.first, 0);
     }
 
     inline utree::ref_iterator utree::ref_end()
@@ -991,11 +1003,11 @@
         if (get_type() == type::reference_type)
             return ((utree const*)p)->begin();
         else if (get_type() == type::range_type)
-            return const_iterator(r.first);
+            return const_iterator(r.first, 0);
 
         // otherwise...
         BOOST_ASSERT(get_type() == type::list_type);
-        return const_iterator(l.first);
+        return const_iterator(l.first, 0);
     }
 
     inline utree::const_iterator utree::end() const
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-22 04:50:25 EDT (Thu, 22 Apr 2010)
@@ -356,4 +356,23 @@
 
 #include <utree/detail/utree_detail2.hpp>
 
+// $$$ move this in its own file $$$
+namespace scheme { namespace utree_functions
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // Extra functions
+    ///////////////////////////////////////////////////////////////////////////
+    inline utree rest(utree& x)
+    {
+        utree::iterator i = x.begin(); ++i;
+        return utree(utree::range(i, x.end()), shallow);
+    }
+
+    inline utree rest(utree const& x)
+    {
+        utree::const_iterator i = x.begin(); ++i;
+        return utree(utree::const_range(i, x.end()), shallow);
+    }
+}}
+
 #endif