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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2619 by schoenebeck, Wed Jun 11 13:24:32 2014 UTC revision 2948 by schoenebeck, Fri Jul 15 15:29:04 2016 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014-2016 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 20  Line 20 
20  #include <stddef.h> // offsetof()  #include <stddef.h> // offsetof()
21    
22  namespace LinuxSampler {  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 {      enum ParserIssueType_t {
29          PARSER_ERROR,          PARSER_ERROR, ///< Script parser encountered an error, the script cannot be executed.
30          PARSER_WARNING          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 {      enum ExprType_t {
41          EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value          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,          INT_EXPR, ///< integer (scalar) expression
43          INT_ARR_EXPR,          INT_ARR_EXPR, ///< integer array expression
44          STRING_EXPR,          STRING_EXPR, ///< string expression
45          STRING_ARR_EXPR,          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 {      enum StmtFlags_t {
59         STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred.         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).         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),         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),         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 {      enum VMExecStatus_t {
73          VM_EXEC_NOT_RUNNING = 0,          VM_EXEC_NOT_RUNNING = 0, ///< Script is currently not executed by the VM.
74          VM_EXEC_RUNNING = 1,          VM_EXEC_RUNNING = 1, ///< The VM is currently executing the script.
75          VM_EXEC_SUSPENDED = (1<<1),          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),          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;      class VMIntExpr;
93      class VMStringExpr;      class VMStringExpr;
94      class VMIntArrayExpr;      class VMIntArrayExpr;
95      class VMStringArrayExpr;      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 {      class VMExpr {
111      public:      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;          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;          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;          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;          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 {      class VMIntExpr : virtual public VMExpr {
185      public:      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;          virtual int evalInt() = 0;
191          ExprType_t exprType() const { return INT_EXPR; }  
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 {      class VMStringExpr : virtual public VMExpr {
206      public:      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;          virtual String evalStr() = 0;
212          ExprType_t exprType() const { return STRING_EXPR; }  
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 {      class VMArrayExpr : virtual public VMExpr {
227      public:      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;          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 {      class VMIntArrayExpr : virtual public VMArrayExpr {
243      public:      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;          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;          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 {      class VMFnArgs {
276      public:      public:
277            /**
278             * Returns the amount of arguments going to be passed to the script
279             * function.
280             */
281          virtual int argsCount() const = 0;          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;          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 {      class VMFnResult {
303      public:      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;          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; }          virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }
317      };      };
318    
319      /** @brief VM built-in function.      /** @brief Virtual machine built-in function.
320       *       *
321       * Abstract base class for built-in script functions, defining the interface       * Abstract base class for built-in script functions, defining the interface
322       * for all built-in script function implementations.       * 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 {      class VMFunction {
343      public:      public:
344          /**          /**
345           * Script data type of the function's return value. If the function does           * Script data type of the function's return value. If the function does
346           * not return any value, then it returns EMPTY_EXPR here.           * not return any value (void), then it returns EMPTY_EXPR here.
347           */           */
348          virtual ExprType_t returnType() = 0;          virtual ExprType_t returnType() = 0;
349    
# Line 127  namespace LinuxSampler { Line 365  namespace LinuxSampler {
365           * Script data type of the function's @c iArg 'th function argument.           * Script data type of the function's @c iArg 'th function argument.
366           * The information provided here is less strong than acceptsArgType().           * The information provided here is less strong than acceptsArgType().
367           * The parser will compare argument data types provided in scripts by           * The parser will compare argument data types provided in scripts by
368           * calling cceptsArgType(). The return value of argType() is used by the           * calling acceptsArgType(). The return value of argType() is used by the
369           * parser instead to show an appropriate parser error which data type           * parser instead to show an appropriate parser error which data type
370           * this function usually expects as "default" data type. Reason: a           * this function usually expects as "default" data type. Reason: a
371           * function may accept multiple data types for a certain function           * function may accept multiple data types for a certain function
# Line 135  namespace LinuxSampler { Line 373  namespace LinuxSampler {
373           * that case to the type it actually needs.           * that case to the type it actually needs.
374           *           *
375           * @param iArg - index of the function argument in question           * @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;          virtual ExprType_t argType(int iArg) const = 0;
379    
380          /**          /**
381           * This function is called by the parser to check whether arguments           * This method is called by the parser to check whether arguments
382           * passed in scripts to this function are accepted by this function. If           * 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           * a script calls this function with an argument's data type not
384           * accepted by this function, the parser will throw a parser error.           * 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           * @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           * @param type - script data type used for this function argument by
392           *               currently parsed script           *               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;          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;
397    
398          /**          /**
399           * Implements the actual function execution. This function is called by           * This method is called by the parser to check whether some arguments
400           * the VM when this function shall be executed at script runtime.           * (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           * @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;          virtual VMFnResult* exec(VMFnArgs* args) = 0;
425    
426          /**          /**
427           * Concenience method for function implementations to show warning           * Convenience method for function implementations to show warning
428           * messages.           * messages during actual execution of the built-in function.
429           *           *
430           * @param txt - warning text           * @param txt - runtime warning text to be shown to user
431           */           */
432          void wrnMsg(const String& txt);          void wrnMsg(const String& txt);
433    
434          /**          /**
435           * Concenience method for function implementations to show error           * Convenience method for function implementations to show error
436           * messages.           * messages during actual execution of the built-in function.
437           *           *
438           * @param txt - error text           * @param txt - runtime error text to be shown to user
439           */           */
440          void errMsg(const String& txt);          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       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be
446       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.
447         *
448         * @see VMIntRelPtr, VMInt8RelPtr
449       */       */
450      struct VMRelPtr {      struct VMRelPtr {
451          void** base; ///< Base pointer.          void** base; ///< Base pointer.
452          int offset;  ///< Offset (in bytes) to base pointer.          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).      /** @brief Pointer to built-in VM integer variable (of C/C++ type int).
457       *       *
458       * Used for defining built-in integer script variables.       * 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       * @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       * of type "int" (which on most systems is 32 bit in size). If the C/C++ int
# Line 209  namespace LinuxSampler { Line 478  namespace LinuxSampler {
478          VMIntRelPtr() {          VMIntRelPtr() {
479              base   = NULL;              base   = NULL;
480              offset = 0;              offset = 0;
481                readonly = false;
482          }          }
483          VMIntRelPtr(const VMRelPtr& data) {          VMIntRelPtr(const VMRelPtr& data) {
484              base   = data.base;              base   = data.base;
485              offset = data.offset;              offset = data.offset;
486                readonly = false;
487          }          }
488          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }
489          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }
# Line 220  namespace LinuxSampler { Line 491  namespace LinuxSampler {
491    
492      /** @brief Pointer to built-in VM integer variable (of C/C++ type int8_t).      /** @brief Pointer to built-in VM integer variable (of C/C++ type int8_t).
493       *       *
494       * Used for defining built-in integer script variables.       * 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       * @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       * of type "int8_t" (8 bit integer). If the C/C++ int variable you want to
# Line 252  namespace LinuxSampler { Line 523  namespace LinuxSampler {
523    
524      /**      /**
525       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr
526       * structures. Example:       * structures. Usage example:
527       * @code       * @code
528       * struct Foo {       * struct Foo {
529       *   uint8_t a;       *   uint8_t a; // native representation of a built-in integer script variable
530       *   int b;       *   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       * Foo foo1 = (Foo) { 1, 3000 };       * // initializing the built-in script variables to some values
536       * Foo foo2 = (Foo) { 2, 4000 };       * Foo foo1 = (Foo) { 1, 2000, 3000, 4 };
537         * Foo foo2 = (Foo) { 5, 6000, 7000, 8 };
538       *       *
539       * Foo* pFoo;       * Foo* pFoo;
540       *       *
541       * VMInt8RelPtr var1 = DECLARE_VMINT(pFoo, class Foo, a);       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
542       * VMIntRelPtr  var2 = DECLARE_VMINT(pFoo, class Foo, b);       * 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;       * pFoo = &foo1;
547       * printf("%d\n", var1->evalInt()); // will print 1       * printf("%d\n", varA->evalInt()); // will print 1
548       * printf("%d\n", var2->evalInt()); // will print 3000       * 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;       * pFoo = &foo2;
555       * printf("%d\n", var1->evalInt()); // will print 2       * printf("%d\n", varA->evalInt()); // will print 5
556       * printf("%d\n", var2->evalInt()); // will print 4000       * 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       * @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) ( \      #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \
567          (VMRelPtr) {                                     \          (VMRelPtr) {                                     \
568              (void**) &basePtr,                           \              (void**) &basePtr,                           \
569              offsetof(T_struct, T_member)                 \              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.      /** @brief Built-in VM 8 bit integer array variable.
596       *       *
597       * Used for defining built-in integer array script variables.       * 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 {      struct VMInt8Array {
602          int8_t* data;          int8_t* data;
# Line 294  namespace LinuxSampler { Line 605  namespace LinuxSampler {
605          VMInt8Array() : data(NULL), size(0) {}          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.      /** @brief Provider for built-in script functions and variables.
716       *       *
717       * Abstract base class defining the interface for all classes which add and       * Abstract base class defining the high-level interface for all classes
718       * implement built-in script functions and built-in script variables.       * which add and implement built-in script functions and built-in script
719         * variables.
720       */       */
721      class VMFunctionProvider {      class VMFunctionProvider {
722      public:      public:
723          /**          /**
724           * Returns pointer to the built-in function with the given function           * Returns pointer to the built-in function with the given function
725           * name, or NULL if there is no built-in function with that name.           * @a name, or NULL if there is no built-in function with that function
726             * name.
727           *           *
728           * @param name - function name           * @param name - function name (i.e. "wait" or "message" or "exit", etc.)
729           */           */
730          virtual VMFunction* functionByName(const String& name) = 0;          virtual VMFunction* functionByName(const String& name) = 0;
731    
732          /**          /**
733           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script variables
734           * which point to native "int" (usually 32 bit) variables.           * which point to native "int" scalar (usually 32 bit) variables.
735           */           */
736          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;
737    
738          /**          /**
739           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script integer
740           * which point to native "int8_t" (8 bit) variables.           * array variables with array element type "int8_t" (8 bit).
741           */           */
742          virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;          virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
743    
# Line 326  namespace LinuxSampler { Line 746  namespace LinuxSampler {
746           * variables, which never change their value at runtime.           * variables, which never change their value at runtime.
747           */           */
748          virtual std::map<String,int> builtInConstIntVariables() = 0;          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.      /** @brief Execution state of a virtual machine.
# Line 333  namespace LinuxSampler { Line 760  namespace LinuxSampler {
760       * An instance of this abstract base class represents exactly one execution       * An instance of this abstract base class represents exactly one execution
761       * state of a virtual machine. This encompasses most notably the VM       * state of a virtual machine. This encompasses most notably the VM
762       * execution stack, and VM polyphonic variables. It does not contain global       * execution stack, and VM polyphonic variables. It does not contain global
763       * variable. Global variables are contained in the VMParserContext object.       * variables. Global variables are contained in the VMParserContext object.
764       * You might see a VMExecContext object as one virtual thread of the virtual       * You might see a VMExecContext object as one virtual thread of the virtual
765       * machine.       * machine.
766       *       *
# Line 346  namespace LinuxSampler { Line 773  namespace LinuxSampler {
773      class VMExecContext {      class VMExecContext {
774      public:      public:
775          virtual ~VMExecContext() {}          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;          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 {      class VMEventHandler {
806      public:      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;          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 {      struct ParserIssue {
835          String txt;          String txt; ///< Human readable explanation text of the parser issue.
836          int line;          int firstLine; ///< The first line number within the script where this issue was encountered (indexed with 1 being the very first line).
837          ParserIssueType_t type;          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() {          inline void dump() {
846              switch (type) {              switch (type) {
847                  case PARSER_ERROR:                  case PARSER_ERROR:
848                      printf("[ERROR] line %d: %s\n", line, txt.c_str());                      printf("[ERROR] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
849                      break;                      break;
850                  case PARSER_WARNING:                  case PARSER_WARNING:
851                      printf("[Warning] line %d: %s\n", line, txt.c_str());                      printf("[Warning] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
852                      break;                      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;   }          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; }          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) {      inline String typeStr(const ExprType_t& type) {
875          switch (type) {          switch (type) {
876              case EMPTY_EXPR: return "empty";              case EMPTY_EXPR: return "empty";
# Line 388  namespace LinuxSampler { Line 885  namespace LinuxSampler {
885      /** @brief Virtual machine representation of a script.      /** @brief Virtual machine representation of a script.
886       *       *
887       * An instance of this abstract base class represents a parsed script,       * An instance of this abstract base class represents a parsed script,
888       * translated into a virtual machine. You should first check if there were       * translated into a virtual machine tree. You should first check if there
889       * any parser errors. If there were any parser errors, you should refrain       * were any parser errors. If there were any parser errors, you should
890       * from executing the virtual machine. Otherwise if there were no parser       * refrain from executing the virtual machine. Otherwise if there were no
891       * errors (i.e. only warnings), then you might access one of the script's       * parser errors (i.e. only warnings), then you might access one of the
892       * event handlers by i.e. calling eventHandlerByName() and pass the       * script's event handlers by i.e. calling eventHandlerByName() and pass the
893       * respective event handler to the ScriptVM class (or to one of its       * respective event handler to the ScriptVM class (or to one of the ScriptVM
894       * descendants) for execution.       * descendants) for execution.
895       *       *
896       * @see VMExecContext       * @see VMExecContext, ScriptVM
897       */       */
898      class VMParserContext {      class VMParserContext {
899      public:      public:
900          virtual ~VMParserContext() {}          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;          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;          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;          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;          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;          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  } // namespace LinuxSampler
991    
992  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

Legend:
Removed from v.2619  
changed lines
  Added in v.2948

  ViewVC Help
Powered by ViewVC