/[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 3345 - (show annotations) (download)
Thu Aug 10 13:18:06 2017 UTC (6 years, 8 months ago) by schoenebeck
File size: 14958 byte(s)
* Fixed compilation error with clang libc++.

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

  ViewVC Help
Powered by ViewVC