/[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 3551 - (hide annotations) (download)
Thu Aug 1 10:22:56 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 15921 byte(s)
* Added test cases for NKSP core language aspects and core built-in
  functions.
* NKSP: Added method ScriptVM::setExitResultEnabled() which allows
  to explicitly enable the built-in exit() function to optionally
  accept one function argument; the value of the passed exit()
  function argument will then become available by calling
  VMExecContext::exitResult() after script execution.
* Bumped version (2.1.1.svn2).

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 2598 VMFnResult* VMIntResultFunction::errorResult(int i) {
39     result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
40     result.value = i;
41     return &result;
42 schoenebeck 2596 }
43    
44 schoenebeck 2598 VMFnResult* VMIntResultFunction::successResult(int 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 2581 bool CoreVMFunction_message::acceptsArgType(int iArg, ExprType_t type) const {
69     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 3285 printf("[ScriptVM %.3f] %d\n", usecs/1000000.f, 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 3551 int CoreVMFunction_exit::maxAllowedArgs() const {
96     return (vm->isExitResultEnabled()) ? 1 : 0;
97     }
98    
99     bool CoreVMFunction_exit::acceptsArgType(int iArg, ExprType_t type) const {
100     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 2581 VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
128     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
129     VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));
130 schoenebeck 2972 int us = expr->evalInt();
131     if (us < 0) {
132     wrnMsg("wait(): argument may not be negative! Aborting script!");
133     this->result.flags = STMT_ABORT_SIGNALLED;
134     } else if (us == 0) {
135     wrnMsg("wait(): argument may not be zero! Aborting script!");
136     this->result.flags = STMT_ABORT_SIGNALLED;
137     } else {
138     ctx->suspendMicroseconds = us;
139     this->result.flags = STMT_SUSPEND_SIGNALLED;
140     }
141 schoenebeck 2581 return &result;
142     }
143    
144 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
145     // built-in script function: abs()
146    
147 schoenebeck 2619 bool CoreVMFunction_abs::acceptsArgType(int iArg, ExprType_t type) const {
148     return type == INT_EXPR;
149     }
150    
151     VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
152     return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );
153     }
154    
155 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
156     // built-in script function: random()
157    
158 schoenebeck 2619 bool CoreVMFunction_random::acceptsArgType(int iArg, ExprType_t type) const {
159     return type == INT_EXPR;
160     }
161    
162     VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
163     int iMin = args->arg(0)->asInt()->evalInt();
164     int iMax = args->arg(1)->asInt()->evalInt();
165 schoenebeck 2620 float f = float(::rand()) / float(RAND_MAX);
166 schoenebeck 2619 return successResult(
167     iMin + roundf( f * float(iMax - iMin) )
168     );
169     }
170    
171 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
172     // built-in script function: num_elements()
173    
174 schoenebeck 2619 bool CoreVMFunction_num_elements::acceptsArgType(int iArg, ExprType_t type) const {
175     return type == INT_ARR_EXPR;
176     }
177    
178     VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
179     return successResult( args->arg(0)->asIntArray()->arraySize() );
180     }
181    
182 schoenebeck 2945 ///////////////////////////////////////////////////////////////////////////
183     // built-in script function: inc()
184    
185     VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
186     VMExpr* arg = args->arg(0);
187     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
188     VMVariable* out = dynamic_cast<VMVariable*>(arg);
189     if (!in || !out) successResult(0);
190     int i = in->evalInt() + 1;
191     IntLiteral tmp(i);
192     out->assignExpr(&tmp);
193     return successResult(i);
194     }
195    
196     ///////////////////////////////////////////////////////////////////////////
197     // built-in script function: dec()
198    
199     VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
200     VMExpr* arg = args->arg(0);
201     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
202     VMVariable* out = dynamic_cast<VMVariable*>(arg);
203     if (!in || !out) successResult(0);
204     int i = in->evalInt() - 1;
205     IntLiteral tmp(i);
206     out->assignExpr(&tmp);
207     return successResult(i);
208     }
209    
210 schoenebeck 2965 ///////////////////////////////////////////////////////////////////////////
211 schoenebeck 3076 // built-in script function: in_range()
212    
213     VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
214     int i = args->arg(0)->asInt()->evalInt();
215     int lo = args->arg(1)->asInt()->evalInt();
216     int hi = args->arg(2)->asInt()->evalInt();
217     if (lo > hi) { // swap lo and hi
218     int tmp = lo;
219     lo = hi;
220     hi = tmp;
221     }
222     return successResult(i >= lo && i <= hi);
223     }
224    
225     ///////////////////////////////////////////////////////////////////////////
226 schoenebeck 2965 // built-in script function: sh_left()
227    
228     VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
229     int i = args->arg(0)->asInt()->evalInt();
230     int n = args->arg(1)->asInt()->evalInt();
231     return successResult(i << n);
232     }
233    
234     ///////////////////////////////////////////////////////////////////////////
235     // built-in script function: sh_right()
236    
237     VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
238     int i = args->arg(0)->asInt()->evalInt();
239     int n = args->arg(1)->asInt()->evalInt();
240     return successResult(i >> n);
241     }
242    
243 schoenebeck 2970 ///////////////////////////////////////////////////////////////////////////
244     // built-in script function: min()
245    
246     VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
247     int l = args->arg(0)->asInt()->evalInt();
248     int r = args->arg(1)->asInt()->evalInt();
249     return successResult(l < r ? l : r);
250     }
251    
252     ///////////////////////////////////////////////////////////////////////////
253     // built-in script function: max()
254    
255     VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
256     int l = args->arg(0)->asInt()->evalInt();
257     int r = args->arg(1)->asInt()->evalInt();
258     return successResult(l > r ? l : r);
259     }
260    
261 schoenebeck 3221 ///////////////////////////////////////////////////////////////////////////
262     // built-in script function: array_equal()
263    
264     VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
265     VMIntArrayExpr* l = args->arg(0)->asIntArray();
266     VMIntArrayExpr* r = args->arg(1)->asIntArray();
267     if (l->arraySize() != r->arraySize()) {
268     wrnMsg("array_equal(): the two arrays differ in size");
269     return successResult(0); // false
270     }
271     const int n = l->arraySize();
272     for (int i = 0; i < n; ++i)
273     if (l->evalIntElement(i) != r->evalIntElement(i))
274     return successResult(0); // false
275     return successResult(1); // true
276     }
277    
278     ///////////////////////////////////////////////////////////////////////////
279     // built-in script function: search()
280    
281     ExprType_t CoreVMFunction_search::argType(int iArg) const {
282     return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
283     }
284    
285     bool CoreVMFunction_search::acceptsArgType(int iArg, ExprType_t type) const {
286     if (iArg == 0)
287     return type == INT_ARR_EXPR;
288     else
289     return type == INT_EXPR;
290     }
291    
292     VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
293     VMIntArrayExpr* a = args->arg(0)->asIntArray();
294     const int needle = args->arg(1)->asInt()->evalInt();
295     const int n = a->arraySize();
296     for (int i = 0; i < n; ++i)
297     if (a->evalIntElement(i) == needle)
298     return successResult(i);
299     return successResult(-1); // not found
300     }
301    
302     ///////////////////////////////////////////////////////////////////////////
303     // built-in script function: sort()
304    
305     ExprType_t CoreVMFunction_sort::argType(int iArg) const {
306     return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
307     }
308    
309     bool CoreVMFunction_sort::acceptsArgType(int iArg, ExprType_t type) const {
310     if (iArg == 0)
311     return type == INT_ARR_EXPR;
312     else
313     return type == INT_EXPR;
314     }
315    
316     struct ArrElemPOD {
317     VMIntArrayExpr* m_array;
318     int m_index;
319     };
320    
321 schoenebeck 3222 static inline void swap(class ArrElemRef a, class ArrElemRef b);
322 schoenebeck 3221
323     class ArrElemRef : protected ArrElemPOD {
324     public:
325     ArrElemRef() {
326     m_array = NULL;
327     m_index = 0;
328     }
329     ArrElemRef(VMIntArrayExpr* a, int index) {
330     m_array = a;
331     m_index = index;
332     }
333     inline ArrElemRef& operator=(const ArrElemRef& e) {
334     setValue(e.getValue());
335     return *this;
336     }
337     inline ArrElemRef& operator=(int val) {
338     setValue(val);
339     return *this;
340     }
341     inline bool operator==(const ArrElemRef& e) const {
342     if (m_index == e.m_index)
343     return true;
344     return getValue() == e.getValue();
345     }
346     inline bool operator==(int val) const {
347     return getValue() == val;
348     }
349     inline bool operator!=(const ArrElemRef& e) const {
350     return !(operator==(e));
351     }
352     inline bool operator!=(int val) const {
353     return !(operator==(val));
354     }
355     inline bool operator<(const ArrElemRef& e) const {
356     if (m_index == e.m_index)
357     return false;
358     return getValue() < e.getValue();
359     }
360     inline bool operator<(int val) const {
361     return getValue() < val;
362     }
363     inline bool operator>(const ArrElemRef& e) const {
364     if (m_index == e.m_index)
365     return false;
366     return getValue() > e.getValue();
367     }
368     inline bool operator>(int val) const {
369     return getValue() > val;
370     }
371     inline bool operator<=(const ArrElemRef& e) const {
372     if (m_index == e.m_index)
373     return true;
374     return getValue() <= e.getValue();
375     }
376     inline bool operator<=(int val) const {
377     return getValue() <= val;
378     }
379     inline bool operator>=(const ArrElemRef& e) const {
380     if (m_index == e.m_index)
381     return true;
382     return getValue() >= e.getValue();
383     }
384     inline bool operator>=(int val) const {
385     return getValue() >= val;
386     }
387     inline operator int() const {
388     return getValue();
389     }
390     protected:
391     inline int getValue() const {
392     return m_array->evalIntElement(m_index);
393     }
394     inline void setValue(int value) {
395     m_array->assignIntElement(m_index, value);
396     }
397    
398 schoenebeck 3222 friend void swap(class ArrElemRef a, class ArrElemRef b);
399 schoenebeck 3221 };
400    
401     class ArrElemPtr : protected ArrElemPOD {
402     public:
403     ArrElemPtr() {
404     m_array = NULL;
405     m_index = 0;
406     }
407     ArrElemPtr(VMIntArrayExpr* a, int index) {
408     m_array = a;
409     m_index = index;
410     }
411     inline ArrElemRef operator*() {
412     return *(ArrElemRef*)this;
413     }
414     };
415    
416 schoenebeck 3222 static inline void swap(ArrElemRef a, ArrElemRef b) {
417 schoenebeck 3221 int valueA = a.getValue();
418     int valueB = b.getValue();
419     a.setValue(valueB);
420     b.setValue(valueA);
421     }
422    
423     class ArrExprIter : public ArrElemPOD {
424     public:
425     typedef std::random_access_iterator_tag iterator_category;
426     typedef int value_type;
427     typedef ssize_t difference_type;
428     typedef ArrElemPtr pointer;
429     typedef ArrElemRef reference;
430    
431     ArrExprIter(VMIntArrayExpr* a, int index) {
432     m_array = a;
433     m_index = index;
434     }
435     inline ArrElemRef operator*() {
436     return *(ArrElemRef*)this;
437     }
438     inline ArrExprIter& operator++() { // prefix increment
439     ++m_index;
440     return *this;
441     }
442     inline ArrExprIter& operator--() { // prefix decrement
443     --m_index;
444     return *this;
445     }
446     inline ArrExprIter operator++(int) { // postfix increment
447     ArrExprIter it = *this;
448     ++m_index;
449     return it;
450     }
451     inline ArrExprIter operator--(int) { // postfix decrement
452     ArrExprIter it = *this;
453     --m_index;
454     return it;
455     }
456 schoenebeck 3345 inline ArrExprIter& operator+=(difference_type d) {
457     m_index += d;
458     return *this;
459     }
460     inline ArrExprIter& operator-=(difference_type d) {
461     m_index -= d;
462     return *this;
463     }
464 schoenebeck 3221 inline bool operator==(const ArrExprIter& other) const {
465     return m_index == other.m_index;
466     }
467     inline bool operator!=(const ArrExprIter& other) const {
468     return m_index != other.m_index;
469     }
470     inline bool operator<(const ArrExprIter& other) const {
471     return m_index < other.m_index;
472     }
473     inline bool operator>(const ArrExprIter& other) const {
474     return m_index > other.m_index;
475     }
476     inline bool operator<=(const ArrExprIter& other) const {
477     return m_index <= other.m_index;
478     }
479     inline bool operator>=(const ArrExprIter& other) const {
480     return m_index >= other.m_index;
481     }
482     inline difference_type operator+(const ArrExprIter& other) const {
483     return m_index + other.m_index;
484     }
485     inline difference_type operator-(const ArrExprIter& other) const {
486     return m_index - other.m_index;
487     }
488     inline ArrExprIter operator-(difference_type d) const {
489     return ArrExprIter(m_array, m_index - d);
490     }
491     inline ArrExprIter operator+(difference_type d) const {
492     return ArrExprIter(m_array, m_index + d);
493     }
494     inline ArrExprIter operator*(difference_type factor) const {
495     return ArrExprIter(m_array, m_index * factor);
496     }
497     };
498    
499     struct DescArrExprSorter {
500     inline bool operator()(const int& a, const int& b) const {
501     return a > b;
502     }
503     };
504    
505     VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
506     VMIntArrayExpr* a = args->arg(0)->asIntArray();
507     bool bAscending =
508     (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
509     int n = a->arraySize();
510     ArrExprIter itBegin(a, 0);
511     ArrExprIter itEnd(a, n);
512     if (bAscending) {
513     std::sort(itBegin, itEnd);
514     } else {
515     DescArrExprSorter sorter;
516     std::sort(itBegin, itEnd, sorter);
517     }
518     return successResult();
519     }
520    
521 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC