/[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 3744 - (show annotations) (download)
Sat Feb 15 11:50:02 2020 UTC (4 years, 2 months ago) by schoenebeck
File size: 59249 byte(s)
* NKSP: Fixed intermediate function result values never having reflected
  any standard measuring unit type.

* Tests: Guard this fixed NKSP issue by test cases.

* Bumped version (2.1.1.svn49).

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

  ViewVC Help
Powered by ViewVC