/[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 3034 by schoenebeck, Mon Oct 31 00:05:00 2016 UTC revision 3585 by schoenebeck, Fri Aug 30 17:51:24 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 18  Line 19 
19  #include <vector>  #include <vector>
20  #include <map>  #include <map>
21  #include <stddef.h> // offsetof()  #include <stddef.h> // offsetof()
22    #include <functional> // std::function<>
23    
24  namespace LinuxSampler {  namespace LinuxSampler {
25    
26      /**      /**
27         * Native data type used by the script engine both internally, as well as
28         * for all integer data types used by scripts (i.e. for all $foo variables
29         * in NKSP scripts). Note that this is different from the original KSP which
30         * is limited to 32 bit for integer variables in KSP scripts.
31         */
32        typedef int64_t vmint;
33    
34        /**
35         * Native data type used internally by the script engine for all unsigned
36         * integer types. This type is currently not exposed to scripts.
37         */
38        typedef uint64_t vmuint;
39    
40        /**
41         * Native data type used by the script engine both internally for floating
42         * point data, as well as for all @c real data types used by scripts (i.e.
43         * for all ~foo variables in NKSP scripts).
44         */
45        typedef float vmfloat;
46    
47        /**
48       * Identifies the type of a noteworthy issue identified by the script       * Identifies the type of a noteworthy issue identified by the script
49       * parser. That's either a parser error or parser warning.       * parser. That's either a parser error or parser warning.
50       */       */
# Line 43  namespace LinuxSampler { Line 66  namespace LinuxSampler {
66          INT_ARR_EXPR, ///< integer array expression          INT_ARR_EXPR, ///< integer array expression
67          STRING_EXPR, ///< string expression          STRING_EXPR, ///< string expression
68          STRING_ARR_EXPR, ///< string array expression          STRING_ARR_EXPR, ///< string array expression
69            REAL_EXPR, ///< floating point (scalar) expression
70            REAL_ARR_EXPR, ///< floating point array expression
71      };      };
72    
73      /** @brief Result flags of a script statement or script function call.      /** @brief Result flags of a script statement or script function call.
# Line 80  namespace LinuxSampler { Line 105  namespace LinuxSampler {
105       *       *
106       * Identifies one of the possible event handler callback types defined by       * Identifies one of the possible event handler callback types defined by
107       * the NKSP script language.       * the NKSP script language.
108         *
109         * IMPORTANT: this type is forced to be emitted as int32_t type ATM, because
110         * that's the native size expected by the built-in instrument script
111         * variable bindings (see occurrences of VMInt32RelPtr and DECLARE_VMINT
112         * respectively. A native type mismatch between the two could lead to
113         * undefined behavior! Background: By definition the C/C++ compiler is free
114         * to choose a bit size for individual enums which it might find
115         * appropriate, which is usually decided by the compiler according to the
116         * biggest enum constant value defined (in practice it is usually 32 bit).
117       */       */
118      enum VMEventHandlerType_t {      enum VMEventHandlerType_t : int32_t {
119          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.
120          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.
121          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.
122          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.
123      };      };
124    
125        /**
126         * All metric unit prefixes (actually just scale factors) supported by this
127         * script engine.
128         */
129        enum MetricPrefix_t {
130            VM_NO_PREFIX = 0, ///< = 1
131            VM_KILO,          ///< = 10^3, short 'k'
132            VM_HECTO,         ///< = 10^2, short 'h'
133            VM_DECA,          ///< = 10, short 'da'
134            VM_DECI,          ///< = 10^-1, short 'd'
135            VM_CENTI,         ///< = 10^-2, short 'c' (this is also used for tuning "cents")
136            VM_MILLI,         ///< = 10^-3, short 'm'
137            VM_MICRO,         ///< = 10^-6, short 'u'
138        };
139    
140        /**
141         * This constant is used for comparison with Unit::unitFactor() to check
142         * whether a number does have any metric unit prefix at all.
143         *
144         * @see Unit::unitFactor()
145         */
146        static const vmfloat VM_NO_FACTOR = vmfloat(1);
147    
148        /**
149         * All measurement unit types supported by this script engine.
150         *
151         * @e Note: there is no standard unit "cents" here (for pitch/tuning), use
152         * @c VM_CENTI for the latter instad. That's because the commonly cited
153         * "cents" unit is actually no measurement unit type but rather a metric
154         * unit prefix.
155         *
156         * @see MetricPrefix_t
157         */
158        enum StdUnit_t {
159            VM_NO_UNIT = 0, ///< No unit used, the number is just an abstract number.
160            VM_SECOND,      ///< Measuring time.
161            VM_HERTZ,       ///< Measuring frequency.
162            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).
163        };
164    
165        //TODO: see Unit::hasUnitFactorEver()
166        enum EverTriState_t {
167            VM_NEVER = 0,
168            VM_MAYBE,
169            VM_ALWAYS,
170        };
171    
172      // just symbol prototyping      // just symbol prototyping
173      class VMIntExpr;      class VMIntExpr;
174        class VMRealExpr;
175      class VMStringExpr;      class VMStringExpr;
176        class VMNumberExpr;
177        class VMArrayExpr;
178      class VMIntArrayExpr;      class VMIntArrayExpr;
179        class VMRealArrayExpr;
180      class VMStringArrayExpr;      class VMStringArrayExpr;
181        class VMParserContext;
182    
183        /** @brief Virtual machine standard measuring unit.
184         *
185         * Abstract base class representing standard measurement units throughout
186         * the script engine. These might be e.g. "dB" (deci Bel) for loudness,
187         * "Hz" (Hertz) for frequencies or "s" for "seconds". These unit types can
188         * combined with metric prefixes, for instance "kHz" (kilo Hertz),
189         * "us" (micro second), etc.
190         *
191         * Originally the script engine only supported abstract integer values for
192         * controlling any synthesis parameter or built-in function argument or
193         * variable. Under certain situations it makes sense though for an
194         * instrument script author to provide values in real, standard measurement
195         * units to provide a more natural and intuitive approach for writing
196         * instrument scripts, for example by setting the frequency of some LFO
197         * directly to "20Hz" or reducing loudness by "-4.2dB". Hence support for
198         * standard units in scripts was added as an extension to the NKSP script
199         * engine.
200         *
201         * So a unit consists of 1) a sequence of metric prefixes as scale factor
202         * (e.g. "k" for kilo) and 2) the actual unit type (e.g. "Hz" for Hertz).
203         * The unit type is a constant feature of number literals and variables, so
204         * once a variable was declared with a unit type (or no unit type at all)
205         * then that unit type of that variable cannot be changed for the entire
206         * life time of the script. This is different from the unit's metric
207         * prefix(es) of variables which may freely be changed at runtime.
208         */
209        class VMUnit {
210        public:
211            /**
212             * Returns the metric prefix(es) of this unit as unit factor. A metric
213             * prefix essentially is just a mathematical scale factor that should be
214             * applied to the number associated with the measurement unit. Consider
215             * a string literal in an NKSP script like '3kHz' where 'k' (kilo) is
216             * the metric prefix, which essentically is a scale factor of 1000.
217             *
218             * Usually a unit either has exactly none or one metric prefix, but note
219             * that there might also be units with more than one prefix, for example
220             * @c mdB (milli deci Bel) is used sometimes which has two prefixes. The
221             * latter is an exception though and more than two prefixes is currently
222             * not supported by the script engine.
223             *
224             * The factor returned by this method is the final mathematical factor
225             * that should be multiplied against the number associated with this
226             * unit. This factor results from the sequence of metric prefixes of
227             * this unit.
228             *
229             * @see MetricPrefix_t, hasUnitFactorNow(), hasUnitFactorEver(),
230             *      VM_NO_FACTOR
231             * @returns current metric unit factor
232             */
233            virtual vmfloat unitFactor() const = 0;
234    
235            //TODO: this still needs to be implemented in tree.h/.pp, built-in functions and as 2nd pass of parser appropriately
236            /*virtual*/ EverTriState_t hasUnitFactorEver() const { return VM_NEVER; }
237    
238            /**
239             * Whether this unit currently does have any metric unit prefix.
240             *
241             * This is actually just a convenience method which returns @c true if
242             * unitFactor() is not @c 1.0.
243             *
244             * @see MetricPrefix_t, unitFactor(), hasUnitFactorEver(), VM_NO_FACTOR
245             * @returns @c true if this unit currently has any metric prefix
246             */
247            bool hasUnitFactorNow() const;
248    
249            /**
250             * This is the actual fundamental measuring unit base type of this unit,
251             * which might be either Hertz, second or Bel.
252             *
253             * Note that a number without a unit type may still have metric
254             * prefixes.
255             *
256             * @returns standard unit type identifier or VM_NO_UNIT if no unit type
257             *          is used for this object
258             */
259            virtual StdUnit_t unitType() const = 0;
260    
261            /**
262             * Returns the actual mathematical factor represented by the passed
263             * @a prefix argument.
264             */
265            static vmfloat unitFactor(MetricPrefix_t prefix);
266    
267            /**
268             * Returns the actual mathematical factor represented by the passed
269             * two @a prefix1 and @a prefix2 arguments.
270             *
271             * @returns scale factor of given metric unit prefixes
272             */
273            static vmfloat unitFactor(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
274    
275            /**
276             * Returns the actual mathematical factor represented by the passed
277             * @a prefixes array. The passed array should always be terminated by a
278             * VM_NO_PREFIX value as last element.
279             *
280             * @param prefixes - sequence of metric prefixes
281             * @param size - max. amount of elements of array @a prefixes
282             * @returns scale factor of given metric unit prefixes
283             */
284            static vmfloat unitFactor(const MetricPrefix_t* prefixes, vmuint size = 2);
285        };
286    
287      /** @brief Virtual machine expression      /** @brief Virtual machine expression
288       *       *
# Line 125  namespace LinuxSampler { Line 315  namespace LinuxSampler {
315           * if this expression is i.e. actually a string expression like "12",           * if this expression is i.e. actually a string expression like "12",
316           * calling asInt() will @b not cast that numerical string expression to           * calling asInt() will @b not cast that numerical string expression to
317           * an integer expression 12 for you, instead this method will simply           * an integer expression 12 for you, instead this method will simply
318           * return NULL!           * return NULL! Same applies if this expression is actually a real
319             * number expression: asInt() would return NULL in that case as well.
320           *           *
321           * @see exprType()           * @see exprType(), asReal(), asNumber()
322           */           */
323          VMIntExpr* asInt() const;          VMIntExpr* asInt() const;
324    
325          /**          /**
326             * In case this expression is a real number (floating point) expression,
327             * then this method returns a casted pointer to that VMRealExpr object.
328             * It returns NULL if this expression is not a real number expression.
329             *
330             * @b Note: type casting performed by this method is strict! That means
331             * if this expression is i.e. actually a string expression like "12",
332             * calling asReal() will @b not cast that numerical string expression to
333             * a real number expression 12.0 for you, instead this method will
334             * simply return NULL! Same applies if this expression is actually an
335             * integer expression: asReal() would return NULL in that case as well.
336             *
337             * @see exprType(), asInt(), asNumber()
338             */
339            VMRealExpr* asReal() const;
340    
341            /**
342             * In case this expression is a scalar number expression, that is either
343             * an integer (scalar) expression or a real number (floating point
344             * scalar) expression, then this method returns a casted pointer to that
345             * VMNumberExpr base class object. It returns NULL if this
346             * expression is neither an integer (scalar), nor a real number (scalar)
347             * expression.
348             *
349             * Since the methods asInt() and asReal() are very strict, this method
350             * is provided as convenience access in case only very general
351             * information (e.g. which standard measurement unit is being used or
352             * whether final operator being effective to this expression) is
353             * intended to be retrieved of this scalar number expression independent
354             * from whether this expression is actually an integer or a real number
355             * expression.
356             *
357             * @see exprType(), asInt(), asReal()
358             */
359            VMNumberExpr* asNumber() const;
360    
361            /**
362           * In case this expression is a string expression, then this method           * In case this expression is a string expression, then this method
363           * returns a casted pointer to that VMStringExpr object. It returns NULL           * returns a casted pointer to that VMStringExpr object. It returns NULL
364           * if this expression is not a string expression.           * if this expression is not a string expression.
# Line 152  namespace LinuxSampler { Line 379  namespace LinuxSampler {
379           * returns NULL if this expression is not an integer array expression.           * returns NULL if this expression is not an integer array expression.
380           *           *
381           * @b Note: type casting performed by this method is strict! That means           * @b Note: type casting performed by this method is strict! That means
382           * if this expression is i.e. an integer expression or a string           * if this expression is i.e. an integer scalar expression, a real
383           * expression, calling asIntArray() will @b not cast those scalar           * number expression or a string expression, calling asIntArray() will
384           * expressions to an array expression for you, instead this method will           * @b not cast those expressions to an integer array expression for you,
385           * simply return NULL!           * instead this method will simply return NULL!
386             *
387             * @b Note: this method is currently, and in contrast to its other
388             * counter parts, declared as virtual method. Some deriving classes are
389             * currently using this to override this default implementation in order
390             * to implement an "evaluate now as integer array" behavior. This has
391             * efficiency reasons, however this also currently makes this part of
392             * the API less clean and should thus be addressed in future with
393             * appropriate changes to the API.
394           *           *
395           * @see exprType()           * @see exprType()
396           */           */
397          VMIntArrayExpr* asIntArray() const;          virtual VMIntArrayExpr* asIntArray() const;
398    
399            /**
400             * In case this expression is a real number (floating point) array
401             * expression, then this method returns a casted pointer to that
402             * VMRealArrayExpr object. It returns NULL if this expression is not a
403             * real number array expression.
404             *
405             * @b Note: type casting performed by this method is strict! That means
406             * if this expression is i.e. a real number scalar expression, an
407             * integer expression or a string expression, calling asRealArray() will
408             * @b not cast those scalar expressions to a real number array
409             * expression for you, instead this method will simply return NULL!
410             *
411             * @b Note: this method is currently, and in contrast to its other
412             * counter parts, declared as virtual method. Some deriving classes are
413             * currently using this to override this default implementation in order
414             * to implement an "evaluate now as real number array" behavior. This
415             * has efficiency reasons, however this also currently makes this part
416             * of the API less clean and should thus be addressed in future with
417             * appropriate changes to the API.
418             *
419             * @see exprType()
420             */
421            virtual VMRealArrayExpr* asRealArray() const;
422    
423            /**
424             * This is an alternative to calling either asIntArray() or
425             * asRealArray(). This method here might be used if the fundamental
426             * scalar data type (real or integer) of the array is not relevant,
427             * i.e. for just getting the size of the array. Since all as*() methods
428             * here are very strict regarding type casting, this asArray() method
429             * sometimes can reduce code complexity.
430             *
431             * Likewise calling this method only returns a valid pointer if the
432             * expression is some array type (currently either integer array or real
433             * number array). For any other expression type this method will return
434             * NULL instead.
435             *
436             * @see exprType()
437             */
438            VMArrayExpr* asArray() const;
439    
440          /**          /**
441           * 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 192  namespace LinuxSampler { Line 468  namespace LinuxSampler {
468          bool isModifyable() const;          bool isModifyable() const;
469      };      };
470    
471        /** @brief Virtual machine scalar number expression
472         *
473         * This is the abstract base class for integer (scalar) expressions and
474         * real number (floating point scalar) expressions of scripts.
475         */
476        class VMNumberExpr : virtual public VMExpr, virtual public VMUnit {
477        public:
478            /**
479             * Returns @c true if the value of this expression should be applied
480             * as final value to the respective destination synthesis chain
481             * parameter.
482             *
483             * This property is somewhat special and dedicated for the purpose of
484             * this expression's (integer or real number) value to be applied as
485             * parameter to the synthesis chain of the sampler (i.e. for altering a
486             * filter cutoff frequency). Now historically and by default all values
487             * of scripts are applied relatively to the sampler's synthesis chain,
488             * that is the synthesis parameter value of a script is multiplied
489             * against other sources for the same synthesis parameter (i.e. an LFO
490             * or a dedicated MIDI controller either hard wired in the engine or
491             * defined by the instrument patch). So by default the resulting actual
492             * final synthesis parameter is a combination of all these sources. This
493             * has the advantage that it creates a very living and dynamic overall
494             * sound.
495             *
496             * However sometimes there are requirements by script authors where this
497             * is not what you want. Therefore the NKSP script engine added a
498             * language extension by prefixing a value in scripts with a @c !
499             * character the value will be defined as being the "final" value of the
500             * destination synthesis parameter, so that causes this value to be
501             * applied exclusively, and the values of all other sources are thus
502             * entirely ignored by the sampler's synthesis core as long as this
503             * value is assigned by the script engine as "final" value for the
504             * requested synthesis parameter.
505             */
506            virtual bool isFinal() const = 0;
507    
508            /**
509             * Calling this method evaluates the expression and returns the value
510             * of the expression as integer. If this scalar number expression is a
511             * real number expression then this method automatically casts the value
512             * from real number to integer.
513             */
514            vmint evalCastInt();
515    
516            /**
517             * Calling this method evaluates the expression and returns the value
518             * of the expression as integer and thus behaves similar to the previous
519             * method, however this overridden method automatically takes unit
520             * prefixes into account and returns a converted value corresponding to
521             * the given unit @a prefix expected by the caller.
522             *
523             * Example: Assume this expression was an integer expression '12kHz'
524             * then calling this method as @c evalCastInt(VM_MILLI) would return
525             * the value @c 12000000.
526             *
527             * @param prefix - measuring unit prefix expected for result by caller
528             */
529            vmint evalCastInt(MetricPrefix_t prefix);
530    
531            /**
532             * This method behaves like the previous method, just that it takes a
533             * measuring unit prefix with two elements (e.g. "milli cents" for
534             * tuning).
535             *
536             * @param prefix1 - 1st measuring unit prefix element expected by caller
537             * @param prefix2 - 2nd measuring unit prefix element expected by caller
538             */
539            vmint evalCastInt(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
540    
541            /**
542             * Calling this method evaluates the expression and returns the value
543             * of the expression as real number. If this scalar number expression is
544             * an integer expression then this method automatically casts the value
545             * from integer to real number.
546             */
547            vmfloat evalCastReal();
548    
549            /**
550             * Calling this method evaluates the expression and returns the value
551             * of the expression as real number and thus behaves similar to the
552             * previous method, however this overridden method automatically takes
553             * unit prefixes into account and returns a converted value
554             * corresponding to the given unit @a prefix expected by the caller.
555             *
556             * Example: Assume this expression was an integer expression '8ms' then
557             * calling this method as @c evalCastReal(VM_NO_PREFIX) would return the
558             * value @c 0.008.
559             *
560             * @param prefix - measuring unit prefix expected for result by caller
561             */
562            vmfloat evalCastReal(MetricPrefix_t prefix);
563    
564            /**
565             * This method behaves like the previous method, just that it takes a
566             * measuring unit prefix with two elements (e.g. "milli cents" for
567             * tuning).
568             *
569             * @param prefix1 - 1st measuring unit prefix element expected by caller
570             * @param prefix2 - 2nd measuring unit prefix element expected by caller
571             */
572            vmfloat evalCastReal(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
573        };
574    
575      /** @brief Virtual machine integer expression      /** @brief Virtual machine integer expression
576       *       *
577       * This is the abstract base class for all expressions inside scripts which       * This is the abstract base class for all expressions inside scripts which
# Line 199  namespace LinuxSampler { Line 579  namespace LinuxSampler {
579       * abstract method evalInt() to return the actual integer result value of       * abstract method evalInt() to return the actual integer result value of
580       * the expression.       * the expression.
581       */       */
582      class VMIntExpr : virtual public VMExpr {      class VMIntExpr : virtual public VMNumberExpr {
583      public:      public:
584          /**          /**
585           * Returns the result of this expression as integer (scalar) value.           * Returns the result of this expression as integer (scalar) value.
586           * This abstract method must be implemented by deriving classes.           * This abstract method must be implemented by deriving classes.
587           */           */
588          virtual int evalInt() = 0;          virtual vmint evalInt() = 0;
589    
590            /**
591             * Returns the result of this expression as integer (scalar) value and
592             * thus behaves similar to the previous method, however this overridden
593             * method automatically takes unit prefixes into account and returns a
594             * value corresponding to the expected given unit @a prefix.
595             *
596             * @param prefix - default measurement unit prefix expected by caller
597             */
598            vmint evalInt(MetricPrefix_t prefix);
599    
600            /**
601             * This method behaves like the previous method, just that it takes
602             * a default measurement prefix with two elements (i.e. "milli cents"
603             * for tuning).
604             */
605            vmint evalInt(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
606    
607          /**          /**
608           * Returns always INT_EXPR for instances of this class.           * Returns always INT_EXPR for instances of this class.
# Line 213  namespace LinuxSampler { Line 610  namespace LinuxSampler {
610          ExprType_t exprType() const OVERRIDE { return INT_EXPR; }          ExprType_t exprType() const OVERRIDE { return INT_EXPR; }
611      };      };
612    
613        /** @brief Virtual machine real number (floating point scalar) expression
614         *
615         * This is the abstract base class for all expressions inside scripts which
616         * evaluate to a real number (floating point scalar) value. Deriving classes
617         * implement the abstract method evalReal() to return the actual floating
618         * point result value of the expression.
619         */
620        class VMRealExpr : virtual public VMNumberExpr {
621        public:
622            /**
623             * Returns the result of this expression as real number (floating point
624             * scalar) value. This abstract method must be implemented by deriving
625             * classes.
626             */
627            virtual vmfloat evalReal() = 0;
628    
629            /**
630             * Returns the result of this expression as real number (floating point
631             * scalar) value and thus behaves similar to the previous method,
632             * however this overridden method automatically takes unit prefixes into
633             * account and returns a value corresponding to the expected given unit
634             * @a prefix.
635             *
636             * @param prefix - default measurement unit prefix expected by caller
637             */
638            vmfloat evalReal(MetricPrefix_t prefix);
639    
640            /**
641             * This method behaves like the previous method, just that it takes
642             * a default measurement prefix with two elements (i.e. "milli cents"
643             * for tuning).
644             */
645            vmfloat evalReal(MetricPrefix_t prefix1, MetricPrefix_t prefix2);
646    
647            /**
648             * Returns always REAL_EXPR for instances of this class.
649             */
650            ExprType_t exprType() const OVERRIDE { return REAL_EXPR; }
651        };
652    
653      /** @brief Virtual machine string expression      /** @brief Virtual machine string expression
654       *       *
655       * This is the abstract base class for all expressions inside scripts which       * This is the abstract base class for all expressions inside scripts which
# Line 247  namespace LinuxSampler { Line 684  namespace LinuxSampler {
684           * Returns amount of elements in this array. This abstract method must           * Returns amount of elements in this array. This abstract method must
685           * be implemented by deriving classes.           * be implemented by deriving classes.
686           */           */
687          virtual int arraySize() const = 0;          virtual vmint arraySize() const = 0;
688        };
689    
690        /** @brief Virtual Machine Number Array Expression
691         *
692         * This is the abstract base class for all expressions which either evaluate
693         * to an integer array or real number array.
694         */
695        class VMNumberArrayExpr : virtual public VMArrayExpr {
696        public:
697            /**
698             * Returns the metric unit factor of the requested array element.
699             *
700             * @param i - array element index (must be between 0 .. arraySize() - 1)
701             * @see VMUnit::unitFactor() for details about metric unit factors
702             */
703            virtual vmfloat unitFactorOfElement(vmuint i) const = 0;
704    
705            /**
706             * Changes the current unit factor of the array element given by element
707             * index @a i.
708             *
709             * @param i - array element index (must be between 0 .. arraySize() - 1)
710             * @param factor - new unit factor to be assigned
711             * @see VMUnit::unitFactor() for details about metric unit factors
712             */
713            virtual void assignElementUnitFactor(vmuint i, vmfloat factor) = 0;
714      };      };
715    
716      /** @brief Virtual Machine Integer Array Expression      /** @brief Virtual Machine Integer Array Expression
# Line 257  namespace LinuxSampler { Line 720  namespace LinuxSampler {
720       * abstract methods arraySize(), evalIntElement() and assignIntElement() to       * abstract methods arraySize(), evalIntElement() and assignIntElement() to
721       * access the individual integer array values.       * access the individual integer array values.
722       */       */
723      class VMIntArrayExpr : virtual public VMArrayExpr {      class VMIntArrayExpr : virtual public VMNumberArrayExpr {
724      public:      public:
725          /**          /**
726           * Returns the (scalar) integer value of the array element given by           * Returns the (scalar) integer value of the array element given by
# Line 265  namespace LinuxSampler { Line 728  namespace LinuxSampler {
728           *           *
729           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
730           */           */
731          virtual int evalIntElement(uint i) = 0;          virtual vmint evalIntElement(vmuint i) = 0;
732    
733          /**          /**
734           * 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 737  namespace LinuxSampler {
737           * @param i - array element index (must be between 0 .. arraySize() - 1)           * @param i - array element index (must be between 0 .. arraySize() - 1)
738           * @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
739           */           */
740          virtual void assignIntElement(uint i, int value) = 0;          virtual void assignIntElement(vmuint i, vmint value) = 0;
741    
742          /**          /**
743           * Returns always INT_ARR_EXPR for instances of this class.           * Returns always INT_ARR_EXPR for instances of this class.
# Line 282  namespace LinuxSampler { Line 745  namespace LinuxSampler {
745          ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; }          ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; }
746      };      };
747    
748        /** @brief Virtual Machine Real Number Array Expression
749         *
750         * This is the abstract base class for all expressions inside scripts which
751         * evaluate to an array of real numbers (floating point values). Deriving
752         * classes implement the abstract methods arraySize(), evalRealElement() and
753         * assignRealElement() to access the array's individual real numbers.
754         */
755        class VMRealArrayExpr : virtual public VMNumberArrayExpr {
756        public:
757            /**
758             * Returns the (scalar) real mumber (floating point value) of the array
759             * element given by element index @a i.
760             *
761             * @param i - array element index (must be between 0 .. arraySize() - 1)
762             */
763            virtual vmfloat evalRealElement(vmuint i) = 0;
764    
765            /**
766             * Changes the current value of an element (given by array element
767             * index @a i) of this real number array.
768             *
769             * @param i - array element index (must be between 0 .. arraySize() - 1)
770             * @param value - new real number value to be assigned to that array element
771             */
772            virtual void assignRealElement(vmuint i, vmfloat value) = 0;
773    
774            /**
775             * Returns always REAL_ARR_EXPR for instances of this class.
776             */
777            ExprType_t exprType() const OVERRIDE { return REAL_ARR_EXPR; }
778        };
779    
780      /** @brief Arguments (parameters) for being passed to a built-in script function.      /** @brief Arguments (parameters) for being passed to a built-in script function.
781       *       *
782       * An argument or a set of arguments passed to a script function are       * An argument or a set of arguments passed to a script function are
# Line 296  namespace LinuxSampler { Line 791  namespace LinuxSampler {
791           * Returns the amount of arguments going to be passed to the script           * Returns the amount of arguments going to be passed to the script
792           * function.           * function.
793           */           */
794          virtual int argsCount() const = 0;          virtual vmint argsCount() const = 0;
795    
796          /**          /**
797           * 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 801  namespace LinuxSampler {
801           *           *
802           * @param i - function argument index (indexed from left to right)           * @param i - function argument index (indexed from left to right)
803           */           */
804          virtual VMExpr* arg(int i) = 0;          virtual VMExpr* arg(vmint i) = 0;
805      };      };
806    
807      /** @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 362  namespace LinuxSampler { Line 857  namespace LinuxSampler {
857          /**          /**
858           * Script data type of the function's return value. If the function does           * Script data type of the function's return value. If the function does
859           * not return any value (void), then it returns EMPTY_EXPR here.           * not return any value (void), then it returns EMPTY_EXPR here.
860             *
861             * Some functions may have a different return type depending on the
862             * arguments to be passed to this function. That's what the @a args
863             * parameter is for, so that the method implementation can look ahead
864             * of what kind of parameters are going to be passed to the built-in
865             * function later on in order to decide which return value type would
866             * be used and returned by the function accordingly in that case.
867             *
868             * @param args - function arguments going to be passed for executing
869             *               this built-in function later on
870             */
871            virtual ExprType_t returnType(VMFnArgs* args) = 0;
872    
873            /**
874             * Standard measuring unit type of the function's result value
875             * (e.g. second, Hertz).
876             *
877             * Some functions may have a different standard measuring unit type for
878             * their return value depending on the arguments to be passed to this
879             * function. That's what the @a args parameter is for, so that the
880             * method implementation can look ahead of what kind of parameters are
881             * going to be passed to the built-in function later on in order to
882             * decide which return value type would be used and returned by the
883             * function accordingly in that case.
884             *
885             * @param args - function arguments going to be passed for executing
886             *               this built-in function later on
887             * @see Unit for details about standard measuring units
888           */           */
889          virtual ExprType_t returnType() = 0;          virtual StdUnit_t returnUnitType(VMFnArgs* args) = 0;
890    
891            /**
892             * Whether the result value returned by this built-in function is
893             * considered to be a 'final' value.
894             *
895             * Some functions may have a different 'final' feature for their return
896             * value depending on the arguments to be passed to this function.
897             * That's what the @a args parameter is for, so that the method
898             * implementation can look ahead of what kind of parameters are going to
899             * be passed to the built-in function later on in order to decide which
900             * return value type would be used and returned by the function
901             * accordingly in that case.
902             *
903             * @param args - function arguments going to be passed for executing
904             *               this built-in function later on
905             * @see VMNumberExpr::isFinal() for details about 'final' values
906             */
907            virtual bool returnsFinal(VMFnArgs* args) = 0;
908    
909          /**          /**
910           * Minimum amount of function arguments this function accepts. If a           * Minimum amount of function arguments this function accepts. If a
911           * script is calling this function with less arguments, the script           * script is calling this function with less arguments, the script
912           * parser will throw a parser error.           * parser will throw a parser error.
913           */           */
914          virtual int minRequiredArgs() const = 0;          virtual vmint minRequiredArgs() const = 0;
915    
916          /**          /**
917           * Maximum amount of function arguments this functions accepts. If a           * Maximum amount of function arguments this functions accepts. If a
918           * script is calling this function with more arguments, the script           * script is calling this function with more arguments, the script
919           * parser will throw a parser error.           * parser will throw a parser error.
920           */           */
921          virtual int maxAllowedArgs() const = 0;          virtual vmint maxAllowedArgs() const = 0;
922    
923          /**          /**
924           * Script data type of the function's @c iArg 'th function argument.           * This method is called by the parser to check whether arguments
925           * The information provided here is less strong than acceptsArgType().           * passed in scripts to this function are accepted by this function. If
926           * The parser will compare argument data types provided in scripts by           * a script calls this function with an argument's data type not
927           * calling acceptsArgType(). The return value of argType() is used by the           * accepted by this function, the parser will throw a parser error.
928           * parser instead to show an appropriate parser error which data type           *
929           * this function usually expects as "default" data type. Reason: a           * The parser will also use this method to assemble a list of actually
930           * function may accept multiple data types for a certain function           * supported data types accepted by this built-in function for the
931           * argument and would automatically cast the passed argument value in           * function argument in question, that is to provide an appropriate and
932           * that case to the type it actually needs.           * precise parser error message in such cases.
933           *           *
934           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
935           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
936             * @param type - script data type used for this function argument by
937             *               currently parsed script
938             * @return true if the given data type would be accepted for the
939             *         respective function argument by the function
940           */           */
941          virtual ExprType_t argType(int iArg) const = 0;          virtual bool acceptsArgType(vmint iArg, ExprType_t type) const = 0;
942    
943          /**          /**
944           * This method is called by the parser to check whether arguments           * This method is called by the parser to check whether arguments
945           * passed in scripts to this function are accepted by this function. If           * passed in scripts to this function are accepted by this function. If
946           * a script calls this function with an argument's data type not           * a script calls this function with an argument's measuremnt unit type
947           * accepted by this function, the parser will throw a parser error. On           * not accepted by this function, the parser will throw a parser error.
948           * such errors the data type returned by argType() will be used to           *
949           * assemble an appropriate error message regarding the precise misusage           * This default implementation of this method does not accept any
950           * of the built-in function.           * measurement unit. Deriving subclasses would override this method
951             * implementation in case they do accept any measurement unit for its
952             * function arguments.
953           *           *
954           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
955           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
956           * @param type - script data type used for this function argument by           * @param type - standard measurement unit data type used for this
957           *               currently parsed script           *               function argument by currently parsed script
958           * @return true if the given data type would be accepted for the           * @return true if the given standard measurement unit type would be
959           *         respective function argument by the function           *         accepted for the respective function argument by the function
960             */
961            virtual bool acceptsArgUnitType(vmint iArg, StdUnit_t type) const;
962    
963            /**
964             * This method is called by the parser to check whether arguments
965             * passed in scripts to this function are accepted by this function. If
966             * a script calls this function with a metric unit prefix and metric
967             * prefixes are not accepted for that argument by this function, then
968             * the parser will throw a parser error.
969             *
970             * This default implementation of this method does not accept any
971             * metric prefix. Deriving subclasses would override this method
972             * implementation in case they do accept any metric prefix for its
973             * function arguments.
974             *
975             * @param iArg - index of the function argument in question
976             *               (must be between 0 .. maxAllowedArgs() - 1)
977             * @param type - standard measurement unit data type used for that
978             *               function argument by currently parsed script
979             *
980             * @return true if a metric prefix would be accepted for the respective
981             *         function argument by this function
982             *
983             * @see MetricPrefix_t
984             */
985            virtual bool acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const;
986    
987            /**
988             * This method is called by the parser to check whether arguments
989             * passed in scripts to this function are accepted by this function. If
990             * a script calls this function with an argument that is declared to be
991             * a "final" value and this is not accepted by this function, the parser
992             * will throw a parser error.
993             *
994             * This default implementation of this method does not accept a "final"
995             * value. Deriving subclasses would override this method implementation
996             * in case they do accept a "final" value for its function arguments.
997             *
998             * @param iArg - index of the function argument in question
999             *               (must be between 0 .. maxAllowedArgs() - 1)
1000             * @return true if a "final" value would be accepted for the respective
1001             *         function argument by the function
1002             *
1003             * @see VMNumberExpr::isFinal(), returnsFinal()
1004           */           */
1005          virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;          virtual bool acceptsArgFinal(vmint iArg) const;
1006    
1007          /**          /**
1008           * 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 1017  namespace LinuxSampler {
1017           * @param iArg - index of the function argument in question           * @param iArg - index of the function argument in question
1018           *               (must be between 0 .. maxAllowedArgs() - 1)           *               (must be between 0 .. maxAllowedArgs() - 1)
1019           */           */
1020          virtual bool modifiesArg(int iArg) const = 0;          virtual bool modifiesArg(vmint iArg) const = 0;
1021    
1022            /**
1023             * This method is called by the parser to let the built-in function
1024             * perform its own, individual parse time checks on the arguments to be
1025             * passed to the built-in function. So this method is the place for
1026             * implementing custom checks which are very specific to the individual
1027             * built-in function's purpose and its individual requirements.
1028             *
1029             * For instance the built-in 'in_range()' function uses this method to
1030             * check whether the last 2 of their 3 arguments are of same data type
1031             * and if not it triggers a parser error. 'in_range()' also checks
1032             * whether all of its 3 arguments do have the same standard measuring
1033             * unit type and likewise raises a parser error if not.
1034             *
1035             * For less critical issues built-in functions may also raise parser
1036             * warnings instead.
1037             *
1038             * It is recommended that classes implementing (that is overriding) this
1039             * method should always call their super class's implementation of this
1040             * method to ensure their potential parse time checks are always
1041             * performed as well.
1042             *
1043             * @param args - function arguments going to be passed for executing
1044             *               this built-in function later on
1045             * @param err - the parser's error handler to be called by this method
1046             *              implementation to trigger a parser error with the
1047             *              respective error message text
1048             * @param wrn - the parser's warning handler to be called by this method
1049             *              implementation to trigger a parser warning with the
1050             *              respective warning message text
1051             */
1052            virtual void checkArgs(VMFnArgs* args,
1053                                   std::function<void(String)> err,
1054                                   std::function<void(String)> wrn);
1055    
1056          /**          /**
1057           * Implements the actual function execution. This exec() method is           * Implements the actual function execution. This exec() method is
# Line 460  namespace LinuxSampler { Line 1085  namespace LinuxSampler {
1085    
1086      /** @brief Virtual machine relative pointer.      /** @brief Virtual machine relative pointer.
1087       *       *
1088       * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be       * POD base of VMInt64RelPtr, VMInt32RelPtr and VMInt8RelPtr structures. Not
1089       * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.       * intended to be used directly. Use VMInt64RelPtr, VMInt32RelPtr,
1090         * VMInt8RelPtr instead.
1091       *       *
1092       * @see VMIntRelPtr, VMInt8RelPtr       * @see VMInt64RelPtr, VMInt32RelPtr, VMInt8RelPtr
1093       */       */
1094      struct VMRelPtr {      struct VMRelPtr {
1095          void** base; ///< Base pointer.          void** base; ///< Base pointer.
1096          int offset;  ///< Offset (in bytes) relative to base pointer.          vmint offset;  ///< Offset (in bytes) relative to base pointer.
1097          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.
1098      };      };
1099    
1100      /** @brief Pointer to built-in VM integer variable (of C/C++ type int).      /** @brief Pointer to built-in VM integer variable (interface class).
1101         *
1102         * This class acts as an abstract interface to all built-in integer script
1103         * variables, independent of their actual native size (i.e. some built-in
1104         * script variables are internally using a native int size of 64 bit or 32
1105         * bit or 8 bit). The virtual machine is using this interface class instead
1106         * of its implementing descendants (VMInt64RelPtr, VMInt32RelPtr,
1107         * VMInt8RelPtr) in order for the virtual machine for not being required to
1108         * handle each of them differently.
1109         */
1110        struct VMIntPtr {
1111            virtual vmint evalInt() = 0;
1112            virtual void assign(vmint i) = 0;
1113            virtual bool isAssignable() const = 0;
1114        };
1115    
1116        /** @brief Pointer to built-in VM integer variable (of C/C++ type int64_t).
1117         *
1118         * Used for defining built-in 64 bit integer script variables.
1119         *
1120         * @b CAUTION: You may only use this class for pointing to C/C++ variables
1121         * of type "int64_t" (thus being exactly 64 bit in size). If the C/C++ int
1122         * variable you want to reference is only 32 bit in size then you @b must
1123         * use VMInt32RelPtr instead! Respectively for a referenced native variable
1124         * with only 8 bit in size you @b must use VMInt8RelPtr instead!
1125         *
1126         * For efficiency reasons the actual native C/C++ int variable is referenced
1127         * by two components here. The actual native int C/C++ variable in memory
1128         * is dereferenced at VM run-time by taking the @c base pointer dereference
1129         * and adding @c offset bytes. This has the advantage that for a large
1130         * number of built-in int variables, only one (or few) base pointer need
1131         * to be re-assigned before running a script, instead of updating each
1132         * built-in variable each time before a script is executed.
1133         *
1134         * Refer to DECLARE_VMINT() for example code.
1135         *
1136         * @see VMInt32RelPtr, VMInt8RelPtr, DECLARE_VMINT()
1137         */
1138        struct VMInt64RelPtr : VMRelPtr, VMIntPtr {
1139            VMInt64RelPtr() {
1140                base   = NULL;
1141                offset = 0;
1142                readonly = false;
1143            }
1144            VMInt64RelPtr(const VMRelPtr& data) {
1145                base   = data.base;
1146                offset = data.offset;
1147                readonly = false;
1148            }
1149            vmint evalInt() OVERRIDE {
1150                return (vmint)*(int64_t*)&(*(uint8_t**)base)[offset];
1151            }
1152            void assign(vmint i) OVERRIDE {
1153                *(int64_t*)&(*(uint8_t**)base)[offset] = (int64_t)i;
1154            }
1155            bool isAssignable() const OVERRIDE { return !readonly; }
1156        };
1157    
1158        /** @brief Pointer to built-in VM integer variable (of C/C++ type int32_t).
1159       *       *
1160       * Used for defining built-in 32 bit integer script variables.       * Used for defining built-in 32 bit integer script variables.
1161       *       *
1162       * @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
1163       * 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
1164       * 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
1165       * use VMInt8RelPtr instead!       * VMInt64RelPtr instead! Respectively for a referenced native variable with
1166         * only 8 bit in size you @b must use VMInt8RelPtr instead!
1167       *       *
1168       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
1169       * 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 1175  namespace LinuxSampler {
1175       *       *
1176       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
1177       *       *
1178       * @see VMInt8RelPtr, DECLARE_VMINT()       * @see VMInt64RelPtr, VMInt8RelPtr, DECLARE_VMINT()
1179       */       */
1180      struct VMIntRelPtr : VMRelPtr {      struct VMInt32RelPtr : VMRelPtr, VMIntPtr {
1181          VMIntRelPtr() {          VMInt32RelPtr() {
1182              base   = NULL;              base   = NULL;
1183              offset = 0;              offset = 0;
1184              readonly = false;              readonly = false;
1185          }          }
1186          VMIntRelPtr(const VMRelPtr& data) {          VMInt32RelPtr(const VMRelPtr& data) {
1187              base   = data.base;              base   = data.base;
1188              offset = data.offset;              offset = data.offset;
1189              readonly = false;              readonly = false;
1190          }          }
1191          virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }          vmint evalInt() OVERRIDE {
1192          virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }              return (vmint)*(int32_t*)&(*(uint8_t**)base)[offset];
1193            }
1194            void assign(vmint i) OVERRIDE {
1195                *(int32_t*)&(*(uint8_t**)base)[offset] = (int32_t)i;
1196            }
1197            bool isAssignable() const OVERRIDE { return !readonly; }
1198      };      };
1199    
1200      /** @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 1203  namespace LinuxSampler {
1203       *       *
1204       * @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
1205       * 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
1206       * 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
1207       * @b must use VMIntRelPtr instead!       * either VMInt32RelPtr for native 32 bit variables or VMInt64RelPtrl for
1208         * native 64 bit variables instead!
1209       *       *
1210       * For efficiency reasons the actual native C/C++ int variable is referenced       * For efficiency reasons the actual native C/C++ int variable is referenced
1211       * 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 1217  namespace LinuxSampler {
1217       *       *
1218       * Refer to DECLARE_VMINT() for example code.       * Refer to DECLARE_VMINT() for example code.
1219       *       *
1220       * @see VMIntRelPtr, DECLARE_VMINT()       * @see VMIntRel32Ptr, VMIntRel64Ptr, DECLARE_VMINT()
1221       */       */
1222      struct VMInt8RelPtr : VMIntRelPtr {      struct VMInt8RelPtr : VMRelPtr, VMIntPtr {
1223          VMInt8RelPtr() : VMIntRelPtr() {}          VMInt8RelPtr() {
1224          VMInt8RelPtr(const VMRelPtr& data) : VMIntRelPtr(data) {}              base   = NULL;
1225          virtual int evalInt() OVERRIDE {              offset = 0;
1226              return *(uint8_t*)&(*(uint8_t**)base)[offset];              readonly = false;
1227            }
1228            VMInt8RelPtr(const VMRelPtr& data) {
1229                base   = data.base;
1230                offset = data.offset;
1231                readonly = false;
1232          }          }
1233          virtual void assign(int i) OVERRIDE {          vmint evalInt() OVERRIDE {
1234              *(uint8_t*)&(*(uint8_t**)base)[offset] = i;              return (vmint)*(uint8_t*)&(*(uint8_t**)base)[offset];
1235          }          }
1236            void assign(vmint i) OVERRIDE {
1237                *(uint8_t*)&(*(uint8_t**)base)[offset] = (uint8_t)i;
1238            }
1239            bool isAssignable() const OVERRIDE { return !readonly; }
1240      };      };
1241    
1242        /** @brief Pointer to built-in VM integer variable (of C/C++ type vmint).
1243         *
1244         * Use this typedef if the native variable to be pointed to is using the
1245         * typedef vmint. If the native C/C++ variable to be pointed to is using
1246         * another C/C++ type then better use one of VMInt64RelPtr or VMInt32RelPtr
1247         * instead.
1248         */
1249        typedef VMInt64RelPtr VMIntRelPtr;
1250    
1251        #if HAVE_CXX_EMBEDDED_PRAGMA_DIAGNOSTICS
1252        # define COMPILER_DISABLE_OFFSETOF_WARNING                    \
1253            _Pragma("GCC diagnostic push")                            \
1254            _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
1255        # define COMPILER_RESTORE_OFFSETOF_WARNING \
1256            _Pragma("GCC diagnostic pop")
1257        #else
1258        # define COMPILER_DISABLE_OFFSETOF_WARNING
1259        # define COMPILER_RESTORE_OFFSETOF_WARNING
1260        #endif
1261    
1262      /**      /**
1263       * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr       * Convenience macro for initializing VMInt64RelPtr, VMInt32RelPtr and
1264       * structures. Usage example:       * VMInt8RelPtr structures. Usage example:
1265       * @code       * @code
1266       * struct Foo {       * struct Foo {
1267       *   uint8_t a; // native representation of a built-in integer script variable       *   uint8_t a; // native representation of a built-in integer script variable
1268       *   int b; // native representation of another built-in integer script variable       *   int64_t b; // native representation of another built-in integer script variable
1269       *   int c; // native representation of another built-in integer script variable       *   int64_t c; // native representation of another built-in integer script variable
1270       *   uint8_t d; // native representation of another built-in integer script variable       *   uint8_t d; // native representation of another built-in integer script variable
1271       * };       * };
1272       *       *
# Line 557  namespace LinuxSampler { Line 1277  namespace LinuxSampler {
1277       * Foo* pFoo;       * Foo* pFoo;
1278       *       *
1279       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);       * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
1280       * VMIntRelPtr  varB = DECLARE_VMINT(pFoo, class Foo, b);       * VMInt64RelPtr varB = DECLARE_VMINT(pFoo, class Foo, b);
1281       * VMIntRelPtr  varC = DECLARE_VMINT(pFoo, class Foo, c);       * VMInt64RelPtr varC = DECLARE_VMINT(pFoo, class Foo, c);
1282       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);       * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
1283       *       *
1284       * pFoo = &foo1;       * pFoo = &foo1;
# Line 583  namespace LinuxSampler { Line 1303  namespace LinuxSampler {
1303       */       */
1304      #define DECLARE_VMINT(basePtr, T_struct, T_member) (          \      #define DECLARE_VMINT(basePtr, T_struct, T_member) (          \
1305          /* Disable offsetof warning, trust us, we are cautios. */ \          /* Disable offsetof warning, trust us, we are cautios. */ \
1306          _Pragma("GCC diagnostic push")                            \          COMPILER_DISABLE_OFFSETOF_WARNING                         \
         _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")  \  
1307          (VMRelPtr) {                                              \          (VMRelPtr) {                                              \
1308              (void**) &basePtr,                                    \              (void**) &basePtr,                                    \
1309              offsetof(T_struct, T_member),                         \              offsetof(T_struct, T_member),                         \
1310              false                                                 \              false                                                 \
1311          }                                                         \          }                                                         \
1312          _Pragma("GCC diagnostic pop")                             \          COMPILER_RESTORE_OFFSETOF_WARNING                         \
1313      )                                                             \      )                                                             \
1314    
1315      /**      /**
1316       * Same as DECLARE_VMINT(), but this one defines the VMIntRelPtr and       * Same as DECLARE_VMINT(), but this one defines the VMInt64RelPtr,
1317       * VMInt8RelPtr structures to be of read-only type. That means the script       * VMInt32RelPtr and VMInt8RelPtr structures to be of read-only type.
1318       * 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
1319       * modify such a read-only built-in variable.       * script is trying to modify such a read-only built-in variable.
1320       *       *
1321       * @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
1322       * 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 608  namespace LinuxSampler { Line 1327  namespace LinuxSampler {
1327       */       */
1328      #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \      #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
1329          /* Disable offsetof warning, trust us, we are cautios. */ \          /* Disable offsetof warning, trust us, we are cautios. */ \
1330          _Pragma("GCC diagnostic push")                            \          COMPILER_DISABLE_OFFSETOF_WARNING                         \
         _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")  \  
