/[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 3257 by schoenebeck, Tue May 30 17:20:02 2017 UTC revision 3747 by schoenebeck, Sun Feb 16 11:31:46 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    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 IntArrayExpr::evalCastToStr() {  String RealArrayExpr::evalCastToStr() {
168      String s = "{";      String s = "{";
169      for (int i = 0; i < arraySize(); ++i) {      for (vmint i = 0; i < arraySize(); ++i) {
170          int val = evalIntElement(i);          vmfloat val = evalRealElement(i);
171            vmfloat factor = unitFactorOfElement(i);
172          if (i) s += ",";          if (i) s += ",";
173          s += ToString(val);          s += ToString(val) + _unitFactorToShortStr(factor);
174      }      }
175      s += "}";      s += "}";
176      return s;      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  int IntLiteral::evalInt() {  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 60  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 77  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 94  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 111  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      if (!pLHS || !pRHS) return 0;      if (!pLHS || !pRHS) return 0;
380      int l = pLHS->evalInt();      vmint l = pLHS->evalInt();
381      int r = pRHS->evalInt();      vmint r = pRHS->evalInt();
382      if (r == 0) return 0;      if (r == 0) return 0;
383      return l / r;      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) {
397      printIndents(level);      printIndents(level);
398      printf("Div(\n");      printf("Div(\n");
# Line 132  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 160  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 188  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 200  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 252  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 289  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),
580        result( (fn) ? fn->allocResult(dynamic_cast<VMFnArgs*>(&*args)) : NULL )
581    {
582    }
583    
584    FunctionCall::~FunctionCall() {
585        if (result) {
586            delete result;
587            result = NULL;
588        }
589    }
590    
591  void FunctionCall::dump(int level) {  void FunctionCall::dump(int level) {
592      printIndents(level);      printIndents(level);
593      printf("FunctionCall '%s' args={\n", functionName.c_str());      printf("FunctionCall '%s' args={\n", functionName.c_str());
# Line 299  void FunctionCall::dump(int level) { Line 598  void FunctionCall::dump(int level) {
598    
599  ExprType_t FunctionCall::exprType() const {  ExprType_t FunctionCall::exprType() const {
600      if (!fn) return EMPTY_EXPR;      if (!fn) return EMPTY_EXPR;
601      return fn->returnType();      FunctionCall* self = const_cast<FunctionCall*>(this);
602        return fn->returnType(dynamic_cast<VMFnArgs*>(&*self->args));
603    }
604    
605    vmfloat FunctionCall::unitFactor() const {
606        if (!fn || !result) return VM_NO_FACTOR;
607        VMExpr* expr = result->resultValue();
608        if (!expr) return VM_NO_FACTOR;
609        VMNumberExpr* scalar = expr->asNumber();
610        if (!scalar) return VM_NO_FACTOR;
611        return scalar->unitFactor();
612    }
613    
614    bool FunctionCall::isFinal() const {
615        if (!fn) return false;
616        FunctionCall* self = const_cast<FunctionCall*>(this);
617        return fn->returnsFinal(dynamic_cast<VMFnArgs*>(&*self->args));
618  }  }
619    
620  VMFnResult* FunctionCall::execVMFn() {  VMFnResult* FunctionCall::execVMFn() {
621      if (!fn) return NULL;      if (!fn) return NULL;
622    
623        // tell function where it shall dump its return value to
624        VMFnResult* oldRes = fn->boundResult();
625        fn->bindResult(result);
626    
627      // assuming here that all argument checks (amount and types) have been made      // assuming here that all argument checks (amount and types) have been made
628      // at parse time, to avoid time intensive checks on each function call      // at parse time, to avoid time intensive checks on each function call
629      return fn->exec(dynamic_cast<VMFnArgs*>(&*args));      VMFnResult* res = fn->exec(dynamic_cast<VMFnArgs*>(&*args));
630    
631        // restore previous result binding of some potential toplevel or concurrent
632        // caller, i.e. if exactly same function is called more than one time,
633        // concurrently in a term by other FunctionCall objects, e.g.:
634        // ~c := ceil( ceil(~a) + ~b)
635        fn->bindResult(oldRes);
636    
637        if (!res) return res;
638    
639        VMExpr* expr = res->resultValue();
640        if (!expr) return res;
641    
642        // For performance reasons we always only let 'FunctionCall' assign the unit
643        // type to the function's result expression, never by the function
644        // implementation itself, nor by other classes, because a FunctionCall
645        // object solely knows the unit type in O(1).
646        ExprType_t type = expr->exprType();
647        if (type == INT_EXPR) {
648            VMIntResult* intRes = dynamic_cast<VMIntResult*>(res);
649            intRes->unitBaseType = unitType();
650        } else if (type == REAL_EXPR) {
651            VMRealResult* realRes = dynamic_cast<VMRealResult*>(res);
652            realRes->unitBaseType = unitType();
653        }
654    
655        return res;
656  }  }
657    
658  StmtFlags_t FunctionCall::exec() {  StmtFlags_t FunctionCall::exec() {
# Line 316  StmtFlags_t FunctionCall::exec() { Line 662  StmtFlags_t FunctionCall::exec() {
662      return result->resultFlags();      return result->resultFlags();
663  }  }
664    
665  int FunctionCall::evalInt() {  vmint FunctionCall::evalInt() {
666      VMFnResult* result = execVMFn();      VMFnResult* result = execVMFn();
667      if (!result) return 0;      if (!result) return 0;
668      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
# Line 324  int FunctionCall::evalInt() { Line 670  int FunctionCall::evalInt() {
670      return intExpr->evalInt();      return intExpr->evalInt();
671  }  }
672    
673    vmfloat FunctionCall::evalReal() {
674        VMFnResult* result = execVMFn();
675        if (!result) return 0;
676        VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
677        if (!realExpr) return 0;
678        return realExpr->evalReal();
679    }
680    
681  VMIntArrayExpr* FunctionCall::asIntArray() const {  VMIntArrayExpr* FunctionCall::asIntArray() const {
682      VMFnResult* result = const_cast<FunctionCall*>(this)->execVMFn();      //FIXME: asIntArray() not intended for evaluation semantics (for both
683        // performance reasons with arrays, but also to prevent undesired value
684        // mutation by implied (hidden) evaluation, as actually done here. We must
685        // force function evaluation here though, because we need it for function
686        // calls to be evaluated at all. This issue should be addressed cleanly by
687        // adjusting the API appropriately.
688        FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
689        VMFnResult* result = rwSelf->execVMFn();
690    
691      if (!result) return 0;      if (!result) return 0;
692      VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());      VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());
693      return intArrExpr;      return intArrExpr;
694  }  }
695    
696    VMRealArrayExpr* FunctionCall::asRealArray() const {
697        //FIXME: asRealArray() not intended for evaluation semantics (for both
698        // performance reasons with arrays, but also to prevent undesired value
699        // mutation by implied (hidden) evaluation, as actually done here. We must
700        // force function evaluation here though, because we need it for function
701        // calls to be evaluated at all. This issue should be addressed cleanly by
702        // adjusting the API appropriately.
703        FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
704        VMFnResult* result = rwSelf->execVMFn();
705    
706        if (!result) return 0;
707        VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue());
708        return realArrExpr;
709    }
710    
711  String FunctionCall::evalStr() {  String FunctionCall::evalStr() {
712      VMFnResult* result = execVMFn();      VMFnResult* result = execVMFn();
713      if (!result) return "";      if (!result) return "";
# Line 342  String FunctionCall::evalStr() { Line 719  String FunctionCall::evalStr() {
719  String FunctionCall::evalCastToStr() {  String FunctionCall::evalCastToStr() {
720      VMFnResult* result = execVMFn();      VMFnResult* result = execVMFn();
721      if (!result) return "";      if (!result) return "";
722      if (result->resultValue()->exprType() == STRING_EXPR) {      const ExprType_t resultType = result->resultValue()->exprType();
723        if (resultType == STRING_EXPR) {
724          VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());          VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
725          return strExpr ? strExpr->evalStr() : "";          return strExpr ? strExpr->evalStr() : "";
726        } else if (resultType == REAL_EXPR) {
727            VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
728            return realExpr ? ToString(realExpr->evalReal()) + _unitToStr(realExpr) : "";
729      } else {      } else {
730          VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());          VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
731          return intExpr ? ToString(intExpr->evalInt()) : "";          return intExpr ? ToString(intExpr->evalInt()) + _unitToStr(intExpr) : "";
732      }      }
733  }  }
734    
735  IntVariable::IntVariable(ParserContext* ctx)  Variable::Variable(const VariableDecl& decl) :
736      : Variable(ctx, ctx ? ctx->globalIntVarCount++ : 0, false), polyphonic(false)      context(decl.ctx), memPos(decl.memPos), bConst(decl.isConst)
737  {  {
     //printf("globalIntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);  
     assert(ctx);  
738  }  }
739    
740  inline static int postfixInc(int& object, int incBy) {  NumberVariable::NumberVariable(const VariableDecl& decl) :
741      const int i = object;      Variable(decl),
742        Unit(decl.unitType),
743        unitFactorMemPos(decl.unitFactorMemPos), polyphonic(decl.isPolyphonic),
744        finalVal(decl.isFinal)
745    {
746    }
747    
748    vmfloat NumberVariable::unitFactor() const {
749        if (isPolyphonic()) {
750            return context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos];
751        }
752        return (*context->globalUnitFactorMemory)[unitFactorMemPos];
753    }
754    
755    inline static vmint postfixInc(vmint& object, vmint incBy) {
756        const vmint i = object;
757      object += incBy;      object += incBy;
758      return i;      return i;
759  }  }
760    
761  IntVariable::IntVariable(ParserContext* ctx, bool polyphonic, bool bConst, int size)  IntVariable::IntVariable(const VariableDecl& decl) :
762      : Variable(ctx, !ctx ? 0 : polyphonic ? postfixInc(ctx->polyphonicIntVarCount, size) : postfixInc(ctx->globalIntVarCount, size), bConst),      NumberVariable({
763        polyphonic(polyphonic)          .ctx = decl.ctx,
764  {          .isPolyphonic = decl.isPolyphonic,
765      //printf("InvVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx);          .isConst = decl.isConst,
766      if (polyphonic) {          .elements = decl.elements,
767          //printf("polyIntVar memPOS=%d\n", memPos);          .memPos = (
768          assert(ctx);              (!decl.ctx) ? 0 :
769      }                  (decl.isPolyphonic) ?
770                        postfixInc(decl.ctx->polyphonicIntVarCount, decl.elements) :
771                        postfixInc(decl.ctx->globalIntVarCount, decl.elements)
772            ),
773            .unitFactorMemPos = (
774                (!decl.ctx) ? 0 :
775                    (decl.isPolyphonic) ?
776                        postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
777                        postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
778            ),
779            .unitType = decl.unitType,
780            .isFinal = decl.isFinal,
781        }),
782        Unit(decl.unitType)
783    {
784        //printf("IntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
785        assert(!decl.isPolyphonic || decl.ctx);
786  }  }
787    
788  void IntVariable::assign(Expression* expr) {  void IntVariable::assign(Expression* expr) {
789      IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);      IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
790      if (intExpr) {      if (intExpr) {
791          if (polyphonic)          //NOTE: sequence matters! evalInt() must be called before getting unitFactor() !
792            if (isPolyphonic()) {
793              context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();              context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();
794          else              context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = intExpr->unitFactor();
795            } else {
796              (*context->globalIntMemory)[memPos] = intExpr->evalInt();              (*context->globalIntMemory)[memPos] = intExpr->evalInt();
797                (*context->globalUnitFactorMemory)[unitFactorMemPos] = intExpr->unitFactor();
798            }
799      }      }
800  }  }
801    
802  int IntVariable::evalInt() {  vmint IntVariable::evalInt() {
803      //printf("IntVariable::eval pos=%d\n", memPos);      //printf("IntVariable::eval pos=%d\n", memPos);
804      if (polyphonic) {      if (isPolyphonic()) {
805          //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);
806          return context->execContext->polyphonicIntMemory[memPos];          return context->execContext->polyphonicIntMemory[memPos];
807      }      }
# Line 400  void IntVariable::dump(int level) { Line 814  void IntVariable::dump(int level) {
814      //printf("IntVariable memPos=%d\n", memPos);      //printf("IntVariable memPos=%d\n", memPos);
815  }  }
816    
817  //ConstIntVariable::ConstIntVariable(ParserContext* ctx, int value)  RealVariable::RealVariable(const VariableDecl& decl) :
818  ConstIntVariable::ConstIntVariable(int value)      NumberVariable({
819      : IntVariable(NULL,false,true), value(value)          .ctx = decl.ctx,
820            .isPolyphonic = decl.isPolyphonic,
821            .isConst = decl.isConst,
822            .elements = decl.elements,
823            .memPos = (
824                (!decl.ctx) ? 0 :
825                    (decl.isPolyphonic) ?
826                        postfixInc(decl.ctx->polyphonicRealVarCount, decl.elements) :
827                        postfixInc(decl.ctx->globalRealVarCount, decl.elements)
828            ),
829            .unitFactorMemPos = (
830                (!decl.ctx) ? 0 :
831                    (decl.isPolyphonic) ?
832                        postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
833                        postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
834            ),
835            .unitType = decl.unitType,
836            .isFinal = decl.isFinal,
837        }),
838        Unit(decl.unitType)
839    {
840        //printf("RealVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
841        assert(!decl.isPolyphonic || decl.ctx);
842    }
843    
844    void RealVariable::assign(Expression* expr) {
845        RealExpr* realExpr = dynamic_cast<RealExpr*>(expr);
846        if (realExpr) {
847            //NOTE: sequence matters! evalReal() must be called before getting unitFactor() !
848            if (isPolyphonic()) {
849                context->execContext->polyphonicRealMemory[memPos] = realExpr->evalReal();
850                context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = realExpr->unitFactor();
851            } else {
852                (*context->globalRealMemory)[memPos] = realExpr->evalReal();
853                (*context->globalUnitFactorMemory)[unitFactorMemPos] = realExpr->unitFactor();
854            }
855        }
856    }
857    
858    vmfloat RealVariable::evalReal() {
859        //printf("RealVariable::eval pos=%d\n", memPos);
860        if (isPolyphonic()) {
861            //printf("evalReal() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
862            return context->execContext->polyphonicRealMemory[memPos];
863        }
864        return (*context->globalRealMemory)[memPos];
865    }
866    
867    void RealVariable::dump(int level) {
868        printIndents(level);
869        printf("RealVariable\n");
870        //printf("RealVariable memPos=%d\n", memPos);
871    }
872    
873    ConstIntVariable::ConstIntVariable(const IntVarDef& def) :
874        IntVariable({
875            .ctx = def.ctx,
876            .isPolyphonic = false,
877            .isConst = true,
878            .elements = 1,
879            .memPos = def.memPos,
880            .unitFactorMemPos = def.unitFactorMemPos,
881            .unitType = def.unitType,
882            .isFinal = def.isFinal,
883        }),
884        Unit(def.unitType),
885        value(def.value), unitPrefixFactor(def.unitFactor)
886  {  {
887  }  }
888    
# Line 417  void ConstIntVariable::assign(Expression Line 897  void ConstIntVariable::assign(Expression
897  */  */
898  }  }
899    
900  int ConstIntVariable::evalInt() {  vmint ConstIntVariable::evalInt() {
901      return value;      return value;
902  }  }
903    
904  void ConstIntVariable::dump(int level) {  void ConstIntVariable::dump(int level) {
905      printIndents(level);      printIndents(level);
906      printf("ConstIntVariable val=%d\n", value);      printf("ConstIntVariable val=%" PRId64 "\n", (int64_t)value);
907  }  }
908    
909  BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntRelPtr* ptr)  ConstRealVariable::ConstRealVariable(const RealVarDef& def) :
910      : IntVariable(NULL,false,false), name(name), ptr(ptr)      RealVariable({
911            .ctx = def.ctx,
912            .isPolyphonic = false,
913            .isConst = true,
914            .elements = 1,
915            .memPos = def.memPos,
916            .unitFactorMemPos = def.unitFactorMemPos,
917            .unitType = def.unitType,
918            .isFinal = def.isFinal,
919        }),
920        Unit(def.unitType),
921        value(def.value), unitPrefixFactor(def.unitFactor)
922    {
923    }
924    
925    void ConstRealVariable::assign(Expression* expr) {
926        // ignore assignment
927    }
928    
929    vmfloat ConstRealVariable::evalReal() {
930        return value;
931    }
932    
933    void ConstRealVariable::dump(int level) {
934        printIndents(level);
935        printf("ConstRealVariable val=%f\n", value);
936    }
937    
938    BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) :
939        IntVariable({
940            .ctx = NULL,
941            .isPolyphonic = false,
942            .isConst = false, // may or may not be modifyable though!
943            .elements = 0,
944            .memPos = 0,
945            .unitFactorMemPos = 0,
946            .unitType = VM_NO_UNIT,
947            .isFinal = false,
948        }),
949        Unit(VM_NO_UNIT),
950        name(name), ptr(ptr)
951  {  {
952  }  }
953    
# Line 437  void BuiltInIntVariable::assign(Expressi Line 957  void BuiltInIntVariable::assign(Expressi
957      ptr->assign(valueExpr->evalInt());      ptr->assign(valueExpr->evalInt());
958  }  }
959    
960  int BuiltInIntVariable::evalInt() {  vmint BuiltInIntVariable::evalInt() {
961      return ptr->evalInt();      return ptr->evalInt();
962  }  }
963    
# Line 446  void BuiltInIntVariable::dump(int level) Line 966  void BuiltInIntVariable::dump(int level)
966      printf("Built-in IntVar '%s'\n", name.c_str());      printf("Built-in IntVar '%s'\n", name.c_str());
967  }  }
968    
969  PolyphonicIntVariable::PolyphonicIntVariable(ParserContext* ctx)  PolyphonicIntVariable::PolyphonicIntVariable(const VariableDecl& decl) :
970      : IntVariable(ctx,true,false)      IntVariable({
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  {  {
982  }  }
983    
# Line 456  void PolyphonicIntVariable::dump(int lev Line 986  void PolyphonicIntVariable::dump(int lev
986      printf("PolyphonicIntVariable\n");      printf("PolyphonicIntVariable\n");
987  }  }
988    
989  IntArrayVariable::IntArrayVariable(ParserContext* ctx, int size)  PolyphonicRealVariable::PolyphonicRealVariable(const VariableDecl& decl) :
990      : Variable(ctx, 0, false)      RealVariable({
991            .ctx = decl.ctx,
992            .isPolyphonic = true,
993            .isConst = decl.isConst,
994            .elements = 1,
995            .memPos = 0,
996            .unitFactorMemPos = 0,
997            .unitType = decl.unitType,
998            .isFinal = decl.isFinal,
999        }),
1000        Unit(decl.unitType)
1001  {  {
     values.resize(size);  
     memset(&values[0], 0, size * sizeof(int));  
1002  }  }
1003    
1004  IntArrayVariable::IntArrayVariable(ParserContext* ctx, int size, ArgsRef values, bool _bConst)  void PolyphonicRealVariable::dump(int level) {
1005      : Variable(ctx, 0, _bConst)      printIndents(level);
1006        printf("PolyphonicRealVariable\n");
1007    }
1008    
1009    IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size) :
1010        Variable({
1011            .ctx = ctx,
1012            .isPolyphonic = false,
1013            .isConst = false,
1014            .elements = 0,
1015            .memPos = 0,
1016            .unitFactorMemPos = 0,
1017            .unitType = VM_NO_UNIT,
1018            .isFinal = false,
1019        })
1020    {
1021        values.resize(size);
1022        memset(&values[0], 0, size * sizeof(vmint));
1023    
1024        unitFactors.resize(size);
1025        for (size_t i = 0; i < size; ++i)
1026            unitFactors[i] = VM_NO_FACTOR;
1027    }
1028    
1029    IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size,
1030                                       ArgsRef values, bool _bConst) :
1031        Variable({
1032            .ctx = ctx,
1033            .isPolyphonic = false,
1034            .isConst = _bConst,
1035            .elements = 0,
1036            .memPos = 0,
1037            .unitFactorMemPos = 0,
1038            .unitType = VM_NO_UNIT,
1039            .isFinal = false,
1040        })
1041  {  {
1042      this->values.resize(size);      this->values.resize(size);
1043      for (int i = 0; i < values->argsCount(); ++i) {      this->unitFactors.resize(size);
1044        for (vmint i = 0; i < values->argsCount(); ++i) {
1045          VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));          VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));
1046          if (expr) this->values[i] = expr->evalInt();          if (expr) {
1047                this->values[i] = expr->evalInt();
1048                this->unitFactors[i] = expr->unitFactor();
1049            }
1050      }      }
1051  }  }
1052    
1053  IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst)  IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst) :
1054      : Variable(ctx, 0, bConst)      Variable({
1055            .ctx = ctx,
1056            .isPolyphonic = false,
1057            .isConst = bConst,
1058            .elements = 0,
1059            .memPos = 0,
1060            .unitFactorMemPos = 0,
1061            .unitType = VM_NO_UNIT,
1062            .isFinal = false,
1063        })
1064  {  {
1065  }  }
1066    
1067  int IntArrayVariable::evalIntElement(uint i) {  vmint IntArrayVariable::evalIntElement(vmuint i) {
1068      if (i >= values.size()) return 0;      if (i >= values.size()) return 0;
1069      return values[i];      return values[i];
1070  }  }
1071    
1072  void IntArrayVariable::assignIntElement(uint i, int value) {  void IntArrayVariable::assignIntElement(vmuint i, vmint value) {
1073      if (i >= values.size()) return;      if (i >= values.size()) return;
1074      values[i] = value;      values[i] = value;
1075  }  }
1076    
1077    vmfloat IntArrayVariable::unitFactorOfElement(vmuint i) const {
1078        if (i >= unitFactors.size()) return VM_NO_FACTOR;
1079        return unitFactors[i];
1080    }
1081    
1082    void IntArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1083        if (i >= unitFactors.size()) return;
1084        unitFactors[i] = factor;
1085    }
1086    
1087  void IntArrayVariable::dump(int level) {  void IntArrayVariable::dump(int level) {
1088      printIndents(level);      printIndents(level);
1089      printf("IntArray(");      printf("IntArray(");
1090      for (int i = 0; i < values.size(); ++i) {      for (vmint i = 0; i < values.size(); ++i) {
1091            if (i % 12 == 0) {
1092                printf("\n");
1093                printIndents(level+1);
1094            }
1095            printf("%" PRId64 ", ", (int64_t)values[i]);
1096        }
1097        printIndents(level);
1098        printf(")\n");
1099    }
1100    
1101    RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size) :
1102        Variable({
1103            .ctx = ctx,
1104            .isPolyphonic = false,
1105            .isConst = false,
1106            .elements = 0,
1107            .memPos = 0,
1108            .unitFactorMemPos = 0,
1109            .unitType = VM_NO_UNIT,
1110            .isFinal = false,
1111        })
1112    {
1113        values.resize(size);
1114        memset(&values[0], 0, size * sizeof(vmfloat));
1115    
1116        unitFactors.resize(size);
1117        for (size_t i = 0; i < size; ++i)
1118            unitFactors[i] = VM_NO_FACTOR;
1119    }
1120    
1121    RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size,
1122                                         ArgsRef values, bool _bConst) :
1123        Variable({
1124            .ctx = ctx,
1125            .isPolyphonic = false,
1126            .isConst = _bConst,
1127            .elements = 0,
1128            .memPos = 0,
1129            .unitFactorMemPos = 0,
1130            .unitType = VM_NO_UNIT,
1131            .isFinal = false,
1132        })
1133    {
1134        this->values.resize(size);
1135        this->unitFactors.resize(size);
1136        for (vmint i = 0; i < values->argsCount(); ++i) {
1137            VMRealExpr* expr = dynamic_cast<VMRealExpr*>(values->arg(i));
1138            if (expr) {
1139                this->values[i] = expr->evalReal();
1140                this->unitFactors[i] = expr->unitFactor();
1141            }
1142        }
1143    }
1144    
1145    RealArrayVariable::RealArrayVariable(ParserContext* ctx, bool bConst) :
1146        Variable({
1147            .ctx = ctx,
1148            .isPolyphonic = false,
1149            .isConst = bConst,
1150            .elements = 0,
1151            .memPos = 0,
1152            .unitFactorMemPos = 0,
1153            .unitType = VM_NO_UNIT,
1154            .isFinal = false,
1155        })
1156    {
1157    }
1158    
1159    vmfloat RealArrayVariable::evalRealElement(vmuint i) {
1160        if (i >= values.size()) return 0;
1161        return values[i];
1162    }
1163    
1164    void RealArrayVariable::assignRealElement(vmuint i, vmfloat value) {
1165        if (i >= values.size()) return;
1166        values[i] = value;
1167    }
1168    
1169    vmfloat RealArrayVariable::unitFactorOfElement(vmuint i) const {
1170        if (i >= unitFactors.size()) return VM_NO_FACTOR;
1171        return unitFactors[i];
1172    }
1173    
1174    void RealArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1175        if (i >= unitFactors.size()) return;
1176        unitFactors[i] = factor;
1177    }
1178    
1179    void RealArrayVariable::dump(int level) {
1180        printIndents(level);
1181        printf("RealArray(");
1182        for (vmint i = 0; i < values.size(); ++i) {
1183          if (i % 12 == 0) {          if (i % 12 == 0) {
1184              printf("\n");              printf("\n");
1185              printIndents(level+1);              printIndents(level+1);
1186          }          }
1187          printf("%d, ", values[i]);          printf("%f, ", values[i]);
1188      }      }
1189      printIndents(level);      printIndents(level);
1190      printf(")\n");      printf(")\n");
1191  }  }
1192    
1193  BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name, VMInt8Array* array)  BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name,
1194      : IntArrayVariable(NULL, false), name(name), array(array)                                                   VMInt8Array* array) :
1195        IntArrayVariable(NULL, false),
1196        name(name), array(array)
1197  {  {
1198  }  }
1199    
1200  int BuiltInIntArrayVariable::evalIntElement(uint i) {  vmint BuiltInIntArrayVariable::evalIntElement(vmuint i) {
1201      return i >= array->size ? 0 : array->data[i];      return i >= array->size ? 0 : array->data[i];
1202  }  }
1203    
1204  void BuiltInIntArrayVariable::assignIntElement(uint i, int value) {  void BuiltInIntArrayVariable::assignIntElement(vmuint i, vmint value) {
1205      if (i >= array->size) return;      if (i >= array->size) return;
1206      array->data[i] = value;      array->data[i] = value;
1207  }  }
# Line 521  void BuiltInIntArrayVariable::dump(int l Line 1211  void BuiltInIntArrayVariable::dump(int l
1211      printf("Built-In Int Array Variable '%s'\n", name.c_str());      printf("Built-In Int Array Variable '%s'\n", name.c_str());
1212  }  }
1213    
1214  IntArrayElement::IntArrayElement(IntArrayVariableRef array, IntExprRef arrayIndex)  IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) :
1215      : IntVariable(NULL, false, false, 0), array(array), index(arrayIndex)      IntVariable({
1216  {              .ctx = NULL,
1217            .isPolyphonic = (array) ? array->isPolyphonic() : false,
1218            .isConst = (array) ? array->isConstExpr() : false,
1219            .elements = 0,
1220            .memPos = 0,
1221            .unitFactorMemPos = 0,
1222            .unitType = VM_NO_UNIT,
1223            .isFinal = false,
1224        }),
1225        Unit(VM_NO_UNIT),
1226        array(array), index(arrayIndex), currentIndex(-1)
1227    {
1228  }  }
1229    
1230  void IntArrayElement::assign(Expression* expr) {  void IntArrayElement::assign(Expression* expr) {
1231      IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);      IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
1232      if (!valueExpr) return;      if (!valueExpr) return;
1233      int value = valueExpr->evalInt();      vmint value = valueExpr->evalInt();
1234        vmfloat unitFactor = valueExpr->unitFactor();
1235    
1236      if (!index) return;      if (!index) return;
1237      int idx = index->evalInt();      vmint idx = currentIndex = index->evalInt();
1238      if (idx < 0 || idx >= array->arraySize()) return;      if (idx < 0 || idx >= array->arraySize()) return;
1239    
1240      array->assignIntElement(idx, value);      array->assignIntElement(idx, value);
1241        array->assignElementUnitFactor(idx, unitFactor);
1242  }  }
1243    
1244  int IntArrayElement::evalInt() {  vmint IntArrayElement::evalInt() {
1245      if (!index) return 0;      if (!index) return 0;
1246      int idx = index->evalInt();      vmint idx = currentIndex = index->evalInt();
1247      if (idx < 0 || idx >= array->arraySize()) return 0;      if (idx < 0 || idx >= array->arraySize()) return 0;
1248    
1249      return array->evalIntElement(idx);      return array->evalIntElement(idx);
1250  }  }
1251    
1252    vmfloat IntArrayElement::unitFactor() const {
1253        if (!index) return VM_NO_FACTOR;
1254        vmint idx = currentIndex;
1255        if (idx < 0 || idx >= array->arraySize()) return 0;
1256    
1257        return array->unitFactorOfElement(idx);
1258    }
1259    
1260  void IntArrayElement::dump(int level) {  void IntArrayElement::dump(int level) {
1261      printIndents(level);      printIndents(level);
1262      printf("IntArrayElement\n");      printf("IntArrayElement\n");
1263  }  }
1264    
1265  StringVariable::StringVariable(ParserContext* ctx)  RealArrayElement::RealArrayElement(RealArrayExprRef array, IntExprRef arrayIndex) :
1266      : Variable(ctx,ctx->globalStrVarCount++,false)      RealVariable({
1267            .ctx = NULL,
1268            .isPolyphonic = (array) ? array->isPolyphonic() : false,
1269            .isConst = (array) ? array->isConstExpr() : false,
1270            .elements = 0,
1271            .memPos = 0,
1272            .unitFactorMemPos = 0,
1273            .unitType = VM_NO_UNIT,
1274            .isFinal = false,
1275        }),
1276        Unit(VM_NO_UNIT),
1277        array(array), index(arrayIndex), currentIndex(-1)
1278    {
1279    }
1280    
1281    void RealArrayElement::assign(Expression* expr) {
1282        RealExpr* valueExpr = dynamic_cast<RealExpr*>(expr);
1283        if (!valueExpr) return;
1284        vmfloat value = valueExpr->evalReal();
1285        vmfloat unitFactor = valueExpr->unitFactor();
1286    
1287        if (!index) return;
1288        vmint idx = currentIndex = index->evalInt();
1289        if (idx < 0 || idx >= array->arraySize()) return;
1290    
1291        array->assignRealElement(idx, value);
1292        array->assignElementUnitFactor(idx, unitFactor);
1293    }
1294    
1295    vmfloat RealArrayElement::evalReal() {
1296        if (!index) return 0;
1297        vmint idx = currentIndex = index->evalInt();
1298        if (idx < 0 || idx >= array->arraySize()) return 0;
1299    
1300        return array->evalRealElement(idx);
1301    }
1302    
1303    vmfloat RealArrayElement::unitFactor() const {
1304        if (!index) return VM_NO_FACTOR;
1305        vmint idx = currentIndex;
1306        if (idx < 0 || idx >= array->arraySize()) return 0;
1307    
1308        return array->unitFactorOfElement(idx);
1309    }
1310    
1311    void RealArrayElement::dump(int level) {
1312        printIndents(level);
1313        printf("RealArrayElement\n");
1314    }
1315    
1316    StringVariable::StringVariable(ParserContext* ctx) :
1317        Variable({
1318            .ctx = ctx,
1319            .elements = 1,
1320            .memPos = ctx->globalStrVarCount++
1321        })
1322  {  {
1323  }  }
1324    
1325  StringVariable::StringVariable(ParserContext* ctx, bool bConst)  StringVariable::StringVariable(ParserContext* ctx, bool bConst) :
1326      : Variable(ctx,0,bConst)      Variable({
1327            .ctx = ctx,
1328            .isConst = bConst,
1329            .memPos = 0,
1330        })
1331  {  {
1332  }  }
1333    
# Line 573  String StringVariable::evalStr() { Line 1343  String StringVariable::evalStr() {
1343    
1344  void StringVariable::dump(int level) {  void StringVariable::dump(int level) {
1345      printIndents(level);      printIndents(level);
1346      printf("StringVariable memPos=%d\n", memPos);      printf("StringVariable memPos=%" PRId64 "\n", (int64_t)memPos);
1347  }  }
1348    
1349  ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)  ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)
# Line 596  void ConstStringVariable::dump(int level Line 1366  void ConstStringVariable::dump(int level
1366      printf("ConstStringVariable val='%s'\n", value.c_str());      printf("ConstStringVariable val='%s'\n", value.c_str());
1367  }  }
1368    
1369    bool NumberBinaryOp::isFinal() const {
1370        NumberExprRef l = (NumberExprRef) lhs;
1371        NumberExprRef r = (NumberExprRef) rhs;
1372        return l->isFinal() || r->isFinal();
1373    }
1374    
1375    ExprType_t VaritypeScalarBinaryOp::exprType() const {
1376        return (lhs->exprType() == REAL_EXPR || rhs->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
1377    }
1378    
1379    String VaritypeScalarBinaryOp::evalCastToStr() {
1380        return (exprType() == REAL_EXPR) ?
1381            RealExpr::evalCastToStr() : IntExpr::evalCastToStr();
1382    }
1383    
1384  void If::dump(int level) {  void If::dump(int level) {
1385      printIndents(level);      printIndents(level);
1386      if (ifStatements && elseStatements)      if (ifStatements && elseStatements)
# Line 606  void If::dump(int level) { Line 1391  void If::dump(int level) {
1391          printf("if [INVALID]\n");          printf("if [INVALID]\n");
1392  }  }
1393    
1394  int If::evalBranch() {  vmint If::evalBranch() {
1395      if (condition->evalInt()) return 0;      if (condition->evalInt()) return 0;
1396      if (elseStatements) return 1;      if (elseStatements) return 1;
1397      return -1;      return -1;
1398  }  }
1399    
1400  Statements* If::branch(uint i) const {  Statements* If::branch(vmuint i) const {
1401      if (i == 0) return (Statements*) &*ifStatements;      if (i == 0) return (Statements*) &*ifStatements;
1402      if (i == 1) return (elseStatements) ? (Statements*) &*elseStatements : NULL;      if (i == 1) return (elseStatements) ? (Statements*) &*elseStatements : NULL;
1403      return NULL;      return NULL;
# Line 628  void SelectCase::dump(int level) { Line 1413  void SelectCase::dump(int level) {
1413      printIndents(level);      printIndents(level);
1414      if (select)      if (select)
1415          if (select->isConstExpr())          if (select->isConstExpr())
1416              printf("Case select %d\n", select->evalInt());              printf("Case select %" PRId64 "\n", (int64_t)select->evalInt());
1417          else          else
1418              printf("Case select [runtime expr]\n");              printf("Case select [runtime expr]\n");
1419      else      else
1420          printf("Case select NULL\n");          printf("Case select NULL\n");
1421      for (int i = 0; i < branches.size(); ++i) {      for (vmint i = 0; i < branches.size(); ++i) {
1422          printIndents(level+1);          printIndents(level+1);
1423          CaseBranch& branch = branches[i];          CaseBranch& branch = branches[i];
1424          if (branch.from && branch.to)          if (branch.from && branch.to)
1425              if (branch.from->isConstExpr() && branch.to->isConstExpr())              if (branch.from->isConstExpr() && branch.to->isConstExpr())
1426                  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());
1427              else if (branch.from->isConstExpr() && !branch.to->isConstExpr())              else if (branch.from->isConstExpr() && !branch.to->isConstExpr())
1428                  printf("case %d to [runtime expr]\n", branch.from->evalInt());                  printf("case %" PRId64 " to [runtime expr]\n", (int64_t)branch.from->evalInt());
1429              else if (!branch.from->isConstExpr() && branch.to->isConstExpr())              else if (!branch.from->isConstExpr() && branch.to->isConstExpr())
1430                  printf("case [runtime expr] to %d\n", branch.to->evalInt());                  printf("case [runtime expr] to %" PRId64 "\n", (int64_t)branch.to->evalInt());
1431              else              else
1432                  printf("case [runtime expr] to [runtime expr]\n");                  printf("case [runtime expr] to [runtime expr]\n");
1433          else if (branch.from)          else if (branch.from)
1434              if (branch.from->isConstExpr())              if (branch.from->isConstExpr())
1435                  printf("case %d\n", branch.from->evalInt());                  printf("case %" PRId64 "\n", (int64_t)branch.from->evalInt());
1436              else              else
1437                  printf("case [runtime expr]\n");                  printf("case [runtime expr]\n");
1438          else          else
# Line 655  void SelectCase::dump(int level) { Line 1440  void SelectCase::dump(int level) {
1440      }      }
1441  }  }
1442    
1443  int SelectCase::evalBranch() {  vmint SelectCase::evalBranch() {
1444      int value = select->evalInt();      vmint value = select->evalInt();
1445      for (int i = 0; i < branches.size(); ++i) {      for (vmint i = 0; i < branches.size(); ++i) {
1446          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" ...
1447              if (branches.at(i).from->evalInt() <= value &&              if (branches.at(i).from->evalInt() <= value &&
1448                  branches.at(i).to->evalInt() >= value) return i;                  branches.at(i).to->evalInt() >= value) return i;
# Line 668  int SelectCase::evalBranch() { Line 1453  int SelectCase::evalBranch() {
1453      return -1;      return -1;
1454  }  }
1455    
1456  Statements* SelectCase::branch(uint i) const {  Statements* SelectCase::branch(vmuint i) const {
1457      if (i < branches.size())      if (i < branches.size())
1458          return const_cast<Statements*>( &*branches[i].statements );          return const_cast<Statements*>( &*branches[i].statements );
1459      return NULL;      return NULL;
# Line 676  Statements* SelectCase::branch(uint i) c Line 1461  Statements* SelectCase::branch(uint i) c
1461    
1462  bool SelectCase::isPolyphonic() const {  bool SelectCase::isPolyphonic() const {
1463      if (select->isPolyphonic()) return true;      if (select->isPolyphonic()) return true;
1464      for (int i = 0; i < branches.size(); ++i)      for (vmint i = 0; i < branches.size(); ++i)
1465          if (branches[i].statements->isPolyphonic())          if (branches[i].statements->isPolyphonic())
1466              return true;              return true;
1467      return false;      return false;
1468  }  }
1469    
 // 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);  
 // }  
   
1470  void While::dump(int level) {  void While::dump(int level) {
1471      printIndents(level);      printIndents(level);
1472      if (m_condition)      if (m_condition)
1473          if (m_condition->isConstExpr())          if (m_condition->isConstExpr())
1474              printf("while (%d) {\n", m_condition->evalInt());              printf("while (%" PRId64 ") {\n", (int64_t)m_condition->evalInt());
1475          else          else
1476              printf("while ([runtime expr]) {\n");              printf("while ([runtime expr]) {\n");
1477      else      else
# Line 724  bool While::evalLoopStartCondition() { Line 1490  bool While::evalLoopStartCondition() {
1490      return m_condition->evalInt();      return m_condition->evalInt();
1491  }  }
1492    
1493    void SyncBlock::dump(int level) {
1494        printIndents(level);
1495        printf("sync {\n");
1496        m_statements->dump(level+1);
1497        printIndents(level);
1498        printf("}\n");
1499    }
1500    
1501    Statements* SyncBlock::statements() const {
1502        return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1503    }
1504    
1505    String Neg::evalCastToStr() {
1506        return expr->evalCastToStr();
1507    }
1508    
1509  void Neg::dump(int level) {  void Neg::dump(int level) {
1510      printIndents(level);      printIndents(level);
1511      printf("Negative Expr\n");      printf("Negative Expr\n");
# Line 757  bool ConcatString::isConstExpr() const { Line 1539  bool ConcatString::isConstExpr() const {
1539      return lhs->isConstExpr() && rhs->isConstExpr();      return lhs->isConstExpr() && rhs->isConstExpr();
1540  }  }
1541    
1542  int Relation::evalInt() {  Relation::Relation(ExpressionRef lhs, Type type, ExpressionRef rhs) :
1543        Unit(VM_NO_UNIT),
1544        lhs(lhs), rhs(rhs), type(type)
1545    {
1546    }
1547    
1548    // Equal / unequal comparison of real numbers in NKSP scripts:
1549    //
1550    // Unlike system level languages like C/C++ we are less conservative about
1551    // comparing floating point numbers for 'equalness' or 'unequalness' in NKSP
1552    // scripts. Due to the musical context of the NKSP language we automatically
1553    // take the (to be) expected floating point tolerances into account when
1554    // comparing two floating point numbers with each other, however only for '='
1555    // and '#' operators. The '<=' and '>=' still use conservative low level
1556    // floating point comparison for not breaking their transitivity feature.
1557    
1558    template<typename T_LHS, typename T_RHS>
1559    struct RelComparer {
1560        static inline bool isEqual(T_LHS a, T_RHS b) { // for int comparison ('3 = 3')
1561            return a == b;
1562        }
1563        static inline bool isUnequal(T_LHS a, T_RHS b) { // for int comparison ('3 # 3')
1564            return a != b;
1565        }
1566    };
1567    
1568    template<>
1569    struct RelComparer<float,float> {
1570        static inline bool isEqual(float a, float b) { // for real number comparison ('3.1 = 3.1')
1571            return RTMath::fEqual32(a, b);
1572        }
1573        static inline bool isUnequal(float a, float b) { // for real number comparison ('3.1 # 3.1')
1574            return !RTMath::fEqual32(a, b);
1575        }
1576    };
1577    
1578    template<>
1579    struct RelComparer<double,double> {
1580        static inline bool isEqual(double a, double b) { // for future purpose
1581            return RTMath::fEqual64(a, b);
1582        }
1583        static inline bool isUnqqual(double a, double b) { // for future purpose
1584            return !RTMath::fEqual64(a, b);
1585        }
1586    };
1587    
1588    template<class T_LHS, class T_RHS>
1589    inline vmint _evalRelation(Relation::Type type, T_LHS lhs, T_RHS rhs) {
1590      switch (type) {      switch (type) {
1591          case LESS_THAN:          case Relation::LESS_THAN:
1592              return lhs->evalInt() < rhs->evalInt();              return lhs < rhs;
1593          case GREATER_THAN:          case Relation::GREATER_THAN:
1594              return lhs->evalInt() > rhs->evalInt();              return lhs > rhs;
1595          case LESS_OR_EQUAL:          case Relation::LESS_OR_EQUAL:
1596              return lhs->evalInt() <= rhs->evalInt();              return lhs <= rhs;
1597          case GREATER_OR_EQUAL:          case Relation::GREATER_OR_EQUAL:
1598              return lhs->evalInt() >= rhs->evalInt();              return lhs >= rhs;
1599          case EQUAL:          case Relation::EQUAL:
1600              if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR)              return RelComparer<typeof(lhs),typeof(rhs)>::isEqual(lhs, rhs);
1601            case Relation::NOT_EQUAL:
1602                return RelComparer<typeof(lhs),typeof(rhs)>::isUnequal(lhs, rhs);
1603        }
1604        return 0;
1605    }
1606    
1607    template<class T_LVALUE, class T_RVALUE, class T_LEXPR, class T_REXPR>
1608    inline vmint _evalRealRelation(Relation::Type type,
1609                                   T_LVALUE lvalue, T_RVALUE rvalue,
1610                                   T_LEXPR* pLHS, T_REXPR* pRHS)
1611    {
1612        if (pLHS->unitFactor() == pRHS->unitFactor())
1613            return _evalRelation(type, lvalue, rvalue);
1614        if (pLHS->unitFactor() < pRHS->unitFactor())
1615            return _evalRelation(type, lvalue, Unit::convRealToUnitFactor(rvalue, pRHS, pLHS));
1616        else
1617            return _evalRelation(type, Unit::convRealToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1618    }
1619    
1620    template<class T_LEXPR, class T_REXPR>
1621    inline vmint _evalIntRelation(Relation::Type type,
1622                                  vmint lvalue, vmint rvalue,
1623                                  T_LEXPR* pLHS, T_REXPR* pRHS)
1624    {
1625        if (pLHS->unitFactor() == pRHS->unitFactor())
1626            return _evalRelation(type, lvalue, rvalue);
1627        if (pLHS->unitFactor() < pRHS->unitFactor())
1628            return _evalRelation(type, lvalue, Unit::convIntToUnitFactor(rvalue, pRHS, pLHS));
1629        else
1630            return _evalRelation(type, Unit::convIntToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1631    }
1632    
1633    vmint Relation::evalInt() {
1634        const ExprType_t lType = lhs->exprType();
1635        const ExprType_t rType = rhs->exprType();
1636        if (lType == STRING_EXPR || rType == STRING_EXPR) {
1637            switch (type) {
1638                case EQUAL:
1639                  return lhs->evalCastToStr() == rhs->evalCastToStr();                  return lhs->evalCastToStr() == rhs->evalCastToStr();
1640              else              case NOT_EQUAL:
                 return lhs->evalInt() == rhs->evalInt();  
         case NOT_EQUAL:  
             if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR)  
1641                  return lhs->evalCastToStr() != rhs->evalCastToStr();                  return lhs->evalCastToStr() != rhs->evalCastToStr();
1642              else              default:
1643                  return lhs->evalInt() != rhs->evalInt();                  return 0;
1644            }
1645        } else if (lType == REAL_EXPR && rType == REAL_EXPR) {
1646            vmfloat lvalue = lhs->asReal()->evalReal();
1647            vmfloat rvalue = rhs->asReal()->evalReal();
1648            return _evalRealRelation(
1649                type, lvalue, rvalue, lhs->asReal(), rhs->asReal()
1650            );
1651        } else if (lType == REAL_EXPR && rType == INT_EXPR) {
1652            vmfloat lvalue = lhs->asReal()->evalReal();
1653            vmint rvalue = rhs->asInt()->evalInt();
1654            return _evalRealRelation(
1655                type, lvalue, rvalue, lhs->asReal(), rhs->asInt()
1656            );
1657        } else if (lType == INT_EXPR && rType == REAL_EXPR) {
1658            vmint lvalue = lhs->asInt()->evalInt();
1659            vmfloat rvalue = rhs->asReal()->evalReal();
1660            return _evalRealRelation(
1661                type, lvalue, rvalue, lhs->asInt(), rhs->asReal()
1662            );
1663        } else {
1664            vmint lvalue = lhs->asInt()->evalInt();
1665            vmint rvalue = rhs->asInt()->evalInt();
1666            return _evalIntRelation(
1667                type, lvalue, rvalue, lhs->asInt(), rhs->asInt()
1668            );
1669      }      }
     return 0;  
1670  }  }
1671    
1672  void Relation::dump(int level) {  void Relation::dump(int level) {
# Line 815  bool Relation::isConstExpr() const { Line 1703  bool Relation::isConstExpr() const {
1703      return lhs->isConstExpr() && rhs->isConstExpr();      return lhs->isConstExpr() && rhs->isConstExpr();
1704  }  }
1705    
1706  int Or::evalInt() {  vmint Or::evalInt() {
1707      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1708      if (pLHS->evalInt()) return 1;      if (pLHS->evalInt()) return 1;
1709      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);;      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1710      return (pRHS->evalInt()) ? 1 : 0;      return (pRHS->evalInt()) ? 1 : 0;
1711  }  }
1712    
# Line 833  void Or::dump(int level) { Line 1721  void Or::dump(int level) {
1721      printf(")\n");      printf(")\n");
1722  }  }
1723    
1724  int BitwiseOr::evalInt() {  vmint BitwiseOr::evalInt() {
1725      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1726      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1727      return pLHS->evalInt() | pRHS->evalInt();      return pLHS->evalInt() | pRHS->evalInt();
# Line 850  void BitwiseOr::dump(int level) { Line 1738  void BitwiseOr::dump(int level) {
1738      printf(")\n");      printf(")\n");
1739  }  }
1740    
1741  int And::evalInt() {  vmint And::evalInt() {
1742      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1743      if (!pLHS->evalInt()) return 0;      if (!pLHS->evalInt()) return 0;
1744      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
# Line 868  void And::dump(int level) { Line 1756  void And::dump(int level) {
1756      printf(")\n");      printf(")\n");
1757  }  }
1758    
1759  int BitwiseAnd::evalInt() {  vmint BitwiseAnd::evalInt() {
1760      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1761      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1762      return pLHS->evalInt() & pRHS->evalInt();      return pLHS->evalInt() & pRHS->evalInt();
# Line 901  void BitwiseNot::dump(int level) { Line 1789  void BitwiseNot::dump(int level) {
1789      printf(")\n");      printf(")\n");
1790  }  }
1791    
1792    String Final::evalCastToStr() {
1793        if (exprType() == REAL_EXPR)
1794            return ToString(evalReal());
1795        else
1796            return ToString(evalInt());
1797    }
1798    
1799    void Final::dump(int level) {
1800        printIndents(level);
1801        printf("Final(\n");
1802        expr->dump(level+1);
1803        printIndents(level);
1804        printf(")\n");
1805    }
1806    
1807  StatementsRef ParserContext::userFunctionByName(const String& name) {  StatementsRef ParserContext::userFunctionByName(const String& name) {
1808      if (!userFnTable.count(name)) {      if (!userFnTable.count(name)) {
1809          return StatementsRef();          return StatementsRef();
# Line 929  IntVariableRef ParserContext::globalIntV Line 1832  IntVariableRef ParserContext::globalIntV
1832      return globalVar(name);      return globalVar(name);
1833  }  }
1834    
1835    RealVariableRef ParserContext::globalRealVar(const String& name) {
1836        return globalVar(name);
1837    }
1838    
1839  StringVariableRef ParserContext::globalStrVar(const String& name) {  StringVariableRef ParserContext::globalStrVar(const String& name) {
1840      return globalVar(name);      return globalVar(name);
1841  }  }
# Line 939  ParserContext::~ParserContext() { Line 1846  ParserContext::~ParserContext() {
1846          delete globalIntMemory;          delete globalIntMemory;
1847          globalIntMemory = NULL;          globalIntMemory = NULL;
1848      }      }
1849        if (globalRealMemory) {
1850            delete globalRealMemory;
1851            globalRealMemory = NULL;
1852        }
1853  }  }
1854    
1855  void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {  void ParserContext::addErr(int firstLine, int lastLine, int firstColumn,
1856                               int lastColumn, int firstByte, int lengthBytes,
1857                               const char* txt)
1858    {
1859      ParserIssue e;      ParserIssue e;
1860      e.type = PARSER_ERROR;      e.type = PARSER_ERROR;
1861      e.txt = txt;      e.txt = txt;
# Line 949  void ParserContext::addErr(int firstLine Line 1863  void ParserContext::addErr(int firstLine
1863      e.lastLine = lastLine;      e.lastLine = lastLine;
1864      e.firstColumn = firstColumn;      e.firstColumn = firstColumn;
1865      e.lastColumn = lastColumn;      e.lastColumn = lastColumn;
1866        e.firstByte = firstByte;
1867        e.lengthBytes = lengthBytes;
1868      vErrors.push_back(e);      vErrors.push_back(e);
1869      vIssues.push_back(e);      vIssues.push_back(e);
1870  }  }
1871    
1872  void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {  void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn,
1873                               int lastColumn, int firstByte, int lengthBytes,
1874                               const char* txt)
1875    {
1876      ParserIssue w;      ParserIssue w;
1877      w.type = PARSER_WARNING;      w.type = PARSER_WARNING;
1878      w.txt = txt;      w.txt = txt;
# Line 961  void ParserContext::addWrn(int firstLine Line 1880  void ParserContext::addWrn(int firstLine
1880      w.lastLine = lastLine;      w.lastLine = lastLine;
1881      w.firstColumn = firstColumn;      w.firstColumn = firstColumn;
1882      w.lastColumn = lastColumn;      w.lastColumn = lastColumn;
1883        w.firstByte = firstByte;
1884        w.lengthBytes = lengthBytes;
1885      vWarnings.push_back(w);      vWarnings.push_back(w);
1886      vIssues.push_back(w);      vIssues.push_back(w);
1887  }  }
1888    
1889    void ParserContext::addPreprocessorComment(int firstLine, int lastLine,
1890                                               int firstColumn, int lastColumn,
1891                                               int firstByte, int lengthBytes)
1892    {
1893        CodeBlock block;
1894        block.firstLine = firstLine;
1895        block.lastLine = lastLine;
1896        block.firstColumn = firstColumn;
1897        block.lastColumn = lastColumn;
1898        block.firstByte = firstByte;
1899        block.lengthBytes = lengthBytes;
1900        vPreprocessorComments.push_back(block);
1901    }
1902    
1903  bool ParserContext::setPreprocessorCondition(const char* name) {  bool ParserContext::setPreprocessorCondition(const char* name) {
1904      if (builtinPreprocessorConditions.count(name)) return false;      if (builtinPreprocessorConditions.count(name)) return false;
1905      if (userPreprocessorConditions.count(name)) return false;      if (userPreprocessorConditions.count(name)) return false;
# Line 996  std::vector<ParserIssue> ParserContext:: Line 1931  std::vector<ParserIssue> ParserContext::
1931      return vWarnings;      return vWarnings;
1932  }  }
1933    
1934    std::vector<CodeBlock> ParserContext::preprocessorComments() const {
1935        return vPreprocessorComments;
1936    }
1937    
1938  VMEventHandler* ParserContext::eventHandler(uint index) {  VMEventHandler* ParserContext::eventHandler(uint index) {
1939      if (!handlers) return NULL;      if (!handlers) return NULL;
1940      return handlers->eventHandler(index);      return handlers->eventHandler(index);
# Line 1006  VMEventHandler* ParserContext::eventHand Line 1945  VMEventHandler* ParserContext::eventHand
1945      return handlers->eventHandlerByName(name);      return handlers->eventHandlerByName(name);
1946  }  }
1947    
1948  void ParserContext::registerBuiltInConstIntVariables(const std::map<String,int>& vars) {  void ParserContext::registerBuiltInConstIntVariables(const std::map<String,vmint>& vars) {
1949      for (std::map<String,int>::const_iterator it = vars.begin();      for (std::map<String,vmint>::const_iterator it = vars.begin();
1950             it != vars.end(); ++it)
1951        {
1952            ConstIntVariableRef ref = new ConstIntVariable({
1953                .value = it->second
1954            });
1955            vartable[it->first] = ref;
1956        }
1957    }
1958    
1959    void ParserContext::registerBuiltInConstRealVariables(const std::map<String,vmfloat>& vars) {
1960        for (std::map<String,vmfloat>::const_iterator it = vars.begin();
1961           it != vars.end(); ++it)           it != vars.end(); ++it)
1962      {      {
1963          ConstIntVariableRef ref = new ConstIntVariable(it->second);          ConstRealVariableRef ref = new ConstRealVariable({
1964                .value = it->second
1965            });
1966          vartable[it->first] = ref;          vartable[it->first] = ref;
1967      }      }
1968  }  }
1969    
1970  void ParserContext::registerBuiltInIntVariables(const std::map<String,VMIntRelPtr*>& vars) {  void ParserContext::registerBuiltInIntVariables(const std::map<String,VMIntPtr*>& vars) {
1971      for (std::map<String,VMIntRelPtr*>::const_iterator it = vars.begin();      for (std::map<String,VMIntPtr*>::const_iterator it = vars.begin();
1972           it != vars.end(); ++it)           it != vars.end(); ++it)
1973      {      {
1974          BuiltInIntVariableRef ref = new BuiltInIntVariable(it->first, it->second);          BuiltInIntVariableRef ref = new BuiltInIntVariable(it->first, it->second);
# Line 1042  void ParserContext::registerBuiltInDynVa Line 1994  void ParserContext::registerBuiltInDynVa
1994      }      }
1995  }  }
1996    
1997    ExecContext::ExecContext() :
1998        status(VM_EXEC_NOT_RUNNING), flags(STMT_SUCCESS), stackFrame(-1),
1999        suspendMicroseconds(0), instructionsCount(0)
2000    {
2001        exitRes.value = NULL;
2002    }
2003    
2004    void ExecContext::forkTo(VMExecContext* ectx) const {
2005        ExecContext* child = dynamic_cast<ExecContext*>(ectx);
2006    
2007        child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory);
2008        child->polyphonicRealMemory.copyFlatFrom(polyphonicRealMemory);
2009        child->status = VM_EXEC_SUSPENDED;
2010        child->flags = STMT_SUCCESS;
2011        child->stack.copyFlatFrom(stack);
2012        child->stackFrame = stackFrame;
2013        child->suspendMicroseconds = 0;
2014        child->instructionsCount = 0;
2015    }
2016    
2017  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.3257  
changed lines
  Added in v.3747

  ViewVC Help
Powered by ViewVC