/[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 3345 by schoenebeck, Thu Aug 10 13:18:06 2017 UTC revision 3582 by schoenebeck, Fri Aug 30 12:23:40 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2017 Christian Schoenebeck   * Copyright (c) 2014-2019 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 19  Line 19 
19    
20  namespace LinuxSampler {  namespace LinuxSampler {
21    
22    inline bool _fEqualX(vmfloat a, vmfloat b) {
23        if (sizeof(vmfloat) == sizeof(float))
24            return RTMath::fEqual32(a, b);
25        else
26            return RTMath::fEqual64(a, b);
27    }
28    
29  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
30  // class VMEmptyResultFunction  // class VMEmptyResultFunction
31    
# Line 35  VMFnResult* VMEmptyResultFunction::succe Line 42  VMFnResult* VMEmptyResultFunction::succe
42  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
43  // class VMIntResultFunction  // class VMIntResultFunction
44    
45  VMFnResult* VMIntResultFunction::errorResult(int i) {  VMFnResult* VMIntResultFunction::errorResult(vmint i) {
46      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
47      result.value = i;      result.value = i;
48        result.unitPrefixFactor = VM_NO_FACTOR;
49      return &result;      return &result;
50  }  }
51    
52  VMFnResult* VMIntResultFunction::successResult(int i) {  VMFnResult* VMIntResultFunction::successResult(vmint i) {
53      result.flags = STMT_SUCCESS;      result.flags = STMT_SUCCESS;
54      result.value = i;      result.value = i;
55        result.unitPrefixFactor = VM_NO_FACTOR;
56        return &result;
57    }
58    
59    VMFnResult* VMIntResultFunction::errorResult(VMIntFnResDef res) {
60        result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
61        result.value = res.value;
62        result.unitPrefixFactor = res.unitFactor;
63        return &result;
64    }
65    
66    VMFnResult* VMIntResultFunction::successResult(VMIntFnResDef res) {
67        result.flags = STMT_SUCCESS;
68        result.value = res.value;
69        result.unitPrefixFactor = res.unitFactor;
70        return &result;
71    }
72    
73    ///////////////////////////////////////////////////////////////////////////
74    // class VMRealResultFunction
75    
76    VMFnResult* VMRealResultFunction::errorResult(vmfloat f) {
77        result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
78        result.value = f;
79        result.unitPrefixFactor = VM_NO_FACTOR;
80        return &result;
81    }
82    
83    VMFnResult* VMRealResultFunction::errorResult(VMRealFnResDef res) {
84        result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
85        result.value = res.value;
86        result.unitPrefixFactor = res.unitFactor;
87        return &result;
88    }
89    
90    VMFnResult* VMRealResultFunction::successResult(vmfloat f) {
91        result.flags = STMT_SUCCESS;
92        result.value = f;
93        result.unitPrefixFactor = VM_NO_FACTOR;
94        return &result;
95    }
96    
97    VMFnResult* VMRealResultFunction::successResult(VMRealFnResDef res) {
98        result.flags = STMT_SUCCESS;
99        result.value = res.value;
100        result.unitPrefixFactor = res.unitFactor;
101      return &result;      return &result;
102  }  }
103    
# Line 63  VMFnResult* VMStringResultFunction::succ Line 117  VMFnResult* VMStringResultFunction::succ
117  }  }
118    
119  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
120    // class VMNumberResultFunction
121    
122    VMFnResult* VMNumberResultFunction::errorResult(vmint i) {
123        intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
124        intResult.value = i;
125        intResult.unitPrefixFactor = VM_NO_FACTOR;
126        return &intResult;
127    }
128    
129    VMFnResult* VMNumberResultFunction::errorResult(vmfloat f) {
130        realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
131        realResult.value = f;
132        realResult.unitPrefixFactor = VM_NO_FACTOR;
133        return &realResult;
134    }
135    
136    VMFnResult* VMNumberResultFunction::successResult(vmint i) {
137        intResult.flags = STMT_SUCCESS;
138        intResult.value = i;
139        intResult.unitPrefixFactor = VM_NO_FACTOR;
140        return &intResult;
141    }
142    
143    VMFnResult* VMNumberResultFunction::successResult(vmfloat f) {
144        realResult.flags = STMT_SUCCESS;
145        realResult.value = f;
146        realResult.unitPrefixFactor = VM_NO_FACTOR;
147        return &realResult;
148    }
149    
150    VMFnResult* VMNumberResultFunction::errorIntResult(VMIntFnResDef res) {
151        intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
152        intResult.value = res.value;
153        intResult.unitPrefixFactor = res.unitFactor;
154        return &intResult;
155    }
156    
157    VMFnResult* VMNumberResultFunction::errorRealResult(VMRealFnResDef res) {
158        realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
159        realResult.value = res.value;
160        realResult.unitPrefixFactor = res.unitFactor;
161        return &realResult;
162    }
163    
164    VMFnResult* VMNumberResultFunction::successIntResult(VMIntFnResDef res) {
165        intResult.flags = STMT_SUCCESS;
166        intResult.value = res.value;
167        intResult.unitPrefixFactor = res.unitFactor;
168        return &intResult;
169    }
170    
171    VMFnResult* VMNumberResultFunction::successRealResult(VMRealFnResDef res) {
172        realResult.flags = STMT_SUCCESS;
173        realResult.value = res.value;
174        realResult.unitPrefixFactor = res.unitFactor;
175        return &realResult;
176    }
177    
178    ///////////////////////////////////////////////////////////////////////////
179  // built-in script function:  message()  // built-in script function:  message()
180    
181  bool CoreVMFunction_message::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
182      return type == INT_EXPR || type == STRING_EXPR;      return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
183  }  }
184    
185  VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
# Line 80  VMFnResult* CoreVMFunction_message::exec Line 193  VMFnResult* CoreVMFunction_message::exec
193          return successResult();          return successResult();
194      }      }
195    
196        VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(args->arg(0));
197        if (realExpr) {
198            printf("[ScriptVM %.3f] %f\n", usecs/1000000.f, realExpr->evalReal());
199            return successResult();
200        }
201    
202      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
203      if (intExpr) {      if (intExpr) {
204          printf("[ScriptVM %.3f] %d\n", usecs/1000000.f, intExpr->evalInt());          printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
205          return successResult();          return successResult();
206      }      }
207    
# Line 92  VMFnResult* CoreVMFunction_message::exec Line 211  VMFnResult* CoreVMFunction_message::exec
211  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
212  // built-in script function:  exit()  // built-in script function:  exit()
213    
214    vmint CoreVMFunction_exit::maxAllowedArgs() const {
215        return (vm->isExitResultEnabled()) ? 1 : 0;
216    }
217    
218    bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
219        if (!vm->isExitResultEnabled()) return false;
220        return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
221    }
222    
223    bool CoreVMFunction_exit::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
224        if (!vm->isExitResultEnabled()) return false;
225        return true;
226    }
227    
228    bool CoreVMFunction_exit::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
229        if (!vm->isExitResultEnabled()) return false;
230        return true;
231    }
232    bool CoreVMFunction_exit::acceptsArgFinal(vmint iArg) const {
233        if (!vm->isExitResultEnabled()) return false;
234        return true;
235    }
236    
237  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
238      this->result.flags = STMT_ABORT_SIGNALLED;      this->result.flags = STMT_ABORT_SIGNALLED;
239        if (vm->isExitResultEnabled() && args->argsCount()) {
240            ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
241            switch (args->arg(0)->exprType()) {
242                case INT_EXPR: {
243                    VMIntExpr* expr = args->arg(0)->asInt();
244                    ctx->exitRes.intLiteral = IntLiteral({
245                        .value = expr->evalInt(),
246                        .unitFactor = expr->unitFactor(),
247                        .unitType = expr->unitType(),
248                        .isFinal = expr->isFinal()
249                    });
250                    ctx->exitRes.value = &ctx->exitRes.intLiteral;
251                    break;
252                }
253                case REAL_EXPR: {
254                    VMRealExpr* expr = args->arg(0)->asReal();
255                    ctx->exitRes.realLiteral = RealLiteral({
256                        .value = expr->evalReal(),
257                        .unitFactor = expr->unitFactor(),
258                        .unitType = expr->unitType(),
259                        .isFinal = expr->isFinal()
260                    });
261                    ctx->exitRes.value = &ctx->exitRes.realLiteral;
262                    break;
263                }
264                case STRING_EXPR:
265                    ctx->exitRes.stringLiteral = StringLiteral(
266                        args->arg(0)->asString()->evalStr()
267                    );
268                    ctx->exitRes.value = &ctx->exitRes.stringLiteral;
269                    break;
270                default:
271                    ; // noop - just to shut up the compiler
272            }
273        }
274      return &result;      return &result;
275  }  }
276    
277  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
278  // built-in script function:  wait()  // built-in script function:  wait()
279    
280    bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
281        if (iArg == 0)
282            return type == VM_NO_UNIT || type == VM_SECOND;
283        else
284            return type == VM_NO_UNIT;
285    }
286    
287    bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
288        return iArg == 0 && type == VM_SECOND;
289    }
290    
291  VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
292      ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());      ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
293      VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));      VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));
294      int us = expr->evalInt();      StdUnit_t unit = expr->unitType();
295        vmint us = (unit) ? expr->evalInt(VM_MICRO) : expr->evalInt();
296      if (us < 0) {      if (us < 0) {
297          wrnMsg("wait(): argument may not be negative! Aborting script!");          wrnMsg("wait(): argument may not be negative! Aborting script!");
298          this->result.flags = STMT_ABORT_SIGNALLED;          this->result.flags = STMT_ABORT_SIGNALLED;
# Line 120  VMFnResult* CoreVMFunction_wait::exec(VM Line 309  VMFnResult* CoreVMFunction_wait::exec(VM
309  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
310  // built-in script function:  abs()  // built-in script function:  abs()
311    
312  bool CoreVMFunction_abs::acceptsArgType(int iArg, ExprType_t type) const {  ExprType_t CoreVMFunction_abs::returnType(VMFnArgs* args) {
313      return type == INT_EXPR;      return args->arg(0)->exprType();
314    }
315    
316    StdUnit_t CoreVMFunction_abs::returnUnitType(VMFnArgs* args) {
317        return args->arg(0)->asNumber()->unitType();
318    }
319    
320    bool CoreVMFunction_abs::returnsFinal(VMFnArgs* args) {
321        return args->arg(0)->asNumber()->isFinal();
322    }
323    
324    bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
325        return type == INT_EXPR || type == REAL_EXPR;
326  }  }
327    
328  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
329      return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );      VMExpr* arg = args->arg(0);
330        if (arg->exprType() == REAL_EXPR) {
331            VMRealExpr* expr = arg->asReal();
332            return successRealResult({
333                .value = ::fabs(expr->evalReal()),
334                .unitFactor = expr->unitFactor()
335            });
336        } else {
337            VMIntExpr* expr = arg->asInt();
338            return successIntResult({
339                .value = ::abs(expr->evalInt()),
340                .unitFactor = expr->unitFactor()
341            });
342        }
343  }  }
344    
345  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
346  // built-in script function:  random()  // built-in script function:  random()
347    
348  bool CoreVMFunction_random::acceptsArgType(int iArg, ExprType_t type) const {  ExprType_t CoreVMFunction_random::returnType(VMFnArgs* args) {
349      return type == INT_EXPR;      return (args->arg(0)->exprType() == INT_EXPR &&
350                args->arg(1)->exprType() == INT_EXPR) ? INT_EXPR : REAL_EXPR;
351    }
352    
353    StdUnit_t CoreVMFunction_random::returnUnitType(VMFnArgs* args) {
354        // we ensure in checkArgs() below (which is called before this method here)
355        // that both arguments must be of same unit type, so either one is fine here
356        return args->arg(0)->asNumber()->unitType();
357    }
358    
359    bool CoreVMFunction_random::returnsFinal(VMFnArgs* args) {
360        return args->arg(0)->asNumber()->isFinal() ||
361               args->arg(1)->asNumber()->isFinal();
362    }
363    
364    bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
365        return type == INT_EXPR || type == REAL_EXPR;
366    }
367    
368    void CoreVMFunction_random::checkArgs(VMFnArgs* args,
369                                          std::function<void(String)> err,
370                                          std::function<void(String)> wrn)
371    {
372        // super class checks
373        Super::checkArgs(args, err, wrn);
374    
375        // own checks ...
376        if (args->arg(0)->asNumber()->unitType() !=
377            args->arg(1)->asNumber()->unitType())
378        {
379            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
380            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
381            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
382            return;
383        }
384        if (args->arg(0)->asNumber()->isFinal() !=
385            args->arg(1)->asNumber()->isFinal())
386        {
387            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
388            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
389            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
390        }
391  }  }
392    
393  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
     int iMin = args->arg(0)->asInt()->evalInt();  
     int iMax = args->arg(1)->asInt()->evalInt();  
