1 |
/* |
/* |
2 |
* Copyright (c) 2014 Christian Schoenebeck |
* Copyright (c) 2014-2015 Christian Schoenebeck |
3 |
* |
* |
4 |
* http://www.linuxsampler.org |
* http://www.linuxsampler.org |
5 |
* |
* |
20 |
#include <stddef.h> // offsetof() |
#include <stddef.h> // offsetof() |
21 |
|
|
22 |
namespace LinuxSampler { |
namespace LinuxSampler { |
23 |
|
|
24 |
|
/** |
25 |
|
* Identifies the type of a noteworthy issue identified by the script |
26 |
|
* parser. That's either a parser error or parser warning. |
27 |
|
*/ |
28 |
enum ParserIssueType_t { |
enum ParserIssueType_t { |
29 |
PARSER_ERROR, |
PARSER_ERROR, ///< Script parser encountered an error, the script cannot be executed. |
30 |
PARSER_WARNING |
PARSER_WARNING ///< Script parser encountered a warning, the script may be executed if desired, but the script may not necessarily behave as originally intended by the script author. |
31 |
}; |
}; |
32 |
|
|
33 |
|
/** @brief Expression's data type. |
34 |
|
* |
35 |
|
* Identifies to which data type an expression within a script evaluates to. |
36 |
|
* This can for example reflect the data type of script function arguments, |
37 |
|
* script function return values, but also the resulting data type of some |
38 |
|
* mathematical formula within a script. |
39 |
|
*/ |
40 |
enum ExprType_t { |
enum ExprType_t { |
41 |
EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value |
EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value (the built-in wait() or message() functions for instance) |
42 |
INT_EXPR, |
INT_EXPR, ///< integer (scalar) expression |
43 |
INT_ARR_EXPR, |
INT_ARR_EXPR, ///< integer array expression |
44 |
STRING_EXPR, |
STRING_EXPR, ///< string expression |
45 |
STRING_ARR_EXPR, |
STRING_ARR_EXPR, ///< string array expression |
46 |
}; |
}; |
47 |
|
|
48 |
|
/** @brief Result flags of a script statement or script function call. |
49 |
|
* |
50 |
|
* A set of bit flags which provide informations about the success or |
51 |
|
* failure of a statement within a script. That's also especially used for |
52 |
|
* providing informations about success / failure of a call to a built-in |
53 |
|
* script function. The virtual machine evaluates these flags during runtime |
54 |
|
* to decide whether it should i.e. stop or suspend execution of a script. |
55 |
|
* |
56 |
|
* Since these are bit flags, these constants are bitwise combined. |
57 |
|
*/ |
58 |
enum StmtFlags_t { |
enum StmtFlags_t { |
59 |
STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred. |
STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred. |
60 |
STMT_ABORT_SIGNALLED = 1, ///< VM should stop the current callback execution (usually because of an error, but might also be without an error reason). |
STMT_ABORT_SIGNALLED = 1, ///< VM should stop the current callback execution (usually because of an error, but might also be without an error reason, i.e. when the built-in script function exit() was called). |
61 |
STMT_SUSPEND_SIGNALLED = (1<<1), |
STMT_SUSPEND_SIGNALLED = (1<<1), ///< VM supended execution, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time |
62 |
STMT_ERROR_OCCURRED = (1<<2), |
STMT_ERROR_OCCURRED = (1<<2), ///< VM stopped execution due to some script runtime error that occurred |
63 |
}; |
}; |
64 |
|
|
65 |
|
/** @brief Virtual machine execution status. |
66 |
|
* |
67 |
|
* A set of bit flags which reflect the current overall execution status of |
68 |
|
* the virtual machine concerning a certain script execution instance. |
69 |
|
* |
70 |
|
* Since these are bit flags, these constants are bitwise combined. |
71 |
|
*/ |
72 |
enum VMExecStatus_t { |
enum VMExecStatus_t { |
73 |
VM_EXEC_NOT_RUNNING = 0, |
VM_EXEC_NOT_RUNNING = 0, ///< Script is currently not executed by the VM. |
74 |
VM_EXEC_RUNNING = 1, |
VM_EXEC_RUNNING = 1, ///< The VM is currently executing the script. |
75 |
VM_EXEC_SUSPENDED = (1<<1), |
VM_EXEC_SUSPENDED = (1<<1), ///< Script is currently suspended by the VM, either because the script called the built-in wait() script function or because the script consumed too much execution time and was forced by the VM to be suspended for some time. |
76 |
VM_EXEC_ERROR = (1<<2), |
VM_EXEC_ERROR = (1<<2), ///< A runtime error occurred while executing the script (i.e. a call to some built-in script function failed). |
77 |
}; |
}; |
78 |
|
|
79 |
|
// just symbol prototyping |
80 |
class VMIntExpr; |
class VMIntExpr; |
81 |
class VMStringExpr; |
class VMStringExpr; |
82 |
class VMIntArrayExpr; |
class VMIntArrayExpr; |
83 |
class VMStringArrayExpr; |
class VMStringArrayExpr; |
84 |
|
|
85 |
|
/** @brief Virtual machine expression |
86 |
|
* |
87 |
|
* This is the abstract base class for all expressions of scripts. |
88 |
|
* Deriving classes must implement the abstract method exprType(). |
89 |
|
* |
90 |
|
* An expression within a script is translated into one instance of this |
91 |
|
* class. It allows a high level access for the virtual machine to evaluate |
92 |
|
* and handle expressions appropriately during execution. Expressions are |
93 |
|
* for example all kinds of formulas, function calls, statements or a |
94 |
|
* combination of them. Most of them evaluate to some kind of value, which |
95 |
|
* might be further processed as part of encompassing expressions to outer |
96 |
|
* expression results and so forth. |
97 |
|
*/ |
98 |
class VMExpr { |
class VMExpr { |
99 |
public: |
public: |
100 |
|
/** |
101 |
|
* Identifies the data type to which the result of this expression |
102 |
|
* evaluates to. This abstract method must be implemented by deriving |
103 |
|
* classes. |
104 |
|
*/ |
105 |
virtual ExprType_t exprType() const = 0; |
virtual ExprType_t exprType() const = 0; |
106 |
|
|
107 |
|
/** |
108 |
|
* In case this expression is an integer expression, then this method |
109 |
|
* returns a casted pointer to that VMIntExpr object. It returns NULL |
110 |
|
* if this expression is not an integer expression. |
111 |
|
* |
112 |
|
* @b Note: type casting performed by this method is strict! That means |
113 |
|
* if this expression is i.e. actually a string expression like "12", |
114 |
|
* calling asInt() will @b not cast that numerical string expression to |
115 |
|
* an integer expression 12 for you, instead this method will simply |
116 |
|
* return NULL! |
117 |
|
* |
118 |
|
* @see exprType() |
119 |
|
*/ |
120 |
VMIntExpr* asInt() const; |
VMIntExpr* asInt() const; |
121 |
|
|
122 |
|
/** |
123 |
|
* In case this expression is a string expression, then this method |
124 |
|
* returns a casted pointer to that VMStringExpr object. It returns NULL |
125 |
|
* if this expression is not a string expression. |
126 |
|
* |
127 |
|
* @b Note: type casting performed by this method is strict! That means |
128 |
|
* if this expression is i.e. actually an integer expression like 120, |
129 |
|
* calling asString() will @b not cast that integer expression to a |
130 |
|
* string expression "120" for you, instead this method will simply |
131 |
|
* return NULL! |
132 |
|
* |
133 |
|
* @see exprType() |
134 |
|
*/ |
135 |
VMStringExpr* asString() const; |
VMStringExpr* asString() const; |
136 |
|
|
137 |
|
/** |
138 |
|
* In case this expression is an integer array expression, then this |
139 |
|
* method returns a casted pointer to that VMIntArrayExpr object. It |
140 |
|
* returns NULL if this expression is not an integer array expression. |
141 |
|
* |
142 |
|
* @b Note: type casting performed by this method is strict! That means |
143 |
|
* if this expression is i.e. an integer expression or a string |
144 |
|
* expression, calling asIntArray() will @b not cast those scalar |
145 |
|
* expressions to an array expression for you, instead this method will |
146 |
|
* simply return NULL! |
147 |
|
* |
148 |
|
* @see exprType() |
149 |
|
*/ |
150 |
VMIntArrayExpr* asIntArray() const; |
VMIntArrayExpr* asIntArray() const; |
151 |
}; |
}; |
152 |
|
|
153 |
|
/** @brief Virtual machine integer expression |
154 |
|
* |
155 |
|
* This is the abstract base class for all expressions inside scripts which |
156 |
|
* evaluate to an integer (scalar) value. Deriving classes implement the |
157 |
|
* abstract method evalInt() to return the actual integer result value of |
158 |
|
* the expression. |
159 |
|
*/ |
160 |
class VMIntExpr : virtual public VMExpr { |
class VMIntExpr : virtual public VMExpr { |
161 |
public: |
public: |
162 |
|
/** |
163 |
|
* Returns the result of this expression as integer (scalar) value. |
164 |
|
* This abstract method must be implemented by deriving classes. |
165 |
|
*/ |
166 |
virtual int evalInt() = 0; |
virtual int evalInt() = 0; |
167 |
ExprType_t exprType() const { return INT_EXPR; } |
|
168 |
|
/** |
169 |
|
* Returns always INT_EXPR for instances of this class. |
170 |
|
*/ |
171 |
|
ExprType_t exprType() const OVERRIDE { return INT_EXPR; } |
172 |
}; |
}; |
173 |
|
|
174 |
|
/** @brief Virtual machine string expression |
175 |
|
* |
176 |
|
* This is the abstract base class for all expressions inside scripts which |
177 |
|
* evaluate to a string value. Deriving classes implement the abstract |
178 |
|
* method evalStr() to return the actual string result value of the |
179 |
|
* expression. |
180 |
|
*/ |
181 |
class VMStringExpr : virtual public VMExpr { |
class VMStringExpr : virtual public VMExpr { |
182 |
public: |
public: |
183 |
|
/** |
184 |
|
* Returns the result of this expression as string value. This abstract |
185 |
|
* method must be implemented by deriving classes. |
186 |
|
*/ |
187 |
virtual String evalStr() = 0; |
virtual String evalStr() = 0; |
188 |
ExprType_t exprType() const { return STRING_EXPR; } |
|
189 |
|
/** |
190 |
|
* Returns always STRING_EXPR for instances of this class. |
191 |
|
*/ |
192 |
|
ExprType_t exprType() const OVERRIDE { return STRING_EXPR; } |
193 |
}; |
}; |
194 |
|
|
195 |
|
/** @brief Virtual Machine Array Value Expression |
196 |
|
* |
197 |
|
* This is the abstract base class for all expressions inside scripts which |
198 |
|
* evaluate to some kind of array value. Deriving classes implement the |
199 |
|
* abstract method arraySize() to return the amount of elements within the |
200 |
|
* array. |
201 |
|
*/ |
202 |
class VMArrayExpr : virtual public VMExpr { |
class VMArrayExpr : virtual public VMExpr { |
203 |
public: |
public: |
204 |
|
/** |
205 |
|
* Returns amount of elements in this array. This abstract method must |
206 |
|
* be implemented by deriving classes. |
207 |
|
*/ |
208 |
virtual int arraySize() const = 0; |
virtual int arraySize() const = 0; |
209 |
}; |
}; |
210 |
|
|
211 |
|
/** @brief Virtual Machine Integer Array Expression |
212 |
|
* |
213 |
|
* This is the abstract base class for all expressions inside scripts which |
214 |
|
* evaluate to an array of integer values. Deriving classes implement the |
215 |
|
* abstract methods arraySize(), evalIntElement() and assignIntElement() to |
216 |
|
* access the individual integer array values. |
217 |
|
*/ |
218 |
class VMIntArrayExpr : virtual public VMArrayExpr { |
class VMIntArrayExpr : virtual public VMArrayExpr { |
219 |
public: |
public: |
220 |
|
/** |
221 |
|
* Returns the (scalar) integer value of the array element given by |
222 |
|
* element index @a i. |
223 |
|
* |
224 |
|
* @param i - array element index (must be between 0 .. arraySize() - 1) |
225 |
|
*/ |
226 |
virtual int evalIntElement(uint i) = 0; |
virtual int evalIntElement(uint i) = 0; |
227 |
|
|
228 |
|
/** |
229 |
|
* Changes the current value of an element (given by array element |
230 |
|
* index @a i) of this integer array. |
231 |
|
* |
232 |
|
* @param i - array element index (must be between 0 .. arraySize() - 1) |
233 |
|
* @param value - new integer scalar value to be assigned to that array element |
234 |
|
*/ |
235 |
virtual void assignIntElement(uint i, int value) = 0; |
virtual void assignIntElement(uint i, int value) = 0; |
236 |
ExprType_t exprType() const { return INT_ARR_EXPR; } |
|
237 |
|
/** |
238 |
|
* Returns always INT_ARR_EXPR for instances of this class. |
239 |
|
*/ |
240 |
|
ExprType_t exprType() const OVERRIDE { return INT_ARR_EXPR; } |
241 |
}; |
}; |
242 |
|
|
243 |
|
/** @brief Arguments (parameters) for being passed to a built-in script function. |
244 |
|
* |
245 |
|
* An argument or a set of arguments passed to a script function are |
246 |
|
* translated by the parser to an instance of this class. This abstract |
247 |
|
* interface class is used by implementations of built-in functions to |
248 |
|
* obtain the individual function argument values being passed to them at |
249 |
|
* runtime. |
250 |
|
*/ |
251 |
class VMFnArgs { |
class VMFnArgs { |
252 |
public: |
public: |
253 |
|
/** |
254 |
|
* Returns the amount of arguments going to be passed to the script |
255 |
|
* function. |
256 |
|
*/ |
257 |
virtual int argsCount() const = 0; |
virtual int argsCount() const = 0; |
258 |
|
|
259 |
|
/** |
260 |
|
* Returns the respective argument (requested by argument index @a i) of |
261 |
|
* this set of arguments. This method is called by implementations of |
262 |
|
* built-in script functions to obtain the value of each function |
263 |
|
* argument passed to the function at runtime. |
264 |
|
* |
265 |
|
* @param i - function argument index (indexed from left to right) |
266 |
|
*/ |
267 |
virtual VMExpr* arg(int i) = 0; |
virtual VMExpr* arg(int i) = 0; |
268 |
}; |
}; |
269 |
|
|
270 |
|
/** @brief Result value returned from a call to a built-in script function. |
271 |
|
* |
272 |
|
* Implementations of built-in script functions return an instance of this |
273 |
|
* object to let the virtual machine obtain the result value of the function |
274 |
|
* call, which might then be further processed by the virtual machine |
275 |
|
* according to the script. It also provides informations about the success |
276 |
|
* or failure of the function call. |
277 |
|
*/ |
278 |
class VMFnResult { |
class VMFnResult { |
279 |
public: |
public: |
280 |
|
/** |
281 |
|
* Returns the result value of the function call, represented by a high |
282 |
|
* level expression object. |
283 |
|
*/ |
284 |
virtual VMExpr* resultValue() = 0; |
virtual VMExpr* resultValue() = 0; |
285 |
|
|
286 |
|
/** |
287 |
|
* Provides detailed informations of the success / failure of the |
288 |
|
* function call. The virtual machine is evaluating the flags returned |
289 |
|
* here to decide whether it must abort or suspend execution of the |
290 |
|
* script at this point. |
291 |
|
*/ |
292 |
virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; } |
virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; } |
293 |
}; |
}; |
294 |
|
|
295 |
/** @brief VM built-in function. |
/** @brief Virtual machine built-in function. |
296 |
* |
* |
297 |
* Abstract base class for built-in script functions, defining the interface |
* Abstract base class for built-in script functions, defining the interface |
298 |
* for all built-in script function implementations. |
* for all built-in script function implementations. All built-in script |
299 |
|
* functions are deriving from this abstract interface class in order to |
300 |
|
* provide their functionality to the virtual machine with this unified |
301 |
|
* interface. |
302 |
|
* |
303 |
|
* The methods of this interface class provide two purposes: |
304 |
|
* |
305 |
|
* 1. When a script is loaded, the script parser uses the methods of this |
306 |
|
* interface to check whether the script author was calling the |
307 |
|
* respective built-in script function in a correct way. For example |
308 |
|
* the parser checks whether the required amount of parameters were |
309 |
|
* passed to the function and whether the data types passed match the |
310 |
|
* data types expected by the function. If not, loading the script will |
311 |
|
* be aborted with a parser error, describing to the user (i.e. script |
312 |
|
* author) the precise misusage of the respective function. |
313 |
|
* 2. After the script was loaded successfully and the script is executed, |
314 |
|
* the virtual machine calls the exec() method of the respective built-in |
315 |
|
* function to provide the actual functionality of the built-in function |
316 |
|
* call. |
317 |
*/ |
*/ |
318 |
class VMFunction { |
class VMFunction { |
319 |
public: |
public: |
320 |
/** |
/** |
321 |
* 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 |
322 |
* not return any value, then it returns EMPTY_EXPR here. |
* not return any value (void), then it returns EMPTY_EXPR here. |
323 |
*/ |
*/ |
324 |
virtual ExprType_t returnType() = 0; |
virtual ExprType_t returnType() = 0; |
325 |
|
|
349 |
* that case to the type it actually needs. |
* that case to the type it actually needs. |
350 |
* |
* |
351 |
* @param iArg - index of the function argument in question |
* @param iArg - index of the function argument in question |
352 |
|
* (must be between 0 .. maxAllowedArgs() - 1) |
353 |
*/ |
*/ |
354 |
virtual ExprType_t argType(int iArg) const = 0; |
virtual ExprType_t argType(int iArg) const = 0; |
355 |
|
|
357 |
* This function is called by the parser to check whether arguments |
* This function is called by the parser to check whether arguments |
358 |
* passed in scripts to this function are accepted by this function. If |
* passed in scripts to this function are accepted by this function. If |
359 |
* a script calls this function with an argument's data type not |
* a script calls this function with an argument's data type not |
360 |
* accepted by this function, the parser will throw a parser error. |
* accepted by this function, the parser will throw a parser error. On |
361 |
|
* such errors the data type returned by argType() will be used to |
362 |
|
* assemble an appropriate error message regarding the precise misusage |
363 |
|
* of the built-in function. |
364 |
* |
* |
365 |
* @param iArg - index of the function argument in question |
* @param iArg - index of the function argument in question |
366 |
|
* (must be between 0 .. maxAllowedArgs() - 1) |
367 |
* @param type - script data type used for this function argument by |
* @param type - script data type used for this function argument by |
368 |
* currently parsed script |
* currently parsed script |
369 |
|
* @return true if the given data type would be accepted for the |
370 |
|
* respective function argument by the function |
371 |
*/ |
*/ |
372 |
virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0; |
virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0; |
373 |
|
|
374 |
/** |
/** |
375 |
* Implements the actual function execution. This function is called by |
* Implements the actual function execution. This exec() method is |
376 |
* the VM when this function shall be executed at script runtime. |
* called by the VM whenever this function implementation shall be |
377 |
|
* executed at script runtime. This method blocks until the function |
378 |
|
* call completed. |
379 |
* |
* |
380 |
* @param args - function arguments for executing this built-in function |
* @param args - function arguments for executing this built-in function |
381 |
|
* @returns function's return value (if any) and general status |
382 |
|
* informations (i.e. whether the function call caused a |
383 |
|
* runtime error) |
384 |
*/ |
*/ |
385 |
virtual VMFnResult* exec(VMFnArgs* args) = 0; |
virtual VMFnResult* exec(VMFnArgs* args) = 0; |
386 |
|
|
387 |
/** |
/** |
388 |
* Concenience method for function implementations to show warning |
* Convenience method for function implementations to show warning |
389 |
* messages. |
* messages during actual execution of the built-in function. |
390 |
* |
* |
391 |
* @param txt - warning text |
* @param txt - runtime warning text to be shown to user |
392 |
*/ |
*/ |
393 |
void wrnMsg(const String& txt); |
void wrnMsg(const String& txt); |
394 |
|
|
395 |
/** |
/** |
396 |
* Concenience method for function implementations to show error |
* Convenience method for function implementations to show error |
397 |
* messages. |
* messages during actual execution of the built-in function. |
398 |
* |
* |
399 |
* @param txt - error text |
* @param txt - runtime error text to be shown to user |
400 |
*/ |
*/ |
401 |
void errMsg(const String& txt); |
void errMsg(const String& txt); |
402 |
}; |
}; |
403 |
|
|
404 |
/** |
/** @brief Virtual machine relative pointer. |
405 |
|
* |
406 |
* POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be |
* POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be |
407 |
* used directly. Use VMIntRelPtr or VMInt8RelPtr instead. |
* used directly. Use VMIntRelPtr or VMInt8RelPtr instead. |
408 |
|
* |
409 |
|
* @see VMIntRelPtr, VMInt8RelPtr |
410 |
*/ |
*/ |
411 |
struct VMRelPtr { |
struct VMRelPtr { |
412 |
void** base; ///< Base pointer. |
void** base; ///< Base pointer. |
413 |
int offset; ///< Offset (in bytes) to base pointer. |
int offset; ///< Offset (in bytes) relative to base pointer. |
414 |
}; |
}; |
415 |
|
|
416 |
/** @brief Pointer to built-in VM integer variable (of C/C++ type int). |
/** @brief Pointer to built-in VM integer variable (of C/C++ type int). |
417 |
* |
* |
418 |
* Used for defining built-in integer script variables. |
* Used for defining built-in 32 bit integer script variables. |
419 |
* |
* |
420 |
* @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 |
421 |
* of type "int" (which on most systems is 32 bit in size). If the C/C++ int |
* of type "int" (which on most systems is 32 bit in size). If the C/C++ int |
449 |
|
|
450 |
/** @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). |
451 |
* |
* |
452 |
* Used for defining built-in integer script variables. |
* Used for defining built-in 8 bit integer script variables. |
453 |
* |
* |
454 |
* @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 |
455 |
* 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 |
481 |
|
|
482 |
/** |
/** |
483 |
* Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr |
* Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr |
484 |
* structures. Example: |
* structures. Usage example: |
485 |
* @code |
* @code |
486 |
* struct Foo { |
* struct Foo { |
487 |
* uint8_t a; |
* uint8_t a; // native representation of a built-in integer script variable |
488 |
* int b; |
* int b; // native representation of another built-in integer script variable |
489 |
|
* int c; // native representation of another built-in integer script variable |
490 |
|
* uint8_t d; // native representation of another built-in integer script variable |
491 |
* }; |
* }; |
492 |
* |
* |
493 |
* Foo foo1 = (Foo) { 1, 3000 }; |
* // initializing the built-in script variables to some values |
494 |
* Foo foo2 = (Foo) { 2, 4000 }; |
* Foo foo1 = (Foo) { 1, 2000, 3000, 4 }; |
495 |
|
* Foo foo2 = (Foo) { 5, 6000, 7000, 8 }; |
496 |
* |
* |
497 |
* Foo* pFoo; |
* Foo* pFoo; |
498 |
* |
* |
499 |
* VMInt8RelPtr var1 = DECLARE_VMINT(pFoo, class Foo, a); |
* VMInt8RelPtr varA = DECLARE_VMINT(pFoo, class Foo, a); |
500 |
* VMIntRelPtr var2 = DECLARE_VMINT(pFoo, class Foo, b); |
* VMIntRelPtr varB = DECLARE_VMINT(pFoo, class Foo, b); |
501 |
|
* VMIntRelPtr varC = DECLARE_VMINT(pFoo, class Foo, c); |
502 |
|
* VMInt8RelPtr varD = DECLARE_VMINT(pFoo, class Foo, d); |
503 |
* |
* |
504 |
* pFoo = &foo1; |
* pFoo = &foo1; |
505 |
* printf("%d\n", var1->evalInt()); // will print 1 |
* printf("%d\n", varA->evalInt()); // will print 1 |
506 |
* printf("%d\n", var2->evalInt()); // will print 3000 |
* printf("%d\n", varB->evalInt()); // will print 2000 |
507 |
|
* printf("%d\n", varC->evalInt()); // will print 3000 |
508 |
|
* printf("%d\n", varD->evalInt()); // will print 4 |
509 |
|
* |
510 |
|
* // same printf() code, just with pFoo pointer being changed ... |
511 |
* |
* |
512 |
* pFoo = &foo2; |
* pFoo = &foo2; |
513 |
* printf("%d\n", var1->evalInt()); // will print 2 |
* printf("%d\n", varA->evalInt()); // will print 5 |
514 |
* printf("%d\n", var2->evalInt()); // will print 4000 |
* printf("%d\n", varB->evalInt()); // will print 6000 |
515 |
|
* printf("%d\n", varC->evalInt()); // will print 7000 |
516 |
|
* printf("%d\n", varD->evalInt()); // will print 8 |
517 |
* @endcode |
* @endcode |
518 |
|
* As you can see above, by simply changing one single pointer, you can |
519 |
|
* remap a huge bunch of built-in integer script variables to completely |
520 |
|
* different native values/native variables. Which especially reduces code |
521 |
|
* complexity inside the sampler engines which provide the actual script |
522 |
|
* functionalities. |
523 |
*/ |
*/ |
524 |
#define DECLARE_VMINT(basePtr, T_struct, T_member) ( \ |
#define DECLARE_VMINT(basePtr, T_struct, T_member) ( \ |
525 |
(VMRelPtr) { \ |
(VMRelPtr) { \ |
530 |
|
|
531 |
/** @brief Built-in VM 8 bit integer array variable. |
/** @brief Built-in VM 8 bit integer array variable. |
532 |
* |
* |
533 |
* Used for defining built-in integer array script variables. |
* Used for defining built-in integer array script variables (8 bit per |
534 |
|
* array element). Currently there is no support for any other kind of array |
535 |
|
* type. So all integer arrays of scripts use 8 bit data types. |
536 |
*/ |
*/ |
537 |
struct VMInt8Array { |
struct VMInt8Array { |
538 |
int8_t* data; |
int8_t* data; |
543 |
|
|
544 |
/** @brief Provider for built-in script functions and variables. |
/** @brief Provider for built-in script functions and variables. |
545 |
* |
* |
546 |
* Abstract base class defining the interface for all classes which add and |
* Abstract base class defining the high-level interface for all classes |
547 |
* implement built-in script functions and built-in script variables. |
* which add and implement built-in script functions and built-in script |
548 |
|
* variables. |
549 |
*/ |
*/ |
550 |
class VMFunctionProvider { |
class VMFunctionProvider { |
551 |
public: |
public: |
552 |
/** |
/** |
553 |
* Returns pointer to the built-in function with the given function |
* Returns pointer to the built-in function with the given function |
554 |
* name, or NULL if there is no built-in function with that name. |
* @a name, or NULL if there is no built-in function with that function |
555 |
|
* name. |
556 |
* |
* |
557 |
* @param name - function name |
* @param name - function name (i.e. "wait" or "message" or "exit", etc.) |
558 |
*/ |
*/ |
559 |
virtual VMFunction* functionByName(const String& name) = 0; |
virtual VMFunction* functionByName(const String& name) = 0; |
560 |
|
|
561 |
/** |
/** |
562 |
* Returns a variable name indexed map of all built-in script variables |
* Returns a variable name indexed map of all built-in script variables |
563 |
* which point to native "int" (usually 32 bit) variables. |
* which point to native "int" scalar (usually 32 bit) variables. |
564 |
*/ |
*/ |
565 |
virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0; |
virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0; |
566 |
|
|
567 |
/** |
/** |
568 |
* Returns a variable name indexed map of all built-in script variables |
* Returns a variable name indexed map of all built-in script integer |
569 |
* which point to native "int8_t" (8 bit) variables. |
* array variables with array element type "int8_t" (8 bit). |
570 |
*/ |
*/ |
571 |
virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0; |
virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0; |
572 |
|
|
582 |
* An instance of this abstract base class represents exactly one execution |
* An instance of this abstract base class represents exactly one execution |
583 |
* state of a virtual machine. This encompasses most notably the VM |
* state of a virtual machine. This encompasses most notably the VM |
584 |
* execution stack, and VM polyphonic variables. It does not contain global |
* execution stack, and VM polyphonic variables. It does not contain global |
585 |
* variable. Global variables are contained in the VMParserContext object. |
* variables. Global variables are contained in the VMParserContext object. |
586 |
* You might see a VMExecContext object as one virtual thread of the virtual |
* You might see a VMExecContext object as one virtual thread of the virtual |
587 |
* machine. |
* machine. |
588 |
* |
* |
595 |
class VMExecContext { |
class VMExecContext { |
596 |
public: |
public: |
597 |
virtual ~VMExecContext() {} |
virtual ~VMExecContext() {} |
598 |
|
|
599 |
|
/** |
600 |
|
* In case the script was suspended for some reason, this method returns |
601 |
|
* the amount of microseconds before the script shall continue its |
602 |
|
* execution. Note that the virtual machine itself does never put its |
603 |
|
* own execution thread(s) to sleep. So the respective class (i.e. sampler |
604 |
|
* engine) which is using the virtual machine classes here, must take |
605 |
|
* care by itself about taking time stamps, determining the script |
606 |
|
* handlers that shall be put aside for the requested amount of |
607 |
|
* microseconds indicated by this method by comparing the time stamps in |
608 |
|
* real-time, and to continue passing the respective handler to |
609 |
|
* ScriptVM::exec() as soon as its suspension exceeded, etc. Or in other |
610 |
|
* words: all classes in this directory never have an idea what time it |
611 |
|
* is. |
612 |
|
* |
613 |
|
* You should check the return value of ScriptVM::exec() to determine |
614 |
|
* whether the script was actually suspended before calling this method |
615 |
|
* here. |
616 |
|
* |
617 |
|
* @see ScriptVM::exec() |
618 |
|
*/ |
619 |
virtual int suspensionTimeMicroseconds() const = 0; |
virtual int suspensionTimeMicroseconds() const = 0; |
620 |
}; |
}; |
621 |
|
|
622 |
/** @brief Script callback for a certain event. |
/** @brief Script callback for a certain event. |
623 |
* |
* |
624 |
* Represents a script callback for a certain event, i.e. |
* Represents a script callback for a certain event, i.e. |
625 |
* "on note ... end on". |
* "on note ... end on" code block. |
626 |
*/ |
*/ |
627 |
class VMEventHandler { |
class VMEventHandler { |
628 |
public: |
public: |
640 |
virtual bool isPolyphonic() const = 0; |
virtual bool isPolyphonic() const = 0; |
641 |
}; |
}; |
642 |
|
|
643 |
|
/** |
644 |
|
* Encapsulates a noteworty parser issue. This encompasses the type of the |
645 |
|
* issue (either a parser error or parser warning), a human readable |
646 |
|
* explanation text of the error or warning and the location of the |
647 |
|
* encountered parser issue within the script. |
648 |
|
*/ |
649 |
struct ParserIssue { |
struct ParserIssue { |
650 |
String txt; |
String txt; ///< Human readable explanation text of the parser issue. |
651 |
int line; |
int line; ///< Line number within the script where this issue was encountered. |
652 |
ParserIssueType_t type; |
ParserIssueType_t type; ///< Whether this issue is either a parser error or just a parser warning. |
653 |
|
|
654 |
|
/** |
655 |
|
* Print this issue out to the console (stdio). |
656 |
|
*/ |
657 |
inline void dump() { |
inline void dump() { |
658 |
switch (type) { |
switch (type) { |
659 |
case PARSER_ERROR: |
case PARSER_ERROR: |
664 |
break; |
break; |
665 |
} |
} |
666 |
} |
} |
667 |
|
|
668 |
|
/** |
669 |
|
* Returns true if this issue is a parser error. In this case the parsed |
670 |
|
* script may not be executed! |
671 |
|
*/ |
672 |
inline bool isErr() const { return type == PARSER_ERROR; } |
inline bool isErr() const { return type == PARSER_ERROR; } |
673 |
|
|
674 |
|
/** |
675 |
|
* Returns true if this issue is just a parser warning. A parsed script |
676 |
|
* that only raises warnings may be executed if desired, however the |
677 |
|
* script may not behave exactly as intended by the script author. |
678 |
|
*/ |
679 |
inline bool isWrn() const { return type == PARSER_WARNING; } |
inline bool isWrn() const { return type == PARSER_WARNING; } |
680 |
}; |
}; |
681 |
|
|
682 |
|
/** |
683 |
|
* Convenience function used for converting an ExprType_t constant to a |
684 |
|
* string, i.e. for generating error message by the parser. |
685 |
|
*/ |
686 |
inline String typeStr(const ExprType_t& type) { |
inline String typeStr(const ExprType_t& type) { |
687 |
switch (type) { |
switch (type) { |
688 |
case EMPTY_EXPR: return "empty"; |
case EMPTY_EXPR: return "empty"; |
697 |
/** @brief Virtual machine representation of a script. |
/** @brief Virtual machine representation of a script. |
698 |
* |
* |
699 |
* An instance of this abstract base class represents a parsed script, |
* An instance of this abstract base class represents a parsed script, |
700 |
* translated into a virtual machine. You should first check if there were |
* translated into a virtual machine tree. You should first check if there |
701 |
* any parser errors. If there were any parser errors, you should refrain |
* were any parser errors. If there were any parser errors, you should |
702 |
* from executing the virtual machine. Otherwise if there were no parser |
* refrain from executing the virtual machine. Otherwise if there were no |
703 |
* errors (i.e. only warnings), then you might access one of the script's |
* parser errors (i.e. only warnings), then you might access one of the |
704 |
* event handlers by i.e. calling eventHandlerByName() and pass the |
* script's event handlers by i.e. calling eventHandlerByName() and pass the |
705 |
* respective event handler to the ScriptVM class (or to one of its |
* respective event handler to the ScriptVM class (or to one of the ScriptVM |
706 |
* descendants) for execution. |
* descendants) for execution. |
707 |
* |
* |
708 |
* @see VMExecContext |
* @see VMExecContext, ScriptVM |
709 |
*/ |
*/ |
710 |
class VMParserContext { |
class VMParserContext { |
711 |
public: |
public: |
712 |
virtual ~VMParserContext() {} |
virtual ~VMParserContext() {} |
713 |
|
|
714 |
|
/** |
715 |
|
* Returns all noteworthy issues encountered when the script was parsed. |
716 |
|
* These are parser errors and parser warnings. |
717 |
|
*/ |
718 |
virtual std::vector<ParserIssue> issues() const = 0; |
virtual std::vector<ParserIssue> issues() const = 0; |
719 |
|
|
720 |
|
/** |
721 |
|
* Same as issues(), but this method only returns parser errors. |
722 |
|
*/ |
723 |
virtual std::vector<ParserIssue> errors() const = 0; |
virtual std::vector<ParserIssue> errors() const = 0; |
724 |
|
|
725 |
|
/** |
726 |
|
* Same as issues(), but this method only returns parser warnings. |
727 |
|
*/ |
728 |
virtual std::vector<ParserIssue> warnings() const = 0; |
virtual std::vector<ParserIssue> warnings() const = 0; |
729 |
|
|
730 |
|
/** |
731 |
|
* Returns the translated virtual machine representation of an event |
732 |
|
* handler block (i.e. "on note ... end on" code block) within the |
733 |
|
* parsed script. This translated representation of the event handler |
734 |
|
* can be executed by the virtual machine. |
735 |
|
* |
736 |
|
* @param index - index of the event handler within the script |
737 |
|
*/ |
738 |
virtual VMEventHandler* eventHandler(uint index) = 0; |
virtual VMEventHandler* eventHandler(uint index) = 0; |
739 |
|
|
740 |
|
/** |
741 |
|
* Same as eventHandler(), but this method returns the event handler by |
742 |
|
* its name. So for a "on note ... end on" code block of the parsed |
743 |
|
* script you would pass "note" for argument @a name here. |
744 |
|
* |
745 |
|
* @param name - name of the event handler (i.e. "init", "note", |
746 |
|
* "controller", "release") |
747 |
|
*/ |
748 |
virtual VMEventHandler* eventHandlerByName(const String& name) = 0; |
virtual VMEventHandler* eventHandlerByName(const String& name) = 0; |
749 |
}; |
}; |
750 |
|
|