/[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 3557 - (show annotations) (download)
Sun Aug 18 00:06:04 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 16040 byte(s)
* NKSP: Introducing 64 bit support for NKSP integer scripts
  variables (declare $foo).
* Require C++11 compiler support.
* Autoconf: Added m4/ax_cxx_compile_stdcxx.m4 macro which is used
  for checking in configure for C++11 support (as mandatory
  requirement) and automatically adds compiler argument if required
  (e.g. -std=C++11).
* Bumped version (2.1.1.svn3).

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

  ViewVC Help
Powered by ViewVC