/[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 3846 - (hide annotations) (download)
Wed Jan 6 14:01:11 2021 UTC (3 years, 3 months ago) by schoenebeck
File size: 61905 byte(s)
* ScriptVM: Fixed crash when handling array results of built-in
  functions (e.g. "num_elements(by_marks($MARK_1)").

* Bumped version (2.1.1.svn69).

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

  ViewVC Help
Powered by ViewVC