/[svn]/linuxsampler/trunk/src/scriptvm/ScriptVM.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/scriptvm/ScriptVM.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3590 - (show annotations) (download) (as text)
Mon Sep 2 09:03:31 2019 UTC (4 years, 7 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 16752 byte(s)
NKSP: Implemented common real number math functions.

* Added built-in real number functions "round()", "ceil()", "floor()",
  "sqrt()", "log()", "log2()", "log10()", "exp()", "pow()", "sin()",
  "cos()", "tan()", "asin()", "acos()", "atan()".

* Added built-in script real number constant "~NI_MATH_PI".

* Added built-in script real number constant "~NI_MATH_E".

* Added NKSP test cases for built-in functions "round()", "ceil()",
  "floor()", "sqrt()", "log()", "log2()", "log10()", "exp()", "pow()",
  "sin()", "cos()", "tan()", "asin()", "acos()", "atan()".

* Bumped version (2.1.1.svn14).

1 /*
2 * Copyright (c) 2014-2019 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #ifndef LS_SCRIPTVM_H
11 #define LS_SCRIPTVM_H
12
13 #include <iostream>
14 #include <vector>
15
16 #include "../common/global.h"
17 #include "common.h"
18
19 namespace LinuxSampler {
20
21 class ParserContext;
22 class ExecContext;
23
24 /** @brief Core virtual machine for real-time instrument scripts.
25 *
26 * This is the core of the virtual machine and main entry class, used for
27 * running real-time instrument scripts. This VM core encompasses the
28 * instrument script parser, generalized virtual machine and very generic
29 * built-in script functions. Thus this class only provides functionalities
30 * which are yet independent of the actual purpose the virtual machine is
31 * going to be used for.
32 *
33 * The actual use case specific functionalites (i.e. MIDI processing) is
34 * then implemented by sampler engines' VM classes which are derived from
35 * this generalized ScriptVM class.
36 *
37 * Typical usage of this class:
38 *
39 * - 1. Create an instance of this ScriptVM class (or of one of its deriving
40 * classes).
41 * - 2. Load a script by passing its source code to method loadScript(),
42 * which will return the parsed representation of the script.
43 * - 3. Create a VM execution context by calling createExecContext().
44 * - 4. Execute the script by calling method exec().
45 *
46 * This class is re-entrant safe, but not thread safe. So you can share one
47 * instance of this class between multiple (native) threads, but you @b must
48 * @b not execute methods of the same class instance simultaniously from
49 * different (native) threads. If you want to execute scripts simultaniously
50 * multi threaded, then create a separate ScriptVM instance for each
51 * (native) thread. Also note that one VMParserContext instance is tied to
52 * exactly one ScriptVM instance. So you @b must @b not create a
53 * VMParserContext with one ScriptVM instance and run it with a different
54 * ScriptVM instance!
55 */
56 class ScriptVM : public VMFunctionProvider {
57 public:
58 ScriptVM();
59 virtual ~ScriptVM();
60
61 /**
62 * Loads a script given by its source code (passed as argument @a s to
63 * this method) and returns the parsed representation of that script.
64 * After calling this method you must check the returned VMParserContext
65 * object whether there had been any parser errors. If there were no
66 * parser errors, you may pass the VMParserContext object to method
67 * exec() for actually executing the script.
68 *
69 * It is your responsibility to free the returned VMParserContext
70 * object once you don't need it anymore.
71 *
72 * @param s - entire source code of the script to be loaded
73 * @returns parsed representation of the script
74 */
75 VMParserContext* loadScript(const String& s);
76
77 /**
78 * Same as above's loadScript() method, but this one reads the script's
79 * source code from an input stream object (i.e. stdin or a file).
80 *
81 * @param is - input stream from which the entire source code of the
82 * script is to be read and loaded from
83 * @returns parsed representation of the script
84 */
85 VMParserContext* loadScript(std::istream* is);
86
87 /**
88 * Parses a script's source code (passed as argument @a s to this
89 * method), splits that input up in its individual tokens (i.e.
90 * keyword, variable name, event name, etc.) and returns all those
91 * tokens, for the purpose that the caller can provide syntax syntax
92 * highlighting for the passed script.
93 *
94 * This method is actually not used by the sampler at all, it is rather
95 * provided for external script editor applications, to provide them a
96 * convenient backend for parsing scripts and providing syntax
97 * highlighting.
98 *
99 * @returns recognized tokens of passed script's source code
100 */
101 std::vector<VMSourceToken> syntaxHighlighting(const String& s);
102
103 /**
104 * Same as above's syntaxHighlighting() method, but this one reads the
105 * script's source code from an input stream object (i.e. stdin or a
106 * file).
107 *
108 * @param is - input stream from which the entire source code of the
109 * script is to be read and loaded from
110 * @returns recognized tokens of passed script's source code
111 */
112 std::vector<VMSourceToken> syntaxHighlighting(std::istream* is);
113
114 /**
115 * Dumps the translated tree of the already parsed script, given by
116 * argument @a context, to stdout. This method is for debugging purposes
117 * only.
118 *
119 * @param context - parsed representation of the script
120 * @see loadScript()
121 */
122 void dumpParsedScript(VMParserContext* context);
123
124 /**
125 * Creates a so called VM exceution context for a specific, already
126 * parsed script (provided by argument @a parserContext). Due to the
127 * general real-time design of this virtual machine, the VM execution
128 * context differs for every script. So you must (re)create the
129 * execution context for each script being loaded.
130 *
131 * @param parserContext - parsed representation of the script
132 * @see loadScript()
133 */
134 VMExecContext* createExecContext(VMParserContext* parserContext);
135
136 /**
137 * Execute a script by virtual machine. Since scripts are event-driven,
138 * you actually execute only one specific event handler block (i.e. a
139 * "on note ... end on" code block) by calling this method (not the
140 * entire script), and hence you must provide one precise handler of the
141 * script to be executed by this method.
142 *
143 * This method usually blocks until the entire script event handler
144 * block has been executed completely. It may however also return before
145 * completion if either a) a script runtime error occurred or b) the
146 * script was suspended by the VM (either because script execution
147 * exceeded a certain limit of time or the script called the built-in
148 * wait() function). You must check the return value of this method to
149 * find out which case applies.
150 *
151 * @param parserContext - parsed representation of the script (see loadScript())
152 * @param execContext - VM execution context (see createExecContext())
153 * @param handler - precise event handler (i.e. "on note ... end on"
154 * code block) to be executed
155 * (see VMParserContext::eventHandlerByName())
156 * @returns current status of the vitual machine (i.e. script succeeded,
157 * script runtime error occurred or script was suspended for
158 * some reason).
159 */
160 VMExecStatus_t exec(VMParserContext* parserContext, VMExecContext* execContext, VMEventHandler* handler);
161
162 /**
163 * Returns built-in script function for the given function @a name. To
164 * get the implementation of the built-in message() script function for
165 * example, you would pass "message" here).
166 *
167 * This method is re-implemented by deriving classes to add more use
168 * case specific built-in functions.
169 *
170 * @param name - name of the function to be retrieved (i.e. "wait" for the
171 * built-in wait() function).
172 */
173 VMFunction* functionByName(const String& name) OVERRIDE;
174
175 /**
176 * Whether the passed built-in function is disabled and should thus be
177 * ignored by the parser at the passed parser context (parser state
178 * where the built-in function call occurs).
179 *
180 * @param fn - built-in function to be checked
181 * @param ctx - parser context at the position where the built-in
182 * function call is located within the script
183 */
184 bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) OVERRIDE;
185
186 /**
187 * Returns all built-in integer script variables. This method returns a
188 * STL map, where the map's key is the variable name and the map's value
189 * is the native pointer to the actual built-in variable.
190 *
191 * This method is re-implemented by deriving classes to add more use
192 * case specific built-in variables.
193 */
194 std::map<String,VMIntPtr*> builtInIntVariables() OVERRIDE;
195
196 /**
197 * Returns all built-in (8 bit) integer array script variables. This
198 * method returns a STL map, where the map's key is the array variable
199 * name and the map's value is the native pointer to the actual built-in
200 * array variable.
201 *
202 * This method is re-implemented by deriving classes to add more use
203 * case specific built-in array variables.
204 */
205 std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
206
207 /**
208 * Returns all built-in constant integer script variables, which are
209 * constant and their final data is already available at parser time
210 * and won't change during runtime. Providing your built-in constants
211 * this way may lead to performance benefits compared to using other
212 * ways of providing built-in variables, because the script parser
213 * can perform optimizations when the script is refering to such
214 * constants.
215 *
216 * This type of built-in variable can only be read, but not be altered
217 * by scripts. This method returns a STL map, where the map's key is
218 * the variable name and the map's value is the final constant data.
219 *
220 * This method is re-implemented by deriving classes to add more use
221 * case specific built-in constant integers.
222 *
223 * @b Note: In case your built-in variable should be read-only but its
224 * value is not already available at parser time (i.e. because its
225 * value may change at runtime), then you should add it to
226 * builtInIntVariables() instead and use the macro
227 * DECLARE_VMINT_READONLY() to define the variable for read-only
228 * access by scripts.
229 */
230 std::map<String,vmint> builtInConstIntVariables() OVERRIDE;
231
232 /**
233 * Returns all built-in constant real number (floating point) script
234 * variables, which are constant and their final data is already
235 * available at parser time and won't change during runtime. Providing
236 * your built-in constants this way may lead to performance benefits
237 * compared to using other ways of providing built-in variables, because
238 * the script parser can perform optimizations when the script is
239 * refering to such constants.
240 *
241 * This type of built-in variable can only be read, but not be altered
242 * by scripts. This method returns a STL map, where the map's key is
243 * the variable name and the map's value is the final constant data.
244 *
245 * This method is re-implemented by deriving classes to add more use
246 * case specific built-in constant real numbers.
247 */
248 std::map<String,vmfloat> builtInConstRealVariables() OVERRIDE;
249
250 /**
251 * Returns all built-in dynamic variables. This method returns a STL
252 * map, where the map's key is the dynamic variable's name and the
253 * map's value is the pointer to the actual object implementing the
254 * behavior which is actually generating the content of the dynamic
255 * variable.
256 *
257 * This method is re-implemented by deriving classes to add more use
258 * case specific built-in dynamic variables.
259 */
260 std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
261
262 /**
263 * Enables or disables automatic suspension of scripts by the VM.
264 * If automatic suspension is enabled then scripts are monitored
265 * regarding their execution time and in case they are execution
266 * for too long, then they are automatically suspended by the VM for
267 * a certain amount of time in order to avoid any RT instablity
268 * issues caused by bugs in the script, i.e. endless while() loops
269 * or very large scripts.
270 *
271 * Automatic suspension is enabled by default due to the aimed
272 * real-time context of this virtual machine.
273 *
274 * @param b - true: enable auto suspension [default],
275 * false: disable auto suspension
276 */
277 void setAutoSuspendEnabled(bool b = true);
278
279 /**
280 * Returns true in case automatic suspension of scripts by the VM is
281 * enabled. See setAutoSuspendEnabled() for details.
282 *
283 * Automatic suspension is enabled by default due to the aimed
284 * real-time context of this virtual machine.
285 */
286 bool isAutoSuspendEnabled() const;
287
288 /**
289 * By default (i.e. in production use) the built-in exit() function
290 * prohibits any arguments to be passed to its function by scripts. So
291 * by default, scripts trying to pass any arguments to the built-in
292 * exit() function will yield in a parser error.
293 *
294 * By calling this method the built-in exit() function will optionally
295 * accept one argument to be passed to its function call by scripts. The
296 * value of that function argument will become available by calling
297 * VMExecContext::exitResult() after execution of the script.
298 *
299 * @see VMExecContext::exitResult()
300 */
301 void setExitResultEnabled(bool b = true);
302
303 /**
304 * Returns @c true if the built-in exit() function optionally accepts
305 * a function argument by scripts.
306 *
307 * @see setExitResultEnabled()
308 */
309 bool isExitResultEnabled() const;
310
311 VMEventHandler* currentVMEventHandler(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
312 VMParserContext* currentVMParserContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
313 VMExecContext* currentVMExecContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
314
315 protected:
316 VMEventHandler* m_eventHandler;
317 ParserContext* m_parserContext;
318 bool m_autoSuspend;
319 bool m_acceptExitRes;
320 class CoreVMFunction_message* m_fnMessage;
321 class CoreVMFunction_exit* m_fnExit;
322 class CoreVMFunction_wait* m_fnWait;
323 class CoreVMFunction_abs* m_fnAbs;
324 class CoreVMFunction_random* m_fnRandom;
325 class CoreVMFunction_num_elements* m_fnNumElements;
326 class CoreVMFunction_inc* m_fnInc;
327 class CoreVMFunction_dec* m_fnDec;
328 class CoreVMFunction_in_range* m_fnInRange;
329 class CoreVMFunction_sh_left* m_fnShLeft;
330 class CoreVMFunction_sh_right* m_fnShRight;
331 class CoreVMFunction_min* m_fnMin;
332 class CoreVMFunction_max* m_fnMax;
333 class CoreVMFunction_array_equal* m_fnArrayEqual;
334 class CoreVMFunction_search* m_fnSearch;
335 class CoreVMFunction_sort* m_fnSort;
336 class CoreVMFunction_int_to_real* m_fnIntToReal;
337 class CoreVMFunction_real_to_int* m_fnRealToInt;
338 class CoreVMFunction_round* m_fnRound;
339 class CoreVMFunction_ceil* m_fnCeil;
340 class CoreVMFunction_floor* m_fnFloor;
341 class CoreVMFunction_sqrt* m_fnSqrt;
342 class CoreVMFunction_log* m_fnLog;
343 class CoreVMFunction_log2* m_fnLog2;
344 class CoreVMFunction_log10* m_fnLog10;
345 class CoreVMFunction_exp* m_fnExp;
346 class CoreVMFunction_pow* m_fnPow;
347 class CoreVMFunction_sin* m_fnSin;
348 class CoreVMFunction_cos* m_fnCos;
349 class CoreVMFunction_tan* m_fnTan;
350 class CoreVMFunction_asin* m_fnAsin;
351 class CoreVMFunction_acos* m_fnAcos;
352 class CoreVMFunction_atan* m_fnAtan;
353 class CoreVMDynVar_NKSP_REAL_TIMER* m_varRealTimer;
354 class CoreVMDynVar_NKSP_PERF_TIMER* m_varPerfTimer;
355 };
356
357 } // namespace LinuxSampler
358
359 #endif // LS_INSTRUMENTSCRIPTVM_H

  ViewVC Help
Powered by ViewVC