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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3584 - (hide annotations) (download)
Fri Aug 30 13:33:32 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 48007 byte(s)
* NKSP VM API: Added 4 overridden methods to class VMNumberExpr:
  evalCastInt(MetricPrefix_t), evalCastInt(MetricPrefix_t,MetricPrefix_t),
  evalCastReal(MetricPrefix_t), evalCastReal(MetricPrefix_t,MetricPrefix_t)
  as convenient methods for automatically converting values to expected
  metric value basis.

* NKSP built-in function "wait()" accepts now both integers and real numbers
  as argument.

* Bumped version (2.1.1.svn9).

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

  ViewVC Help
Powered by ViewVC