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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.2942  
changed lines
  Added in v.3744

  ViewVC Help
Powered by ViewVC