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

Legend:
Removed from v.2598  
changed lines
  Added in v.3575

  ViewVC Help
Powered by ViewVC