/[svn]/linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3561 - (hide annotations) (download)
Fri Aug 23 11:44:00 2019 UTC (4 years, 8 months ago) by schoenebeck
File size: 16343 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

1 schoenebeck 2581 /*
2 schoenebeck 3551 * Copyright (c) 2014-2019 Christian Schoenebeck
3 schoenebeck 2581 *
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     #include "CoreVMFunctions.h"
11    
12     #include <iostream>
13 schoenebeck 3221 #include <algorithm> // for std::sort()
14 schoenebeck 2619 #include <math.h>
15     #include <stdlib.h>
16 schoenebeck 2581 #include "tree.h"
17     #include "ScriptVM.h"
18 schoenebeck 3285 #include "../common/RTMath.h"
19 schoenebeck 2581
20     namespace LinuxSampler {
21    
22 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
23     // class VMEmptyResultFunction
24    
25 schoenebeck 2581 VMFnResult* VMEmptyResultFunction::errorResult() {
26     result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
27     return &result;
28     }
29    
30 schoenebeck 2598 VMFnResult* VMEmptyResultFunction::successResult() {
31     result.flags = STMT_SUCCESS;
32     return &result;
33 schoenebeck 2596 }
34    
35 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
36     // class VMIntResultFunction
37    
38 schoenebeck 3557 VMFnResult* VMIntResultFunction::errorResult(vmint i) {
39 schoenebeck 2598 result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
40     result.value = i;
41     return &result;
42 schoenebeck 2596 }
43    
44 schoenebeck 3557 VMFnResult* VMIntResultFunction::successResult(vmint i) {
45 schoenebeck 2581 result.flags = STMT_SUCCESS;
46 schoenebeck 2598 result.value = i;
47 schoenebeck 2581 return &result;
48     }
49    
50 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
51     // class VMStringResultFunction
52    
53 schoenebeck 2581 VMFnResult* VMStringResultFunction::errorResult(const String& s) {
54     result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
55     result.value = s;
56     return &result;
57     }
58    
59     VMFnResult* VMStringResultFunction::successResult(const String& s) {
60     result.flags = STMT_SUCCESS;
61     result.value = s;
62     return &result;
63     }
64    
65 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
66     // built-in script function: message()
67    
68 schoenebeck 3557 bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
69 schoenebeck 2581 return type == INT_EXPR || type == STRING_EXPR;
70     }
71    
72     VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
73     if (!args->argsCount()) return errorResult();
74    
75 schoenebeck 3285 uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock);
76    
77 schoenebeck 2581 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));
78     if (strExpr) {
79 schoenebeck 3285 printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str());
80 schoenebeck 2581 return successResult();
81     }
82    
83     VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
84     if (intExpr) {
85 schoenebeck 3557 printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
86 schoenebeck 2581 return successResult();
87     }
88    
89     return errorResult();
90     }
91    
92 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
93     // built-in script function: exit()
94    
95 schoenebeck 3557 vmint CoreVMFunction_exit::maxAllowedArgs() const {
96 schoenebeck 3551 return (vm->isExitResultEnabled()) ? 1 : 0;
97     }
98    
99 schoenebeck 3557 bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
100 schoenebeck 3551 if (!vm->isExitResultEnabled()) return false;
101     return type == INT_EXPR || type == STRING_EXPR;
102     }
103    
104 schoenebeck 2581 VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
105     this->result.flags = STMT_ABORT_SIGNALLED;
106 schoenebeck 3551 if (vm->isExitResultEnabled() && args->argsCount()) {
107     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
108     switch (args->arg(0)->exprType()) {
109     case INT_EXPR:
110     ctx->exitRes.intLiteral.value = args->arg(0)->asInt()->evalInt();
111     ctx->exitRes.value = &ctx->exitRes.intLiteral;
112     break;
113     case STRING_EXPR:
114     ctx->exitRes.stringLiteral.value = args->arg(0)->asString()->evalStr();
115     ctx->exitRes.value = &ctx->exitRes.stringLiteral;
116     break;
117     default:
118     ; // noop - just to shut up the compiler
119     }
120     }
121 schoenebeck 2581 return &result;
122     }
123    
124 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
125     // built-in script function: wait()
126    
127 schoenebeck 3561 bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
128     if (iArg == 0)
129     return type == VM_NO_UNIT || type == VM_SECOND;
130     else
131     return type == VM_NO_UNIT;
132     }
133    
134     bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg) const {
135     return iArg == 0;
136     }
137    
138 schoenebeck 2581 VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
139     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
140     VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));
141 schoenebeck 3561 vmint us = expr->evalInt(VM_MICRO);
142 schoenebeck 2972 if (us < 0) {
143     wrnMsg("wait(): argument may not be negative! Aborting script!");
144     this->result.flags = STMT_ABORT_SIGNALLED;
145     } else if (us == 0) {
146     wrnMsg("wait(): argument may not be zero! Aborting script!");
147     this->result.flags = STMT_ABORT_SIGNALLED;
148     } else {
149     ctx->suspendMicroseconds = us;
150     this->result.flags = STMT_SUSPEND_SIGNALLED;
151     }
152 schoenebeck 2581 return &result;
153     }
154    
155 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
156     // built-in script function: abs()
157    
158 schoenebeck 3557 bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
159 schoenebeck 2619 return type == INT_EXPR;
160     }
161    
162     VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
163     return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );
164     }
165    
166 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
167     // built-in script function: random()
168    
169 schoenebeck 3557 bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
170 schoenebeck 2619 return type == INT_EXPR;
171     }
172    
173     VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
174 schoenebeck 3557 vmint iMin = args->arg(0)->asInt()->evalInt();
175     vmint iMax = args->arg(1)->asInt()->evalInt();
176 schoenebeck 2620 float f = float(::rand()) / float(RAND_MAX);
177 schoenebeck 2619 return successResult(
178     iMin + roundf( f * float(iMax - iMin) )
179     );
180     }
181    
182 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
183     // built-in script function: num_elements()
184    
185 schoenebeck 3557 bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
186 schoenebeck 2619 return type == INT_ARR_EXPR;
187     }
188    
189     VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
190     return successResult( args->arg(0)->asIntArray()->arraySize() );
191     }
192    
193 schoenebeck 2945 ///////////////////////////////////////////////////////////////////////////
194     // built-in script function: inc()
195    
196     VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
197     VMExpr* arg = args->arg(0);
198     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
199     VMVariable* out = dynamic_cast<VMVariable*>(arg);
200     if (!in || !out) successResult(0);
201 schoenebeck 3557 vmint i = in->evalInt() + 1;
202 schoenebeck 2945 IntLiteral tmp(i);
203     out->assignExpr(&tmp);
204     return successResult(i);
205     }
206    
207     ///////////////////////////////////////////////////////////////////////////
208     // built-in script function: dec()
209    
210     VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
211     VMExpr* arg = args->arg(0);
212     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
213     VMVariable* out = dynamic_cast<VMVariable*>(arg);
214     if (!in || !out) successResult(0);
215 schoenebeck 3557 vmint i = in->evalInt() - 1;
216 schoenebeck 2945 IntLiteral tmp(i);
217     out->assignExpr(&tmp);
218     return successResult(i);
219     }
220    
221 schoenebeck 2965 ///////////////////////////////////////////////////////////////////////////
222 schoenebeck 3076 // built-in script function: in_range()
223    
224     VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
225 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
226     vmint lo = args->arg(1)->asInt()->evalInt();
227     vmint hi = args->arg(2)->asInt()->evalInt();
228 schoenebeck 3076 if (lo > hi) { // swap lo and hi
229 schoenebeck 3557 vmint tmp = lo;
230 schoenebeck 3076 lo = hi;
231     hi = tmp;
232     }
233     return successResult(i >= lo && i <= hi);
234     }
235    
236     ///////////////////////////////////////////////////////////////////////////
237 schoenebeck 2965 // built-in script function: sh_left()
238    
239     VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
240 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
241     vmint n = args->arg(1)->asInt()->evalInt();
242 schoenebeck 2965 return successResult(i << n);
243     }
244    
245     ///////////////////////////////////////////////////////////////////////////
246     // built-in script function: sh_right()
247    
248     VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
249 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
250     vmint n = args->arg(1)->asInt()->evalInt();
251 schoenebeck 2965 return successResult(i >> n);
252     }
253    
254 schoenebeck 2970 ///////////////////////////////////////////////////////////////////////////
255     // built-in script function: min()
256    
257     VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
258 schoenebeck 3557 vmint l = args->arg(0)->asInt()->evalInt();
259     vmint r = args->arg(1)->asInt()->evalInt();
260 schoenebeck 2970 return successResult(l < r ? l : r);
261     }
262    
263     ///////////////////////////////////////////////////////////////////////////
264     // built-in script function: max()
265    
266     VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
267 schoenebeck 3557 vmint l = args->arg(0)->asInt()->evalInt();
268     vmint r = args->arg(1)->asInt()->evalInt();
269 schoenebeck 2970 return successResult(l > r ? l : r);
270     }
271    
272 schoenebeck 3221 ///////////////////////////////////////////////////////////////////////////
273     // built-in script function: array_equal()
274    
275     VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
276     VMIntArrayExpr* l = args->arg(0)->asIntArray();
277     VMIntArrayExpr* r = args->arg(1)->asIntArray();
278     if (l->arraySize() != r->arraySize()) {
279     wrnMsg("array_equal(): the two arrays differ in size");
280     return successResult(0); // false
281     }
282 schoenebeck 3557 const vmint n = l->arraySize();
283     for (vmint i = 0; i < n; ++i)
284 schoenebeck 3221 if (l->evalIntElement(i) != r->evalIntElement(i))
285     return successResult(0); // false
286     return successResult(1); // true
287     }
288    
289     ///////////////////////////////////////////////////////////////////////////
290     // built-in script function: search()
291    
292 schoenebeck 3557 ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
293 schoenebeck 3221 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
294     }
295    
296 schoenebeck 3557 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
297 schoenebeck 3221 if (iArg == 0)
298     return type == INT_ARR_EXPR;
299     else
300     return type == INT_EXPR;
301     }
302    
303     VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
304     VMIntArrayExpr* a = args->arg(0)->asIntArray();
305 schoenebeck 3557 const vmint needle = args->arg(1)->asInt()->evalInt();
306     const vmint n = a->arraySize();
307     for (vmint i = 0; i < n; ++i)
308 schoenebeck 3221 if (a->evalIntElement(i) == needle)
309     return successResult(i);
310     return successResult(-1); // not found
311     }
312    
313     ///////////////////////////////////////////////////////////////////////////
314     // built-in script function: sort()
315    
316 schoenebeck 3557 ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
317 schoenebeck 3221 return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
318     }
319    
320 schoenebeck 3557 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
321 schoenebeck 3221 if (iArg == 0)
322     return type == INT_ARR_EXPR;
323     else
324     return type == INT_EXPR;
325     }
326    
327     struct ArrElemPOD {
328     VMIntArrayExpr* m_array;
329 schoenebeck 3557 vmint m_index;
330 schoenebeck 3221 };
331    
332 schoenebeck 3222 static inline void swap(class ArrElemRef a, class ArrElemRef b);
333 schoenebeck 3221
334     class ArrElemRef : protected ArrElemPOD {
335     public:
336     ArrElemRef() {
337     m_array = NULL;
338     m_index = 0;
339     }
340 schoenebeck 3557 ArrElemRef(VMIntArrayExpr* a, vmint index) {
341 schoenebeck 3221 m_array = a;
342     m_index = index;
343     }
344     inline ArrElemRef& operator=(const ArrElemRef& e) {
345     setValue(e.getValue());
346     return *this;
347     }
348 schoenebeck 3557 inline ArrElemRef& operator=(vmint val) {
349 schoenebeck 3221 setValue(val);
350     return *this;
351     }
352     inline bool operator==(const ArrElemRef& e) const {
353     if (m_index == e.m_index)
354     return true;
355     return getValue() == e.getValue();
356     }
357 schoenebeck 3557 inline bool operator==(vmint val) const {
358 schoenebeck 3221 return getValue() == val;
359     }
360     inline bool operator!=(const ArrElemRef& e) const {
361     return !(operator==(e));
362     }
363 schoenebeck 3557 inline bool operator!=(vmint val) const {
364 schoenebeck 3221 return !(operator==(val));
365     }
366     inline bool operator<(const ArrElemRef& e) const {
367     if (m_index == e.m_index)
368     return false;
369     return getValue() < e.getValue();
370     }
371 schoenebeck 3557 inline bool operator<(vmint val) const {
372 schoenebeck 3221 return getValue() < val;
373     }
374     inline bool operator>(const ArrElemRef& e) const {
375     if (m_index == e.m_index)
376     return false;
377     return getValue() > e.getValue();
378     }
379 schoenebeck 3557 inline bool operator>(vmint val) const {
380 schoenebeck 3221 return getValue() > val;
381     }
382     inline bool operator<=(const ArrElemRef& e) const {
383     if (m_index == e.m_index)
384     return true;
385     return getValue() <= e.getValue();
386     }
387 schoenebeck 3557 inline bool operator<=(vmint val) const {
388 schoenebeck 3221 return getValue() <= val;
389     }
390     inline bool operator>=(const ArrElemRef& e) const {
391     if (m_index == e.m_index)
392     return true;
393     return getValue() >= e.getValue();
394     }
395 schoenebeck 3557 inline bool operator>=(vmint val) const {
396 schoenebeck 3221 return getValue() >= val;
397     }
398 schoenebeck 3557 inline operator vmint() const {
399 schoenebeck 3221 return getValue();
400     }
401     protected:
402 schoenebeck 3557 inline vmint getValue() const {
403 schoenebeck 3221 return m_array->evalIntElement(m_index);
404     }
405 schoenebeck 3557 inline void setValue(vmint value) {
406 schoenebeck 3221 m_array->assignIntElement(m_index, value);
407     }
408    
409 schoenebeck 3222 friend void swap(class ArrElemRef a, class ArrElemRef b);
410 schoenebeck 3221 };
411    
412     class ArrElemPtr : protected ArrElemPOD {
413     public:
414     ArrElemPtr() {
415     m_array = NULL;
416     m_index = 0;
417     }
418 schoenebeck 3557 ArrElemPtr(VMIntArrayExpr* a, vmint index) {
419 schoenebeck 3221 m_array = a;
420     m_index = index;
421     }
422     inline ArrElemRef operator*() {
423     return *(ArrElemRef*)this;
424     }
425     };
426    
427 schoenebeck 3222 static inline void swap(ArrElemRef a, ArrElemRef b) {
428 schoenebeck 3557 vmint valueA = a.getValue();
429     vmint valueB = b.getValue();
430 schoenebeck 3221 a.setValue(valueB);
431     b.setValue(valueA);
432     }
433    
434     class ArrExprIter : public ArrElemPOD {
435     public:
436     typedef std::random_access_iterator_tag iterator_category;
437 schoenebeck 3557 typedef vmint value_type;
438 schoenebeck 3221 typedef ssize_t difference_type;
439     typedef ArrElemPtr pointer;
440     typedef ArrElemRef reference;
441    
442 schoenebeck 3557 ArrExprIter(VMIntArrayExpr* a, vmint index) {
443 schoenebeck 3221 m_array = a;
444     m_index = index;
445     }
446     inline ArrElemRef operator*() {
447     return *(ArrElemRef*)this;
448     }
449     inline ArrExprIter& operator++() { // prefix increment
450     ++m_index;
451     return *this;
452     }
453     inline ArrExprIter& operator--() { // prefix decrement
454     --m_index;
455     return *this;
456     }
457     inline ArrExprIter operator++(int) { // postfix increment
458     ArrExprIter it = *this;
459     ++m_index;
460     return it;
461     }
462     inline ArrExprIter operator--(int) { // postfix decrement
463     ArrExprIter it = *this;
464     --m_index;
465     return it;
466     }
467 schoenebeck 3345 inline ArrExprIter& operator+=(difference_type d) {
468     m_index += d;
469     return *this;
470     }
471     inline ArrExprIter& operator-=(difference_type d) {
472     m_index -= d;
473     return *this;
474     }
475 schoenebeck 3221 inline bool operator==(const ArrExprIter& other) const {
476     return m_index == other.m_index;
477     }
478     inline bool operator!=(const ArrExprIter& other) const {
479     return m_index != other.m_index;
480     }
481     inline bool operator<(const ArrExprIter& other) const {
482     return m_index < other.m_index;
483     }
484     inline bool operator>(const ArrExprIter& other) const {
485     return m_index > other.m_index;
486     }
487     inline bool operator<=(const ArrExprIter& other) const {
488     return m_index <= other.m_index;
489     }
490     inline bool operator>=(const ArrExprIter& other) const {
491     return m_index >= other.m_index;
492     }
493     inline difference_type operator+(const ArrExprIter& other) const {
494     return m_index + other.m_index;
495     }
496     inline difference_type operator-(const ArrExprIter& other) const {
497     return m_index - other.m_index;
498     }
499     inline ArrExprIter operator-(difference_type d) const {
500     return ArrExprIter(m_array, m_index - d);
501     }
502     inline ArrExprIter operator+(difference_type d) const {
503     return ArrExprIter(m_array, m_index + d);
504     }
505     inline ArrExprIter operator*(difference_type factor) const {
506     return ArrExprIter(m_array, m_index * factor);
507     }
508     };
509    
510     struct DescArrExprSorter {
511 schoenebeck 3557 inline bool operator()(const vmint& a, const vmint& b) const {
512 schoenebeck 3221 return a > b;
513     }
514     };
515    
516     VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
517     VMIntArrayExpr* a = args->arg(0)->asIntArray();
518     bool bAscending =
519     (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
520 schoenebeck 3557 vmint n = a->arraySize();
521 schoenebeck 3221 ArrExprIter itBegin(a, 0);
522     ArrExprIter itEnd(a, n);
523     if (bAscending) {
524     std::sort(itBegin, itEnd);
525     } else {
526     DescArrExprSorter sorter;
527     std::sort(itBegin, itEnd, sorter);
528     }
529     return successResult();
530     }
531    
532 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC