1 /* Funky: a light-weight embeddable programming language
2 * Copyright (c) 2007, Ronald Landheer-Cieslak
5 * This is free software. You may distribute it and/or modify it and
6 * distribute modified forms provided that the following terms are met:
8 * * Redistributions of the source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the distribution;
13 * * None of the names of the authors of this software may be used to endorse
14 * or promote this software, derived software or any distribution of this
15 * software or any distribution of which this software is part, without
16 * prior written permission from the authors involved;
17 * * Unless you have received a written statement from Ronald Landheer-Cieslak
18 * that says otherwise, the terms of the GNU General Public License, as
19 * published by the Free Software Foundation, version 2 or (at your option)
20 * any later version, also apply.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 #ifndef _funky_groovy_h
35 #define _funky_groovy_h
37 #include "Details/prologue.h"
41 #include <boost/function.hpp>
47 template < typename LiteralType
>
50 /** Groovy: a tiny, embeddable functional programming language.
51 * This class implements a tiny, embeddable programming language that has
52 * the following features:
53 * \li you can install your own functions in the language
54 * \li simple arithmatic functions are built-in
55 * \li you can pass any number of arguments to the script
56 * The languages syntax is very lisp-like: a statement is written in brackets
57 * and consists of a comma-separated list, the first entry in which is a
58 * function name (all others being its arguments). The following functions
60 * \li test: returns 1 if its argument is non-zero, 0 otherwise.
61 * \li or: returns 1 if either of its two arguments is non-zero, 0 otherwise.
62 * \li and: returns 1 if both of its arguments are non-zero, 0 otherwise
63 * \li not: returns 1 if its argument is 0, 0 otherwise
64 * \li add: returns the sum of its two arguments
65 * \li neg: returns the negative equivalent of its argument
66 * \li mul: returns the product of its two arguments
67 * \li div: returns the result of dividing its two arguments
68 * For example, the following script:
70 * (add, (neg, (add, 6, 6)), 12)
72 * will return 0: it will first add 6 to 6, resulting in 12. It will then
73 * negate 12, resulting in -12, to which it will add 12, resulting in 0.
75 * You may have noticed that there is no "sub" function built-in. That's because
76 * you don't need one: you can easily subtract like this: (add, \@0, (neg, \@1))
77 * which very nicely introduces two features of this little language: there's
78 * nothing there you don't need (but some things you do need may be missing -
79 * for which reason you can always add to the language) and you can pass
80 * parameters to your scripts and reference them using the @ sign and the index
81 * of the parameter you want in the parameters you've passed, starting at 0.
83 class FUNKY_API Groovy
86 //! The type of the arguments as they are passed around
87 typedef std::vector
< int > Arguments
;
88 //! Signature of an installable function: return a int and take a vector of ints as parameter
89 typedef boost::function1
< int, std::vector
< int > > Function
;
90 //! Signature of an installable function that returns more than one value
91 typedef boost::function1
< std::vector
< int >, std::vector
< int > > MultiReturnFunction
;
94 //! Construct a interpreter without any functions installed (except the built-in ones)
96 //! Destroy the interpreter and free all associated resources
99 /** Parse a given script for later evaluation.
100 * Once successfully parsed, you can use the run function to run the
101 * script. Both steps can be done in a single go using the eval
102 * function, which will parse and then run the script with the given
104 * note that parsing a script that defines functions will alter the
105 * state of the interpreter in that it will add functions to the
106 * internal function table, and those functions may replace the ones
107 * already there (so if you want to override functions define in the
108 * scripts, you should install them after parsing the script. Likewise
109 * if you want a script to be able to override your built-in functions,
110 * install your functions before parsing the script).
112 * \param program_text the script to parse
113 * \throws Exceptions::ParseError if an error occurs during parsing */
114 void parse(const std::string
& program_text
);
116 /** Run a previously parsed script. Note that execution will start at
117 * the last statement parsed by the parser.
119 * \param arguments the arguments to pass to the script.
120 * \throws Exceptions::FunctionCallError if one of the functions does
121 * not behave as expected */
122 int run(const Arguments
& arguments
= Arguments());
124 /** Evaluate a given script with the given arguments.
125 * \param program_text the script to evaluate
126 * \param arguments the arguments to pass to the script
127 * \return the result of the script
128 * \throws Exceptions::ParseError if an error occurs during parsing
129 * \throws Exceptions::FunctionCallError if one of the functions does
130 * not behave as expected */
131 int eval(const std::string
& program_text
, const Arguments
& arguments
= Arguments());
133 /** Install a function in the interpreter, callable by a script.
134 * \param function_name the name of the function to install
135 * \param function a pointer to the function to call when invoked by the script
136 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed */
137 void installFunction(const std::string
& function_name
, const Function
& function
, int expected_args
= any__
);
138 /** Install a function in the interpreter, callable by a script.
139 * \param function_name the name of the function to install
140 * \param function a pointer to the function to call when invoked by the script
141 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed
142 * \param expected_returns the number of values the function should be expected to return, or -1 if any amount is allowed */
143 void installFunction(const std::string
& function_name
, const MultiReturnFunction
& function
, int expected_args
= any__
, int expected_returns
= any__
);
144 /** Remove (uninstall) a previously installed function from the interpreter.
145 * \param function_name the function to remove */
146 void removeFunction(const std::string
& function_name
);
152 // Neither CopyConstructible nor Assignable
153 Groovy(const Groovy
&);
154 Groovy
&operator=(const Groovy
&);
157 Private::Grammar
< int > * grammar_
;