/[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 3585 - (hide annotations) (download)
Fri Aug 30 17:51:24 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 47779 byte(s)
NKSP: Cleanup regarding multiple data types for built-in function args.

* NKSP VM API cleanup: Get rid of legacy method
  VMFunction::argType(vmint iArg) which was already superseded by its new
  replacement VMFunction::acceptsArgType(vmint iArg, ExprType_t type).

* NKSP parser: if wrong argument type was passed to a built-in function and
  that built-in function accepts more than one data type for the argument,
  then show all supported data types as parser error message.

* Bumped version (2.1.1.svn10).

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 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
916 schoenebeck 3221 if (iArg == 0)
917 schoenebeck 3581 return isArray(type);
918 schoenebeck 3221 else
919 schoenebeck 3581 return type == INT_EXPR || type == REAL_EXPR;
920 schoenebeck 3221 }
921    
922 schoenebeck 3581 void CoreVMFunction_search::checkArgs(VMFnArgs* args,
923     std::function<void(String)> err,
924     std::function<void(String)> wrn)
925     {
926     // super class checks
927     Super::checkArgs(args, err, wrn);
928    
929     // own checks ...
930     if (args->arg(0)->exprType() == INT_ARR_EXPR &&
931     args->arg(1)->exprType() != INT_EXPR)
932     {
933     String a = typeStr(INT_ARR_EXPR);
934     String bIs = typeStr(args->arg(1)->exprType());
935     String bShould = typeStr(INT_EXPR);
936     err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
937     return;
938     }
939     if (args->arg(0)->exprType() == REAL_ARR_EXPR &&
940     args->arg(1)->exprType() != REAL_EXPR)
941     {
942     String a = typeStr(REAL_ARR_EXPR);
943     String bIs = typeStr(args->arg(1)->exprType());
944     String bShould = typeStr(REAL_EXPR);
945     err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
946     return;
947     }
948     }
949    
950 schoenebeck 3221 VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
951 schoenebeck 3581 VMArrayExpr* a = args->arg(0)->asArray();
952 schoenebeck 3557 const vmint n = a->arraySize();
953 schoenebeck 3581 if (a->exprType() == INT_ARR_EXPR) {
954     const vmint needle = args->arg(1)->asInt()->evalInt();
955     VMIntArrayExpr* intArray = a->asIntArray();
956     for (vmint i = 0; i < n; ++i)
957     if (intArray->evalIntElement(i) == needle)
958     return successResult(i);
959     } else { // real array ...
960     const vmfloat needle = args->arg(1)->asReal()->evalReal();
961     VMRealArrayExpr* realArray = a->asRealArray();
962     for (vmint i = 0; i < n; ++i) {
963     const vmfloat value = realArray->evalRealElement(i);
964     if (_fEqualX(value, needle))
965     return successResult(i);
966     }
967     }
968 schoenebeck 3221 return successResult(-1); // not found
969     }
970    
971     ///////////////////////////////////////////////////////////////////////////
972     // built-in script function: sort()
973    
974 schoenebeck 3557 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
975 schoenebeck 3221 if (iArg == 0)
976 schoenebeck 3581 return isArray(type);
977 schoenebeck 3221 else
978     return type == INT_EXPR;
979     }
980    
981 schoenebeck 3581 // The following structs and template classes act as adapters for allowing to
982     // use std sort algorithms on our arrays. It might look a bit more complicated
983     // than it ought to be, but there is one reason for the large amount of
984     // 'adapter' code below: the STL std algorithms rely on 'lvalues' to do their
985     // e.g. sorting) jobs, that is they expect containers to have 'localizeable'
986     // data which essentially means their data should reside somewhere in memory and
987     // directly be accessible (readable and writable) there, which is not the case
988     // with our VM interfaces which actually always require virtual getter and
989     // setter methods to be called instead. So we must emulate lvalues by custom
990     // classes/structs which forward between our getters/setters and the lvalue
991     // access operators used by the STL std algorithms.
992    
993     struct IntArrayAccessor {
994     static inline vmint getPrimaryValue(VMIntArrayExpr* arr, vmint index) {
995     return arr->evalIntElement(index);
996     }
997     static inline void setPrimaryValue(VMIntArrayExpr* arr, vmint index, vmint value) {
998     arr->assignIntElement(index, value);
999     }
1000     };
1001    
1002     struct RealArrayAccessor {
1003     static inline vmfloat getPrimaryValue(VMRealArrayExpr* arr, vmint index) {
1004     return arr->evalRealElement(index);
1005     }
1006     static inline void setPrimaryValue(VMRealArrayExpr* arr, vmint index, vmfloat value) {
1007     arr->assignRealElement(index, value);
1008     }
1009     };
1010    
1011     template<class T_array> // i.e. T_array is either VMIntArrayExpr or VMRealArrayExpr
1012 schoenebeck 3221 struct ArrElemPOD {
1013 schoenebeck 3581 T_array* m_array;
1014 schoenebeck 3557 vmint m_index;
1015 schoenebeck 3221 };
1016    
1017 schoenebeck 3581 // This class is used for temporary values by std::sort().
1018     template<class T_value> // i.e. T_value is either vmint or vmfloat
1019     struct ScalarNmbrVal {
1020     T_value primValue;
1021     vmfloat unitFactor;
1022 schoenebeck 3221
1023 schoenebeck 3581 inline bool operator<(const ScalarNmbrVal& other) const {
1024     return getProdValue() < other.getProdValue();
1025     }
1026     inline bool operator>(const ScalarNmbrVal& other) const {
1027     return getProdValue() > other.getProdValue();
1028     }
1029     inline vmfloat getProdValue() const {
1030     // simple solution for both vmint and vmfloat, should be fine for just sorting
1031     return primValue * unitFactor;
1032     }
1033     };
1034    
1035     // This class emulates lvalue access (access by reference) which is used by ArrExprIter::operator*() below.
1036     template<class T_array, // T_array is either VMIntArrayExpr or VMRealArrayExpr
1037     class T_value, // T_value is either vmint or vmfloat
1038     class T_accessor> // T_accessor is either IntArrayAccessor or RealArrayAccessor
1039     class ArrElemRef : protected ArrElemPOD<T_array> {
1040 schoenebeck 3221 public:
1041 schoenebeck 3581 typedef ScalarNmbrVal<T_value> ScalarNmbrVal;
1042    
1043     inline ArrElemRef(T_array* a, vmint index) {
1044     this->m_array = a;
1045     this->m_index = index;
1046 schoenebeck 3221 }
1047 schoenebeck 3581 inline ArrElemRef(const ArrElemRef& ref) {
1048     this->m_array = ref.m_array;
1049     this->m_index = ref.m_index;
1050 schoenebeck 3221 }
1051     inline ArrElemRef& operator=(const ArrElemRef& e) {
1052 schoenebeck 3581 setPrimValue(e.getPrimValue());
1053     setUnitFactor(e.getUnitFactor());
1054 schoenebeck 3221 return *this;
1055     }
1056 schoenebeck 3581 inline ArrElemRef& operator=(ScalarNmbrVal value) {
1057     setPrimValue(value.primValue);
1058     setUnitFactor(value.unitFactor);
1059 schoenebeck 3221 return *this;
1060     }
1061     inline bool operator==(const ArrElemRef& e) const {
1062 schoenebeck 3581 return getProdValue() == e.getProdValue();
1063 schoenebeck 3221 }
1064     inline bool operator!=(const ArrElemRef& e) const {
1065     return !(operator==(e));
1066     }
1067     inline bool operator<(const ArrElemRef& e) const {
1068 schoenebeck 3581 return getProdValue() < e.getProdValue();
1069 schoenebeck 3221 }
1070     inline bool operator>(const ArrElemRef& e) const {
1071 schoenebeck 3581 return getProdValue() > e.getProdValue();
1072 schoenebeck 3221 }
1073     inline bool operator<=(const ArrElemRef& e) const {
1074 schoenebeck 3581 return getProdValue() <= e.getProdValue();
1075 schoenebeck 3221 }
1076     inline bool operator>=(const ArrElemRef& e) const {
1077 schoenebeck 3581 return getProdValue() >= e.getProdValue();
1078 schoenebeck 3221 }
1079 schoenebeck 3581 inline bool operator==(const ScalarNmbrVal& s) const {
1080     return getProdValue() == s.getProdValue();
1081 schoenebeck 3221 }
1082 schoenebeck 3581 inline bool operator!=(const ScalarNmbrVal& s) const {
1083     return !(operator==(s));
1084 schoenebeck 3221 }
1085 schoenebeck 3581 inline bool operator<(const ScalarNmbrVal& s) const {
1086     return getProdValue() < s.getProdValue();
1087     }
1088     inline bool operator>(const ScalarNmbrVal& s) const {
1089     return getProdValue() > s.getProdValue();
1090     }
1091     inline bool operator<=(const ScalarNmbrVal& s) const {
1092     return getProdValue() <= s.getProdValue();
1093     }
1094     inline bool operator>=(const ScalarNmbrVal& s) const {
1095     return getProdValue() >= s.getProdValue();
1096     }
1097     inline operator ScalarNmbrVal() {
1098     return {
1099     .primValue = getPrimValue() ,
1100     .unitFactor = getUnitFactor()
1101     };
1102     }
1103 schoenebeck 3221 protected:
1104 schoenebeck 3581 inline T_value getPrimValue() const {
1105     return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1106 schoenebeck 3221 }
1107 schoenebeck 3581 inline void setPrimValue(T_value value) {
1108     T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1109 schoenebeck 3221 }
1110 schoenebeck 3581 inline vmfloat getUnitFactor() const {
1111     return this->m_array->unitFactorOfElement(this->m_index);
1112 schoenebeck 3221 }
1113 schoenebeck 3581 inline void setUnitFactor(vmfloat factor) {
1114     this->m_array->assignElementUnitFactor(this->m_index, factor);
1115 schoenebeck 3221 }
1116 schoenebeck 3581 inline vmfloat getProdValue() const {
1117     // simple solution for both vmint and vmfloat, should be fine for just sorting
1118     vmfloat primary = (vmfloat) getPrimValue();
1119     vmfloat factor = getUnitFactor();
1120     return primary * factor;
1121 schoenebeck 3221 }
1122 schoenebeck 3581
1123     // allow swap() functions below to access protected methods here
1124     friend void swap(class ArrElemRef<T_array,T_value,T_accessor> a,
1125     class ArrElemRef<T_array,T_value,T_accessor> b);
1126 schoenebeck 3221 };
1127    
1128 schoenebeck 3581 // custom iterator class to be used by std:sort() on our VM arrays
1129     template<class T_array, class T_value, class T_accessor>
1130     class ArrExprIter : public ArrElemPOD<T_array> {
1131 schoenebeck 3221 public:
1132     typedef std::random_access_iterator_tag iterator_category;
1133     typedef ssize_t difference_type;
1134 schoenebeck 3581 typedef ArrElemRef<T_array, T_value, T_accessor> ArrElemRef;
1135     typedef ArrElemRef reference; // type used by STL for access by reference
1136     typedef void pointer; // type used by STL for -> operator result, we don't use that operator at all so just void it
1137     typedef ScalarNmbrVal<T_value> value_type; // type used by STL for temporary values
1138 schoenebeck 3221
1139 schoenebeck 3581 ArrExprIter(T_array* a, vmint index) {
1140     this->m_array = a;
1141     this->m_index = index;
1142 schoenebeck 3221 }
1143 schoenebeck 3581 ArrExprIter(const ArrElemRef& ref) {
1144     this->m_array = ref.m_array;
1145     this->m_index = ref.m_index;
1146     }
1147 schoenebeck 3221 inline ArrElemRef operator*() {
1148 schoenebeck 3581 return ArrElemRef(this->m_array, this->m_index);
1149 schoenebeck 3221 }
1150     inline ArrExprIter& operator++() { // prefix increment
1151 schoenebeck 3581 ++(this->m_index);
1152 schoenebeck 3221 return *this;
1153     }
1154     inline ArrExprIter& operator--() { // prefix decrement
1155 schoenebeck 3581 --(this->m_index);
1156 schoenebeck 3221 return *this;
1157     }
1158     inline ArrExprIter operator++(int) { // postfix increment
1159     ArrExprIter it = *this;
1160 schoenebeck 3581 ++(this->m_index);
1161 schoenebeck 3221 return it;
1162     }
1163     inline ArrExprIter operator--(int) { // postfix decrement
1164     ArrExprIter it = *this;
1165 schoenebeck 3581 --(this->m_index);
1166 schoenebeck 3221 return it;
1167     }
1168 schoenebeck 3345 inline ArrExprIter& operator+=(difference_type d) {
1169 schoenebeck 3581 this->m_index += d;
1170 schoenebeck 3345 return *this;
1171     }
1172     inline ArrExprIter& operator-=(difference_type d) {
1173 schoenebeck 3581 this->m_index -= d;
1174 schoenebeck 3345 return *this;
1175     }
1176 schoenebeck 3221 inline bool operator==(const ArrExprIter& other) const {
1177 schoenebeck 3581 return this->m_index == other.m_index;
1178 schoenebeck 3221 }
1179     inline bool operator!=(const ArrExprIter& other) const {
1180 schoenebeck 3581 return this->m_index != other.m_index;
1181 schoenebeck 3221 }
1182     inline bool operator<(const ArrExprIter& other) const {
1183 schoenebeck 3581 return this->m_index < other.m_index;
1184 schoenebeck 3221 }
1185     inline bool operator>(const ArrExprIter& other) const {
1186 schoenebeck 3581 return this->m_index > other.m_index;
1187 schoenebeck 3221 }
1188     inline bool operator<=(const ArrExprIter& other) const {
1189 schoenebeck 3581 return this->m_index <= other.m_index;
1190 schoenebeck 3221 }
1191     inline bool operator>=(const ArrExprIter& other) const {
1192 schoenebeck 3581 return this->m_index >= other.m_index;
1193 schoenebeck 3221 }
1194     inline difference_type operator+(const ArrExprIter& other) const {
1195 schoenebeck 3581 return this->m_index + other.m_index;
1196 schoenebeck 3221 }
1197     inline difference_type operator-(const ArrExprIter& other) const {
1198 schoenebeck 3581 return this->m_index - other.m_index;
1199 schoenebeck 3221 }
1200     inline ArrExprIter operator-(difference_type d) const {
1201 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index - d);
1202 schoenebeck 3221 }
1203     inline ArrExprIter operator+(difference_type d) const {
1204 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index + d);
1205 schoenebeck 3221 }
1206     inline ArrExprIter operator*(difference_type factor) const {
1207 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index * factor);
1208 schoenebeck 3221 }
1209     };
1210    
1211 schoenebeck 3581 typedef ArrExprIter<VMIntArrayExpr,vmint,IntArrayAccessor> IntArrExprIter;
1212     typedef ArrExprIter<VMRealArrayExpr,vmfloat,RealArrayAccessor> RealArrExprIter;
1213    
1214     // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1215     static inline void swap(IntArrExprIter::ArrElemRef a,
1216     IntArrExprIter::ArrElemRef b)
1217     {
1218     vmint valueA = a.getPrimValue();
1219     vmint valueB = b.getPrimValue();
1220     vmfloat factorA = a.getUnitFactor();
1221     vmfloat factorB = b.getUnitFactor();
1222     a.setPrimValue(valueB);
1223     a.setUnitFactor(factorB);
1224     b.setPrimValue(valueA);
1225     b.setUnitFactor(factorA);
1226     }
1227    
1228     // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1229     static inline void swap(RealArrExprIter::ArrElemRef a,
1230     RealArrExprIter::ArrElemRef b)
1231     {
1232     vmfloat valueA = a.getPrimValue();
1233     vmfloat valueB = b.getPrimValue();
1234     vmfloat factorA = a.getUnitFactor();
1235     vmfloat factorB = b.getUnitFactor();
1236     a.setPrimValue(valueB);
1237     a.setUnitFactor(factorB);
1238     b.setPrimValue(valueA);
1239     b.setUnitFactor(factorA);
1240     }
1241    
1242     // used to sort in descending order (unlike the default behaviour of std::sort() which is ascending order)
1243     template<class T> // T is either IntArrExprIter or RealArrExprIter
1244 schoenebeck 3221 struct DescArrExprSorter {
1245 schoenebeck 3581 inline bool operator()(const typename T::value_type a, const typename T::value_type b) const {
1246 schoenebeck 3221 return a > b;
1247     }
1248     };
1249    
1250     VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1251 schoenebeck 3581 const bool bAscending =
1252 schoenebeck 3221 (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1253 schoenebeck 3581
1254     if (args->arg(0)->exprType() == INT_ARR_EXPR) {
1255     VMIntArrayExpr* a = args->arg(0)->asIntArray();
1256     vmint n = a->arraySize();
1257     IntArrExprIter itBegin(a, 0);
1258     IntArrExprIter itEnd(a, n);
1259     if (bAscending) {
1260     std::sort(itBegin, itEnd);
1261     } else {
1262     DescArrExprSorter<IntArrExprIter> sorter;
1263     std::sort(itBegin, itEnd, sorter);
1264     }
1265 schoenebeck 3221 } else {
1266 schoenebeck 3581 VMRealArrayExpr* a = args->arg(0)->asRealArray();
1267     vmint n = a->arraySize();
1268     RealArrExprIter itBegin(a, 0);
1269     RealArrExprIter itEnd(a, n);
1270     if (bAscending) {
1271     std::sort(itBegin, itEnd);
1272     } else {
1273     DescArrExprSorter<RealArrExprIter> sorter;
1274     std::sort(itBegin, itEnd, sorter);
1275     }
1276 schoenebeck 3221 }
1277 schoenebeck 3581
1278 schoenebeck 3221 return successResult();
1279     }
1280    
1281 schoenebeck 3573 ///////////////////////////////////////////////////////////////////////////
1282     // built-in script function: real_to_int() and int()
1283    
1284 schoenebeck 3581 StdUnit_t CoreVMFunction_real_to_int::returnUnitType(VMFnArgs* args) {
1285 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
1286 schoenebeck 3581 }
1287    
1288     bool CoreVMFunction_real_to_int::returnsFinal(VMFnArgs* args) {
1289 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
1290 schoenebeck 3581 }
1291    
1292 schoenebeck 3573 VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1293 schoenebeck 3581 VMRealExpr* realExpr = args->arg(0)->asReal();
1294     vmfloat f = realExpr->evalReal();
1295     return successResult({
1296     .value = vmint(f),
1297     .unitFactor = realExpr->unitFactor()
1298     });
1299 schoenebeck 3573 }
1300    
1301     ///////////////////////////////////////////////////////////////////////////
1302     // built-in script function: int_to_real() and real()
1303    
1304 schoenebeck 3581 StdUnit_t CoreVMFunction_int_to_real::returnUnitType(VMFnArgs* args) {
1305 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
1306 schoenebeck 3581 }
1307    
1308     bool CoreVMFunction_int_to_real::returnsFinal(VMFnArgs* args) {
1309 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
1310 schoenebeck 3581 }
1311    
1312 schoenebeck 3573 VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1313 schoenebeck 3581 VMIntExpr* intExpr = args->arg(0)->asInt();
1314     vmint i = intExpr->evalInt();
1315     return successResult({
1316     .value = vmfloat(i),
1317     .unitFactor = intExpr->unitFactor()
1318     });
1319 schoenebeck 3573 }
1320    
1321 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC