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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3581 - (show annotations) (download)
Fri Aug 30 11:40:25 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 55453 byte(s)
NKSP: Allow more wider support of standard measuring units & 'final'ness.

* Raised compiler requirement to be C++14 compliant (due to severe
  restrictions regarding C-style aggregate initializer lists in C++11
  which are now massively used throughout the code base).

* NKSP VM API: Allow units and 'final'ness to be returned as result from
  built-in functions (added methods VMFunction::returnUnitType() and
  VMFunction::returnsFinal() for that purpose which must be implemented by
  built-in function implementations).

* NKSP language: Allow metric unit prefixes of numeric scalar and array
  variables to be changed freely at runtime (unlike unit types like Hz etc.
  which are still sticky parse-time features of variables which cannot be
  changed at runtime for the intentional sake of determinism).

* NKSP language: 'final' values are prohibited for array variables for now
  (attempt causes a parsers error).

* NKSP language: expressions with unit types (e.g. Hz) are prohibited for
  conditions of runtime control structures like if(), while(), select()
  (attempt causes a parser error).

* NKSP VM API: Allow built-in functions to perform their own, individual
  parse time checks of arguments going to be passed to the function at
  runtime (added method VMFunction::checkArgs() for that purpose).

* NKSP language: raise parser warning if only one operand of binary
  operators (like logical 'or' comparison) contain a 'final' value (because
  it would always yield in a 'final' result in such cases).

