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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3733 - (hide annotations) (download) (as text)
Sat Feb 1 18:11:20 2020 UTC (4 years, 2 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 19420 byte(s)
NKSP: Added support for 'patch' variables.

* NKSP language: Added support for 'patch' variable qualifier
  (as new dedicated keyword 'patch').

* NKSP parser: capture locations of 'patch' variable declarations
  in script's source code.

* ScriptVM: Allow patching 'patch' script variables by replacing
  their default assignment expression with a supplied replacement
  variable initialization expression by optional 2nd argument when
  calling loadScript().

* ScriptVM: Allow retrieval of default initialization expressions
  of all 'patch' variables by optional 3rd argument when calling
  loadScript() (i.e. for instrument editors).

* gig engine: Implemented support for loading real-time instrument
  scripts with 'patch' variables bundled with gig instruments.

* Bumped version (2.1.1.svn46).


1 schoenebeck 2581 /*
2 schoenebeck 3733 * Copyright (c) 2014-2020 Christian Schoenebeck
3 schoenebeck 2581 *
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 schoenebeck 2588 class ExecContext;
23 schoenebeck 2581
24 schoenebeck 2594 /** @brief Core virtual machine for real-time instrument scripts.
25     *
26 schoenebeck 2727 * 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 schoenebeck 2594 *
33     * The actual use case specific functionalites (i.e. MIDI processing) is
34 schoenebeck 2727 * then implemented by sampler engines' VM classes which are derived from
35     * this generalized ScriptVM class.
36 schoenebeck 2594 *
37 schoenebeck 2727 * 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 schoenebeck 2729 * which will return the parsed representation of the script.
43 schoenebeck 2727 * - 3. Create a VM execution context by calling createExecContext().
44     * - 4. Execute the script by calling method exec().
45     *
46 schoenebeck 2594 * 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 schoenebeck 2581 class ScriptVM : public VMFunctionProvider {
57     public:
58     ScriptVM();
59     virtual ~ScriptVM();
60 schoenebeck 2727
61     /**
62     * Loads a script given by its source code (passed as argument @a s to
63 schoenebeck 2729 * this method) and returns the parsed representation of that script.
64 schoenebeck 2727 * 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 schoenebeck 2889 * It is your responsibility to free the returned VMParserContext
70     * object once you don't need it anymore.
71     *
72 schoenebeck 3733 * The NKSP language supports so called 'patch' variables, which are
73     * declared by the dedicated keyword 'patch' (as variable qualifier) in
74     * real-time instrument scripts, like e.g.:
75     * @code
76     * on init
77     * declare patch ~foo := 0.435
78     * end on
79     * @endcode
80     * These 'patch' variables allow to override their initial value (i.e.
81     * on a per instrument basis). In the example above, the script variable
82     * @c ~foo would be initialized with value @c 0.435 by default. However
83     * by simply passing an appropriate key-value pair with argument
84     * @p patchVars when calling this method, the NKSP parser will replace
85     * that default initialization value by the passed replacement value.
86     * So key of the optional @p patchVars map argument is the ('patch')
87     * variable name to be patched, and value is the replacement
88     * initialization value for the respective variable. You can see this as
89     * kind of preprocessor mechanism of the NKSP parser, so you are not
90     * limited to simply replace a scalar value with a different scalar
91     * value, you can actually replace any complex default initialization
92     * expression with a new (potentially complex) replacement expression,
93     * e.g. including function calls, formulas, etc.
94     *
95     * The optional 3rd argument @p patchVarsDef allows you to retrieve the
96     * default initialization value(s) of all 'patch' variables declared in
97     * the passed script itself. This is useful for instrument editors.
98     *
99 schoenebeck 2727 * @param s - entire source code of the script to be loaded
100 schoenebeck 3733 * @param patchVars - (optional) replacement value for patch variables
101     * @param patchVarsDef - (optional) output of original values of patch
102     * variables
103 schoenebeck 2729 * @returns parsed representation of the script
104 schoenebeck 2727 */
105 schoenebeck 3733 VMParserContext* loadScript(const String& s,
106     const std::map<String,String>& patchVars =
107     std::map<String,String>(),
108     std::map<String,String>* patchVarsDef = NULL);
109 schoenebeck 2727
110     /**
111     * Same as above's loadScript() method, but this one reads the script's
112     * source code from an input stream object (i.e. stdin or a file).
113     *
114     * @param is - input stream from which the entire source code of the
115     * script is to be read and loaded from
116 schoenebeck 3733 * @param patchVars - (optional) replacement value for patch variables
117     * @param patchVarsDef - (optional) output of original values of patch
118     * variables
119 schoenebeck 2729 * @returns parsed representation of the script
120 schoenebeck 2727 */
121 schoenebeck 3733 VMParserContext* loadScript(std::istream* is,
122     const std::map<String,String>& patchVars =
123     std::map<String,String>(),
124     std::map<String,String>* patchVarsDef = NULL);
125 schoenebeck 2727
126     /**
127 schoenebeck 2885 * Parses a script's source code (passed as argument @a s to this
128     * method), splits that input up in its individual tokens (i.e.
129     * keyword, variable name, event name, etc.) and returns all those
130     * tokens, for the purpose that the caller can provide syntax syntax
131     * highlighting for the passed script.
132     *
133     * This method is actually not used by the sampler at all, it is rather
134     * provided for external script editor applications, to provide them a
135     * convenient backend for parsing scripts and providing syntax
136     * highlighting.
137     *
138     * @returns recognized tokens of passed script's source code
139     */
140     std::vector<VMSourceToken> syntaxHighlighting(const String& s);
141    
142     /**
143     * Same as above's syntaxHighlighting() method, but this one reads the
144     * script's source code from an input stream object (i.e. stdin or a
145     * file).
146     *
147     * @param is - input stream from which the entire source code of the
148     * script is to be read and loaded from
149     * @returns recognized tokens of passed script's source code
150     */
151     std::vector<VMSourceToken> syntaxHighlighting(std::istream* is);
152    
153     /**
154 schoenebeck 2727 * Dumps the translated tree of the already parsed script, given by
155     * argument @a context, to stdout. This method is for debugging purposes
156     * only.
157     *
158 schoenebeck 2729 * @param context - parsed representation of the script
159 schoenebeck 2728 * @see loadScript()
160 schoenebeck 2727 */
161 schoenebeck 2588 void dumpParsedScript(VMParserContext* context);
162 schoenebeck 2727
163     /**
164     * Creates a so called VM exceution context for a specific, already
165     * parsed script (provided by argument @a parserContext). Due to the
166     * general real-time design of this virtual machine, the VM execution
167     * context differs for every script. So you must (re)create the
168     * execution context for each script being loaded.
169 schoenebeck 2728 *
170 schoenebeck 2729 * @param parserContext - parsed representation of the script
171 schoenebeck 2728 * @see loadScript()
172 schoenebeck 2727 */
173 schoenebeck 2588 VMExecContext* createExecContext(VMParserContext* parserContext);
174 schoenebeck 2727
175     /**
176     * Execute a script by virtual machine. Since scripts are event-driven,
177     * you actually execute only one specific event handler block (i.e. a
178     * "on note ... end on" code block) by calling this method (not the
179     * entire script), and hence you must provide one precise handler of the
180     * script to be executed by this method.
181     *
182     * This method usually blocks until the entire script event handler
183     * block has been executed completely. It may however also return before
184     * completion if either a) a script runtime error occurred or b) the
185 schoenebeck 2871 * script was suspended by the VM (either because script execution
186 schoenebeck 2727 * exceeded a certain limit of time or the script called the built-in
187     * wait() function). You must check the return value of this method to
188     * find out which case applies.
189     *
190 schoenebeck 2729 * @param parserContext - parsed representation of the script (see loadScript())
191 schoenebeck 2727 * @param execContext - VM execution context (see createExecContext())
192     * @param handler - precise event handler (i.e. "on note ... end on"
193     * code block) to be executed
194     * (see VMParserContext::eventHandlerByName())
195     * @returns current status of the vitual machine (i.e. script succeeded,
196     * script runtime error occurred or script was suspended for
197     * some reason).
198     */
199     VMExecStatus_t exec(VMParserContext* parserContext, VMExecContext* execContext, VMEventHandler* handler);
200    
201     /**
202     * Returns built-in script function for the given function @a name. To
203     * get the implementation of the built-in message() script function for
204     * example, you would pass "message" here).
205     *
206     * This method is re-implemented by deriving classes to add more use
207     * case specific built-in functions.
208     *
209     * @param name - name of the function to be retrieved (i.e. "wait" for the
210     * built-in wait() function).
211     */
212 schoenebeck 2594 VMFunction* functionByName(const String& name) OVERRIDE;
213 schoenebeck 2727
214     /**
215 schoenebeck 3311 * Whether the passed built-in function is disabled and should thus be
216     * ignored by the parser at the passed parser context (parser state
217     * where the built-in function call occurs).
218     *
219     * @param fn - built-in function to be checked
220     * @param ctx - parser context at the position where the built-in
221     * function call is located within the script
222     */
223     bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) OVERRIDE;
224    
225     /**
226 schoenebeck 2727 * Returns all built-in integer script variables. This method returns a
227     * STL map, where the map's key is the variable name and the map's value
228     * is the native pointer to the actual built-in variable.
229     *
230     * This method is re-implemented by deriving classes to add more use
231     * case specific built-in variables.
232     */
233 schoenebeck 3557 std::map<String,VMIntPtr*> builtInIntVariables() OVERRIDE;
234 schoenebeck 2727
235     /**
236     * Returns all built-in (8 bit) integer array script variables. This
237     * method returns a STL map, where the map's key is the array variable
238     * name and the map's value is the native pointer to the actual built-in
239     * array variable.
240     *
241     * This method is re-implemented by deriving classes to add more use
242     * case specific built-in array variables.
243     */
244 schoenebeck 2594 std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
245 schoenebeck 2727
246     /**
247 schoenebeck 2948 * Returns all built-in constant integer script variables, which are
248     * constant and their final data is already available at parser time
249     * and won't change during runtime. Providing your built-in constants
250     * this way may lead to performance benefits compared to using other
251     * ways of providing built-in variables, because the script parser
252     * can perform optimizations when the script is refering to such
253     * constants.
254 schoenebeck 2727 *
255 schoenebeck 2948 * This type of built-in variable can only be read, but not be altered
256     * by scripts. This method returns a STL map, where the map's key is
257     * the variable name and the map's value is the final constant data.
258     *
259 schoenebeck 2727 * This method is re-implemented by deriving classes to add more use
260     * case specific built-in constant integers.
261     *
262 schoenebeck 2948 * @b Note: In case your built-in variable should be read-only but its
263     * value is not already available at parser time (i.e. because its
264     * value may change at runtime), then you should add it to
265     * builtInIntVariables() instead and use the macro
266     * DECLARE_VMINT_READONLY() to define the variable for read-only
267     * access by scripts.
268 schoenebeck 2727 */
269 schoenebeck 3557 std::map<String,vmint> builtInConstIntVariables() OVERRIDE;
270 schoenebeck 2588
271 schoenebeck 2942 /**
272 schoenebeck 3590 * Returns all built-in constant real number (floating point) script
273     * variables, which are constant and their final data is already
274     * available at parser time and won't change during runtime. Providing
275     * your built-in constants this way may lead to performance benefits
276     * compared to using other ways of providing built-in variables, because
277     * the script parser can perform optimizations when the script is
278     * refering to such constants.
279     *
280     * This type of built-in variable can only be read, but not be altered
281     * by scripts. This method returns a STL map, where the map's key is
282     * the variable name and the map's value is the final constant data.
283     *
284     * This method is re-implemented by deriving classes to add more use
285     * case specific built-in constant real numbers.
286     */
287     std::map<String,vmfloat> builtInConstRealVariables() OVERRIDE;
288    
289     /**
290 schoenebeck 2942 * Returns all built-in dynamic variables. This method returns a STL
291     * map, where the map's key is the dynamic variable's name and the
292     * map's value is the pointer to the actual object implementing the
293     * behavior which is actually generating the content of the dynamic
294     * variable.
295     *
296     * This method is re-implemented by deriving classes to add more use
297     * case specific built-in dynamic variables.
298     */
299     std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
300    
301 schoenebeck 2974 /**
302     * Enables or disables automatic suspension of scripts by the VM.
303     * If automatic suspension is enabled then scripts are monitored
304     * regarding their execution time and in case they are execution
305     * for too long, then they are automatically suspended by the VM for
306     * a certain amount of time in order to avoid any RT instablity
307     * issues caused by bugs in the script, i.e. endless while() loops
308     * or very large scripts.
309     *
310     * Automatic suspension is enabled by default due to the aimed
311     * real-time context of this virtual machine.
312     *
313     * @param b - true: enable auto suspension [default],
314     * false: disable auto suspension
315     */
316     void setAutoSuspendEnabled(bool b = true);
317    
318     /**
319     * Returns true in case automatic suspension of scripts by the VM is
320     * enabled. See setAutoSuspendEnabled() for details.
321     *
322     * Automatic suspension is enabled by default due to the aimed
323     * real-time context of this virtual machine.
324     */
325     bool isAutoSuspendEnabled() const;
326    
327 schoenebeck 3551 /**
328     * By default (i.e. in production use) the built-in exit() function
329     * prohibits any arguments to be passed to its function by scripts. So
330     * by default, scripts trying to pass any arguments to the built-in
331     * exit() function will yield in a parser error.
332     *
333     * By calling this method the built-in exit() function will optionally
334     * accept one argument to be passed to its function call by scripts. The
335     * value of that function argument will become available by calling
336     * VMExecContext::exitResult() after execution of the script.
337     *
338     * @see VMExecContext::exitResult()
339     */
340     void setExitResultEnabled(bool b = true);
341    
342     /**
343     * Returns @c true if the built-in exit() function optionally accepts
344     * a function argument by scripts.
345     *
346     * @see setExitResultEnabled()
347     */
348     bool isExitResultEnabled() const;
349    
350 schoenebeck 2879 VMEventHandler* currentVMEventHandler(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
351 schoenebeck 2588 VMParserContext* currentVMParserContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
352     VMExecContext* currentVMExecContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions)
353 schoenebeck 2727
354 schoenebeck 3733 private:
355     VMParserContext* loadScriptOnePass(const String& s);
356 schoenebeck 2581 protected:
357 schoenebeck 2879 VMEventHandler* m_eventHandler;
358 schoenebeck 2588 ParserContext* m_parserContext;
359 schoenebeck 2974 bool m_autoSuspend;
360 schoenebeck 3551 bool m_acceptExitRes;
361 schoenebeck 2942 class CoreVMFunction_message* m_fnMessage;
362     class CoreVMFunction_exit* m_fnExit;
363     class CoreVMFunction_wait* m_fnWait;
364     class CoreVMFunction_abs* m_fnAbs;
365     class CoreVMFunction_random* m_fnRandom;
366     class CoreVMFunction_num_elements* m_fnNumElements;
367 schoenebeck 2945 class CoreVMFunction_inc* m_fnInc;
368     class CoreVMFunction_dec* m_fnDec;
369 schoenebeck 3076 class CoreVMFunction_in_range* m_fnInRange;
370 schoenebeck 2965 class CoreVMFunction_sh_left* m_fnShLeft;
371     class CoreVMFunction_sh_right* m_fnShRight;
372 schoenebeck 3678 class CoreVMFunction_msb* m_fnMsb;
373     class CoreVMFunction_lsb* m_fnLsb;
374 schoenebeck 2970 class CoreVMFunction_min* m_fnMin;
375     class CoreVMFunction_max* m_fnMax;
376 schoenebeck 3221 class CoreVMFunction_array_equal* m_fnArrayEqual;
377     class CoreVMFunction_search* m_fnSearch;
378     class CoreVMFunction_sort* m_fnSort;
379 schoenebeck 3573 class CoreVMFunction_int_to_real* m_fnIntToReal;
380     class CoreVMFunction_real_to_int* m_fnRealToInt;
381 schoenebeck 3590 class CoreVMFunction_round* m_fnRound;
382     class CoreVMFunction_ceil* m_fnCeil;
383     class CoreVMFunction_floor* m_fnFloor;
384     class CoreVMFunction_sqrt* m_fnSqrt;
385     class CoreVMFunction_log* m_fnLog;
386     class CoreVMFunction_log2* m_fnLog2;
387     class CoreVMFunction_log10* m_fnLog10;
388     class CoreVMFunction_exp* m_fnExp;
389     class CoreVMFunction_pow* m_fnPow;
390     class CoreVMFunction_sin* m_fnSin;
391     class CoreVMFunction_cos* m_fnCos;
392     class CoreVMFunction_tan* m_fnTan;
393     class CoreVMFunction_asin* m_fnAsin;
394     class CoreVMFunction_acos* m_fnAcos;
395     class CoreVMFunction_atan* m_fnAtan;
396 schoenebeck 2942 class CoreVMDynVar_NKSP_REAL_TIMER* m_varRealTimer;
397     class CoreVMDynVar_NKSP_PERF_TIMER* m_varPerfTimer;
398 schoenebeck 2581 };
399    
400     } // namespace LinuxSampler
401    
402     #endif // LS_INSTRUMENTSCRIPTVM_H

  ViewVC Help
Powered by ViewVC