394      float f = float(::rand()) / float(RAND_MAX);      float f = float(::rand()) / float(RAND_MAX);
395      return successResult(  
396          iMin + roundf( f * float(iMax - iMin) )      VMNumberExpr* arg0 = args->arg(0)->asNumber();
397      );      VMNumberExpr* arg1 = args->arg(1)->asNumber();
398    
399        if (arg0->exprType() == INT_EXPR && arg1->exprType() == INT_EXPR) {
400            vmint iMin = args->arg(0)->asInt()->evalInt();
401            vmint iMax = args->arg(1)->asInt()->evalInt();
402            if (arg0->unitFactor() == arg1->unitFactor()) {
403                return successIntResult({
404                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
405                    .unitFactor = arg0->unitFactor()
406                });
407            } else if (arg0->unitFactor() < arg1->unitFactor()) {
408                iMax = Unit::convIntToUnitFactor(iMax, arg1, arg0);
409                return successIntResult({
410                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
411                    .unitFactor = arg0->unitFactor()
412                });
413            } else { // arg0->unitFactor() > arg1->unitFactor() ...
414                iMin = Unit::convIntToUnitFactor(iMin, arg0, arg1);
415                return successIntResult({
416                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
417                    .unitFactor = arg1->unitFactor()
418                });
419            }
420        } else {
421            vmfloat fMin = arg0->evalCastReal();
422            vmfloat fMax = arg1->evalCastReal();
423            if (arg0->unitFactor() == arg1->unitFactor()) {
424                return successRealResult({
425                    .value = fMin + f * (fMax - fMin),
426                    .unitFactor = arg0->unitFactor()
427                });
428            } else if (arg0->unitFactor() < arg1->unitFactor()) {
429                fMax = Unit::convRealToUnitFactor(fMax, arg1, arg0);
430                return successRealResult({
431                    .value = fMin + f * (fMax - fMin),
432                    .unitFactor = arg0->unitFactor()
433                });
434            } else { // arg0->unitFactor() > arg1->unitFactor() ...
435                fMin = Unit::convRealToUnitFactor(fMin, arg0, arg1);
436                return successRealResult({
437                    .value = fMin + f * (fMax - fMin),
438                    .unitFactor = arg1->unitFactor()
439                });
440            }
441        }
442  }  }
443    
444  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
445  // built-in script function:  num_elements()  // built-in script function:  num_elements()
446    
447  bool CoreVMFunction_num_elements::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
448      return type == INT_ARR_EXPR;      return isArray(type);
449  }  }
450    
451  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
452      return successResult( args->arg(0)->asIntArray()->arraySize() );      return successResult( args->arg(0)->asArray()->arraySize() );
453  }  }
454    
455  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
456  // built-in script function:  inc()  // built-in script function:  inc()
457    
458    StdUnit_t CoreVMFunction_inc::returnUnitType(VMFnArgs* args) {
459        return args->arg(0)->asNumber()->unitType();
460    }
461    
462    bool CoreVMFunction_inc::returnsFinal(VMFnArgs* args) {
463        return args->arg(0)->asNumber()->isFinal();
464    }
465    
466    void CoreVMFunction_inc::checkArgs(VMFnArgs* args,
467                                       std::function<void(String)> err,
468                                       std::function<void(String)> wrn)
469    {
470        // super class checks
471        Super::checkArgs(args, err, wrn);
472    
473        // own checks ...
474        if (args->arg(0)->asNumber()->unitType()) {
475            String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
476            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be incremented by one.");
477        }
478    }
479    
480  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
481      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
482      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
483      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
484      if (!in || !out) successResult(0);      vmint i = in->evalInt() + 1;
485      int i = in->evalInt() + 1;      IntLiteral tmp({
486      IntLiteral tmp(i);          .value = i,
487            .unitFactor = in->unitFactor()
488        });
489      out->assignExpr(&tmp);      out->assignExpr(&tmp);
490      return successResult(i);      return successResult({
491            .value = i,
492            .unitFactor = in->unitFactor()
493        });
494  }  }
495    
496  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
497  // built-in script function:  dec()  // built-in script function:  dec()
498    
499    StdUnit_t CoreVMFunction_dec::returnUnitType(VMFnArgs* args) {
500        return args->arg(0)->asNumber()->unitType();
501    }
502    
503    bool CoreVMFunction_dec::returnsFinal(VMFnArgs* args) {
504        return args->arg(0)->asNumber()->isFinal();
505    }
506    
507    void CoreVMFunction_dec::checkArgs(VMFnArgs* args,
508                                       std::function<void(String)> err,
509                                       std::function<void(String)> wrn)
510    {
511        // super class checks
512        Super::checkArgs(args, err, wrn);
513    
514        // own checks ...
515        if (args->arg(0)->asNumber()->unitType()) {
516            String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
517            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be decremented by one.");
518        }
519    }
520    
521  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
522      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
523      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
524      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
525      if (!in || !out) successResult(0);      vmint i = in->evalInt() - 1;
526      int i = in->evalInt() - 1;      IntLiteral tmp({
527      IntLiteral tmp(i);          .value = i,
528            .unitFactor = in->unitFactor()
529        });
530      out->assignExpr(&tmp);      out->assignExpr(&tmp);
531      return successResult(i);      return successResult({
532            .value = i,
533            .unitFactor = in->unitFactor()
534        });
535  }  }
536    
537  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
538  // built-in script function:  in_range()  // built-in script function:  in_range()
539    
540  VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {  bool CoreVMFunction_in_range::acceptsArgType(vmint iArg, ExprType_t type) const {
541      int i  = args->arg(0)->asInt()->evalInt();      return type == INT_EXPR || type == REAL_EXPR;
542      int lo = args->arg(1)->asInt()->evalInt();  }
543      int hi = args->arg(2)->asInt()->evalInt();  
544      if (lo > hi) { // swap lo and hi  void CoreVMFunction_in_range::checkArgs(VMFnArgs* args,
545          int tmp = lo;                                          std::function<void(String)> err,
546          lo = hi;                                          std::function<void(String)> wrn)
547          hi = tmp;  {
548        // super class checks
549        Super::checkArgs(args, err, wrn);
550    
551        // own checks ...
552        if (args->arg(0)->asNumber()->unitType() !=
553            args->arg(1)->asNumber()->unitType() ||
554            args->arg(1)->asNumber()->unitType() !=
555            args->arg(2)->asNumber()->unitType())
556        {
557            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
558            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
559            String c = unitTypeStr(args->arg(2)->asNumber()->unitType());
560            err("Arguments must all have same unit, however argument 1 is " + a +
561                ", argument 2 is " + b + ", argument 3 is " + c + ".");
562            return;
563        }
564        if (args->arg(0)->exprType() != args->arg(1)->exprType() ||
565            args->arg(1)->exprType() != args->arg(2)->exprType())
566        {
567            String a = typeStr(args->arg(0)->exprType());
568            String b = typeStr(args->arg(1)->exprType());
569            String c = typeStr(args->arg(2)->exprType());
570            String r = typeStr(REAL_EXPR);
571            wrn("Argument 1 is " + a + ", argument 2 is " + b +
572                ", argument 3 is " + c + ", function result will be " + r + ".");
573      }      }
574      return successResult(i >= lo && i <= hi);  }
575    
576    template<class T>
577    inline void _swapByValue(T& a, T& b) {
578        T tmp = a;
579        a = b;
580        b = tmp;
581    }
582    
583    VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
584        VMNumberExpr* argNeedle = args->arg(0)->asNumber();
585        VMNumberExpr* argLo = args->arg(1)->asNumber();
586        VMNumberExpr* argHi = args->arg(2)->asNumber();
587    
588        vmfloat needle = argNeedle->evalCastReal();
589        vmfloat lo = argLo->evalCastReal();
590        vmfloat hi = argHi->evalCastReal();
591    
592        needle *= argNeedle->unitFactor();
593        lo *= argLo->unitFactor();
594        hi *= argHi->unitFactor();
595    
596        if (lo > hi) _swapByValue(lo, hi);
597    
598        return successResult(needle >= lo && needle <= hi);
599  }  }
600    
601  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
602  // built-in script function:  sh_left()  // built-in script function:  sh_left()
603    
604    bool CoreVMFunction_sh_left::returnsFinal(VMFnArgs* args) {
605        return args->arg(0)->asNumber()->isFinal();
606    }
607    
608  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
609      int i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
610      int n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
611      return successResult(i << n);      return successResult(i << n);
612  }  }
613    
614  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
615  // built-in script function:  sh_right()  // built-in script function:  sh_right()
616    
617    bool CoreVMFunction_sh_right::returnsFinal(VMFnArgs* args) {
618        return args->arg(0)->asNumber()->isFinal();
619    }
620    
621  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
622      int i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
623      int n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
624      return successResult(i >> n);      return successResult(i >> n);
625  }  }
626    
627  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
628  // built-in script function:  min()  // built-in script function:  min()
629    
630    ExprType_t CoreVMFunction_min::returnType(VMFnArgs* args) {
631        return (args->arg(0)->exprType() == REAL_EXPR ||
632                args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
633    }
634    
635    StdUnit_t CoreVMFunction_min::returnUnitType(VMFnArgs* args) {
636        return args->arg(0)->asNumber()->unitType();
637    }
638    
639    bool CoreVMFunction_min::returnsFinal(VMFnArgs* args) {
640        return args->arg(0)->asNumber()->isFinal() ||
641               args->arg(1)->asNumber()->isFinal();
642    }
643    
644    bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {
645        return type == INT_EXPR || type == REAL_EXPR;
646    }
647    
648    void CoreVMFunction_min::checkArgs(VMFnArgs* args,
649                                       std::function<void(String)> err,
650                                       std::function<void(String)> wrn)
651    {
652        // super class checks
653        Super::checkArgs(args, err, wrn);
654    
655        // own checks ...
656        if (args->arg(0)->asNumber()->unitType() !=
657            args->arg(1)->asNumber()->unitType())
658        {
659            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
660            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
661            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
662            return;
663        }
664        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
665            String a = typeStr(args->arg(0)->exprType());
666            String b = typeStr(args->arg(1)->exprType());
667            String c = typeStr(REAL_EXPR);
668            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
669            return;
670        }
671        if (args->arg(0)->asNumber()->isFinal() !=
672            args->arg(1)->asNumber()->isFinal())
673        {
674            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
675            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
676            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
677        }
678    }
679    
680  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
681      int l = args->arg(0)->asInt()->evalInt();      VMNumberExpr* lhs = args->arg(0)->asNumber();
682      int r = args->arg(1)->asInt()->evalInt();      VMNumberExpr* rhs = args->arg(1)->asNumber();
683      return successResult(l < r ? l : r);      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
684            vmfloat lm = lhs->asReal()->evalReal();
685            vmfloat rm = rhs->asReal()->evalReal();
686            vmfloat lprod = lm * lhs->unitFactor();
687            vmfloat rprod = rm * rhs->unitFactor();
688            return successRealResult({
689                .value = (lprod < rprod) ? lm : rm,
690                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
691            });
692        } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
693            vmfloat lm = lhs->asReal()->evalReal();
694            vmint   rm = rhs->asInt()->evalInt();
695            vmfloat lprod = lm * lhs->unitFactor();
696            vmfloat rprod = rm * rhs->unitFactor();
697            return successRealResult({
698                .value = (lprod < rprod) ? lm : rm,
699                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
700            });
701        } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
702            vmint   lm = lhs->asInt()->evalInt();
703            vmfloat rm = rhs->asReal()->evalReal();
704            vmfloat lprod = lm * lhs->unitFactor();
705            vmfloat rprod = rm * rhs->unitFactor();
706            return successRealResult({
707                .value = (lprod < rprod) ? lm : rm,
708                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
709            });
710        } else {
711            vmint lm = lhs->asInt()->evalInt();
712            vmint rm = rhs->asInt()->evalInt();
713            vmfloat lprod = lm * lhs->unitFactor();
714            vmfloat rprod = rm * rhs->unitFactor();
715            return successIntResult({
716                .value = (lprod < rprod) ? lm : rm,
717                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
718            });
719        }
720  }  }
721    
722  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
723  // built-in script function:  max()  // built-in script function:  max()
724    
725    ExprType_t CoreVMFunction_max::returnType(VMFnArgs* args) {
726        return (args->arg(0)->exprType() == REAL_EXPR ||
727                args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
728    }
729    
730    StdUnit_t CoreVMFunction_max::returnUnitType(VMFnArgs* args) {
731        return args->arg(0)->asNumber()->unitType();
732    }
733    
734    bool CoreVMFunction_max::returnsFinal(VMFnArgs* args) {
735        return args->arg(0)->asNumber()->isFinal() ||
736               args->arg(1)->asNumber()->isFinal();
737    }
738    
739    bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {
740        return type == INT_EXPR || type == REAL_EXPR;
741    }
742    
743    void CoreVMFunction_max::checkArgs(VMFnArgs* args,
744                                       std::function<void(String)> err,
745                                       std::function<void(String)> wrn)
746    {
747        // super class checks
748        Super::checkArgs(args, err, wrn);
749    
750        // own checks ...
751        if (args->arg(0)->asNumber()->unitType() !=
752            args->arg(1)->asNumber()->unitType())
753        {
754            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
755            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
756            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
757            return;
758        }
759        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
760            String a = typeStr(args->arg(0)->exprType());
761            String b = typeStr(args->arg(1)->exprType());
762            String c = typeStr(REAL_EXPR);
763            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
764            return;
765        }
766        if (args->arg(0)->asNumber()->isFinal() !=
767            args->arg(1)->asNumber()->isFinal())
768        {
769            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
770            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
771            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
772        }
773    }
774    
775  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
776      int l = args->arg(0)->asInt()->evalInt();      VMNumberExpr* lhs = args->arg(0)->asNumber();
777      int r = args->arg(1)->asInt()->evalInt();      VMNumberExpr* rhs = args->arg(1)->asNumber();
778      return successResult(l > r ? l : r);      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
779            vmfloat lm = lhs->asReal()->evalReal();
780            vmfloat rm = rhs->asReal()->evalReal();
781            vmfloat lprod = lm * lhs->unitFactor();
782            vmfloat rprod = rm * rhs->unitFactor();
783            return successRealResult({
784                .value = (lprod > rprod) ? lm : rm,
785                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
786            });
787        } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
788            vmfloat lm = lhs->asReal()->evalReal();
789            vmint   rm = rhs->asInt()->evalInt();
790            vmfloat lprod = lm * lhs->unitFactor();
791            vmfloat rprod = rm * rhs->unitFactor();
792            return successRealResult({
793                .value = (lprod > rprod) ? lm : rm,
794                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
795            });
796        } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
797            vmint   lm = lhs->asInt()->evalInt();
798            vmfloat rm = rhs->asReal()->evalReal();
799            vmfloat lprod = lm * lhs->unitFactor();
800            vmfloat rprod = rm * rhs->unitFactor();
801            return successRealResult({
802                .value = (lprod > rprod) ? lm : rm,
803                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
804            });
805        } else {
806            vmint lm = lhs->asInt()->evalInt();
807            vmint rm = rhs->asInt()->evalInt();
808            vmfloat lprod = lm * lhs->unitFactor();
809            vmfloat rprod = rm * rhs->unitFactor();
810            return successIntResult({
811                .value = (lprod > rprod) ? lm : rm,
812                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
813            });
814        }
815  }  }
816    
817  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
818  // built-in script function:  array_equal()  // built-in script function:  array_equal()
819    
820    bool CoreVMFunction_array_equal::acceptsArgType(vmint iArg, ExprType_t type) const {
821        return isArray(type);
822    }
823    
824    void CoreVMFunction_array_equal::checkArgs(VMFnArgs* args,
825                                               std::function<void(String)> err,
826                                               std::function<void(String)> wrn)
827    {
828        // super class checks
829        Super::checkArgs(args, err, wrn);
830    
831        // own checks ...
832        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
833            String a = typeStr(args->arg(0)->exprType());
834            String b = typeStr(args->arg(1)->exprType());
835            err("Argument 1 is " + a + ", whereas argument 2 is " + b + ".");
836            return;
837        }
838        if (args->arg(0)->asArray()->arraySize() !=
839            args->arg(1)->asArray()->arraySize())
840        {
841            wrn("Result of function call is always false, since the passed two arrays were declared with different array sizes.");
842        }
843    }
844    
845  VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
846      VMIntArrayExpr* l = args->arg(0)->asIntArray();      VMArrayExpr* l = args->arg(0)->asArray();
847      VMIntArrayExpr* r = args->arg(1)->asIntArray();      VMArrayExpr* r = args->arg(1)->asArray();
848      if (l->arraySize() != r->arraySize()) {      if (l->arraySize() != r->arraySize()) {
849          wrnMsg("array_equal(): the two arrays differ in size");          //wrnMsg("array_equal(): the two arrays differ in size");
850          return successResult(0); // false          return successResult(0); // false
851      }      }
852      const int n = l->arraySize();      const vmint n = l->arraySize();
853      for (int i = 0; i < n; ++i)      // checkArgs() above ensured that we either have INT_ARR_EXPR on both sides
854          if (l->evalIntElement(i) != r->evalIntElement(i))      // or REAL_ARR_EXPR on both sides, so we can simplify here (a bit)
855              return successResult(0); // false      if (l->exprType() == INT_ARR_EXPR) {
856            VMIntArrayExpr* lia = l->asIntArray();
857            VMIntArrayExpr* ria = r->asIntArray();
858            for (vmint i = 0; i < n; ++i) {
859                vmint lvalue = lia->evalIntElement(i);
860                vmint rvalue = ria->evalIntElement(i);
861                vmfloat lfactor = lia->unitFactorOfElement(i);
862                vmfloat rfactor = ria->unitFactorOfElement(i);
863                if (lfactor == rfactor) {
864                    if (lvalue != rvalue)
865                        return successResult(0); // false
866                    else
867                        continue;
868                }
869                if (lfactor < rfactor) {
870                    if (lvalue != Unit::convIntToUnitFactor(rvalue, rfactor, lfactor))
871                        return successResult(0); // false
872                    else
873                        continue;
874                } else {
875                    if (rvalue != Unit::convIntToUnitFactor(lvalue, lfactor, rfactor))
876                        return successResult(0); // false
877                    else
878                        continue;
879                }
880            }
881        } else {
882            VMRealArrayExpr* lra = l->asRealArray();
883            VMRealArrayExpr* rra = r->asRealArray();
884            for (vmint i = 0; i < n; ++i) {
885                vmfloat lvalue = lra->evalRealElement(i);
886                vmfloat rvalue = rra->evalRealElement(i);
887                vmfloat lfactor = lra->unitFactorOfElement(i);
888                vmfloat rfactor = rra->unitFactorOfElement(i);
889                if (lfactor == rfactor) {
890                    if (!_fEqualX(lvalue, rvalue))
891                        return successResult(0); // false
892                    else
893                        continue;
894                }
895                if (lfactor < rfactor) {
896                    if (!_fEqualX(lvalue, Unit::convRealToUnitFactor(rvalue, rfactor, lfactor)))
897                        return successResult(0); // false
898                    else
899                        continue;
900                } else {
901                    if (!_fEqualX(rvalue, Unit::convRealToUnitFactor(lvalue, lfactor, rfactor)))
902                        return successResult(0); // false
903                    else
904                        continue;
905                }
906            }
907        }
908      return successResult(1); // true      return successResult(1); // true
909  }  }
910    
911  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
912  // built-in script function:  search()  // built-in script function:  search()
913    
914  ExprType_t CoreVMFunction_search::argType(int iArg) const {  ExprType_t CoreVMFunction_search::argType(vmint iArg) const {
915      return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;      return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
916  }  }
917    
918  bool CoreVMFunction_search::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
919      if (iArg == 0)      if (iArg == 0)
920          return type == INT_ARR_EXPR;          return isArray(type);
921      else      else
922          return type == INT_EXPR;          return type == INT_EXPR || type == REAL_EXPR;
923    }
924    
925    void CoreVMFunction_search::checkArgs(VMFnArgs* args,
926                                          std::function<void(String)> err,
927                                          std::function<void(String)> wrn)
928    {
929        // super class checks
930        Super::checkArgs(args, err, wrn);
931    
932        // own checks ...
933        if (args->arg(0)->exprType() == INT_ARR_EXPR &&
934            args->arg(1)->exprType() != INT_EXPR)
935        {
936            String a = typeStr(INT_ARR_EXPR);
937            String bIs = typeStr(args->arg(1)->exprType());
938            String bShould = typeStr(INT_EXPR);
939            err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
940            return;
941        }
942        if (args->arg(0)->exprType() == REAL_ARR_EXPR &&
943            args->arg(1)->exprType() != REAL_EXPR)
944        {
945            String a = typeStr(REAL_ARR_EXPR);
946            String bIs = typeStr(args->arg(1)->exprType());
947            String bShould = typeStr(REAL_EXPR);
948            err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
949            return;
950        }
951  }  }
952    
953  VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
954      VMIntArrayExpr* a = args->arg(0)->asIntArray();      VMArrayExpr* a = args->arg(0)->asArray();
955      const int needle = args->arg(1)->asInt()->evalInt();      const vmint n = a->arraySize();
956      const int n = a->arraySize();      if (a->exprType() == INT_ARR_EXPR) {
957      for (int i = 0; i < n; ++i)          const vmint needle = args->arg(1)->asInt()->evalInt();
958          if (a->evalIntElement(i) == needle)          VMIntArrayExpr* intArray = a->asIntArray();
959              return successResult(i);          for (vmint i = 0; i < n; ++i)
960                if (intArray->evalIntElement(i) == needle)
961                    return successResult(i);
962        } else { // real array ...
963            const vmfloat needle = args->arg(1)->asReal()->evalReal();
964            VMRealArrayExpr* realArray = a->asRealArray();
965            for (vmint i = 0; i < n; ++i) {
966                const vmfloat value = realArray->evalRealElement(i);
967                if (_fEqualX(value, needle))
968                    return successResult(i);
969            }
970        }
971      return successResult(-1); // not found      return successResult(-1); // not found
972  }  }
973    
974  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
975  // built-in script function:  sort()  // built-in script function:  sort()
976    
977  ExprType_t CoreVMFunction_sort::argType(int iArg) const {  ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {
978      return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;      return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;
979  }  }
980    
981  bool CoreVMFunction_sort::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
982      if (iArg == 0)      if (iArg == 0)
983          return type == INT_ARR_EXPR;          return isArray(type);
984      else      else
985          return type == INT_EXPR;          return type == INT_EXPR;
986  }  }
987    
988    // The following structs and template classes act as adapters for allowing to
989    // use std sort algorithms on our arrays. It might look a bit more complicated
990    // than it ought to be, but there is one reason for the large amount of
991    // 'adapter' code below: the STL std algorithms rely on 'lvalues' to do their
992    // e.g. sorting) jobs, that is they expect containers to have 'localizeable'
993    // data which essentially means their data should reside somewhere in memory and
994    // directly be accessible (readable and writable) there, which is not the case
995    // with our VM interfaces which actually always require virtual getter and
996    // setter methods to be called instead. So we must emulate lvalues by custom
997    // classes/structs which forward between our getters/setters and the lvalue
998    // access operators used by the STL std algorithms.
999    
1000    struct IntArrayAccessor {
1001        static inline vmint getPrimaryValue(VMIntArrayExpr* arr, vmint index) {
1002            return arr->evalIntElement(index);
1003        }
1004        static inline void setPrimaryValue(VMIntArrayExpr* arr, vmint index, vmint value) {
1005            arr->assignIntElement(index, value);
1006        }
1007    };
1008    
1009    struct RealArrayAccessor {
1010        static inline vmfloat getPrimaryValue(VMRealArrayExpr* arr, vmint index) {
1011            return arr->evalRealElement(index);
1012        }
1013        static inline void setPrimaryValue(VMRealArrayExpr* arr, vmint index, vmfloat value) {
1014            arr->assignRealElement(index, value);
1015        }
1016    };
1017    
1018    template<class T_array> // i.e. T_array is either VMIntArrayExpr or VMRealArrayExpr
1019  struct ArrElemPOD {  struct ArrElemPOD {
1020      VMIntArrayExpr* m_array;      T_array* m_array;
1021      int m_index;      vmint m_index;
1022  };  };
1023    
1024  static inline void swap(class ArrElemRef a, class ArrElemRef b);  // This class is used for temporary values by std::sort().
1025    template<class T_value> // i.e. T_value is either vmint or vmfloat
1026    struct ScalarNmbrVal {
1027        T_value primValue;
1028        vmfloat unitFactor;
1029    
1030        inline bool operator<(const ScalarNmbrVal& other) const {
1031            return getProdValue() < other.getProdValue();
1032        }
1033        inline bool operator>(const ScalarNmbrVal& other) const {
1034            return getProdValue() > other.getProdValue();
1035        }
1036        inline vmfloat getProdValue() const {
1037            // simple solution for both vmint and vmfloat, should be fine for just sorting
1038            return primValue * unitFactor;
1039        }
1040    };
1041    
1042  class ArrElemRef : protected ArrElemPOD {  // This class emulates lvalue access (access by reference) which is used by ArrExprIter::operator*() below.
1043    template<class T_array, // T_array is either VMIntArrayExpr or VMRealArrayExpr
1044             class T_value, // T_value is either vmint or vmfloat
1045             class T_accessor> // T_accessor is either IntArrayAccessor or RealArrayAccessor
1046    class ArrElemRef : protected ArrElemPOD<T_array> {
1047  public:  public:
1048      ArrElemRef() {      typedef ScalarNmbrVal<T_value> ScalarNmbrVal;
1049          m_array = NULL;  
1050          m_index = 0;      inline ArrElemRef(T_array* a, vmint index) {
1051      }          this->m_array = a;
1052      ArrElemRef(VMIntArrayExpr* a, int index) {          this->m_index = index;
1053          m_array = a;      }
1054          m_index = index;      inline ArrElemRef(const ArrElemRef& ref) {
1055            this->m_array = ref.m_array;
1056            this->m_index = ref.m_index;
1057      }      }
1058      inline ArrElemRef& operator=(const ArrElemRef& e) {      inline ArrElemRef& operator=(const ArrElemRef& e) {
1059          setValue(e.getValue());          setPrimValue(e.getPrimValue());
1060            setUnitFactor(e.getUnitFactor());
1061          return *this;          return *this;
1062      }      }
1063      inline ArrElemRef& operator=(int val) {      inline ArrElemRef& operator=(ScalarNmbrVal value) {
1064          setValue(val);          setPrimValue(value.primValue);
1065            setUnitFactor(value.unitFactor);
1066          return *this;          return *this;
1067      }      }
1068      inline bool operator==(const ArrElemRef& e) const {      inline bool operator==(const ArrElemRef& e) const {
1069          if (m_index == e.m_index)          return getProdValue() == e.getProdValue();
             return true;  
         return getValue() == e.getValue();  
     }  
     inline bool operator==(int val) const {  
         return getValue() == val;  
1070      }      }
1071      inline bool operator!=(const ArrElemRef& e) const {      inline bool operator!=(const ArrElemRef& e) const {
1072          return !(operator==(e));          return !(operator==(e));
1073      }      }
     inline bool operator!=(int val) const {  
         return !(operator==(val));  
     }  
1074      inline bool operator<(const ArrElemRef& e) const {      inline bool operator<(const ArrElemRef& e) const {
1075          if (m_index == e.m_index)          return getProdValue() < e.getProdValue();
             return false;  
         return getValue() < e.getValue();  
     }  
     inline bool operator<(int val) const {  
         return getValue() < val;  
1076      }      }
1077      inline bool operator>(const ArrElemRef& e) const {      inline bool operator>(const ArrElemRef& e) const {
1078          if (m_index == e.m_index)          return getProdValue() > e.getProdValue();
             return false;  
         return getValue() > e.getValue();  
     }  
     inline bool operator>(int val) const {  
         return getValue() > val;  
1079      }      }
1080      inline bool operator<=(const ArrElemRef& e) const {      inline bool operator<=(const ArrElemRef& e) const {
1081          if (m_index == e.m_index)          return getProdValue() <= e.getProdValue();
             return true;  
         return getValue() <= e.getValue();  
     }  
     inline bool operator<=(int val) const {  
         return getValue() <= val;  
1082      }      }
1083      inline bool operator>=(const ArrElemRef& e) const {      inline bool operator>=(const ArrElemRef& e) const {
1084          if (m_index == e.m_index)          return getProdValue() >= e.getProdValue();
1085              return true;      }
1086          return getValue() >= e.getValue();      inline bool operator==(const ScalarNmbrVal& s) const {
1087            return getProdValue() == s.getProdValue();
1088        }
1089        inline bool operator!=(const ScalarNmbrVal& s) const {
1090            return !(operator==(s));
1091      }      }
1092      inline bool operator>=(int val) const {      inline bool operator<(const ScalarNmbrVal& s) const {
1093          return getValue() >= val;          return getProdValue() < s.getProdValue();
1094      }      }
1095      inline operator int() const {      inline bool operator>(const ScalarNmbrVal& s) const {
1096          return getValue();          return getProdValue() > s.getProdValue();
1097        }
1098        inline bool operator<=(const ScalarNmbrVal& s) const {
1099            return getProdValue() <= s.getProdValue();
1100        }
1101        inline bool operator>=(const ScalarNmbrVal& s) const {
1102            return getProdValue() >= s.getProdValue();
1103        }
1104        inline operator ScalarNmbrVal() {
1105            return {
1106                .primValue = getPrimValue() ,
1107                .unitFactor = getUnitFactor()
1108            };
1109      }      }
1110  protected:  protected:
1111      inline int getValue() const {      inline T_value getPrimValue() const {
1112          return m_array->evalIntElement(m_index);          return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1113      }      }
1114      inline void setValue(int value) {      inline void setPrimValue(T_value value) {
1115          m_array->assignIntElement(m_index, value);          T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1116      }      }
1117        inline vmfloat getUnitFactor() const {
1118      friend void swap(class ArrElemRef a, class ArrElemRef b);          return this->m_array->unitFactorOfElement(this->m_index);
 };  
   
 class ArrElemPtr : protected ArrElemPOD {  
 public:  
     ArrElemPtr() {  
         m_array = NULL;  
         m_index = 0;  
     }  
     ArrElemPtr(VMIntArrayExpr* a, int index) {  
         m_array = a;  
         m_index = index;  
1119      }      }
1120      inline ArrElemRef operator*() {      inline void setUnitFactor(vmfloat factor) {
1121          return *(ArrElemRef*)this;          this->m_array->assignElementUnitFactor(this->m_index, factor);
1122        }
1123        inline vmfloat getProdValue() const {
1124            // simple solution for both vmint and vmfloat, should be fine for just sorting
1125            vmfloat primary = (vmfloat) getPrimValue();
1126            vmfloat factor  = getUnitFactor();
1127            return primary * factor;
1128      }      }
 };  
1129    
1130  static inline void swap(ArrElemRef a, ArrElemRef b) {      // allow swap() functions below to access protected methods here
1131      int valueA = a.getValue();      friend void swap(class ArrElemRef<T_array,T_value,T_accessor> a,
1132      int valueB = b.getValue();                       class ArrElemRef<T_array,T_value,T_accessor> b);
1133      a.setValue(valueB);  };
     b.setValue(valueA);  
 }  
