/[svn]/linuxsampler/trunk/src/scriptvm/common.h
ViewVC logotype

Annotation of /linuxsampler/trunk/src/scriptvm/common.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3562 - (hide annotations) (download) (as text)
Fri Aug 23 12:51:58 2019 UTC (4 years, 7 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 68891 byte(s)
* NKSP script editor API: Added support for detecting standard unit tokens
  and their potential metric prefix token.

1 schoenebeck 2581 /*
2 schoenebeck 3551 * Copyright (c) 2014-2019 Christian Schoenebeck
3 schoenebeck 2581 *
4     * http://www.linuxsampler.org
5     *
6     * This file is part of LinuxSampler and released under the same terms.
7     * See README file for details.
8     */
9    
10     // This header defines data types shared between the VM core implementation
11     // (inside the current source directory) and other parts of the sampler
12 schoenebeck 3292 // (located at other source directories). It also acts as public API of the
13     // Real-Time script engine for other applications.
14 schoenebeck 2581
15     #ifndef LS_INSTR_SCRIPT_PARSER_COMMON_H
16     #define LS_INSTR_SCRIPT_PARSER_COMMON_H
17    
18     #include "../common/global.h"
19 schoenebeck 2588 #include <vector>
20 schoenebeck 2594 #include <map>
21     #include <stddef.h> // offsetof()
22 schoenebeck 2581
23     namespace LinuxSampler {
24 schoenebeck 2727
25     /**
26 schoenebeck 3557 * 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 schoenebeck 3561 * 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 schoenebeck 2727 * Identifies the type of a noteworthy issue identified by the script
47     * parser. That's either a parser error or parser warning.
48     */
49 schoenebeck 2581 enum ParserIssueType_t {
50 schoenebeck 2727 PARSER_ERROR, ///< Script parser encountered an error, the script cannot be executed.
51     PARSER_WARNING ///< Script parser encountered a warning, the script may be executed if desired, but the script may not necessarily behave as originally intended by the script author.
52 schoenebeck 2581 };
53    
54 schoenebeck 2727 /** @brief Expression's data type.
55     *
56     * Identifies to which data type an expression within a script evaluates to.
57     * This can for example reflect the data type of script function arguments,
58     * script function return values, but also the resulting data type of some
59     * mathematical formula within a script.
60     */
61 schoenebeck 2581 enum ExprType_t {
62 schoenebeck 2727 EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value (the built-in wait() or message() functions for instance)
63     INT_EXPR, ///< integer (scalar) expression
64     INT_ARR_EXPR, ///< integer array expression
65     STRING_EXPR, ///< string expression
66     STRING_ARR_EXPR, ///< string array expression
67 schoenebeck 2581 };
68    
69 schoenebeck 2727 /** @brief Result flags of a script statement or script function call.
70     *
71     * A set of bit flags which provide informations about the success or
72     * failure of a statement within a script. That's also especially used for
73     * providing informations about success / failure of a call to a built-in
74     * script function. The virtual machine evaluates these flags during runtime
75     * to decide whether it should i.e. stop or suspend execution of a script.
76     *
77     * Since these are bit flags, these constants are bitwise combined.
78     */
79 schoenebeck 2581 enum StmtFlags_t {
80     STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred.
81 schoenebeck 2727 STMT_ABORT_SIGNALLED = 1, ///< VM should stop the current callback execution (usually because of an error, but might also be without an error reason, i.e. when the built-in script function exit() was called).
82     STMT_SUSPEND_SIGNALLED = (1<<1), ///< VM supended execution, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time
83     STMT_ERROR_OCCURRED = (1<<2), ///< VM stopped execution due to some script runtime error that occurred
84 schoenebeck 2581 };
85    
86 schoenebeck 2727 /** @brief Virtual machine execution status.
87     *
88     * A set of bit flags which reflect the current overall execution status of
89     * the virtual machine concerning a certain script execution instance.
90     *
91     * Since these are bit flags, these constants are bitwise combined.
92     */
93 schoenebeck 2581 enum VMExecStatus_t {
94 schoenebeck 2727 VM_EXEC_NOT_RUNNING = 0, ///< Script is currently not executed by the VM.
95     VM_EXEC_RUNNING = 1, ///< The VM is currently executing the script.
96     VM_EXEC_SUSPENDED = (1<<1), ///< Script is currently suspended by the VM, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time.
97     VM_EXEC_ERROR = (1<<2), ///< A runtime error occurred while executing the script (i.e. a call to some built-in script function failed).
98 schoenebeck 2581 };
99    
100 schoenebeck 2879 /** @brief Script event handler type.
101     *
102     * Identifies one of the possible event handler callback types defined by
103     * the NKSP script language.
104 schoenebeck 3557 *
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 schoenebeck 2879 */
114 schoenebeck 3557 enum VMEventHandlerType_t : int32_t {
115 schoenebeck 2879 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.
117     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.
119     };
120    
121 schoenebeck 3561 /**
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 schoenebeck 2727 // just symbol prototyping
154 schoenebeck 2596 class VMIntExpr;
155     class VMStringExpr;
156 schoenebeck 2619 class VMIntArrayExpr;
157     class VMStringArrayExpr;
158 schoenebeck 3311 class VMParserContext;
159 schoenebeck 2596
160 schoenebeck 3561 /** @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 schoenebeck 2727 /** @brief Virtual machine expression
227     *
228     * This is the abstract base class for all expressions of scripts.
229     * Deriving classes must implement the abstract method exprType().
230     *
231     * An expression within a script is translated into one instance of this
232     * class. It allows a high level access for the virtual machine to evaluate
233     * and handle expressions appropriately during execution. Expressions are
234     * for example all kinds of formulas, function calls, statements or a
235     * combination of them. Most of them evaluate to some kind of value, which
236     * might be further processed as part of encompassing expressions to outer
237     * expression results and so forth.
238     */
239 schoenebeck 2581 class VMExpr {
240     public:
241 schoenebeck 2727 /**
242     * Identifies the data type to which the result of this expression
243     * evaluates to. This abstract method must be implemented by deriving
244     * classes.
245     */
246 schoenebeck 2581 virtual ExprType_t exprType() const = 0;
247 schoenebeck 2727
248     /**
249     * In case this expression is an integer expression, then this method
250     * returns a casted pointer to that VMIntExpr object. It returns NULL
251     * if this expression is not an integer expression.
252     *
253     * @b Note: type casting performed by this method is strict! That means
254     * if this expression is i.e. actually a string expression like "12",
255     * calling asInt() will @b not cast that numerical string expression to
256     * an integer expression 12 for you, instead this method will simply
257     * return NULL!
258     *
259     * @see exprType()
260     */
261 schoenebeck 2596 VMIntExpr* asInt() const;
262 schoenebeck 2727
263     /**
264     * In case this expression is a string expression, then this method
265     * returns a casted pointer to that VMStringExpr object. It returns NULL
266     * if this expression is not a string expression.
267     *
268     * @b Note: type casting performed by this method is strict! That means
269     * if this expression is i.e. actually an integer expression like 120,
270     * calling asString() will @b not cast that integer expression to a
271     * string expression "120" for you, instead this method will simply
272     * return NULL!
273     *
274     * @see exprType()
275     */
276 schoenebeck 2596 VMStringExpr* asString() const;
277 schoenebeck 2727
278     /**
279     * In case this expression is an integer array expression, then this
280     * method returns a casted pointer to that VMIntArrayExpr object. It
281     * returns NULL if this expression is not an integer array expression.
282     *
283     * @b Note: type casting performed by this method is strict! That means
284     * if this expression is i.e. an integer expression or a string
285     * expression, calling asIntArray() will @b not cast those scalar
286     * expressions to an array expression for you, instead this method will
287     * simply return NULL!
288     *
289 schoenebeck 3056 * @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 schoenebeck 2727 * @see exprType()
298     */
299 schoenebeck 3056 virtual VMIntArrayExpr* asIntArray() const;
300 schoenebeck 2945
301     /**
302     * Returns true in case this expression can be considered to be a
303     * constant expression. A constant expression will retain the same
304     * value throughout the entire life time of a script and the
305     * expression's constant value may be evaluated already at script
306     * parse time, which may result in performance benefits during script
307     * runtime.
308 schoenebeck 2960 *
309     * @b NOTE: A constant expression is per se always also non modifyable.
310     * But a non modifyable expression may not necessarily be a constant
311     * expression!
312     *
313     * @see isModifyable()
314 schoenebeck 2945 */
315     virtual bool isConstExpr() const = 0;
316    
317 schoenebeck 2960 /**
318     * Returns true in case this expression is allowed to be modified.
319     * If this method returns @c false then this expression must be handled
320     * as read-only expression, which means that assigning a new value to it
321     * is either not possible or not allowed.
322     *
323     * @b NOTE: A constant expression is per se always also non modifyable.
324     * But a non modifyable expression may not necessarily be a constant
325     * expression!
326     *
327     * @see isConstExpr()
328     */
329 schoenebeck 2945 bool isModifyable() const;
330 schoenebeck 2581 };
331    
332 schoenebeck 2727 /** @brief Virtual machine integer expression
333     *
334     * This is the abstract base class for all expressions inside scripts which
335     * evaluate to an integer (scalar) value. Deriving classes implement the
336     * abstract method evalInt() to return the actual integer result value of
337     * the expression.
338     */
339 schoenebeck 3561 class VMIntExpr : virtual public VMExpr, virtual public VMUnit {
340 schoenebeck 2581 public:
341 schoenebeck 2727 /**
342     * Returns the result of this expression as integer (scalar) value.
343     * This abstract method must be implemented by deriving classes.
344     */
345 schoenebeck 3557 virtual vmint evalInt() = 0;
346 schoenebeck 2727
347     /**
348 schoenebeck 3561 * 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 schoenebeck 2727 * Returns always INT_EXPR for instances of this class.
366     */
367     ExprType_t exprType() const OVERRIDE { return INT_EXPR; }
368 schoenebeck 3561
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 schoenebeck 2581 };
398    
399 schoenebeck 2727 /** @brief Virtual machine string expression
400     *
401     * This is the abstract base class for all expressions inside scripts which
402     * evaluate to a string value. Deriving classes implement the abstract
403     * method evalStr() to return the actual string result value of the
404     * expression.
405     */
406 schoenebeck 2581 class VMStringExpr : virtual public VMExpr {
407     public:
408 schoenebeck 2727 /**
409     * Returns the result of this expression as string value. This abstract
410     * method must be implemented by deriving classes.
411     */
412 schoenebeck 2581 virtual String evalStr() = 0;
413 schoenebeck 2727
414     /**
415     * Returns always STRING_EXPR for instances of this class.
416     */
417     ExprType_t exprType() const OVERRIDE { return STRING_EXPR; }
418 schoenebeck 2581 };
419    
420 schoenebeck 2727 /** @brief Virtual Machine Array Value Expression
421     *
422     * This is the abstract base class for all expressions inside scripts which
423     * evaluate to some kind of array value. Deriving classes implement the
424     * abstract method arraySize() to return the amount of elements within the
425     * array.
426     */
427 schoenebeck 2619 class VMArrayExpr : virtual public VMExpr {
428     public:
429 schoenebeck 2727 /**
430     * Returns amount of elements in this array. This abstract method must
431     * be implemented by deriving classes.
432     */
433 schoenebeck 3557 virtual vmint arraySize() const = 0;
434 schoenebeck 2619 };
435    
436 schoenebeck 2727 /** @brief Virtual Machine Integer Array Expression
437     *
438     * This is the abstract base class for all expressions inside scripts which
439     * evaluate to an array of integer values. Deriving classes implement the
440     * abstract methods arraySize(), evalIntElement() and assignIntElement() to
441     * access the individual integer array values.
442     */
443 schoenebeck 2619 class VMIntArrayExpr : virtual public VMArrayExpr {
444     public:
445 schoenebeck 2727 /**
446     * Returns the (scalar) integer value of the array element given by
447     * element index @a i.
448     *
449     * @param i - array element index (must be between 0 .. arraySize() - 1)
450     */
451 schoenebeck 3557 virtual vmint evalIntElement(vmuint i) = 0;
452 schoenebeck 2727
453     /**
454     * Changes the current value of an element (given by array element
455     * index @a i) of this integer array.
456     *
457     * @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
459     */
460 schoenebeck 3557 virtual void assignIntElement(vmuint i, vmint value) = 0;
461 schoenebeck 2727
462     /**
463     * Returns always INT_ARR_EXPR for instances of this class.
464     */
465     ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; }
466 schoenebeck 2619 };
467    
468 schoenebeck 2727 /** @brief Arguments (parameters) for being passed to a built-in script function.
469     *
470     * An argument or a set of arguments passed to a script function are
471     * translated by the parser to an instance of this class. This abstract
472     * interface class is used by implementations of built-in functions to
473     * obtain the individual function argument values being passed to them at
474     * runtime.
475     */
476 schoenebeck 2581 class VMFnArgs {
477     public:
478 schoenebeck 2727 /**
479     * Returns the amount of arguments going to be passed to the script
480     * function.
481     */
482 schoenebeck 3557 virtual vmint argsCount() const = 0;
483 schoenebeck 2727
484     /**
485     * Returns the respective argument (requested by argument index @a i) of
486     * this set of arguments. This method is called by implementations of
487     * built-in script functions to obtain the value of each function
488     * argument passed to the function at runtime.
489     *
490     * @param i - function argument index (indexed from left to right)
491     */
492 schoenebeck 3557 virtual VMExpr* arg(vmint i) = 0;
493 schoenebeck 2581 };
494    
495 schoenebeck 2727 /** @brief Result value returned from a call to a built-in script function.
496     *
497     * Implementations of built-in script functions return an instance of this
498     * object to let the virtual machine obtain the result value of the function
499     * call, which might then be further processed by the virtual machine
500     * according to the script. It also provides informations about the success
501     * or failure of the function call.
502     */
503 schoenebeck 2581 class VMFnResult {
504     public:
505 schoenebeck 2727 /**
506     * Returns the result value of the function call, represented by a high
507     * level expression object.
508     */
509 schoenebeck 2581 virtual VMExpr* resultValue() = 0;
510 schoenebeck 2727
511     /**
512     * Provides detailed informations of the success / failure of the
513     * function call. The virtual machine is evaluating the flags returned
514     * here to decide whether it must abort or suspend execution of the
515     * script at this point.
516     */
517 schoenebeck 2581 virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }
518     };
519    
520 schoenebeck 2727 /** @brief Virtual machine built-in function.
521 schoenebeck 2612 *
522     * Abstract base class for built-in script functions, defining the interface
523 schoenebeck 2727 * for all built-in script function implementations. All built-in script
524     * functions are deriving from this abstract interface class in order to
525     * provide their functionality to the virtual machine with this unified
526     * interface.
527     *
528     * The methods of this interface class provide two purposes:
529     *
530     * 1. When a script is loaded, the script parser uses the methods of this
531     * interface to check whether the script author was calling the
532     * respective built-in script function in a correct way. For example
533     * the parser checks whether the required amount of parameters were
534     * passed to the function and whether the data types passed match the
535     * data types expected by the function. If not, loading the script will
536     * be aborted with a parser error, describing to the user (i.e. script
537     * author) the precise misusage of the respective function.
538     * 2. After the script was loaded successfully and the script is executed,
539     * the virtual machine calls the exec() method of the respective built-in
540     * function to provide the actual functionality of the built-in function
541     * call.
542 schoenebeck 2612 */
543 schoenebeck 2581 class VMFunction {
544     public:
545 schoenebeck 2612 /**
546     * Script data type of the function's return value. If the function does
547 schoenebeck 2727 * not return any value (void), then it returns EMPTY_EXPR here.
548 schoenebeck 2612 */
549 schoenebeck 2581 virtual ExprType_t returnType() = 0;
550 schoenebeck 2612
551     /**
552     * Minimum amount of function arguments this function accepts. If a
553     * script is calling this function with less arguments, the script
554     * parser will throw a parser error.
555     */
556 schoenebeck 3557 virtual vmint minRequiredArgs() const = 0;
557 schoenebeck 2612
558     /**
559     * Maximum amount of function arguments this functions accepts. If a
560     * script is calling this function with more arguments, the script
561     * parser will throw a parser error.
562     */
563 schoenebeck 3557 virtual vmint maxAllowedArgs() const = 0;
564 schoenebeck 2612
565     /**
566     * Script data type of the function's @c iArg 'th function argument.
567     * The information provided here is less strong than acceptsArgType().
568     * The parser will compare argument data types provided in scripts by
569 schoenebeck 2871 * calling acceptsArgType(). The return value of argType() is used by the
570 schoenebeck 2612 * parser instead to show an appropriate parser error which data type
571     * this function usually expects as "default" data type. Reason: a
572     * function may accept multiple data types for a certain function
573     * argument and would automatically cast the passed argument value in
574     * that case to the type it actually needs.
575     *
576     * @param iArg - index of the function argument in question
577 schoenebeck 2727 * (must be between 0 .. maxAllowedArgs() - 1)
578 schoenebeck 2612 */
579 schoenebeck 3557 virtual ExprType_t argType(vmint iArg) const = 0;
580 schoenebeck 2612
581     /**
582 schoenebeck 2945 * This method is called by the parser to check whether arguments
583 schoenebeck 2612 * passed in scripts to this function are accepted by this function. If
584     * a script calls this function with an argument's data type not
585 schoenebeck 2727 * accepted by this function, the parser will throw a parser error. On
586     * such errors the data type returned by argType() will be used to
587     * assemble an appropriate error message regarding the precise misusage
588     * of the built-in function.
589 schoenebeck 2612 *
590     * @param iArg - index of the function argument in question
591 schoenebeck 2727 * (must be between 0 .. maxAllowedArgs() - 1)
592 schoenebeck 2612 * @param type - script data type used for this function argument by
593     * currently parsed script
594 schoenebeck 2727 * @return true if the given data type would be accepted for the
595     * respective function argument by the function
596 schoenebeck 2612 */
597 schoenebeck 3557 virtual bool acceptsArgType(vmint iArg, ExprType_t type) const = 0;
598 schoenebeck 2612
599     /**
600 schoenebeck 3561 * 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     *
634     * @return true if a metric prefix would be accepted for the respective
635     * function argument by this function
636     *
637     * @see MetricPrefix_t
638     */
639     virtual bool acceptsArgUnitPrefix(vmint iArg) const;
640    
641     /**
642     * This method is called by the parser to check whether arguments
643     * passed in scripts to this function are accepted by this function. If
644     * a script calls this function with an argument that is declared to be
645     * a "final" value and this is not accepted by this function, the parser
646     * will throw a parser error.
647     *
648     * This default implementation of this method does not accept a "final"
649     * value. Deriving subclasses would override this method implementation
650     * in case they do accept a "final" value for its function arguments.
651     *
652     * @param iArg - index of the function argument in question
653     * (must be between 0 .. maxAllowedArgs() - 1)
654     * @return true if a "final" value would be accepted for the respective
655     * function argument by the function
656     *
657     * @see VMIntExpr::isFinal()
658     */
659     virtual bool acceptsArgFinal(vmint iArg) const;
660    
661     /**
662 schoenebeck 2945 * This method is called by the parser to check whether some arguments
663     * (and if yes which ones) passed to this script function will be
664     * modified by this script function. Most script functions simply use
665     * their arguments as inputs, that is they only read the argument's
666     * values. However some script function may also use passed
667     * argument(s) as output variables. In this case the function
668     * implementation must return @c true for the respective argument
669     * index here.
670     *
671     * @param iArg - index of the function argument in question
672     * (must be between 0 .. maxAllowedArgs() - 1)
673     */
674 schoenebeck 3557 virtual bool modifiesArg(vmint iArg) const = 0;
675 schoenebeck 2945
676     /**
677 schoenebeck 2727 * Implements the actual function execution. This exec() method is
678     * called by the VM whenever this function implementation shall be
679     * executed at script runtime. This method blocks until the function
680     * call completed.
681 schoenebeck 2612 *
682     * @param args - function arguments for executing this built-in function
683 schoenebeck 2727 * @returns function's return value (if any) and general status
684     * informations (i.e. whether the function call caused a
685     * runtime error)
686 schoenebeck 2612 */
687 schoenebeck 2581 virtual VMFnResult* exec(VMFnArgs* args) = 0;
688 schoenebeck 2612
689     /**
690 schoenebeck 2727 * Convenience method for function implementations to show warning
691     * messages during actual execution of the built-in function.
692 schoenebeck 2612 *
693 schoenebeck 2727 * @param txt - runtime warning text to be shown to user
694 schoenebeck 2612 */
695 schoenebeck 2598 void wrnMsg(const String& txt);
696 schoenebeck 2612
697     /**
698 schoenebeck 2727 * Convenience method for function implementations to show error
699     * messages during actual execution of the built-in function.
700 schoenebeck 2612 *
701 schoenebeck 2727 * @param txt - runtime error text to be shown to user
702 schoenebeck 2612 */
703 schoenebeck 2598 void errMsg(const String& txt);
704 schoenebeck 2581 };
705    
706 schoenebeck 2727 /** @brief Virtual machine relative pointer.
707     *
708 schoenebeck 3557 * POD base of VMInt64RelPtr, VMInt32RelPtr and VMInt8RelPtr structures. Not
709     * intended to be used directly. Use VMInt64RelPtr, VMInt32RelPtr,
710     * VMInt8RelPtr instead.
711 schoenebeck 2727 *
712 schoenebeck 3557 * @see VMInt64RelPtr, VMInt32RelPtr, VMInt8RelPtr
713 schoenebeck 2594 */
714     struct VMRelPtr {
715     void** base; ///< Base pointer.
716 schoenebeck 3557 vmint offset; ///< Offset (in bytes) relative to base pointer.
717 schoenebeck 2948 bool readonly; ///< Whether the pointed data may be modified or just be read.
718 schoenebeck 2594 };
719    
720 schoenebeck 3557 /** @brief Pointer to built-in VM integer variable (interface class).
721 schoenebeck 2594 *
722 schoenebeck 3557 * This class acts as an abstract interface to all built-in integer script
723     * variables, independent of their actual native size (i.e. some built-in
724     * script variables are internally using a native int size of 64 bit or 32
725     * bit or 8 bit). The virtual machine is using this interface class instead
726     * of its implementing descendants (VMInt64RelPtr, VMInt32RelPtr,
727     * VMInt8RelPtr) in order for the virtual machine for not being required to
728     * handle each of them differently.
729     */
730     struct VMIntPtr {
731     virtual vmint evalInt() = 0;
732     virtual void assign(vmint i) = 0;
733     virtual bool isAssignable() const = 0;
734     };
735    
736     /** @brief Pointer to built-in VM integer variable (of C/C++ type int64_t).
737     *
738     * Used for defining built-in 64 bit integer script variables.
739     *
740     * @b CAUTION: You may only use this class for pointing to C/C++ variables
741     * of type "int64_t" (thus being exactly 64 bit in size). If the C/C++ int
742     * variable you want to reference is only 32 bit in size then you @b must
743     * use VMInt32RelPtr instead! Respectively for a referenced native variable
744     * with only 8 bit in size you @b must use VMInt8RelPtr instead!
745     *
746     * For efficiency reasons the actual native C/C++ int variable is referenced
747     * by two components here. The actual native int C/C++ variable in memory
748     * is dereferenced at VM run-time by taking the @c base pointer dereference
749     * and adding @c offset bytes. This has the advantage that for a large
750     * number of built-in int variables, only one (or few) base pointer need
751     * to be re-assigned before running a script, instead of updating each
752     * built-in variable each time before a script is executed.
753     *
754     * Refer to DECLARE_VMINT() for example code.
755     *
756     * @see VMInt32RelPtr, VMInt8RelPtr, DECLARE_VMINT()
757     */
758     struct VMInt64RelPtr : VMRelPtr, VMIntPtr {
759     VMInt64RelPtr() {
760     base = NULL;
761     offset = 0;
762     readonly = false;
763     }
764     VMInt64RelPtr(const VMRelPtr& data) {
765     base = data.base;
766     offset = data.offset;
767     readonly = false;
768     }
769     vmint evalInt() OVERRIDE {
770     return (vmint)*(int64_t*)&(*(uint8_t**)base)[offset];
771     }
772     void assign(vmint i) OVERRIDE {
773     *(int64_t*)&(*(uint8_t**)base)[offset] = (int64_t)i;
774     }
775     bool isAssignable() const OVERRIDE { return !readonly; }
776     };
777    
778     /** @brief Pointer to built-in VM integer variable (of C/C++ type int32_t).
779     *
780 schoenebeck 2727 * Used for defining built-in 32 bit integer script variables.
781 schoenebeck 2594 *
782     * @b CAUTION: You may only use this class for pointing to C/C++ variables
783 schoenebeck 3557 * of type "int32_t" (thus being exactly 32 bit in size). If the C/C++ int
784     * variable you want to reference is 64 bit in size then you @b must use
785     * VMInt64RelPtr instead! Respectively for a referenced native variable with
786     * only 8 bit in size you @b must use VMInt8RelPtr instead!
787 schoenebeck 2594 *
788     * For efficiency reasons the actual native C/C++ int variable is referenced
789     * by two components here. The actual native int C/C++ variable in memory
790     * is dereferenced at VM run-time by taking the @c base pointer dereference
791     * and adding @c offset bytes. This has the advantage that for a large
792     * number of built-in int variables, only one (or few) base pointer need
793     * to be re-assigned before running a script, instead of updating each
794     * built-in variable each time before a script is executed.
795     *
796     * Refer to DECLARE_VMINT() for example code.
797     *
798 schoenebeck 3557 * @see VMInt64RelPtr, VMInt8RelPtr, DECLARE_VMINT()
799 schoenebeck 2594 */
800 schoenebeck 3557 struct VMInt32RelPtr : VMRelPtr, VMIntPtr {
801     VMInt32RelPtr() {
802 schoenebeck 2594 base = NULL;
803     offset = 0;
804 schoenebeck 2948 readonly = false;
805 schoenebeck 2594 }
806 schoenebeck 3557 VMInt32RelPtr(const VMRelPtr& data) {
807 schoenebeck 2594 base = data.base;
808     offset = data.offset;
809 schoenebeck 2948 readonly = false;
810 schoenebeck 2594 }
811 schoenebeck 3557 vmint evalInt() OVERRIDE {
812     return (vmint)*(int32_t*)&(*(uint8_t**)base)[offset];
813     }
814     void assign(vmint i) OVERRIDE {
815     *(int32_t*)&(*(uint8_t**)base)[offset] = (int32_t)i;
816     }
817     bool isAssignable() const OVERRIDE { return !readonly; }
818 schoenebeck 2594 };
819    
820     /** @brief Pointer to built-in VM integer variable (of C/C++ type int8_t).
821     *
822 schoenebeck 2727 * Used for defining built-in 8 bit integer script variables.
823 schoenebeck 2594 *
824     * @b CAUTION: You may only use this class for pointing to C/C++ variables
825     * of type "int8_t" (8 bit integer). If the C/C++ int variable you want to
826 schoenebeck 3557 * reference is not exactly 8 bit in size then you @b must respectively use
827     * either VMInt32RelPtr for native 32 bit variables or VMInt64RelPtrl for
828     * native 64 bit variables instead!
829 schoenebeck 2594 *
830     * For efficiency reasons the actual native C/C++ int variable is referenced
831     * by two components here. The actual native int C/C++ variable in memory
832     * is dereferenced at VM run-time by taking the @c base pointer dereference
833     * and adding @c offset bytes. This has the advantage that for a large
834     * number of built-in int variables, only one (or few) base pointer need
835     * to be re-assigned before running a script, instead of updating each
836     * built-in variable each time before a script is executed.
837     *
838     * Refer to DECLARE_VMINT() for example code.
839     *
840 schoenebeck 3557 * @see VMIntRel32Ptr, VMIntRel64Ptr, DECLARE_VMINT()
841 schoenebeck 2594 */
842 schoenebeck 3557 struct VMInt8RelPtr : VMRelPtr, VMIntPtr {
843     VMInt8RelPtr() {
844     base = NULL;
845     offset = 0;
846     readonly = false;
847 schoenebeck 2594 }
848 schoenebeck 3557 VMInt8RelPtr(const VMRelPtr& data) {
849     base = data.base;
850     offset = data.offset;
851     readonly = false;
852 schoenebeck 2594 }
853 schoenebeck 3557 vmint evalInt() OVERRIDE {
854     return (vmint)*(uint8_t*)&(*(uint8_t**)base)[offset];
855     }
856     void assign(vmint i) OVERRIDE {
857     *(uint8_t*)&(*(uint8_t**)base)[offset] = (uint8_t)i;
858     }
859     bool isAssignable() const OVERRIDE { return !readonly; }
860 schoenebeck 2594 };
861    
862 schoenebeck 3557 /** @brief Pointer to built-in VM integer variable (of C/C++ type vmint).
863     *
864     * Use this typedef if the native variable to be pointed to is using the
865     * typedef vmint. If the native C/C++ variable to be pointed to is using
866     * another C/C++ type then better use one of VMInt64RelPtr or VMInt32RelPtr
867     * instead.
868     */
869     typedef VMInt64RelPtr VMIntRelPtr;
870    
871 schoenebeck 3035 #if HAVE_CXX_EMBEDDED_PRAGMA_DIAGNOSTICS
872     # define COMPILER_DISABLE_OFFSETOF_WARNING \
873     _Pragma("GCC diagnostic push") \
874     _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
875     # define COMPILER_RESTORE_OFFSETOF_WARNING \
876     _Pragma("GCC diagnostic pop")
877     #else
878     # define COMPILER_DISABLE_OFFSETOF_WARNING
879     # define COMPILER_RESTORE_OFFSETOF_WARNING
880     #endif
881    
882 schoenebeck 2594 /**
883 schoenebeck 3557 * Convenience macro for initializing VMInt64RelPtr, VMInt32RelPtr and
884     * VMInt8RelPtr structures. Usage example:
885 schoenebeck 2594 * @code
886     * struct Foo {
887 schoenebeck 2727 * uint8_t a; // native representation of a built-in integer script variable
888 schoenebeck 3557 * int64_t b; // native representation of another built-in integer script variable
889     * int64_t c; // native representation of another built-in integer script variable
890 schoenebeck 2727 * uint8_t d; // native representation of another built-in integer script variable
891 schoenebeck 2594 * };
892     *
893 schoenebeck 2727 * // initializing the built-in script variables to some values
894     * Foo foo1 = (Foo) { 1, 2000, 3000, 4 };
895     * Foo foo2 = (Foo) { 5, 6000, 7000, 8 };
896 schoenebeck 2594 *
897     * Foo* pFoo;
898     *
899 schoenebeck 2727 * VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a);
900 schoenebeck 3557 * VMInt64RelPtr varB = DECLARE_VMINT(pFoo, class Foo, b);
901     * VMInt64RelPtr varC = DECLARE_VMINT(pFoo, class Foo, c);
902 schoenebeck 2727 * VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d);
903 schoenebeck 2594 *
904     * pFoo = &foo1;
905 schoenebeck 2727 * printf("%d\n", varA->evalInt()); // will print 1
906     * printf("%d\n", varB->evalInt()); // will print 2000
907     * printf("%d\n", varC->evalInt()); // will print 3000
908     * printf("%d\n", varD->evalInt()); // will print 4
909 schoenebeck 2594 *
910 schoenebeck 2727 * // same printf() code, just with pFoo pointer being changed ...
911     *
912 schoenebeck 2594 * pFoo = &foo2;
913 schoenebeck 2727 * printf("%d\n", varA->evalInt()); // will print 5
914     * printf("%d\n", varB->evalInt()); // will print 6000
915     * printf("%d\n", varC->evalInt()); // will print 7000
916     * printf("%d\n", varD->evalInt()); // will print 8
917 schoenebeck 2594 * @endcode
918 schoenebeck 2727 * As you can see above, by simply changing one single pointer, you can
919     * remap a huge bunch of built-in integer script variables to completely
920     * different native values/native variables. Which especially reduces code
921     * complexity inside the sampler engines which provide the actual script
922     * functionalities.
923 schoenebeck 2594 */
924 schoenebeck 3034 #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \
925     /* Disable offsetof warning, trust us, we are cautios. */ \
926 schoenebeck 3035 COMPILER_DISABLE_OFFSETOF_WARNING \
927 schoenebeck 3034 (VMRelPtr) { \
928     (void**) &basePtr, \
929     offsetof(T_struct, T_member), \
930     false \
931     } \
932 schoenebeck 3035 COMPILER_RESTORE_OFFSETOF_WARNING \
933 schoenebeck 3034 ) \
934 schoenebeck 2594
935 schoenebeck 2948 /**
936 schoenebeck 3557 * Same as DECLARE_VMINT(), but this one defines the VMInt64RelPtr,
937     * VMInt32RelPtr and VMInt8RelPtr structures to be of read-only type.
938     * That means the script parser will abort any script at parser time if the
939     * script is trying to modify such a read-only built-in variable.
940 schoenebeck 2948 *
941     * @b NOTE: this is only intended for built-in read-only variables that
942     * may change during runtime! If your built-in variable's data is rather
943     * already available at parser time and won't change during runtime, then
944     * you should rather register a built-in constant in your VM class instead!
945     *
946     * @see ScriptVM::builtInConstIntVariables()
947     */
948     #define DECLARE_VMINT_READONLY(basePtr, T_struct, T_member) ( \
949 schoenebeck 3034 /* Disable offsetof warning, trust us, we are cautios. */ \
950 schoenebeck 3035 COMPILER_DISABLE_OFFSETOF_WARNING \
951 schoenebeck 3034 (VMRelPtr) { \
952     (void**) &basePtr, \
953     offsetof(T_struct, T_member), \
954     true \
955     } \
956 schoenebeck 3035 COMPILER_RESTORE_OFFSETOF_WARNING \
957 schoenebeck 3034 ) \
958 schoenebeck 2948
959 schoenebeck 2594 /** @brief Built-in VM 8 bit integer array variable.
960     *
961 schoenebeck 2727 * Used for defining built-in integer array script variables (8 bit per
962     * array element). Currently there is no support for any other kind of array
963     * type. So all integer arrays of scripts use 8 bit data types.
964 schoenebeck 2594 */
965     struct VMInt8Array {
966     int8_t* data;
967 schoenebeck 3557 vmint size;
968 schoenebeck 3253 bool readonly; ///< Whether the array data may be modified or just be read.
969 schoenebeck 2594
970 schoenebeck 3253 VMInt8Array() : data(NULL), size(0), readonly(false) {}
971 schoenebeck 2594 };
972    
973 schoenebeck 2945 /** @brief Virtual machine script variable.
974     *
975     * Common interface for all variables accessed in scripts.
976     */
977     class VMVariable : virtual public VMExpr {
978     public:
979     /**
980     * Whether a script may modify the content of this variable by
981     * assigning a new value to it.
982     *
983     * @see isConstExpr(), assign()
984     */
985     virtual bool isAssignable() const = 0;
986    
987     /**
988     * In case this variable is assignable, this method will be called to
989     * perform the value assignment to this variable with @a expr
990     * reflecting the new value to be assigned.
991     *
992     * @param expr - new value to be assigned to this variable
993     */
994     virtual void assignExpr(VMExpr* expr) = 0;
995     };
996    
997 schoenebeck 2942 /** @brief Dynamically executed variable (abstract base class).
998     *
999     * Interface for the implementation of a dynamically generated content of
1000     * a built-in script variable. Most built-in variables are simply pointers
1001     * to some native location in memory. So when a script reads them, the
1002     * memory location is simply read to get the value of the variable. A
1003     * dynamic variable however is not simply a memory location. For each access
1004     * to a dynamic variable some native code is executed to actually generate
1005     * and provide the content (value) of this type of variable.
1006     */
1007 schoenebeck 2945 class VMDynVar : public VMVariable {
1008 schoenebeck 2942 public:
1009     /**
1010     * Returns true in case this dynamic variable can be considered to be a
1011     * constant expression. A constant expression will retain the same value
1012     * throughout the entire life time of a script and the expression's
1013     * constant value may be evaluated already at script parse time, which
1014     * may result in performance benefits during script runtime.
1015     *
1016     * However due to the "dynamic" behavior of dynamic variables, almost
1017     * all dynamic variables are probably not constant expressions. That's
1018     * why this method returns @c false by default. If you are really sure
1019     * that your dynamic variable implementation can be considered a
1020     * constant expression then you may override this method and return
1021     * @c true instead. Note that when you return @c true here, your
1022     * dynamic variable will really just be executed once; and exectly
1023     * already when the script is loaded!
1024     *
1025     * As an example you may implement a "constant" built-in dynamic
1026     * variable that checks for a certain operating system feature and
1027     * returns the result of that OS feature check as content (value) of
1028     * this dynamic variable. Since the respective OS feature might become
1029     * available/unavailable after OS updates, software migration, etc. the
1030     * OS feature check should at least be performed once each time the
1031     * application is launched. And since the OS feature check might take a
1032     * certain amount of execution time, it might make sense to only
1033     * perform the check if the respective variable name is actually
1034     * referenced at all in the script to be loaded. Note that the dynamic
1035     * variable will still be evaluated again though if the script is
1036     * loaded again. So it is up to you to probably cache the result in the
1037     * implementation of your dynamic variable.
1038     *
1039     * On doubt, please rather consider to use a constant built-in script
1040     * variable instead of implementing a "constant" dynamic variable, due
1041     * to the runtime overhead a dynamic variable may cause.
1042     *
1043     * @see isAssignable()
1044     */
1045 schoenebeck 2945 bool isConstExpr() const OVERRIDE { return false; }
1046 schoenebeck 2942
1047     /**
1048     * In case this dynamic variable is assignable, the new value (content)
1049     * to be assigned to this dynamic variable.
1050     *
1051     * By default this method does nothing. Override and implement this
1052     * method in your subclass in case your dynamic variable allows to
1053     * assign a new value by script.
1054     *
1055     * @param expr - new value to be assigned to this variable
1056     */
1057 schoenebeck 2945 void assignExpr(VMExpr* expr) OVERRIDE {}
1058 schoenebeck 3034
1059     virtual ~VMDynVar() {}
1060 schoenebeck 2942 };
1061    
1062     /** @brief Dynamically executed variable (of integer data type).
1063     *
1064     * This is the base class for all built-in integer script variables whose
1065     * variable content needs to be provided dynamically by executable native
1066     * code on each script variable access.
1067     */
1068     class VMDynIntVar : virtual public VMDynVar, virtual public VMIntExpr {
1069     public:
1070 schoenebeck 3561 MetricPrefix_t unitPrefix(vmuint i) const OVERRIDE { return VM_NO_PREFIX; }
1071     StdUnit_t unitType() const OVERRIDE { return VM_NO_UNIT; }
1072     bool isFinal() const OVERRIDE { return false; }
1073 schoenebeck 2942 };
1074    
1075     /** @brief Dynamically executed variable (of string data type).
1076     *
1077     * This is the base class for all built-in string script variables whose
1078     * variable content needs to be provided dynamically by executable native
1079     * code on each script variable access.
1080     */
1081     class VMDynStringVar : virtual public VMDynVar, virtual public VMStringExpr {
1082     public:
1083     };
1084    
1085 schoenebeck 3073 /** @brief Dynamically executed variable (of integer array data type).
1086     *
1087     * This is the base class for all built-in integer array script variables
1088     * whose variable content needs to be provided dynamically by executable
1089     * native code on each script variable access.
1090     */
1091     class VMDynIntArrayVar : virtual public VMDynVar, virtual public VMIntArrayExpr {
1092     public:
1093     };
1094    
1095 schoenebeck 2612 /** @brief Provider for built-in script functions and variables.
1096     *
1097 schoenebeck 2727 * Abstract base class defining the high-level interface for all classes
1098     * which add and implement built-in script functions and built-in script
1099     * variables.
1100 schoenebeck 2612 */
1101 schoenebeck 2581 class VMFunctionProvider {
1102     public:
1103 schoenebeck 2612 /**
1104     * Returns pointer to the built-in function with the given function
1105 schoenebeck 2727 * @a name, or NULL if there is no built-in function with that function
1106     * name.
1107 schoenebeck 2612 *
1108 schoenebeck 2727 * @param name - function name (i.e. "wait" or "message" or "exit", etc.)
1109 schoenebeck 2612 */
1110 schoenebeck 2581 virtual VMFunction* functionByName(const String& name) = 0;
1111 schoenebeck 2612
1112     /**
1113 schoenebeck 3311 * Returns @c true if the passed built-in function is disabled and
1114     * should be ignored by the parser. This method is called by the
1115     * parser on preprocessor level for each built-in function call within
1116     * a script. Accordingly if this method returns @c true, then the
1117     * respective function call is completely filtered out on preprocessor
1118     * level, so that built-in function won't make into the result virtual
1119     * machine representation, nor would expressions of arguments passed to
1120     * that built-in function call be evaluated, nor would any check
1121     * regarding correct usage of the built-in function be performed.
1122     * In other words: a disabled function call ends up as a comment block.
1123     *
1124     * @param fn - built-in function to be checked
1125     * @param ctx - parser context at the position where the built-in
1126     * function call is located within the script
1127     */
1128     virtual bool isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) = 0;
1129    
1130     /**
1131 schoenebeck 2612 * Returns a variable name indexed map of all built-in script variables
1132 schoenebeck 2727 * which point to native "int" scalar (usually 32 bit) variables.
1133 schoenebeck 2612 */
1134 schoenebeck 3557 virtual std::map<String,VMIntPtr*> builtInIntVariables() = 0;
1135 schoenebeck 2612
1136     /**
1137 schoenebeck 2727 * Returns a variable name indexed map of all built-in script integer
1138     * array variables with array element type "int8_t" (8 bit).
1139 schoenebeck 2612 */
1140 schoenebeck 2594 virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
1141 schoenebeck 2612
1142     /**
1143     * Returns a variable name indexed map of all built-in constant script
1144     * variables, which never change their value at runtime.
1145     */
1146 schoenebeck 3557 virtual std::map<String,vmint> builtInConstIntVariables() = 0;
1147 schoenebeck 2942
1148     /**
1149     * Returns a variable name indexed map of all built-in dynamic variables,
1150     * which are not simply data stores, rather each one of them executes
1151     * natively to provide or alter the respective script variable data.
1152     */
1153     virtual std::map<String,VMDynVar*> builtInDynamicVariables() = 0;
1154 schoenebeck 2581 };
1155    
1156 schoenebeck 2594 /** @brief Execution state of a virtual machine.
1157     *
1158     * An instance of this abstract base class represents exactly one execution
1159     * state of a virtual machine. This encompasses most notably the VM
1160 schoenebeck 2612 * execution stack, and VM polyphonic variables. It does not contain global
1161 schoenebeck 2727 * variables. Global variables are contained in the VMParserContext object.
1162 schoenebeck 2612 * You might see a VMExecContext object as one virtual thread of the virtual
1163     * machine.
1164 schoenebeck 2594 *
1165 schoenebeck 2612 * In contrast to a VMParserContext, a VMExecContext is not tied to a
1166     * ScriptVM instance. Thus you can use a VMExecContext with different
1167     * ScriptVM instances, however not concurrently at the same time.
1168     *
1169 schoenebeck 2594 * @see VMParserContext
1170     */
1171 schoenebeck 2581 class VMExecContext {
1172     public:
1173     virtual ~VMExecContext() {}
1174 schoenebeck 2727
1175     /**
1176     * In case the script was suspended for some reason, this method returns
1177     * the amount of microseconds before the script shall continue its
1178     * execution. Note that the virtual machine itself does never put its
1179     * own execution thread(s) to sleep. So the respective class (i.e. sampler
1180     * engine) which is using the virtual machine classes here, must take
1181     * care by itself about taking time stamps, determining the script
1182     * handlers that shall be put aside for the requested amount of
1183 schoenebeck 2871 * microseconds, indicated by this method by comparing the time stamps in
1184 schoenebeck 2727 * real-time, and to continue passing the respective handler to
1185     * ScriptVM::exec() as soon as its suspension exceeded, etc. Or in other
1186     * words: all classes in this directory never have an idea what time it
1187     * is.
1188     *
1189     * You should check the return value of ScriptVM::exec() to determine
1190     * whether the script was actually suspended before calling this method
1191     * here.
1192     *
1193     * @see ScriptVM::exec()
1194     */
1195 schoenebeck 3557 virtual vmint suspensionTimeMicroseconds() const = 0;
1196 schoenebeck 3207
1197     /**
1198     * Causes all polyphonic variables to be reset to zero values. A
1199     * polyphonic variable is expected to be zero when entering a new event
1200     * handler instance. As an exception the values of polyphonic variables
1201     * shall only be preserved from an note event handler instance to its
1202     * correspending specific release handler instance. So in the latter
1203     * case the script author may pass custom data from the note handler to
1204     * the release handler, but only for the same specific note!
1205     */
1206     virtual void resetPolyphonicData() = 0;
1207 schoenebeck 3221
1208     /**
1209     * Returns amount of virtual machine instructions which have been
1210     * performed the last time when this execution context was executing a
1211     * script. So in case you need the overall amount of instructions
1212     * instead, then you need to add them by yourself after each
1213     * ScriptVM::exec() call.
1214     */
1215     virtual size_t instructionsPerformed() const = 0;
1216 schoenebeck 3277
1217     /**
1218     * Sends a signal to this script execution instance to abort its script
1219     * execution as soon as possible. This method is called i.e. when one
1220     * script execution instance intends to stop another script execution
1221     * instance.
1222     */
1223     virtual void signalAbort() = 0;
1224 schoenebeck 3293
1225     /**
1226     * Copies the current entire execution state from this object to the
1227     * given object. So this can be used to "fork" a new script thread which
1228     * then may run independently with its own polyphonic data for instance.
1229     */
1230     virtual void forkTo(VMExecContext* ectx) const = 0;
1231 schoenebeck 3551
1232     /**
1233     * In case the script called the built-in exit() function and passed a
1234     * value as argument to the exit() function, then this method returns
1235     * the value that had been passed as argument to the exit() function.
1236     * Otherwise if the exit() function has not been called by the script
1237     * or no argument had been passed to the exit() function, then this
1238     * method returns NULL instead.
1239     *
1240     * Currently this is only used for automated test cases against the
1241     * script engine, which return some kind of value in the individual
1242     * test case scripts to check their behaviour in automated way. There
1243     * is no purpose for this mechanism in production use. Accordingly this
1244     * exit result value is @b always completely ignored by the sampler
1245     * engines.
1246     *
1247     * Officially the built-in exit() function does not expect any arguments
1248     * to be passed to its function call, and by default this feature is
1249     * hence disabled and will yield in a parser error unless
1250     * ScriptVM::setExitResultEnabled() was explicitly set.
1251     *
1252     * @see ScriptVM::setExitResultEnabled()
1253     */
1254     virtual VMExpr* exitResult() = 0;
1255 schoenebeck 2581 };
1256    
1257 schoenebeck 2645 /** @brief Script callback for a certain event.
1258     *
1259     * Represents a script callback for a certain event, i.e.
1260 schoenebeck 2727 * "on note ... end on" code block.
1261 schoenebeck 2645 */
1262 schoenebeck 2581 class VMEventHandler {
1263     public:
1264 schoenebeck 2645 /**
1265 schoenebeck 2879 * Type of this event handler, which identifies its purpose. For example
1266     * for a "on note ... end on" script callback block,
1267     * @c VM_EVENT_HANDLER_NOTE would be returned here.
1268     */
1269     virtual VMEventHandlerType_t eventHandlerType() const = 0;
1270    
1271     /**
1272 schoenebeck 2645 * Name of the event handler which identifies its purpose. For example
1273     * for a "on note ... end on" script callback block, the name "note"
1274     * would be returned here.
1275     */
1276 schoenebeck 2581 virtual String eventHandlerName() const = 0;
1277 schoenebeck 2645
1278     /**
1279     * Whether or not the event handler makes any use of so called
1280     * "polyphonic" variables.
1281     */
1282     virtual bool isPolyphonic() const = 0;
1283 schoenebeck 2581 };
1284    
1285 schoenebeck 2727 /**
1286 schoenebeck 3285 * Reflects the precise position and span of a specific code block within
1287     * a script. This is currently only used for the locations of commented
1288 schoenebeck 3292 * code blocks due to preprocessor statements, and for parser errors and
1289     * parser warnings.
1290 schoenebeck 3285 *
1291 schoenebeck 3292 * @see ParserIssue for code locations of parser errors and parser warnings
1292     *
1293     * @see VMParserContext::preprocessorComments() for locations of code which
1294     * have been filtered out by preprocessor statements
1295 schoenebeck 3285 */
1296     struct CodeBlock {
1297     int firstLine; ///< The first line number of this code block within the script (indexed with 1 being the very first line).
1298     int lastLine; ///< The last line number of this code block within the script.
1299     int firstColumn; ///< The first column of this code block within the script (indexed with 1 being the very first column).
1300     int lastColumn; ///< The last column of this code block within the script.
1301     };
1302    
1303     /**
1304 schoenebeck 2727 * Encapsulates a noteworty parser issue. This encompasses the type of the
1305     * issue (either a parser error or parser warning), a human readable
1306     * explanation text of the error or warning and the location of the
1307     * encountered parser issue within the script.
1308 schoenebeck 3012 *
1309     * @see VMSourceToken for processing syntax highlighting instead.
1310 schoenebeck 2727 */
1311 schoenebeck 3292 struct ParserIssue : CodeBlock {
1312 schoenebeck 2727 String txt; ///< Human readable explanation text of the parser issue.
1313     ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning.
1314 schoenebeck 2581
1315 schoenebeck 2727 /**
1316     * Print this issue out to the console (stdio).
1317     */
1318 schoenebeck 2581 inline void dump() {
1319     switch (type) {
1320     case PARSER_ERROR:
1321 schoenebeck 2889 printf("[ERROR] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
1322 schoenebeck 2581 break;
1323     case PARSER_WARNING:
1324 schoenebeck 2889 printf("[Warning] line %d, column %d: %s\n", firstLine, firstColumn, txt.c_str());
1325 schoenebeck 2581 break;
1326     }
1327     }
1328 schoenebeck 2727
1329     /**
1330     * Returns true if this issue is a parser error. In this case the parsed
1331     * script may not be executed!
1332     */
1333 schoenebeck 2581 inline bool isErr() const { return type == PARSER_ERROR; }
1334 schoenebeck 2727
1335     /**
1336     * Returns true if this issue is just a parser warning. A parsed script
1337     * that only raises warnings may be executed if desired, however the
1338     * script may not behave exactly as intended by the script author.
1339     */
1340 schoenebeck 2581 inline bool isWrn() const { return type == PARSER_WARNING; }
1341     };
1342    
1343 schoenebeck 2727 /**
1344     * Convenience function used for converting an ExprType_t constant to a
1345     * string, i.e. for generating error message by the parser.
1346     */
1347 schoenebeck 2581 inline String typeStr(const ExprType_t& type) {
1348     switch (type) {
1349     case EMPTY_EXPR: return "empty";
1350     case INT_EXPR: return "integer";
1351     case INT_ARR_EXPR: return "integer array";
1352     case STRING_EXPR: return "string";
1353     case STRING_ARR_EXPR: return "string array";
1354     }
1355     return "invalid";
1356     }
1357    
1358 schoenebeck 3561 /**
1359     * Convenience function used for converting an StdUnit_t constant to a
1360     * string, i.e. for generating error message by the parser.
1361     */
1362     inline String unitTypeStr(const StdUnit_t& type) {
1363     switch (type) {
1364     case VM_NO_UNIT: return "none";
1365     case VM_SECOND: return "seconds";
1366     case VM_HERTZ: return "Hz";
1367     case VM_BEL: return "Bel";
1368     }
1369     return "invalid";
1370     }
1371    
1372 schoenebeck 2594 /** @brief Virtual machine representation of a script.
1373     *
1374     * An instance of this abstract base class represents a parsed script,
1375 schoenebeck 2727 * translated into a virtual machine tree. You should first check if there
1376     * were any parser errors. If there were any parser errors, you should
1377     * refrain from executing the virtual machine. Otherwise if there were no
1378     * parser errors (i.e. only warnings), then you might access one of the
1379     * script's event handlers by i.e. calling eventHandlerByName() and pass the
1380     * respective event handler to the ScriptVM class (or to one of the ScriptVM
1381 schoenebeck 2594 * descendants) for execution.
1382     *
1383 schoenebeck 2727 * @see VMExecContext, ScriptVM
1384 schoenebeck 2594 */
1385 schoenebeck 2588 class VMParserContext {
1386     public:
1387     virtual ~VMParserContext() {}
1388 schoenebeck 2727
1389     /**
1390     * Returns all noteworthy issues encountered when the script was parsed.
1391     * These are parser errors and parser warnings.
1392     */
1393 schoenebeck 2588 virtual std::vector<ParserIssue> issues() const = 0;
1394 schoenebeck 2727
1395     /**
1396     * Same as issues(), but this method only returns parser errors.
1397     */
1398 schoenebeck 2588 virtual std::vector<ParserIssue> errors() const = 0;
1399 schoenebeck 2727
1400     /**
1401     * Same as issues(), but this method only returns parser warnings.
1402     */
1403 schoenebeck 2588 virtual std::vector<ParserIssue> warnings() const = 0;
1404 schoenebeck 2727
1405     /**
1406 schoenebeck 3285 * Returns all code blocks of the script which were filtered out by the
1407     * preprocessor.
1408     */
1409     virtual std::vector<CodeBlock> preprocessorComments() const = 0;
1410    
1411     /**
1412 schoenebeck 2727 * Returns the translated virtual machine representation of an event
1413     * handler block (i.e. "on note ... end on" code block) within the
1414     * parsed script. This translated representation of the event handler
1415     * can be executed by the virtual machine.
1416     *
1417     * @param index - index of the event handler within the script
1418     */
1419 schoenebeck 2588 virtual VMEventHandler* eventHandler(uint index) = 0;
1420 schoenebeck 2727
1421     /**
1422     * Same as eventHandler(), but this method returns the event handler by
1423     * its name. So for a "on note ... end on" code block of the parsed
1424     * script you would pass "note" for argument @a name here.
1425     *
1426     * @param name - name of the event handler (i.e. "init", "note",
1427     * "controller", "release")
1428     */
1429 schoenebeck 2588 virtual VMEventHandler* eventHandlerByName(const String& name) = 0;
1430     };
1431    
1432 schoenebeck 2885 class SourceToken;
1433    
1434     /** @brief Recognized token of a script's source code.
1435     *
1436     * Represents one recognized token of a script's source code, for example
1437     * a keyword, variable name, etc. and it provides further informations about
1438     * that particular token, i.e. the precise location (line and column) of the
1439     * token within the original script's source code.
1440     *
1441     * This class is not actually used by the sampler itself. It is rather
1442     * provided for external script editor applications. Primary purpose of
1443     * this class is syntax highlighting for external script editors.
1444 schoenebeck 3012 *
1445     * @see ParserIssue for processing compile errors and warnings instead.
1446 schoenebeck 2885 */
1447     class VMSourceToken {
1448     public:
1449     VMSourceToken();
1450     VMSourceToken(SourceToken* ct);
1451     VMSourceToken(const VMSourceToken& other);
1452     virtual ~VMSourceToken();
1453    
1454     // original text of this token as it is in the script's source code
1455     String text() const;
1456    
1457     // position of token in script
1458 schoenebeck 3012 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.
1459     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().
1460 schoenebeck 2885
1461     // base types
1462 schoenebeck 3012 bool isEOF() const; ///< Returns true in case this source token represents the end of the source code file.
1463     bool isNewLine() const; ///< Returns true in case this source token represents a line feed character (i.e. "\n" on Unix systems).
1464     bool isKeyword() const; ///< Returns true in case this source token represents a language keyword (i.e. "while", "function", "declare", "on", etc.).
1465     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.
1466     bool isIdentifier() const; ///< Returns true in case this source token represents an identifier, which currently always means a function name.
1467     bool isNumberLiteral() const; ///< Returns true in case this source token represents a number literal (i.e. 123).
1468     bool isStringLiteral() const; ///< Returns true in case this source token represents a string literal (i.e. "Some text").
1469     bool isComment() const; ///< Returns true in case this source token represents a source code comment.
1470     bool isPreprocessor() const; ///< Returns true in case this source token represents a preprocessor statement.
1471 schoenebeck 3562 bool isMetricPrefix() const;
1472     bool isStdUnit() const;
1473 schoenebeck 3012 bool isOther() const; ///< Returns true in case this source token represents anything else not covered by the token types mentioned above.
1474 schoenebeck 2885
1475     // extended types
1476 schoenebeck 3012 bool isIntegerVariable() const; ///< Returns true in case this source token represents an integer variable name (i.e. "$someIntVariable").
1477     bool isStringVariable() const; ///< Returns true in case this source token represents an string variable name (i.e. "\@someStringVariable").
1478     bool isArrayVariable() const; ///< Returns true in case this source token represents an array variable name (i.e. "%someArryVariable").
1479     bool isEventHandlerName() const; ///< Returns true in case this source token represents an event handler name (i.e. "note", "release", "controller").
1480 schoenebeck 2885
1481     VMSourceToken& operator=(const VMSourceToken& other);
1482    
1483     private:
1484     SourceToken* m_token;
1485     };
1486    
1487 schoenebeck 2581 } // namespace LinuxSampler
1488    
1489     #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

  ViewVC Help
Powered by ViewVC