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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2948 - (show annotations) (download) (as text)
Fri Jul 15 15:29:04 2016 UTC (7 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 43476 byte(s)
* NKSP: Implemented built-in script function "stop_wait()".
* NKSP: Implemented built-in script variable "$NI_CALLBACK_ID".
* NKSP: Implemented built-in script variable "$NI_CALLBACK_TYPE".
* NKSP: Implemented built-in script variable "$NKSP_IGNORE_WAIT".
* NKSP: Added support for read-only built-in variables
  (respectively handled by the script parser).
* NKSP: Added built-in script constant "$NI_CB_TYPE_INIT".
* NKSP: Added built-in script constant "$NI_CB_TYPE_NOTE".
* NKSP: Added built-in script constant "$NI_CB_TYPE_RELEASE".
* NKSP: Added built-in script constant "$NI_CB_TYPE_CONTROLLER".
* Bumped version (2.0.0.svn17).

1 /*
2 * Copyright (c) 2014-2016 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 // This header defines data types shared between the VM core implementation
11 // (inside the current source directory) and other parts of the sampler
12 // (located at other source directories).
13
14 #ifndef LS_INSTR_SCRIPT_PARSER_COMMON_H
15 #define LS_INSTR_SCRIPT_PARSER_COMMON_H
16
17 #include "../common/global.h"
18 #include <vector>
19 #include <map>
20 #include <stddef.h> // offsetof()
21
22 namespace LinuxSampler {
23
24 /**
25 * Identifies the type of a noteworthy issue identified by the script
26 * parser. That's either a parser error or parser warning.
27 */
28 enum ParserIssueType_t {
29 PARSER_ERROR, ///< Script parser encountered an error, the script cannot be executed.
30 PARSER_WARNING ///< Script parser encountered a warning, the script may be executed if desired, but the script may not necessarily behave as originally intended by the script author.
31 };
32
33 /** @brief Expression's data type.
34 *
35 * Identifies to which data type an expression within a script evaluates to.
36 * This can for example reflect the data type of script function arguments,
37 * script function return values, but also the resulting data type of some
38 * mathematical formula within a script.
39 */
40 enum ExprType_t {
41 EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value (the built-in wait() or message() functions for instance)
42 INT_EXPR, ///< integer (scalar) expression
43 INT_ARR_EXPR, ///< integer array expression
44 STRING_EXPR, ///< string expression
45 STRING_ARR_EXPR, ///< string array expression
46 };
47
48 /** @brief Result flags of a script statement or script function call.
49 *
50 * A set of bit flags which provide informations about the success or
51 * failure of a statement within a script. That's also especially used for
52 * providing informations about success / failure of a call to a built-in
53 * script function. The virtual machine evaluates these flags during runtime
54 * to decide whether it should i.e. stop or suspend execution of a script.
55 *
56 * Since these are bit flags, these constants are bitwise combined.
57 */
58 enum StmtFlags_t {
59 STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred.
60 STMT_ABORT_SIGNALLED = 1, ///< VM should stop the current callback execution (usually because of an error, but might also be without an error reason, i.e. when the built-in script function exit() was called).
61 STMT_SUSPEND_SIGNALLED = (1<<1), ///< VM supended execution, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time
62 STMT_ERROR_OCCURRED = (1<<2), ///< VM stopped execution due to some script runtime error that occurred
63 };
64
65 /** @brief Virtual machine execution status.
66 *
67 * A set of bit flags which reflect the current overall execution status of
68 * the virtual machine concerning a certain script execution instance.
69 *
70 * Since these are bit flags, these constants are bitwise combined.
71 */
72 enum VMExecStatus_t {
73 VM_EXEC_NOT_RUNNING = 0, ///< Script is currently not executed by the VM.
74 VM_EXEC_RUNNING = 1, ///< The VM is currently executing the script.
75 VM_EXEC_SUSPENDED = (1<<1), ///< Script is currently suspended by the VM, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time.
76 VM_EXEC_ERROR = (1<<2), ///< A runtime error occurred while executing the script (i.e. a call to some built-in script function failed).
77 };
78
79 /** @brief Script event handler type.
80 *
81 * Identifies one of the possible event handler callback types defined by
82 * the NKSP script language.
83 */
84 enum VMEventHandlerType_t {
85 VM_EVENT_HANDLER_INIT, ///< Initilization event handler, that is script's "on init ... end on" code block.
86 VM_EVENT_HANDLER_NOTE, ///< Note event handler, that is script's "on note ... end on" code block.
87 VM_EVENT_HANDLER_RELEASE, ///< Release event handler, that is script's "on release ... end on" code block.
88 VM_EVENT_HANDLER_CONTROLLER, ///< Controller event handler, that is script's "on controller ... end on" code block.
89 };
90
91 // just symbol prototyping
92 class VMIntExpr;
93 class VMStringExpr;
94 class VMIntArrayExpr;
95 class VMStringArrayExpr;
96
97 /** @brief Virtual machine expression
98 *
99 * This is the abstract base class for all expressions of scripts.
100 * Deriving classes must implement the abstract method exprType().
101 *
102 * An expression within a script is translated into one instance of this
103 * class. It allows a high level access for the virtual machine to evaluate
104 * and handle expressions appropriately during execution. Expressions are
105 * for example all kinds of formulas, function calls, statements or a
106 * combination of them. Most of them evaluate to some kind of value, which
107 * might be further processed as part of encompassing expressions to outer
108 * expression results and so forth.
109 */
110 class VMExpr {
111 public:
112 /**
113 * Identifies the data type to which the result of this expression
114 * evaluates to. This abstract method must be implemented by deriving
115 * classes.
116 */
117 virtual ExprType_t exprType() const = 0;
118
119 /**
120 * In case this expression is an integer expression, then this method
121 * returns a casted pointer to that VMIntExpr object. It returns NULL
122 * if this expression is not an integer expression.
123 *
124 * @b Note: type casting performed by this method is strict! That means
125 * if this expression is i.e. actually a string expression like "12",
126 * calling asInt() will @b not cast that numerical string expression to
127 * an integer expression 12 for you, instead this method will simply
128 * return NULL!
129 *
130 * @see exprType()
131 */
132 VMIntExpr* asInt() const;
133
134 /**
135 * In case this expression is a string expression, then this method
136 * returns a casted pointer to that VMStringExpr object. It returns NULL
137 * if this expression is not a string expression.
138 *
139 * @b Note: type casting performed by this method is strict! That means
140 * if this expression is i.e. actually an integer expression like 120,
141 * calling asString() will @b not cast that integer expression to a
142 * string expression "120" for you, instead this method will simply
143 * return NULL!
144 *
145 * @see exprType()
146 */
147 VMStringExpr* asString() const;
148
149 /**
150 * In case this expression is an integer array expression, then this
151 * method returns a casted pointer to that VMIntArrayExpr object. It
152 * returns NULL if this expression is not an integer array expression.
153 *
154 * @b Note: type casting performed by this method is strict! That means
155 * if this expression is i.e. an integer expression or a string
156 * expression, calling asIntArray() will @b not cast those scalar
157 * expressions to an array expression for you, instead this method will
158 * simply return NULL!
159 *
160 * @see exprType()
161 */
162 VMIntArrayExpr* asIntArray() const;
163
164 /**
165 * Returns true in case this expression can be considered to be a
166 * constant expression. A constant expression will retain the same
167 * value throughout the entire life time of a script and the
168 * expression's constant value may be evaluated already at script
169 * parse time, which may result in performance benefits during script
170 * runtime.
171 */
172 virtual bool isConstExpr() const = 0;
173
174 bool isModifyable() const;
175 };
176
177 /** @brief Virtual machine integer expression
178 *
179 * This is the abstract base class for all expressions inside scripts which
180 * evaluate to an integer (scalar) value. Deriving classes implement the
181 * abstract method evalInt() to return the actual integer result value of
182 * the expression.
183 */
184 class VMIntExpr : virtual public VMExpr {
185 public:
186 /**
187 * Returns the result of this expression as integer (scalar) value.
188 * This abstract method must be implemented by deriving classes.
189 */
190 virtual int evalInt() = 0;
191
192 /**
193 * Returns always INT_EXPR for instances of this class.
194 */
195 ExprType_t exprType() const OVERRIDE { return INT_EXPR; }
196 };
197
198 /** @brief Virtual machine string expression
199 *
200 * This is the abstract base class for all expressions inside scripts which
201 * evaluate to a string value. Deriving classes implement the abstract
202 * method evalStr() to return the actual string result value of the
203 * expression.
204 */
205 class VMStringExpr : virtual public VMExpr {
206 public:
207 /**
208 * Returns the result of this expression as string value. This abstract
209 * method must be implemented by deriving classes.
210 */
211 virtual String evalStr() = 0;
212
213 /**
214 * Returns always STRING_EXPR for instances of this class.
215 */
216 ExprType_t exprType() const OVERRIDE { return STRING_EXPR; }
217 };
218
219 /** @brief Virtual Machine Array Value Expression
220 *
221 * This is the abstract base class for all expressions inside scripts which
222 * evaluate to some kind of array value. Deriving classes implement the
223 * abstract method arraySize() to return the amount of elements within the
224 * array.
225 */
226 class VMArrayExpr : virtual public VMExpr {
227 public:
228 /**
229 * Returns amount of elements in this array. This abstract method must
230 * be implemented by deriving classes.
231 */
232 virtual int arraySize() const = 0;
233 };
234
235 /** @brief Virtual Machine Integer Array Expression
236 *
237 * This is the abstract base class for all expressions inside scripts which
238 * evaluate to an array of integer values. Deriving classes implement the
239 * abstract methods arraySize(), evalIntElement() and assignIntElement() to
240 * access the individual integer array values.
241 */
242 class VMIntArrayExpr : virtual public VMArrayExpr {
243 public:
244 /**
245 * Returns the (scalar) integer value of the array element given by
246 * element index @a i.
247 *
248 * @param i - array element index (must be between 0 .. arraySize() - 1)
249 */
250 virtual int evalIntElement(uint i) = 0;
251
252 /**
253 * Changes the current value of an element (given by array element
254 * index @a i) of this integer array.
255 *
256 * @param i - array element index (must be between 0 .. arraySize() - 1)
257 * @param value - new integer scalar value to be assigned to that array element
258 */
259 virtual void assignIntElement(uint i, int value) = 0;
260
261 /**
262 * Returns always INT_ARR_EXPR for instances of this class.
263 */
264 ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; }
265 };
266
267 /** @brief Arguments (parameters) for being passed to a built-in script function.
268 *
269 * An argument or a set of arguments passed to a script function are
270 * translated by the parser to an instance of this class. This abstract
271 * interface class is used by implementations of built-in functions to
272 * obtain the individual function argument values being passed to them at
273 * runtime.
274 */
275 class VMFnArgs {
276 public:
277 /**
278 * Returns the amount of arguments going to be passed to the script
279 * function.
280 */
281 virtual int argsCount() const = 0;
282
283 /**
284 * Returns the respective argument (requested by argument index @a i) of
285 * this set of arguments. This method is called by implementations of
286 * built-in script functions to obtain the value of each function
287 * argument passed to the function at runtime.
288 *
289 * @param i - function argument index (indexed from left to right)
290 */
291 virtual VMExpr* arg(int i) = 0;
292 };
293
294 /** @brief Result value returned from a call to a built-in script function.
295 *
296 * Implementations of built-in script functions return an instance of this
297 * object to let the virtual machine obtain the result value of the function
298 * call, which might then be further processed by the virtual machine
299 * according to the script. It also provides informations about the success
300 * or failure of the function call.
301 */
302 class VMFnResult {
303 public:
304 /**
305 * Returns the result value of the function call, represented by a high
306 * level expression object.
307 */
308 virtual VMExpr* resultValue() = 0;
309
310 /**
311 * Provides detailed informations of the success / failure of the
312 * function call. The virtual machine is evaluating the flags returned
313 * here to decide whether it must abort or suspend execution of the
314 * script at this point.
315 */
316 virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }
317 };
318
319 /** @brief Virtual machine built-in function.
320 *
321 * Abstract base class for built-in script functions, defining the interface
322 * for all built-in script function implementations. All built-in script
323 * functions are deriving from this abstract interface class in order to
324 * provide their functionality to the virtual machine with this unified
325 * interface.
326 *
327 * The methods of this interface class provide two purposes:
328 *
329 * 1. When a script is loaded, the script parser uses the methods of this
330 * interface to check whether the script author was calling the
331 * respective built-in script function in a correct way. For example
332 * the parser checks whether the required amount of parameters were
333 * passed to the function and whether the data types passed match the
334 * data types expected by the function. If not, loading the script will
335 * be aborted with a parser error, describing to the user (i.e. script
336 * author) the precise misusage of the respective function.
337 * 2. After the script was loaded successfully and the script is executed,
338 * the virtual machine calls the exec() method of the respective built-in
339 * function to provide the actual functionality of the built-in function
340 * call.
341 */
342 class VMFunction {
343 public:
344 /**
345 * Script data type of the function's return value. If the function does
346 * not return any value (void), then it returns EMPTY_EXPR here.
347 */
348 virtual ExprType_t returnType() = 0;
349
350 /**
351 * Minimum amount of function arguments this function accepts. If a
352 * script is calling this function with less arguments, the script
353 * parser will throw a parser error.
354 */
355 virtual int minRequiredArgs() const = 0;
356
357 /**
358 * Maximum amount of function arguments this functions accepts. If a
359 * script is calling this function with more arguments, the script
360 * parser will throw a parser error.
361 */
362 virtual int maxAllowedArgs() const = 0;
363
364 /**
365 * Script data type of the function's @c iArg 'th function argument.
366 * The information provided here is less strong than acceptsArgType().
367 * The parser will compare argument data types provided in scripts by
368 * calling acceptsArgType(). The return value of argType() is used by the
369 * parser instead to show an appropriate parser error which data type
370 * this function usually expects as "default" data type. Reason: a
371 * function may accept multiple data types for a certain function
372 * argument and would automatically cast the passed argument value in
373 * that case to the type it actually needs.
374 *
375 * @param iArg - index of the function argument in question
376 * (must be between 0 .. maxAllowedArgs() - 1)
377 */
378 virtual ExprType_t argType(int iArg) const = 0;
379
380 /**
381 * This method is called by the parser to check whether arguments
382 * passed in scripts to this function are accepted by this function. If
383 * a script calls this function with an argument's data type not
384 * accepted by this function, the parser will throw a parser error. On
385 * such errors the data type returned by argType() will be used to
386 * assemble an appropriate error message regarding the precise misusage
387 * of the built-in function.
388 *
389 * @param iArg - index of the function argument in question
390 * (must be between 0 .. maxAllowedArgs() - 1)
391 * @param type - script data type used for this function argument by
392 * currently parsed script
393 * @return true if the given data type would be accepted for the
394 * respective function argument by the function
395 */
396 virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;
397
398 /**
399 * This method is called by the parser to check whether some arguments
400 * (and if yes which ones) passed to this script function will be
401 * modified by this script function. Most script functions simply use
402 * their arguments as inputs, that is they only read the argument's
403 * values. However some script function may also use passed
404 * argument(s) as output variables. In this case the function
405 * implementation must return @c true for the respective argument
406 * index here.
407 *
408 * @param iArg - index of the function argument in question
409 * (must be between 0 .. maxAllowedArgs() - 1)
410 */
411 virtual bool modifiesArg(int iArg) const = 0;
412
413 /**
414 * Implements the actual function execution. This exec() method is
415 * called by the VM whenever this function implementation shall be
416 * executed at script runtime. This method blocks until the function
417 * call completed.
418 *
419 * @param args - function arguments for executing this built-in function
420 * @returns function's return value (if any) and general status
421 * informations (i.e. whether the function call caused a
422 * runtime error)
423 */
424 virtual VMFnResult* exec(VMFnArgs* args) = 0;
425
426 /**
427 * Convenience method for function implementations to show warning
428 * messages during actual execution of the built-in function.
429 *
430 * @param txt - runtime warning text to be shown to user
431 */
432 void wrnMsg(const String& txt);
433
434 /**
435 * Convenience method for function implementations to show error
436 * messages during actual execution of the built-in function.
437 *
438 * @param txt - runtime error text to be shown to user
439 */
440 void errMsg(const String& txt);
441 };
442
443 /** @brief Virtual machine relative pointer.
444 *
445 * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be
446 * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.
447 *
448 * @see VMIntRelPtr, VMInt8RelPtr
449 */
450 struct VMRelPtr {
451 void** base; ///< Base pointer.
452 int offset; ///< Offset (in bytes) relative to base pointer.
453 bool readonly; ///< Whether the pointed data may be modified or just be read.
454 };
455
456 /** @brief Pointer to built-in VM integer variable (of C/C++ type int).
457 *
458 * Used for defining built-in 32 bit integer script variables.
459 *
460 * @b CAUTION: You may only use this class for pointing to C/C++ variables
461 * of type "int" (which on most systems is 32 bit in size). If the C/C++ int
462 * variable you want to reference is only 8 bit in size, then you @b must
463 * use VMInt8RelPtr instead!
464 *
465 * For efficiency reasons the actual native C/C++ int variable is referenced
466 * by two components here. The actual native int C/C++ variable in memory
467 * is dereferenced at VM run-time by taking the @c base pointer dereference
468 * and adding @c offset bytes. This has the advantage that for a large
469 * number of built-in int variables, only one (or few) base pointer need
470 * to be re-assigned before running a script, instead of updating each
471 * built-in variable each time before a script is executed.
472 *
473 * Refer to DECLARE_VMINT() for example code.
474 *
475 * @see VMInt8RelPtr, DECLARE_VMINT()
476 */
477 struct VMIntRelPtr : VMRelPtr {
478 VMIntRelPtr() {
479 base = NULL;
480 offset = 0;
481 readonly = false;
482 }
483 VMIntRelPtr(const VMRelPtr& data) {
484 base = data.base;
485 offset = data.offset;
486 readonly = false;
487 }
488 virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }
489 virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }
490 };
491
492 /** @brief Pointer to built-in VM integer variable (of C/C++ type int8_t).
493 *
494 * Used for defining built-in 8 bit integer script variables.
495 *
496 * @b CAUTION: You may only use this class for pointing to C/C++ variables
497 * of type "int8_t" (8 bit integer). If the C/C++ int variable you want to
498 * reference is an "int" type (which is 32 bit on most systems), then you
499 * @b must use VMIntRelPtr instead!
500 *
501 * For efficiency reasons the actual native C/C++ int variable is referenced
502 * by two components here. The actual native int C/C++ variable in memory
503 * is dereferenced at VM run-time by taking the @c base pointer dereference
504 * and adding @c offset bytes. This has the advantage that for a large
505 * number of built-in int variables, only one (or few) base pointer need
506 * to be re-assigned before running a script, instead of updating each
507 * built-in variable each time before a script is executed.
508 *
509 * Refer to DECLARE_VMINT() for example code.
510 *
511 * @see VMIntRelPtr, DECLARE_VMINT()
512 */
513 struct VMInt8RelPtr : VMIntRelPtr {
514 VMInt8RelPtr() : VMIntRelPtr() {}
515 VMInt8RelPtr(const VMRelPtr& data) : VMIntRelPtr(data) {}
516 virtual int evalInt() OVERRIDE {
517 return *(uint8_t*)&(*(uint8_t**)base)[offset];
518 }
519 virtual void assign(int i) OVERRIDE {
520 *(uint8_t*)&(*(uint8_t**)base)[offset] = i;
521 }
522 };
523
524 /**
525 * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr
526 * structures. Usage example:
527 * @code
528 * struct Foo {
529 * uint8_t a; // native representation of a built-in integer script variable
530 * int b; // native representation of another built-in integer script variable
531 * int c; // native representation of another built-in integer script variable
532 * uint8_t d; // native representation of another built-in integer script variable
533 * };
534 *
535 * // initializing the built-in script variables to some values
536 * Foo foo1 = (Foo) { 1, 2000, 3000, 4 };
537 * Foo foo2 = (Foo) { 5, 6000, 7000, 8 };
538 *
539 * Foo* pFoo;
540 *
541 * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
542 * VMIntRelPtr varB = DECLARE_VMINT(pFoo, class Foo, b);
543 * VMIntRelPtr varC = DECLARE_VMINT(pFoo, class Foo, c);
544 * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
545 *
546 * pFoo = &foo1;
547 * printf("%d\n", varA->evalInt()); // will print 1
548 * printf("%d\n", varB->evalInt()); // will print 2000
549 * printf("%d\n", varC->evalInt()); // will print 3000
550 * printf("%d\n", varD->evalInt()); // will print 4
551 *
552 * // same printf() code, just with pFoo pointer being changed ...
553 *
554 * pFoo = &foo2;
555 * printf("%d\n", varA->evalInt()); // will print 5
556 * printf("%d\n", varB->evalInt()); // will print 6000
557 * printf("%d\n", varC->evalInt()); // will print 7000
558 * printf("%d\n", varD->evalInt()); // will print 8
559 * @endcode
560 * As you can see above, by simply changing one single pointer, you can
561 * remap a huge bunch of built-in integer script variables to completely
562 * different native values/native variables. Which especially reduces code
563 * complexity inside the sampler engines which provide the actual script
564 * functionalities.
565 */
566 #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \
567 (VMRelPtr) { \
568 (void**) &basePtr, \
569 offsetof(T_struct, T_member), \
570 false \
571 } \
572 ) \
573
574 /**
575 * Same as DECLARE_VMINT(), but this one defines the VMIntRelPtr and
576 * VMInt8RelPtr structures to be of read-only type. That means the script
577 * parser will abort any script at parser time if the script is trying to
578 * modify such a read-only built-in variable.
579 *
580 * @b NOTE: this is only intended for built-in read-only variables that
581 * may change during runtime! If your built-in variable's data is rather
582 * already available at parser time and won't change during runtime, then
583 * you should rather register a built-in constant in your VM class instead!
584 *
585 * @see ScriptVM::builtInConstIntVariables()
586 */
587 #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
588 (VMRelPtr) { \
589 (void**) &basePtr, \
590 offsetof(T_struct, T_member), \
591 true \
592 } \
593 ) \
594
595 /** @brief Built-in VM 8 bit integer array variable.
596 *
597 * Used for defining built-in integer array script variables (8 bit per
598 * array element). Currently there is no support for any other kind of array
599 * type. So all integer arrays of scripts use 8 bit data types.
600 */
601 struct VMInt8Array {
602 int8_t* data;
603 int size;
604
605 VMInt8Array() : data(NULL), size(0) {}
606 };
607
608 /** @brief Virtual machine script variable.
609 *
610 * Common interface for all variables accessed in scripts.
611 */
612 class VMVariable : virtual public VMExpr {
613 public:
614 /**
615 * Whether a script may modify the content of this variable by
616 * assigning a new value to it.
617 *
618 * @see isConstExpr(), assign()
619 */
620 virtual bool isAssignable() const = 0;
621
622 /**
623 * In case this variable is assignable, this method will be called to
624 * perform the value assignment to this variable with @a expr
625 * reflecting the new value to be assigned.
626 *
627 * @param expr - new value to be assigned to this variable
628 */
629 virtual void assignExpr(VMExpr* expr) = 0;
630 };
631
632 /** @brief Dynamically executed variable (abstract base class).
633 *
634 * Interface for the implementation of a dynamically generated content of
635 * a built-in script variable. Most built-in variables are simply pointers
636 * to some native location in memory. So when a script reads them, the
637 * memory location is simply read to get the value of the variable. A
638 * dynamic variable however is not simply a memory location. For each access
639 * to a dynamic variable some native code is executed to actually generate
640 * and provide the content (value) of this type of variable.
641 */
642 class VMDynVar : public VMVariable {
643 public:
644 /**
645 * Returns true in case this dynamic variable can be considered to be a
646 * constant expression. A constant expression will retain the same value
647 * throughout the entire life time of a script and the expression's
648 * constant value may be evaluated already at script parse time, which
649 * may result in performance benefits during script runtime.
650 *
651 * However due to the "dynamic" behavior of dynamic variables, almost
652 * all dynamic variables are probably not constant expressions. That's
653 * why this method returns @c false by default. If you are really sure
654 * that your dynamic variable implementation can be considered a
655 * constant expression then you may override this method and return
656 * @c true instead. Note that when you return @c true here, your
657 * dynamic variable will really just be executed once; and exectly
658 * already when the script is loaded!
659 *
660 * As an example you may implement a "constant" built-in dynamic
661 * variable that checks for a certain operating system feature and
662 * returns the result of that OS feature check as content (value) of
663 * this dynamic variable. Since the respective OS feature might become
664 * available/unavailable after OS updates, software migration, etc. the
665 * OS feature check should at least be performed once each time the
666 * application is launched. And since the OS feature check might take a
667 * certain amount of execution time, it might make sense to only
668 * perform the check if the respective variable name is actually
669 * referenced at all in the script to be loaded. Note that the dynamic
670 * variable will still be evaluated again though if the script is
671 * loaded again. So it is up to you to probably cache the result in the
672 * implementation of your dynamic variable.
673 *
674 * On doubt, please rather consider to use a constant built-in script
675 * variable instead of implementing a "constant" dynamic variable, due
676 * to the runtime overhead a dynamic variable may cause.
677 *
678 * @see isAssignable()
679 */
680 bool isConstExpr() const OVERRIDE { return false; }
681
682 /**
683 * In case this dynamic variable is assignable, the new value (content)
684 * to be assigned to this dynamic variable.
685 *
686 * By default this method does nothing. Override and implement this
687 * method in your subclass in case your dynamic variable allows to
688 * assign a new value by script.
689 *
690 * @param expr - new value to be assigned to this variable
691 */
692 void assignExpr(VMExpr* expr) OVERRIDE {}
693 };
694
695 /** @brief Dynamically executed variable (of integer data type).
696 *
697 * This is the base class for all built-in integer script variables whose
698 * variable content needs to be provided dynamically by executable native
699 * code on each script variable access.
700 */
701 class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
702 public:
703 };
704
705 /** @brief Dynamically executed variable (of string data type).
706 *
707 * This is the base class for all built-in string script variables whose
708 * variable content needs to be provided dynamically by executable native
709 * code on each script variable access.
710 */
711 class VMDynStringVar : virtual public VMDynVar, virtual public VMStringExpr {
712 public:
713 };
714
715 /** @brief Provider for built-in script functions and variables.
716 *
717 * Abstract base class defining the high-level interface for all classes
718 * which add and implement built-in script functions and built-in script
719 * variables.
720 */
721 class VMFunctionProvider {
722 public:
723 /**
724 * Returns pointer to the built-in function with the given function
725 * @a name, or NULL if there is no built-in function with that function
726 * name.
727 *
728 * @param name - function name (i.e. "wait" or "message" or "exit", etc.)
729 */
730 virtual VMFunction* functionByName(const String& name) = 0;
731
732 /**
733 * Returns a variable name indexed map of all built-in script variables
734 * which point to native "int" scalar (usually 32 bit) variables.
735 */
736 virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;
737
738 /**
739 * Returns a variable name indexed map of all built-in script integer
740 * array variables with array element type "int8_t" (8 bit).
741 */
742 virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
743
744 /**
745 * Returns a variable name indexed map of all built-in constant script
746 * variables, which never change their value at runtime.
747 */
748 virtual std::map<String,int> builtInConstIntVariables() = 0;
749
750 /**
751 * Returns a variable name indexed map of all built-in dynamic variables,
752 * which are not simply data stores, rather each one of them executes
753 * natively to provide or alter the respective script variable data.
754 */
755 virtual std::map<String,VMDynVar*> builtInDynamicVariables() = 0;
756 };
757
758 /** @brief Execution state of a virtual machine.
759 *
760 * An instance of this abstract base class represents exactly one execution
761 * state of a virtual machine. This encompasses most notably the VM
762 * execution stack, and VM polyphonic variables. It does not contain global
763 * variables. Global variables are contained in the VMParserContext object.
764 * You might see a VMExecContext object as one virtual thread of the virtual
765 * machine.
766 *
767 * In contrast to a VMParserContext, a VMExecContext is not tied to a
768 * ScriptVM instance. Thus you can use a VMExecContext with different
769 * ScriptVM instances, however not concurrently at the same time.
770 *
771 * @see VMParserContext
772 */
773 class VMExecContext {
774 public:
775 virtual ~VMExecContext() {}
776
777 /**
778 * In case the script was suspended for some reason, this method returns
779 * the amount of microseconds before the script shall continue its
780 * execution. Note that the virtual machine itself does never put its
781 * own execution thread(s) to sleep. So the respective class (i.e. sampler
782 * engine) which is using the virtual machine classes here, must take
783 * care by itself about taking time stamps, determining the script
784 * handlers that shall be put aside for the requested amount of
785 * microseconds, indicated by this method by comparing the time stamps in
786 * real-time, and to continue passing the respective handler to
787 * ScriptVM::exec() as soon as its suspension exceeded, etc. Or in other
788 * words: all classes in this directory never have an idea what time it
789 * is.
790 *
791 * You should check the return value of ScriptVM::exec() to determine
792 * whether the script was actually suspended before calling this method
793 * here.
794 *
795 * @see ScriptVM::exec()
796 */
797 virtual int suspensionTimeMicroseconds() const = 0;
798 };
799
800 /** @brief Script callback for a certain event.
801 *
802 * Represents a script callback for a certain event, i.e.
803 * "on note ... end on" code block.
804 */
805 class VMEventHandler {
806 public:
807 /**
808 * Type of this event handler, which identifies its purpose. For example
809 * for a "on note ... end on" script callback block,
810 * @c VM_EVENT_HANDLER_NOTE would be returned here.
811 */
812 virtual VMEventHandlerType_t eventHandlerType() const = 0;
813
814 /**
815 * Name of the event handler which identifies its purpose. For example
816 * for a "on note ... end on" script callback block, the name "note"
817 * would be returned here.
818 */
819 virtual String eventHandlerName() const = 0;
820
821 /**
822 * Whether or not the event handler makes any use of so called
823 * "polyphonic" variables.
824 */
825 virtual bool isPolyphonic() const = 0;
826 };
827
828 /**
829 * Encapsulates a noteworty parser issue. This encompasses the type of the
830 * issue (either a parser error or parser warning), a human readable
831 * explanation text of the error or warning and the location of the
832 * encountered parser issue within the script.
833 */
834 struct ParserIssue {
835 String txt; ///< Human readable explanation text of the parser issue.
836 int firstLine; ///< The first line number within the script where this issue was encountered (indexed with 1 being the very first line).
837 int lastLine; ///< The last line number within the script where this issue was encountered.
838 int firstColumn; ///< The first column within the script where this issue was encountered (indexed with 1 being the very first column).
839 int lastColumn; ///< The last column within the script where this issue was encountered.
840 ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning.
841
842 /**
843 * Print this issue out to the console (stdio).
844 */
845 inline void dump() {
846 switch (type) {
847 case PARSER_ERROR:
848 printf("[ERROR] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
849 break;
850 case PARSER_WARNING:
851 printf("[Warning] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
852 break;
853 }
854 }
855
856 /**
857 * Returns true if this issue is a parser error. In this case the parsed
858 * script may not be executed!
859 */
860 inline bool isErr() const { return type == PARSER_ERROR; }
861
862 /**
863 * Returns true if this issue is just a parser warning. A parsed script
864 * that only raises warnings may be executed if desired, however the
865 * script may not behave exactly as intended by the script author.
866 */
867 inline bool isWrn() const { return type == PARSER_WARNING; }
868 };
869
870 /**
871 * Convenience function used for converting an ExprType_t constant to a
872 * string, i.e. for generating error message by the parser.
873 */
874 inline String typeStr(const ExprType_t& type) {
875 switch (type) {
876 case EMPTY_EXPR: return "empty";
877 case INT_EXPR: return "integer";
878 case INT_ARR_EXPR: return "integer array";
879 case STRING_EXPR: return "string";
880 case STRING_ARR_EXPR: return "string array";
881 }
882 return "invalid";
883 }
884
885 /** @brief Virtual machine representation of a script.
886 *
887 * An instance of this abstract base class represents a parsed script,
888 * translated into a virtual machine tree. You should first check if there
889 * were any parser errors. If there were any parser errors, you should
890 * refrain from executing the virtual machine. Otherwise if there were no
891 * parser errors (i.e. only warnings), then you might access one of the
892 * script's event handlers by i.e. calling eventHandlerByName() and pass the
893 * respective event handler to the ScriptVM class (or to one of the ScriptVM
894 * descendants) for execution.
895 *
896 * @see VMExecContext, ScriptVM
897 */
898 class VMParserContext {
899 public:
900 virtual ~VMParserContext() {}
901
902 /**
903 * Returns all noteworthy issues encountered when the script was parsed.
904 * These are parser errors and parser warnings.
905 */
906 virtual std::vector<ParserIssue> issues() const = 0;
907
908 /**
909 * Same as issues(), but this method only returns parser errors.
910 */
911 virtual std::vector<ParserIssue> errors() const = 0;
912
913 /**
914 * Same as issues(), but this method only returns parser warnings.
915 */
916 virtual std::vector<ParserIssue> warnings() const = 0;
917
918 /**
919 * Returns the translated virtual machine representation of an event
920 * handler block (i.e. "on note ... end on" code block) within the
921 * parsed script. This translated representation of the event handler
922 * can be executed by the virtual machine.
923 *
924 * @param index - index of the event handler within the script
925 */
926 virtual VMEventHandler* eventHandler(uint index) = 0;
927
928 /**
929 * Same as eventHandler(), but this method returns the event handler by
930 * its name. So for a "on note ... end on" code block of the parsed
931 * script you would pass "note" for argument @a name here.
932 *
933 * @param name - name of the event handler (i.e. "init", "note",
934 * "controller", "release")
935 */
936 virtual VMEventHandler* eventHandlerByName(const String& name) = 0;
937 };
938
939 class SourceToken;
940
941 /** @brief Recognized token of a script's source code.
942 *
943 * Represents one recognized token of a script's source code, for example
944 * a keyword, variable name, etc. and it provides further informations about
945 * that particular token, i.e. the precise location (line and column) of the
946 * token within the original script's source code.
947 *
948 * This class is not actually used by the sampler itself. It is rather
949 * provided for external script editor applications. Primary purpose of
950 * this class is syntax highlighting for external script editors.
951 */
952 class VMSourceToken {
953 public:
954 VMSourceToken();
955 VMSourceToken(SourceToken* ct);
956 VMSourceToken(const VMSourceToken& other);
957 virtual ~VMSourceToken();
958
959 // original text of this token as it is in the script's source code
960 String text() const;
961
962 // position of token in script
963 int firstLine() const; ///< First line this source token is located at in script source code (indexed with 0 being the very first line).
964 int firstColumn() const; ///< Last line this source token is located at in script source code.
965
966 // base types
967 bool isEOF() const;
968 bool isNewLine() const;
969 bool isKeyword() const;
970 bool isVariableName() const;
971 bool isIdentifier() const;
972 bool isNumberLiteral() const;
973 bool isStringLiteral() const;
974 bool isComment() const;
975 bool isPreprocessor() const;
976 bool isOther() const;
977
978 // extended types
979 bool isIntegerVariable() const;
980 bool isStringVariable() const;
981 bool isArrayVariable() const;
982 bool isEventHandlerName() const;
983
984 VMSourceToken& operator=(const VMSourceToken& other);
985
986 private:
987 SourceToken* m_token;
988 };
989
990 } // namespace LinuxSampler
991
992 #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

  ViewVC Help
Powered by ViewVC