/[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 3221 - (hide annotations) (download)
Fri May 26 18:30:42 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 14622 byte(s)
* NKSP Fix: Never suspend "init" event handlers.
* NKSP: Implemented built-in script function "array_equal()".
* NKSP: Implemented built-in script function "search()".
* NKSP: Implemented built-in script function "sort()".
* Bumped version (2.0.0.svn52).

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

  ViewVC Help
Powered by ViewVC