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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3575 - (show annotations) (download)
Wed Aug 28 11:12:04 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 17884 byte(s)
NKSP: Added some initial floating point test cases.

* RTMath: Implemented floating point comparison methods
  fEqual32(float,float) and fEqual64(double,double)
  which take the expected floating point tolerances
  into account.

* NKSP: Allow built-in exit() function to potentially
  accept real type argument as well.

* NKSP: Added real number test cases for built-in
  functions exit(), int_to_real(), real(), real_to_int()
  and int(), as well as for the plus, minus and negate
  language operators.

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

  ViewVC Help
Powered by ViewVC