/[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 2960 by schoenebeck, Sun Jul 17 12:10:06 2016 UTC revision 3564 by schoenebeck, Sat Aug 24 09:18:57 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         * Native data type used internally by the script engine for floating point
41         * data types. This type is currently not exposed to scripts.
42         */
43        typedef float vmfloat;
44    
45        /**
46       * Identifies the type of a noteworthy issue identified by the script       * Identifies the type of a noteworthy issue identified by the script
47       * parser. That's either a parser error or parser warning.       * parser. That's either a parser error or parser warning.
48       */       */
# Line 80  namespace LinuxSampler { Line 101  namespace LinuxSampler {
101       *       *
102       * Identifies one of the possible event handler callback types defined by       * Identifies one of the possible event handler callback types defined by
103       * the NKSP script language.       * the NKSP script language.
104         *
105         * IMPORTANT: this type is forced to be emitted as int32_t type ATM, because
106         * that's the native size expected by the built-in instrument script
107         * variable bindings (see occurrences of VMInt32RelPtr and DECLARE_VMINT
108         * respectively. A native type mismatch between the two could lead to
109         * undefined behavior! Background: By definition the C/C++ compiler is free
110         * to choose a bit size for individual enums which it might find
111         * appropriate, which is usually decided by the compiler according to the
112         * biggest enum constant value defined (in practice it is usually 32 bit).
113       */       */
114      enum VMEventHandlerType_t {      enum VMEventHandlerType_t : int32_t {
115          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.
116          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.
117          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.
118          VM_EVENT_HANDLER_CONTROLLER, ///< Controller event handler, that is script's "on controller ... end on" code block.          VM_EVENT_HANDLER_CONTROLLER, ///< Controller event handler, that is script's "on controller ... end on" code block.
119      };      };
120    
121        /**
122         * All metric unit prefixes (actually just scale factors) supported by this
123         * script engine.
124         */
125        enum MetricPrefix_t {
126            VM_NO_PREFIX = 0, ///< = 1
127            VM_KILO,          ///< = 10^3, short 'k'
128            VM_HECTO,         ///< = 10^2, short 'h'
129            VM_DECA,          ///< = 10, short 'da'
130            VM_DECI,          ///< = 10^-1, short 'd'
131            VM_CENTI,         ///< = 10^-2, short 'c' (this is also used for tuning "cents")
132            VM_MILLI,         ///< = 10^-3, short 'm'
133            VM_MICRO,         ///< = 10^-6, short 'u'
134        };
135    
136        /**
137         * All measurement unit types supported by this script engine.
138         *
139         * @e Note: there is no standard unit "cents" here (for pitch/tuning), use
140         * @c VM_CENTI for the latter instad. That's because the commonly cited
141         * "cents" unit is actually no measurement unit type but rather a metric
142         * unit prefix.
143         *
144         * @see MetricPrefix_t
145         */
146        enum StdUnit_t {
147            VM_NO_UNIT = 0, ///< No unit used, the number is just an abstract number.
148            VM_SECOND,      ///< Measuring time.
149            VM_HERTZ,       ///< Measuring frequency.
150            VM_BEL,         ///< Measuring relation between two energy levels (in logarithmic scale). Since we are using it for accoustics, we are always referring to A-weighted Bels (i.e. dBA).
151        };
152    
153      // just symbol prototyping      // just symbol prototyping
154      class VMIntExpr;      class VMIntExpr;
155      class VMStringExpr;      class VMStringExpr;
156      class VMIntArrayExpr;      class VMIntArrayExpr;
157      class VMStringArrayExpr;      class VMStringArrayExpr;
158        class VMParserContext;
159    
160        /** @brief Virtual machine measuring unit.
161         *
162         * Abstract base class representing standard measurement units throughout
163         * the script engine. These might be i.e. "dB" (deci Bel) for loudness,
164         * "Hz" (Hertz) for frequencies or "s" for "seconds".
165         *
166         * Originally the script engine only supported abstract integer values for
167         * controlling any synthesis parameter or built-in function argument or
168         * variable. Under certain situations it makes sense though for an
169         * instrument script author to provide values in real, standard measurement
170         * units, for example setting the frequency of some LFO directly to "20Hz".
171         * Hence support for standard units in scripts was added as an extension to
172         * the NKSP script engine.
173         */
174        class VMUnit {
175        public:
176            /**
177             * Returns the metric prefix of this unit. A metric prefix essentially
178             * is just a mathematical scale factor that should be applied to the
179             * number associated with the measurement unit. Usually a unit either
180             * has exactly none or one prefix, but note that there might also be
181             * units with more than one prefix, for example mdB (mili deci bel)
182             * is used sometimes which has two prefixes. This is an exception though
183             * and more than two prefixes is currently not supported by the script
184             * engine.
185             *
186             * Start iterating over the prefixes of this unit by passing @c 0 as
187             * argument to this method. The prefixes are terminated with return
188             * value VM_NO_PREFIX being always the last element.
189             *
190             * @param i - index of prefix
191             * @returns prefix of requested index or VM_NO_PREFIX otherwise
192             * @see unitFactor()
193             */
194            virtual MetricPrefix_t unitPrefix(vmuint i) const = 0;
195    
196            /**
197             * Conveniently returns the final mathematical factor that should be
198             * multiplied against the number associated with this unit. This factor
199             * results from the sequence of metric prefixes of this unit.
200             *
201             * @see unitPrefix()
202             */
203            vmfloat unitFactor() const;
204    
205            /**
206             * This is the actual fundamental measuring unit base type of this unit,
207             * which might be either Hertz, second or Bel.
208             *
209             * @returns standard unit type identifier or VM_NO_UNIT if no unit used
210             */
211            virtual StdUnit_t unitType() const = 0;
212    
213            /**
214             * Returns the actual mathematical factor represented by the passed
215             * @a prefix argument.
216             */
217            static vmfloat unitFactor(MetricPrefix_t prefix);
218    
219            /**
220             * Returns the actual mathematical factor represented by the passed
221             * two @a prefix1 and @a prefix2 arguments.
222             */
223            static vmfloat unitFactor(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
224        };
225    
226      /** @brief Virtual machine expression      /** @brief Virtual machine expression
227       *       *
# Line 157  namespace LinuxSampler { Line 286  namespace LinuxSampler {
286           * expressions to an array expression for you, instead this method will           * expressions to an array expression for you, instead this method will
287           * simply return NULL!           * simply return NULL!
288           *           *
289             * @b Note: this method is currently, and in contrast to its other
290             * counter parts, declared as virtual method. Some deriving classes are
291             * currently using this to override this default implementation in order
292             * to implement an "evaluate now as integer array" behavior. This has
293             * efficiency reasons, however this also currently makes this part of
294             * the API less clean and should thus be addressed in future with
295             * appropriate changes to the API.
296             *
297           * @see exprType()           * @see exprType()
298           */           */
299          VMIntArrayExpr* asIntArray() const;          virtual VMIntArrayExpr* asIntArray() const;
300    
301          /**          /**
302           * Returns true in case this expression can be considered to be a           * Returns true in case this expression can be considered to be a
# Line 199  namespace LinuxSampler { Line 336  namespace LinuxSampler {
336       * abstract method evalInt() to return the actual integer result value of       * abstract method evalInt() to return the actual integer result value of
337       * the expression.       * the expression.
338       */       */
339      class VMIntExpr : virtual public VMExpr {      class VMIntExpr : virtual public VMExpr, virtual public VMUnit {
340      public:      public:
341          /**          /**
342           * Returns the result of this expression as integer (scalar) value.           * Returns the result of this expression as integer (scalar) value.
343           * This abstract method must be implemented by deriving classes.           * This abstract method must be implemented by deriving classes.
344           */           */
345          virtual int evalInt() = 0;          virtual vmint evalInt() = 0;
346    
347            /**
348             * Returns the result of this expression as integer (scalar) value and
349             * thus behaves similar to the previous method, however this overridden
350             * method automatically takes unit prefixes into account and returns a
351             * value corresponding to the expected given unit @a prefix.
352             *
353             * @param prefix - default measurement unit prefix expected by caller
354             */
355            vmint evalInt(MetricPrefix_t prefix);
356    
357            /**
358             * This method behaves like the previous method, just that it takes
359             * a default measurement prefix with two elements (i.e. "milli cents"
360             * for tuning).
361             */
362            vmint evalInt(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
363    
364          /**          /**
365           * Returns always INT_EXPR for instances of this class.           * Returns always INT_EXPR for instances of this class.
366           */           */
367          ExprType_t exprType() const OVERRIDE { return INT_EXPR; }          ExprType_t exprType() const OVERRIDE { return INT_EXPR; }
368    
369            /**
370             * Returns @c true if the value of this expression should be applied
371             * as final value to the respective destination synthesis chain
372             * parameter.
373             *
374             * This property is somewhat special and dedicated for the purpose of
375             * this expression's integer value to be applied as parameter to the
376             * synthesis chain of the sampler (i.e. for altering a filter cutoff
377             * frequency). Now historically and by default all values of scripts are
378             * applied relatively to the sampler's synthesis chain, that is the
379             * synthesis parameter value of a script is multiplied against other
380             * sources for the same synthesis parameter (i.e. an LFO or a dedicated
381             * MIDI controller either hard wired in the engine or defined by the
382             * instrument patch). So by default the resulting actual final synthesis
383             * parameter is a combination of all these sources. This has the
384             * advantage that it creates a very living and dynamic overall sound.
385             *
386             * However sometimes there are requirements by script authors where this
387             * is not what you want. Therefore the NKSP script engine added a
388             * language extension by prefixing a value in scripts with a @c !
389             * character the value will be defined as being the "final" value of the
390             * destination synthesis parameter, so that causes this value to be
391             * applied exclusively, and the values of all other sources are thus
392             * entirely ignored by the sampler's synthesis core as long as this
393             * value is assigned by the script engine as "final" value for the
394             * requested synthesis parameter.
395             */
396            virtual bool isFinal() const = 0;
397      };      };
398    
399      /** @brief Virtual machine string expression      /** @brief Virtual machine string expression
# Line 247  namespace LinuxSampler { Line 430  namespace LinuxSampler {
430           * Returns amount of elements in this array. This abstract method must           * Returns amount of elements in this array. This abstract method must
431           * be implemented by deriving classes.           * be implemented by deriving classes.
432           */           */
433          virtual int arraySize() const = 0;          virtual vmint arraySize() const = 0;
434      };      };
435    
436      /** @brief Virtual Machine Integer Array Expression      /** @brief Virtual Machine Integer Array Expression
# Line 265  namespace LinuxSampler { Line 448  namespace LinuxSampler {
448           *           *
449           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
450           */           */
451          virtual int evalIntElement(uint i) = 0;          virtual vmint evalIntElement(vmuint i) = 0;
452    
453          /**          /**
454           * Changes the current value of an element (given by array element           * Changes the current value of an element (given by array element
# Line 274  namespace LinuxSampler { Line 457  namespace LinuxSampler {
457           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
458           * @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
459           */           */
460          virtual void assignIntElement(uint i, int value) = 0;          virtual void assignIntElement(vmuint i, vmint value) = 0;
461    
462          /**          /**
463           * Returns always INT_ARR_EXPR for instances of this class.           * Returns always INT_ARR_EXPR for instances of this class.
# Line 296  namespace LinuxSampler { Line 479  namespace LinuxSampler {
479           * Returns the amount of arguments going to be passed to the script           * Returns the amount of arguments going to be passed to the script
480           * function.           * function.
481           */           */
482          virtual int argsCount() const = 0;          virtual vmint argsCount() const = 0;
483    
484          /**          /**
485           * Returns the respective argument (requested by argument index @a i) of           * Returns the respective argument (requested by argument index @a i) of
# Line 306  namespace LinuxSampler { Line 489  namespace LinuxSampler {
489           *           *
490           * @param i - function argument index (indexed from left to right)           * @param i - function argument index (indexed from left to right)
491           */           */
492          virtual VMExpr* arg(int i) = 0;          virtual VMExpr* arg(vmint i) = 0;
493      };      };
494    
495      /** @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 370  namespace LinuxSampler { Line 553  namespace LinuxSampler {
553           * script is calling this function with less arguments, the script           * script is calling this function with less arguments, the script
554           * parser will throw a parser error.           * parser will throw a parser error.
555           */           */
556          virtual int minRequiredArgs() const = 0;          virtual vmint minRequiredArgs() const = 0;
557    
558          /**          /**
559           * Maximum amount of function arguments this functions accepts. If a           * Maximum amount of function arguments this functions accepts. If a
560           * script is calling this function with more arguments, the script           * script is calling this function with more arguments, the script
561           * parser will throw a parser error.           * parser will throw a parser error.
562           */           */
563          virtual int maxAllowedArgs() const = 0;          virtual vmint maxAllowedArgs() const = 0;
564    
565          /**          /**
566           * 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 393  namespace LinuxSampler { Line 576  namespace LinuxSampler {
576           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
577           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
578           */           */
579          virtual ExprType_t argType(int iArg) const = 0;          virtual ExprType_t argType(vmint iArg) const = 0;
580    
581          /**          /**
582           * This method is called by the parser to check whether arguments           * This method is called by the parser to check whether arguments
# Line 411  namespace LinuxSampler { Line 594  namespace LinuxSampler {
594           * @return true if the given data type would be accepted for the           * @return true if the given data type would be accepted for the
595           *         respective function argument by the function           *         respective function argument by the function
596           */           */
597          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;          virtual bool acceptsArgType(vmint iArg, ExprType_t type) const = 0;
598    
599            /**
600             * This method is called by the parser to check whether arguments
601             * passed in scripts to this function are accepted by this function. If
602             * a script calls this function with an argument's measuremnt unit type
603             * not accepted by this function, the parser will throw a parser error.
604             *
605             * This default implementation of this method does not accept any
606             * measurement unit. Deriving subclasses would override this method
607             * implementation in case they do accept any measurement unit for its
608             * function arguments.
609             *
610             * @param iArg - index of the function argument in question
611             *               (must be between 0 .. maxAllowedArgs() - 1)
612             * @param type - standard measurement unit data type used for this
613             *               function argument by currently parsed script
614             * @return true if the given standard measurement unit type would be
615             *         accepted for the respective function argument by the function
616             */
617            virtual bool acceptsArgUnitType(vmint iArg, StdUnit_t type) const;
618    
619            /**
620             * This method is called by the parser to check whether arguments
621             * passed in scripts to this function are accepted by this function. If
622             * a script calls this function with a metric unit prefix and metric
623             * prefixes are not accepted for that argument by this function, then
624             * the parser will throw a parser error.
625             *
626             * This default implementation of this method does not accept any
627             * metric prefix. Deriving subclasses would override this method
628             * implementation in case they do accept any metric prefix for its
629             * function arguments.
630             *
631             * @param iArg - index of the function argument in question
632             *               (must be between 0 .. maxAllowedArgs() - 1)
633             * @param type - standard measurement unit data type used for that
634             *               function argument by currently parsed script
635             *
636             * @return true if a metric prefix would be accepted for the respective
637             *         function argument by this function
638             *
639             * @see MetricPrefix_t
640             */
641            virtual bool acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const;
642    
643            /**
644             * This method is called by the parser to check whether arguments
645             * passed in scripts to this function are accepted by this function. If
646             * a script calls this function with an argument that is declared to be
647             * a "final" value and this is not accepted by this function, the parser
648             * will throw a parser error.
649             *
650             * This default implementation of this method does not accept a "final"
651             * value. Deriving subclasses would override this method implementation
652             * in case they do accept a "final" value for its function arguments.
653             *
654             * @param iArg - index of the function argument in question
655             *               (must be between 0 .. maxAllowedArgs() - 1)
656             * @return true if a "final" value would be accepted for the respective
657             *         function argument by the function
658             *
659             * @see VMIntExpr::isFinal()
660             */
661            virtual bool acceptsArgFinal(vmint iArg) const;
662    
663          /**          /**
664           * This method is called by the parser to check whether some arguments           * This method is called by the parser to check whether some arguments
# Line 426  namespace LinuxSampler { Line 673  namespace LinuxSampler {
673           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
674           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
675           */           */
676          virtual bool modifiesArg(int iArg) const = 0;          virtual bool modifiesArg(vmint iArg) const = 0;
677    
678          /**          /**
679           * Implements the actual function execution. This exec() method is           * Implements the actual function execution. This exec() method is
# Line 460  namespace LinuxSampler { Line 707  namespace LinuxSampler {
707    
708      /** @brief Virtual machine relative pointer.      /** @brief Virtual machine relative pointer.
709       *       *
710       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be       * POD base of VMInt64RelPtr, VMInt32RelPtr and VMInt8RelPtr structures. Not
711       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.       * intended to be used directly. Use VMInt64RelPtr, VMInt32RelPtr,
712         * VMInt8RelPtr instead.
713       *       *
714       * @see VMIntRelPtr, VMInt8RelPtr       * @see VMInt64RelPtr, VMInt32RelPtr, VMInt8RelPtr
715       */       */
716      struct VMRelPtr {      struct VMRelPtr {
717          void** base; ///< Base pointer.          void** base; ///< Base pointer.
718          int offset;  ///< Offset (in bytes) relative to base pointer.          vmint offset;  ///< Offset (in bytes) relative to base pointer.
719          bool readonly; ///< Whether the pointed data may be modified or just be read.          bool readonly; ///< Whether the pointed data may be modified or just be read.
720      };      };
721    
722      /** @brief Pointer to built-in VM integer variable (of C/C++ type int).      /** @brief Pointer to built-in VM integer variable (interface class).
723         *
724         * This class acts as an abstract interface to all built-in integer script
725         * variables, independent of their actual native size (i.e. some built-in
726         * script variables are internally using a native int size of 64 bit or 32
727         * bit or 8 bit). The virtual machine is using this interface class instead
728         * of its implementing descendants (VMInt64RelPtr, VMInt32RelPtr,
729         * VMInt8RelPtr) in order for the virtual machine for not being required to
730         * handle each of them differently.
731         */
732        struct VMIntPtr {
733            virtual vmint evalInt() = 0;
734            virtual void assign(vmint i) = 0;
735            virtual bool isAssignable() const = 0;
736        };
737    
738        /** @brief Pointer to built-in VM integer variable (of C/C++ type int64_t).
739         *
740         * Used for defining built-in 64 bit integer script variables.
741         *
742         * @b CAUTION: You may only use this class for pointing to C/C++ variables
743         * of type "int64_t" (thus being exactly 64 bit in size). If the C/C++ int
744         * variable you want to reference is only 32 bit in size then you @b must
745         * use VMInt32RelPtr instead! Respectively for a referenced native variable
746         * with only 8 bit in size you @b must use VMInt8RelPtr instead!
747         *
748         * For efficiency reasons the actual native C/C++ int variable is referenced
749         * by two components here. The actual native int C/C++ variable in memory
750         * is dereferenced at VM run-time by taking the @c base pointer dereference
751         * and adding @c offset bytes. This has the advantage that for a large
752         * number of built-in int variables, only one (or few) base pointer need
753         * to be re-assigned before running a script, instead of updating each
754         * built-in variable each time before a script is executed.
755         *
756         * Refer to DECLARE_VMINT() for example code.
757         *
758         * @see VMInt32RelPtr, VMInt8RelPtr, DECLARE_VMINT()
759         */
760        struct VMInt64RelPtr : VMRelPtr, VMIntPtr {
761            VMInt64RelPtr() {
762                base   = NULL;
763                offset = 0;
764                readonly = false;
765            }
766            VMInt64RelPtr(const VMRelPtr& data) {
767                base   = data.base;
768                offset = data.offset;
769                readonly = false;
770            }
771            vmint evalInt() OVERRIDE {
772                return (vmint)*(int64_t*)&(*(uint8_t**)base)[offset];
773            }
774            void assign(vmint i) OVERRIDE {
775                *(int64_t*)&(*(uint8_t**)base)[offset] = (int64_t)i;
776            }
777            bool isAssignable() const OVERRIDE { return !readonly; }
778        };
779    
780        /** @brief Pointer to built-in VM integer variable (of C/C++ type int32_t).
781       *       *
782       * Used for defining built-in 32 bit integer script variables.       * Used for defining built-in 32 bit integer script variables.
783       *       *
784       * @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
785       * 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
786       * 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
787       * use VMInt8RelPtr instead!       * VMInt64RelPtr instead! Respectively for a referenced native variable with
788         * only 8 bit in size you @b must use VMInt8RelPtr instead!
789       *       *
790       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
791       * 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 490  namespace LinuxSampler { Line 797  namespace LinuxSampler {
797       *       *
798       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
799       *       *
800       * @see VMInt8RelPtr, DECLARE_VMINT()       * @see VMInt64RelPtr, VMInt8RelPtr, DECLARE_VMINT()
801       */       */
802      struct VMIntRelPtr : VMRelPtr {      struct VMInt32RelPtr : VMRelPtr, VMIntPtr {
803          VMIntRelPtr() {          VMInt32RelPtr() {
804              base   = NULL;              base   = NULL;
805              offset = 0;              offset = 0;
806              readonly = false;              readonly = false;
807          }          }
808          VMIntRelPtr(const VMRelPtr& data) {          VMInt32RelPtr(const VMRelPtr& data) {
809              base   = data.base;              base   = data.base;
810              offset = data.offset;              offset = data.offset;
811              readonly = false;              readonly = false;
812          }          }
813          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }          vmint evalInt() OVERRIDE {
814          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }              return (vmint)*(int32_t*)&(*(uint8_t**)base)[offset];
815            }
816            void assign(vmint i) OVERRIDE {
817                *(int32_t*)&(*(uint8_t**)base)[offset] = (int32_t)i;
818            }
819            bool isAssignable() const OVERRIDE { return !readonly; }
820      };      };
821    
822      /** @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 513  namespace LinuxSampler { Line 825  namespace LinuxSampler {
825       *       *
826       * @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
827       * 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
828       * 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
829       * @b must use VMIntRelPtr instead!       * either VMInt32RelPtr for native 32 bit variables or VMInt64RelPtrl for
830         * native 64 bit variables instead!
831       *       *
832       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
833       * 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 526  namespace LinuxSampler { Line 839  namespace LinuxSampler {
839       *       *
840       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
841       *       *
842       * @see VMIntRelPtr, DECLARE_VMINT()       * @see VMIntRel32Ptr, VMIntRel64Ptr, DECLARE_VMINT()
843       */       */
844      struct VMInt8RelPtr : VMIntRelPtr {      struct VMInt8RelPtr : VMRelPtr, VMIntPtr {
845          VMInt8RelPtr() : VMIntRelPtr() {}          VMInt8RelPtr() {
846          VMInt8RelPtr(const VMRelPtr& data) : VMIntRelPtr(data) {}              base   = NULL;
847          virtual int evalInt() OVERRIDE {              offset = 0;
848              return *(uint8_t*)&(*(uint8_t**)base)[offset];              readonly = false;
849            }
850            VMInt8RelPtr(const VMRelPtr& data) {
851                base   = data.base;
852                offset = data.offset;
853                readonly = false;
854          }          }
855          virtual void assign(int i) OVERRIDE {          vmint evalInt() OVERRIDE {
856              *(uint8_t*)&(*(uint8_t**)base)[offset] = i;              return (vmint)*(uint8_t*)&(*(uint8_t**)base)[offset];
857          }          }
858            void assign(vmint i) OVERRIDE {
859                *(uint8_t*)&(*(uint8_t**)base)[offset] = (uint8_t)i;
860            }
861            bool isAssignable() const OVERRIDE { return !readonly; }
862      };      };
863    
864        /** @brief Pointer to built-in VM integer variable (of C/C++ type vmint).
865         *
866         * Use this typedef if the native variable to be pointed to is using the
867         * typedef vmint. If the native C/C++ variable to be pointed to is using
868         * another C/C++ type then better use one of VMInt64RelPtr or VMInt32RelPtr
869         * instead.
870         */
871        typedef VMInt64RelPtr VMIntRelPtr;
872    
873        #if HAVE_CXX_EMBEDDED_PRAGMA_DIAGNOSTICS
874        # define COMPILER_DISABLE_OFFSETOF_WARNING                    \
875            _Pragma("GCC diagnostic push")                            \
876            _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
877        # define COMPILER_RESTORE_OFFSETOF_WARNING \
878            _Pragma("GCC diagnostic pop")
879        #else
880        # define COMPILER_DISABLE_OFFSETOF_WARNING
881        # define COMPILER_RESTORE_OFFSETOF_WARNING
882        #endif
883    
884      /**      /**
885       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr       * Convenience macro for initializing VMInt64RelPtr, VMInt32RelPtr and
886       * structures. Usage example:       * VMInt8RelPtr structures. Usage example:
887       * @code       * @code
888       * struct Foo {       * struct Foo {
889       *   uint8_t a; // native representation of a built-in integer script variable       *   uint8_t a; // native representation of a built-in integer script variable
890       *   int b; // native representation of another built-in integer script variable       *   int64_t b; // native representation of another built-in integer script variable
891       *   int c; // native representation of another built-in integer script variable       *   int64_t c; // native representation of another built-in integer script variable
892       *   uint8_t d; // native representation of another built-in integer script variable       *   uint8_t d; // native representation of another built-in integer script variable
893       * };       * };
894       *       *
# Line 557  namespace LinuxSampler { Line 899  namespace LinuxSampler {
899       * Foo* pFoo;       * Foo* pFoo;
900       *       *
901       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
902       * VMIntRelPtr  varB = DECLARE_VMINT(pFoo, class Foo, b);       * VMInt64RelPtr varB = DECLARE_VMINT(pFoo, class Foo, b);
903       * VMIntRelPtr  varC = DECLARE_VMINT(pFoo, class Foo, c);       * VMInt64RelPtr varC = DECLARE_VMINT(pFoo, class Foo, c);
904       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
905       *       *
906       * pFoo = &foo1;       * pFoo = &foo1;
# Line 581  namespace LinuxSampler { Line 923  namespace LinuxSampler {
923       * complexity inside the sampler engines which provide the actual script       * complexity inside the sampler engines which provide the actual script
924       * functionalities.       * functionalities.
925       */       */
926      #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \      #define DECLARE_VMINT(basePtr, T_struct, T_member) (          \
927          (VMRelPtr) {                                     \          /* Disable offsetof warning, trust us, we are cautios. */ \
928              (void**) &basePtr,                           \          COMPILER_DISABLE_OFFSETOF_WARNING                         \
929              offsetof(T_struct, T_member),                \          (VMRelPtr) {                                              \
930              false                                        \              (void**) &basePtr,                                    \
931          }                                                \              offsetof(T_struct, T_member),                         \
932      )                                                    \              false                                                 \
933            }                                                         \
934            COMPILER_RESTORE_OFFSETOF_WARNING                         \
935        )                                                             \
936    
937      /**      /**
938       * Same as DECLARE_VMINT(), but this one defines the VMIntRelPtr and       * Same as DECLARE_VMINT(), but this one defines the VMInt64RelPtr,
939       * VMInt8RelPtr structures to be of read-only type. That means the script       * VMInt32RelPtr and VMInt8RelPtr structures to be of read-only type.
940       * parser will abort any script at parser time if the script is trying to       * That means the script parser will abort any script at parser time if the
941       * modify such a read-only built-in variable.       * script is trying to modify such a read-only built-in variable.
942       *       *
943       * @b NOTE: this is only intended for built-in read-only variables that       * @b NOTE: this is only intended for built-in read-only variables that
944       * may change during runtime! If your built-in variable's data is rather       * may change during runtime! If your built-in variable's data is rather
# Line 603  namespace LinuxSampler { Line 948  namespace LinuxSampler {
948       * @see ScriptVM::builtInConstIntVariables()       * @see ScriptVM::builtInConstIntVariables()
949       */       */
950      #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \      #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
951          (VMRelPtr) {                                          \          /* Disable offsetof warning, trust us, we are cautios. */ \
952              (void**) &basePtr,                                \          COMPILER_DISABLE_OFFSETOF_WARNING                         \
953              offsetof(T_struct, T_member),                     \          (VMRelPtr) {                                              \
954              true                                              \              (void**) &basePtr,                                    \
955          }                                                     \              offsetof(T_struct, T_member),                         \
956      )                                                         \              true                                                  \
957            }                                                         \
958            COMPILER_RESTORE_OFFSETOF_WARNING                         \
959        )                                                             \
960    
961      /** @brief Built-in VM 8 bit integer array variable.      /** @brief Built-in VM 8 bit integer array variable.
962       *       *
# Line 618  namespace LinuxSampler { Line 966  namespace LinuxSampler {
966       */       */
967      struct VMInt8Array {      struct VMInt8Array {
968          int8_t* data;          int8_t* data;
969          int size;          vmint size;
970            bool readonly; ///< Whether the array data may be modified or just be read.
971    
972          VMInt8Array() : data(NULL), size(0) {}          VMInt8Array() : data(NULL), size(0), readonly(false) {}
973      };      };
974    
975      /** @brief Virtual machine script variable.      /** @brief Virtual machine script variable.
# Line 708  namespace LinuxSampler { Line 1057  namespace LinuxSampler {
1057           * @param expr - new value to be assigned to this variable           * @param expr - new value to be assigned to this variable
1058           */           */
1059          void assignExpr(VMExpr* expr) OVERRIDE {}          void assignExpr(VMExpr* expr) OVERRIDE {}
1060    
1061            virtual ~VMDynVar() {}
1062      };      };
1063    
1064      /** @brief Dynamically executed variable (of integer data type).      /** @brief Dynamically executed variable (of integer data type).
# Line 718  namespace LinuxSampler { Line 1069  namespace LinuxSampler {
1069       */       */
1070      class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {      class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
1071      public:      public:
1072            MetricPrefix_t unitPrefix(vmuint i) const OVERRIDE { return VM_NO_PREFIX; }
1073            StdUnit_t unitType() const OVERRIDE { return VM_NO_UNIT; }
1074            bool isFinal() const OVERRIDE { return false; }
1075      };      };
1076    
1077      /** @brief Dynamically executed variable (of string data type).      /** @brief Dynamically executed variable (of string data type).
# Line 730  namespace LinuxSampler { Line 1084  namespace LinuxSampler {
1084      public:      public:
1085      };      };
1086    
1087        /** @brief Dynamically executed variable (of integer array data type).
1088         *
1089         * This is the base class for all built-in integer array script variables
1090         * whose variable content needs to be provided dynamically by executable
1091         * native code on each script variable access.
1092         */
1093        class VMDynIntArrayVar : virtual public VMDynVar, virtual public VMIntArrayExpr {
1094        public:
1095        };
1096    
1097      /** @brief Provider for built-in script functions and variables.      /** @brief Provider for built-in script functions and variables.
1098       *       *
1099       * Abstract base class defining the high-level interface for all classes       * Abstract base class defining the high-level interface for all classes
# Line 748  namespace LinuxSampler { Line 1112  namespace LinuxSampler {
1112          virtual VMFunction* functionByName(const String& name) = 0;          virtual VMFunction* functionByName(const String& name) = 0;
1113    
1114          /**          /**
1115             * Returns @c true if the passed built-in function is disabled and
1116             * should be ignored by the parser. This method is called by the
1117             * parser on preprocessor level for each built-in function call within
1118             * a script. Accordingly if this method returns @c true, then the
1119             * respective function call is completely filtered out on preprocessor
1120             * level, so that built-in function won't make into the result virtual
1121             * machine representation, nor would expressions of arguments passed to
1122             * that built-in function call be evaluated, nor would any check
1123             * regarding correct usage of the built-in function be performed.
1124             * In other words: a disabled function call ends up as a comment block.
1125             *
1126             * @param fn - built-in function to be checked
1127             * @param ctx - parser context at the position where the built-in
1128             *              function call is located within the script
1129             */
1130            virtual bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) = 0;
1131    
1132            /**
1133           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script variables
1134           * which point to native "int" scalar (usually 32 bit) variables.           * which point to native "int" scalar (usually 32 bit) variables.
1135           */           */
1136          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;          virtual std::map<String,VMIntPtr*> builtInIntVariables() = 0;
1137    
1138          /**          /**
1139           * 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 763  namespace LinuxSampler { Line 1145  namespace LinuxSampler {
1145           * Returns a variable name indexed map of all built-in constant script           * Returns a variable name indexed map of all built-in constant script
1146           * variables, which never change their value at runtime.           * variables, which never change their value at runtime.
1147           */           */
1148          virtual std::map<String,int> builtInConstIntVariables() = 0;          virtual std::map<String,vmint> builtInConstIntVariables() = 0;
1149    
1150          /**          /**
1151           * Returns a variable name indexed map of all built-in dynamic variables,           * Returns a variable name indexed map of all built-in dynamic variables,
# Line 812  namespace LinuxSampler { Line 1194  namespace LinuxSampler {
1194           *           *
1195           * @see ScriptVM::exec()           * @see ScriptVM::exec()
1196           */           */
1197          virtual int suspensionTimeMicroseconds() const = 0;          virtual vmint suspensionTimeMicroseconds() const = 0;
1198    
1199            /**
1200             * Causes all polyphonic variables to be reset to zero values. A
1201             * polyphonic variable is expected to be zero when entering a new event
1202             * handler instance. As an exception the values of polyphonic variables
1203             * shall only be preserved from an note event handler instance to its
1204             * correspending specific release handler instance. So in the latter
1205             * case the script author may pass custom data from the note handler to
1206             * the release handler, but only for the same specific note!
1207             */
1208            virtual void resetPolyphonicData() = 0;
1209    
1210            /**
1211             * Returns amount of virtual machine instructions which have been
1212             * performed the last time when this execution context was executing a
1213             * script. So in case you need the overall amount of instructions
1214             * instead, then you need to add them by yourself after each
1215             * ScriptVM::exec() call.
1216             */
1217            virtual size_t instructionsPerformed() const = 0;
1218    
1219            /**
1220             * Sends a signal to this script execution instance to abort its script
1221             * execution as soon as possible. This method is called i.e. when one
1222             * script execution instance intends to stop another script execution
1223             * instance.
1224             */
1225            virtual void signalAbort() = 0;
1226    
1227            /**
1228             * Copies the current entire execution state from this object to the
1229             * given object. So this can be used to "fork" a new script thread which
1230             * then may run independently with its own polyphonic data for instance.
1231             */
1232            virtual void forkTo(VMExecContext* ectx) const = 0;
1233    
1234            /**
1235             * In case the script called the built-in exit() function and passed a
1236             * value as argument to the exit() function, then this method returns
1237             * the value that had been passed as argument to the exit() function.
1238             * Otherwise if the exit() function has not been called by the script
1239             * or no argument had been passed to the exit() function, then this
1240             * method returns NULL instead.
1241             *
1242             * Currently this is only used for automated test cases against the
1243             * script engine, which return some kind of value in the individual
1244             * test case scripts to check their behaviour in automated way. There
1245             * is no purpose for this mechanism in production use. Accordingly this
1246             * exit result value is @b always completely ignored by the sampler
1247             * engines.
1248             *
1249             * Officially the built-in exit() function does not expect any arguments
1250             * to be passed to its function call, and by default this feature is
1251             * hence disabled and will yield in a parser error unless
1252             * ScriptVM::setExitResultEnabled() was explicitly set.
1253             *
1254             * @see ScriptVM::setExitResultEnabled()
1255             */
1256            virtual VMExpr* exitResult() = 0;
1257      };      };
1258    
1259      /** @brief Script callback for a certain event.      /** @brief Script callback for a certain event.
# Line 844  namespace LinuxSampler { Line 1285  namespace LinuxSampler {
1285      };      };
1286    
1287      /**      /**
1288         * Reflects the precise position and span of a specific code block within
1289         * a script. This is currently only used for the locations of commented
1290         * code blocks due to preprocessor statements, and for parser errors and
1291         * parser warnings.
1292         *
1293         * @see ParserIssue for code locations of parser errors and parser warnings
1294         *
1295         * @see VMParserContext::preprocessorComments() for locations of code which
1296         *      have been filtered out by preprocessor statements
1297         */
1298        struct CodeBlock {
1299            int firstLine; ///< The first line number of this code block within the script (indexed with 1 being the very first line).
1300            int lastLine; ///< The last line number of this code block within the script.
1301            int firstColumn; ///< The first column of this code block within the script (indexed with 1 being the very first column).
1302            int lastColumn; ///< The last column of this code block within the script.
1303        };
1304    
1305        /**
1306       * Encapsulates a noteworty parser issue. This encompasses the type of the       * Encapsulates a noteworty parser issue. This encompasses the type of the
1307       * issue (either a parser error or parser warning), a human readable       * issue (either a parser error or parser warning), a human readable
1308       * explanation text of the error or warning and the location of the       * explanation text of the error or warning and the location of the
1309       * encountered parser issue within the script.       * encountered parser issue within the script.
1310         *
1311         * @see VMSourceToken for processing syntax highlighting instead.
1312       */       */
1313      struct ParserIssue {      struct ParserIssue : CodeBlock {
1314          String txt; ///< Human readable explanation text of the parser issue.          String txt; ///< Human readable explanation text of the parser issue.
         int firstLine; ///< The first line number within the script where this issue was encountered (indexed with 1 being the very first line).  
         int lastLine; ///< The last line number within the script where this issue was encountered.  
         int firstColumn; ///< The first column within the script where this issue was encountered (indexed with 1 being the very first column).  
         int lastColumn; ///< The last column within the script where this issue was encountered.  
1315          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.
1316    
1317          /**          /**
# Line 900  namespace LinuxSampler { Line 1357  namespace LinuxSampler {
1357          return "invalid";          return "invalid";
1358      }      }
1359    
1360        /**
1361         * Convenience function used for converting an StdUnit_t constant to a
1362         * string, i.e. for generating error message by the parser.
1363         */
1364        inline String unitTypeStr(const StdUnit_t& type) {
1365            switch (type) {
1366                case VM_NO_UNIT: return "none";
1367                case VM_SECOND: return "seconds";
1368                case VM_HERTZ: return "Hz";
1369                case VM_BEL: return "Bel";
1370            }
1371            return "invalid";
1372        }
1373    
1374      /** @brief Virtual machine representation of a script.      /** @brief Virtual machine representation of a script.
1375       *       *
1376       * An instance of this abstract base class represents a parsed script,       * An instance of this abstract base class represents a parsed script,
# Line 934  namespace LinuxSampler { Line 1405  namespace LinuxSampler {
1405          virtual std::vector<ParserIssue> warnings() const = 0;          virtual std::vector<ParserIssue> warnings() const = 0;
1406    
1407          /**          /**
1408             * Returns all code blocks of the script which were filtered out by the
1409             * preprocessor.
1410             */
1411            virtual std::vector<CodeBlock> preprocessorComments() const = 0;
1412    
1413            /**
1414           * Returns the translated virtual machine representation of an event           * Returns the translated virtual machine representation of an event
1415           * handler block (i.e. "on note ... end on" code block) within the           * handler block (i.e. "on note ... end on" code block) within the
1416           * parsed script. This translated representation of the event handler           * parsed script. This translated representation of the event handler
# Line 966  namespace LinuxSampler { Line 1443  namespace LinuxSampler {
1443       * This class is not actually used by the sampler itself. It is rather       * This class is not actually used by the sampler itself. It is rather
1444       * provided for external script editor applications. Primary purpose of       * provided for external script editor applications. Primary purpose of
1445       * this class is syntax highlighting for external script editors.       * this class is syntax highlighting for external script editors.
1446         *
1447         * @see ParserIssue for processing compile errors and warnings instead.
1448       */       */
1449      class VMSourceToken {      class VMSourceToken {
1450      public:      public:
# Line 978  namespace LinuxSampler { Line 1457  namespace LinuxSampler {
1457          String text() const;          String text() const;
1458    
1459          // position of token in script          // position of token in script
1460          int firstLine() const; ///< First line this source token is located at in script source code (indexed with 0 being the very first line).          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.
1461          int firstColumn() const; ///< Last line this source token is located at in script source code.          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().
1462    
1463          // base types          // base types
1464          bool isEOF() const;          bool isEOF() const; ///< Returns true in case this source token represents the end of the source code file.
1465          bool isNewLine() const;          bool isNewLine() const; ///< Returns true in case this source token represents a line feed character (i.e. "\n" on Unix systems).
1466          bool isKeyword() const;          bool isKeyword() const; ///< Returns true in case this source token represents a language keyword (i.e. "while", "function", "declare", "on", etc.).
1467          bool isVariableName() const;          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.
1468          bool isIdentifier() const;          bool isIdentifier() const; ///< Returns true in case this source token represents an identifier, which currently always means a function name.
1469          bool isNumberLiteral() const;          bool isNumberLiteral() const; ///< Returns true in case this source token represents a number literal (i.e. 123).
1470          bool isStringLiteral() const;          bool isStringLiteral() const; ///< Returns true in case this source token represents a string literal (i.e. "Some text").
1471          bool isComment() const;          bool isComment() const; ///< Returns true in case this source token represents a source code comment.
1472          bool isPreprocessor() const;          bool isPreprocessor() const; ///< Returns true in case this source token represents a preprocessor statement.
1473          bool isOther() const;          bool isMetricPrefix() const;
1474            bool isStdUnit() const;
1475            bool isOther() const; ///< Returns true in case this source token represents anything else not covered by the token types mentioned above.
1476    
1477          // extended types          // extended types
1478          bool isIntegerVariable() const;          bool isIntegerVariable() const; ///< Returns true in case this source token represents an integer variable name (i.e. "$someIntVariable").
1479          bool isStringVariable() const;          bool isStringVariable() const; ///< Returns true in case this source token represents an string variable name (i.e. "\@someStringVariable").
1480          bool isArrayVariable() const;          bool isArrayVariable() const; ///< Returns true in case this source token represents an array variable name (i.e. "%someArryVariable").
1481          bool isEventHandlerName() const;          bool isEventHandlerName() const; ///< Returns true in case this source token represents an event handler name (i.e. "note", "release", "controller").
1482    
1483          VMSourceToken& operator=(const VMSourceToken& other);          VMSourceToken& operator=(const VMSourceToken& other);
1484    

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

  ViewVC Help
Powered by ViewVC