/[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 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 UTC revision 3557 by schoenebeck, Sun Aug 18 00:06:04 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2016 Christian Schoenebeck   * Copyright (c) 2014-2019 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 9  Line 9 
9    
10  // This header defines data types shared between the VM core implementation  // This header defines data types shared between the VM core implementation
11  // (inside the current source directory) and other parts of the sampler  // (inside the current source directory) and other parts of the sampler
12  // (located at other source directories).  // (located at other source directories). It also acts as public API of the
13    // Real-Time script engine for other applications.
14    
15  #ifndef LS_INSTR_SCRIPT_PARSER_COMMON_H  #ifndef LS_INSTR_SCRIPT_PARSER_COMMON_H
16  #define LS_INSTR_SCRIPT_PARSER_COMMON_H  #define LS_INSTR_SCRIPT_PARSER_COMMON_H
# Line 22  Line 23 
23  namespace LinuxSampler {  namespace LinuxSampler {
24    
25      /**      /**
26         * Native data type used by the script engine both internally, as well as
27         * for all integer data types used by scripts (i.e. for all $foo variables
28         * in NKSP scripts). Note that this is different from the original KSP which
29         * is limited to 32 bit for integer variables in KSP scripts.
30         */
31        typedef int64_t vmint;
32    
33        /**
34         * Native data type used internally by the script engine for all unsigned
35         * integer types. This type is currently not exposed to scripts.
36         */
37        typedef uint64_t vmuint;
38    
39        /**
40       * Identifies the type of a noteworthy issue identified by the script       * Identifies the type of a noteworthy issue identified by the script
41       * parser. That's either a parser error or parser warning.       * parser. That's either a parser error or parser warning.
42       */       */
# Line 80  namespace LinuxSampler { Line 95  namespace LinuxSampler {
95       *       *
96       * Identifies one of the possible event handler callback types defined by       * Identifies one of the possible event handler callback types defined by
97       * the NKSP script language.       * the NKSP script language.
98         *
99         * IMPORTANT: this type is forced to be emitted as int32_t type ATM, because
100         * that's the native size expected by the built-in instrument script
101         * variable bindings (see occurrences of VMInt32RelPtr and DECLARE_VMINT
102         * respectively. A native type mismatch between the two could lead to
103         * undefined behavior! Background: By definition the C/C++ compiler is free
104         * to choose a bit size for individual enums which it might find
105         * appropriate, which is usually decided by the compiler according to the
106         * biggest enum constant value defined (in practice it is usually 32 bit).
107       */       */
108      enum VMEventHandlerType_t {      enum VMEventHandlerType_t : int32_t {
109          VM_EVENT_HANDLER_INIT, ///< Initilization event handler, that is script's "on init ... end on" code block.          VM_EVENT_HANDLER_INIT, ///< Initilization event handler, that is script's "on init ... end on" code block.
110          VM_EVENT_HANDLER_NOTE, ///< Note event handler, that is script's "on note ... end on" code block.          VM_EVENT_HANDLER_NOTE, ///< Note event handler, that is script's "on note ... end on" code block.
111          VM_EVENT_HANDLER_RELEASE, ///< Release event handler, that is script's "on release ... end on" code block.          VM_EVENT_HANDLER_RELEASE, ///< Release event handler, that is script's "on release ... end on" code block.
# Line 93  namespace LinuxSampler { Line 117  namespace LinuxSampler {
117      class VMStringExpr;      class VMStringExpr;
118      class VMIntArrayExpr;      class VMIntArrayExpr;
119      class VMStringArrayExpr;      class VMStringArrayExpr;
120        class VMParserContext;
121    
122      /** @brief Virtual machine expression      /** @brief Virtual machine expression
123       *       *
# Line 157  namespace LinuxSampler { Line 182  namespace LinuxSampler {
182           * expressions to an array expression for you, instead this method will           * expressions to an array expression for you, instead this method will
183           * simply return NULL!           * simply return NULL!
184           *           *
185             * @b Note: this method is currently, and in contrast to its other
186             * counter parts, declared as virtual method. Some deriving classes are
187             * currently using this to override this default implementation in order
188             * to implement an "evaluate now as integer array" behavior. This has
189             * efficiency reasons, however this also currently makes this part of
190             * the API less clean and should thus be addressed in future with
191             * appropriate changes to the API.
192             *
193           * @see exprType()           * @see exprType()
194           */           */
195          VMIntArrayExpr* asIntArray() const;          virtual VMIntArrayExpr* asIntArray() const;
196    
197            /**
198             * Returns true in case this expression can be considered to be a
199             * constant expression. A constant expression will retain the same
200             * value throughout the entire life time of a script and the
201             * expression's constant value may be evaluated already at script
202             * parse time, which may result in performance benefits during script
203             * runtime.
204             *
205             * @b NOTE: A constant expression is per se always also non modifyable.
206             * But a non modifyable expression may not necessarily be a constant
207             * expression!
208             *
209             * @see isModifyable()
210             */
211            virtual bool isConstExpr() const = 0;
212    
213            /**
214             * Returns true in case this expression is allowed to be modified.
215             * If this method returns @c false then this expression must be handled
216             * as read-only expression, which means that assigning a new value to it
217             * is either not possible or not allowed.
218             *
219             * @b NOTE: A constant expression is per se always also non modifyable.
220             * But a non modifyable expression may not necessarily be a constant
221             * expression!
222             *
223             * @see isConstExpr()
224             */
225            bool isModifyable() const;
226      };      };
227    
228      /** @brief Virtual machine integer expression      /** @brief Virtual machine integer expression
# Line 175  namespace LinuxSampler { Line 238  namespace LinuxSampler {
238           * Returns the result of this expression as integer (scalar) value.           * Returns the result of this expression as integer (scalar) value.
239           * This abstract method must be implemented by deriving classes.           * This abstract method must be implemented by deriving classes.
240           */           */
241          virtual int evalInt() = 0;          virtual vmint evalInt() = 0;
242    
243          /**          /**
244           * Returns always INT_EXPR for instances of this class.           * Returns always INT_EXPR for instances of this class.
# Line 217  namespace LinuxSampler { Line 280  namespace LinuxSampler {
280           * Returns amount of elements in this array. This abstract method must           * Returns amount of elements in this array. This abstract method must
281           * be implemented by deriving classes.           * be implemented by deriving classes.
282           */           */
283          virtual int arraySize() const = 0;          virtual vmint arraySize() const = 0;
284      };      };
285    
286      /** @brief Virtual Machine Integer Array Expression      /** @brief Virtual Machine Integer Array Expression
# Line 235  namespace LinuxSampler { Line 298  namespace LinuxSampler {
298           *           *
299           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
300           */           */
301          virtual int evalIntElement(uint i) = 0;          virtual vmint evalIntElement(vmuint i) = 0;
302    
303          /**          /**
304           * Changes the current value of an element (given by array element           * Changes the current value of an element (given by array element
# Line 244  namespace LinuxSampler { Line 307  namespace LinuxSampler {
307           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
308           * @param value - new integer scalar value to be assigned to that array element           * @param value - new integer scalar value to be assigned to that array element
309           */           */
310          virtual void assignIntElement(uint i, int value) = 0;          virtual void assignIntElement(vmuint i, vmint value) = 0;
311    
312          /**          /**
313           * Returns always INT_ARR_EXPR for instances of this class.           * Returns always INT_ARR_EXPR for instances of this class.
# Line 266  namespace LinuxSampler { Line 329  namespace LinuxSampler {
329           * Returns the amount of arguments going to be passed to the script           * Returns the amount of arguments going to be passed to the script
330           * function.           * function.
331           */           */
332          virtual int argsCount() const = 0;          virtual vmint argsCount() const = 0;
333    
334          /**          /**
335           * Returns the respective argument (requested by argument index @a i) of           * Returns the respective argument (requested by argument index @a i) of
# Line 276  namespace LinuxSampler { Line 339  namespace LinuxSampler {
339           *           *
340           * @param i - function argument index (indexed from left to right)           * @param i - function argument index (indexed from left to right)
341           */           */
342          virtual VMExpr* arg(int i) = 0;          virtual VMExpr* arg(vmint i) = 0;
343      };      };
344    
345      /** @brief Result value returned from a call to a built-in script function.      /** @brief Result value returned from a call to a built-in script function.
# Line 340  namespace LinuxSampler { Line 403  namespace LinuxSampler {
403           * script is calling this function with less arguments, the script           * script is calling this function with less arguments, the script
404           * parser will throw a parser error.           * parser will throw a parser error.
405           */           */
406          virtual int minRequiredArgs() const = 0;          virtual vmint minRequiredArgs() const = 0;
407    
408          /**          /**
409           * Maximum amount of function arguments this functions accepts. If a           * Maximum amount of function arguments this functions accepts. If a
410           * script is calling this function with more arguments, the script           * script is calling this function with more arguments, the script
411           * parser will throw a parser error.           * parser will throw a parser error.
412           */           */
413          virtual int maxAllowedArgs() const = 0;          virtual vmint maxAllowedArgs() const = 0;
414    
415          /**          /**
416           * Script data type of the function's @c iArg 'th function argument.           * Script data type of the function's @c iArg 'th function argument.
# Line 363  namespace LinuxSampler { Line 426  namespace LinuxSampler {
426           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
427           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
428           */           */
429          virtual ExprType_t argType(int iArg) const = 0;          virtual ExprType_t argType(vmint iArg) const = 0;
430    
431          /**          /**
432           * This function is called by the parser to check whether arguments           * This method is called by the parser to check whether arguments
433           * passed in scripts to this function are accepted by this function. If           * passed in scripts to this function are accepted by this function. If
434           * a script calls this function with an argument's data type not           * a script calls this function with an argument's data type not
435           * accepted by this function, the parser will throw a parser error. On           * accepted by this function, the parser will throw a parser error. On
# Line 381  namespace LinuxSampler { Line 444  namespace LinuxSampler {
444           * @return true if the given data type would be accepted for the           * @return true if the given data type would be accepted for the
445           *         respective function argument by the function           *         respective function argument by the function
446           */           */
447          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;          virtual bool acceptsArgType(vmint iArg, ExprType_t type) const = 0;
448    
449            /**
450             * This method is called by the parser to check whether some arguments
451             * (and if yes which ones) passed to this script function will be
452             * modified by this script function. Most script functions simply use
453             * their arguments as inputs, that is they only read the argument's
454             * values. However some script function may also use passed
455             * argument(s) as output variables. In this case the function
456             * implementation must return @c true for the respective argument
457             * index here.
458             *
459             * @param iArg - index of the function argument in question
460             *               (must be between 0 .. maxAllowedArgs() - 1)
461             */
462            virtual bool modifiesArg(vmint iArg) const = 0;
463    
464          /**          /**
465           * Implements the actual function execution. This exec() method is           * Implements the actual function execution. This exec() method is
# Line 415  namespace LinuxSampler { Line 493  namespace LinuxSampler {
493    
494      /** @brief Virtual machine relative pointer.      /** @brief Virtual machine relative pointer.
495       *       *
496       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be       * POD base of VMInt64RelPtr, VMInt32RelPtr and VMInt8RelPtr structures. Not
497       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.       * intended to be used directly. Use VMInt64RelPtr, VMInt32RelPtr,
498         * VMInt8RelPtr instead.
499       *       *
500       * @see VMIntRelPtr, VMInt8RelPtr       * @see VMInt64RelPtr, VMInt32RelPtr, VMInt8RelPtr
501       */       */
502      struct VMRelPtr {      struct VMRelPtr {
503          void** base; ///< Base pointer.          void** base; ///< Base pointer.
504          int offset;  ///< Offset (in bytes) relative to base pointer.          vmint offset;  ///< Offset (in bytes) relative to base pointer.
505            bool readonly; ///< Whether the pointed data may be modified or just be read.
506      };      };
507    
508      /** @brief Pointer to built-in VM integer variable (of C/C++ type int).      /** @brief Pointer to built-in VM integer variable (interface class).
509         *
510         * This class acts as an abstract interface to all built-in integer script
511         * variables, independent of their actual native size (i.e. some built-in
512         * script variables are internally using a native int size of 64 bit or 32
513         * bit or 8 bit). The virtual machine is using this interface class instead
514         * of its implementing descendants (VMInt64RelPtr, VMInt32RelPtr,
515         * VMInt8RelPtr) in order for the virtual machine for not being required to
516         * handle each of them differently.
517         */
518        struct VMIntPtr {
519            virtual vmint evalInt() = 0;
520            virtual void assign(vmint i) = 0;
521            virtual bool isAssignable() const = 0;
522        };
523    
524        /** @brief Pointer to built-in VM integer variable (of C/C++ type int64_t).
525         *
526         * Used for defining built-in 64 bit integer script variables.
527         *
528         * @b CAUTION: You may only use this class for pointing to C/C++ variables
529         * of type "int64_t" (thus being exactly 64 bit in size). If the C/C++ int
530         * variable you want to reference is only 32 bit in size then you @b must
531         * use VMInt32RelPtr instead! Respectively for a referenced native variable
532         * with only 8 bit in size you @b must use VMInt8RelPtr instead!
533         *
534         * For efficiency reasons the actual native C/C++ int variable is referenced
535         * by two components here. The actual native int C/C++ variable in memory
536         * is dereferenced at VM run-time by taking the @c base pointer dereference
537         * and adding @c offset bytes. This has the advantage that for a large
538         * number of built-in int variables, only one (or few) base pointer need
539         * to be re-assigned before running a script, instead of updating each
540         * built-in variable each time before a script is executed.
541         *
542         * Refer to DECLARE_VMINT() for example code.
543         *
544         * @see VMInt32RelPtr, VMInt8RelPtr, DECLARE_VMINT()
545         */
546        struct VMInt64RelPtr : VMRelPtr, VMIntPtr {
547            VMInt64RelPtr() {
548                base   = NULL;
549                offset = 0;
550                readonly = false;
551            }
552            VMInt64RelPtr(const VMRelPtr& data) {
553                base   = data.base;
554                offset = data.offset;
555                readonly = false;
556            }
557            vmint evalInt() OVERRIDE {
558                return (vmint)*(int64_t*)&(*(uint8_t**)base)[offset];
559            }
560            void assign(vmint i) OVERRIDE {
561                *(int64_t*)&(*(uint8_t**)base)[offset] = (int64_t)i;
562            }
563            bool isAssignable() const OVERRIDE { return !readonly; }
564        };
565    
566        /** @brief Pointer to built-in VM integer variable (of C/C++ type int32_t).
567       *       *
568       * Used for defining built-in 32 bit integer script variables.       * Used for defining built-in 32 bit integer script variables.
569       *       *
570       * @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
571       * of type "int" (which on most systems is 32 bit in size). If the C/C++ int       * of type "int32_t" (thus being exactly 32 bit in size). If the C/C++ int
572       * variable you want to reference is only 8 bit in size, then you @b must       * variable you want to reference is 64 bit in size then you @b must use
573       * use VMInt8RelPtr instead!       * VMInt64RelPtr instead! Respectively for a referenced native variable with
574         * only 8 bit in size you @b must use VMInt8RelPtr instead!
575       *       *
576       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
577       * by two components here. The actual native int C/C++ variable in memory       * by two components here. The actual native int C/C++ variable in memory
# Line 444  namespace LinuxSampler { Line 583  namespace LinuxSampler {
583       *       *
584       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
585       *       *
586       * @see VMInt8RelPtr, DECLARE_VMINT()       * @see VMInt64RelPtr, VMInt8RelPtr, DECLARE_VMINT()
587       */       */
588      struct VMIntRelPtr : VMRelPtr {      struct VMInt32RelPtr : VMRelPtr, VMIntPtr {
589          VMIntRelPtr() {          VMInt32RelPtr() {
590              base   = NULL;              base   = NULL;
591              offset = 0;              offset = 0;
592                readonly = false;
593          }          }
594          VMIntRelPtr(const VMRelPtr& data) {          VMInt32RelPtr(const VMRelPtr& data) {
595              base   = data.base;              base   = data.base;
596              offset = data.offset;              offset = data.offset;
597                readonly = false;
598          }          }
599          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }          vmint evalInt() OVERRIDE {
600          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }              return (vmint)*(int32_t*)&(*(uint8_t**)base)[offset];
601            }
602            void assign(vmint i) OVERRIDE {
603                *(int32_t*)&(*(uint8_t**)base)[offset] = (int32_t)i;
604            }
605            bool isAssignable() const OVERRIDE { return !readonly; }
606      };      };
607    
608      /** @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).
# Line 465  namespace LinuxSampler { Line 611  namespace LinuxSampler {
611       *       *
612       * @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
613       * 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
614       * reference is an "int" type (which is 32 bit on most systems), then you       * reference is not exactly 8 bit in size then you @b must respectively use
615       * @b must use VMIntRelPtr instead!       * either VMInt32RelPtr for native 32 bit variables or VMInt64RelPtrl for
616         * native 64 bit variables instead!
617       *       *
618       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
619       * by two components here. The actual native int C/C++ variable in memory       * by two components here. The actual native int C/C++ variable in memory
# Line 478  namespace LinuxSampler { Line 625  namespace LinuxSampler {
625       *       *
626       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
627       *       *
628       * @see VMIntRelPtr, DECLARE_VMINT()       * @see VMIntRel32Ptr, VMIntRel64Ptr, DECLARE_VMINT()
629       */       */
630      struct VMInt8RelPtr : VMIntRelPtr {      struct VMInt8RelPtr : VMRelPtr, VMIntPtr {
631          VMInt8RelPtr() : VMIntRelPtr() {}          VMInt8RelPtr() {
632          VMInt8RelPtr(const VMRelPtr& data) : VMIntRelPtr(data) {}              base   = NULL;
633          virtual int evalInt() OVERRIDE {              offset = 0;
634              return *(uint8_t*)&(*(uint8_t**)base)[offset];              readonly = false;
635          }          }
636          virtual void assign(int i) OVERRIDE {          VMInt8RelPtr(const VMRelPtr& data) {
637              *(uint8_t*)&(*(uint8_t**)base)[offset] = i;              base   = data.base;
638                offset = data.offset;
639                readonly = false;
640            }
641            vmint evalInt() OVERRIDE {
642                return (vmint)*(uint8_t*)&(*(uint8_t**)base)[offset];
643          }          }
644            void assign(vmint i) OVERRIDE {
645                *(uint8_t*)&(*(uint8_t**)base)[offset] = (uint8_t)i;
646            }
647            bool isAssignable() const OVERRIDE { return !readonly; }
648      };      };
649    
650        /** @brief Pointer to built-in VM integer variable (of C/C++ type vmint).
651         *
652         * Use this typedef if the native variable to be pointed to is using the
653         * typedef vmint. If the native C/C++ variable to be pointed to is using
654         * another C/C++ type then better use one of VMInt64RelPtr or VMInt32RelPtr
655         * instead.
656         */
657        typedef VMInt64RelPtr VMIntRelPtr;
658    
659        #if HAVE_CXX_EMBEDDED_PRAGMA_DIAGNOSTICS
660        # define COMPILER_DISABLE_OFFSETOF_WARNING                    \
661            _Pragma("GCC diagnostic push")                            \
662            _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
663        # define COMPILER_RESTORE_OFFSETOF_WARNING \
664            _Pragma("GCC diagnostic pop")
665        #else
666        # define COMPILER_DISABLE_OFFSETOF_WARNING
667        # define COMPILER_RESTORE_OFFSETOF_WARNING
668        #endif
669    
670      /**      /**
671       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr       * Convenience macro for initializing VMInt64RelPtr, VMInt32RelPtr and
672       * structures. Usage example:       * VMInt8RelPtr structures. Usage example:
673       * @code       * @code
674       * struct Foo {       * struct Foo {
675       *   uint8_t a; // native representation of a built-in integer script variable       *   uint8_t a; // native representation of a built-in integer script variable
676       *   int b; // native representation of another built-in integer script variable       *   int64_t b; // native representation of another built-in integer script variable
677       *   int c; // native representation of another built-in integer script variable       *   int64_t c; // native representation of another built-in integer script variable
678       *   uint8_t d; // native representation of another built-in integer script variable       *   uint8_t d; // native representation of another built-in integer script variable
679       * };       * };
680       *       *
# Line 509  namespace LinuxSampler { Line 685  namespace LinuxSampler {
685       * Foo* pFoo;       * Foo* pFoo;
686       *       *
687       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
688       * VMIntRelPtr  varB = DECLARE_VMINT(pFoo, class Foo, b);       * VMInt64RelPtr varB = DECLARE_VMINT(pFoo, class Foo, b);
689       * VMIntRelPtr  varC = DECLARE_VMINT(pFoo, class Foo, c);       * VMInt64RelPtr varC = DECLARE_VMINT(pFoo, class Foo, c);
690       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
691       *       *
692       * pFoo = &foo1;       * pFoo = &foo1;
# Line 533  namespace LinuxSampler { Line 709  namespace LinuxSampler {
709       * complexity inside the sampler engines which provide the actual script       * complexity inside the sampler engines which provide the actual script
710       * functionalities.       * functionalities.
711       */       */
712      #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \      #define DECLARE_VMINT(basePtr, T_struct, T_member) (          \
713          (VMRelPtr) {                                     \          /* Disable offsetof warning, trust us, we are cautios. */ \
714              (void**) &basePtr,                           \          COMPILER_DISABLE_OFFSETOF_WARNING                         \
715              offsetof(T_struct, T_member)                 \          (VMRelPtr) {                                              \
716          }                                                \              (void**) &basePtr,                                    \
717      )                                                    \              offsetof(T_struct, T_member),                         \
718                false                                                 \
719            }                                                         \
720            COMPILER_RESTORE_OFFSETOF_WARNING                         \
721        )                                                             \
722    
723        /**
724         * Same as DECLARE_VMINT(), but this one defines the VMInt64RelPtr,
725         * VMInt32RelPtr and VMInt8RelPtr structures to be of read-only type.
726         * That means the script parser will abort any script at parser time if the
727         * script is trying to modify such a read-only built-in variable.
728         *
729         * @b NOTE: this is only intended for built-in read-only variables that
730         * may change during runtime! If your built-in variable's data is rather
731         * already available at parser time and won't change during runtime, then
732         * you should rather register a built-in constant in your VM class instead!
733         *
734         * @see ScriptVM::builtInConstIntVariables()
735         */
736        #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
737            /* Disable offsetof warning, trust us, we are cautios. */ \
738            COMPILER_DISABLE_OFFSETOF_WARNING                         \
739            (VMRelPtr) {                                              \
740                (void**) &basePtr,                                    \
741                offsetof(T_struct, T_member),                         \
742                true                                                  \
743            }                                                         \
744            COMPILER_RESTORE_OFFSETOF_WARNING                         \
745        )                                                             \
746    
747      /** @brief Built-in VM 8 bit integer array variable.      /** @brief Built-in VM 8 bit integer array variable.
748       *       *
# Line 548  namespace LinuxSampler { Line 752  namespace LinuxSampler {
752       */       */
753      struct VMInt8Array {      struct VMInt8Array {
754          int8_t* data;          int8_t* data;
755          int size;          vmint size;
756            bool readonly; ///< Whether the array data may be modified or just be read.
757    
758            VMInt8Array() : data(NULL), size(0), readonly(false) {}
759        };
760    
761        /** @brief Virtual machine script variable.
762         *
763         * Common interface for all variables accessed in scripts.
764         */
765        class VMVariable : virtual public VMExpr {
766        public:
767            /**
768             * Whether a script may modify the content of this variable by
769             * assigning a new value to it.
770             *
771             * @see isConstExpr(), assign()
772             */
773            virtual bool isAssignable() const = 0;
774    
775            /**
776             * In case this variable is assignable, this method will be called to
777             * perform the value assignment to this variable with @a expr
778             * reflecting the new value to be assigned.
779             *
780             * @param expr - new value to be assigned to this variable
781             */
782            virtual void assignExpr(VMExpr* expr) = 0;
783        };
784        
785        /** @brief Dynamically executed variable (abstract base class).
786         *
787         * Interface for the implementation of a dynamically generated content of
788         * a built-in script variable. Most built-in variables are simply pointers
789         * to some native location in memory. So when a script reads them, the
790         * memory location is simply read to get the value of the variable. A
791         * dynamic variable however is not simply a memory location. For each access
792         * to a dynamic variable some native code is executed to actually generate
793         * and provide the content (value) of this type of variable.
794         */
795        class VMDynVar : public VMVariable {
796        public:
797            /**
798             * Returns true in case this dynamic variable can be considered to be a
799             * constant expression. A constant expression will retain the same value
800             * throughout the entire life time of a script and the expression's
801             * constant value may be evaluated already at script parse time, which
802             * may result in performance benefits during script runtime.
803             *
804             * However due to the "dynamic" behavior of dynamic variables, almost
805             * all dynamic variables are probably not constant expressions. That's
806             * why this method returns @c false by default. If you are really sure
807             * that your dynamic variable implementation can be considered a
808             * constant expression then you may override this method and return
809             * @c true instead. Note that when you return @c true here, your
810             * dynamic variable will really just be executed once; and exectly
811             * already when the script is loaded!
812             *
813             * As an example you may implement a "constant" built-in dynamic
814             * variable that checks for a certain operating system feature and
815             * returns the result of that OS feature check as content (value) of
816             * this dynamic variable. Since the respective OS feature might become
817             * available/unavailable after OS updates, software migration, etc. the
818             * OS feature check should at least be performed once each time the
819             * application is launched. And since the OS feature check might take a
820             * certain amount of execution time, it might make sense to only
821             * perform the check if the respective variable name is actually
822             * referenced at all in the script to be loaded. Note that the dynamic
823             * variable will still be evaluated again though if the script is
824             * loaded again. So it is up to you to probably cache the result in the
825             * implementation of your dynamic variable.
826             *
827             * On doubt, please rather consider to use a constant built-in script
828             * variable instead of implementing a "constant" dynamic variable, due
829             * to the runtime overhead a dynamic variable may cause.
830             *
831             * @see isAssignable()
832             */
833            bool isConstExpr() const OVERRIDE { return false; }
834    
835            /**
836             * In case this dynamic variable is assignable, the new value (content)
837             * to be assigned to this dynamic variable.
838             *
839             * By default this method does nothing. Override and implement this
840             * method in your subclass in case your dynamic variable allows to
841             * assign a new value by script.
842             *
843             * @param expr - new value to be assigned to this variable
844             */
845            void assignExpr(VMExpr* expr) OVERRIDE {}
846    
847            virtual ~VMDynVar() {}
848        };
849    
850        /** @brief Dynamically executed variable (of integer data type).
851         *
852         * This is the base class for all built-in integer script variables whose
853         * variable content needs to be provided dynamically by executable native
854         * code on each script variable access.
855         */
856        class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
857        public:
858        };
859    
860          VMInt8Array() : data(NULL), size(0) {}      /** @brief Dynamically executed variable (of string data type).
861         *
862         * This is the base class for all built-in string script variables whose
863         * variable content needs to be provided dynamically by executable native
864         * code on each script variable access.
865         */
866        class VMDynStringVar : virtual public VMDynVar, virtual public VMStringExpr {
867        public:
868        };
869    
870        /** @brief Dynamically executed variable (of integer array data type).
871         *
872         * This is the base class for all built-in integer array script variables
873         * whose variable content needs to be provided dynamically by executable
874         * native code on each script variable access.
875         */
876        class VMDynIntArrayVar : virtual public VMDynVar, virtual public VMIntArrayExpr {
877        public:
878      };      };
879    
880      /** @brief Provider for built-in script functions and variables.      /** @brief Provider for built-in script functions and variables.
# Line 571  namespace LinuxSampler { Line 895  namespace LinuxSampler {
895          virtual VMFunction* functionByName(const String& name) = 0;          virtual VMFunction* functionByName(const String& name) = 0;
896    
897          /**          /**
898             * Returns @c true if the passed built-in function is disabled and
899             * should be ignored by the parser. This method is called by the
900             * parser on preprocessor level for each built-in function call within
901             * a script. Accordingly if this method returns @c true, then the
902             * respective function call is completely filtered out on preprocessor
903             * level, so that built-in function won't make into the result virtual
904             * machine representation, nor would expressions of arguments passed to
905             * that built-in function call be evaluated, nor would any check
906             * regarding correct usage of the built-in function be performed.
907             * In other words: a disabled function call ends up as a comment block.
908             *
909             * @param fn - built-in function to be checked
910             * @param ctx - parser context at the position where the built-in
911             *              function call is located within the script
912             */
913            virtual bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) = 0;
914    
915            /**
916           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script variables
917           * which point to native "int" scalar (usually 32 bit) variables.           * which point to native "int" scalar (usually 32 bit) variables.
918           */           */
919          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;          virtual std::map<String,VMIntPtr*> builtInIntVariables() = 0;
920    
921          /**          /**
922           * Returns a variable name indexed map of all built-in script integer           * Returns a variable name indexed map of all built-in script integer
# Line 586  namespace LinuxSampler { Line 928  namespace LinuxSampler {
928           * Returns a variable name indexed map of all built-in constant script           * Returns a variable name indexed map of all built-in constant script
929           * variables, which never change their value at runtime.           * variables, which never change their value at runtime.
930           */           */
931          virtual std::map<String,int> builtInConstIntVariables() = 0;          virtual std::map<String,vmint> builtInConstIntVariables() = 0;
932    
933            /**
934             * Returns a variable name indexed map of all built-in dynamic variables,
935             * which are not simply data stores, rather each one of them executes
936             * natively to provide or alter the respective script variable data.
937             */
938            virtual std::map<String,VMDynVar*> builtInDynamicVariables() = 0;
939      };      };
940    
941      /** @brief Execution state of a virtual machine.      /** @brief Execution state of a virtual machine.
# Line 628  namespace LinuxSampler { Line 977  namespace LinuxSampler {
977           *           *
978           * @see ScriptVM::exec()           * @see ScriptVM::exec()
979           */           */
980          virtual int suspensionTimeMicroseconds() const = 0;          virtual vmint suspensionTimeMicroseconds() const = 0;
981    
982            /**
983             * Causes all polyphonic variables to be reset to zero values. A
984             * polyphonic variable is expected to be zero when entering a new event
985             * handler instance. As an exception the values of polyphonic variables
986             * shall only be preserved from an note event handler instance to its
987             * correspending specific release handler instance. So in the latter
988             * case the script author may pass custom data from the note handler to
989             * the release handler, but only for the same specific note!
990             */
991            virtual void resetPolyphonicData() = 0;
992    
993            /**
994             * Returns amount of virtual machine instructions which have been
995             * performed the last time when this execution context was executing a
996             * script. So in case you need the overall amount of instructions
997             * instead, then you need to add them by yourself after each
998             * ScriptVM::exec() call.
999             */
1000            virtual size_t instructionsPerformed() const = 0;
1001    
1002            /**
1003             * Sends a signal to this script execution instance to abort its script
1004             * execution as soon as possible. This method is called i.e. when one
1005             * script execution instance intends to stop another script execution
1006             * instance.
1007             */
1008            virtual void signalAbort() = 0;
1009    
1010            /**
1011             * Copies the current entire execution state from this object to the
1012             * given object. So this can be used to "fork" a new script thread which
1013             * then may run independently with its own polyphonic data for instance.
1014             */
1015            virtual void forkTo(VMExecContext* ectx) const = 0;
1016    
1017            /**
1018             * In case the script called the built-in exit() function and passed a
1019             * value as argument to the exit() function, then this method returns
1020             * the value that had been passed as argument to the exit() function.
1021             * Otherwise if the exit() function has not been called by the script
1022             * or no argument had been passed to the exit() function, then this
1023             * method returns NULL instead.
1024             *
1025             * Currently this is only used for automated test cases against the
1026             * script engine, which return some kind of value in the individual
1027             * test case scripts to check their behaviour in automated way. There
1028             * is no purpose for this mechanism in production use. Accordingly this
1029             * exit result value is @b always completely ignored by the sampler
1030             * engines.
1031             *
1032             * Officially the built-in exit() function does not expect any arguments
1033             * to be passed to its function call, and by default this feature is
1034             * hence disabled and will yield in a parser error unless
1035             * ScriptVM::setExitResultEnabled() was explicitly set.
1036             *
1037             * @see ScriptVM::setExitResultEnabled()
1038             */
1039            virtual VMExpr* exitResult() = 0;
1040      };      };
1041    
1042      /** @brief Script callback for a certain event.      /** @brief Script callback for a certain event.
# Line 660  namespace LinuxSampler { Line 1068  namespace LinuxSampler {
1068      };      };
1069    
1070      /**      /**
1071         * Reflects the precise position and span of a specific code block within
1072         * a script. This is currently only used for the locations of commented
1073         * code blocks due to preprocessor statements, and for parser errors and
1074         * parser warnings.
1075         *
1076         * @see ParserIssue for code locations of parser errors and parser warnings
1077         *
1078         * @see VMParserContext::preprocessorComments() for locations of code which
1079         *      have been filtered out by preprocessor statements
1080         */
1081        struct CodeBlock {
1082            int firstLine; ///< The first line number of this code block within the script (indexed with 1 being the very first line).
1083            int lastLine; ///< The last line number of this code block within the script.
1084            int firstColumn; ///< The first column of this code block within the script (indexed with 1 being the very first column).
1085            int lastColumn; ///< The last column of this code block within the script.
1086        };
1087    
1088        /**
1089       * Encapsulates a noteworty parser issue. This encompasses the type of the       * Encapsulates a noteworty parser issue. This encompasses the type of the
1090       * issue (either a parser error or parser warning), a human readable       * issue (either a parser error or parser warning), a human readable
1091       * explanation text of the error or warning and the location of the       * explanation text of the error or warning and the location of the
1092       * encountered parser issue within the script.       * encountered parser issue within the script.
1093         *
1094         * @see VMSourceToken for processing syntax highlighting instead.
1095       */       */
1096      struct ParserIssue {      struct ParserIssue : CodeBlock {
1097          String txt; ///< Human readable explanation text of the parser issue.          String txt; ///< Human readable explanation text of the parser issue.
         int line; ///< Line number within the script where this issue was encountered.  
1098          ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning.          ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning.
1099    
1100          /**          /**
# Line 676  namespace LinuxSampler { Line 1103  namespace LinuxSampler {
1103          inline void dump() {          inline void dump() {
1104              switch (type) {              switch (type) {
1105                  case PARSER_ERROR:                  case PARSER_ERROR:
1106                      printf("[ERROR] line %d: %s\n", line, txt.c_str());                      printf("[ERROR] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
1107                      break;                      break;
1108                  case PARSER_WARNING:                  case PARSER_WARNING:
1109                      printf("[Warning] line %d: %s\n", line, txt.c_str());                      printf("[Warning] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
1110                      break;                      break;
1111              }              }
1112          }          }
# Line 747  namespace LinuxSampler { Line 1174  namespace LinuxSampler {
1174          virtual std::vector<ParserIssue> warnings() const = 0;          virtual std::vector<ParserIssue> warnings() const = 0;
1175    
1176          /**          /**
1177             * Returns all code blocks of the script which were filtered out by the
1178             * preprocessor.
1179             */
1180            virtual std::vector<CodeBlock> preprocessorComments() const = 0;
1181    
1182            /**
1183           * Returns the translated virtual machine representation of an event           * Returns the translated virtual machine representation of an event
1184           * handler block (i.e. "on note ... end on" code block) within the           * handler block (i.e. "on note ... end on" code block) within the
1185           * parsed script. This translated representation of the event handler           * parsed script. This translated representation of the event handler
# Line 767  namespace LinuxSampler { Line 1200  namespace LinuxSampler {
1200          virtual VMEventHandler* eventHandlerByName(const String& name) = 0;          virtual VMEventHandler* eventHandlerByName(const String& name) = 0;
1201      };      };
1202    
1203        class SourceToken;
1204    
1205        /** @brief Recognized token of a script's source code.
1206         *
1207         * Represents one recognized token of a script's source code, for example
1208         * a keyword, variable name, etc. and it provides further informations about
1209         * that particular token, i.e. the precise location (line and column) of the
1210         * token within the original script's source code.
1211         *
1212         * This class is not actually used by the sampler itself. It is rather
1213         * provided for external script editor applications. Primary purpose of
1214         * this class is syntax highlighting for external script editors.
1215         *
1216         * @see ParserIssue for processing compile errors and warnings instead.
1217         */
1218        class VMSourceToken {
1219        public:
1220            VMSourceToken();
1221            VMSourceToken(SourceToken* ct);
1222            VMSourceToken(const VMSourceToken& other);
1223            virtual ~VMSourceToken();
1224    
1225            // original text of this token as it is in the script's source code
1226            String text() const;
1227    
1228            // position of token in script
1229            int firstLine() const; ///< First line this source token is located at in script source code (indexed with 0 being the very first line). Most source code tokens are not spanning over multiple lines, the only current exception are comments, in the latter case you need to process text() to get the last line and last column for the comment.
1230            int firstColumn() const; ///< First column on the first line this source token is located at in script source code (indexed with 0 being the very first column). To get the length of this token use text().length().
1231    
1232            // base types
1233            bool isEOF() const; ///< Returns true in case this source token represents the end of the source code file.
1234            bool isNewLine() const; ///< Returns true in case this source token represents a line feed character (i.e. "\n" on Unix systems).
1235            bool isKeyword() const; ///< Returns true in case this source token represents a language keyword (i.e. "while", "function", "declare", "on", etc.).
1236            bool isVariableName() const; ///< Returns true in case this source token represents a variable name (i.e. "$someIntVariable", "%someArrayVariable", "\@someStringVariable"). @see isIntegerVariable(), isStringVariable(), isArrayVariable() for the precise variable type.
1237            bool isIdentifier() const; ///< Returns true in case this source token represents an identifier, which currently always means a function name.
1238            bool isNumberLiteral() const; ///< Returns true in case this source token represents a number literal (i.e. 123).
1239            bool isStringLiteral() const; ///< Returns true in case this source token represents a string literal (i.e. "Some text").
1240            bool isComment() const; ///< Returns true in case this source token represents a source code comment.
1241            bool isPreprocessor() const; ///< Returns true in case this source token represents a preprocessor statement.
1242            bool isOther() const; ///< Returns true in case this source token represents anything else not covered by the token types mentioned above.
1243    
1244            // extended types
1245            bool isIntegerVariable() const; ///< Returns true in case this source token represents an integer variable name (i.e. "$someIntVariable").
1246            bool isStringVariable() const; ///< Returns true in case this source token represents an string variable name (i.e. "\@someStringVariable").
1247            bool isArrayVariable() const; ///< Returns true in case this source token represents an array variable name (i.e. "%someArryVariable").
1248            bool isEventHandlerName() const; ///< Returns true in case this source token represents an event handler name (i.e. "note", "release", "controller").
1249    
1250            VMSourceToken& operator=(const VMSourceToken& other);
1251    
1252        private:
1253            SourceToken* m_token;
1254        };
1255    
1256  } // namespace LinuxSampler  } // namespace LinuxSampler
1257    
1258  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H  #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

Legend:
Removed from v.2879  
changed lines
  Added in v.3557

  ViewVC Help
Powered by ViewVC