/[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 3573 - (show annotations) (download)
Tue Aug 27 21:36:53 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 17663 byte(s)
NKSP: Introducing floating point support.

* NKSP language: Added support for NKSP real number literals and
  arithmetic operations on them (e.g. "(3.9 + 2.9) / 12.3 - 42.0").

* NKSP language: Added support for NKSP real number (floating point)
  script variables (declare ~foo := 3.4).

* NKSP language: Added support for NKSP real number (floating point)
  array script variables (declare ?foo[3] := ( 1.1, 2.7, 49.0 )).

* NKSP built-in script function "message()" accepts now real number
  argument as well.

* Added built-in NKSP script function "real_to_int()" and its short
  hand form "int()" for casting from real number to integer in NKSP
  scripts.

* Added built-in NKSP script function "int_to_real()" and its short
  hand form "real()" for casting from integer to real number in NKSP
  scripts.

* Bumped version (2.1.1.svn6).

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

  ViewVC Help
Powered by ViewVC