1331          (VMRelPtr) {                                              \          (VMRelPtr) {                                              \
1332              (void**) &basePtr,                                    \              (void**) &basePtr,                                    \
1333              offsetof(T_struct, T_member),                         \              offsetof(T_struct, T_member),                         \
1334              true                                                  \              true                                                  \
1335          }                                                         \          }                                                         \
1336          _Pragma("GCC diagnostic pop")                             \          COMPILER_RESTORE_OFFSETOF_WARNING                         \
1337      )                                                             \      )                                                             \
1338    
1339      /** @brief Built-in VM 8 bit integer array variable.      /** @brief Built-in VM 8 bit integer array variable.
1340       *       *
1341       * Used for defining built-in integer array script variables (8 bit per       * Used for defining built-in integer array script variables (8 bit per
1342       * array element). Currently there is no support for any other kind of array       * array element). Currently there is no support for any other kind of
1343       * type. So all integer arrays of scripts use 8 bit data types.       * built-in array type. So all built-in integer arrays accessed by scripts
1344         * use 8 bit data types.
1345       */       */
1346      struct VMInt8Array {      struct VMInt8Array {
1347          int8_t* data;          int8_t* data;
1348          int size;          vmint size;
1349            bool readonly; ///< Whether the array data may be modified or just be read.
1350    
1351          VMInt8Array() : data(NULL), size(0) {}          VMInt8Array() : data(NULL), size(0), readonly(false) {}
1352      };      };
1353    
1354      /** @brief Virtual machine script variable.      /** @brief Virtual machine script variable.
1355       *       *
1356       * Common interface for all variables accessed in scripts.       * Common interface for all variables accessed in scripts, independent of
1357         * their precise data type.
1358       */       */
1359      class VMVariable : virtual public VMExpr {      class VMVariable : virtual public VMExpr {
1360      public:      public:
# Line 654  namespace LinuxSampler { Line 1375  namespace LinuxSampler {
1375           */           */
1376          virtual void assignExpr(VMExpr* expr) = 0;          virtual void assignExpr(VMExpr* expr) = 0;
1377      };      };
1378        
1379      /** @brief Dynamically executed variable (abstract base class).      /** @brief Dynamically executed variable (abstract base class).
1380       *       *
1381       * Interface for the implementation of a dynamically generated content of       * Interface for the implementation of a dynamically generated content of
# Line 728  namespace LinuxSampler { Line 1449  namespace LinuxSampler {
1449       */       */
1450      class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {      class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
1451      public:      public:
1452            vmfloat unitFactor() const OVERRIDE { return VM_NO_FACTOR; }
1453            StdUnit_t unitType() const OVERRIDE { return VM_NO_UNIT; }
1454            bool isFinal() const OVERRIDE { return false; }
1455      };      };
1456    
1457      /** @brief Dynamically executed variable (of string data type).      /** @brief Dynamically executed variable (of string data type).
# Line 740  namespace LinuxSampler { Line 1464  namespace LinuxSampler {
1464      public:      public:
1465      };      };
1466    
1467        /** @brief Dynamically executed variable (of integer array data type).
1468         *
1469         * This is the base class for all built-in integer array script variables
1470         * whose variable content needs to be provided dynamically by executable
1471         * native code on each script variable access.
1472         */
1473        class VMDynIntArrayVar : virtual public VMDynVar, virtual public VMIntArrayExpr {
1474        public:
1475        };
1476    
1477      /** @brief Provider for built-in script functions and variables.      /** @brief Provider for built-in script functions and variables.
1478       *       *
1479       * Abstract base class defining the high-level interface for all classes       * Abstract base class defining the high-level interface for all classes
# Line 758  namespace LinuxSampler { Line 1492  namespace LinuxSampler {
1492          virtual VMFunction* functionByName(const String& name) = 0;          virtual VMFunction* functionByName(const String& name) = 0;
1493    
1494          /**          /**
1495             * Returns @c true if the passed built-in function is disabled and
1496             * should be ignored by the parser. This method is called by the
1497             * parser on preprocessor level for each built-in function call within
1498             * a script. Accordingly if this method returns @c true, then the
1499             * respective function call is completely filtered out on preprocessor
1500             * level, so that built-in function won't make into the result virtual
1501             * machine representation, nor would expressions of arguments passed to
1502             * that built-in function call be evaluated, nor would any check
1503             * regarding correct usage of the built-in function be performed.
1504             * In other words: a disabled function call ends up as a comment block.
1505             *
1506             * @param fn - built-in function to be checked
1507             * @param ctx - parser context at the position where the built-in
1508             *              function call is located within the script
1509             */
1510            virtual bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) = 0;
1511    
1512            /**
1513           * Returns a variable name indexed map of all built-in script variables           * Returns a variable name indexed map of all built-in script variables
1514           * which point to native "int" scalar (usually 32 bit) variables.           * which point to native "int" scalar (usually 32 bit) variables.
1515           */           */
1516          virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;          virtual std::map<String,VMIntPtr*> builtInIntVariables() = 0;
1517    
1518          /**          /**
1519           * 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 773  namespace LinuxSampler { Line 1525  namespace LinuxSampler {
1525           * Returns a variable name indexed map of all built-in constant script           * Returns a variable name indexed map of all built-in constant script
1526           * variables, which never change their value at runtime.           * variables, which never change their value at runtime.
1527           */           */
1528          virtual std::map<String,int> builtInConstIntVariables() = 0;          virtual std::map<String,vmint> builtInConstIntVariables() = 0;
1529    
1530          /**          /**
1531           * 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 822  namespace LinuxSampler { Line 1574  namespace LinuxSampler {
1574           *           *
1575           * @see ScriptVM::exec()           * @see ScriptVM::exec()
1576           */           */
1577          virtual int suspensionTimeMicroseconds() const = 0;          virtual vmint suspensionTimeMicroseconds() const = 0;
1578    
1579            /**
1580             * Causes all polyphonic variables to be reset to zero values. A
1581             * polyphonic variable is expected to be zero when entering a new event
1582             * handler instance. As an exception the values of polyphonic variables
1583             * shall only be preserved from an note event handler instance to its
1584             * correspending specific release handler instance. So in the latter
1585             * case the script author may pass custom data from the note handler to
1586             * the release handler, but only for the same specific note!
1587             */
1588            virtual void resetPolyphonicData() = 0;
1589    
1590            /**
1591             * Returns amount of virtual machine instructions which have been
1592             * performed the last time when this execution context was executing a
1593             * script. So in case you need the overall amount of instructions
1594             * instead, then you need to add them by yourself after each
1595             * ScriptVM::exec() call.
1596             */
1597            virtual size_t instructionsPerformed() const = 0;
1598    
1599            /**
1600             * Sends a signal to this script execution instance to abort its script
1601             * execution as soon as possible. This method is called i.e. when one
1602             * script execution instance intends to stop another script execution
1603             * instance.
1604             */
1605            virtual void signalAbort() = 0;
1606    
1607            /**
1608             * Copies the current entire execution state from this object to the
1609             * given object. So this can be used to "fork" a new script thread which
1610             * then may run independently with its own polyphonic data for instance.
1611             */
1612            virtual void forkTo(VMExecContext* ectx) const = 0;
1613    
1614            /**
1615             * In case the script called the built-in exit() function and passed a
1616             * value as argument to the exit() function, then this method returns
1617             * the value that had been passed as argument to the exit() function.
1618             * Otherwise if the exit() function has not been called by the script
1619             * or no argument had been passed to the exit() function, then this
1620             * method returns NULL instead.
1621             *
1622             * Currently this is only used for automated test cases against the
1623             * script engine, which return some kind of value in the individual
1624             * test case scripts to check their behaviour in automated way. There
1625             * is no purpose for this mechanism in production use. Accordingly this
1626             * exit result value is @b always completely ignored by the sampler
1627             * engines.
1628             *
1629             * Officially the built-in exit() function does not expect any arguments
1630             * to be passed to its function call, and by default this feature is
1631             * hence disabled and will yield in a parser error unless
1632             * ScriptVM::setExitResultEnabled() was explicitly set.
1633             *
1634             * @see ScriptVM::setExitResultEnabled()
1635             */
1636            virtual VMExpr* exitResult() = 0;
1637      };      };
1638    
1639      /** @brief Script callback for a certain event.      /** @brief Script callback for a certain event.
# Line 854  namespace LinuxSampler { Line 1665  namespace LinuxSampler {
1665      };      };
1666    
1667      /**      /**
1668         * Reflects the precise position and span of a specific code block within
1669         * a script. This is currently only used for the locations of commented
1670         * code blocks due to preprocessor statements, and for parser errors and
1671         * parser warnings.
1672         *
1673         * @see ParserIssue for code locations of parser errors and parser warnings
1674         *
1675         * @see VMParserContext::preprocessorComments() for locations of code which
1676         *      have been filtered out by preprocessor statements
1677         */
1678        struct CodeBlock {
1679            int firstLine; ///< The first line number of this code block within the script (indexed with 1 being the very first line).
1680            int lastLine; ///< The last line number of this code block within the script.
1681            int firstColumn; ///< The first column of this code block within the script (indexed with 1 being the very first column).
1682            int lastColumn; ///< The last column of this code block within the script.
1683        };
1684    
1685        /**
1686       * Encapsulates a noteworty parser issue. This encompasses the type of the       * Encapsulates a noteworty parser issue. This encompasses the type of the
1687       * issue (either a parser error or parser warning), a human readable       * issue (either a parser error or parser warning), a human readable
1688       * explanation text of the error or warning and the location of the       * explanation text of the error or warning and the location of the
# Line 861  namespace LinuxSampler { Line 1690  namespace LinuxSampler {
1690       *       *
1691       * @see VMSourceToken for processing syntax highlighting instead.       * @see VMSourceToken for processing syntax highlighting instead.
1692       */       */
1693      struct ParserIssue {      struct ParserIssue : CodeBlock {
1694          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.  
1695          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.
1696    
1697          /**          /**
# Line 906  namespace LinuxSampler { Line 1731  namespace LinuxSampler {
1731              case EMPTY_EXPR: return "empty";              case EMPTY_EXPR: return "empty";
1732              case INT_EXPR: return "integer";              case INT_EXPR: return "integer";
1733              case INT_ARR_EXPR: return "integer array";              case INT_ARR_EXPR: return "integer array";
1734                case REAL_EXPR: return "real number";
1735                case REAL_ARR_EXPR: return "real number array";
1736              case STRING_EXPR: return "string";              case STRING_EXPR: return "string";
1737              case STRING_ARR_EXPR: return "string array";              case STRING_ARR_EXPR: return "string array";
1738          }          }
1739          return "invalid";          return "invalid";
1740      }      }
1741    
1742        /**
1743         * Returns @c true in case the passed data type is some array data type.
1744         */
1745        inline bool isArray(const ExprType_t& type) {
1746            return type == INT_ARR_EXPR || type == REAL_ARR_EXPR ||
1747                   type == STRING_ARR_EXPR;
1748        }
1749    
1750        /**
1751         * Returns @c true in case the passed data type is some scalar number type
1752         * (i.e. not an array and not a string).
1753         */
1754        inline bool isNumber(const ExprType_t& type) {
1755            return type == INT_EXPR || type == REAL_EXPR;
1756        }
1757    
1758        /**
1759         * Convenience function used for converting an StdUnit_t constant to a
1760         * string, i.e. for generating error message by the parser.
1761         */
1762        inline String unitTypeStr(const StdUnit_t& type) {
1763            switch (type) {
1764                case VM_NO_UNIT: return "none";
1765                case VM_SECOND: return "seconds";
1766                case VM_HERTZ: return "Hz";
1767                case VM_BEL: return "Bel";
1768            }
1769            return "invalid";
1770        }
1771    
1772      /** @brief Virtual machine representation of a script.      /** @brief Virtual machine representation of a script.
1773       *       *
1774       * An instance of this abstract base class represents a parsed script,       * An instance of this abstract base class represents a parsed script,
# Line 946  namespace LinuxSampler { Line 1803  namespace LinuxSampler {
1803          virtual std::vector<ParserIssue> warnings() const = 0;          virtual std::vector<ParserIssue> warnings() const = 0;
1804    
1805          /**          /**
1806             * Returns all code blocks of the script which were filtered out by the
1807             * preprocessor.
1808             */
1809            virtual std::vector<CodeBlock> preprocessorComments() const = 0;
1810    
1811            /**
1812           * Returns the translated virtual machine representation of an event           * Returns the translated virtual machine representation of an event
1813           * handler block (i.e. "on note ... end on" code block) within the           * handler block (i.e. "on note ... end on" code block) within the
1814           * parsed script. This translated representation of the event handler           * parsed script. This translated representation of the event handler
# Line 1005  namespace LinuxSampler { Line 1868  namespace LinuxSampler {
1868          bool isStringLiteral() const; ///< Returns true in case this source token represents a string literal (i.e. "Some text").          bool isStringLiteral() const; ///< Returns true in case this source token represents a string literal (i.e. "Some text").
1869          bool isComment() const; ///< Returns true in case this source token represents a source code comment.          bool isComment() const; ///< Returns true in case this source token represents a source code comment.
1870          bool isPreprocessor() const; ///< Returns true in case this source token represents a preprocessor statement.          bool isPreprocessor() const; ///< Returns true in case this source token represents a preprocessor statement.
1871            bool isMetricPrefix() const;
1872            bool isStdUnit() const;
1873          bool isOther() const; ///< Returns true in case this source token represents anything else not covered by the token types mentioned above.          bool isOther() const; ///< Returns true in case this source token represents anything else not covered by the token types mentioned above.
1874    
1875          // extended types          // extended types
1876          bool isIntegerVariable() const; ///< Returns true in case this source token represents an integer variable name (i.e. "$someIntVariable").          bool isIntegerVariable() const; ///< Returns true in case this source token represents an integer variable name (i.e. "$someIntVariable").
1877            bool isRealVariable() const; ///< Returns true in case this source token represents a floating point variable name (i.e. "~someRealVariable").
1878          bool isStringVariable() const; ///< Returns true in case this source token represents an string variable name (i.e. "\@someStringVariable").          bool isStringVariable() const; ///< Returns true in case this source token represents an string variable name (i.e. "\@someStringVariable").
1879          bool isArrayVariable() const; ///< Returns true in case this source token represents an array variable name (i.e. "%someArryVariable").          bool isIntArrayVariable() const; ///< Returns true in case this source token represents an integer array variable name (i.e. "%someArrayVariable").
1880            bool isRealArrayVariable() const; ///< Returns true in case this source token represents a real number array variable name (i.e. "?someArrayVariable").
1881            bool isArrayVariable() const DEPRECATED_API; ///< Returns true in case this source token represents an @b integer array variable name (i.e. "%someArrayVariable"). @deprecated This method will be removed, use isIntArrayVariable() instead.
1882          bool isEventHandlerName() const; ///< Returns true in case this source token represents an event handler name (i.e. "note", "release", "controller").          bool isEventHandlerName() const; ///< Returns true in case this source token represents an event handler name (i.e. "note", "release", "controller").
1883    
1884          VMSourceToken& operator=(const VMSourceToken& other);          VMSourceToken& operator=(const VMSourceToken& other);

Legend:
Removed from v.3034  
changed lines
  Added in v.3585

  ViewVC Help
Powered by ViewVC