/[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 2645 by schoenebeck, Wed Jun 18 00:14:57 2014 UTC revision 2960 by schoenebeck, Sun Jul 17 12:10:06 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             * @b NOTE: A constant expression is per se always also non modifyable.
173             * But a non modifyable expression may not necessarily be a constant
174             * expression!
175             *
176             * @see isModifyable()
177             */
178            virtual bool isConstExpr() const = 0;
179    
180            /**
181             * Returns true in case this expression is allowed to be modified.
182             * If this method returns @c false then this expression must be handled
183             * as read-only expression, which means that assigning a new value to it
184             * is either not possible or not allowed.
185             *
186             * @b NOTE: A constant expression is per se always also non modifyable.
187             * But a non modifyable expression may not necessarily be a constant
188             * expression!
189             *
190             * @see isConstExpr()
191             */
192            bool isModifyable() const;
193      };      };
194    
195        /** @brief Virtual machine integer expression
196         *
197         * This is the abstract base class for all expressions inside scripts which
198         * evaluate to an integer (scalar) value. Deriving classes implement the
199         * abstract method evalInt() to return the actual integer result value of
200         * the expression.
201         */
202      class VMIntExpr : virtual public VMExpr {      class VMIntExpr : virtual public VMExpr {
203      public:      public:
204            /**
205             * Returns the result of this expression as integer (scalar) value.
206             * This abstract method must be implemented by deriving classes.
207             */
208          virtual int evalInt() = 0;          virtual int evalInt() = 0;
209          ExprType_t exprType() const { return INT_EXPR; }  
210            /**
211             * Returns always INT_EXPR for instances of this class.
212             */
213            ExprType_t exprType() const OVERRIDE { return INT_EXPR; }
214      };      };
215    
216        /** @brief Virtual machine string expression
217         *
218         * This is the abstract base class for all expressions inside scripts which
219         * evaluate to a string value. Deriving classes implement the abstract
220         * method evalStr() to return the actual string result value of the
221         * expression.
222         */
223      class VMStringExpr : virtual public VMExpr {      class VMStringExpr : virtual public VMExpr {
224      public:      public:
225            /**
226             * Returns the result of this expression as string value. This abstract
227             * method must be implemented by deriving classes.
228             */
229          virtual String evalStr() = 0;          virtual String evalStr() = 0;
230          ExprType_t exprType() const { return STRING_EXPR; }  
231            /**
232             * Returns always STRING_EXPR for instances of this class.
233             */
234            ExprType_t exprType() const OVERRIDE { return STRING_EXPR; }
235      };      };
236    
237        /** @brief Virtual Machine Array Value Expression
238         *
239         * This is the abstract base class for all expressions inside scripts which
240         * evaluate to some kind of array value. Deriving classes implement the
241         * abstract method arraySize() to return the amount of elements within the
242         * array.
243         */
244      class VMArrayExpr : virtual public VMExpr {      class VMArrayExpr : virtual public VMExpr {
245      public:      public:
246            /**
247             * Returns amount of elements in this array. This abstract method must
248             * be implemented by deriving classes.
249             */
250          virtual int arraySize() const = 0;          virtual int arraySize() const = 0;
251      };      };
252    
253        /** @brief Virtual Machine Integer Array Expression
254         *
255         * This is the abstract base class for all expressions inside scripts which
256         * evaluate to an array of integer values. Deriving classes implement the
257         * abstract methods arraySize(), evalIntElement() and assignIntElement() to
258         * access the individual integer array values.
259         */
260      class VMIntArrayExpr : virtual public VMArrayExpr {      class VMIntArrayExpr : virtual public VMArrayExpr {
261      public:      public:
262            /**
263             * Returns the (scalar) integer value of the array element given by
264             * element index @a i.
265             *
266             * @param i - array element index (must be between 0 .. arraySize() - 1)
267             */
268          virtual int evalIntElement(uint i) = 0;          virtual int evalIntElement(uint i) = 0;
269    
270            /**
271             * Changes the current value of an element (given by array element
272             * index @a i) of this integer array.
273             *
274             * @param i - array element index (must be between 0 .. arraySize() - 1)
275             * @param value - new integer scalar value to be assigned to that array element
276             */
277          virtual void assignIntElement(uint i, int value) = 0;          virtual void assignIntElement(uint i, int value) = 0;
278          ExprType_t exprType() const { return INT_ARR_EXPR; }  
279            /**
280             * Returns always INT_ARR_EXPR for instances of this class.
281             */
282            ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; }
283      };      };
284    
285        /** @brief Arguments (parameters) for being passed to a built-in script function.
286         *
287         * An argument or a set of arguments passed to a script function are
288         * translated by the parser to an instance of this class. This abstract
289         * interface class is used by implementations of built-in functions to
290         * obtain the individual function argument values being passed to them at
291         * runtime.
292         */
293      class VMFnArgs {      class VMFnArgs {
294      public:      public:
295            /**
296             * Returns the amount of arguments going to be passed to the script
297             * function.
298             */
299          virtual int argsCount() const = 0;          virtual int argsCount() const = 0;
300    
301            /**
302             * Returns the respective argument (requested by argument index @a i) of
303             * this set of arguments. This method is called by implementations of
304             * built-in script functions to obtain the value of each function
305             * argument passed to the function at runtime.
306             *
307             * @param i - function argument index (indexed from left to right)
308             */
309          virtual VMExpr* arg(int i) = 0;          virtual VMExpr* arg(int i) = 0;
310      };      };
311    
312        /** @brief Result value returned from a call to a built-in script function.
313         *
314         * Implementations of built-in script functions return an instance of this
315         * object to let the virtual machine obtain the result value of the function
316         * call, which might then be further processed by the virtual machine
317         * according to the script. It also provides informations about the success
318         * or failure of the function call.
319         */
320      class VMFnResult {      class VMFnResult {
321      public:      public:
322            /**
323             * Returns the result value of the function call, represented by a high
324             * level expression object.
325             */
326          virtual VMExpr* resultValue() = 0;          virtual VMExpr* resultValue() = 0;
327    
328            /**
329             * Provides detailed informations of the success / failure of the
330             * function call. The virtual machine is evaluating the flags returned
331             * here to decide whether it must abort or suspend execution of the
332             * script at this point.
333             */
334          virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }          virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }
335      };      };
336    
337      /** @brief VM built-in function.      /** @brief Virtual machine built-in function.
338       *       *
339       * Abstract base class for built-in script functions, defining the interface       * Abstract base class for built-in script functions, defining the interface
340       * for all built-in script function implementations.       * for all built-in script function implementations. All built-in script
341         * functions are deriving from this abstract interface class in order to
342         * provide their functionality to the virtual machine with this unified
343         * interface.
344         *
345         * The methods of this interface class provide two purposes:
346         *
347         * 1. When a script is loaded, the script parser uses the methods of this
348         *    interface to check whether the script author was calling the
349         *    respective built-in script function in a correct way. For example
350         *    the parser checks whether the required amount of parameters were
351         *    passed to the function and whether the data types passed match the
352         *    data types expected by the function. If not, loading the script will
353         *    be aborted with a parser error, describing to the user (i.e. script
354         *    author) the precise misusage of the respective function.
355         * 2. After the script was loaded successfully and the script is executed,
356         *    the virtual machine calls the exec() method of the respective built-in
357         *    function to provide the actual functionality of the built-in function
358         *    call.
359       */       */
360      class VMFunction {      class VMFunction {
361      public:      public:
362          /**          /**
363           * 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
364           * not return any value, then it returns EMPTY_EXPR here.           * not return any value (void), then it returns EMPTY_EXPR here.
365           */           */
366          virtual ExprType_t returnType() = 0;          virtual ExprType_t returnType() = 0;
367    
# Line 128  namespace LinuxSampler { Line 383  namespace LinuxSampler {
383           * Script data type of the function's @c iArg 'th function argument.           * Script data type of the function's @c iArg 'th function argument.
384           * The information provided here is less strong than acceptsArgType().           * The information provided here is less strong than acceptsArgType().
385           * The parser will compare argument data types provided in scripts by           * The parser will compare argument data types provided in scripts by
386           * calling cceptsArgType(). The return value of argType() is used by the           * calling acceptsArgType(). The return value of argType() is used by the
387           * parser instead to show an appropriate parser error which data type           * parser instead to show an appropriate parser error which data type
388           * this function usually expects as "default" data type. Reason: a           * this function usually expects as "default" data type. Reason: a
389           * function may accept multiple data types for a certain function           * function may accept multiple data types for a certain function
# Line 136  namespace LinuxSampler { Line 391  namespace LinuxSampler {
391           * that case to the type it actually needs.           * that case to the type it actually needs.
392           *           *
393           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
394             *               (must be between 0 .. maxAllowedArgs() - 1)
395           */           */
396          virtual ExprType_t argType(int iArg) const = 0;          virtual ExprType_t argType(int iArg) const = 0;
397    
398          /**          /**
399           * This function is called by the parser to check whether arguments           * This method is called by the parser to check whether arguments
400           * passed in scripts to this function are accepted by this function. If           * passed in scripts to this function are accepted by this function. If
401           * a script calls this function with an argument's data type not           * a script calls this function with an argument's data type not
402           * accepted by this function, the parser will throw a parser error.           * accepted by this function, the parser will throw a parser error. On
403             * such errors the data type returned by argType() will be used to
404             * assemble an appropriate error message regarding the precise misusage
405             * of the built-in function.
406           *           *
407           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
408             *               (must be between 0 .. maxAllowedArgs() - 1)
409           * @param type - script data type used for this function argument by           * @param type - script data type used for this function argument by
410           *               currently parsed script           *               currently parsed script
411             * @return true if the given data type would be accepted for the
412             *         respective function argument by the function
413           */           */
414          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;
415    
416          /**          /**
417           * Implements the actual function execution. This function is called by           * This method is called by the parser to check whether some arguments
418           * the VM when this function shall be executed at script runtime.           * (and if yes which ones) passed to this script function will be
419             * modified by this script function. Most script functions simply use
420             * their arguments as inputs, that is they only read the argument's
421             * values. However some script function may also use passed
422             * argument(s) as output variables. In this case the function
423             * implementation must return @c true for the respective argument
424             * index here.
425             *
426             * @param iArg - index of the function argument in question
427             *               (must be between 0 .. maxAllowedArgs() - 1)
428             */
429            virtual bool modifiesArg(int iArg) const = 0;
430    
431            /**
432             * Implements the actual function execution. This exec() method is
433             * called by the VM whenever this function implementation shall be
434             * executed at script runtime. This method blocks until the function
435             * call completed.
436           *           *
437           * @param args - function arguments for executing this built-in function           * @param args - function arguments for executing this built-in function
438             * @returns function's return value (if any) and general status
439             *          informations (i.e. whether the function call caused a
440             *          runtime error)
441           */           */
442          virtual VMFnResult* exec(VMFnArgs* args) = 0;          virtual VMFnResult* exec(VMFnArgs* args) = 0;
443    
444          /**          /**
445           * Concenience method for function implementations to show warning           * Convenience method for function implementations to show warning
446           * messages.           * messages during actual execution of the built-in function.
447           *           *
448           * @param txt - warning text           * @param txt - runtime warning text to be shown to user
449           */           */
450          void wrnMsg(const String& txt);          void wrnMsg(const String& txt);
451    
452          /**          /**
453           * Concenience method for function implementations to show error           * Convenience method for function implementations to show error
454           * messages.           * messages during actual execution of the built-in function.
455           *           *
456           * @param txt - error text           * @param txt - runtime error text to be shown to user
457           */           */
458          void errMsg(const String& txt);          void errMsg(const String& txt);
459      };      };
460    
461      /**      /** @brief Virtual machine relative pointer.
462         *
463       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be
464       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.
465         *
466         * @see VMIntRelPtr, VMInt8RelPtr
467       */       */
468      struct VMRelPtr {      struct VMRelPtr {
469          void** base; ///< Base pointer.          void** base; ///< Base pointer.
470          int offset;  ///< Offset (in bytes) to base pointer.          int offset;  ///< Offset (in bytes) relative to base pointer.
471            bool readonly; ///< Whether the pointed data may be modified or just be read.
472      };      };
473    
474      /** @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).
475       *       *
476       * Used for defining built-in integer script variables.       * Used for defining built-in 32 bit integer script variables.
477       *       *
478       * @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
479       * 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 210  namespace LinuxSampler { Line 496  namespace LinuxSampler {
496          VMIntRelPtr() {          VMIntRelPtr() {
497              base   = NULL;              base   = NULL;
498              offset = 0;              offset = 0;
499                readonly = false;
500          }          }
501          VMIntRelPtr(const VMRelPtr& data) {          VMIntRelPtr(const VMRelPtr& data) {
502              base   = data.base;              base   = data.base;
503              offset = data.offset;              offset = data.offset;
504                readonly = false;
505          }          }
506          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }
507          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }
# Line 221  namespace LinuxSampler { Line 509  namespace LinuxSampler {
509    
510      /** @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).
511       *       *
512       * Used for defining built-in integer script variables.       * Used for defining built-in 8 bit integer script variables.
513       *       *
514       * @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
515       * 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 253  namespace LinuxSampler { Line 541  namespace LinuxSampler {
541    
542      /**      /**
543       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr
544       * structures. Example:       * structures. Usage example:
545       * @code       * @code
546       * struct Foo {       * struct Foo {
547       *   uint8_t a;       *   uint8_t a; // native representation of a built-in integer script variable
548       *   int b;       *   int b; // native representation of another built-in integer script variable
549         *   int c; // native representation of another built-in integer script variable
550         *   uint8_t d; // native representation of another built-in integer script variable
551       * };       * };
552       *       *
553       * Foo foo1 = (Foo) { 1, 3000 };       * // initializing the built-in script variables to some values
554       * Foo foo2 = (Foo) { 2, 4000 };       * Foo foo1 = (Foo) { 1, 2000, 3000, 4 };
555         * Foo foo2 = (Foo) { 5, 6000, 7000, 8 };
556       *       *
557       * Foo* pFoo;       * Foo* pFoo;
558       *       *
559       * VMInt8RelPtr var1 = DECLARE_VMINT(pFoo, class Foo, a);       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
560       * VMIntRelPtr  var2 = DECLARE_VMINT(pFoo, class Foo, b);       * VMIntRelPtr  varB = DECLARE_VMINT(pFoo, class Foo, b);
561         * VMIntRelPtr  varC = DECLARE_VMINT(pFoo, class Foo, c);
562         * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
563       *       *
564       * pFoo = &foo1;       * pFoo = &foo1;
565       * printf("%d\n", var1->evalInt()); // will print 1       * printf("%d\n", varA->evalInt()); // will print 1
566       * printf("%d\n", var2->evalInt()); // will print 3000       * printf("%d\n", varB->evalInt()); // will print 2000
567         * printf("%d\n", varC->evalInt()); // will print 3000
568         * printf("%d\n", varD->evalInt()); // will print 4
569         *
570         * // same printf() code, just with pFoo pointer being changed ...
571       *       *
572       * pFoo = &foo2;       * pFoo = &foo2;
573       * printf("%d\n", var1->evalInt()); // will print 2       * printf("%d\n", varA->evalInt()); // will print 5
574       * printf("%d\n", var2->evalInt()); // will print 4000       * printf("%d\n", varB->evalInt()); // will print 6000
575         * printf("%d\n", varC->evalInt()); // will print 7000
576         * printf("%d\n", varD->evalInt()); // will print 8
577       * @endcode       * @endcode
578         * As you can see above, by simply changing one single pointer, you can
579         * remap a huge bunch of built-in integer script variables to completely
580         * different native values/native variables. Which especially reduces code
581         * complexity inside the sampler engines which provide the actual script
582         * functionalities.
583       */       */
584      #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \      #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \
585          (VMRelPtr) {                                     \          (VMRelPtr) {                                     \
586              (void**) &basePtr,                           \              (void**) &basePtr,                           \
587              offsetof(T_struct, T_member)                 \              offsetof(T_struct, T_member),                \
588                false                                        \
589          }                                                \          }                                                \
590      )                                                    \      )                                                    \
591    
592        /**
593         * Same as DECLARE_VMINT(), but this one defines the VMIntRelPtr and
594         * VMInt8RelPtr structures to be of read-only type. That means the script
595         * parser will abort any script at parser time if the script is trying to
596         * modify such a read-only built-in variable.
597         *
598         * @b NOTE: this is only intended for built-in read-only variables that
599         * may change during runtime! If your built-in variable's data is rather
600         * already available at parser time and won't change during runtime, then
601         * you should rather register a built-in constant in your VM class instead!
602         *
603         * @see ScriptVM::builtInConstIntVariables()
604         */
605        #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
606            (VMRelPtr) {                                          \
607                (void**) &basePtr,                                \
608                offsetof(T_struct, T_member),                     \
609                true                                              \
610            }                                                     \
611        )                                                         \
612    
613      /** @brief Built-in VM 8 bit integer array variable.      /** @brief Built-in VM 8 bit integer array variable.
614       *       *
615       * Used for defining built-in integer array script variables.       * Used for defining built-in integer array script variables (8 bit per
616         * array element). Currently there is no support for any other kind of array
617         * type. So all integer arrays of scripts use 8 bit data types.
618       */       */
619      struct VMInt8Array {      struct VMInt8Array {
620          int8_t* data;          int8_t* data;
# Line 295  namespace LinuxSampler { Line 623  namespace LinuxSampler {
623          VMInt8Array() : data(NULL), size(0) {}          VMInt8Array() : data(NULL), size(0) {}
624      };      };
625    
626        /** @brief Virtual machine script variable.
627         *
628         * Common interface for all variables accessed in scripts.
629         */
630        class VMVariable : virtual public VMExpr {
631        public:
632            /**
633             * Whether a script may modify the content of this variable by
634             * assigning a new value to it.
635             *
636             * @see isConstExpr(), assign()
637             */
638            virtual bool isAssignable() const = 0;
639    
640            /**
641             * In case this variable is assignable, this method will be called to
642             * perform the value assignment to this variable with @a expr
643             * reflecting the new value to be assigned.
644             *
645             * @param expr - new value to be assigned to this variable
646             */
647            virtual void assignExpr(VMExpr* expr) = 0;
648        };
649        
650        /** @brief Dynamically executed variable (abstract base class).
651         *
652         * Interface for the implementation of a dynamically generated content of
653         * a built-in script variable. Most built-in variables are simply pointers
654         * to some native location in memory. So when a script reads them, the
655         * memory location is simply read to get the value of the variable. A
656         * dynamic variable however is not simply a memory location. For each access
657         * to a dynamic variable some native code is executed to actually generate
658         * and provide the content (value) of this type of variable.
659         */
660        class VMDynVar : public VMVariable {
661        public:
662            /**
663             * Returns true in case this dynamic variable can be considered to be a
664             * constant expression. A constant expression will retain the same value
665             * throughout the entire life time of a script and the expression's
666             * constant value may be evaluated already at script parse time, which
667             * may result in performance benefits during script runtime.
668             *
669             * However due to the "dynamic" behavior of dynamic variables, almost
670             * all dynamic variables are probably not constant expressions. That's
671             * why this method returns @c false by default. If you are really sure
672             * that your dynamic variable implementation can be considered a
673             * constant expression then you may override this method and return
674             * @c true instead. Note that when you return @c true here, your
675             * dynamic variable will really just be executed once; and exectly
676             * already when the script is loaded!
677             *
678             * As an example you may implement a "constant" built-in dynamic
679             * variable that checks for a certain operating system feature and
680             * returns the result of that OS feature check as content (value) of
681             * this dynamic variable. Since the respective OS feature might become
682             * available/unavailable after OS updates, software migration, etc. the
683             * OS feature check should at least be performed once each time the
684             * application is launched. And since the OS feature check might take a
685             * certain amount of execution time, it might make sense to only
686             * perform the check if the respective variable name is actually
687             * referenced at all in the script to be loaded. Note that the dynamic
688             * variable will still be evaluated again though if the script is
689             * loaded again. So it is up to you to probably cache the result in the
690             * implementation of your dynamic variable.
691             *
692             * On doubt, please rather consider to use a constant built-in script
693             * variable instead of implementing a "constant" dynamic variable, due
694             * to the runtime overhead a dynamic variable may cause.
695             *
696             * @see isAssignable()
697             */
698            bool isConstExpr() const OVERRIDE { return false; }
699    
700            /**
701             * In case this dynamic variable is assignable, the new value (content)
702             * to be assigned to this dynamic variable.
703             *
704             * By default this method does nothing. Override and implement this
705             * method in your subclass in case your dynamic variable allows to
706             * assign a new value by script.
707             *
708             * @param expr - new value to be assigned to this variable
709             */
710            void assignExpr(VMExpr* expr) OVERRIDE {}
711        };
712    
713        /** @brief Dynamically executed variable (of integer data type).
714         *
715         * This is the base class for all built-in integer script variables whose
716         * variable content needs to be provided dynamically by executable native
717         * code on each script variable access.
718         */
719        class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
720        public:
721        };
722    
723        /** @brief Dynamically executed variable (of string data type).
724         *
725         * This is the base class for all built-in string script variables whose
726         * variable content needs to be provided dynamically by executable native
727         * code on each script variable access.
728         */
729        class VMDynStringVar : virtual public VMDynVar, virtual public VMStringExpr {
730        public:
731        };
732    
733      /** @brief Provider for built-in script functions and variables.      /** @brief Provider for built-in script functions and variables.
734       *       *
735       * Abstract base class defining the interface for all classes which add and       * Abstract base class defining the high-level interface for all classes
736       * implement built-in script functions and built-in script variables.       * which add and implement built-in script functions and built-in script
737         * variables.
738       */       */
739      class VMFunctionProvider {      class VMFunctionProvider {
740      public:      public:
741          /**          /**
742           * Returns pointer to the built-in function with the given function           * Returns pointer to the built-in function with the given function
743           * 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
744             * name.
745           *           *
746           * @param name - function name           * @param name - function name (i.e. "wait" or "message" or "exit", etc.)
747           */           */
748          virtual VMFunction* functionByName(const String& name) = 0;          virtual VMFunction* functionByName(const String& name) = 0;
749    
750          /**          /**
751           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script variables
752           * which point to native "int" (usually 32 bit) variables.           * which point to native "int" scalar (usually 32 bit) variables.
753           */           */
754          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;
755    
756          /**          /**
757           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script integer
758           * which point to native "int8_t" (8 bit) variables.           * array variables with array element type "int8_t" (8 bit).
759           */           */
760          virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;          virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
761    
# Line 327  namespace LinuxSampler { Line 764  namespace LinuxSampler {
764           * variables, which never change their value at runtime.           * variables, which never change their value at runtime.
765           */           */
766          virtual std::map<String,int> builtInConstIntVariables() = 0;          virtual std::map<String,int> builtInConstIntVariables() = 0;
767    
768            /**
769             * Returns a variable name indexed map of all built-in dynamic variables,
770             * which are not simply data stores, rather each one of them executes
771             * natively to provide or alter the respective script variable data.
772             */
773            virtual std::map<String,VMDynVar*> builtInDynamicVariables() = 0;
774      };      };
775    
776      /** @brief Execution state of a virtual machine.      /** @brief Execution state of a virtual machine.
# Line 334  namespace LinuxSampler { Line 778  namespace LinuxSampler {
778       * An instance of this abstract base class represents exactly one execution       * An instance of this abstract base class represents exactly one execution
779       * state of a virtual machine. This encompasses most notably the VM       * state of a virtual machine. This encompasses most notably the VM
780       * execution stack, and VM polyphonic variables. It does not contain global       * execution stack, and VM polyphonic variables. It does not contain global
781       * variable. Global variables are contained in the VMParserContext object.       * variables. Global variables are contained in the VMParserContext object.
782       * 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
783       * machine.       * machine.
784       *       *
# Line 347  namespace LinuxSampler { Line 791  namespace LinuxSampler {
791      class VMExecContext {      class VMExecContext {
792      public:      public:
793          virtual ~VMExecContext() {}          virtual ~VMExecContext() {}
794    
795            /**
796             * In case the script was suspended for some reason, this method returns
797             * the amount of microseconds before the script shall continue its
798             * execution. Note that the virtual machine itself does never put its
799             * own execution thread(s) to sleep. So the respective class (i.e. sampler
800             * engine) which is using the virtual machine classes here, must take
801             * care by itself about taking time stamps, determining the script
802             * handlers that shall be put aside for the requested amount of
803             * microseconds, indicated by this method by comparing the time stamps in
804             * real-time, and to continue passing the respective handler to
805             * ScriptVM::exec() as soon as its suspension exceeded, etc. Or in other
806             * words: all classes in this directory never have an idea what time it
807             * is.
808             *
809             * You should check the return value of ScriptVM::exec() to determine
810             * whether the script was actually suspended before calling this method
811             * here.
812             *
813             * @see ScriptVM::exec()
814             */
815          virtual int suspensionTimeMicroseconds() const = 0;          virtual int suspensionTimeMicroseconds() const = 0;
816      };      };
817    
818      /** @brief Script callback for a certain event.      /** @brief Script callback for a certain event.
819       *       *
820       * Represents a script callback for a certain event, i.e.       * Represents a script callback for a certain event, i.e.
821       * "on note ... end on".       * "on note ... end on" code block.
822       */       */
823      class VMEventHandler {      class VMEventHandler {
824      public:      public:
825          /**          /**
826             * Type of this event handler, which identifies its purpose. For example
827             * for a "on note ... end on" script callback block,
828             * @c VM_EVENT_HANDLER_NOTE would be returned here.
829             */
830            virtual VMEventHandlerType_t eventHandlerType() const = 0;
831    
832            /**
833           * Name of the event handler which identifies its purpose. For example           * Name of the event handler which identifies its purpose. For example
834           * for a "on note ... end on" script callback block, the name "note"           * for a "on note ... end on" script callback block, the name "note"
835           * would be returned here.           * would be returned here.
# Line 371  namespace LinuxSampler { Line 843  namespace LinuxSampler {
843          virtual bool isPolyphonic() const = 0;          virtual bool isPolyphonic() const = 0;
844      };      };
845    
846        /**
847         * Encapsulates a noteworty parser issue. This encompasses the type of the
848         * issue (either a parser error or parser warning), a human readable
849         * explanation text of the error or warning and the location of the
850         * encountered parser issue within the script.
851         */
852      struct ParserIssue {      struct ParserIssue {
853          String txt;          String txt; ///< Human readable explanation text of the parser issue.
854          int line;          int firstLine; ///< The first line number within the script where this issue was encountered (indexed with 1 being the very first line).
855          ParserIssueType_t type;          int lastLine; ///< The last line number within the script where this issue was encountered.
856            int firstColumn; ///< The first column within the script where this issue was encountered (indexed with 1 being the very first column).
857            int lastColumn; ///< The last column within the script where this issue was encountered.
858            ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning.
859    
860            /**
861             * Print this issue out to the console (stdio).
862             */
863          inline void dump() {          inline void dump() {
864              switch (type) {              switch (type) {
865                  case PARSER_ERROR:                  case PARSER_ERROR:
866                      printf("[ERROR] line %d: %s\n", line, txt.c_str());                      printf("[ERROR] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
867                      break;                      break;
868                  case PARSER_WARNING:                  case PARSER_WARNING:
869                      printf("[Warning] line %d: %s\n", line, txt.c_str());                      printf("[Warning] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
870                      break;                      break;
871              }              }
872          }          }
873            
874            /**
875             * Returns true if this issue is a parser error. In this case the parsed
876             * script may not be executed!
877             */
878          inline bool isErr() const { return type == PARSER_ERROR;   }          inline bool isErr() const { return type == PARSER_ERROR;   }
879    
880            /**
881             * Returns true if this issue is just a parser warning. A parsed script
882             * that only raises warnings may be executed if desired, however the
883             * script may not behave exactly as intended by the script author.
884             */
885          inline bool isWrn() const { return type == PARSER_WARNING; }          inline bool isWrn() const { return type == PARSER_WARNING; }
886      };      };
887    
888        /**
889         * Convenience function used for converting an ExprType_t constant to a
890         * string, i.e. for generating error message by the parser.
891         */
892      inline String typeStr(const ExprType_t& type) {      inline String typeStr(const ExprType_t& type) {
893          switch (type) {          switch (type) {
894              case EMPTY_EXPR: return "empty";              case EMPTY_EXPR: return "empty";
# Line 405  namespace LinuxSampler { Line 903  namespace LinuxSampler {
903      /** @brief Virtual machine representation of a script.      /** @brief Virtual machine representation of a script.
904       *       *
905       * An instance of this abstract base class represents a parsed script,       * An instance of this abstract base class represents a parsed script,
906       * translated into a virtual machine. You should first check if there were       * translated into a virtual machine tree. You should first check if there
907       * any parser errors. If there were any parser errors, you should refrain       * were any parser errors. If there were any parser errors, you should
908       * from executing the virtual machine. Otherwise if there were no parser       * refrain from executing the virtual machine. Otherwise if there were no
909       * 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
910       * event handlers by i.e. calling eventHandlerByName() and pass the       * script's event handlers by i.e. calling eventHandlerByName() and pass the
911       * 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
912       * descendants) for execution.       * descendants) for execution.
913       *       *
914       * @see VMExecContext       * @see VMExecContext, ScriptVM
915       */       */
916      class VMParserContext {      class VMParserContext {
917      public:      public:
918          virtual ~VMParserContext() {}          virtual ~VMParserContext() {}
919    
920            /**
921             * Returns all noteworthy issues encountered when the script was parsed.
922             * These are parser errors and parser warnings.
923             */
924          virtual std::vector<ParserIssue> issues() const = 0;          virtual std::vector<ParserIssue> issues() const = 0;
925    
926            /**
927             * Same as issues(), but this method only returns parser errors.
928             */
929          virtual std::vector<ParserIssue> errors() const = 0;          virtual std::vector<ParserIssue> errors() const = 0;
930    
931            /**
932             * Same as issues(), but this method only returns parser warnings.
933             */
934          virtual std::vector<ParserIssue> warnings() const = 0;          virtual std::vector<ParserIssue> warnings() const = 0;
935    
936            /**
937             * Returns the translated virtual machine representation of an event
938             * handler block (i.e. "on note ... end on" code block) within the
939             * parsed script. This translated representation of the event handler
940             * can be executed by the virtual machine.
941             *
942             * @param index - index of the event handler within the script
943             */
944          virtual VMEventHandler* eventHandler(uint index) = 0;          virtual VMEventHandler* eventHandler(uint index) = 0;
945    
946            /**
947             * Same as eventHandler(), but this method returns the event handler by
948             * its name. So for a "on note ... end on" code block of the parsed
949             * script you would pass "note" for argument @a name here.
950             *
951             * @param name - name of the event handler (i.e. "init", "note",
952             *               "controller", "release")
953             */
954          virtual VMEventHandler* eventHandlerByName(const String& name) = 0;          virtual VMEventHandler* eventHandlerByName(const String& name) = 0;
955      };      };
956    
957        class SourceToken;
958    
959        /** @brief Recognized token of a script's source code.
960         *
961         * Represents one recognized token of a script's source code, for example
962         * a keyword, variable name, etc. and it provides further informations about
963         * that particular token, i.e. the precise location (line and column) of the
964         * token within the original script's source code.
965         *
966         * This class is not actually used by the sampler itself. It is rather
967         * provided for external script editor applications. Primary purpose of
968         * this class is syntax highlighting for external script editors.
969         */
970        class VMSourceToken {
971        public:
972            VMSourceToken();
973            VMSourceToken(SourceToken* ct);
974            VMSourceToken(const VMSourceToken& other);
975            virtual ~VMSourceToken();
976    
977            // original text of this token as it is in the script's source code
978            String text() const;
979    
980            // position of token in script
981            int firstLine() const; ///< First line this source token is located at in script source code (indexed with 0 being the very first line).
982            int firstColumn() const; ///< Last line this source token is located at in script source code.
983    
984            // base types
985            bool isEOF() const;
986            bool isNewLine() const;
987            bool isKeyword() const;
988            bool isVariableName() const;
989            bool isIdentifier() const;
990            bool isNumberLiteral() const;
991            bool isStringLiteral() const;
992            bool isComment() const;
993            bool isPreprocessor() const;
994            bool isOther() const;
995    
996            // extended types
997            bool isIntegerVariable() const;
998            bool isStringVariable() const;
999            bool isArrayVariable() const;
1000            bool isEventHandlerName() const;
1001    
1002            VMSourceToken& operator=(const VMSourceToken& other);
1003    
1004        private:
1005            SourceToken* m_token;
1006        };
1007    
1008  } // namespace LinuxSampler  } // namespace LinuxSampler
1009    
1010  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

Legend:
Removed from v.2645  
changed lines
  Added in v.2960

  ViewVC Help
Powered by ViewVC