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

Legend:
Removed from v.2581  
changed lines
  Added in v.2945

  ViewVC Help
Powered by ViewVC