1134    
1135  class ArrExprIter : public ArrElemPOD {  // custom iterator class to be used by std:sort() on our VM arrays
1136    template<class T_array, class T_value, class T_accessor>
1137    class ArrExprIter : public ArrElemPOD<T_array> {
1138  public:  public:
1139      typedef std::random_access_iterator_tag iterator_category;      typedef std::random_access_iterator_tag iterator_category;
     typedef int value_type;  
1140      typedef ssize_t difference_type;      typedef ssize_t difference_type;
1141      typedef ArrElemPtr pointer;      typedef ArrElemRef<T_array, T_value, T_accessor> ArrElemRef;
1142      typedef ArrElemRef reference;      typedef ArrElemRef reference; // type used by STL for access by reference
1143        typedef void pointer; // type used by STL for -> operator result, we don't use that operator at all so just void it
1144      ArrExprIter(VMIntArrayExpr* a, int index) {      typedef ScalarNmbrVal<T_value> value_type; // type used by STL for temporary values
1145          m_array = a;  
1146          m_index = index;      ArrExprIter(T_array* a, vmint index) {
1147            this->m_array = a;
1148            this->m_index = index;
1149        }
1150        ArrExprIter(const ArrElemRef& ref) {
1151            this->m_array = ref.m_array;
1152            this->m_index = ref.m_index;
1153      }      }
1154      inline ArrElemRef operator*() {      inline ArrElemRef operator*() {
1155          return *(ArrElemRef*)this;          return ArrElemRef(this->m_array, this->m_index);
1156      }      }
1157      inline ArrExprIter& operator++() { // prefix increment      inline ArrExprIter& operator++() { // prefix increment
1158          ++m_index;          ++(this->m_index);
1159          return *this;          return *this;
1160      }      }
1161      inline ArrExprIter& operator--() { // prefix decrement      inline ArrExprIter& operator--() { // prefix decrement
1162          --m_index;          --(this->m_index);
1163          return *this;          return *this;
1164      }      }
1165      inline ArrExprIter operator++(int) { // postfix increment      inline ArrExprIter operator++(int) { // postfix increment
1166          ArrExprIter it = *this;          ArrExprIter it = *this;
1167          ++m_index;          ++(this->m_index);
1168          return it;          return it;
1169      }      }
1170      inline ArrExprIter operator--(int) { // postfix decrement      inline ArrExprIter operator--(int) { // postfix decrement
1171          ArrExprIter it = *this;          ArrExprIter it = *this;
1172          --m_index;          --(this->m_index);
1173          return it;          return it;
1174      }      }
1175      inline ArrExprIter& operator+=(difference_type d) {      inline ArrExprIter& operator+=(difference_type d) {
1176          m_index += d;          this->m_index += d;
1177          return *this;          return *this;
1178      }      }
1179      inline ArrExprIter& operator-=(difference_type d) {      inline ArrExprIter& operator-=(difference_type d) {
1180          m_index -= d;          this->m_index -= d;
1181          return *this;          return *this;
1182      }      }
1183      inline bool operator==(const ArrExprIter& other) const {      inline bool operator==(const ArrExprIter& other) const {
1184          return m_index == other.m_index;          return this->m_index == other.m_index;
1185      }      }
1186      inline bool operator!=(const ArrExprIter& other) const {      inline bool operator!=(const ArrExprIter& other) const {
1187          return m_index != other.m_index;          return this->m_index != other.m_index;
1188      }      }
1189      inline bool operator<(const ArrExprIter& other) const {      inline bool operator<(const ArrExprIter& other) const {
1190          return m_index < other.m_index;          return this->m_index < other.m_index;
1191      }      }
1192      inline bool operator>(const ArrExprIter& other) const {      inline bool operator>(const ArrExprIter& other) const {
1193          return m_index > other.m_index;          return this->m_index > other.m_index;
1194      }      }
1195      inline bool operator<=(const ArrExprIter& other) const {      inline bool operator<=(const ArrExprIter& other) const {
1196          return m_index <= other.m_index;          return this->m_index <= other.m_index;
1197      }      }
1198      inline bool operator>=(const ArrExprIter& other) const {      inline bool operator>=(const ArrExprIter& other) const {
1199          return m_index >= other.m_index;          return this->m_index >= other.m_index;
1200      }      }
1201      inline difference_type operator+(const ArrExprIter& other) const {      inline difference_type operator+(const ArrExprIter& other) const {
1202          return m_index + other.m_index;          return this->m_index + other.m_index;
1203      }      }
1204      inline difference_type operator-(const ArrExprIter& other) const {      inline difference_type operator-(const ArrExprIter& other) const {
1205          return m_index - other.m_index;          return this->m_index - other.m_index;
1206      }      }
1207      inline ArrExprIter operator-(difference_type d) const {      inline ArrExprIter operator-(difference_type d) const {
1208          return ArrExprIter(m_array, m_index - d);          return ArrExprIter(this->m_array, this->m_index - d);
1209      }      }
1210      inline ArrExprIter operator+(difference_type d) const {      inline ArrExprIter operator+(difference_type d) const {
1211          return ArrExprIter(m_array, m_index + d);          return ArrExprIter(this->m_array, this->m_index + d);
1212      }      }
1213      inline ArrExprIter operator*(difference_type factor) const {      inline ArrExprIter operator*(difference_type factor) const {
1214          return ArrExprIter(m_array, m_index * factor);          return ArrExprIter(this->m_array, this->m_index * factor);
1215      }      }
1216  };  };
1217    
1218    typedef ArrExprIter<VMIntArrayExpr,vmint,IntArrayAccessor> IntArrExprIter;
1219    typedef ArrExprIter<VMRealArrayExpr,vmfloat,RealArrayAccessor> RealArrExprIter;
1220    
1221    // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1222    static inline void swap(IntArrExprIter::ArrElemRef a,
1223                            IntArrExprIter::ArrElemRef b)
1224    {
1225        vmint valueA = a.getPrimValue();
1226        vmint valueB = b.getPrimValue();
1227        vmfloat factorA = a.getUnitFactor();
1228        vmfloat factorB = b.getUnitFactor();
1229        a.setPrimValue(valueB);
1230        a.setUnitFactor(factorB);
1231        b.setPrimValue(valueA);
1232        b.setUnitFactor(factorA);
1233    }
1234    
1235    // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1236    static inline void swap(RealArrExprIter::ArrElemRef a,
1237                            RealArrExprIter::ArrElemRef b)
1238    {
1239        vmfloat valueA = a.getPrimValue();
1240        vmfloat valueB = b.getPrimValue();
1241        vmfloat factorA = a.getUnitFactor();
1242        vmfloat factorB = b.getUnitFactor();
1243        a.setPrimValue(valueB);
1244        a.setUnitFactor(factorB);
1245        b.setPrimValue(valueA);
1246        b.setUnitFactor(factorA);
1247    }
1248    
1249    // used to sort in descending order (unlike the default behaviour of std::sort() which is ascending order)
1250    template<class T> // T is either IntArrExprIter or RealArrExprIter
1251  struct DescArrExprSorter {  struct DescArrExprSorter {
1252      inline bool operator()(const int& a, const int& b) const {      inline bool operator()(const typename T::value_type a, const typename T::value_type b) const {
1253          return a > b;          return a > b;
1254      }      }
1255  };  };
1256    
1257  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1258      VMIntArrayExpr* a = args->arg(0)->asIntArray();      const bool bAscending =
     bool bAscending =  