* NKSP language: Allow comparison (=, #, <, >, <=, >=) of values with
  different metric unit prefixes, which will behave as expected (e.g.
  result of expression '1000us < 2ms' is true).

* NKSP language: Allow adding values with different metric unit prefixes
  (e.g. result of expression '100Hz + 5kHz' is '5100Hz').

* NKSP language: Allow subtracting values with different metric unit
  prefixes (e.g. result of expression '1ms - 20us' is '980us').

* NKSP language: Allow multiplying with any metric unit prefixes
  (e.g. result of expression '2k * 3ms' is '6s'), however multiplications
  with unit types on both sides (e.g. '2s * 2s') is still prohibited since
  we don't have any considerable practical use for a term like '4s^2'
  (hence any attempt multiplying two unit types still causes parser error).

* NKSP language: Allow dividing by any metric unit prefixes and allow
  division of same unit type on both sides (e.g. expression '8kHz / 1000Hz'
  yields in unit free result '8'). So this is now a way to cast units away
  e.g. for passing the result to other expressions, certain function calls
  or variables which are not accepting any units (or that specific unit).

* NKSP language: integer arrays and real number arrays can now be converted
  to strings (e.g. for dumping their content with message() calls for
  script debugging purposes).

* NKSP language: expressions and variables with units are now correctly
  casted to strings (e.g. with message() calls).

* NKSP language: comparing real numbers for equalness (e.g. '~foo = 3.1') or
  unequalness (e.g. '~foo # 3.1') is now less strict and takes the expected
  floating point tolerances into account.

* NKSP VM API: Added methods VMScalarNumberExpr::evalCastInt() and
  VMScalarNumberExpr::evalCastReal().

* NKSP VM API: Added base class 'VMNumberArrayExpr' for classes
  'VMIntArrayExpr' and 'VMRealArrayExpr'.

* NKSP VM API: replaced all unitPrefix() (parse time) methods by
  unitFactor() (runtime) methods.

* Built-in function "exit()" supports now returning units and 'final'ness
  exclusively for test cases.

* The following built-in functions support now units as well: "abs()",
  "random()", "inc()", "dec()", "in_range()", "min()", "max()",
  "real_to_int()", "int()", "int_to_real()" and "real()".

* Built-in functions "array_equal()", "search()" and "sort()" support now
  real number arrays (correctly) as well.

* Added individual parse time checks of arguments to be passed to built-in
  functions "random()", "inc()", "dec()", "in_range()", "min()", "max()",
  "array_equal()" and "search()" specific for their individual purposes.

* Test cases: Added massive amount of NKSP test cases for standard
  measuring units and 'final' operator usage cases.

* Test cases: Added NKSP test cases for (floating point tolerance aware)
  real number equalness / unequalness comparison.

* Bumped version (2.1.1.svn8).

1 /*
2 * Copyright (c) 2014 - 2019 Christian Schoenebeck and Andreas Persson
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 <cstdio>
11 #include <string.h>
12 #include "tree.h"
13 #include "../common/global_private.h"
14 #include "../common/RTMath.h"
15 #include <assert.h>
16
17 namespace LinuxSampler {
18
19 bool isNoOperation(StatementRef statement) {
20 return statement->statementType() == STMT_NOOP;
21 }
22
23 Node::Node() {
24 }
25
26 Node::~Node() {
27 }
28
29 void Node::printIndents(int n) {
30 for (int i = 0; i < n; ++i) printf(" ");
31 fflush(stdout);
32 }
33
34 vmint Unit::convIntToUnitFactor(vmint iValue, VMUnit* srcUnit, VMUnit* dstUnit) {
35 vmfloat f = (vmfloat) iValue;
36 vmfloat factor = srcUnit->unitFactor() / dstUnit->unitFactor();
37 if (sizeof(vmfloat) == sizeof(float))
38 return llroundf(f * factor);
39 else
40 return llround(f * factor);
41 }
42
43 vmint Unit::convIntToUnitFactor(vmint iValue, vmfloat srcFactor, vmfloat dstFactor) {
44 vmfloat f = (vmfloat) iValue;
45 vmfloat factor = srcFactor / dstFactor;
46 if (sizeof(vmfloat) == sizeof(float))
47 return llroundf(f * factor);
48 else
49 return llround(f * factor);
50 }
51
52 vmfloat Unit::convRealToUnitFactor(vmfloat fValue, VMUnit* srcUnit, VMUnit* dstUnit) {
53 vmfloat factor = srcUnit->unitFactor() / dstUnit->unitFactor();
54 return fValue * factor;
55 }
56
57 vmfloat Unit::convRealToUnitFactor(vmfloat fValue, vmfloat srcFactor, vmfloat dstFactor) {
58 vmfloat factor = srcFactor / dstFactor;
59 return fValue * factor;
60 }
61
62 vmint IntExpr::evalIntToUnitFactor(vmfloat unitFactor) {
63 vmfloat f = (vmfloat) evalInt();
64 vmfloat factor = this->unitFactor() / unitFactor;
65 if (sizeof(vmfloat) == sizeof(float))
66 return llroundf(f * factor);
67 else
68 return llround(f * factor);
69 }
70
71 static String _unitFactorToShortStr(vmfloat unitFactor) {
72 const long int tens = lround( log10(unitFactor) );
73 switch (tens) {
74 case 3: return "k"; // kilo = 10^3
75 case 2: return "h"; // hecto = 10^2
76 case 1: return "da"; // deca = 10
77 case 0: return "" ; // -- = 1
78 case -1: return "d"; // deci = 10^-1
79 case -2: return "c"; // centi = 10^-2 (this is also used for tuning "cents")
80 case -3: return "m"; // milli = 10^-3
81 case -4: return "md"; // milli deci = 10^-4
82 case -5: return "mc"; // milli centi = 10^-5 (this is also used for tuning "cents")
83 case -6: return "u"; // micro = 10^-6
84 default: return "*10^" + ToString(tens);
85 }
86 }
87
88 static String _unitToStr(Unit* unit) {
89 const StdUnit_t type = unit->unitType();
90 String sType;
91 switch (type) {
92 case VM_NO_UNIT: break;
93 case VM_SECOND: sType = "s"; break;
94 case VM_HERTZ: sType = "Hz"; break;
95 case VM_BEL: sType = "B"; break;
96 }
97
98 String prefix = _unitFactorToShortStr( unit->unitFactor() );
99
100 return prefix + sType;
101 }
102
103 String IntExpr::evalCastToStr() {
104 return ToString(evalInt()) + _unitToStr(this);
105 }
106
107 vmfloat RealExpr::evalRealToUnitFactor(vmfloat unitFactor) {
108 vmfloat f = evalReal();
109 vmfloat factor = this->unitFactor() / unitFactor;
110 return f * factor;
111 }
112
113 String RealExpr::evalCastToStr() {
114 return ToString(evalReal()) + _unitToStr(this);
115 }
116
117 String IntArrayExpr::evalCastToStr() {
118 String s = "{";
119 for (vmint i = 0; i < arraySize(); ++i) {
120 vmint val = evalIntElement(i);
121 vmfloat factor = unitFactorOfElement(i);
122 if (i) s += ",";
123 s += ToString(val) + _unitFactorToShortStr(factor);
124 }
125 s += "}";
126 return s;
127 }
128
129 String RealArrayExpr::evalCastToStr() {
130 String s = "{";
131 for (vmint i = 0; i < arraySize(); ++i) {
132 vmfloat val = evalRealElement(i);
133 vmfloat factor = unitFactorOfElement(i);
134 if (i) s += ",";
135 s += ToString(val) + _unitFactorToShortStr(factor);
136 }
137 s += "}";
138 return s;
139 }
140
141 IntLiteral::IntLiteral(const IntLitDef& def) :
142 IntExpr(), Unit(def.unitType),
143 value(def.value), unitPrefixFactor(def.unitFactor),
144 finalVal(def.isFinal)
145 {
146 }
147
148 vmint IntLiteral::evalInt() {
149 return value;
150 }
151
152 void IntLiteral::dump(int level) {
153 printIndents(level);
154 printf("IntLiteral %lld\n", value);
155 }
156
157 RealLiteral::RealLiteral(const RealLitDef& def) :
158 RealExpr(), Unit(def.unitType),
159 value(def.value), unitPrefixFactor(def.unitFactor),
160 finalVal(def.isFinal)
161 {
162 }
163
164 vmfloat RealLiteral::evalReal() {
165 return value;
166 }
167
168 void RealLiteral::dump(int level) {
169 printIndents(level);
170 printf("RealLiteral %f\n", value);
171 }
172
173 void StringLiteral::dump(int level) {
174 printIndents(level);
175 printf("StringLiteral: '%s'\n", value.c_str());
176 }
177
178 Add::Add(ScalarNumberExprRef lhs, ScalarNumberExprRef rhs) :
179 VaritypeScalarBinaryOp(lhs, rhs),
180 Unit(
181 // lhs and rhs are forced to be same unit type at parse time, so either one is fine here
182 (lhs) ? lhs->unitType() : VM_NO_UNIT
183 )
184 {
185 }
186
187 vmint Add::evalInt() {
188 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
189 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
190 if (!pLHS || !pRHS) return 0;
191 // eval*() call is required before calling unitFactor(), since the latter does not evaluate expressions!
192 vmint lvalue = pLHS->evalInt();
193 vmint rvalue = pRHS->evalInt();
194 if (pLHS->unitFactor() == pRHS->unitFactor())
195 return lvalue + rvalue;
196 if (pLHS->unitFactor() < pRHS->unitFactor())
197 return lvalue + Unit::convIntToUnitFactor(rvalue, pRHS, pLHS);
198 else
199 return Unit::convIntToUnitFactor(lvalue, pLHS, pRHS) + rvalue;
200 }
201
202 vmfloat Add::evalReal() {
203 RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
204 RealExpr* pRHS = dynamic_cast<RealExpr*>(&*rhs);
205 if (!pLHS || !pRHS) return 0;
206 // eval*() call is required before calling unitFactor(), since the latter does not evaluate expressions!
207 vmfloat lvalue = pLHS->evalReal();
208 vmfloat rvalue = pRHS->evalReal();
209 if (pLHS->unitFactor() == pRHS->unitFactor())
210 return lvalue + rvalue;
211 if (pLHS->unitFactor() < pRHS->unitFactor())
212 return lvalue + Unit::convRealToUnitFactor(rvalue, pRHS, pLHS);
213 else
214 return Unit::convRealToUnitFactor(lvalue, pLHS, pRHS) + rvalue;
215 }
216
217 vmfloat Add::unitFactor() const {
218 const ScalarNumberExpr* pLHS = dynamic_cast<const ScalarNumberExpr*>(&*lhs);
219 const ScalarNumberExpr* pRHS = dynamic_cast<const ScalarNumberExpr*>(&*rhs);
220 return (pLHS->unitFactor() < pRHS->unitFactor()) ? pLHS->unitFactor() : pRHS->unitFactor();
221 }
222
223 void Add::dump(int level) {
224 printIndents(level);
225 printf("Add(\n");
226 lhs->dump(level+1);
227 printIndents(level);
228 printf(",\n");
229 rhs->dump(level+1);
230 printIndents(level);
231 printf(")\n");
232 }
233
234 Sub::Sub(ScalarNumberExprRef lhs, ScalarNumberExprRef rhs) :
235 VaritypeScalarBinaryOp(lhs, rhs),
236 Unit(
237 // lhs and rhs are forced to be same unit type at parse time, so either one is fine here
238 (lhs) ? lhs->unitType() : VM_NO_UNIT
239 )
240 {
241 }
242
243 vmint Sub::evalInt() {
244 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
245 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
246 if (!pLHS || !pRHS) return 0;
247 // eval*() call is required before calling unitFactor(), since the latter does not evaluate expressions!
248 vmint lvalue = pLHS->evalInt();
249 vmint rvalue = pRHS->evalInt();
250 if (pLHS->unitFactor() == pRHS->unitFactor())
251 return lvalue - rvalue;
252 if (pLHS->unitFactor() < pRHS->unitFactor())
253 return lvalue - Unit::convIntToUnitFactor(rvalue, pRHS, pLHS);
254 else
255 return Unit::convIntToUnitFactor(lvalue, pLHS, pRHS) - rvalue;
256 }
257
258 vmfloat Sub::evalReal() {
259 RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
260 RealExpr* pRHS = dynamic_cast<RealExpr*>(&*rhs);
261 if (!pLHS || !pRHS) return 0;
262 // eval*() call is required before calling unitFactor(), since the latter does not evaluate expressions!
263 vmfloat lvalue = pLHS->evalReal();
264 vmfloat rvalue = pRHS->evalReal();
265 if (pLHS->unitFactor() == pRHS->unitFactor())
266 return lvalue - rvalue;
267 if (pLHS->unitFactor() < pRHS->unitFactor())
268 return lvalue - Unit::convRealToUnitFactor(rvalue, pRHS, pLHS);
269 else
270 return Unit::convRealToUnitFactor(lvalue, pLHS, pRHS) - rvalue;
271 }
272
273 vmfloat Sub::unitFactor() const {
274 const ScalarNumberExpr* pLHS = dynamic_cast<const ScalarNumberExpr*>(&*lhs);
275 const ScalarNumberExpr* pRHS = dynamic_cast<const ScalarNumberExpr*>(&*rhs);
276 return (pLHS->unitFactor() < pRHS->unitFactor()) ? pLHS->unitFactor() : pRHS->unitFactor();
277 }
278
279 void Sub::dump(int level) {
280 printIndents(level);
281 printf("Sub(\n");
282 lhs->dump(level+1);
283 printIndents(level);
284 printf(",\n");
285 rhs->dump(level+1);
286 printIndents(level);
287 printf(")\n");
288 }
289
290 Mul::Mul(ScalarNumberExprRef lhs, ScalarNumberExprRef rhs) :
291 VaritypeScalarBinaryOp(lhs, rhs),
292 Unit(
293 // currently the NKSP parser only allows a unit type on either side on multiplications
294 (lhs->unitType()) ? lhs->unitType() : rhs->unitType()
295 )
296 {
297 }
298
299 vmint Mul::evalInt() {
300 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
301 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);;
302 return (pLHS && pRHS) ? pLHS->evalInt() * pRHS->evalInt() : 0;
303 }
304
305 vmfloat Mul::evalReal() {
306 RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
307 RealExpr* pRHS = dynamic_cast<RealExpr*>(&*rhs);;
308 return (pLHS && pRHS) ? pLHS->evalReal() * pRHS->evalReal() : 0;
309 }
310
311 void Mul::dump(int level) {
312 printIndents(level);
313 printf("Mul(\n");
314 lhs->dump(level+1);
315 printIndents(level);
316 printf(",\n");
317 rhs->dump(level+1);
318 printIndents(level);
319 printf(")\n");
320 }
321
322 vmfloat Mul::unitFactor() const {
323 const ScalarNumberExpr* pLHS = dynamic_cast<const ScalarNumberExpr*>(&*lhs);
324 const ScalarNumberExpr* pRHS = dynamic_cast<const ScalarNumberExpr*>(&*rhs);
325 return pLHS->unitFactor() * pRHS->unitFactor();
326 }
327
328 Div::Div(ScalarNumberExprRef lhs, ScalarNumberExprRef rhs) :
329 VaritypeScalarBinaryOp(lhs, rhs),
330 Unit(
331 // the NKSP parser only allows either A) a unit type on left side and none
332 // on right side or B) an identical unit type on both sides
333 (lhs->unitType() && rhs->unitType()) ? VM_NO_UNIT : lhs->unitType()
334 )
335 {
336 }
337
338 vmint Div::evalInt() {
339 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
340 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
341 if (!pLHS || !pRHS) return 0;
342 vmint l = pLHS->evalInt();
343 vmint r = pRHS->evalInt();
344 if (r == 0) return 0;
345 return l / r;
346 }
347
348 vmfloat Div::evalReal() {
349 RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
350 RealExpr* pRHS = dynamic_cast<RealExpr*>(&*rhs);
351 if (!pLHS || !pRHS) return 0;
352 vmfloat l = pLHS->evalReal();
353 vmfloat r = pRHS->evalReal();
354 if (r == vmfloat(0)) return 0;
355 return l / r;
356 }
357
358 void Div::dump(int level) {
359 printIndents(level);
360 printf("Div(\n");
361 lhs->dump(level+1);
362 printIndents(level);
363 printf(",\n");
364 rhs->dump(level+1);
365 printIndents(level);
366 printf(")\n");
367 }
368
369 vmfloat Div::unitFactor() const {
370 const ScalarNumberExpr* pLHS = dynamic_cast<const ScalarNumberExpr*>(&*lhs);
371 const ScalarNumberExpr* pRHS = dynamic_cast<const ScalarNumberExpr*>(&*rhs);
372 return pLHS->unitFactor() / pRHS->unitFactor();
373 }
374
375 vmint Mod::evalInt() {
376 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
377 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
378 return (pLHS && pRHS) ? pLHS->evalInt() % pRHS->evalInt() : 0;
379 }
380
381 void Mod::dump(int level) {
382 printIndents(level);
383 printf("Mod(\n");
384 lhs->dump(level+1);
385 printIndents(level);
386 printf(",\n");
387 rhs->dump(level+1);
388 printIndents(level);
389 printf(")\n");
390 }
391
392 void Args::dump(int level) {
393 printIndents(level);
394 printf("Args(\n");
395 for (std::vector<ExpressionRef>::iterator it = args.begin() ; it != args.end() ; ++it) {
396 (*it)->dump(level+1);
397 }
398 printIndents(level);
399 printf(")\n");
400 }
401
402 bool Args::isPolyphonic() const {
403 for (vmint i = 0; i < args.size(); ++i)
404 if (args[i]->isPolyphonic())
405 return true;
406 return false;
407 }
408
409 EventHandlers::EventHandlers() {
410 //printf("EventHandlers::Constructor 0x%lx\n", (long long)this);
411 }
412
413 EventHandlers::~EventHandlers() {
414 }
415
416 void EventHandlers::add(EventHandlerRef arg) {
417 args.push_back(arg);
418 }
419
420 void EventHandlers::dump(int level) {
421 printIndents(level);
422 printf("EventHandlers {\n");
423 for (std::vector<EventHandlerRef>::iterator it = args.begin() ; it != args.end() ; ++it) {
424 (*it)->dump(level+1);
425 }
426 printIndents(level);
427 printf("}\n");
428 }
429
430 EventHandler* EventHandlers::eventHandlerByName(const String& name) const {
431 for (vmint i = 0; i < args.size(); ++i)
432 if (args.at(i)->eventHandlerName() == name)
433 return const_cast<EventHandler*>(&*args.at(i));
434 return NULL;
435 }
436
437 EventHandler* EventHandlers::eventHandler(uint index) const {
438 if (index >= args.size()) return NULL;
439 return const_cast<EventHandler*>(&*args.at(index));
440 }
441
442 bool EventHandlers::isPolyphonic() const {
443 for (vmint i = 0; i < args.size(); ++i)
444 if (args[i]->isPolyphonic())
445 return true;
446 return false;
447 }
448
449 Assignment::Assignment(VariableRef variable, ExpressionRef value)
450 : variable(variable), value(value)
451 {
452 }
453
454 void Assignment::dump(int level) {
455 printIndents(level);
456 printf("Assignment\n");
457 }
458
459 StmtFlags_t Assignment::exec() {
460 if (!variable)
461 return StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
462 variable->assign(&*value);
463 return STMT_SUCCESS;
464 }
465
466 EventHandler::EventHandler(StatementsRef statements) {
467 this->statements = statements;
468 usingPolyphonics = statements->isPolyphonic();
469 }
470
471 void EventHandler::dump(int level) {
472 printIndents(level);
473 printf("EventHandler {\n");
474 statements->dump(level+1);
475 printIndents(level);
476 printf("}\n");
477 }
478
479 void Statements::dump(int level) {
480 printIndents(level);
481 printf("Statements {\n");
482 for (std::vector<StatementRef>::iterator it = args.begin() ; it != args.end() ; ++it) {
483 (*it)->dump(level+1);
484 }
485 printIndents(level);
486 printf("}\n");
487 }
488
489 Statement* Statements::statement(uint i) {
490 if (i >= args.size()) return NULL;
491 return &*args.at(i);
492 }
493
494 bool Statements::isPolyphonic() const {
495 for (vmint i = 0; i < args.size(); ++i)
496 if (args[i]->isPolyphonic())
497 return true;
498 return false;
499 }
500
501 DynamicVariableCall::DynamicVariableCall(const String& name, ParserContext* ctx, VMDynVar* v) :
502 Variable({
503 .ctx = ctx,
504 .elements = 0
505 }),
506 Unit(VM_NO_UNIT),
507 dynVar(v), varName(name)
508 {
509 }
510
511 vmint DynamicVariableCall::evalInt() {
512 VMIntExpr* expr = dynamic_cast<VMIntExpr*>(dynVar);
513 if (!expr) return 0;
514 return expr->evalInt();
515 }
516
517 String DynamicVariableCall::evalStr() {
518 VMStringExpr* expr = dynamic_cast<VMStringExpr*>(dynVar);
519 if (!expr) return "";
520 return expr->evalStr();
521 }
522
523 String DynamicVariableCall::evalCastToStr() {
524 if (dynVar->exprType() == STRING_EXPR) {
525 return evalStr();
526 } else {
527 VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(dynVar);
528 return intExpr ? ToString(intExpr->evalInt()) : "";
529 }
530 }
531
532 void DynamicVariableCall::dump(int level) {
533 printIndents(level);
534 printf("Dynamic Variable '%s'\n", varName.c_str());
535 }
536
537 FunctionCall::FunctionCall(const char* function, ArgsRef args, VMFunction* fn) :
538 Unit(
539 (fn) ? fn->returnUnitType(dynamic_cast<VMFnArgs*>(&*args)) : VM_NO_UNIT
540 ),
541 functionName(function), args(args), fn(fn), result(NULL)
542 {
543 }
544
545 void FunctionCall::dump(int level) {
546 printIndents(level);
547 printf("FunctionCall '%s' args={\n", functionName.c_str());
548 args->dump(level+1);
549 printIndents(level);
550 printf("}\n");
551 }
552
553 ExprType_t FunctionCall::exprType() const {
554 if (!fn) return EMPTY_EXPR;
555 FunctionCall* self = const_cast<FunctionCall*>(this);
556 return fn->returnType(dynamic_cast<VMFnArgs*>(&*self->args));
557 }
558
559 vmfloat FunctionCall::unitFactor() const {
560 if (!fn || !result) return VM_NO_FACTOR;
561 VMExpr* expr = result->resultValue();
562 if (!expr) return VM_NO_FACTOR;
563 VMScalarNumberExpr* scalar = expr->asScalarNumberExpr();
564 if (!scalar) return VM_NO_FACTOR;
565 return scalar->unitFactor();
566 }
567
568 bool FunctionCall::isFinal() const {
569 if (!fn) return false;
570 FunctionCall* self = const_cast<FunctionCall*>(this);
571 return fn->returnsFinal(dynamic_cast<VMFnArgs*>(&*self->args));
572 }
573
574 VMFnResult* FunctionCall::execVMFn() {
575 if (!fn) return NULL;
576 // assuming here that all argument checks (amount and types) have been made
577 // at parse time, to avoid time intensive checks on each function call
578 return fn->exec(dynamic_cast<VMFnArgs*>(&*args));
579 }
580
581 StmtFlags_t FunctionCall::exec() {
582 result = execVMFn();
583 if (!result)
584 return StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
585 return result->resultFlags();
586 }
587
588 vmint FunctionCall::evalInt() {
589 result = execVMFn();
590 if (!result) return 0;
591 VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
592 if (!intExpr) return 0;
593 return intExpr->evalInt();
594 }
595
596 vmfloat FunctionCall::evalReal() {
597 result = execVMFn();
598 if (!result) return 0;
599 VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
600 if (!realExpr) return 0;
601 return realExpr->evalReal();
602 }
603
604 VMIntArrayExpr* FunctionCall::asIntArray() const {
605 if (!result) return 0;
606 VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());
607 return intArrExpr;
608 }
609
610 VMRealArrayExpr* FunctionCall::asRealArray() const {
611 if (!result) return 0;
612 VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue());
613 return realArrExpr;
614 }
615
616 String FunctionCall::evalStr() {
617 result = execVMFn();
618 if (!result) return "";
619 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
620 if (!strExpr) return "";
621 return strExpr->evalStr();
622 }
623
624 String FunctionCall::evalCastToStr() {
625 result = execVMFn();
626 if (!result) return "";
627 const ExprType_t resultType = result->resultValue()->exprType();
628 if (resultType == STRING_EXPR) {
629 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
630 return strExpr ? strExpr->evalStr() : "";
631 } else if (resultType == REAL_EXPR) {
632 VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
633 return realExpr ? ToString(realExpr->evalReal()) : "";
634 } else {
635 VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
636 return intExpr ? ToString(intExpr->evalInt()) : "";
637 }
638 }
639
640 Variable::Variable(const VariableDecl& decl) :
641 context(decl.ctx), memPos(decl.memPos), bConst(decl.isConst)
642 {
643 }
644
645 ScalarNumberVariable::ScalarNumberVariable(const VariableDecl& decl) :
646 Variable(decl),
647 Unit(decl.unitType),
648 unitFactorMemPos(decl.unitFactorMemPos), polyphonic(decl.isPolyphonic),
649 finalVal(decl.isFinal)
650 {
651 }
652
653 vmfloat ScalarNumberVariable::unitFactor() const {
654 if (isPolyphonic()) {
655 return context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos];
656 }
657 return (*context->globalUnitFactorMemory)[unitFactorMemPos];
658 }
659
660 inline static vmint postfixInc(vmint& object, vmint incBy) {
661 const vmint i = object;
662 object += incBy;
663 return i;
664 }
665
666 IntVariable::IntVariable(const VariableDecl& decl) :
667 ScalarNumberVariable({
668 .ctx = decl.ctx,
669 .isPolyphonic = decl.isPolyphonic,
670 .isConst = decl.isConst,
671 .isFinal = decl.isFinal,
672 .elements = decl.elements,
673 .memPos = (
674 (!decl.ctx) ? 0 :
675 (decl.isPolyphonic) ?
676 postfixInc(decl.ctx->polyphonicIntVarCount, decl.elements) :
677 postfixInc(decl.ctx->globalIntVarCount, decl.elements)
678 ),
679 .unitFactorMemPos = (
680 (!decl.ctx) ? 0 :
681 (decl.isPolyphonic) ?
682 postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
683 postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
684 ),
685 .unitType = decl.unitType
686 }),
687 Unit(decl.unitType)
688 {
689 //printf("IntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
690 assert(!decl.isPolyphonic || decl.ctx);
691 }
692
693 void IntVariable::assign(Expression* expr) {
694 IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
695 if (intExpr) {
696 //NOTE: sequence matters! evalInt() must be called before getting unitFactor() !
697 if (isPolyphonic()) {
698 context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();
699 context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = intExpr->unitFactor();
700 } else {
701 (*context->globalIntMemory)[memPos] = intExpr->evalInt();
702 (*context->globalUnitFactorMemory)[unitFactorMemPos] = intExpr->unitFactor();
703 }
704 }
705 }
706
707 vmint IntVariable::evalInt() {
708 //printf("IntVariable::eval pos=%d\n", memPos);
709 if (isPolyphonic()) {
710 //printf("evalInt() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
711 return context->execContext->polyphonicIntMemory[memPos];
712 }
713 return (*context->globalIntMemory)[memPos];
714 }
715
716 void IntVariable::dump(int level) {
717 printIndents(level);
718 printf("IntVariable\n");
719 //printf("IntVariable memPos=%d\n", memPos);
720 }
721
722 RealVariable::RealVariable(const VariableDecl& decl) :
723 ScalarNumberVariable({
724 .ctx = decl.ctx,
725 .isPolyphonic = decl.isPolyphonic,
726 .isConst = decl.isConst,
727 .isFinal = decl.isFinal,
728 .elements = decl.elements,
729 .memPos = (
730 (!decl.ctx) ? 0 :
731 (decl.isPolyphonic) ?
732 postfixInc(decl.ctx->polyphonicRealVarCount, decl.elements) :
733 postfixInc(decl.ctx->globalRealVarCount, decl.elements)
734 ),
735 .unitFactorMemPos = (
736 (!decl.ctx) ? 0 :
737 (decl.isPolyphonic) ?
738 postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
739 postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
740 ),
741 .unitType = decl.unitType
742 }),
743 Unit(decl.unitType)
744 {
745 //printf("RealVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
746 assert(!decl.isPolyphonic || decl.ctx);
747 }
748
749 void RealVariable::assign(Expression* expr) {
750 RealExpr* realExpr = dynamic_cast<RealExpr*>(expr);
751 if (realExpr) {
752 //NOTE: sequence matters! evalReal() must be called before getting unitFactor() !
753 if (isPolyphonic()) {
754 context->execContext->polyphonicRealMemory[memPos] = realExpr->evalReal();
755 context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = realExpr->unitFactor();
756 } else {
757 (*context->globalRealMemory)[memPos] = realExpr->evalReal();
758 (*context->globalUnitFactorMemory)[unitFactorMemPos] = realExpr->unitFactor();
759 }
760 }
761 }
762
763 vmfloat RealVariable::evalReal() {
764 //printf("RealVariable::eval pos=%d\n", memPos);
765 if (isPolyphonic()) {
766 //printf("evalReal() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
767 return context->execContext->polyphonicRealMemory[memPos];
768 }
769 return (*context->globalRealMemory)[memPos];
770 }
771
772 void RealVariable::dump(int level) {
773 printIndents(level);
774 printf("RealVariable\n");
775 //printf("RealVariable memPos=%d\n", memPos);
776 }
777
778 ConstIntVariable::ConstIntVariable(const IntVarDef& def) :
779 IntVariable({
780 .ctx = def.ctx,
781 .isPolyphonic = false,
782 .isConst = true,
783 .isFinal = def.isFinal,
784 .elements = 1,
785 .memPos = def.memPos,
786 .unitFactorMemPos = def.unitFactorMemPos,
787 .unitType = def.unitType
788 }),
789 Unit(def.unitType),
790 value(def.value), unitPrefixFactor(def.unitFactor)
791 {
792 }
793
794 void ConstIntVariable::assign(Expression* expr) {
795 // ignore assignment
796 /*
797 printf("ConstIntVariable::assign()\n");
798 IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
799 if (intExpr) {
800 value = intExpr->evalInt();
801 }
802 */
803 }
804
805 vmint ConstIntVariable::evalInt() {
806 return value;
807 }
808
809 void ConstIntVariable::dump(int level) {
810 printIndents(level);
811 printf("ConstIntVariable val=%lld\n", value);
812 }
813
814 ConstRealVariable::ConstRealVariable(const RealVarDef& def) :
815 RealVariable({
816 .ctx = def.ctx,
817 .isPolyphonic = false,
818 .isConst = true,
819 .isFinal = def.isFinal,
820 .elements = 1,
821 .memPos = def.memPos,
822 .unitFactorMemPos = def.unitFactorMemPos,
823 .unitType = def.unitType
824 }),
825 Unit(def.unitType),
826 value(def.value), unitPrefixFactor(def.unitFactor)
827 {
828 }
829
830 void ConstRealVariable::assign(Expression* expr) {
831 // ignore assignment
832 }
833
834 vmfloat ConstRealVariable::evalReal() {
835 return value;
836 }
837
838 void ConstRealVariable::dump(int level) {
839 printIndents(level);
840 printf("ConstRealVariable val=%f\n", value);
841 }
842
843 BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) :
844 IntVariable({
845 .ctx = NULL,
846 .isPolyphonic = false,
847 .isConst = false, // may or may not be modifyable though!
848 .isFinal = false,
849 .elements = 0,
850 .memPos = 0,
851 .unitFactorMemPos = 0,
852 .unitType = VM_NO_UNIT
853 }),
854 Unit(VM_NO_UNIT),
855 name(name), ptr(ptr)
856 {
857 }
858
859 void BuiltInIntVariable::assign(Expression* expr) {
860 IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
861 if (!valueExpr) return;
862 ptr->assign(valueExpr->evalInt());
863 }
864
865 vmint BuiltInIntVariable::evalInt() {
866 return ptr->evalInt();
867 }
868
869 void BuiltInIntVariable::dump(int level) {
870 printIndents(level);
871 printf("Built-in IntVar '%s'\n", name.c_str());
872 }
873
874 PolyphonicIntVariable::PolyphonicIntVariable(const VariableDecl& decl) :
875 IntVariable({
876 .ctx = decl.ctx,
877 .isPolyphonic = true,
878 .isConst = decl.isConst,
879 .isFinal = decl.isFinal,
880 .elements = 1,
881 .memPos = 0,
882 .unitFactorMemPos = 0,
883 .unitType = decl.unitType
884 }),
885 Unit(decl.unitType)
886 {
887 }
888
889 void PolyphonicIntVariable::dump(int level) {
890 printIndents(level);
891 printf("PolyphonicIntVariable\n");
892 }
893
894 PolyphonicRealVariable::PolyphonicRealVariable(const VariableDecl& decl) :
895 RealVariable({
896 .ctx = decl.ctx,
897 .isPolyphonic = true,
898 .isConst = decl.isConst,
899 .isFinal = decl.isFinal,
900 .elements = 1,
901 .memPos = 0,
902 .unitFactorMemPos = 0,
903 .unitType = decl.unitType
904 }),
905 Unit(decl.unitType)
906 {
907 }
908
909 void PolyphonicRealVariable::dump(int level) {
910 printIndents(level);
911 printf("PolyphonicRealVariable\n");
912 }
913
914 IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size) :
915 Variable({
916 .ctx = ctx,
917 .isPolyphonic = false,
918 .isConst = false,
919 .isFinal = false,
920 .elements = 0,
921 .memPos = 0,
922 .unitFactorMemPos = 0,
923 .unitType = VM_NO_UNIT
924 })
925 {
926 values.resize(size);
927 memset(&values[0], 0, size * sizeof(vmint));
928
929 unitFactors.resize(size);
930 for (size_t i = 0; i < size; ++i)
931 unitFactors[i] = VM_NO_FACTOR;
932 }
933
934 IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size,
935 ArgsRef values, bool _bConst) :
936 Variable({
937 .ctx = ctx,
938 .isPolyphonic = false,
939 .isConst = _bConst,
940 .isFinal = false,
941 .elements = 0,
942 .memPos = 0,
943 .unitFactorMemPos = 0,
944 .unitType = VM_NO_UNIT
945 })
946 {
947 this->values.resize(size);
948 this->unitFactors.resize(size);
949 for (vmint i = 0; i < values->argsCount(); ++i) {
950 VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));
951 if (expr) {
952 this->values[i] = expr->evalInt();
953 this->unitFactors[i] = expr->unitFactor();
954 }
955 }
956 }
957
958 IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst) :
959 Variable({
960 .ctx = ctx,
961 .isPolyphonic = false,
962 .isConst = bConst,
963 .isFinal = false,
964 .elements = 0,
965 .memPos = 0,
966 .unitFactorMemPos = 0,
967 .unitType = VM_NO_UNIT
968 })
969 {
970 }
971
972 vmint IntArrayVariable::evalIntElement(vmuint i) {
973 if (i >= values.size()) return 0;
974 return values[i];
975 }
976
977 void IntArrayVariable::assignIntElement(vmuint i, vmint value) {
978 if (i >= values.size()) return;
979 values[i] = value;
980 }
981
982 vmfloat IntArrayVariable::unitFactorOfElement(vmuint i) const {
983 if (i >= unitFactors.size()) return VM_NO_FACTOR;
984 return unitFactors[i];
985 }
986
987 void IntArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
988 if (i >= unitFactors.size()) return;
989 unitFactors[i] = factor;
990 }
991
992 void IntArrayVariable::dump(int level) {
993 printIndents(level);
994 printf("IntArray(");
995 for (vmint i = 0; i < values.size(); ++i) {
996 if (i % 12 == 0) {
997 printf("\n");
998 printIndents(level+1);
999 }
1000 printf("%lld, ", values[i]);
1001 }
1002 printIndents(level);
1003 printf(")\n");
1004 }
1005
1006 RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size) :
1007 Variable({
1008 .ctx = ctx,
1009 .isPolyphonic = false,
1010 .isConst = false,
1011 .isFinal = false,
1012 .elements = 0,
1013 .memPos = 0,
1014 .unitFactorMemPos = 0,
1015 .unitType = VM_NO_UNIT
1016 })
1017 {
1018 values.resize(size);
1019 memset(&values[0], 0, size * sizeof(vmfloat));
1020
1021 unitFactors.resize(size);
1022 for (size_t i = 0; i < size; ++i)
1023 unitFactors[i] = VM_NO_FACTOR;
1024 }
1025
1026 RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size,
1027 ArgsRef values, bool _bConst) :
1028 Variable({
1029 .ctx = ctx,
1030 .isPolyphonic = false,
1031 .isConst = _bConst,
1032 .isFinal = false,
1033 .elements = 0,
1034 .memPos = 0,
1035 .unitFactorMemPos = 0,
1036 .unitType = VM_NO_UNIT
1037 })
1038 {
1039 this->values.resize(size);
1040 this->unitFactors.resize(size);
1041 for (vmint i = 0; i < values->argsCount(); ++i) {
1042 VMRealExpr* expr = dynamic_cast<VMRealExpr*>(values->arg(i));
1043 if (expr) {
1044 this->values[i] = expr->evalReal();
1045 this->unitFactors[i] = expr->unitFactor();
1046 }
1047 }
1048 }
1049
1050 RealArrayVariable::RealArrayVariable(ParserContext* ctx, bool bConst) :
1051 Variable({
1052 .ctx = ctx,
1053 .isPolyphonic = false,
1054 .isConst = bConst,
1055 .isFinal = false,
1056 .elements = 0,
1057 .memPos = 0,
1058 .unitFactorMemPos = 0,
1059 .unitType = VM_NO_UNIT
1060 })
1061 {
1062 }
1063
1064 vmfloat RealArrayVariable::evalRealElement(vmuint i) {
1065 if (i >= values.size()) return 0;
1066 return values[i];
1067 }
1068
1069 void RealArrayVariable::assignRealElement(vmuint i, vmfloat value) {
1070 if (i >= values.size()) return;
1071 values[i] = value;
1072 }
1073
1074 vmfloat RealArrayVariable::unitFactorOfElement(vmuint i) const {
1075 if (i >= unitFactors.size()) return VM_NO_FACTOR;
1076 return unitFactors[i];
1077 }
1078
1079 void RealArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1080 if (i >= unitFactors.size()) return;
1081 unitFactors[i] = factor;
1082 }
1083
1084 void RealArrayVariable::dump(int level) {
1085 printIndents(level);
1086 printf("RealArray(");
1087 for (vmint i = 0; i < values.size(); ++i) {
1088 if (i % 12 == 0) {
1089 printf("\n");
1090 printIndents(level+1);
1091 }
1092 printf("%f, ", values[i]);
1093 }
1094 printIndents(level);
1095 printf(")\n");
1096 }
1097
1098 BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name,
1099 VMInt8Array* array) :
1100 IntArrayVariable(NULL, false),
1101 name(name), array(array)
1102 {
1103 }
1104
1105 vmint BuiltInIntArrayVariable::evalIntElement(vmuint i) {
1106 return i >= array->size ? 0 : array->data[i];
1107 }
1108
1109 void BuiltInIntArrayVariable::assignIntElement(vmuint i, vmint value) {
1110 if (i >= array->size) return;
1111 array->data[i] = value;
1112 }
1113
1114 void BuiltInIntArrayVariable::dump(int level) {
1115 printIndents(level);
1116 printf("Built-In Int Array Variable '%s'\n", name.c_str());
1117 }
1118
1119 IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) :
1120 IntVariable({
1121 .ctx = NULL,
1122 .isPolyphonic = (array) ? array->isPolyphonic() : false,
1123 .isConst = (array) ? array->isConstExpr() : false,
1124 .isFinal = false,
1125 .elements = 0,
1126 .memPos = 0,
1127 .unitFactorMemPos = 0,
1128 .unitType = VM_NO_UNIT
1129 }),
1130 Unit(VM_NO_UNIT),
1131 array(array), index(arrayIndex), currentIndex(-1)
1132 {
1133 }
1134
1135 void IntArrayElement::assign(Expression* expr) {
1136 IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
1137 if (!valueExpr) return;
1138 vmint value = valueExpr->evalInt();
1139 vmfloat unitFactor = valueExpr->unitFactor();
1140
1141 if (!index) return;
1142 vmint idx = currentIndex = index->evalInt();
1143 if (idx < 0 || idx >= array->arraySize()) return;
1144
1145 array->assignIntElement(idx, value);
1146 array->assignElementUnitFactor(idx, unitFactor);
1147 }
1148
1149 vmint IntArrayElement::evalInt() {
1150 if (!index) return 0;
1151 vmint idx = currentIndex = index->evalInt();
1152 if (idx < 0 || idx >= array->arraySize()) return 0;
1153
1154 return array->evalIntElement(idx);
1155 }
1156
1157 vmfloat IntArrayElement::unitFactor() const {
1158 if (!index) return VM_NO_FACTOR;
1159 vmint idx = currentIndex;
1160 if (idx < 0 || idx >= array->arraySize()) return 0;
1161
1162 return array->unitFactorOfElement(idx);
1163 }
1164
1165 void IntArrayElement::dump(int level) {
1166 printIndents(level);
1167 printf("IntArrayElement\n");
1168 }
1169
1170 RealArrayElement::RealArrayElement(RealArrayExprRef array, IntExprRef arrayIndex) :
1171 RealVariable({
1172 .ctx = NULL,
1173 .isPolyphonic = (array) ? array->isPolyphonic() : false,
1174 .isConst = (array) ? array->isConstExpr() : false,
1175 .isFinal = false,
1176 .elements = 0,
1177 .memPos = 0,
1178 .unitFactorMemPos = 0,
1179 .unitType = VM_NO_UNIT
1180 }),
1181 Unit(VM_NO_UNIT),
1182 array(array), index(arrayIndex), currentIndex(-1)
1183 {
1184 }
1185
1186 void RealArrayElement::assign(Expression* expr) {
1187 RealExpr* valueExpr = dynamic_cast<RealExpr*>(expr);
1188 if (!valueExpr) return;
1189 vmfloat value = valueExpr->evalReal();
1190 vmfloat unitFactor = valueExpr->unitFactor();
1191
1192 if (!index) return;
1193 vmint idx = currentIndex = index->evalInt();
1194 if (idx < 0 || idx >= array->arraySize()) return;
1195
1196 array->assignRealElement(idx, value);
1197 array->assignElementUnitFactor(idx, unitFactor);
1198 }
1199
1200 vmfloat RealArrayElement::evalReal() {
1201 if (!index) return 0;
1202 vmint idx = currentIndex = index->evalInt();
1203 if (idx < 0 || idx >= array->arraySize()) return 0;
1204
1205 return array->evalRealElement(idx);
1206 }
1207
1208 vmfloat RealArrayElement::unitFactor() const {
1209 if (!index) return VM_NO_FACTOR;
1210 vmint idx = currentIndex;
1211 if (idx < 0 || idx >= array->arraySize()) return 0;
1212
1213 return array->unitFactorOfElement(idx);
1214 }
1215
1216 void RealArrayElement::dump(int level) {
1217 printIndents(level);
1218 printf("RealArrayElement\n");
1219 }
1220
1221 StringVariable::StringVariable(ParserContext* ctx) :
1222 Variable({
1223 .ctx = ctx,
1224 .elements = 1,
1225 .memPos = ctx->globalStrVarCount++
1226 })
1227 {
1228 }
1229
1230 StringVariable::StringVariable(ParserContext* ctx, bool bConst) :
1231 Variable({
1232 .ctx = ctx,
1233 .memPos = 0,
1234 .isConst = bConst
1235 })
1236 {
1237 }
1238
1239 void StringVariable::assign(Expression* expr) {
1240 StringExpr* strExpr = dynamic_cast<StringExpr*>(expr);
1241 (*context->globalStrMemory)[memPos] = strExpr->evalStr();
1242 }
1243
1244 String StringVariable::evalStr() {
1245 //printf("StringVariable::eval pos=%d\n", memPos);
1246 return (*context->globalStrMemory)[memPos];
1247 }
1248
1249 void StringVariable::dump(int level) {
1250 printIndents(level);
1251 printf("StringVariable memPos=%lld\n", memPos);
1252 }
1253
1254 ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)
1255 : StringVariable(ctx,true), value(_value)
1256 {
1257 }
1258
1259 void ConstStringVariable::assign(Expression* expr) {
1260 // ignore assignment
1261 // StringExpr* strExpr = dynamic_cast<StringExpr*>(expr);
1262 // if (strExpr) value = strExpr->evalStr();
1263 }
1264
1265 String ConstStringVariable::evalStr() {
1266 return value;
1267 }
1268
1269 void ConstStringVariable::dump(int level) {
1270 printIndents(level);
1271 printf("ConstStringVariable val='%s'\n", value.c_str());
1272 }
1273
1274 bool ScalarNumberBinaryOp::isFinal() const {
1275 ScalarNumberExprRef l = (ScalarNumberExprRef) lhs;
1276 ScalarNumberExprRef r = (ScalarNumberExprRef) rhs;
1277 return l->isFinal() || r->isFinal();
1278 }
1279
1280 ExprType_t VaritypeScalarBinaryOp::exprType() const {
1281 return (lhs->exprType() == REAL_EXPR || rhs->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
1282 }
1283
1284 String VaritypeScalarBinaryOp::evalCastToStr() {
1285 return (exprType() == REAL_EXPR) ?
1286 RealExpr::evalCastToStr() : IntExpr::evalCastToStr();
1287 }
1288
1289 void If::dump(int level) {
1290 printIndents(level);
1291 if (ifStatements && elseStatements)
1292 printf("if cond stmts1 else stmts2 end if\n");
1293 else if (ifStatements)
1294 printf("if cond statements end if\n");
1295 else
1296 printf("if [INVALID]\n");
1297 }
1298
1299 vmint If::evalBranch() {
1300 if (condition->evalInt()) return 0;
1301 if (elseStatements) return 1;
1302 return -1;
1303 }
1304
1305 Statements* If::branch(vmuint i) const {
1306 if (i == 0) return (Statements*) &*ifStatements;
1307 if (i == 1) return (elseStatements) ? (Statements*) &*elseStatements : NULL;
1308 return NULL;
1309 }
1310
1311 bool If::isPolyphonic() const {
1312 if (condition->isPolyphonic() || ifStatements->isPolyphonic())
1313 return true;
1314 return elseStatements ? elseStatements->isPolyphonic() : false;
1315 }
1316
1317 void SelectCase::dump(int level) {
1318 printIndents(level);
1319 if (select)
1320 if (select->isConstExpr())
1321 printf("Case select %lld\n", select->evalInt());
1322 else
1323 printf("Case select [runtime expr]\n");
1324 else
1325 printf("Case select NULL\n");
1326 for (vmint i = 0; i < branches.size(); ++i) {
1327 printIndents(level+1);
1328 CaseBranch& branch = branches[i];
1329 if (branch.from && branch.to)
1330 if (branch.from->isConstExpr() && branch.to->isConstExpr())
1331 printf("case %lld to %lld\n", branch.from->evalInt(), branch.to->evalInt());
1332 else if (branch.from->isConstExpr() && !branch.to->isConstExpr())
1333 printf("case %lld to [runtime expr]\n", branch.from->evalInt());
1334 else if (!branch.from->isConstExpr() && branch.to->isConstExpr())
1335 printf("case [runtime expr] to %lld\n", branch.to->evalInt());
1336 else
1337 printf("case [runtime expr] to [runtime expr]\n");
1338 else if (branch.from)
1339 if (branch.from->isConstExpr())
1340 printf("case %lld\n", branch.from->evalInt());
1341 else
1342 printf("case [runtime expr]\n");
1343 else
1344 printf("case NULL\n");
1345 }
1346 }
1347
1348 vmint SelectCase::evalBranch() {
1349 vmint value = select->evalInt();
1350 for (vmint i = 0; i < branches.size(); ++i) {
1351 if (branches.at(i).from && branches.at(i).to) { // i.e. "case 4 to 7" ...
1352 if (branches.at(i).from->evalInt() <= value &&
1353 branches.at(i).to->evalInt() >= value) return i;
1354 } else { // i.e. "case 5" ...
1355 if (branches.at(i).from->evalInt() == value) return i;
1356 }
1357 }
1358 return -1;
1359 }
1360
1361 Statements* SelectCase::branch(vmuint i) const {
1362 if (i < branches.size())
1363 return const_cast<Statements*>( &*branches[i].statements );
1364 return NULL;
1365 }
1366
1367 bool SelectCase::isPolyphonic() const {
1368 if (select->isPolyphonic()) return true;
1369 for (vmint i = 0; i < branches.size(); ++i)
1370 if (branches[i].statements->isPolyphonic())
1371 return true;
1372 return false;
1373 }
1374
1375 void While::dump(int level) {
1376 printIndents(level);
1377 if (m_condition)
1378 if (m_condition->isConstExpr())
1379 printf("while (%lld) {\n", m_condition->evalInt());
1380 else
1381 printf("while ([runtime expr]) {\n");
1382 else
1383 printf("while ([INVALID]) {\n");
1384 m_statements->dump(level+1);
1385 printIndents(level);
1386 printf("}\n");
1387 }
1388
1389 Statements* While::statements() const {
1390 return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1391 }
1392
1393 bool While::evalLoopStartCondition() {
1394 if (!m_condition) return false;
1395 return m_condition->evalInt();
1396 }
1397
1398 void SyncBlock::dump(int level) {
1399 printIndents(level);
1400 printf("sync {\n");
1401 m_statements->dump(level+1);
1402 printIndents(level);
1403 printf("}\n");
1404 }
1405
1406 Statements* SyncBlock::statements() const {
1407 return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1408 }
1409
1410 String Neg::evalCastToStr() {
1411 return expr->evalCastToStr();
1412 }
1413
1414 void Neg::dump(int level) {
1415 printIndents(level);
1416 printf("Negative Expr\n");
1417 }
1418
1419 String ConcatString::evalStr() {
1420 // temporaries required here to enforce the associative left (to right) order
1421 // ( required for GCC and Visual Studio, see:
1422 // http://stackoverflow.com/questions/25842902/why-stdstring-concatenation-operator-works-like-right-associative-one
1423 // Personally I am not convinced that this is "not a bug" of the
1424 // compiler/STL implementation and the allegedly underlying "function call"
1425 // nature causing this is IMO no profound reason that the C++ language's
1426 // "+" operator's left associativity is ignored. -- Christian, 2016-07-14 )
1427 String l = lhs->evalCastToStr();
1428 String r = rhs->evalCastToStr();
1429 return l + r;
1430 }
1431
1432 void ConcatString::dump(int level) {
1433 printIndents(level);
1434 printf("ConcatString(\n");
1435 lhs->dump(level+1);
1436 printIndents(level);
1437 printf(",\n");
1438 rhs->dump(level+1);
1439 printIndents(level);
1440 printf(")");
1441 }
1442
1443 bool ConcatString::isConstExpr() const {
1444 return lhs->isConstExpr() && rhs->isConstExpr();
1445 }
1446
1447 Relation::Relation(ExpressionRef lhs, Type type, ExpressionRef rhs) :
1448 Unit(VM_NO_UNIT),
1449 lhs(lhs), rhs(rhs), type(type)
1450 {
1451 }
1452
1453 // Equal / unequal comparison of real numbers in NKSP scripts:
1454 //
1455 // Unlike system level languages like C/C++ we are less conservative about
1456 // comparing floating point numbers for 'equalness' or 'unequalness' in NKSP
1457 // scripts. Due to the musical context of the NKSP language we automatically
1458 // take the (to be) expected floating point tolerances into account when
1459 // comparing two floating point numbers with each other, however only for '='
1460 // and '#' operators. The '<=' and '>=' still use conservative low level
1461 // floating point comparison for not breaking their transitivity feature.
1462
1463 template<typename T_LHS, typename T_RHS>
1464 struct RelComparer {
1465 static inline bool isEqual(T_LHS a, T_RHS b) { // for int comparison ('3 = 3')
1466 return a == b;
1467 }
1468 static inline bool isUnequal(T_LHS a, T_RHS b) { // for int comparison ('3 # 3')
1469 return a != b;
1470 }
1471 };
1472
1473 template<>
1474 struct RelComparer<float,float> {
1475 static inline bool isEqual(float a, float b) { // for real number comparison ('3.1 = 3.1')
1476 return RTMath::fEqual32(a, b);
1477 }
1478 static inline bool isUnequal(float a, float b) { // for real number comparison ('3.1 # 3.1')
1479 return !RTMath::fEqual32(a, b);
1480 }
1481 };
1482
1483 template<>
1484 struct RelComparer<double,double> {
1485 static inline bool isEqual(double a, double b) { // for future purpose
1486 return RTMath::fEqual64(a, b);
1487 }
1488 static inline bool isUnqqual(double a, double b) { // for future purpose
1489 return !RTMath::fEqual64(a, b);
1490 }
1491 };
1492
1493 template<class T_LHS, class T_RHS>
1494 inline vmint _evalRelation(Relation::Type type, T_LHS lhs, T_RHS rhs) {
1495 switch (type) {
1496 case Relation::LESS_THAN:
1497 return lhs < rhs;
1498 case Relation::GREATER_THAN:
1499 return lhs > rhs;
1500 case Relation::LESS_OR_EQUAL:
1501 return lhs <= rhs;
1502 case Relation::GREATER_OR_EQUAL:
1503 return lhs >= rhs;
1504 case Relation::EQUAL:
1505 return RelComparer<typeof(lhs),typeof(rhs)>::isEqual(lhs, rhs);
1506 case Relation::NOT_EQUAL:
1507 return RelComparer<typeof(lhs),typeof(rhs)>::isUnequal(lhs, rhs);
1508 }
1509 return 0;
1510 }
1511
1512 template<class T_LVALUE, class T_RVALUE, class T_LEXPR, class T_REXPR>
1513 inline vmint _evalRealRelation(Relation::Type type,
1514 T_LVALUE lvalue, T_RVALUE rvalue,
1515 T_LEXPR* pLHS, T_REXPR* pRHS)
1516 {
1517 if (pLHS->unitFactor() == pRHS->unitFactor())
1518 return _evalRelation(type, lvalue, rvalue);
1519 if (pLHS->unitFactor() < pRHS->unitFactor())
1520 return _evalRelation(type, lvalue, Unit::convRealToUnitFactor(rvalue, pRHS, pLHS));
1521 else
1522 return _evalRelation(type, Unit::convRealToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1523 }
1524
1525 template<class T_LEXPR, class T_REXPR>
1526 inline vmint _evalIntRelation(Relation::Type type,
1527 vmint lvalue, vmint rvalue,
1528 T_LEXPR* pLHS, T_REXPR* pRHS)
1529 {
1530 if (pLHS->unitFactor() == pRHS->unitFactor())
1531 return _evalRelation(type, lvalue, rvalue);
1532 if (pLHS->unitFactor() < pRHS->unitFactor())
1533 return _evalRelation(type, lvalue, Unit::convIntToUnitFactor(rvalue, pRHS, pLHS));
1534 else
1535 return _evalRelation(type, Unit::convIntToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1536 }
1537
1538 vmint Relation::evalInt() {
1539 const ExprType_t lType = lhs->exprType();
1540 const ExprType_t rType = rhs->exprType();
1541 if (lType == STRING_EXPR || rType == STRING_EXPR) {
1542 switch (type) {
1543 case EQUAL:
1544 return lhs->evalCastToStr() == rhs->evalCastToStr();
1545 case NOT_EQUAL:
1546 return lhs->evalCastToStr() != rhs->evalCastToStr();
1547 default:
1548 return 0;
1549 }
1550 } else if (lType == REAL_EXPR && rType == REAL_EXPR) {
1551 vmfloat lvalue = lhs->asReal()->evalReal();
1552 vmfloat rvalue = rhs->asReal()->evalReal();
1553 return _evalRealRelation(
1554 type, lvalue, rvalue, lhs->asReal(), rhs->asReal()
1555 );
1556 } else if (lType == REAL_EXPR && rType == INT_EXPR) {
1557 vmfloat lvalue = lhs->asReal()->evalReal();
1558 vmint rvalue = rhs->asInt()->evalInt();
1559 return _evalRealRelation(
1560 type, lvalue, rvalue, lhs->asReal(), rhs->asInt()
1561 );
1562 } else if (lType == INT_EXPR && rType == REAL_EXPR) {
1563 vmint lvalue = lhs->asInt()->evalInt();
1564 vmfloat rvalue = rhs->asReal()->evalReal();
1565 return _evalRealRelation(
1566 type, lvalue, rvalue, lhs->asInt(), rhs->asReal()
1567 );
1568 } else {
1569 vmint lvalue = lhs->asInt()->evalInt();
1570 vmint rvalue = rhs->asInt()->evalInt();
1571 return _evalIntRelation(
1572 type, lvalue, rvalue, lhs->asInt(), rhs->asInt()
1573 );
1574 }
1575 }
1576
1577 void Relation::dump(int level) {
1578 printIndents(level);
1579 printf("Relation(\n");
1580 lhs->dump(level+1);
1581 printIndents(level);
1582 switch (type) {
1583 case LESS_THAN:
1584 printf("LESS_THAN\n");
1585 break;
1586 case GREATER_THAN:
1587 printf("GREATER_THAN\n");
1588 break;
1589 case LESS_OR_EQUAL:
1590 printf("LESS_OR_EQUAL\n");
1591 break;
1592 case GREATER_OR_EQUAL:
1593 printf("GREATER_OR_EQUAL\n");
1594 break;
1595 case EQUAL:
1596 printf("EQUAL\n");
1597 break;
1598 case NOT_EQUAL:
1599 printf("NOT_EQUAL\n");
1600 break;
1601 }
1602 rhs->dump(level+1);
1603 printIndents(level);
1604 printf(")\n");
1605 }
1606
1607 bool Relation::isConstExpr() const {
1608 return lhs->isConstExpr() && rhs->isConstExpr();
1609 }
1610
1611 vmint Or::evalInt() {
1612 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1613 if (pLHS->evalInt()) return 1;
1614 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1615 return (pRHS->evalInt()) ? 1 : 0;
1616 }
1617
1618 void Or::dump(int level) {
1619 printIndents(level);
1620 printf("Or(\n");
1621 lhs->dump(level+1);
1622 printIndents(level);
1623 printf(",\n");
1624 rhs->dump(level+1);
1625 printIndents(level);
1626 printf(")\n");
1627 }
1628
1629 vmint BitwiseOr::evalInt() {
1630 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1631 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1632 return pLHS->evalInt() | pRHS->evalInt();
1633 }
1634
1635 void BitwiseOr::dump(int level) {
1636 printIndents(level);
1637 printf("BitwiseOr(\n");
1638 lhs->dump(level+1);
1639 printIndents(level);
1640 printf(",\n");
1641 rhs->dump(level+1);
1642 printIndents(level);
1643 printf(")\n");
1644 }
1645
1646 vmint And::evalInt() {
1647 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1648 if (!pLHS->evalInt()) return 0;
1649 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1650 return (pRHS->evalInt()) ? 1 : 0;
1651 }
1652
1653 void And::dump(int level) {
1654 printIndents(level);
1655 printf("And(\n");
1656 lhs->dump(level+1);
1657 printIndents(level);
1658 printf(",\n");
1659 rhs->dump(level+1);
1660 printIndents(level);
1661 printf(")\n");
1662 }
1663
1664 vmint BitwiseAnd::evalInt() {
1665 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1666 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1667 return pLHS->evalInt() & pRHS->evalInt();
1668 }
1669
1670 void BitwiseAnd::dump(int level) {
1671 printIndents(level);
1672 printf("BitwiseAnd(\n");
1673 lhs->dump(level+1);
1674 printIndents(level);
1675 printf(",\n");
1676 rhs->dump(level+1);
1677 printIndents(level);
1678 printf(")\n");
1679 }
1680
1681 void Not::dump(int level) {
1682 printIndents(level);
1683 printf("Not(\n");
1684 expr->dump(level+1);
1685 printIndents(level);
1686 printf(")\n");
1687 }
1688
1689 void BitwiseNot::dump(int level) {
1690 printIndents(level);
1691 printf("BitwiseNot(\n");
1692 expr->dump(level+1);
1693 printIndents(level);
1694 printf(")\n");
1695 }
1696
1697 String Final::evalCastToStr() {
1698 if (exprType() == REAL_EXPR)
1699 return ToString(evalReal());
1700 else
1701 return ToString(evalInt());
1702 }
1703
1704 void Final::dump(int level) {
1705 printIndents(level);
1706 printf("Final(\n");
1707 expr->dump(level+1);
1708 printIndents(level);
1709 printf(")\n");
1710 }
1711
1712 StatementsRef ParserContext::userFunctionByName(const String& name) {
1713 if (!userFnTable.count(name)) {
1714 return StatementsRef();
1715 }
1716 return userFnTable.find(name)->second;
1717 }
1718
1719 VariableRef ParserContext::variableByName(const String& name) {
1720 if (!vartable.count(name)) {
1721 return VariableRef();
1722 }
1723 return vartable.find(name)->second;
1724 }
1725
1726 VariableRef ParserContext::globalVar(const String& name) {
1727 if (!vartable.count(name)) {
1728 //printf("No global var '%s'\n", name.c_str());
1729 //for (std::map<String,VariableRef>::const_iterator it = vartable.begin(); it != vartable.end(); ++it)
1730 // printf("-> var '%s'\n", it->first.c_str());
1731 return VariableRef();
1732 }
1733 return vartable.find(name)->second;
1734 }
1735
1736 IntVariableRef ParserContext::globalIntVar(const String& name) {
1737 return globalVar(name);
1738 }
1739
1740 RealVariableRef ParserContext::globalRealVar(const String& name) {
1741 return globalVar(name);
1742 }
1743
1744 StringVariableRef ParserContext::globalStrVar(const String& name) {
1745 return globalVar(name);
1746 }
1747
1748 ParserContext::~ParserContext() {
1749 destroyScanner();
1750 if (globalIntMemory) {
1751 delete globalIntMemory;
1752 globalIntMemory = NULL;
1753 }
1754 if (globalRealMemory) {
1755 delete globalRealMemory;
1756 globalRealMemory = NULL;
1757 }
1758 }
1759
1760 void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {
1761 ParserIssue e;
1762 e.type = PARSER_ERROR;
1763 e.txt = txt;
1764 e.firstLine = firstLine;
1765 e.lastLine = lastLine;
1766 e.firstColumn = firstColumn;
1767 e.lastColumn = lastColumn;
1768 vErrors.push_back(e);
1769 vIssues.push_back(e);
1770 }
1771
1772 void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {
1773 ParserIssue w;
1774 w.type = PARSER_WARNING;
1775 w.txt = txt;
1776 w.firstLine = firstLine;
1777 w.lastLine = lastLine;
1778 w.firstColumn = firstColumn;
1779 w.lastColumn = lastColumn;
1780 vWarnings.push_back(w);
1781 vIssues.push_back(w);
1782 }
1783
1784 void ParserContext::addPreprocessorComment(int firstLine, int lastLine, int firstColumn, int lastColumn) {
1785 CodeBlock block;
1786 block.firstLine = firstLine;
1787 block.lastLine = lastLine;
1788 block.firstColumn = firstColumn;
1789 block.lastColumn = lastColumn;
1790 vPreprocessorComments.push_back(block);
1791 }
1792
1793 bool ParserContext::setPreprocessorCondition(const char* name) {
1794 if (builtinPreprocessorConditions.count(name)) return false;
1795 if (userPreprocessorConditions.count(name)) return false;
1796 userPreprocessorConditions.insert(name);
1797 return true;
1798 }
1799
1800 bool ParserContext::resetPreprocessorCondition(const char* name) {
1801 if (builtinPreprocessorConditions.count(name)) return false;
1802 if (!userPreprocessorConditions.count(name)) return false;
1803 userPreprocessorConditions.erase(name);
1804 return true;
1805 }
1806
1807 bool ParserContext::isPreprocessorConditionSet(const char* name) {
1808 if (builtinPreprocessorConditions.count(name)) return true;
1809 return userPreprocessorConditions.count(name);
1810 }
1811
1812 std::vector<ParserIssue> ParserContext::issues() const {
1813 return vIssues;
1814 }
1815
1816 std::vector<ParserIssue> ParserContext::errors() const {
1817 return vErrors;
1818 }
1819
1820 std::vector<ParserIssue> ParserContext::warnings() const {
1821 return vWarnings;
1822 }
1823
1824 std::vector<CodeBlock> ParserContext::preprocessorComments() const {
1825 return vPreprocessorComments;
1826 }
1827
1828 VMEventHandler* ParserContext::eventHandler(uint index) {
1829 if (!handlers) return NULL;
1830 return handlers->eventHandler(index);
1831 }
1832
1833 VMEventHandler* ParserContext::eventHandlerByName(const String& name) {
1834 if (!handlers) return NULL;
1835 return handlers->eventHandlerByName(name);
1836 }
1837
1838 void ParserContext::registerBuiltInConstIntVariables(const std::map<String,vmint>& vars) {
1839 for (std::map<String,vmint>::const_iterator it = vars.begin();
1840 it != vars.end(); ++it)
1841 {
1842 ConstIntVariableRef ref = new ConstIntVariable({
1843 .value = it->second
1844 });
1845 vartable[it->first] = ref;
1846 }
1847 }
1848
1849 void ParserContext::registerBuiltInIntVariables(const std::map<String,VMIntPtr*>& vars) {
1850 for (std::map<String,VMIntPtr*>::const_iterator it = vars.begin();
1851 it != vars.end(); ++it)
1852 {
1853 BuiltInIntVariableRef ref = new BuiltInIntVariable(it->first, it->second);
1854 vartable[it->first] = ref;
1855 }
1856 }
1857
1858 void ParserContext::registerBuiltInIntArrayVariables(const std::map<String,VMInt8Array*>& vars) {
1859 for (std::map<String,VMInt8Array*>::const_iterator it = vars.begin();
1860 it != vars.end(); ++it)
1861 {
1862 BuiltInIntArrayVariableRef ref = new BuiltInIntArrayVariable(it->first, it->second);
1863 vartable[it->first] = ref;
1864 }
1865 }
1866
1867 void ParserContext::registerBuiltInDynVariables(const std::map<String,VMDynVar*>& vars) {
1868 for (std::map<String,VMDynVar*>::const_iterator it = vars.begin();
1869 it != vars.end(); ++it)
1870 {
1871 DynamicVariableCallRef ref = new DynamicVariableCall(it->first, this, it->second);
1872 vartable[it->first] = ref;
1873 }
1874 }
1875
1876 ExecContext::ExecContext() :
1877 status(VM_EXEC_NOT_RUNNING), flags(STMT_SUCCESS), stackFrame(-1),
1878 suspendMicroseconds(0), instructionsCount(0)
1879 {
1880 exitRes.value = NULL;
1881 }
1882
1883 void ExecContext::forkTo(VMExecContext* ectx) const {
1884 ExecContext* child = dynamic_cast<ExecContext*>(ectx);
1885
1886 child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory);
1887 child->polyphonicRealMemory.copyFlatFrom(polyphonicRealMemory);
1888 child->status = VM_EXEC_SUSPENDED;
1889 child->flags = STMT_SUCCESS;
1890 child->stack.copyFlatFrom(stack);
1891 child->stackFrame = stackFrame;
1892 child->suspendMicroseconds = 0;
1893 child->instructionsCount = 0;
1894 }
1895
1896 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC