Boost logo

Boost-Commit :

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); \
         } \


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk