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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.2620  
changed lines
  Added in v.3564

  ViewVC Help
Powered by ViewVC