Add the possibility to pass user-defined data to installed functions
[Funky.git] / lib / Funky / Funky.h
blob5af8d38e90b04f25c86689b1e975957853e6cd2f
1 /* Funky: a light-weight embeddable programming language
2 * Copyright (c) 2007, Ronald Landheer-Cieslak
3 * All rights reserved
4 *
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_funky_h
35 #define _funky_funky_h
37 #include "Details/prologue.h"
39 #include <string>
40 #include <vector>
41 #include <boost/any.hpp>
42 #include <boost/function.hpp>
44 namespace Funky
46 namespace Private
48 template < typename LiteralType >
49 struct Grammar;
51 /** Funky: a tiny, embeddable functional programming language.
52 * This class implements a tiny, embeddable programming language that has
53 * the following features:
54 * \li you can install your own functions in the language
55 * \li simple arithmatic functions are built-in
56 * \li you can pass any number of arguments to the script
57 * The languages syntax is very lisp-like: a statement is written in brackets
58 * and consists of a comma-separated list, the first entry in which is a
59 * function name (all others being its arguments). The following functions
60 * are built-in:
61 * \li test: returns 1 if its argument is non-zero, 0 otherwise.
62 * \li or: returns 1 if either of its two arguments is non-zero, 0 otherwise.
63 * \li and: returns 1 if both of its arguments are non-zero, 0 otherwise
64 * \li not: returns 1 if its argument is 0, 0 otherwise
65 * \li add: returns the sum of its two arguments
66 * \li neg: returns the negative equivalent of its argument
67 * \li mul: returns the product of its two arguments
68 * \li div: returns the result of dividing its two arguments
69 * For example, the following script:
70 * \code
71 * (add, (neg, (add, 6, 6)), 12)
72 * \endcode
73 * will return 0: it will first add 6 to 6, resulting in 12. It will then
74 * negate 12, resulting in -12, to which it will add 12, resulting in 0.
76 * You may have noticed that there is no "sub" function built-in. That's because
77 * you don't need one: you can easily subtract like this: (add, \@0, (neg, \@1))
78 * which very nicely introduces two features of this little language: there's
79 * nothing there you don't need (but some things you do need may be missing -
80 * for which reason you can always add to the language) and you can pass
81 * parameters to your scripts and reference them using the @ sign and the index
82 * of the parameter you want in the parameters you've passed, starting at 0.
84 class FUNKY_API Funky
86 public :
87 //! The type of the arguments as they are passed around
88 typedef std::vector< double > Arguments;
89 //! Signature of an installable function: return a double and take a vector of doubles as parameter
90 typedef boost::function1< double, std::vector< double > > Function;
91 //! Signature of an installable function that returns more than one value
92 typedef boost::function1< std::vector< double >, std::vector< double > > MultiReturnFunction;
93 //! Signature of an installable function: return a double and take a vector of doubles as parameter
94 typedef boost::function2< double, boost::any, std::vector< double > > Function2;
95 //! Signature of an installable function that returns more than one value
96 typedef boost::function2< std::vector< double >, boost::any, std::vector< double > > MultiReturnFunction2;
97 enum { any__ = -1 };
99 //! Construct a interpreter without any functions installed (except the built-in ones)
100 Funky();
101 //! Destroy the interpreter and free all associated resources
102 ~Funky();
104 /** Parse a given script for later evaluation.
105 * Once successfully parsed, you can use the run function to run the
106 * script. Both steps can be done in a single go using the eval
107 * function, which will parse and then run the script with the given
108 * arguments.
109 * note that parsing a script that defines functions will alter the
110 * state of the interpreter in that it will add functions to the
111 * internal function table, and those functions may replace the ones
112 * already there (so if you want to override functions define in the
113 * scripts, you should install them after parsing the script. Likewise
114 * if you want a script to be able to override your built-in functions,
115 * install your functions before parsing the script).
117 * \param program_text the script to parse
118 * \throws Exceptions::ParseError if an error occurs during parsing */
119 void parse(const std::string & program_text);
121 /** Run a previously parsed script. Note that execution will start at
122 * the last statement parsed by the parser.
124 * \param arguments the arguments to pass to the script.
125 * \throws Exceptions::FunctionCallError if one of the functions does
126 * not behave as expected */
127 double run(const Arguments & arguments = Arguments());
129 /** Run a previously parsed script. Note that execution will start at
130 * the last statement parsed by the parser.
132 * \param arguments the arguments to pass to the script.
133 * \throws Exceptions::FunctionCallError if one of the functions does
134 * not behave as expected */
135 double run(const boost::any & user, const Arguments & arguments = Arguments());
137 /** Evaluate a given script with the given arguments.
138 * \param program_text the script to evaluate
139 * \param arguments the arguments to pass to the script
140 * \return the result of the script
141 * \throws Exceptions::ParseError if an error occurs during parsing
142 * \throws Exceptions::FunctionCallError if one of the functions does
143 * not behave as expected */
144 double eval(const std::string & program_text, const Arguments & arguments = Arguments());
146 /** Evaluate a given script with the given arguments.
147 * \param program_text the script to evaluate
148 * \param arguments the arguments to pass to the script
149 * \return the result of the script
150 * \throws Exceptions::ParseError if an error occurs during parsing
151 * \throws Exceptions::FunctionCallError if one of the functions does
152 * not behave as expected */
153 double eval(const std::string & program_text, const boost::any & user, const Arguments & arguments = Arguments());
155 /** Install a function in the interpreter, callable by a script.
156 * \param function_name the name of the function to install
157 * \param function a pointer to the function to call when invoked by the script
158 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed */
159 void installFunction(const std::string & function_name, const Function & function, int expected_args = any__);
160 /** Install a function in the interpreter, callable by a script.
161 * \param function_name the name of the function to install
162 * \param function a pointer to the function to call when invoked by the script
163 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed
164 * \param expected_returns the number of values the function should be expected to return, or -1 if any amount is allowed */
165 void installFunction(const std::string & function_name, const MultiReturnFunction & function, int expected_args = any__, int expected_returns = any__);
166 /** Install a function in the interpreter, callable by a script.
167 * \param function_name the name of the function to install
168 * \param function a pointer to the function to call when invoked by the script
169 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed */
170 void installFunction2(const std::string & function_name, const Function2 & function, int expected_args = any__);
171 /** Install a function in the interpreter, callable by a script.
172 * \param function_name the name of the function to install
173 * \param function a pointer to the function to call when invoked by the script
174 * \param expected_args the expected number of arguments the function can be called with, or -1 if any amount is allowed
175 * \param expected_returns the number of values the function should be expected to return, or -1 if any amount is allowed */
176 void installFunction2(const std::string & function_name, const MultiReturnFunction2 & function, int expected_args = any__, int expected_returns = any__);
177 /** Remove (uninstall) a previously installed function from the interpreter.
178 * \param function_name the function to remove */
179 void removeFunction(const std::string & function_name);
181 private :
182 struct FunctionInfo;
183 struct Data;
185 // Neither CopyConstructible nor Assignable
186 Funky(const Funky &);
187 Funky &operator=(const Funky &);
189 Data * data_;
190 Private::Grammar< double > * grammar_;
194 #endif