/[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 3845 - (hide annotations) (download)
Tue Jan 5 20:42:32 2021 UTC (3 years, 4 months ago) by schoenebeck
File size: 61189 byte(s)
* ScriptVM: Fixed incorrect polyphonic data transfer from wrong "note"
  handler to "release" handler; which also fixes no "release" handler
  being executed sometimes, and due to the latter it also fixes potential
  crashes as some polyphonic script events were never released and the
  engine hence was running out of free script events.

* Bumped version (2.1.1.svn68).

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

  ViewVC Help
Powered by ViewVC