/[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 2612 - (show annotations) (download) (as text)
Tue Jun 10 13:32:16 2014 UTC (9 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 14391 byte(s)
* Fixed crashes when exiting the sampler.
* Bumped version (1.0.0.svn47).

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

  ViewVC Help
Powered by ViewVC