/[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 2645 - (hide annotations) (download) (as text)
Wed Jun 18 00:14:57 2014 UTC (9 years, 10 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 schoenebeck 2581 /*
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 schoenebeck 2588 #include <vector>
19 schoenebeck 2594 #include <map>
20     #include <stddef.h> // offsetof()
21 schoenebeck 2581
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 schoenebeck 2596 class VMIntExpr;
52     class VMStringExpr;
53 schoenebeck 2619 class VMIntArrayExpr;
54     class VMStringArrayExpr;
55 schoenebeck 2596
56 schoenebeck 2581 class VMExpr {
57     public:
58     virtual ExprType_t exprType() const = 0;
59 schoenebeck 2596 VMIntExpr* asInt() const;
60     VMStringExpr* asString() const;
61 schoenebeck 2619 VMIntArrayExpr* asIntArray() const;
62 schoenebeck 2581 };
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 schoenebeck 2619 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 schoenebeck 2630 ExprType_t exprType() const { return INT_ARR_EXPR; }
86 schoenebeck 2619 };
87    
88 schoenebeck 2581 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 schoenebeck 2612 /** @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 schoenebeck 2581 class VMFunction {
106     public:
107 schoenebeck 2612 /**
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 schoenebeck 2581 virtual ExprType_t returnType() = 0;
112 schoenebeck 2612
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 schoenebeck 2581 virtual int minRequiredArgs() const = 0;
119 schoenebeck 2612
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 schoenebeck 2581 virtual int maxAllowedArgs() const = 0;
126 schoenebeck 2612
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 schoenebeck 2581 virtual ExprType_t argType(int iArg) const = 0;
141 schoenebeck 2612
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 schoenebeck 2581 virtual bool acceptsArgType(int iArg, ExprType_t type) const = 0;
153 schoenebeck 2612
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 schoenebeck 2581 virtual VMFnResult* exec(VMFnArgs* args) = 0;
161 schoenebeck 2612
162     /**
163     * Concenience method for function implementations to show warning
164     * messages.
165     *
166     * @param txt - warning text
167     */
168 schoenebeck 2598 void wrnMsg(const String& txt);
169 schoenebeck 2612
170     /**
171     * Concenience method for function implementations to show error
172     * messages.
173     *
174     * @param txt - error text
175     */
176 schoenebeck 2598 void errMsg(const String& txt);
177 schoenebeck 2581 };
178    
179 schoenebeck 2594 /**
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 schoenebeck 2612 /** @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 schoenebeck 2581 class VMFunctionProvider {
304     public:
305 schoenebeck 2612 /**
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 schoenebeck 2581 virtual VMFunction* functionByName(const String& name) = 0;
312 schoenebeck 2612
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 schoenebeck 2594 virtual std::map<String,VMIntRelPtr*> builtInIntVariables() = 0;
318 schoenebeck 2612
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 schoenebeck 2594 virtual std::map<String,VMInt8Array*> builtInIntArrayVariables() = 0;
324 schoenebeck 2612
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 schoenebeck 2594 virtual std::map<String,int> builtInConstIntVariables() = 0;
330 schoenebeck 2581 };
331    
332 schoenebeck 2594 /** @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 schoenebeck 2612 * 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 schoenebeck 2594 *
341 schoenebeck 2612 * 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 schoenebeck 2594 * @see VMParserContext
346     */
347 schoenebeck 2581 class VMExecContext {
348     public:
349     virtual ~VMExecContext() {}
350     virtual int suspensionTimeMicroseconds() const = 0;
351     };
352    
353 schoenebeck 2645 /** @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 schoenebeck 2581 class VMEventHandler {
359     public:
360 schoenebeck 2645 /**
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 schoenebeck 2581 virtual String eventHandlerName() const = 0;
366 schoenebeck 2645
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 schoenebeck 2581 };
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 schoenebeck 2594 /** @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 schoenebeck 2588 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 schoenebeck 2581 } // namespace LinuxSampler
429    
430     #endif // LS_INSTR_SCRIPT_PARSER_COMMON_H

  ViewVC Help
Powered by ViewVC