|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61460 - in trunk/libs/spirit/example/scheme: example/scheme scheme
From: joel_at_[hidden]
Date: 2010-04-21 10:02:08
Author: djowel
Date: 2010-04-21 10:02:07 EDT (Wed, 21 Apr 2010)
New Revision: 61460
URL: http://svn.boost.org/trac/boost/changeset/61460
Log:
working lambda function application
Added:
trunk/libs/spirit/example/scheme/example/scheme/scheme_test.cpp
- copied, changed from r61451, /trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp
trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm (contents, props changed)
Removed:
trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp
Text files modified:
trunk/libs/spirit/example/scheme/example/scheme/scheme_test.cpp | 4 +
trunk/libs/spirit/example/scheme/scheme/compiler.hpp | 84 ++++++++++++++++++++++++---------------
trunk/libs/spirit/example/scheme/scheme/interpreter.hpp | 10 ++++
trunk/libs/spirit/example/scheme/scheme/intrinsics.hpp | 18 ++++++++
4 files changed, 81 insertions(+), 35 deletions(-)
Deleted: trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp 2010-04-21 10:02:07 EDT (Wed, 21 Apr 2010)
+++ (empty file)
@@ -1,47 +0,0 @@
-/*=============================================================================
- 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)
-=============================================================================*/
-#include <boost/config/warning_disable.hpp>
-
-#include <input/sexpr.hpp>
-#include <input/parse_sexpr_impl.hpp>
-#include <scheme/compiler.hpp>
-#include <utree/io.hpp>
-#include <fstream>
-
-///////////////////////////////////////////////////////////////////////////////
-// Main program
-///////////////////////////////////////////////////////////////////////////////
-int main(int argc, char **argv)
-{
- char const* filename = filename = argv[1];
- std::ifstream in(filename, std::ios_base::in);
-
- if (!in)
- {
- std::cerr << filename << " not found" << std::endl;
- return -1;
- }
-
- // Ignore the BOM marking the beginning of a UTF-8 file in Windows
- char c = in.peek();
- if (c == '\xef')
- {
- char s[3];
- in >> s[0] >> s[1] >> s[2];
- s[3] = '\0';
- if (s != std::string("\xef\xbb\xbf"))
- {
- std::cerr << "unexpected characters in file" << std::endl;
- return -1;
- }
- }
-
- scheme::interpreter factorial(in, filename);
- return 0;
-}
-
-
Copied: trunk/libs/spirit/example/scheme/example/scheme/scheme_test.cpp (from r61451, /trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp)
==============================================================================
--- /trunk/libs/spirit/example/scheme/example/scheme/scheme_error_test.cpp (original)
+++ trunk/libs/spirit/example/scheme/example/scheme/scheme_test.cpp 2010-04-21 10:02:07 EDT (Wed, 21 Apr 2010)
@@ -40,7 +40,9 @@
}
}
- scheme::interpreter factorial(in, filename);
+ scheme::interpreter f(in, filename);
+ if (!f.empty())
+ f();
return 0;
}
Added: trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/scheme/example/scheme/some_scheme.scm 2010-04-21 10:02:07 EDT (Wed, 21 Apr 2010)
@@ -0,0 +1,3 @@
+(define (apply x f) (display (f x)))
+
+(apply 123 (lambda (x) (+ x 1)))
\ 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-21 10:02:07 EDT (Wed, 21 Apr 2010)
@@ -10,8 +10,10 @@
#include <vector>
#include <map>
#include <exception>
+#include <cstdlib>
#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
#include <scheme/intrinsics.hpp>
#include <scheme/interpreter.hpp>
#include <input/parse_sexpr.hpp>
@@ -27,7 +29,7 @@
{
virtual const char* what() const throw()
{
- return "scheme: Compilation error";
+ return "scheme: Compilation error.";
}
};
@@ -35,7 +37,7 @@
{
virtual const char* what() const throw()
{
- return "scheme: Identifier expected";
+ return "scheme: Identifier expected.";
}
};
@@ -43,7 +45,7 @@
{
std::string msg;
identifier_not_found(std::string const& id)
- : msg("scheme: Identifier (" + id + ") not found") {}
+ : msg("scheme: Identifier (" + id + ") not found.") {}
virtual const char* what() const throw()
{
@@ -59,16 +61,25 @@
virtual const char* what() const throw()
{
- return "scheme: Duplicate identifier";
+ return "scheme: Duplicate identifier.";
}
};
struct incorrect_arity : scheme_exception
{
std::string msg;
- incorrect_arity(std::string const& id)
+ incorrect_arity(std::string const& id, int arity, bool fixed)
: msg("scheme: Invalid number of parameters to function call ("
- + id + ')') {}
+ + id + ").")
+ {
+ if (!fixed)
+ msg += std::string(" Expecting at least ");
+ else
+ msg += std::string(" Expecting ");
+
+ char buff[std::numeric_limits<int>::digits10];
+ msg += std::string(ltoa(arity, buff, 10)) + " arguments.";
+ }
virtual const char* what() const throw()
{
@@ -89,23 +100,27 @@
: outer(parent) {}
template <typename Function>
- void define(std::string const& name, Function const& f, int arity)
+ void define(std::string const& name, Function const& f, int arity, bool fixed)
{
if (definitions.find(name) != definitions.end())
throw duplicate_identifier(name);
- definitions[name] = std::make_pair(compiled_function(f), arity);
+ definitions[name] = boost::make_tuple(compiled_function(f), arity, fixed);
}
- std::pair<compiled_function*, int>
+ boost::tuple<compiled_function*, int, bool>
find(std::string const& name)
{
std::map<std::string, map_element>::iterator
i = definitions.find(name);
if (i != definitions.end())
- return std::make_pair(&i->second.first, i->second.second);
+ return boost::make_tuple(
+ &boost::get<0>(i->second),
+ boost::get<1>(i->second),
+ boost::get<2>(i->second)
+ );
else if (outer != 0)
return outer->find(name);
- return std::make_pair((compiled_function*)0, 0);
+ return boost::make_tuple((compiled_function*)0, 0, false);
}
void undefine(std::string const& name)
@@ -122,7 +137,7 @@
private:
- typedef std::pair<compiled_function, int> map_element;
+ typedef boost::tuple<compiled_function, int, bool> map_element;
environment* outer;
std::map<std::string, map_element> definitions;
@@ -185,11 +200,11 @@
function operator()(utf8_symbol_range const& str) const
{
std::string name(str.begin(), str.end());
- std::pair<compiled_function*, int> r = env.find(name);
- if (r.first)
+ boost::tuple<compiled_function*, int, bool> r = env.find(name);
+ if (boost::get<0>(r))
{
actor_list flist;
- return (*r.first)(flist);
+ return (*boost::get<0>(r))(flist);
}
throw identifier_not_found(name);
return function();
@@ -201,8 +216,8 @@
{
environment local_env(&this->env);
for (std::size_t i = 0; i < args.size(); ++i)
- local_env.define(args[i], boost::bind(arg, i), args.size());
- return compile(body, local_env, fragments, line, source_file);
+ local_env.define(args[i], boost::bind(arg, i), 0, false);
+ return protect(compile(body, local_env, fragments, line, source_file));
}
function define_function(
@@ -216,8 +231,8 @@
throw duplicate_identifier(name);
fragments.push_back(function());
function& f = fragments.back();
- env.define(name, external_function(f), args.size());
- f = make_lambda(args, body);
+ env.define(name, external_function(f), args.size(), true); // $$$ fixed arity for now $$$
+ f = make_lambda(args, body)(); // unprotect (evaluate returns a function)
return f;
}
catch (compilation_error const&)
@@ -266,6 +281,8 @@
Iterator ai = arg_names.begin();
while (ai != arg_names.end())
args.push_back(get_symbol(*ai++));
+
+ return define_function(fname, args, (*i)[2]);
}
}
@@ -285,8 +302,8 @@
}
// (f x)
- std::pair<compiled_function*, int> r = env.find(name);
- if (r.first)
+ boost::tuple<compiled_function*, int, bool> r = env.find(name);
+ if (boost::get<0>(r))
{
actor_list flist;
Iterator i = range.begin(); ++i;
@@ -295,17 +312,17 @@
compile(*i, env, fragments, line, source_file));
// Arity check
- if (r.second < 0) // non-fixed arity
+ if (!boost::get<2>(r)) // non-fixed arity
{
- if (int(flist.size()) < -r.second)
- throw incorrect_arity(name);
+ if (int(flist.size()) < boost::get<1>(r))
+ throw incorrect_arity(name, boost::get<1>(r), false);
}
else // fixed arity
{
- if (int(flist.size()) != r.second)
- throw incorrect_arity(name);
+ if (int(flist.size()) != boost::get<1>(r))
+ throw incorrect_arity(name, boost::get<1>(r), true);
}
- return (*r.first)(flist);
+ return (*boost::get<0>(r))(flist);
}
else
{
@@ -382,12 +399,13 @@
void build_basic_environment(environment& env)
{
- env.define("if", if_, 3);
- env.define("<", less_than, 2);
- env.define("<=", less_than_equal, 2);
- env.define("+", plus, -2);
- env.define("-", minus, -2);
- env.define("*", times, -2);
+ env.define("if", if_, 3, true);
+ env.define("display", display, 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);
}
///////////////////////////////////////////////////////////////////////////
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-21 10:02:07 EDT (Wed, 21 Apr 2010)
@@ -138,6 +138,11 @@
value const val = {};
+ inline function protect(function const& f)
+ {
+ return val(f.f);
+ }
+
///////////////////////////////////////////////////////////////////////////
// arguments
///////////////////////////////////////////////////////////////////////////
@@ -148,7 +153,10 @@
utree eval(args_type args) const
{
- return utree(boost::ref(args[n]));
+ if (args[n].which() != utree_type::function_type)
+ return utree(boost::ref(args[n]));
+ else
+ return args[n].eval(args);
}
};
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-21 10:02:07 EDT (Wed, 21 Apr 2010)
@@ -149,6 +149,24 @@
struct times_composite : nary_composite<times_function> {};
times_composite const times = times_composite();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // display
+ ///////////////////////////////////////////////////////////////////////////
+ struct display_function : unary_function<display_function>
+ {
+ display_function(function const& a)
+ : base_type(a) {}
+
+ utree eval(utree const& element) const
+ {
+ std::cout << element;
+ return utree();
+ }
+ };
+
+ struct display_composite : unary_composite<display_function> {};
+ display_composite const display = display_composite();
}
#endif
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