/*============================================================================= 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_SCHEME_INTERPRETER) #define BOOST_SPIRIT_SCHEME_INTERPRETER #include <list> #include <boost/function.hpp> #include <boost/foreach.hpp> #include <boost/array.hpp> #include <boost/scoped_array.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/spirit/include/support_utree.hpp> #define SCHEME_COMPOSITE_LIMIT 10 #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4018) #endif namespace scheme { /////////////////////////////////////////////////////////////////////////////// // The runtime interpreter /////////////////////////////////////////////////////////////////////////////// using boost::spirit::utree; using boost::spirit::utree_type; using boost::spirit::scope; using boost::spirit::shallow; using boost::spirit::stored_function; using boost::spirit::function_base; using boost::spirit::binary_string; using boost::spirit::utf8_symbol; using boost::spirit::utf8_string; using boost::spirit::binary_range; using boost::spirit::utf8_symbol_range; using boost::spirit::utf8_string_range; using boost::spirit::nil; /////////////////////////////////////////////////////////////////////////// // typedefs /////////////////////////////////////////////////////////////////////////// struct function; typedef std::list<function> actor_list; /////////////////////////////////////////////////////////////////////////// // actor /////////////////////////////////////////////////////////////////////////// template <typename Derived> struct actor { typedef utree result_type; typedef actor<Derived> base_type; utree operator()(scope const& env) const { return derived().eval(env); } utree operator()() const { return derived().eval(scope()); } template <typename A0> utree operator()(A0 const& _0) const { boost::array<utree, 1> elements; elements[0] = _0; return derived().eval(get_range(elements)); } template <typename A0, typename A1> utree operator()(A0 const& _0, A1 const& _1) const { boost::array<utree, 2> elements; elements[0] = _0; elements[1] = _1; return derived().eval(get_range(elements)); } // More operators #include <scheme/detail/function_call.hpp> template <std::size_t n> static scope get_range(boost::array<utree, n>& array) { return scope(array.begin(), array.end()); } Derived const& derived() const { return *static_cast<Derived const*>(this); } }; /////////////////////////////////////////////////////////////////////////// // function /////////////////////////////////////////////////////////////////////////// struct function : actor<function> { utree f; function() : f() {} function(utree const& f) : f(f) {} template <typename F> function(F const& f) : f(stored_function<F>(f)) { } bool empty() const { return f.which() != utree_type::function_type; } utree eval(scope const& env) const { return f.eval(env); } }; /////////////////////////////////////////////////////////////////////////// // values /////////////////////////////////////////////////////////////////////////// struct value_function : actor<value_function> { utree val; value_function(utree const& val) : val(val) {} utree eval(scope const& /*env*/) const { return utree(boost::ref(val)); } }; struct value { typedef function result_type; function operator()(utree const& val) const { return function(value_function(val)); } }; value const val = {}; inline function protect(function const& f) { return val(f.f); } /////////////////////////////////////////////////////////////////////////// // arguments /////////////////////////////////////////////////////////////////////////// template <bool scoped = true> struct argument_function : actor<argument_function<scoped> > { std::size_t n; std::size_t level; argument_function(std::size_t n, std::size_t level = 0) : n(n), level(level) {} utree eval(scope const& env) const { scope const* eptr = &env; while (level != eptr->level()) eptr = eptr->outer(); utree const& arg = (*eptr)[n]; if (arg.which() != utree_type::function_type) return utree(boost::ref(arg)); else return arg.eval(*eptr); } }; template <> // scoped = false struct argument_function<false> : actor<argument_function<false> > { std::size_t n; argument_function(std::size_t n, std::size_t level = 0) : n(n) {} utree eval(scope const& env) const { scope const* eptr = &env; utree const& arg = (*eptr)[n]; if (arg.which() != utree_type::function_type) return utree(boost::ref(arg)); else return arg.eval(*eptr); } }; template <bool scoped = true> struct argument { typedef function result_type; function operator()(std::size_t n, std::size_t level = 0) const { return function(argument_function<scoped>(n, level)); } }; // scoped arg argument<true> const arg = {}; // unscoped arg argument<false> const unscoped_arg = {}; // unscoped args function const _1 = unscoped_arg(0); function const _2 = unscoped_arg(1); function const _3 = unscoped_arg(2); function const _4 = unscoped_arg(3); function const _5 = unscoped_arg(4); function const _6 = unscoped_arg(5); function const _7 = unscoped_arg(6); function const _8 = unscoped_arg(7); function const _9 = unscoped_arg(8); function const _10 = unscoped_arg(10); /////////////////////////////////////////////////////////////////////////// // variable arguments. // Collects the arguments from n to last in a utree list. /////////////////////////////////////////////////////////////////////////// template <bool scoped = true> struct vararg_function : actor<vararg_function<scoped> > { std::size_t n; std::size_t level; vararg_function(std::size_t n, std::size_t level = 0) : n(n), level(level) {} utree eval(scope const& env) const { scope const* eptr = &env; while (level != eptr->level()) eptr = eptr->outer(); utree result; for (std::size_t i = n; i < eptr->size(); ++i) { utree const& arg = (*eptr)[i]; if (arg.which() != utree_type::function_type) result.push_back(utree(boost::ref(arg))); else result.push_back(arg.eval(*eptr)); } return result; } }; template <> // scoped = false struct vararg_function<false> : actor<vararg_function<false> > { std::size_t n; vararg_function(std::size_t n, std::size_t level = 0) : n(n) {} utree eval(scope const& env) const { scope const* eptr = &env; utree result; for (std::size_t i = n; i < eptr->size(); ++i) { utree const& arg = (*eptr)[i]; if (arg.which() != utree_type::function_type) result.push_back(utree(boost::ref(arg))); else result.push_back(arg.eval(*eptr)); } return result; } }; template <bool scoped = true> struct vararg { typedef function result_type; function operator()(std::size_t n, std::size_t level = 0) const { return function(vararg_function<scoped>(n, level)); } }; // scoped varg vararg<true> const varg = {}; // unscoped varg vararg<false> const unscoped_varg = {}; // unscoped vargs function const _1_ = unscoped_varg(0); function const _2_ = unscoped_varg(1); function const _3_ = unscoped_varg(2); function const _4_ = unscoped_varg(3); function const _5_ = unscoped_varg(4); function const _6_ = unscoped_varg(5); function const _7_ = unscoped_varg(6); function const _8_ = unscoped_varg(7); function const _9_ = unscoped_varg(8); function const _10_ = unscoped_varg(10); /////////////////////////////////////////////////////////////////////////// // composite /////////////////////////////////////////////////////////////////////////// template <typename Derived> struct composite { typedef function result_type; typedef composite<Derived> base_type; function operator()(actor_list const& elements) const { return derived().compose(elements); } template <typename A0> function operator()(A0 const& _0) const { actor_list elements; elements.push_back(as_function(_0)); return derived().compose(elements); } template <typename A0, typename A1> function operator()(A0 const& _0, A1 const& _1) const { actor_list elements; elements.push_back(as_function(_0)); elements.push_back(as_function(_1)); return derived().compose(elements); } // More operators #include <scheme/detail/composite_call.hpp> Derived const& derived() const { return *static_cast<Derived const*>(this); } template <typename T> static function as_function(T const& val) { return scheme::val(utree(val)); } static function const& as_function(function const& f) { return f; } }; /////////////////////////////////////////////////////////////////////////// // unary_function /////////////////////////////////////////////////////////////////////////// template <typename Derived> struct unary_function : actor<unary_function<Derived> > { function a; typedef unary_function<Derived> base_type; unary_function(function const& a) : a(a) { BOOST_ASSERT(!a.empty()); } utree eval(scope const& env) const { return derived().eval(a(env)); } Derived const& derived() const { return *static_cast<Derived const*>(this); } }; template <typename Function> struct unary_composite : composite<unary_composite<Function> > { function compose(actor_list const& elements) const { return function(Function(elements.front())); } }; /////////////////////////////////////////////////////////////////////////// // binary_function /////////////////////////////////////////////////////////////////////////// template <typename Derived> struct binary_function : actor<binary_function<Derived> > { function a; function b; typedef binary_function<Derived> base_type; binary_function(function const& a, function const& b) : a(a), b(b) { BOOST_ASSERT(!a.empty()); BOOST_ASSERT(!b.empty()); } utree eval(scope const& env) const { return derived().eval(a(env), b(env)); } Derived const& derived() const { return *static_cast<Derived const*>(this); } }; template <typename Function> struct binary_composite : composite<binary_composite<Function> > { function compose(actor_list const& elements) const { actor_list::const_iterator i = elements.begin(); function a = *i++; function b = *i; return function(Function(a, b)); } }; /////////////////////////////////////////////////////////////////////////// // nary_function /////////////////////////////////////////////////////////////////////////// template <typename Derived> struct nary_function : actor<nary_function<Derived> > { actor_list elements; typedef nary_function<Derived> base_type; nary_function(actor_list const& elements) : elements(elements) { BOOST_FOREACH(function const& element, elements) { BOOST_ASSERT(!element.empty()); } } utree eval(scope const& env) const { BOOST_ASSERT(!elements.empty()); actor_list::const_iterator i = elements.begin(); utree result = (*i++)(env); boost::iterator_range<actor_list::const_iterator> rest(i++, elements.end()); BOOST_FOREACH(function const& element, rest) { if (!derived().eval(result, element(env))) break; // allow short-circuit evaluation } return result; } Derived const& derived() const { return *static_cast<Derived const*>(this); } }; template <typename Function> struct nary_composite : composite<nary_composite<Function> > { function compose(actor_list const& elements) const { return function(Function(elements)); } }; /////////////////////////////////////////////////////////////////////////// // lambda /////////////////////////////////////////////////////////////////////////// struct lambda_function : actor<lambda_function> { int level; actor_list elements; // we must hold f by reference because functions can be recursive boost::reference_wrapper<function const> f; lambda_function(function const& f, actor_list const& elements, int level = 0) : level(level), elements(elements), f(f) {} typedef utree result_type; utree eval(scope const& env) const { // Get the parent scope scope const* outer = &env; while (level != outer->level()) outer = outer->outer(); if (!elements.empty()) { boost::scoped_array<utree> fargs(new utree[elements.size()]); std::size_t i = 0; BOOST_FOREACH(function const& element, elements) { fargs[i++] = element(env); } utree* fi = fargs.get(); return f.get()(scope(fi, fi+elements.size(), outer)); } else { return f.get()(scope(0, 0, outer)); } } }; struct lambda : composite<lambda> { function f; lambda() : f() {} lambda(function const& f) : f(f) {} function compose(actor_list const& elements) const { return function(lambda_function(f, elements)); } lambda& operator=(lambda const& other) { f = other.f; return *this; } lambda& operator=(function const& f_) { f = f_; return *this; } }; } #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif