$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61127 - in trunk/libs/spirit/example/scheme: . detail input test
From: joel_at_[hidden]
Date: 2010-04-07 10:23:58
Author: djowel
Date: 2010-04-07 10:23:57 EDT (Wed, 07 Apr 2010)
New Revision: 61127
URL: http://svn.boost.org/trac/boost/changeset/61127
Log:
very rough sketch (scheme interpreter)
Text files modified: 
   trunk/libs/spirit/example/scheme/detail/utree_detail2.hpp |    34 ++++                                    
   trunk/libs/spirit/example/scheme/input/sexpr.hpp          |     1                                         
   trunk/libs/spirit/example/scheme/test/scheme.cpp          |   263 +++++++++++++++++++++++++++------------ 
   trunk/libs/spirit/example/scheme/utree.hpp                |    17 +-                                      
   trunk/libs/spirit/example/scheme/utree_operators.hpp      |    57 +++++--                                 
   5 files changed, 261 insertions(+), 111 deletions(-)
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-07 10:23:57 EDT (Wed, 07 Apr 2010)
@@ -820,7 +820,7 @@
         return 0;
     }
 
-    inline int utree::which() const
+    inline utree_type::info utree::which() const
     {
         return get_type();
     }
@@ -934,10 +934,36 @@
         }
     }
 
-    inline utree::utree(construct_list)
+    template <typename To>
+    struct utree_cast
     {
-        l.default_construct();
-        set_type(type::list_type);
+        typedef To result_type;
+
+        template <typename From>
+        To dispatch(From const& val, boost::mpl::true_) const
+        {
+            return To(val); // From is convertible to To
+        }
+
+        template <typename From>
+        To dispatch(From const& val, boost::mpl::false_) const
+        {
+            // From is NOT convertible to To !!!
+            BOOST_ASSERT(false);
+            return To();
+        }
+
+        template <typename From>
+        To operator()(From const& val) const
+        {
+            return dispatch(val, boost::is_convertible<From, To>());
+        }
+    };
+
+    template <typename T>
+    inline T utree::as() const
+    {
+        return utree::visit(*this, utree_cast<T>());
     }
 }
 
Modified: trunk/libs/spirit/example/scheme/input/sexpr.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/input/sexpr.hpp	(original)
+++ trunk/libs/spirit/example/scheme/input/sexpr.hpp	2010-04-07 10:23:57 EDT (Wed, 07 Apr 2010)
@@ -18,6 +18,7 @@
 #include <boost/regex/pending/unicode_iterator.hpp>
 
 #include "../utree.hpp"
+#include "../utree_operators.hpp"
 
 namespace scheme { namespace input
 {
Modified: trunk/libs/spirit/example/scheme/test/scheme.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/scheme.cpp	(original)
+++ trunk/libs/spirit/example/scheme/test/scheme.cpp	2010-04-07 10:23:57 EDT (Wed, 07 Apr 2010)
@@ -17,131 +17,234 @@
     return out;
 }
 
-#include <boost/unordered_map.hpp>
+#include <vector>
+#include <list>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/foreach.hpp>
 
 namespace scheme
 {
-    class environment
-    {
-    public:
+///////////////////////////////////////////////////////////////////////////////
+//  The runtime interpreter
+///////////////////////////////////////////////////////////////////////////////
 
-        environment(environment* parent = 0)
-          : bindings(), parent(parent) {}
+    typedef boost::function<utree(utree const& args)> function;
+    typedef std::list<function> function_list;
 
-        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;
-        }
+    ///////////////////////////////////////////////////////////////////////////
+    // values
+    ///////////////////////////////////////////////////////////////////////////
+    struct value_impl
+    {
+        utree val;
+        value_impl(utree const& val) : val(val) {}
 
-        utree* find(std::string const& name)
+        typedef utree result_type;
+        utree operator()(utree const& /*args*/) const
         {
-            map::iterator i = bindings.find(name);
-            if (i == bindings.end())
-            {
-                if (parent)
-                    return parent->find(name);
-                return 0;
-            }
-            return &i->second;
+            return utree(boost::ref(val));
         }
+    };
 
-    private:
+    inline function val(utree const& val)
+    {
+        return function(value_impl(val));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // arguments
+    ///////////////////////////////////////////////////////////////////////////
+    struct argument_impl
+    {
+        int n;
+        argument_impl(int n) : n(n) {}
 
-        typedef boost::unordered_map<std::string, utree> map;
-        map bindings;
-        environment* parent;
+        typedef utree result_type;
+        utree operator()(utree const& args) const
+        {
+            return utree(boost::ref(args[n]));
+        }
     };
 
+    inline function arg(int n)
+    {
+        return function(argument_impl(n));
+    }
+
     ///////////////////////////////////////////////////////////////////////////
-    // Intrinsic functions
+    // reference
     ///////////////////////////////////////////////////////////////////////////
-    struct arithmetic_function
+    struct reference_impl
     {
-        typedef bool result_type;
+        function& f;
+        reference_impl(function& f) : f(f) {}
 
-        template <typename A, typename B>
-        bool dispatch(const A&, const B&, boost::mpl::false_) const
+        typedef utree result_type;
+        utree operator()(utree const& args) const
         {
-            return false; // cannot compare different types by default
+            return f(args);
         }
+    };
+
+    inline function ref(function& f)
+    {
+        return function(reference_impl(f));
+    }
 
-        template <typename A, typename B>
-        bool dispatch(const A& a, const B& b, boost::mpl::true_) const
+    ///////////////////////////////////////////////////////////////////////////
+    // plus
+    ///////////////////////////////////////////////////////////////////////////
+    struct plus_impl
+    {
+        function_list operands;
+
+        plus_impl(function_list& operands_)
         {
-            return a == b; // for arithmetic types
+            // we take ownership of the operands
+            operands_.swap(operands);
         }
 
-        template <typename A, typename B>
-        bool operator()(const A& a, const B& b) const
+        typedef utree result_type;
+        utree operator()(utree const& args) const
         {
-            return dispatch(a, b,
-                boost::mpl::and_<
-                    boost::is_arithmetic<A>,
-                    boost::is_arithmetic<B> >());
+            utree result(0);
+            BOOST_FOREACH(function const& operand, operands)
+            {
+                result = result + operand(args);
+            }
+            return result;
         }
     };
 
-    utree plus(environment*, utree& args)
+    struct make_plus
     {
+        typedef function result_type;
+        function operator()(function_list& operands)
+        {
+            // check arity here!
+            return function(plus_impl(operands));
+        }
+    };
 
-    }
-}
+    make_plus const plus = {};
 
 ///////////////////////////////////////////////////////////////////////////////
-//  Main program
+//  The compiler
 ///////////////////////////////////////////////////////////////////////////////
-int main(int argc, char **argv)
-{
-    char const* filename;
-    if (argc > 1)
-    {
-        filename = argv[1];
-    }
-    else
+    typedef boost::function<function(function_list&)> make_function;
+
+    struct compiler_environment
     {
-        std::cerr << "Error: No input file provided." << std::endl;
-        return 1;
-    }
+        compiler_environment() {}
 
-    std::ifstream in(filename, std::ios_base::in);
+        void define(std::string const& name, make_function const& def)
+        {
+            // $$$ use exceptions here $$$
+            BOOST_ASSERT(definitions.find(name) == definitions.end());
+            definitions[name] = def;
+        }
 
-    if (!in)
-    {
-        std::cerr << "Error: Could not open input file: "
-            << filename << std::endl;
-        return 1;
-    }
+        make_function* find(std::string const& name)
+        {
+            std::map<std::string, make_function>::iterator
+                i = definitions.find(name);
+            if (i != definitions.end())
+                return &i->second;
+            return 0;
+        }
+
+        std::map<std::string, make_function> definitions;
+    };
 
-    // Ignore the BOM marking the beginning of a UTF-8 file in Windows
-    char c = in.peek();
-    if (c == '\xef')
+    function compile(utree const& ast, compiler_environment& env);
+
+    struct compiler
     {
-        char s[3];
-        in >> s[0] >> s[1] >> s[2];
-        s[3] = '\0';
-        if (s != std::string("\xef\xbb\xbf"))
+        typedef function result_type;
+
+        compiler_environment& env;
+        compiler(compiler_environment& env)
+          : env(env) {}
+
+        function operator()(nil) const
+        {
+            return scheme::val(utree());
+        }
+
+        template <typename T>
+        function operator()(T const& val) const
+        {
+            return scheme::val(utree(val));
+        }
+
+        function operator()(utf8_symbol_range const& str) const
+        {
+            return function(); // $$$ implement me $$$
+        }
+
+        template <typename Iterator>
+        function operator()(boost::iterator_range<Iterator> const& range) const
         {
-            std::cerr << "Error: Unexpected characters from input file: "
-                << filename << std::endl;
-            return 1;
+            utf8_symbol_range symbol = range.begin()->as<utf8_symbol_range>();
+            std::string fname(symbol.begin(), symbol.end());
+            if (make_function* mf = env.find(fname))
+            {
+                function_list flist;
+                Iterator i = range.begin(); ++i;
+                for (; i != range.end(); ++i)
+                    flist.push_back(compile(*i, env));
+                return (*mf)(flist);
+            }
+
+            return function(); // $$$ implement me $$$
         }
+    };
+
+    function compile(utree const& ast, compiler_environment& env)
+    {
+        return utree::visit(ast, compiler(env));
     }
 
-    scheme::utree result;
-    if (scheme::input::parse_sexpr(in, result))
+    void build_basic_environment(compiler_environment& env)
     {
-        std::cout << "success: ";
-        println(std::cout, result);
-        std::cout << std::endl;
+        env.define("+", make_plus());
     }
-    else
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    std::string in;
+    while (std::getline(std::cin, in))
     {
-        std::cout << "parse error" << std::endl;
+        if (in.empty() || in[0] == 'q' || in[0] == 'Q')
+            break;
+
+        typedef std::string::const_iterator iterator_type;
+        scheme::utree result;
+        scheme::input::sexpr<iterator_type> p;
+        scheme::input::white_space<iterator_type> ws;
+
+        iterator_type first = in.begin();
+        iterator_type last = in.end();
+        if (phrase_parse(first, last, p, ws, result))
+        {
+            std::cout << "success: ";
+            scheme::compiler_environment env;
+            scheme::build_basic_environment(env);
+            scheme::function f = compile(result, env);
+            std::cout << "result: " << f(scheme::utree()) << std::endl;
+        }
+        else
+        {
+            std::cout << "parse error" << std::endl;
+        }
     }
 
+    std::cout << "Bye... :-) \n\n";
     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-07 10:23:57 EDT (Wed, 07 Apr 2010)
@@ -55,8 +55,8 @@
     ///////////////////////////////////////////////////////////////////////////
     // Function pointer
     ///////////////////////////////////////////////////////////////////////////
-    class utree; // forward
-    typedef utree (*function_ptr)(environment* env, utree& args);
+    class utree;
+    typedef utree (*function_ptr)(environment& env);
 
     ///////////////////////////////////////////////////////////////////////////
     // A typed string with parametric Base storage. The storage can be any
@@ -261,7 +261,10 @@
         bool empty() const;
         std::size_t size() const;
 
-        int which() const;
+        utree_type::info which() const;
+
+        template <typename T>
+        T as() const;
 
     private:
 
@@ -270,8 +273,9 @@
         template <typename UTreeX, typename UTreeY>
         friend struct detail::visit_impl;
         friend struct detail::index_impl;
-        friend struct ulist;
-        template <typename T> friend struct detail::get_impl;
+
+        template <typename T>
+        friend struct detail::get_impl;
 
         type::info get_type() const;
         void set_type(type::info t);
@@ -279,9 +283,6 @@
         void free();
         void copy(utree const& other);
 
-        struct construct_list {};
-        utree(construct_list);
-
         union
         {
             detail::fast_string s;
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-07 10:23:57 EDT (Wed, 07 Apr 2010)
@@ -206,6 +206,11 @@
             }
             (*this)(')');
         }
