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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3747 - (hide annotations) (download)
Sun Feb 16 11:31:46 2020 UTC (4 years, 3 months ago) by schoenebeck
File size: 59907 byte(s)
* NKSP: Fixed re-entrant issue with function calls which caused wrong
  result values if the same function was called multiple times in a term
  (specifically if metric prefixes were used).

* Tests: Added NKSP core language test cases to guard this fixed issue.

* Bumped version (2.1.1.svn50).

1 schoenebeck 2581 /*
2 schoenebeck 3551 * Copyright (c) 2014 - 2019 Christian Schoenebeck and Andreas Persson
3 schoenebeck 2581 *
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 schoenebeck 3581 #include "../common/RTMath.h"
15 schoenebeck 2588 #include <assert.h>
16 schoenebeck 3744 #include "CoreVMFunctions.h" // for VMIntResult, VMRealResult
17 schoenebeck 2581
18     namespace LinuxSampler {
19    
20     bool isNoOperation(StatementRef statement) {
21 schoenebeck 3311 return statement->statementType() == STMT_NOOP;
22 schoenebeck 2581 }
23 schoenebeck 3585
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 schoenebeck 2581
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 schoenebeck 3581 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 schoenebeck 3744 static String _unitToStr(VMUnit* unit) {
127 schoenebeck 3581 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 schoenebeck 2581 String IntExpr::evalCastToStr() {
142 schoenebeck 3581 return ToString(evalInt()) + _unitToStr(this);
143 schoenebeck 2581 }
144    
145 schoenebeck 3581 vmfloat RealExpr::evalRealToUnitFactor(vmfloat unitFactor) {
146     vmfloat f = evalReal();
147     vmfloat factor = this->unitFactor() / unitFactor;
148     return f * factor;
149     }
150    
151 schoenebeck 3573 String RealExpr::evalCastToStr() {
152 schoenebeck 3581 return ToString(evalReal()) + _unitToStr(this);
153 schoenebeck 3573 }
154    
155 schoenebeck 3293 String IntArrayExpr::evalCastToStr() {
156 schoenebeck 3056 String s = "{";
157 schoenebeck 3557 for (vmint i = 0; i < arraySize(); ++i) {
158     vmint val = evalIntElement(i);
159 schoenebeck 3581 vmfloat factor = unitFactorOfElement(i);
160 schoenebeck 3056 if (i) s += ",";
161 schoenebeck 3581 s += ToString(val) + _unitFactorToShortStr(factor);
162 schoenebeck 3056 }
163     s += "}";
164     return s;
165 schoenebeck 3293 }
166 schoenebeck 3056
167 schoenebeck 3573 String RealArrayExpr::evalCastToStr() {
168     String s = "{";
169     for (vmint i = 0; i < arraySize(); ++i) {
170     vmfloat val = evalRealElement(i);
171 schoenebeck 3581 vmfloat factor = unitFactorOfElement(i);
172 schoenebeck 3573 if (i) s += ",";
173 schoenebeck 3581 s += ToString(val) + _unitFactorToShortStr(factor);
174 schoenebeck 3573 }
175     s += "}";
176     return s;
177     }
178    
179 schoenebeck 3581 IntLiteral::IntLiteral(const IntLitDef& def) :
180     IntExpr(), Unit(def.unitType),
181     value(def.value), unitPrefixFactor(def.unitFactor),
182     finalVal(def.isFinal)
183     {
184 schoenebeck 3561 }
185    
186 schoenebeck 3557 vmint IntLiteral::evalInt() {
187 schoenebeck 2581 return value;
188     }
189    
190     void IntLiteral::dump(int level) {
191     printIndents(level);
192 schoenebeck 3707 printf("IntLiteral %" PRId64 "\n", (int64_t)value);
193 schoenebeck 2581 }
194    
195 schoenebeck 3581 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 schoenebeck 3573 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 schoenebeck 2581 void StringLiteral::dump(int level) {
212     printIndents(level);
213     printf("StringLiteral: '%s'\n", value.c_str());
214     }
215    
216 schoenebeck 3582 Add::Add(NumberExprRef lhs, NumberExprRef rhs) :
217 schoenebeck 3581 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 schoenebeck 3557 vmint Add::evalInt() {
226 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
227 schoenebeck 3581 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 schoenebeck 2581 }
239    
240 schoenebeck 3573 vmfloat Add::evalReal() {
241     RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
242 schoenebeck 3581 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 schoenebeck 3573 }
254    
255 schoenebeck 3581 vmfloat Add::unitFactor() const {
256 schoenebeck 3582 const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
257     const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
258 schoenebeck 3581 return (pLHS->unitFactor() < pRHS->unitFactor()) ? pLHS->unitFactor() : pRHS->unitFactor();
259     }
260    
261 schoenebeck 2581 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 schoenebeck 3582 Sub::Sub(NumberExprRef lhs, NumberExprRef rhs) :
273 schoenebeck 3581 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 schoenebeck 3557 vmint Sub::evalInt() {
282 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
283 schoenebeck 3581 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 schoenebeck 2581 }
295    
296 schoenebeck 3573 vmfloat Sub::evalReal() {
297     RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
298 schoenebeck 3581 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 schoenebeck 3573 }
310    
311 schoenebeck 3581 vmfloat Sub::unitFactor() const {
312 schoenebeck 3582 const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
313     const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
314 schoenebeck 3581 return (pLHS->unitFactor() < pRHS->unitFactor()) ? pLHS->unitFactor() : pRHS->unitFactor();
315     }
316    
317 schoenebeck 2581 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 schoenebeck 3582 Mul::Mul(NumberExprRef lhs, NumberExprRef rhs) :
329 schoenebeck 3581 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 schoenebeck 3557 vmint Mul::evalInt() {
338 schoenebeck 2581 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 schoenebeck 3573 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 schoenebeck 2581 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 schoenebeck 3581 vmfloat Mul::unitFactor() const {
361 schoenebeck 3582 const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
362     const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
363 schoenebeck 3581 return pLHS->unitFactor() * pRHS->unitFactor();
364 schoenebeck 3561 }
365    
366 schoenebeck 3582 Div::Div(NumberExprRef lhs, NumberExprRef rhs) :
367 schoenebeck 3581 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 schoenebeck 3561 }
375    
376 schoenebeck 3557 vmint Div::evalInt() {
377 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
378 schoenebeck 2945 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
379     if (!pLHS || !pRHS) return 0;
380 schoenebeck 3557 vmint l = pLHS->evalInt();
381     vmint r = pRHS->evalInt();
382 schoenebeck 2945 if (r == 0) return 0;
383     return l / r;
384 schoenebeck 2581 }
385    
386 schoenebeck 3573 vmfloat Div::evalReal() {
387     RealExpr* pLHS = dynamic_cast<RealExpr*>(&*lhs);
388 schoenebeck 3581 RealExpr* pRHS = dynamic_cast<RealExpr*>(&*rhs);
389 schoenebeck 3573 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 schoenebeck 2581 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 schoenebeck 3581 vmfloat Div::unitFactor() const {
408 schoenebeck 3582 const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
409     const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
410 schoenebeck 3581 return pLHS->unitFactor() / pRHS->unitFactor();
411 schoenebeck 3561 }
412    
413 schoenebeck 3557 vmint Mod::evalInt() {
414 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
415 schoenebeck 3581 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
416 schoenebeck 2581 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 schoenebeck 2645 bool Args::isPolyphonic() const {
441 schoenebeck 3557 for (vmint i = 0; i < args.size(); ++i)
442 schoenebeck 2645 if (args[i]->isPolyphonic())
443     return true;
444     return false;
445     }
446    
447 schoenebeck 2581 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 schoenebeck 3557 for (vmint i = 0; i < args.size(); ++i)
470 schoenebeck 2581 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 schoenebeck 2645 bool EventHandlers::isPolyphonic() const {
481 schoenebeck 3557 for (vmint i = 0; i < args.size(); ++i)
482 schoenebeck 2645 if (args[i]->isPolyphonic())
483     return true;
484     return false;
485     }
486    
487 schoenebeck 2581 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 schoenebeck 2645 EventHandler::EventHandler(StatementsRef statements) {
505     this->statements = statements;
506     usingPolyphonics = statements->isPolyphonic();
507     }
508    
509 schoenebeck 2581 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 schoenebeck 2645 bool Statements::isPolyphonic() const {
533 schoenebeck 3557 for (vmint i = 0; i < args.size(); ++i)
534 schoenebeck 2645 if (args[i]->isPolyphonic())
535     return true;
536     return false;
537     }
538    
539 schoenebeck 3581 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 schoenebeck 2942 {
547     }
548    
549 schoenebeck 3557 vmint DynamicVariableCall::evalInt() {
550 schoenebeck 2942 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 schoenebeck 3581 FunctionCall::FunctionCall(const char* function, ArgsRef args, VMFunction* fn) :
576     Unit(
577     (fn) ? fn->returnUnitType(dynamic_cast<VMFnArgs*>(&*args)) : VM_NO_UNIT
578     ),
579 schoenebeck 3747 functionName(function), args(args), fn(fn),
580     result( (fn) ? fn->allocResult(dynamic_cast<VMFnArgs*>(&*args)) : NULL )
581 schoenebeck 3581 {
582     }
583    
584 schoenebeck 3747 FunctionCall::~FunctionCall() {
585     if (result) {
586     delete result;
587     result = NULL;
588     }
589     }
590    
591 schoenebeck 2581 void FunctionCall::dump(int level) {
592     printIndents(level);
593     printf("FunctionCall '%s' args={\n", functionName.c_str());
594     args->dump(level+1);
595     printIndents(level);
596     printf("}\n");
597     }
598    
599     ExprType_t FunctionCall::exprType() const {
600     if (!fn) return EMPTY_EXPR;
601 schoenebeck 3577 FunctionCall* self = const_cast<FunctionCall*>(this);
602     return fn->returnType(dynamic_cast<VMFnArgs*>(&*self->args));
603 schoenebeck 2581 }
604    
605 schoenebeck 3581 vmfloat FunctionCall::unitFactor() const {
606     if (!fn || !result) return VM_NO_FACTOR;
607     VMExpr* expr = result->resultValue();
608     if (!expr) return VM_NO_FACTOR;
609 schoenebeck 3582 VMNumberExpr* scalar = expr->asNumber();
610 schoenebeck 3581 if (!scalar) return VM_NO_FACTOR;
611     return scalar->unitFactor();
612     }
613    
614     bool FunctionCall::isFinal() const {
615     if (!fn) return false;
616     FunctionCall* self = const_cast<FunctionCall*>(this);
617     return fn->returnsFinal(dynamic_cast<VMFnArgs*>(&*self->args));
618     }
619    
620 schoenebeck 2581 VMFnResult* FunctionCall::execVMFn() {
621     if (!fn) return NULL;
622 schoenebeck 3747
623     // tell function where it shall dump its return value to
624     VMFnResult* oldRes = fn->boundResult();
625     fn->bindResult(result);
626    
627 schoenebeck 2581 // assuming here that all argument checks (amount and types) have been made
628     // at parse time, to avoid time intensive checks on each function call
629 schoenebeck 3744 VMFnResult* res = fn->exec(dynamic_cast<VMFnArgs*>(&*args));
630 schoenebeck 3747
631     // restore previous result binding of some potential toplevel or concurrent
632     // caller, i.e. if exactly same function is called more than one time,
633     // concurrently in a term by other FunctionCall objects, e.g.:
634     // ~c := ceil( ceil(~a) + ~b)
635     fn->bindResult(oldRes);
636    
637 schoenebeck 3744 if (!res) return res;
638    
639     VMExpr* expr = res->resultValue();
640     if (!expr) return res;
641    
642     // For performance reasons we always only let 'FunctionCall' assign the unit
643     // type to the function's result expression, never by the function
644     // implementation itself, nor by other classes, because a FunctionCall
645     // object solely knows the unit type in O(1).
646     ExprType_t type = expr->exprType();
647     if (type == INT_EXPR) {
648     VMIntResult* intRes = dynamic_cast<VMIntResult*>(res);
649     intRes->unitBaseType = unitType();
650     } else if (type == REAL_EXPR) {
651     VMRealResult* realRes = dynamic_cast<VMRealResult*>(res);
652     realRes->unitBaseType = unitType();
653     }
654    
655     return res;
656 schoenebeck 2581 }
657    
658     StmtFlags_t FunctionCall::exec() {
659 schoenebeck 3747 VMFnResult* result = execVMFn();
660 schoenebeck 2581 if (!result)
661     return StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
662     return result->resultFlags();
663     }
664    
665 schoenebeck 3557 vmint FunctionCall::evalInt() {
666 schoenebeck 3747 VMFnResult* result = execVMFn();
667 schoenebeck 2581 if (!result) return 0;
668     VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
669     if (!intExpr) return 0;
670     return intExpr->evalInt();
671     }
672    
673 schoenebeck 3573 vmfloat FunctionCall::evalReal() {
674 schoenebeck 3747 VMFnResult* result = execVMFn();
675 schoenebeck 3573 if (!result) return 0;
676     VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
677     if (!realExpr) return 0;
678     return realExpr->evalReal();
679     }
680    
681 schoenebeck 3056 VMIntArrayExpr* FunctionCall::asIntArray() const {
682 schoenebeck 3714 //FIXME: asIntArray() not intended for evaluation semantics (for both
683     // performance reasons with arrays, but also to prevent undesired value
684     // mutation by implied (hidden) evaluation, as actually done here. We must
685     // force function evaluation here though, because we need it for function
686     // calls to be evaluated at all. This issue should be addressed cleanly by
687     // adjusting the API appropriately.
688     FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
689 schoenebeck 3747 VMFnResult* result = rwSelf->execVMFn();
690 schoenebeck 3714
691 schoenebeck 3056 if (!result) return 0;
692     VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());
693     return intArrExpr;
694     }
695    
696 schoenebeck 3573 VMRealArrayExpr* FunctionCall::asRealArray() const {
697 schoenebeck 3714 //FIXME: asRealArray() not intended for evaluation semantics (for both
698     // performance reasons with arrays, but also to prevent undesired value
699     // mutation by implied (hidden) evaluation, as actually done here. We must
700     // force function evaluation here though, because we need it for function
701     // calls to be evaluated at all. This issue should be addressed cleanly by
702     // adjusting the API appropriately.
703     FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
704 schoenebeck 3747 VMFnResult* result = rwSelf->execVMFn();
705 schoenebeck 3714
706 schoenebeck 3573 if (!result) return 0;
707     VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue());
708     return realArrExpr;
709     }
710    
711 schoenebeck 2581 String FunctionCall::evalStr() {
712 schoenebeck 3747 VMFnResult* result = execVMFn();
713 schoenebeck 2581 if (!result) return "";
714     VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
715     if (!strExpr) return "";
716     return strExpr->evalStr();
717     }
718    
719     String FunctionCall::evalCastToStr() {
720 schoenebeck 3747 VMFnResult* result = execVMFn();
721 schoenebeck 2581 if (!result) return "";
722 schoenebeck 3573 const ExprType_t resultType = result->resultValue()->exprType();
723     if (resultType == STRING_EXPR) {
724 schoenebeck 2581 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
725     return strExpr ? strExpr->evalStr() : "";
726 schoenebeck 3573 } else if (resultType == REAL_EXPR) {
727     VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
728 schoenebeck 3744 return realExpr ? ToString(realExpr->evalReal()) + _unitToStr(realExpr) : "";
729 schoenebeck 2581 } else {
730     VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
731 schoenebeck 3744 return intExpr ? ToString(intExpr->evalInt()) + _unitToStr(intExpr) : "";
732 schoenebeck 2581 }
733     }
734    
735 schoenebeck 3581 Variable::Variable(const VariableDecl& decl) :
736     context(decl.ctx), memPos(decl.memPos), bConst(decl.isConst)
737 schoenebeck 2581 {
738 schoenebeck 3573 }
739    
740 schoenebeck 3582 NumberVariable::NumberVariable(const VariableDecl& decl) :
741 schoenebeck 3581 Variable(decl),
742     Unit(decl.unitType),
743     unitFactorMemPos(decl.unitFactorMemPos), polyphonic(decl.isPolyphonic),
744     finalVal(decl.isFinal)
745 schoenebeck 3573 {
746 schoenebeck 2581 }
747    
748 schoenebeck 3582 vmfloat NumberVariable::unitFactor() const {
749 schoenebeck 3581 if (isPolyphonic()) {
750     return context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos];
751     }
752     return (*context->globalUnitFactorMemory)[unitFactorMemPos];
753     }
754    
755 schoenebeck 3557 inline static vmint postfixInc(vmint& object, vmint incBy) {
756     const vmint i = object;
757 schoenebeck 2588 object += incBy;
758     return i;
759     }
760    
761 schoenebeck 3581 IntVariable::IntVariable(const VariableDecl& decl) :
762 schoenebeck 3582 NumberVariable({
763 schoenebeck 3581 .ctx = decl.ctx,
764     .isPolyphonic = decl.isPolyphonic,
765     .isConst = decl.isConst,
766     .elements = decl.elements,
767     .memPos = (
768     (!decl.ctx) ? 0 :
769     (decl.isPolyphonic) ?
770     postfixInc(decl.ctx->polyphonicIntVarCount, decl.elements) :
771     postfixInc(decl.ctx->globalIntVarCount, decl.elements)
772     ),
773     .unitFactorMemPos = (
774     (!decl.ctx) ? 0 :
775     (decl.isPolyphonic) ?
776     postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
777     postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
778     ),
779 schoenebeck 3595 .unitType = decl.unitType,
780     .isFinal = decl.isFinal,
781 schoenebeck 3581 }),
782     Unit(decl.unitType)
783 schoenebeck 2581 {
784 schoenebeck 3581 //printf("IntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
785     assert(!decl.isPolyphonic || decl.ctx);
786 schoenebeck 2581 }
787    
788     void IntVariable::assign(Expression* expr) {
789     IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
790 schoenebeck 3034 if (intExpr) {
791 schoenebeck 3581 //NOTE: sequence matters! evalInt() must be called before getting unitFactor() !
792     if (isPolyphonic()) {
793 schoenebeck 2581 context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();
794 schoenebeck 3581 context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = intExpr->unitFactor();
795     } else {
796 schoenebeck 2581 (*context->globalIntMemory)[memPos] = intExpr->evalInt();
797 schoenebeck 3581 (*context->globalUnitFactorMemory)[unitFactorMemPos] = intExpr->unitFactor();
798     }
799 schoenebeck 3034 }
800 schoenebeck 2581 }
801    
802 schoenebeck 3557 vmint IntVariable::evalInt() {
803 schoenebeck 2581 //printf("IntVariable::eval pos=%d\n", memPos);
804 schoenebeck 3573 if (isPolyphonic()) {
805 schoenebeck 2588 //printf("evalInt() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
806 schoenebeck 2581 return context->execContext->polyphonicIntMemory[memPos];
807 schoenebeck 2588 }
808 schoenebeck 2581 return (*context->globalIntMemory)[memPos];
809     }
810    
811     void IntVariable::dump(int level) {
812     printIndents(level);
813 schoenebeck 2945 printf("IntVariable\n");
814 schoenebeck 2588 //printf("IntVariable memPos=%d\n", memPos);
815 schoenebeck 2581 }
816    
817 schoenebeck 3581 RealVariable::RealVariable(const VariableDecl& decl) :
818 schoenebeck 3582 NumberVariable({
819 schoenebeck 3581 .ctx = decl.ctx,
820     .isPolyphonic = decl.isPolyphonic,
821     .isConst = decl.isConst,
822     .elements = decl.elements,
823     .memPos = (
824     (!decl.ctx) ? 0 :
825     (decl.isPolyphonic) ?
826     postfixInc(decl.ctx->polyphonicRealVarCount, decl.elements) :
827     postfixInc(decl.ctx->globalRealVarCount, decl.elements)
828     ),
829     .unitFactorMemPos = (
830     (!decl.ctx) ? 0 :
831     (decl.isPolyphonic) ?
832     postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
833     postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
834     ),
835 schoenebeck 3595 .unitType = decl.unitType,
836     .isFinal = decl.isFinal,
837 schoenebeck 3581 }),
838     Unit(decl.unitType)
839 schoenebeck 3573 {
840 schoenebeck 3581 //printf("RealVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
841     assert(!decl.isPolyphonic || decl.ctx);
842 schoenebeck 3573 }
843    
844     void RealVariable::assign(Expression* expr) {
845     RealExpr* realExpr = dynamic_cast<RealExpr*>(expr);
846     if (realExpr) {
847 schoenebeck 3581 //NOTE: sequence matters! evalReal() must be called before getting unitFactor() !
848     if (isPolyphonic()) {
849 schoenebeck 3573 context->execContext->polyphonicRealMemory[memPos] = realExpr->evalReal();
850 schoenebeck 3581 context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = realExpr->unitFactor();
851     } else {
852 schoenebeck 3573 (*context->globalRealMemory)[memPos] = realExpr->evalReal();
853 schoenebeck 3581 (*context->globalUnitFactorMemory)[unitFactorMemPos] = realExpr->unitFactor();
854     }
855 schoenebeck 3573 }
856     }
857    
858     vmfloat RealVariable::evalReal() {
859     //printf("RealVariable::eval pos=%d\n", memPos);
860     if (isPolyphonic()) {
861     //printf("evalReal() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
862     return context->execContext->polyphonicRealMemory[memPos];
863     }
864     return (*context->globalRealMemory)[memPos];
865     }
866    
867     void RealVariable::dump(int level) {
868     printIndents(level);
869     printf("RealVariable\n");
870     //printf("RealVariable memPos=%d\n", memPos);
871     }
872    
873 schoenebeck 3581 ConstIntVariable::ConstIntVariable(const IntVarDef& def) :
874     IntVariable({
875     .ctx = def.ctx,
876     .isPolyphonic = false,
877     .isConst = true,
878     .elements = 1,
879     .memPos = def.memPos,
880     .unitFactorMemPos = def.unitFactorMemPos,
881 schoenebeck 3595 .unitType = def.unitType,
882     .isFinal = def.isFinal,
883 schoenebeck 3581 }),
884     Unit(def.unitType),
885     value(def.value), unitPrefixFactor(def.unitFactor)
886 schoenebeck 2581 {
887     }
888    
889     void ConstIntVariable::assign(Expression* expr) {
890     // ignore assignment
891     /*
892     printf("ConstIntVariable::assign()\n");
893     IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
894     if (intExpr) {
895     value = intExpr->evalInt();
896     }
897     */
898     }
899    
900 schoenebeck 3557 vmint ConstIntVariable::evalInt() {
901 schoenebeck 2581 return value;
902     }
903    
904     void ConstIntVariable::dump(int level) {
905     printIndents(level);
906 schoenebeck 3707 printf("ConstIntVariable val=%" PRId64 "\n", (int64_t)value);
907 schoenebeck 2581 }
908    
909 schoenebeck 3581 ConstRealVariable::ConstRealVariable(const RealVarDef& def) :
910     RealVariable({
911     .ctx = def.ctx,
912     .isPolyphonic = false,
913     .isConst = true,
914     .elements = 1,
915     .memPos = def.memPos,
916     .unitFactorMemPos = def.unitFactorMemPos,
917 schoenebeck 3595 .unitType = def.unitType,
918     .isFinal = def.isFinal,
919 schoenebeck 3581 }),
920     Unit(def.unitType),
921     value(def.value), unitPrefixFactor(def.unitFactor)
922 schoenebeck 3573 {
923     }
924    
925     void ConstRealVariable::assign(Expression* expr) {
926     // ignore assignment
927     }
928    
929     vmfloat ConstRealVariable::evalReal() {
930     return value;
931     }
932    
933     void ConstRealVariable::dump(int level) {
934     printIndents(level);
935     printf("ConstRealVariable val=%f\n", value);
936     }
937    
938 schoenebeck 3581 BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) :
939     IntVariable({
940     .ctx = NULL,
941     .isPolyphonic = false,
942     .isConst = false, // may or may not be modifyable though!
943     .elements = 0,
944     .memPos = 0,
945     .unitFactorMemPos = 0,
946 schoenebeck 3595 .unitType = VM_NO_UNIT,
947     .isFinal = false,
948 schoenebeck 3581 }),
949     Unit(VM_NO_UNIT),
950     name(name), ptr(ptr)
951 schoenebeck 2594 {
952     }
953    
954     void BuiltInIntVariable::assign(Expression* expr) {
955     IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
956     if (!valueExpr) return;
957     ptr->assign(valueExpr->evalInt());
958     }
959    
960 schoenebeck 3557 vmint BuiltInIntVariable::evalInt() {
961 schoenebeck 2594 return ptr->evalInt();
962     }
963    
964     void BuiltInIntVariable::dump(int level) {
965     printIndents(level);
966     printf("Built-in IntVar '%s'\n", name.c_str());
967     }
968    
969 schoenebeck 3581 PolyphonicIntVariable::PolyphonicIntVariable(const VariableDecl& decl) :
970     IntVariable({
971     .ctx = decl.ctx,
972     .isPolyphonic = true,
973     .isConst = decl.isConst,
974     .elements = 1,
975     .memPos = 0,
976     .unitFactorMemPos = 0,
977 schoenebeck 3595 .unitType = decl.unitType,
978     .isFinal = decl.isFinal,
979 schoenebeck 3581 }),
980     Unit(decl.unitType)
981 schoenebeck 2581 {
982     }
983    
984     void PolyphonicIntVariable::dump(int level) {
985     printIndents(level);
986     printf("PolyphonicIntVariable\n");
987     }
988    
989 schoenebeck 3581 PolyphonicRealVariable::PolyphonicRealVariable(const VariableDecl& decl) :
990     RealVariable({
991     .ctx = decl.ctx,
992     .isPolyphonic = true,
993     .isConst = decl.isConst,
994     .elements = 1,
995     .memPos = 0,
996     .unitFactorMemPos = 0,
997 schoenebeck 3595 .unitType = decl.unitType,
998     .isFinal = decl.isFinal,
999 schoenebeck 3581 }),
1000     Unit(decl.unitType)
1001 schoenebeck 3573 {
1002     }
1003    
1004     void PolyphonicRealVariable::dump(int level) {
1005     printIndents(level);
1006     printf("PolyphonicRealVariable\n");
1007     }
1008    
1009 schoenebeck 3581 IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size) :
1010     Variable({
1011     .ctx = ctx,
1012     .isPolyphonic = false,
1013     .isConst = false,
1014     .elements = 0,
1015     .memPos = 0,
1016     .unitFactorMemPos = 0,
1017 schoenebeck 3595 .unitType = VM_NO_UNIT,
1018     .isFinal = false,
1019 schoenebeck 3581 })
1020 schoenebeck 2581 {
1021     values.resize(size);
1022 schoenebeck 3557 memset(&values[0], 0, size * sizeof(vmint));
1023 schoenebeck 3581
1024     unitFactors.resize(size);
1025     for (size_t i = 0; i < size; ++i)
1026     unitFactors[i] = VM_NO_FACTOR;
1027 schoenebeck 2581 }
1028    
1029 schoenebeck 3581 IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size,
1030     ArgsRef values, bool _bConst) :
1031     Variable({
1032     .ctx = ctx,
1033     .isPolyphonic = false,
1034     .isConst = _bConst,
1035     .elements = 0,
1036     .memPos = 0,
1037     .unitFactorMemPos = 0,
1038 schoenebeck 3595 .unitType = VM_NO_UNIT,
1039     .isFinal = false,
1040 schoenebeck 3581 })
1041 schoenebeck 2581 {
1042     this->values.resize(size);
1043 schoenebeck 3581 this->unitFactors.resize(size);
1044 schoenebeck 3557 for (vmint i = 0; i < values->argsCount(); ++i) {
1045 schoenebeck 2581 VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));
1046 schoenebeck 3581 if (expr) {
1047     this->values[i] = expr->evalInt();
1048     this->unitFactors[i] = expr->unitFactor();
1049     }
1050 schoenebeck 2581 }
1051     }
1052    
1053 schoenebeck 3581 IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst) :
1054     Variable({
1055     .ctx = ctx,
1056     .isPolyphonic = false,
1057     .isConst = bConst,
1058     .elements = 0,
1059     .memPos = 0,
1060     .unitFactorMemPos = 0,
1061 schoenebeck 3595 .unitType = VM_NO_UNIT,
1062     .isFinal = false,
1063 schoenebeck 3581 })
1064 schoenebeck 2594 {
1065     }
1066    
1067 schoenebeck 3557 vmint IntArrayVariable::evalIntElement(vmuint i) {
1068 schoenebeck 2581 if (i >= values.size()) return 0;
1069     return values[i];
1070     }
1071    
1072 schoenebeck 3557 void IntArrayVariable::assignIntElement(vmuint i, vmint value) {
1073 schoenebeck 2581 if (i >= values.size()) return;
1074     values[i] = value;
1075     }
1076    
1077 schoenebeck 3581 vmfloat IntArrayVariable::unitFactorOfElement(vmuint i) const {
1078     if (i >= unitFactors.size()) return VM_NO_FACTOR;
1079     return unitFactors[i];
1080     }
1081    
1082     void IntArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1083     if (i >= unitFactors.size()) return;
1084     unitFactors[i] = factor;
1085     }
1086    
1087 schoenebeck 2581 void IntArrayVariable::dump(int level) {
1088     printIndents(level);
1089     printf("IntArray(");
1090 schoenebeck 3557 for (vmint i = 0; i < values.size(); ++i) {
1091 schoenebeck 2581 if (i % 12 == 0) {
1092     printf("\n");
1093     printIndents(level+1);
1094     }
1095 schoenebeck 3707 printf("%" PRId64 ", ", (int64_t)values[i]);
1096 schoenebeck 2581 }
1097     printIndents(level);
1098     printf(")\n");
1099     }
1100    
1101 schoenebeck 3581 RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size) :
1102     Variable({
1103     .ctx = ctx,
1104     .isPolyphonic = false,
1105     .isConst = false,
1106     .elements = 0,
1107     .memPos = 0,
1108     .unitFactorMemPos = 0,
1109 schoenebeck 3595 .unitType = VM_NO_UNIT,
1110     .isFinal = false,
1111 schoenebeck 3581 })
1112 schoenebeck 3573 {
1113     values.resize(size);
1114     memset(&values[0], 0, size * sizeof(vmfloat));
1115 schoenebeck 3581
1116     unitFactors.resize(size);
1117     for (size_t i = 0; i < size; ++i)
1118     unitFactors[i] = VM_NO_FACTOR;
1119 schoenebeck 3573 }
1120    
1121 schoenebeck 3581 RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size,
1122     ArgsRef values, bool _bConst) :
1123     Variable({
1124     .ctx = ctx,
1125     .isPolyphonic = false,
1126     .isConst = _bConst,
1127     .elements = 0,
1128     .memPos = 0,
1129     .unitFactorMemPos = 0,
1130 schoenebeck 3595 .unitType = VM_NO_UNIT,
1131     .isFinal = false,
1132 schoenebeck 3581 })
1133 schoenebeck 3573 {
1134     this->values.resize(size);
1135 schoenebeck 3581 this->unitFactors.resize(size);
1136 schoenebeck 3573 for (vmint i = 0; i < values->argsCount(); ++i) {
1137     VMRealExpr* expr = dynamic_cast<VMRealExpr*>(values->arg(i));
1138 schoenebeck 3581 if (expr) {
1139     this->values[i] = expr->evalReal();
1140     this->unitFactors[i] = expr->unitFactor();
1141     }
1142 schoenebeck 3573 }
1143     }
1144    
1145 schoenebeck 3581 RealArrayVariable::RealArrayVariable(ParserContext* ctx, bool bConst) :
1146     Variable({
1147     .ctx = ctx,
1148     .isPolyphonic = false,
1149     .isConst = bConst,
1150     .elements = 0,
1151     .memPos = 0,
1152     .unitFactorMemPos = 0,
1153 schoenebeck 3595 .unitType = VM_NO_UNIT,
1154     .isFinal = false,
1155 schoenebeck 3581 })
1156 schoenebeck 3573 {
1157     }
1158    
1159     vmfloat RealArrayVariable::evalRealElement(vmuint i) {
1160     if (i >= values.size()) return 0;
1161     return values[i];
1162     }
1163    
1164     void RealArrayVariable::assignRealElement(vmuint i, vmfloat value) {
1165     if (i >= values.size()) return;
1166     values[i] = value;
1167     }
1168    
1169 schoenebeck 3581 vmfloat RealArrayVariable::unitFactorOfElement(vmuint i) const {
1170     if (i >= unitFactors.size()) return VM_NO_FACTOR;
1171     return unitFactors[i];
1172     }
1173    
1174     void RealArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1175     if (i >= unitFactors.size()) return;
1176     unitFactors[i] = factor;
1177     }
1178    
1179 schoenebeck 3573 void RealArrayVariable::dump(int level) {
1180     printIndents(level);
1181     printf("RealArray(");
1182     for (vmint i = 0; i < values.size(); ++i) {
1183     if (i % 12 == 0) {
1184     printf("\n");
1185     printIndents(level+1);
1186     }
1187     printf("%f, ", values[i]);
1188     }
1189     printIndents(level);
1190     printf(")\n");
1191     }
1192    
1193 schoenebeck 3581 BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name,
1194     VMInt8Array* array) :
1195     IntArrayVariable(NULL, false),
1196     name(name), array(array)
1197 schoenebeck 2594 {
1198     }
1199    
1200 schoenebeck 3557 vmint BuiltInIntArrayVariable::evalIntElement(vmuint i) {
1201 schoenebeck 2594 return i >= array->size ? 0 : array->data[i];
1202     }
1203    
1204 schoenebeck 3557 void BuiltInIntArrayVariable::assignIntElement(vmuint i, vmint value) {
1205 schoenebeck 2594 if (i >= array->size) return;
1206     array->data[i] = value;
1207     }
1208    
1209     void BuiltInIntArrayVariable::dump(int level) {
1210     printIndents(level);
1211     printf("Built-In Int Array Variable '%s'\n", name.c_str());
1212     }
1213    
1214 schoenebeck 3581 IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) :
1215     IntVariable({
1216     .ctx = NULL,
1217     .isPolyphonic = (array) ? array->isPolyphonic() : false,
1218     .isConst = (array) ? array->isConstExpr() : false,
1219     .elements = 0,
1220     .memPos = 0,
1221     .unitFactorMemPos = 0,
1222 schoenebeck 3595 .unitType = VM_NO_UNIT,
1223     .isFinal = false,
1224 schoenebeck 3581 }),
1225     Unit(VM_NO_UNIT),
1226     array(array), index(arrayIndex), currentIndex(-1)
1227 schoenebeck 3595 {
1228 schoenebeck 2581 }
1229    
1230     void IntArrayElement::assign(Expression* expr) {
1231     IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
1232     if (!valueExpr) return;
1233 schoenebeck 3557 vmint value = valueExpr->evalInt();
1234 schoenebeck 3581 vmfloat unitFactor = valueExpr->unitFactor();
1235 schoenebeck 2581
1236     if (!index) return;
1237 schoenebeck 3581 vmint idx = currentIndex = index->evalInt();
1238 schoenebeck 2581 if (idx < 0 || idx >= array->arraySize()) return;
1239    
1240     array->assignIntElement(idx, value);
1241 schoenebeck 3581 array->assignElementUnitFactor(idx, unitFactor);
1242 schoenebeck 2581 }
1243    
1244 schoenebeck 3557 vmint IntArrayElement::evalInt() {
1245 schoenebeck 2581 if (!index) return 0;
1246 schoenebeck 3581 vmint idx = currentIndex = index->evalInt();
1247 schoenebeck 2581 if (idx < 0 || idx >= array->arraySize()) return 0;
1248    
1249     return array->evalIntElement(idx);
1250     }
1251    
1252 schoenebeck 3581 vmfloat IntArrayElement::unitFactor() const {
1253     if (!index) return VM_NO_FACTOR;
1254     vmint idx = currentIndex;
1255     if (idx < 0 || idx >= array->arraySize()) return 0;
1256    
1257     return array->unitFactorOfElement(idx);
1258     }
1259    
1260 schoenebeck 2581 void IntArrayElement::dump(int level) {
1261     printIndents(level);
1262     printf("IntArrayElement\n");
1263     }
1264    
1265 schoenebeck 3581 RealArrayElement::RealArrayElement(RealArrayExprRef array, IntExprRef arrayIndex) :
1266     RealVariable({
1267     .ctx = NULL,
1268     .isPolyphonic = (array) ? array->isPolyphonic() : false,
1269     .isConst = (array) ? array->isConstExpr() : false,
1270     .elements = 0,
1271     .memPos = 0,
1272     .unitFactorMemPos = 0,
1273 schoenebeck 3595 .unitType = VM_NO_UNIT,
1274     .isFinal = false,
1275 schoenebeck 3581 }),
1276     Unit(VM_NO_UNIT),
1277     array(array), index(arrayIndex), currentIndex(-1)
1278 schoenebeck 3573 {
1279     }
1280    
1281     void RealArrayElement::assign(Expression* expr) {
1282     RealExpr* valueExpr = dynamic_cast<RealExpr*>(expr);
1283     if (!valueExpr) return;
1284     vmfloat value = valueExpr->evalReal();
1285 schoenebeck 3581 vmfloat unitFactor = valueExpr->unitFactor();
1286 schoenebeck 3573
1287     if (!index) return;
1288 schoenebeck 3581 vmint idx = currentIndex = index->evalInt();
1289 schoenebeck 3573 if (idx < 0 || idx >= array->arraySize()) return;
1290    
1291     array->assignRealElement(idx, value);
1292 schoenebeck 3581 array->assignElementUnitFactor(idx, unitFactor);
1293 schoenebeck 3573 }
1294    
1295     vmfloat RealArrayElement::evalReal() {
1296     if (!index) return 0;
1297 schoenebeck 3581 vmint idx = currentIndex = index->evalInt();
1298 schoenebeck 3573 if (idx < 0 || idx >= array->arraySize()) return 0;
1299    
1300     return array->evalRealElement(idx);
1301     }
1302    
1303 schoenebeck 3581 vmfloat RealArrayElement::unitFactor() const {
1304     if (!index) return VM_NO_FACTOR;
1305     vmint idx = currentIndex;
1306     if (idx < 0 || idx >= array->arraySize()) return 0;
1307    
1308     return array->unitFactorOfElement(idx);
1309     }
1310    
1311 schoenebeck 3573 void RealArrayElement::dump(int level) {
1312     printIndents(level);
1313     printf("RealArrayElement\n");
1314     }
1315    
1316 schoenebeck 3581 StringVariable::StringVariable(ParserContext* ctx) :
1317     Variable({
1318     .ctx = ctx,
1319     .elements = 1,
1320     .memPos = ctx->globalStrVarCount++
1321     })
1322 schoenebeck 2581 {
1323     }
1324    
1325 schoenebeck 3581 StringVariable::StringVariable(ParserContext* ctx, bool bConst) :
1326     Variable({
1327     .ctx = ctx,
1328 schoenebeck 3595 .isConst = bConst,
1329 schoenebeck 3581 .memPos = 0,
1330     })
1331 schoenebeck 2581 {
1332     }
1333    
1334     void StringVariable::assign(Expression* expr) {
1335     StringExpr* strExpr = dynamic_cast<StringExpr*>(expr);
1336     (*context->globalStrMemory)[memPos] = strExpr->evalStr();
1337     }
1338    
1339     String StringVariable::evalStr() {
1340     //printf("StringVariable::eval pos=%d\n", memPos);
1341     return (*context->globalStrMemory)[memPos];
1342     }
1343    
1344     void StringVariable::dump(int level) {
1345     printIndents(level);
1346 schoenebeck 3707 printf("StringVariable memPos=%" PRId64 "\n", (int64_t)memPos);
1347 schoenebeck 2581 }
1348    
1349     ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)
1350     : StringVariable(ctx,true), value(_value)
1351     {
1352     }
1353    
1354     void ConstStringVariable::assign(Expression* expr) {
1355     // ignore assignment
1356     // StringExpr* strExpr = dynamic_cast<StringExpr*>(expr);
1357     // if (strExpr) value = strExpr->evalStr();
1358     }
1359    
1360     String ConstStringVariable::evalStr() {
1361     return value;
1362     }
1363    
1364     void ConstStringVariable::dump(int level) {
1365     printIndents(level);
1366     printf("ConstStringVariable val='%s'\n", value.c_str());
1367     }
1368    
1369 schoenebeck 3582 bool NumberBinaryOp::isFinal() const {
1370     NumberExprRef l = (NumberExprRef) lhs;
1371     NumberExprRef r = (NumberExprRef) rhs;
1372 schoenebeck 3561 return l->isFinal() || r->isFinal();
1373     }
1374    
1375 schoenebeck 3573 ExprType_t VaritypeScalarBinaryOp::exprType() const {
1376     return (lhs->exprType() == REAL_EXPR || rhs->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
1377     }
1378    
1379     String VaritypeScalarBinaryOp::evalCastToStr() {
1380     return (exprType() == REAL_EXPR) ?
1381     RealExpr::evalCastToStr() : IntExpr::evalCastToStr();
1382     }
1383    
1384 schoenebeck 2581 void If::dump(int level) {
1385     printIndents(level);
1386     if (ifStatements && elseStatements)
1387     printf("if cond stmts1 else stmts2 end if\n");
1388     else if (ifStatements)
1389     printf("if cond statements end if\n");
1390     else
1391     printf("if [INVALID]\n");
1392     }
1393    
1394 schoenebeck 3557 vmint If::evalBranch() {
1395 schoenebeck 2581 if (condition->evalInt()) return 0;
1396     if (elseStatements) return 1;
1397     return -1;
1398     }
1399    
1400 schoenebeck 3557 Statements* If::branch(vmuint i) const {
1401 schoenebeck 2581 if (i == 0) return (Statements*) &*ifStatements;
1402     if (i == 1) return (elseStatements) ? (Statements*) &*elseStatements : NULL;
1403     return NULL;
1404     }
1405    
1406 schoenebeck 2645 bool If::isPolyphonic() const {
1407     if (condition->isPolyphonic() || ifStatements->isPolyphonic())
1408     return true;
1409     return elseStatements ? elseStatements->isPolyphonic() : false;
1410     }
1411    
1412 schoenebeck 2581 void SelectCase::dump(int level) {
1413     printIndents(level);
1414     if (select)
1415     if (select->isConstExpr())
1416 schoenebeck 3707 printf("Case select %" PRId64 "\n", (int64_t)select->evalInt());
1417 schoenebeck 2581 else
1418     printf("Case select [runtime expr]\n");
1419     else
1420     printf("Case select NULL\n");
1421 schoenebeck 3557 for (vmint i = 0; i < branches.size(); ++i) {
1422 schoenebeck 2581 printIndents(level+1);
1423     CaseBranch& branch = branches[i];
1424     if (branch.from && branch.to)
1425     if (branch.from->isConstExpr() && branch.to->isConstExpr())
1426 schoenebeck 3707 printf("case %" PRId64 " to %" PRId64 "\n", (int64_t)branch.from->evalInt(), (int64_t)branch.to->evalInt());
1427 schoenebeck 2581 else if (branch.from->isConstExpr() && !branch.to->isConstExpr())
1428 schoenebeck 3707 printf("case %" PRId64 " to [runtime expr]\n", (int64_t)branch.from->evalInt());
1429 schoenebeck 2581 else if (!branch.from->isConstExpr() && branch.to->isConstExpr())
1430 schoenebeck 3707 printf("case [runtime expr] to %" PRId64 "\n", (int64_t)branch.to->evalInt());
1431 schoenebeck 2581 else
1432     printf("case [runtime expr] to [runtime expr]\n");
1433     else if (branch.from)
1434     if (branch.from->isConstExpr())
1435 schoenebeck 3707 printf("case %" PRId64 "\n", (int64_t)branch.from->evalInt());
1436 schoenebeck 2581 else
1437     printf("case [runtime expr]\n");
1438     else
1439     printf("case NULL\n");
1440     }
1441     }
1442    
1443 schoenebeck 3557 vmint SelectCase::evalBranch() {
1444     vmint value = select->evalInt();
1445     for (vmint i = 0; i < branches.size(); ++i) {
1446 schoenebeck 2581 if (branches.at(i).from && branches.at(i).to) { // i.e. "case 4 to 7" ...
1447     if (branches.at(i).from->evalInt() <= value &&
1448     branches.at(i).to->evalInt() >= value) return i;
1449     } else { // i.e. "case 5" ...
1450     if (branches.at(i).from->evalInt() == value) return i;
1451     }
1452     }
1453     return -1;
1454     }
1455    
1456 schoenebeck 3557 Statements* SelectCase::branch(vmuint i) const {
1457 schoenebeck 2581 if (i < branches.size())
1458     return const_cast<Statements*>( &*branches[i].statements );
1459     return NULL;
1460     }
1461    
1462 schoenebeck 2645 bool SelectCase::isPolyphonic() const {
1463     if (select->isPolyphonic()) return true;
1464 schoenebeck 3557 for (vmint i = 0; i < branches.size(); ++i)
1465 schoenebeck 2645 if (branches[i].statements->isPolyphonic())
1466     return true;
1467     return false;
1468     }
1469    
1470 schoenebeck 2581 void While::dump(int level) {
1471     printIndents(level);
1472     if (m_condition)
1473     if (m_condition->isConstExpr())
1474 schoenebeck 3707 printf("while (%" PRId64 ") {\n", (int64_t)m_condition->evalInt());
1475 schoenebeck 2581 else
1476     printf("while ([runtime expr]) {\n");
1477     else
1478     printf("while ([INVALID]) {\n");
1479     m_statements->dump(level+1);
1480     printIndents(level);
1481     printf("}\n");
1482     }
1483    
1484     Statements* While::statements() const {
1485     return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1486     }
1487    
1488     bool While::evalLoopStartCondition() {
1489     if (!m_condition) return false;
1490     return m_condition->evalInt();
1491     }
1492    
1493 schoenebeck 3260 void SyncBlock::dump(int level) {
1494     printIndents(level);
1495     printf("sync {\n");
1496     m_statements->dump(level+1);
1497     printIndents(level);
1498     printf("}\n");
1499     }
1500    
1501     Statements* SyncBlock::statements() const {
1502     return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1503     }
1504    
1505 schoenebeck 3576 String Neg::evalCastToStr() {
1506     return expr->evalCastToStr();
1507     }
1508    
1509 schoenebeck 2581 void Neg::dump(int level) {
1510     printIndents(level);
1511     printf("Negative Expr\n");
1512     }
1513    
1514     String ConcatString::evalStr() {
1515 schoenebeck 2945 // temporaries required here to enforce the associative left (to right) order
1516 schoenebeck 2948 // ( required for GCC and Visual Studio, see:
1517     // http://stackoverflow.com/questions/25842902/why-stdstring-concatenation-operator-works-like-right-associative-one
1518     // Personally I am not convinced that this is "not a bug" of the
1519     // compiler/STL implementation and the allegedly underlying "function call"
1520     // nature causing this is IMO no profound reason that the C++ language's
1521     // "+" operator's left associativity is ignored. -- Christian, 2016-07-14 )
1522 schoenebeck 2945 String l = lhs->evalCastToStr();
1523     String r = rhs->evalCastToStr();
1524     return l + r;
1525 schoenebeck 2581 }
1526    
1527     void ConcatString::dump(int level) {
1528     printIndents(level);
1529     printf("ConcatString(\n");
1530     lhs->dump(level+1);
1531     printIndents(level);
1532     printf(",\n");
1533     rhs->dump(level+1);
1534     printIndents(level);
1535     printf(")");
1536     }
1537    
1538     bool ConcatString::isConstExpr() const {
1539     return lhs->isConstExpr() && rhs->isConstExpr();
1540     }
1541    
1542 schoenebeck 3581 Relation::Relation(ExpressionRef lhs, Type type, ExpressionRef rhs) :
1543     Unit(VM_NO_UNIT),
1544     lhs(lhs), rhs(rhs), type(type)
1545     {
1546     }
1547    
1548     // Equal / unequal comparison of real numbers in NKSP scripts:
1549     //
1550     // Unlike system level languages like C/C++ we are less conservative about
1551     // comparing floating point numbers for 'equalness' or 'unequalness' in NKSP
1552     // scripts. Due to the musical context of the NKSP language we automatically
1553     // take the (to be) expected floating point tolerances into account when
1554     // comparing two floating point numbers with each other, however only for '='
1555     // and '#' operators. The '<=' and '>=' still use conservative low level
1556     // floating point comparison for not breaking their transitivity feature.
1557    
1558     template<typename T_LHS, typename T_RHS>
1559     struct RelComparer {
1560     static inline bool isEqual(T_LHS a, T_RHS b) { // for int comparison ('3 = 3')
1561     return a == b;
1562     }
1563     static inline bool isUnequal(T_LHS a, T_RHS b) { // for int comparison ('3 # 3')
1564     return a != b;
1565     }
1566     };
1567    
1568     template<>
1569     struct RelComparer<float,float> {
1570     static inline bool isEqual(float a, float b) { // for real number comparison ('3.1 = 3.1')
1571     return RTMath::fEqual32(a, b);
1572     }
1573     static inline bool isUnequal(float a, float b) { // for real number comparison ('3.1 # 3.1')
1574     return !RTMath::fEqual32(a, b);
1575     }
1576     };
1577    
1578     template<>
1579     struct RelComparer<double,double> {
1580     static inline bool isEqual(double a, double b) { // for future purpose
1581     return RTMath::fEqual64(a, b);
1582     }
1583     static inline bool isUnqqual(double a, double b) { // for future purpose
1584     return !RTMath::fEqual64(a, b);
1585     }
1586     };
1587    
1588 schoenebeck 3573 template<class T_LHS, class T_RHS>
1589 schoenebeck 3581 inline vmint _evalRelation(Relation::Type type, T_LHS lhs, T_RHS rhs) {
1590 schoenebeck 3573 switch (type) {
1591     case Relation::LESS_THAN:
1592     return lhs < rhs;
1593     case Relation::GREATER_THAN:
1594     return lhs > rhs;
1595     case Relation::LESS_OR_EQUAL:
1596     return lhs <= rhs;
1597     case Relation::GREATER_OR_EQUAL:
1598     return lhs >= rhs;
1599     case Relation::EQUAL:
1600 schoenebeck 3581 return RelComparer<typeof(lhs),typeof(rhs)>::isEqual(lhs, rhs);
1601 schoenebeck 3573 case Relation::NOT_EQUAL:
1602 schoenebeck 3581 return RelComparer<typeof(lhs),typeof(rhs)>::isUnequal(lhs, rhs);
1603 schoenebeck 3573 }
1604     return 0;
1605     }
1606    
1607 schoenebeck 3581 template<class T_LVALUE, class T_RVALUE, class T_LEXPR, class T_REXPR>
1608     inline vmint _evalRealRelation(Relation::Type type,
1609     T_LVALUE lvalue, T_RVALUE rvalue,
1610     T_LEXPR* pLHS, T_REXPR* pRHS)
1611     {
1612     if (pLHS->unitFactor() == pRHS->unitFactor())
1613     return _evalRelation(type, lvalue, rvalue);
1614     if (pLHS->unitFactor() < pRHS->unitFactor())
1615     return _evalRelation(type, lvalue, Unit::convRealToUnitFactor(rvalue, pRHS, pLHS));
1616     else
1617     return _evalRelation(type, Unit::convRealToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1618     }
1619    
1620     template<class T_LEXPR, class T_REXPR>
1621     inline vmint _evalIntRelation(Relation::Type type,
1622     vmint lvalue, vmint rvalue,
1623     T_LEXPR* pLHS, T_REXPR* pRHS)
1624     {
1625     if (pLHS->unitFactor() == pRHS->unitFactor())
1626     return _evalRelation(type, lvalue, rvalue);
1627     if (pLHS->unitFactor() < pRHS->unitFactor())
1628     return _evalRelation(type, lvalue, Unit::convIntToUnitFactor(rvalue, pRHS, pLHS));
1629     else
1630     return _evalRelation(type, Unit::convIntToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1631     }
1632    
1633 schoenebeck 3557 vmint Relation::evalInt() {
1634 schoenebeck 3573 const ExprType_t lType = lhs->exprType();
1635     const ExprType_t rType = rhs->exprType();
1636     if (lType == STRING_EXPR || rType == STRING_EXPR) {
1637     switch (type) {
1638     case EQUAL:
1639 schoenebeck 2581 return lhs->evalCastToStr() == rhs->evalCastToStr();
1640 schoenebeck 3573 case NOT_EQUAL:
1641 schoenebeck 2581 return lhs->evalCastToStr() != rhs->evalCastToStr();
1642 schoenebeck 3573 default:
1643     return 0;
1644     }
1645     } else if (lType == REAL_EXPR && rType == REAL_EXPR) {
1646 schoenebeck 3581 vmfloat lvalue = lhs->asReal()->evalReal();
1647     vmfloat rvalue = rhs->asReal()->evalReal();
1648     return _evalRealRelation(
1649     type, lvalue, rvalue, lhs->asReal(), rhs->asReal()
1650 schoenebeck 3573 );
1651     } else if (lType == REAL_EXPR && rType == INT_EXPR) {
1652 schoenebeck 3581 vmfloat lvalue = lhs->asReal()->evalReal();
1653     vmint rvalue = rhs->asInt()->evalInt();
1654     return _evalRealRelation(
1655     type, lvalue, rvalue, lhs->asReal(), rhs->asInt()
1656 schoenebeck 3573 );
1657     } else if (lType == INT_EXPR && rType == REAL_EXPR) {
1658 schoenebeck 3581 vmint lvalue = lhs->asInt()->evalInt();
1659     vmfloat rvalue = rhs->asReal()->evalReal();
1660     return _evalRealRelation(
1661     type, lvalue, rvalue, lhs->asInt(), rhs->asReal()
1662 schoenebeck 3573 );
1663     } else {
1664 schoenebeck 3581 vmint lvalue = lhs->asInt()->evalInt();
1665     vmint rvalue = rhs->asInt()->evalInt();
1666     return _evalIntRelation(
1667     type, lvalue, rvalue, lhs->asInt(), rhs->asInt()
1668 schoenebeck 3573 );
1669 schoenebeck 2581 }
1670     }
1671    
1672     void Relation::dump(int level) {
1673     printIndents(level);
1674     printf("Relation(\n");
1675     lhs->dump(level+1);
1676     printIndents(level);
1677     switch (type) {
1678     case LESS_THAN:
1679     printf("LESS_THAN\n");
1680     break;
1681     case GREATER_THAN:
1682     printf("GREATER_THAN\n");
1683     break;
1684     case LESS_OR_EQUAL:
1685     printf("LESS_OR_EQUAL\n");
1686     break;
1687     case GREATER_OR_EQUAL:
1688     printf("GREATER_OR_EQUAL\n");
1689     break;
1690     case EQUAL:
1691     printf("EQUAL\n");
1692     break;
1693     case NOT_EQUAL:
1694     printf("NOT_EQUAL\n");
1695     break;
1696     }
1697     rhs->dump(level+1);
1698     printIndents(level);
1699     printf(")\n");
1700     }
1701    
1702     bool Relation::isConstExpr() const {
1703     return lhs->isConstExpr() && rhs->isConstExpr();
1704     }
1705    
1706 schoenebeck 3557 vmint Or::evalInt() {
1707 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1708 schoenebeck 2611 if (pLHS->evalInt()) return 1;
1709 schoenebeck 3581 IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1710 schoenebeck 2611 return (pRHS->evalInt()) ? 1 : 0;
1711 schoenebeck 2581 }
1712    
1713     void Or::dump(int level) {
1714     printIndents(level);
1715     printf("Or(\n");
1716     lhs->dump(level+1);
1717     printIndents(level);
1718     printf(",\n");
1719     rhs->dump(level+1);
1720     printIndents(level);
1721     printf(")\n");
1722     }
1723    
1724 schoenebeck 3557 vmint BitwiseOr::evalInt() {
1725 schoenebeck 2935 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1726     IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1727     return pLHS->evalInt() | pRHS->evalInt();
1728     }
1729    
1730     void BitwiseOr::dump(int level) {
1731     printIndents(level);
1732     printf("BitwiseOr(\n");
1733     lhs->dump(level+1);
1734     printIndents(level);
1735     printf(",\n");
1736     rhs->dump(level+1);
1737     printIndents(level);
1738     printf(")\n");
1739     }
1740    
1741 schoenebeck 3557 vmint And::evalInt() {
1742 schoenebeck 2581 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1743 schoenebeck 2611 if (!pLHS->evalInt()) return 0;
1744     IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1745     return (pRHS->evalInt()) ? 1 : 0;
1746 schoenebeck 2581 }
1747    
1748     void And::dump(int level) {
1749     printIndents(level);
1750     printf("And(\n");
1751     lhs->dump(level+1);
1752     printIndents(level);
1753     printf(",\n");
1754     rhs->dump(level+1);
1755     printIndents(level);
1756     printf(")\n");
1757     }
1758    
1759 schoenebeck 3557 vmint BitwiseAnd::evalInt() {
1760 schoenebeck 2935 IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1761     IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1762     return pLHS->evalInt() & pRHS->evalInt();
1763     }
1764    
1765     void BitwiseAnd::dump(int level) {
1766     printIndents(level);
1767     printf("BitwiseAnd(\n");
1768     lhs->dump(level+1);
1769     printIndents(level);
1770     printf(",\n");
1771     rhs->dump(level+1);
1772     printIndents(level);
1773     printf(")\n");
1774     }
1775    
1776 schoenebeck 2581 void Not::dump(int level) {
1777     printIndents(level);
1778     printf("Not(\n");
1779     expr->dump(level+1);
1780     printIndents(level);
1781     printf(")\n");
1782     }
1783    
1784 schoenebeck 2935 void BitwiseNot::dump(int level) {
1785     printIndents(level);
1786     printf("BitwiseNot(\n");
1787     expr->dump(level+1);
1788     printIndents(level);
1789     printf(")\n");
1790     }
1791    
1792 schoenebeck 3573 String Final::evalCastToStr() {
1793     if (exprType() == REAL_EXPR)
1794     return ToString(evalReal());
1795     else
1796     return ToString(evalInt());
1797     }
1798    
1799 schoenebeck 3561 void Final::dump(int level) {
1800     printIndents(level);
1801     printf("Final(\n");
1802     expr->dump(level+1);
1803     printIndents(level);
1804     printf(")\n");
1805     }
1806    
1807 schoenebeck 2951 StatementsRef ParserContext::userFunctionByName(const String& name) {
1808     if (!userFnTable.count(name)) {
1809     return StatementsRef();
1810     }
1811     return userFnTable.find(name)->second;
1812     }
1813    
1814 schoenebeck 2581 VariableRef ParserContext::variableByName(const String& name) {
1815     if (!vartable.count(name)) {
1816     return VariableRef();
1817     }
1818     return vartable.find(name)->second;
1819     }
1820    
1821     VariableRef ParserContext::globalVar(const String& name) {
1822     if (!vartable.count(name)) {
1823     //printf("No global var '%s'\n", name.c_str());
1824     //for (std::map<String,VariableRef>::const_iterator it = vartable.begin(); it != vartable.end(); ++it)
1825     // printf("-> var '%s'\n", it->first.c_str());
1826     return VariableRef();
1827     }
1828     return vartable.find(name)->second;
1829     }
1830    
1831     IntVariableRef ParserContext::globalIntVar(const String& name) {
1832     return globalVar(name);
1833     }
1834    
1835 schoenebeck 3573 RealVariableRef ParserContext::globalRealVar(const String& name) {
1836     return globalVar(name);
1837     }
1838    
1839 schoenebeck 2581 StringVariableRef ParserContext::globalStrVar(const String& name) {
1840     return globalVar(name);
1841     }
1842    
1843 schoenebeck 2588 ParserContext::~ParserContext() {
1844     destroyScanner();
1845     if (globalIntMemory) {
1846     delete globalIntMemory;
1847     globalIntMemory = NULL;
1848     }
1849 schoenebeck 3573 if (globalRealMemory) {
1850     delete globalRealMemory;
1851     globalRealMemory = NULL;
1852     }
1853 schoenebeck 2588 }
1854    
1855 schoenebeck 3729 void ParserContext::addErr(int firstLine, int lastLine, int firstColumn,
1856     int lastColumn, int firstByte, int lengthBytes,
1857     const char* txt)
1858     {
1859 schoenebeck 2581 ParserIssue e;
1860     e.type = PARSER_ERROR;
1861     e.txt = txt;
1862 schoenebeck 2889 e.firstLine = firstLine;
1863     e.lastLine = lastLine;
1864     e.firstColumn = firstColumn;
1865     e.lastColumn = lastColumn;
1866 schoenebeck 3729 e.firstByte = firstByte;
1867     e.lengthBytes = lengthBytes;
1868 schoenebeck 2588 vErrors.push_back(e);
1869     vIssues.push_back(e);
1870 schoenebeck 2581 }
1871    
1872 schoenebeck 3729 void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn,
1873     int lastColumn, int firstByte, int lengthBytes,
1874     const char* txt)
1875     {
1876 schoenebeck 2581 ParserIssue w;
1877     w.type = PARSER_WARNING;
1878     w.txt = txt;
1879 schoenebeck 2889 w.firstLine = firstLine;
1880     w.lastLine = lastLine;
1881     w.firstColumn = firstColumn;
1882     w.lastColumn = lastColumn;
1883 schoenebeck 3729 w.firstByte = firstByte;
1884     w.lengthBytes = lengthBytes;
1885 schoenebeck 2588 vWarnings.push_back(w);
1886     vIssues.push_back(w);
1887 schoenebeck 2581 }
1888    
1889 schoenebeck 3729 void ParserContext::addPreprocessorComment(int firstLine, int lastLine,
1890     int firstColumn, int lastColumn,
1891     int firstByte, int lengthBytes)
1892     {
1893 schoenebeck 3285 CodeBlock block;
1894     block.firstLine = firstLine;
1895     block.lastLine = lastLine;
1896     block.firstColumn = firstColumn;
1897     block.lastColumn = lastColumn;
1898 schoenebeck 3729 block.firstByte = firstByte;
1899     block.lengthBytes = lengthBytes;
1900 schoenebeck 3285 vPreprocessorComments.push_back(block);
1901     }
1902    
1903 schoenebeck 2581 bool ParserContext::setPreprocessorCondition(const char* name) {
1904     if (builtinPreprocessorConditions.count(name)) return false;
1905     if (userPreprocessorConditions.count(name)) return false;
1906     userPreprocessorConditions.insert(name);
1907     return true;
1908     }
1909    
1910     bool ParserContext::resetPreprocessorCondition(const char* name) {
1911     if (builtinPreprocessorConditions.count(name)) return false;
1912     if (!userPreprocessorConditions.count(name)) return false;
1913     userPreprocessorConditions.erase(name);
1914     return true;
1915     }
1916    
1917     bool ParserContext::isPreprocessorConditionSet(const char* name) {
1918     if (builtinPreprocessorConditions.count(name)) return true;
1919     return userPreprocessorConditions.count(name);
1920     }
1921    
1922 schoenebeck 2588 std::vector<ParserIssue> ParserContext::issues() const {
1923     return vIssues;
1924     }
1925    
1926     std::vector<ParserIssue> ParserContext::errors() const {
1927     return vErrors;
1928     }
1929    
1930     std::vector<ParserIssue> ParserContext::warnings() const {
1931     return vWarnings;
1932     }
1933    
1934 schoenebeck 3285 std::vector<CodeBlock> ParserContext::preprocessorComments() const {
1935     return vPreprocessorComments;
1936     }
1937    
1938 schoenebeck 2588 VMEventHandler* ParserContext::eventHandler(uint index) {
1939     if (!handlers) return NULL;
1940     return handlers->eventHandler(index);
1941     }
1942    
1943     VMEventHandler* ParserContext::eventHandlerByName(const String& name) {
1944     if (!handlers) return NULL;
1945     return handlers->eventHandlerByName(name);
1946     }
1947    
1948 schoenebeck 3557 void ParserContext::registerBuiltInConstIntVariables(const std::map<String,vmint>& vars) {
1949     for (std::map<String,vmint>::const_iterator it = vars.begin();
1950 schoenebeck 2594 it != vars.end(); ++it)
1951     {
1952 schoenebeck 3581 ConstIntVariableRef ref = new ConstIntVariable({
1953     .value = it->second
1954     });
1955 schoenebeck 2594 vartable[it->first] = ref;
1956     }
1957     }
1958    
1959 schoenebeck 3590 void ParserContext::registerBuiltInConstRealVariables(const std::map<String,vmfloat>& vars) {
1960     for (std::map<String,vmfloat>::const_iterator it = vars.begin();
1961     it != vars.end(); ++it)
1962     {
1963     ConstRealVariableRef ref = new ConstRealVariable({
1964     .value = it->second
1965     });
1966     vartable[it->first] = ref;
1967     }
1968     }
1969    
1970 schoenebeck 3557 void ParserContext::registerBuiltInIntVariables(const std::map<String,VMIntPtr*>& vars) {
1971     for (std::map<String,VMIntPtr*>::const_iterator it = vars.begin();
1972 schoenebeck 2594 it != vars.end(); ++it)
1973     {
1974     BuiltInIntVariableRef ref = new BuiltInIntVariable(it->first, it->second);
1975     vartable[it->first] = ref;
1976     }
1977     }
1978    
1979     void ParserContext::registerBuiltInIntArrayVariables(const std::map<String,VMInt8Array*>& vars) {
1980     for (std::map<String,VMInt8Array*>::const_iterator it = vars.begin();
1981     it != vars.end(); ++it)
1982     {
1983     BuiltInIntArrayVariableRef ref = new BuiltInIntArrayVariable(it->first, it->second);
1984     vartable[it->first] = ref;
1985     }
1986     }
1987    
1988 schoenebeck 2942 void ParserContext::registerBuiltInDynVariables(const std::map<String,VMDynVar*>& vars) {
1989     for (std::map<String,VMDynVar*>::const_iterator it = vars.begin();
1990     it != vars.end(); ++it)
1991     {
1992     DynamicVariableCallRef ref = new DynamicVariableCall(it->first, this, it->second);
1993     vartable[it->first] = ref;
1994     }
1995     }
1996    
1997 schoenebeck 3551 ExecContext::ExecContext() :
1998     status(VM_EXEC_NOT_RUNNING), flags(STMT_SUCCESS), stackFrame(-1),
1999     suspendMicroseconds(0), instructionsCount(0)
2000     {
2001     exitRes.value = NULL;
2002     }
2003    
2004 schoenebeck 3293 void ExecContext::forkTo(VMExecContext* ectx) const {
2005     ExecContext* child = dynamic_cast<ExecContext*>(ectx);
2006    
2007     child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory);
2008 schoenebeck 3573 child->polyphonicRealMemory.copyFlatFrom(polyphonicRealMemory);
2009 schoenebeck 3293 child->status = VM_EXEC_SUSPENDED;
2010     child->flags = STMT_SUCCESS;
2011     child->stack.copyFlatFrom(stack);
2012     child->stackFrame = stackFrame;
2013     child->suspendMicroseconds = 0;
2014     child->instructionsCount = 0;
2015     }
2016    
2017 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC