/[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 3561 by schoenebeck, Fri Aug 23 11:44:00 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) const {
135        return iArg == 0;
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();      vmint us = expr->evalInt(VM_MICRO);
142      this->result.flags = STMT_SUSPEND_SIGNALLED;      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      return &result;      return &result;
153  }  }
154    
155  bool CoreVMFunction_abs::acceptsArgType(int iArg, ExprType_t type) const {  ///////////////////////////////////////////////////////////////////////////
156    // built-in script function:  abs()
157    
158    bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
159      return type == INT_EXPR;      return type == INT_EXPR;
160  }  }
161    
# Line 94  VMFnResult* CoreVMFunction_abs::exec(VMF Line 163  VMFnResult* CoreVMFunction_abs::exec(VMF
163      return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );      return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );
164  }  }
165    
166  bool CoreVMFunction_random::acceptsArgType(int iArg, ExprType_t type) const {  ///////////////////////////////////////////////////////////////////////////
167    // built-in script function:  random()
168    
169    bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
170      return type == INT_EXPR;      return type == INT_EXPR;
171  }  }
172    
173  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
174      int iMin = args->arg(0)->asInt()->evalInt();      vmint iMin = args->arg(0)->asInt()->evalInt();
175      int iMax = args->arg(1)->asInt()->evalInt();      vmint iMax = args->arg(1)->asInt()->evalInt();
176      float f = float(::rand()) / float(RAND_MAX);      float f = float(::rand()) / float(RAND_MAX);
177      return successResult(      return successResult(
178          iMin + roundf( f * float(iMax - iMin) )          iMin + roundf( f * float(iMax - iMin) )
179      );      );
180  }  }
181    
182  bool CoreVMFunction_num_elements::acceptsArgType(int iArg, ExprType_t type) const {  ///////////////////////////////////////////////////////////////////////////
183    // built-in script function:  num_elements()
184    
185    bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
186      return type == INT_ARR_EXPR;      return type == INT_ARR_EXPR;
187  }  }
188    
# Line 115  VMFnResult* CoreVMFunction_num_elements: Line 190  VMFnResult* CoreVMFunction_num_elements:
190      return successResult( args->arg(0)->asIntArray()->arraySize() );      return successResult( args->arg(0)->asIntArray()->arraySize() );
191  }  }
192    
193    ///////////////////////////////////////////////////////////////////////////
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        vmint i = in->evalInt() + 1;
202        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        vmint i = in->evalInt() - 1;
216        IntLiteral tmp(i);
217        out->assignExpr(&tmp);
218        return successResult(i);
219    }
220    
221    ///////////////////////////////////////////////////////////////////////////
222    // built-in script function:  in_range()
223    
224    VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
225        vmint i  = args->arg(0)->asInt()->evalInt();
226        vmint lo = args->arg(1)->asInt()->evalInt();
227        vmint hi = args->arg(2)->asInt()->evalInt();
228        if (lo > hi) { // swap lo and hi
229            vmint tmp = lo;
230            lo = hi;
231            hi = tmp;
232        }
233        return successResult(i >= lo && i <= hi);
234    }
235    
236    ///////////////////////////////////////////////////////////////////////////
237    // built-in script function:  sh_left()
238    
239    VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
240        vmint i = args->arg(0)->asInt()->evalInt();
241        vmint n = args->arg(1)->asInt()->evalInt();
242        return successResult(i << n);
243    }
244    
245    ///////////////////////////////////////////////////////////////////////////
246    // built-in script function:  sh_right()
247    
248    VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
249        vmint i = args->arg(0)->asInt()->evalInt();
250        vmint n = args->arg(1)->asInt()->evalInt();
251        return successResult(i >> n);
252    }
253    
254    ///////////////////////////////////////////////////////////////////////////
255    // built-in script function:  min()
256    
257    VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
258        vmint l = args->arg(0)->asInt()->evalInt();
259        vmint r = args->arg(1)->asInt()->evalInt();
260        return successResult(l < r ? l : r);
261    }
262    
263    ///////////////////////////////////////////////////////////////////////////
264    // built-in script function:  max()
265    
266    VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
267        vmint l = args->arg(0)->asInt()->evalInt();
268        vmint r = args->arg(1)->asInt()->evalInt();
269        return successResult(l > r ? l : r);
270    }
271    
272    ///////////////////////////////////////////////////////////////////////////
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        const vmint n = l->arraySize();
283        for (vmint i = 0; i < n; ++i)
284            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    ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
293        return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
294    }
295    
296    bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
297        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        const vmint needle = args->arg(1)->asInt()->evalInt();
306        const vmint n = a->arraySize();
307        for (vmint i = 0; i < n; ++i)
308            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    ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
317        return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
318    }
319    
320    bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
321        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        vmint m_index;
330    };
331    
332    static inline void swap(class ArrElemRef a, class ArrElemRef b);
333    
334    class ArrElemRef : protected ArrElemPOD {
335    public:
336        ArrElemRef() {
337            m_array = NULL;
338            m_index = 0;
339        }
340        ArrElemRef(VMIntArrayExpr* a, vmint index) {
341            m_array = a;
342            m_index = index;
343        }
344        inline ArrElemRef& operator=(const ArrElemRef& e) {
345            setValue(e.getValue());
346            return *this;
347        }
348        inline ArrElemRef& operator=(vmint val) {
349            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        inline bool operator==(vmint val) const {
358            return getValue() == val;
359        }
360        inline bool operator!=(const ArrElemRef& e) const {
361            return !(operator==(e));
362        }
363        inline bool operator!=(vmint val) const {
364            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        inline bool operator<(vmint val) const {
372            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        inline bool operator>(vmint val) const {
380            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        inline bool operator<=(vmint val) const {
388            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        inline bool operator>=(vmint val) const {
396            return getValue() >= val;
397        }
398        inline operator vmint() const {
399            return getValue();
400        }
401    protected:
402        inline vmint getValue() const {
403            return m_array->evalIntElement(m_index);
404        }
405        inline void setValue(vmint value) {
406            m_array->assignIntElement(m_index, value);
407        }
408    
409        friend void swap(class ArrElemRef a, class ArrElemRef b);
410    };
411    
412    class ArrElemPtr : protected ArrElemPOD {
413    public:
414        ArrElemPtr() {
415            m_array = NULL;
416            m_index = 0;
417        }
418        ArrElemPtr(VMIntArrayExpr* a, vmint index) {
419            m_array = a;
420            m_index = index;
421        }
422        inline ArrElemRef operator*() {
423            return *(ArrElemRef*)this;
424        }
425    };
426    
427    static inline void swap(ArrElemRef a, ArrElemRef b) {
428        vmint valueA = a.getValue();
429        vmint valueB = b.getValue();
430        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        typedef vmint value_type;
438        typedef ssize_t difference_type;
439        typedef ArrElemPtr pointer;
440        typedef ArrElemRef reference;
441    
442        ArrExprIter(VMIntArrayExpr* a, vmint index) {
443            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        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        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        inline bool operator()(const vmint& a, const vmint& b) const {
512            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        vmint n = a->arraySize();
521        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  } // namespace LinuxSampler  } // namespace LinuxSampler

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

  ViewVC Help
Powered by ViewVC