+
+        void operator()(function_ptr fptr) const
+        {
+            out << "function-pointer(" << fptr << ')';
+        }
     };
 
     template <typename Base>
@@ -213,6 +218,8 @@
     {
         typedef utree result_type;
 
+        // In scheme, anything except false is true
+
         // binary
         utree operator()(bool a, bool b) const
         {
@@ -220,25 +227,37 @@
         }
 
         // binary
+        template <typename A>
+        utree operator()(A const& a, bool b) const
+        {
+            return Base::eval(true, b);
+        }
+
+        // binary
+        template <typename B>
+        utree operator()(bool a, B const& b) const
+        {
+            return Base::eval(a, true);
+        }
+
+        // binary
         template <typename A, typename B>
         utree operator()(A const& a, B const& b) const
         {
-            // $$$ Throw exception here? $$$
-            return utree(); // cannot apply to non booleans
+            return Base::eval(true, true);
         }
 
         // unary
         utree operator()(bool a) const
         {
-            return Base::eval(a); // for boolean types
+            return Base::eval(a);
         }
 
         // unary
         template <typename A>
         utree operator()(A const& a) const
         {
-            // $$$ Throw exception here? $$$
-            return utree(); // cannot apply to non booleans
+            return Base::eval(true);
         }
     };
 
