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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2645 - (show annotations) (download) (as text)
Wed Jun 18 00:14:57 2014 UTC (5 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 15399 byte(s)
* RT instrument scripts: Pass/preserve polyphonic variable data
  from respective "note" event handler to "release" event handler.
* Fixed theoretical memory leak regarding instrument scripts.
* Bumped version (1.0.0.svn54).

1 /*
2 * Copyright (c) 2014 Christian Schoenebeck
3 *
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 // (located at other source directories).
13
14 #ifndef LS_INSTR_SCRIPT_PARSER_COMMON_H
15 #define LS_INSTR_SCRIPT_PARSER_COMMON_H
16
17 #include "../common/global.h"
18 #include <vector>
19 #include <map>
20 #include <stddef.h> // offsetof()
21
22 namespace LinuxSampler {
23
24 enum ParserIssueType_t {
25 PARSER_ERROR,
26 PARSER_WARNING
27 };
28
29 enum ExprType_t {
30 EMPTY_EXPR, ///< i.e. on invalid expressions or i.e. a function call that does not return a result value
31 INT_EXPR,
32 INT_ARR_EXPR,
33 STRING_EXPR,
34 STRING_ARR_EXPR,
35 };
36
37 enum StmtFlags_t {
38 STMT_SUCCESS = 0, ///< Function / statement was executed successfully, no error occurred.
39 STMT_ABORT_SIGNALLED = 1, ///< VM should stop the current callback execution (usually because of an error, but might also be without an error reason).
40 STMT_SUSPEND_SIGNALLED = (1<<1),
41 STMT_ERROR_OCCURRED = (1<<2),
42 };
43
44 enum VMExecStatus_t {
45 VM_EXEC_NOT_RUNNING = 0,
46 VM_EXEC_RUNNING = 1,
47 VM_EXEC_SUSPENDED = (1<<1),
48 VM_EXEC_ERROR = (1<<2),
49 };
50
51 class VMIntExpr;
52 class VMStringExpr;
53 class VMIntArrayExpr;
54 class VMStringArrayExpr;
55
56 class VMExpr {
57 public:
58 virtual ExprType_t exprType() const = 0;
59 VMIntExpr* asInt() const;
60 VMStringExpr* asString() const;
61 VMIntArrayExpr* asIntArray() const;
62 };
63
64 class VMIntExpr : virtual public VMExpr {
65 public:
66 virtual int evalInt() = 0;
67 ExprType_t exprType() const { return INT_EXPR; }
68 };
69
70 class VMStringExpr : virtual public VMExpr {
71 public:
72 virtual String evalStr() = 0;
73 ExprType_t exprType() const { return STRING_EXPR; }
74 };
75
76 class VMArrayExpr : virtual public VMExpr {
77 public:
78 virtual int arraySize() const = 0;
79 };
80
81 class VMIntArrayExpr : virtual public VMArrayExpr {
82 public:
83 virtual int evalIntElement(uint i) = 0;
84 virtual void assignIntElement(uint i, int value) = 0;
85 ExprType_t exprType() const { return INT_ARR_EXPR; }
86 };
87
88 class VMFnArgs {
89 public:
90 virtual int argsCount() const = 0;
91 virtual VMExpr* arg(int i) = 0;
92 };
93
94 class VMFnResult {
95 public:
96 virtual VMExpr* resultValue() = 0;
97 virtual StmtFlags_t resultFlags() { return STMT_SUCCESS; }
98 };
99
100 /** @brief VM built-in function.
101 *
102 * Abstract base class for built-in script functions, defining the interface
103 * for all built-in script function implementations.
104 */
105 class VMFunction {
106 public:
107 /**
108 * Script data type of the function's return value. If the function does
109 * not return any value, then it returns EMPTY_EXPR here.
110 */
111 virtual ExprType_t returnType() = 0;
112
113 /**
114 * Minimum amount of function arguments this function accepts. If a
115 * script is calling this function with less arguments, the script
116 * parser will throw a parser error.
117 */
118 virtual int minRequiredArgs() const = 0;
119
120 /**
121 * Maximum amount of function arguments this functions accepts. If a
122 * script is calling this function with more arguments, the script
123 * parser will throw a parser error.
124 */
125 virtual int maxAllowedArgs() const = 0;
126
127 /**
128 * Script data type of the function's @c iArg 'th function argument.
129 * The information provided here is less strong than acceptsArgType().
130 * The parser will compare argument data types provided in scripts by
131 * calling cceptsArgType(). The return value of argType() is used by the
132 * parser instead to show an appropriate parser error which data type
133 * this function usually expects as "default" data type. Reason: a
134 * function may accept multiple data types for a certain function
135 * argument and would automatically cast the passed argument value in
136 * that case to the type it actually needs.
137 *
138 * @param iArg - index of the function argument in question
139 */
140 virtual ExprType_t argType(int iArg) const = 0;
141
142 /**
143 * This function is called by the parser to check whether arguments
144 * passed in scripts to this function are accepted by this function. If
145 * a script calls this function with an argument's data type not
146 * accepted by this function, the parser will throw a parser error.
147 *
148 * @param iArg - index of the function argument in question
149 * @param type - script data type used for this function argument by
150 * currently parsed script
151 */
152 virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;
153
154 /**
155 * Implements the actual function execution. This function is called by
156 * the VM when this function shall be executed at script runtime.
157 *
158 * @param args - function arguments for executing this built-in function
159 */
160 virtual VMFnResult* exec(VMFnArgs* args) = 0;
161
162 /**
163 * Concenience method for function implementations to show warning
164 * messages.
165 *
166 * @param txt - warning text
167 */
168 void wrnMsg(const String& txt);
169
170 /**
171 * Concenience method for function implementations to show error
172 * messages.
173 *
174 * @param txt - error text
175 */
176 void errMsg(const String& txt);
177 };
178
179 /**
180 * POD base of VMIntRelPtr and VMInt8RelPtr structures. Not intended to be
181 * used directly. Use VMIntRelPtr or VMInt8RelPtr instead.
182 */
183 struct VMRelPtr {
184 void** base; ///< Base pointer.
185 int offset; ///< Offset (in bytes) to base pointer.
186 };
187
188 /** @brief Pointer to built-in VM integer variable (of C/C++ type int).
189 *
190 * Used for defining built-in integer script variables.
191 *
192 * @b CAUTION: You may only use this class for pointing to C/C++ variables
193 * of type "int" (which on most systems is 32 bit in size). If the C/C++ int
194 * variable you want to reference is only 8 bit in size, then you @b must
195 * use VMInt8RelPtr instead!
196 *
197 * For efficiency reasons the actual native C/C++ int variable is referenced
198 * by two components here. The actual native int C/C++ variable in memory
199 * is dereferenced at VM run-time by taking the @c base pointer dereference
200 * and adding @c offset bytes. This has the advantage that for a large
201 * number of built-in int variables, only one (or few) base pointer need
202 * to be re-assigned before running a script, instead of updating each
203 * built-in variable each time before a script is executed.
204 *
205 * Refer to DECLARE_VMINT() for example code.
206 *
207 * @see VMInt8RelPtr, DECLARE_VMINT()
208 */
209 struct VMIntRelPtr : VMRelPtr {
210 VMIntRelPtr() {
211 base = NULL;
212 offset = 0;
213 }
214 VMIntRelPtr(const VMRelPtr& data) {
215 base = data.base;
216 offset = data.offset;
217 }
218 virtual int evalInt() { return *(int*)&(*(uint8_t**)base)[offset]; }
219 virtual void assign(int i) { *(int*)&(*(uint8_t**)base)[offset] = i; }
220 };
221
222 /** @brief Pointer to built-in VM integer variable (of C/C++ type int8_t).
223 *
224 * Used for defining built-in integer script variables.
225 *
226 * @b CAUTION: You may only use this class for pointing to C/C++ variables
227 * of type "int8_t" (8 bit integer). If the C/C++ int variable you want to
228 * reference is an "int" type (which is 32 bit on most systems), then you
229 * @b must use VMIntRelPtr instead!
230 *
231 * For efficiency reasons the actual native C/C++ int variable is referenced
232 * by two components here. The actual native int C/C++ variable in memory
233 * is dereferenced at VM run-time by taking the @c base pointer dereference
234 * and adding @c offset bytes. This has the advantage that for a large
235 * number of built-in int variables, only one (or few) base pointer need
236 * to be re-assigned before running a script, instead of updating each
237 * built-in variable each time before a script is executed.
238 *
239 * Refer to DECLARE_VMINT() for example code.
240 *
241 * @see VMIntRelPtr, DECLARE_VMINT()
242 */
243 struct VMInt8RelPtr : VMIntRelPtr {
244 VMInt8RelPtr() : VMIntRelPtr() {}
245 VMInt8RelPtr(const VMRelPtr& data) : VMIntRelPtr(data) {}
246 virtual int evalInt() OVERRIDE {
247 return *(uint8_t*)&(*(uint8_t**)base)[offset];
248 }
249 virtual void assign(int i) OVERRIDE {
250 *(uint8_t*)&(*(uint8_t**)base)[offset] = i;
251 }
252 };
253
254 /**
255 * Convenience macro for initializing VMIntRelPtr and VMInt8RelPtr
256 * structures. Example:
257 * @code
258 * struct Foo {
259 * uint8_t a;
260 * int b;
261 * };
262 *
263 * Foo foo1 = (Foo) { 1, 3000 };
264 * Foo foo2 = (Foo) { 2, 4000 };
265 *
266 * Foo* pFoo;
267 *
268 * VMInt8RelPtr var1 = DECLARE_VMINT(pFoo, class Foo, a);
269 * VMIntRelPtr var2 = DECLARE_VMINT(pFoo, class Foo, b);
270 *
271 * pFoo = &foo1;
272 * printf("%d\n", var1->evalInt()); // will print 1
273 * printf("%d\n", var2->evalInt()); // will print 3000
274 *
275 * pFoo = &foo2;
276 * printf("%d\n", var1->evalInt()); // will print 2
277 * printf("%d\n", var2->evalInt()); // will print 4000
278 * @endcode
279 */
280 #define DECLARE_VMINT(basePtr, T_struct, T_member) ( \
281 (VMRelPtr) { \
282 (void**) &basePtr, \
283 offsetof(T_struct, T_member) \
284 } \
285 ) \
286
287 /** @brief Built-in VM 8 bit integer array variable.
288 *
289 * Used for defining built-in integer array script variables.
290 */
291 struct VMInt8Array {
292 int8_t* data;
293 int size;
294
295 VMInt8Array() : data(NULL), size(0) {}
296 };
297
298 /** @brief Provider for built-in script functions and variables.
299 *
300 * Abstract base class defining the interface for all classes which add and
301 * implement built-in script functions and built-in script variables.
302 */
303 class VMFunctionProvider {
304 public:
305 /**
306 * Returns pointer to the built-in function with the given function
307 * name, or NULL if there is no built-in function with that name.
308 *
309 * @param name - function name
310 */
311 virtual VMFunction* functionByName(const String& name) = 0;
312
313 /**
314 * Returns a variable name indexed map of all built-in script variables
315 * which point to native "int" (usually 32 bit) variables.
316 */
317 virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;
318
319 /**
320 * Returns a variable name indexed map of all built-in script variables
321 * which point to native "int8_t" (8 bit) variables.
322 */
323 virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
324
325 /**
326 * Returns a variable name indexed map of all built-in constant script
327 * variables, which never change their value at runtime.
328 */
329 virtual std::map<String,int> builtInConstIntVariables() = 0;
330 };
331
332 /** @brief Execution state of a virtual machine.
333 *
334 * An instance of this abstract base class represents exactly one execution
335 * state of a virtual machine. This encompasses most notably the VM
336 * execution stack, and VM polyphonic variables. It does not contain global
337 * variable. Global variables are contained in the VMParserContext object.
338 * You might see a VMExecContext object as one virtual thread of the virtual
339 * machine.
340 *
341 * In contrast to a VMParserContext, a VMExecContext is not tied to a
342 * ScriptVM instance. Thus you can use a VMExecContext with different
343 * ScriptVM instances, however not concurrently at the same time.
344 *
345 * @see VMParserContext
346 */
347 class VMExecContext {
348 public:
349 virtual ~VMExecContext() {}
350 virtual int suspensionTimeMicroseconds() const = 0;
351 };
352
353 /** @brief Script callback for a certain event.
354 *
355 * Represents a script callback for a certain event, i.e.
356 * "on note ... end on".
357 */
358 class VMEventHandler {
359 public:
360 /**
361 * Name of the event handler which identifies its purpose. For example
362 * for a "on note ... end on" script callback block, the name "note"
363 * would be returned here.
364 */
365 virtual String eventHandlerName() const = 0;
366
367 /**
368 * Whether or not the event handler makes any use of so called
369 * "polyphonic" variables.
370 */
371 virtual bool isPolyphonic() const = 0;
372 };
373
374 struct ParserIssue {
375 String txt;
376 int line;
377 ParserIssueType_t type;
378
379 inline void dump() {
380 switch (type) {
381 case PARSER_ERROR:
382 printf("[ERROR] line %d: %s\n", line, txt.c_str());
383 break;
384 case PARSER_WARNING:
385 printf("[Warning] line %d: %s\n", line, txt.c_str());
386 break;
387 }
388 }
389
390 inline bool isErr() const { return type == PARSER_ERROR; }
391 inline bool isWrn() const { return type == PARSER_WARNING; }
392 };
393
394 inline String typeStr(const ExprType_t& type) {
395 switch (type) {
396 case EMPTY_EXPR: return "empty";
397 case INT_EXPR: return "integer";
398 case INT_ARR_EXPR: return "integer array";
399 case STRING_EXPR: return "string";
400 case STRING_ARR_EXPR: return "string array";
401 }
402 return "invalid";
403 }
404
405 /** @brief Virtual machine representation of a script.
406 *
407 * An instance of this abstract base class represents a parsed script,
408 * translated into a virtual machine. You should first check if there were
409 * any parser errors. If there were any parser errors, you should refrain
410 * from executing the virtual machine. Otherwise if there were no parser
411 * errors (i.e. only warnings), then you might access one of the script's
412 * event handlers by i.e. calling eventHandlerByName() and pass the
413 * respective event handler to the ScriptVM class (or to one of its
414 * descendants) for execution.
415 *
416 * @see VMExecContext
417 */
418 class VMParserContext {
419 public:
420 virtual ~VMParserContext() {}
421 virtual std::vector<ParserIssue> issues() const = 0;
422 virtual std::vector<ParserIssue> errors() const = 0;
423 virtual std::vector<ParserIssue> warnings() const = 0;
424 virtual VMEventHandler* eventHandler(uint index) = 0;
425 virtual VMEventHandler* eventHandlerByName(const String& name) = 0;
426 };
427
428 } // namespace LinuxSampler
429
430 #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

  ViewVC Help
Powered by ViewVC