/[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 3714 - (show annotations) (download)
Sat Jan 11 20:19:11 2020 UTC (4 years, 2 months ago) by schoenebeck
File size: 57931 byte(s)
NKSP: Fixed crash with built-in functions returning an array.

* Calling built-in functions returning an array type was broken and
  caused a crash when built-in function's NULL (supposed to be array)
  result value was used by the script VM.

* Bumped version (2.1.1.svn37).

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

  ViewVC Help
Powered by ViewVC