@@ -248,21 +267,21 @@
         typedef utree result_type;
 
         template <typename A, typename B>
-        utree dispatch(A&, B&, boost::mpl::false_) const
+        utree dispatch(A const&, B const&, boost::mpl::false_) const
         {
             // $$$ Throw exception here? $$$
             return utree(); // cannot apply to non-arithmetic types
         }
 
         template <typename A, typename B>
-        utree dispatch(A& a, B& b, boost::mpl::true_) const
+        utree dispatch(A const& a, B const& b, boost::mpl::true_) const
         {
             return Base::eval(a, b); // for arithmetic types
         }
 
         // binary
         template <typename A, typename B>
-        utree operator()(A& a, B& b) const
+        utree operator()(A const& a, B const& b) const
         {
             return dispatch(a, b,
                 boost::mpl::and_<
@@ -271,21 +290,21 @@
         }
 
         template <typename A>
-        utree dispatch(A&, boost::mpl::false_) const
+        utree dispatch(A const&, boost::mpl::false_) const
         {
             // $$$ Throw exception here? $$$
             return utree(); // cannot apply to non-arithmetic types
         }
 
         template <typename A>
-        utree dispatch(A& a, boost::mpl::true_) const
+        utree dispatch(A const& a, boost::mpl::true_) const
         {
             return Base::eval(a); // for arithmetic types
         }
 
         // unary
         template <typename A>
-        utree operator()(A& a) const
+        utree operator()(A const& a) const
         {
             return dispatch(a, boost::is_arithmetic<A>());
         }
@@ -297,21 +316,21 @@
         typedef utree result_type;
 
         template <typename A, typename B>
-        utree dispatch(A&, B&, boost::mpl::false_) const
+        utree dispatch(A const&, B const&, boost::mpl::false_) const
         {
             // $$$ Throw exception here? $$$
             return utree(); // cannot apply to non-integral types
         }
 
         template <typename A, typename B>
-        utree dispatch(A& a, B& b, boost::mpl::true_) const
+        utree dispatch(A const& a, B const& b, boost::mpl::true_) const
         {
             return Base::eval(a, b); // for integral types
         }
 
         // binary
         template <typename A, typename B>
-        utree operator()(A& a, B& b) const
+        utree operator()(A const a, B const& b) const
         {
             return dispatch(a, b,
                 boost::mpl::and_<
@@ -320,21 +339,21 @@
         }
 
         template <typename A>
-        utree dispatch(A&, boost::mpl::false_) const
+        utree dispatch(A const&, boost::mpl::false_) const
         {
             // $$$ Throw exception here? $$$
             return utree(); // cannot apply to non-integral types
         }
 
         template <typename A>
-        utree dispatch(A& a, boost::mpl::true_) const
+        utree dispatch(A const& a, boost::mpl::true_) const
         {
             return Base::eval(a); // for integral types
         }
 
         // unary
         template <typename A>
-        utree operator()(A& a) const
+        utree operator()(A const& a) const
         {
             return dispatch(a, boost::is_integral<A>());
         }
@@ -344,12 +363,12 @@
     struct BOOST_PP_CAT(function_impl_, name)                                   \
     {                                                                           \
         template <typename A, typename B>                                       \
-        static utree eval(A& a, B& b)                                           \
+        static utree eval(A const& a, B const& b)                               \
         {                                                                       \
             return utree(expr);                                                 \
         }                                                                       \
         template <typename A>                                                   \
-        static utree eval(A& a)                                                 \
+        static utree eval(A const& a)                                           \
         {                                                                       \
             return utree(expr);                                                 \
         }                                                                       \