1259          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1260      int n = a->arraySize();  
1261      ArrExprIter itBegin(a, 0);      if (args->arg(0)->exprType() == INT_ARR_EXPR) {
1262      ArrExprIter itEnd(a, n);          VMIntArrayExpr* a = args->arg(0)->asIntArray();
1263      if (bAscending) {          vmint n = a->arraySize();
1264          std::sort(itBegin, itEnd);          IntArrExprIter itBegin(a, 0);
1265            IntArrExprIter itEnd(a, n);
1266            if (bAscending) {
1267                std::sort(itBegin, itEnd);
1268            } else {
1269                DescArrExprSorter<IntArrExprIter> sorter;
1270                std::sort(itBegin, itEnd, sorter);
1271            }
1272      } else {      } else {
1273          DescArrExprSorter sorter;          VMRealArrayExpr* a = args->arg(0)->asRealArray();
1274          std::sort(itBegin, itEnd, sorter);          vmint n = a->arraySize();
1275            RealArrExprIter itBegin(a, 0);
1276            RealArrExprIter itEnd(a, n);
1277            if (bAscending) {
1278                std::sort(itBegin, itEnd);
1279            } else {
1280                DescArrExprSorter<RealArrExprIter> sorter;
1281                std::sort(itBegin, itEnd, sorter);
1282            }
1283      }      }
1284    
1285      return successResult();      return successResult();
1286  }  }
1287    
1288    ///////////////////////////////////////////////////////////////////////////
1289    // built-in script function:  real_to_int()  and  int()
1290    
1291    StdUnit_t CoreVMFunction_real_to_int::returnUnitType(VMFnArgs* args) {
1292        return args->arg(0)->asNumber()->unitType();
1293    }
1294    
1295    bool CoreVMFunction_real_to_int::returnsFinal(VMFnArgs* args) {
1296        return args->arg(0)->asNumber()->isFinal();
1297    }
1298    
1299    VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1300        VMRealExpr* realExpr = args->arg(0)->asReal();
1301        vmfloat f = realExpr->evalReal();
1302        return successResult({
1303            .value = vmint(f),
1304            .unitFactor = realExpr->unitFactor()
1305        });
1306    }
1307    
1308    ///////////////////////////////////////////////////////////////////////////
1309    // built-in script function:  int_to_real()  and  real()
1310    
1311    StdUnit_t CoreVMFunction_int_to_real::returnUnitType(VMFnArgs* args) {
1312        return args->arg(0)->asNumber()->unitType();
1313    }
1314    
1315    bool CoreVMFunction_int_to_real::returnsFinal(VMFnArgs* args) {
1316        return args->arg(0)->asNumber()->isFinal();
1317    }
1318    
1319    VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1320        VMIntExpr* intExpr = args->arg(0)->asInt();
1321        vmint i = intExpr->evalInt();
1322        return successResult({
1323            .value = vmfloat(i),
1324            .unitFactor = intExpr->unitFactor()
1325        });
1326    }
1327    
1328  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.3345  
changed lines
  Added in v.3582

  ViewVC Help
Powered by ViewVC