/[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 2619 - (show annotations) (download) (as text)
Wed Jun 11 13:24:32 2014 UTC (9 years, 9 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 14787 byte(s)
* Implemented built-in instrument script function "abs()".
* Implemented built-in instrument script function "random()".
* Implemented built-in instrument script function "num_elements()".
* Disabled debug mode of RefPtr template class.
* Bumped version (1.0.0.svn51).

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

  ViewVC Help
Powered by ViewVC