/[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 3561 by schoenebeck, Fri Aug 23 11:44:00 2019 UTC revision 3804 by schoenebeck, Thu Aug 6 12:15:02 2020 UTC
# 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      return statement->statementType() == STMT_NOOP;      return statement->statementType() == STMT_NOOP;
22  }  }
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() {
62  }  }
# Line 30  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() {  String IntArrayExpr::evalCastToStr() {
156      String s = "{";      String s = "{";
157      for (vmint i = 0; i < arraySize(); ++i) {      for (vmint i = 0; i < arraySize(); ++i) {
158          vmint val = evalIntElement(i);          vmint val = evalIntElement(i);
159            vmfloat factor = unitFactorOfElement(i);
160          if (i) s += ",";          if (i) s += ",";
161          s += ToString(val);          s += ToString(val) + _unitFactorToShortStr(factor);
162      }      }
163      s += "}";      s += "}";
164      return s;      return s;
165  }  }
166    
167  MetricPrefix_t Unit::unitPrefix(vmuint i) const {  String RealArrayExpr::evalCastToStr() {
168      if (i >= prefix.size()) return VM_NO_PREFIX;      String s = "{";
169      return prefix[i];      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  void Unit::setUnit(const std::vector<MetricPrefix_t>& prefix, StdUnit_t type) {  IntLiteral::IntLiteral(const IntLitDef& def) :
180      this->prefix.resize( prefix.size() );      IntExpr(), Unit(def.unitType),
181      for (vmuint i = 0; i < prefix.size(); ++i)      value(def.value), unitPrefixFactor(def.unitFactor),
182          this->prefix[i] = prefix[i];      finalVal(def.isFinal)
183    {
184    }
185    
186      unit = type;  vmint IntLiteral::evalInt() {
187        return value;
188  }  }
189    
190  void Unit::setUnit(const MetricPrefix_t* prefixes, StdUnit_t type) {  void IntLiteral::dump(int level) {
191      unit = type;      printIndents(level);
192      prefix.clear();      printf("IntLiteral %" PRId64 "\n", (int64_t)value);
     for (int i = 0; i < 2 && prefixes[i]; ++i)  
         prefix.add(prefixes[i]);  
193  }  }
194    
195  void Unit::copyUnitFrom(const IntExprRef& src) {  RealLiteral::RealLiteral(const RealLitDef& def) :
196      unit = src->unitType();      RealExpr(), Unit(def.unitType),
197      prefix.clear();      value(def.value), unitPrefixFactor(def.unitFactor),
198      for (int i = 0; true; ++i) {      finalVal(def.isFinal)
199          MetricPrefix_t p = src->unitPrefix(i);  {
         if (!p) return;  
         prefix.add(p);  
     }  
200  }  }
201    
202  vmint IntLiteral::evalInt() {  vmfloat RealLiteral::evalReal() {
203      return value;      return value;
204  }  }
205    
206  void IntLiteral::dump(int level) {  void RealLiteral::dump(int level) {
207      printIndents(level);      printIndents(level);
208      printf("IntLiteral %lld\n", value);      printf("RealLiteral %f\n", value);
209  }  }
210    
211  void StringLiteral::dump(int level) {  void StringLiteral::dump(int level) {
# Line 89  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    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() {  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 106  void Add::dump(int level) { Line 269  void Add::dump(int level) {
269      printf(")\n");      printf(")\n");
270  }  }
271    
272    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() {  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 123  void Sub::dump(int level) { Line 325  void Sub::dump(int level) {
325      printf(")\n");      printf(")\n");
326  }  }
327    
328    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() {  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 140  void Mul::dump(int level) { Line 357  void Mul::dump(int level) {
357      printf(")\n");      printf(")\n");
358  }  }
359    
360  MetricPrefix_t Mul::unitPrefix(vmuint i) const {  vmfloat Mul::unitFactor() const {
361      const IntExpr* pLHS = dynamic_cast<const IntExpr*>(&*lhs);      const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
362      const IntExpr* pRHS = dynamic_cast<const IntExpr*>(&*rhs);      const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
363      // currently the NKSP parser only allows a unit prefix on either side      return pLHS->unitFactor() * pRHS->unitFactor();
     return (pLHS->unitPrefix(0)) ? pLHS->unitPrefix(i) : pRHS->unitPrefix(i);  
364  }  }
365    
366  StdUnit_t Mul::unitType() const {  Div::Div(NumberExprRef lhs, NumberExprRef rhs) :
367      const IntExpr* pLHS = dynamic_cast<const IntExpr*>(&*lhs);      VaritypeScalarBinaryOp(lhs, rhs),
368      const IntExpr* pRHS = dynamic_cast<const IntExpr*>(&*rhs);      Unit(
369      // currently the NKSP parser only allows a unit type on either side          // the NKSP parser only allows either A) a unit type on left side and none
370      return (pLHS->unitType()) ? pLHS->unitType() : pRHS->unitType();          // 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() {  vmint Div::evalInt() {
# Line 164  vmint Div::evalInt() { Line 383  vmint Div::evalInt() {
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 175  void Div::dump(int level) { Line 404  void Div::dump(int level) {
404      printf(")\n");      printf(")\n");
405  }  }
406    
407  MetricPrefix_t Div::unitPrefix(vmuint i) const {  vmfloat Div::unitFactor() const {
408      const IntExpr* pLHS = dynamic_cast<const IntExpr*>(&*lhs);      const NumberExpr* pLHS = dynamic_cast<const NumberExpr*>(&*lhs);
409      const IntExpr* pRHS = dynamic_cast<const IntExpr*>(&*rhs);      const NumberExpr* pRHS = dynamic_cast<const NumberExpr*>(&*rhs);
410      // currently the NKSP parser only allows either A) a unit prefix on left      return pLHS->unitFactor() / pRHS->unitFactor();
     // side and none on right side or B) an identical unit prefix on both sides  
     return (pLHS->unitPrefix(0) && pRHS->unitPrefix(0)) ? VM_NO_PREFIX : pLHS->unitPrefix(i);  
 }  
   
 StdUnit_t Div::unitType() const {  
     const IntExpr* pLHS = dynamic_cast<const IntExpr*>(&*lhs);  
     const IntExpr* pRHS = dynamic_cast<const IntExpr*>(&*rhs);  
     // the NKSP parser only allows either A) a unit type on left side and none  
     // on right side or B) an identical unit type on both sides  
     return (pLHS->unitType() && pRHS->unitType()) ? VM_NO_UNIT : pLHS->unitType();  
411  }  }
412    
413  vmint Mod::evalInt() {  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 282  StmtFlags_t Assignment::exec() { Line 501  StmtFlags_t Assignment::exec() {
501      return STMT_SUCCESS;      return STMT_SUCCESS;
502  }  }
503    
504  EventHandler::EventHandler(StatementsRef statements) {  Subroutine::Subroutine(StatementsRef statements) {
505      this->statements = statements;      this->statements = statements;
506    }
507    
508    void Subroutine::dump(int level) {
509        printIndents(level);
510        printf("Subroutine {\n");
511        statements->dump(level+1);
512        printIndents(level);
513        printf("}\n");
514    }
515    
516    UserFunction::UserFunction(StatementsRef statements)
517        : Subroutine(statements)
518    {
519    }
520    
521    EventHandler::EventHandler(StatementsRef statements)
522        : Subroutine(statements)
523    {
524      usingPolyphonics = statements->isPolyphonic();      usingPolyphonics = statements->isPolyphonic();
525  }  }
526    
527  void EventHandler::dump(int level) {  void EventHandler::dump(int level) {
528      printIndents(level);      printIndents(level);
529      printf("EventHandler {\n");      printf("EventHandler {\n");
530      statements->dump(level+1);      Subroutine::dump(level+1);
531      printIndents(level);      printIndents(level);
532      printf("}\n");      printf("}\n");
533  }  }
# Line 317  bool Statements::isPolyphonic() const { Line 554  bool Statements::isPolyphonic() const {
554      return false;      return false;
555  }  }
556    
557  DynamicVariableCall::DynamicVariableCall(const String& name, ParserContext* ctx, VMDynVar* v)  DynamicVariableCall::DynamicVariableCall(const String& name, ParserContext* ctx, VMDynVar* v) :
558      : Variable(ctx, 0, false), dynVar(v), varName(name)      Variable({
559            .ctx = ctx,
560            .elements = 0
561        }),
562        Unit(VM_NO_UNIT),
563        dynVar(v), varName(name)
564  {  {
565  }  }
566    
# Line 348  void DynamicVariableCall::dump(int level Line 590  void DynamicVariableCall::dump(int level
590      printf("Dynamic Variable '%s'\n", varName.c_str());      printf("Dynamic Variable '%s'\n", varName.c_str());
591  }  }
592    
593    FunctionCall::FunctionCall(const char* function, ArgsRef args, VMFunction* fn) :
594        Unit(
595            (fn) ? fn->returnUnitType(dynamic_cast<VMFnArgs*>(&*args)) : VM_NO_UNIT
596        ),
597        functionName(function), args(args), fn(fn),
598        result( (fn) ? fn->allocResult(dynamic_cast<VMFnArgs*>(&*args)) : NULL )
599    {
600    }
601    
602    FunctionCall::~FunctionCall() {
603        if (result) {
604            delete result;
605            result = NULL;
606        }
607    }
608    
609  void FunctionCall::dump(int level) {  void FunctionCall::dump(int level) {
610      printIndents(level);      printIndents(level);
611      printf("FunctionCall '%s' args={\n", functionName.c_str());      printf("FunctionCall '%s' args={\n", functionName.c_str());
# Line 358  void FunctionCall::dump(int level) { Line 616  void FunctionCall::dump(int level) {
616    
617  ExprType_t FunctionCall::exprType() const {  ExprType_t FunctionCall::exprType() const {
618      if (!fn) return EMPTY_EXPR;      if (!fn) return EMPTY_EXPR;
619      return fn->returnType();      FunctionCall* self = const_cast<FunctionCall*>(this);
620        return fn->returnType(dynamic_cast<VMFnArgs*>(&*self->args));
621    }
622    
623    vmfloat FunctionCall::unitFactor() const {
624        if (!fn || !result) return VM_NO_FACTOR;
625        VMExpr* expr = result->resultValue();
626        if (!expr) return VM_NO_FACTOR;
627        VMNumberExpr* scalar = expr->asNumber();
628        if (!scalar) return VM_NO_FACTOR;
629        return scalar->unitFactor();
630    }
631    
632    bool FunctionCall::isFinal() const {
633        if (!fn) return false;
634        FunctionCall* self = const_cast<FunctionCall*>(this);
635        return fn->returnsFinal(dynamic_cast<VMFnArgs*>(&*self->args));
636  }  }
637    
638  VMFnResult* FunctionCall::execVMFn() {  VMFnResult* FunctionCall::execVMFn() {
639      if (!fn) return NULL;      if (!fn) return NULL;
640    
641        // tell function where it shall dump its return value to
642        VMFnResult* oldRes = fn->boundResult();
643        fn->bindResult(result);
644    
645      // assuming here that all argument checks (amount and types) have been made      // assuming here that all argument checks (amount and types) have been made
646      // at parse time, to avoid time intensive checks on each function call      // at parse time, to avoid time intensive checks on each function call
647      return fn->exec(dynamic_cast<VMFnArgs*>(&*args));      VMFnResult* res = fn->exec(dynamic_cast<VMFnArgs*>(&*args));
648    
649        // restore previous result binding of some potential toplevel or concurrent
650        // caller, i.e. if exactly same function is called more than one time,
651        // concurrently in a term by other FunctionCall objects, e.g.:
652        // ~c := ceil( ceil(~a) + ~b)
653        fn->bindResult(oldRes);
654    
655        if (!res) return res;
656    
657        VMExpr* expr = res->resultValue();
658        if (!expr) return res;
659    
660        // For performance reasons we always only let 'FunctionCall' assign the unit
661        // type to the function's result expression, never by the function
662        // implementation itself, nor by other classes, because a FunctionCall
663        // object solely knows the unit type in O(1).
664        ExprType_t type = expr->exprType();
665        if (type == INT_EXPR) {
666            VMIntResult* intRes = dynamic_cast<VMIntResult*>(res);
667            intRes->unitBaseType = unitType();
668        } else if (type == REAL_EXPR) {
669            VMRealResult* realRes = dynamic_cast<VMRealResult*>(res);
670            realRes->unitBaseType = unitType();
671        }
672    
673        return res;
674  }  }
675    
676  StmtFlags_t FunctionCall::exec() {  StmtFlags_t FunctionCall::exec() {
# Line 383  vmint FunctionCall::evalInt() { Line 688  vmint FunctionCall::evalInt() {
688      return intExpr->evalInt();      return intExpr->evalInt();
689  }  }
690    
691    vmfloat FunctionCall::evalReal() {
692        VMFnResult* result = execVMFn();
693        if (!result) return 0;
694        VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
695        if (!realExpr) return 0;
696        return realExpr->evalReal();
697    }
698    
699  VMIntArrayExpr* FunctionCall::asIntArray() const {  VMIntArrayExpr* FunctionCall::asIntArray() const {
700      VMFnResult* result = const_cast<FunctionCall*>(this)->execVMFn();      //FIXME: asIntArray() not intended for evaluation semantics (for both
701        // performance reasons with arrays, but also to prevent undesired value
702        // mutation by implied (hidden) evaluation, as actually done here. We must
703        // force function evaluation here though, because we need it for function
704        // calls to be evaluated at all. This issue should be addressed cleanly by
705        // adjusting the API appropriately.
706        FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
707        VMFnResult* result = rwSelf->execVMFn();
708    
709      if (!result) return 0;      if (!result) return 0;
710      VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());      VMIntArrayExpr* intArrExpr = dynamic_cast<VMIntArrayExpr*>(result->resultValue());
711      return intArrExpr;      return intArrExpr;
712  }  }
713    
714    VMRealArrayExpr* FunctionCall::asRealArray() const {
715        //FIXME: asRealArray() not intended for evaluation semantics (for both
716        // performance reasons with arrays, but also to prevent undesired value
717        // mutation by implied (hidden) evaluation, as actually done here. We must
718        // force function evaluation here though, because we need it for function
719        // calls to be evaluated at all. This issue should be addressed cleanly by
720        // adjusting the API appropriately.
721        FunctionCall* rwSelf = const_cast<FunctionCall*>(this);
722        VMFnResult* result = rwSelf->execVMFn();
723    
724        if (!result) return 0;
725        VMRealArrayExpr* realArrExpr = dynamic_cast<VMRealArrayExpr*>(result->resultValue());
726        return realArrExpr;
727    }
728    
729  String FunctionCall::evalStr() {  String FunctionCall::evalStr() {
730      VMFnResult* result = execVMFn();      VMFnResult* result = execVMFn();
731      if (!result) return "";      if (!result) return "";
# Line 401  String FunctionCall::evalStr() { Line 737  String FunctionCall::evalStr() {
737  String FunctionCall::evalCastToStr() {  String FunctionCall::evalCastToStr() {
738      VMFnResult* result = execVMFn();      VMFnResult* result = execVMFn();
739      if (!result) return "";      if (!result) return "";
740      if (result->resultValue()->exprType() == STRING_EXPR) {      const ExprType_t resultType = result->resultValue()->exprType();
741        if (resultType == STRING_EXPR) {
742          VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());          VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(result->resultValue());
743          return strExpr ? strExpr->evalStr() : "";          return strExpr ? strExpr->evalStr() : "";
744        } else if (resultType == REAL_EXPR) {
745            VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(result->resultValue());
746            return realExpr ? ToString(realExpr->evalReal()) + _unitToStr(realExpr) : "";
747      } else {      } else {
748          VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());          VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(result->resultValue());
749          return intExpr ? ToString(intExpr->evalInt()) : "";          return intExpr ? ToString(intExpr->evalInt()) + _unitToStr(intExpr) : "";
750      }      }
751  }  }
752    
753  IntVariable::IntVariable(ParserContext* ctx)  Variable::Variable(const VariableDecl& decl) :
754      : Variable(ctx, ctx ? ctx->globalIntVarCount++ : 0, false),      context(decl.ctx), memPos(decl.memPos), bConst(decl.isConst)
       Unit(),  
       polyphonic(false), finalVal(false)  
755  {  {
756      //printf("globalIntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);  }
757      assert(ctx);  
758    NumberVariable::NumberVariable(const VariableDecl& decl) :
759        Variable(decl),
760        Unit(decl.unitType),
761        unitFactorMemPos(decl.unitFactorMemPos), polyphonic(decl.isPolyphonic),
762        finalVal(decl.isFinal)
763    {
764    }
765    
766    vmfloat NumberVariable::unitFactor() const {
767        if (isPolyphonic()) {
768            return context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos];
769        }
770        return (*context->globalUnitFactorMemory)[unitFactorMemPos];
771  }  }
772    
773  inline static vmint postfixInc(vmint& object, vmint incBy) {  inline static vmint postfixInc(vmint& object, vmint incBy) {
# Line 425  inline static vmint postfixInc(vmint& ob Line 776  inline static vmint postfixInc(vmint& ob
776      return i;      return i;
777  }  }
778    
779  IntVariable::IntVariable(ParserContext* ctx, bool polyphonic, bool bConst, vmint size)  IntVariable::IntVariable(const VariableDecl& decl) :
780      : Variable(ctx, !ctx ? 0 : polyphonic ? postfixInc(ctx->polyphonicIntVarCount, size) : postfixInc(ctx->globalIntVarCount, size), bConst),      NumberVariable({
781        Unit(),          .ctx = decl.ctx,
782        polyphonic(polyphonic), finalVal(false)          .isPolyphonic = decl.isPolyphonic,
783  {          .isConst = decl.isConst,
784      //printf("InvVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx);          .elements = decl.elements,
785      if (polyphonic) {          .memPos = (
786          //printf("polyIntVar memPOS=%d\n", memPos);              (!decl.ctx) ? 0 :
787          assert(ctx);                  (decl.isPolyphonic) ?
788      }                      postfixInc(decl.ctx->polyphonicIntVarCount, decl.elements) :
789                        postfixInc(decl.ctx->globalIntVarCount, decl.elements)
790            ),
791            .unitFactorMemPos = (
792                (!decl.ctx) ? 0 :
793                    (decl.isPolyphonic) ?
794                        postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
795                        postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
796            ),
797            .unitType = decl.unitType,
798            .isFinal = decl.isFinal,
799        }),
800        Unit(decl.unitType)
801    {
802        //printf("IntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
803        assert(!decl.isPolyphonic || decl.ctx);
804  }  }
805    
806  void IntVariable::assign(Expression* expr) {  void IntVariable::assign(Expression* expr) {
807      IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);      IntExpr* intExpr = dynamic_cast<IntExpr*>(expr);
808      if (intExpr) {      if (intExpr) {
809          if (polyphonic)          //NOTE: sequence matters! evalInt() must be called before getting unitFactor() !
810            if (isPolyphonic()) {
811              context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();              context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt();
812          else              context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = intExpr->unitFactor();
813            } else {
814              (*context->globalIntMemory)[memPos] = intExpr->evalInt();              (*context->globalIntMemory)[memPos] = intExpr->evalInt();
815                (*context->globalUnitFactorMemory)[unitFactorMemPos] = intExpr->unitFactor();
816            }
817      }      }
818  }  }
819    
820  vmint IntVariable::evalInt() {  vmint IntVariable::evalInt() {
821      //printf("IntVariable::eval pos=%d\n", memPos);      //printf("IntVariable::eval pos=%d\n", memPos);
822      if (polyphonic) {      if (isPolyphonic()) {
823          //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);
824          return context->execContext->polyphonicIntMemory[memPos];          return context->execContext->polyphonicIntMemory[memPos];
825      }      }
# Line 462  void IntVariable::dump(int level) { Line 832  void IntVariable::dump(int level) {
832      //printf("IntVariable memPos=%d\n", memPos);      //printf("IntVariable memPos=%d\n", memPos);
833  }  }
834    
835  //ConstIntVariable::ConstIntVariable(ParserContext* ctx, int value)  RealVariable::RealVariable(const VariableDecl& decl) :
836  ConstIntVariable::ConstIntVariable(vmint value)      NumberVariable({
837      : IntVariable(NULL,false,true), value(value)          .ctx = decl.ctx,
838            .isPolyphonic = decl.isPolyphonic,
839            .isConst = decl.isConst,
840            .elements = decl.elements,
841            .memPos = (
842                (!decl.ctx) ? 0 :
843                    (decl.isPolyphonic) ?
844                        postfixInc(decl.ctx->polyphonicRealVarCount, decl.elements) :
845                        postfixInc(decl.ctx->globalRealVarCount, decl.elements)
846            ),
847            .unitFactorMemPos = (
848                (!decl.ctx) ? 0 :
849                    (decl.isPolyphonic) ?
850                        postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) :
851                        postfixInc(decl.ctx->globalUnitFactorCount, decl.elements)
852            ),
853            .unitType = decl.unitType,
854            .isFinal = decl.isFinal,
855        }),
856        Unit(decl.unitType)
857    {
858        //printf("RealVar parserctx=0x%lx memPOS=%d\n", ctx, memPos);
859        assert(!decl.isPolyphonic || decl.ctx);
860    }
861    
862    void RealVariable::assign(Expression* expr) {
863        RealExpr* realExpr = dynamic_cast<RealExpr*>(expr);
864        if (realExpr) {
865            //NOTE: sequence matters! evalReal() must be called before getting unitFactor() !
866            if (isPolyphonic()) {
867                context->execContext->polyphonicRealMemory[memPos] = realExpr->evalReal();
868                context->execContext->polyphonicUnitFactorMemory[unitFactorMemPos] = realExpr->unitFactor();
869            } else {
870                (*context->globalRealMemory)[memPos] = realExpr->evalReal();
871                (*context->globalUnitFactorMemory)[unitFactorMemPos] = realExpr->unitFactor();
872            }
873        }
874    }
875    
876    vmfloat RealVariable::evalReal() {
877        //printf("RealVariable::eval pos=%d\n", memPos);
878        if (isPolyphonic()) {
879            //printf("evalReal() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext);
880            return context->execContext->polyphonicRealMemory[memPos];
881        }
882        return (*context->globalRealMemory)[memPos];
883    }
884    
885    void RealVariable::dump(int level) {
886        printIndents(level);
887        printf("RealVariable\n");
888        //printf("RealVariable memPos=%d\n", memPos);
889    }
890    
891    ConstIntVariable::ConstIntVariable(const IntVarDef& def) :
892        IntVariable({
893            .ctx = def.ctx,
894            .isPolyphonic = false,
895            .isConst = true,
896            .elements = 1,
897            .memPos = def.memPos,
898            .unitFactorMemPos = def.unitFactorMemPos,
899            .unitType = def.unitType,
900            .isFinal = def.isFinal,
901        }),
902        Unit(def.unitType),
903        value(def.value), unitPrefixFactor(def.unitFactor)
904  {  {
905  }  }
906    
# Line 485  vmint ConstIntVariable::evalInt() { Line 921  vmint ConstIntVariable::evalInt() {
921    
922  void ConstIntVariable::dump(int level) {  void ConstIntVariable::dump(int level) {
923      printIndents(level);      printIndents(level);
924      printf("ConstIntVariable val=%lld\n", value);      printf("ConstIntVariable val=%" PRId64 "\n", (int64_t)value);
925  }  }
926    
927  BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr)  ConstRealVariable::ConstRealVariable(const RealVarDef& def) :
928      : IntVariable(NULL,false,false), name(name), ptr(ptr)      RealVariable({
929            .ctx = def.ctx,
930            .isPolyphonic = false,
931            .isConst = true,
932            .elements = 1,
933            .memPos = def.memPos,
934            .unitFactorMemPos = def.unitFactorMemPos,
935            .unitType = def.unitType,
936            .isFinal = def.isFinal,
937        }),
938        Unit(def.unitType),
939        value(def.value), unitPrefixFactor(def.unitFactor)
940    {
941    }
942    
943    void ConstRealVariable::assign(Expression* expr) {
944        // ignore assignment
945    }
946    
947    vmfloat ConstRealVariable::evalReal() {
948        return value;
949    }
950    
951    void ConstRealVariable::dump(int level) {
952        printIndents(level);
953        printf("ConstRealVariable val=%f\n", value);
954    }
955    
956    BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) :
957        IntVariable({
958            .ctx = NULL,
959            .isPolyphonic = false,
960            .isConst = false, // may or may not be modifyable though!
961            .elements = 0,
962            .memPos = 0,
963            .unitFactorMemPos = 0,
964            .unitType = VM_NO_UNIT,
965            .isFinal = false,
966        }),
967        Unit(VM_NO_UNIT),
968        name(name), ptr(ptr)
969  {  {
970  }  }
971    
# Line 508  void BuiltInIntVariable::dump(int level) Line 984  void BuiltInIntVariable::dump(int level)
984      printf("Built-in IntVar '%s'\n", name.c_str());      printf("Built-in IntVar '%s'\n", name.c_str());
985  }  }
986    
987  PolyphonicIntVariable::PolyphonicIntVariable(ParserContext* ctx)  PolyphonicIntVariable::PolyphonicIntVariable(const VariableDecl& decl) :
988      : IntVariable(ctx,true,false)      IntVariable({
989            .ctx = decl.ctx,
990            .isPolyphonic = true,
991            .isConst = decl.isConst,
992            .elements = 1,
993            .memPos = 0,
994            .unitFactorMemPos = 0,
995            .unitType = decl.unitType,
996            .isFinal = decl.isFinal,
997        }),
998        Unit(decl.unitType)
999  {  {
1000  }  }
1001    
# Line 518  void PolyphonicIntVariable::dump(int lev Line 1004  void PolyphonicIntVariable::dump(int lev
1004      printf("PolyphonicIntVariable\n");      printf("PolyphonicIntVariable\n");
1005  }  }
1006    
1007  IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size)  PolyphonicRealVariable::PolyphonicRealVariable(const VariableDecl& decl) :
1008      : Variable(ctx, 0, false)      RealVariable({
1009            .ctx = decl.ctx,
1010            .isPolyphonic = true,
1011            .isConst = decl.isConst,
1012            .elements = 1,
1013            .memPos = 0,
1014            .unitFactorMemPos = 0,
1015            .unitType = decl.unitType,
1016            .isFinal = decl.isFinal,
1017        }),
1018        Unit(decl.unitType)
1019    {
1020    }
1021    
1022    void PolyphonicRealVariable::dump(int level) {
1023        printIndents(level);
1024        printf("PolyphonicRealVariable\n");
1025    }
1026    
1027    IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size) :
1028        Variable({
1029            .ctx = ctx,
1030            .isPolyphonic = false,
1031            .isConst = false,
1032            .elements = 0,
1033            .memPos = 0,
1034            .unitFactorMemPos = 0,
1035            .unitType = VM_NO_UNIT,
1036            .isFinal = false,
1037        })
1038  {  {
1039      values.resize(size);      values.resize(size);
1040      memset(&values[0], 0, size * sizeof(vmint));      memset(&values[0], 0, size * sizeof(vmint));
 }  
1041    
1042  IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size, ArgsRef values, bool _bConst)      unitFactors.resize(size);
1043      : Variable(ctx, 0, _bConst)      for (size_t i = 0; i < size; ++i)
1044            unitFactors[i] = VM_NO_FACTOR;
1045    }
1046    
1047    IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size,
1048                                       ArgsRef values, bool _bConst) :
1049        Variable({
1050            .ctx = ctx,
1051            .isPolyphonic = false,
1052            .isConst = _bConst,
1053            .elements = 0,
1054            .memPos = 0,
1055            .unitFactorMemPos = 0,
1056            .unitType = VM_NO_UNIT,
1057            .isFinal = false,
1058        })
1059  {  {
1060      this->values.resize(size);      this->values.resize(size);
1061        this->unitFactors.resize(size);
1062      for (vmint i = 0; i < values->argsCount(); ++i) {      for (vmint i = 0; i < values->argsCount(); ++i) {
1063          VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));          VMIntExpr* expr = dynamic_cast<VMIntExpr*>(values->arg(i));
1064          if (expr) this->values[i] = expr->evalInt();          if (expr) {
1065                this->values[i] = expr->evalInt();
1066                this->unitFactors[i] = expr->unitFactor();
1067            } else {
1068                this->values[i] = 0;
1069                this->unitFactors[i] = VM_NO_FACTOR;
1070            }
1071        }
1072        for (vmint i = values->argsCount(); i < size; ++i) {
1073            this->values[i] = 0;
1074            this->unitFactors[i] = VM_NO_FACTOR;
1075      }      }
1076  }  }
1077    
1078  IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst)  IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst) :
1079      : Variable(ctx, 0, bConst)      Variable({
1080            .ctx = ctx,
1081            .isPolyphonic = false,
1082            .isConst = bConst,
1083            .elements = 0,
1084            .memPos = 0,
1085            .unitFactorMemPos = 0,
1086            .unitType = VM_NO_UNIT,
1087            .isFinal = false,
1088        })
1089  {  {
1090  }  }
1091    
# Line 550  void IntArrayVariable::assignIntElement( Line 1099  void IntArrayVariable::assignIntElement(
1099      values[i] = value;      values[i] = value;
1100  }  }
1101    
1102    vmfloat IntArrayVariable::unitFactorOfElement(vmuint i) const {
1103        if (i >= unitFactors.size()) return VM_NO_FACTOR;
1104        return unitFactors[i];
1105    }
1106    
1107    void IntArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1108        if (i >= unitFactors.size()) return;
1109        unitFactors[i] = factor;
1110    }
1111    
1112  void IntArrayVariable::dump(int level) {  void IntArrayVariable::dump(int level) {
1113      printIndents(level);      printIndents(level);
1114      printf("IntArray(");      printf("IntArray(");
# Line 558  void IntArrayVariable::dump(int level) { Line 1117  void IntArrayVariable::dump(int level) {
1117              printf("\n");              printf("\n");
1118              printIndents(level+1);              printIndents(level+1);
1119          }          }
1120          printf("%lld, ", values[i]);          printf("%" PRId64 ", ", (int64_t)values[i]);
1121      }      }
1122      printIndents(level);      printIndents(level);
1123      printf(")\n");      printf(")\n");
1124  }  }
1125    
1126  BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name, VMInt8Array* array)  RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size) :
1127      : IntArrayVariable(NULL, false), name(name), array(array)      Variable({
1128            .ctx = ctx,
1129            .isPolyphonic = false,
1130            .isConst = false,
1131            .elements = 0,
1132            .memPos = 0,
1133            .unitFactorMemPos = 0,
1134            .unitType = VM_NO_UNIT,
1135            .isFinal = false,
1136        })
1137    {
1138        values.resize(size);
1139        memset(&values[0], 0, size * sizeof(vmfloat));
1140    
1141        unitFactors.resize(size);
1142        for (size_t i = 0; i < size; ++i)
1143            unitFactors[i] = VM_NO_FACTOR;
1144    }
1145    
1146    RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size,
1147                                         ArgsRef values, bool _bConst) :
1148        Variable({
1149            .ctx = ctx,
1150            .isPolyphonic = false,
1151            .isConst = _bConst,
1152            .elements = 0,
1153            .memPos = 0,
1154            .unitFactorMemPos = 0,
1155            .unitType = VM_NO_UNIT,
1156            .isFinal = false,
1157        })
1158    {
1159        this->values.resize(size);
1160        this->unitFactors.resize(size);
1161        for (vmint i = 0; i < values->argsCount(); ++i) {
1162            VMRealExpr* expr = dynamic_cast<VMRealExpr*>(values->arg(i));
1163            if (expr) {
1164                this->values[i] = expr->evalReal();
1165                this->unitFactors[i] = expr->unitFactor();
1166            } else {
1167                this->values[i] = (vmfloat) 0;
1168                this->unitFactors[i] = VM_NO_FACTOR;
1169            }
1170        }
1171        for (vmint i = values->argsCount(); i < size; ++i) {
1172            this->values[i] = (vmfloat) 0;
1173            this->unitFactors[i] = VM_NO_FACTOR;
1174        }
1175    }
1176    
1177    RealArrayVariable::RealArrayVariable(ParserContext* ctx, bool bConst) :
1178        Variable({
1179            .ctx = ctx,
1180            .isPolyphonic = false,
1181            .isConst = bConst,
1182            .elements = 0,
1183            .memPos = 0,
1184            .unitFactorMemPos = 0,
1185            .unitType = VM_NO_UNIT,
1186            .isFinal = false,
1187        })
1188    {
1189    }
1190    
1191    vmfloat RealArrayVariable::evalRealElement(vmuint i) {
1192        if (i >= values.size()) return 0;
1193        return values[i];
1194    }
1195    
1196    void RealArrayVariable::assignRealElement(vmuint i, vmfloat value) {
1197        if (i >= values.size()) return;
1198        values[i] = value;
1199    }
1200    
1201    vmfloat RealArrayVariable::unitFactorOfElement(vmuint i) const {
1202        if (i >= unitFactors.size()) return VM_NO_FACTOR;
1203        return unitFactors[i];
1204    }
1205    
1206    void RealArrayVariable::assignElementUnitFactor(vmuint i, vmfloat factor) {
1207        if (i >= unitFactors.size()) return;
1208        unitFactors[i] = factor;
1209    }
1210    
1211    void RealArrayVariable::dump(int level) {
1212        printIndents(level);
1213        printf("RealArray(");
1214        for (vmint i = 0; i < values.size(); ++i) {
1215            if (i % 12 == 0) {
1216                printf("\n");
1217                printIndents(level+1);
1218            }
1219            printf("%f, ", values[i]);
1220        }
1221        printIndents(level);
1222        printf(")\n");
1223    }
1224    
1225    BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name,
1226                                                     VMInt8Array* array) :
1227        IntArrayVariable(NULL, false),
1228        name(name), array(array)
1229  {  {
1230  }  }
1231    
# Line 583  void BuiltInIntArrayVariable::dump(int l Line 1243  void BuiltInIntArrayVariable::dump(int l
1243      printf("Built-In Int Array Variable '%s'\n", name.c_str());      printf("Built-In Int Array Variable '%s'\n", name.c_str());
1244  }  }
1245    
1246  IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex)  IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) :
1247      : IntVariable(NULL, false, false, 0), array(array), index(arrayIndex)      IntVariable({
1248  {              .ctx = NULL,
1249            .isPolyphonic = (array) ? array->isPolyphonic() : false,
1250            .isConst = (array) ? array->isConstExpr() : false,
1251            .elements = 0,
1252            .memPos = 0,
1253            .unitFactorMemPos = 0,
1254            .unitType = VM_NO_UNIT,
1255            .isFinal = false,
1256        }),
1257        Unit(VM_NO_UNIT),
1258        array(array), index(arrayIndex), currentIndex(-1)
1259    {
1260  }  }
1261    
1262  void IntArrayElement::assign(Expression* expr) {  void IntArrayElement::assign(Expression* expr) {
1263      IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);      IntExpr* valueExpr = dynamic_cast<IntExpr*>(expr);
1264      if (!valueExpr) return;      if (!valueExpr) return;
1265      vmint value = valueExpr->evalInt();      vmint value = valueExpr->evalInt();
1266        vmfloat unitFactor = valueExpr->unitFactor();
1267    
1268      if (!index) return;      if (!index) return;
1269      vmint idx = index->evalInt();      vmint idx = currentIndex = index->evalInt();
1270      if (idx < 0 || idx >= array->arraySize()) return;      if (idx < 0 || idx >= array->arraySize()) return;
1271    
1272      array->assignIntElement(idx, value);      array->assignIntElement(idx, value);
1273        array->assignElementUnitFactor(idx, unitFactor);
1274  }  }
1275    
1276  vmint IntArrayElement::evalInt() {  vmint IntArrayElement::evalInt() {
1277      if (!index) return 0;      if (!index) return 0;
1278      vmint idx = index->evalInt();      vmint idx = currentIndex = index->evalInt();
1279      if (idx < 0 || idx >= array->arraySize()) return 0;      if (idx < 0 || idx >= array->arraySize()) return 0;
1280    
1281      return array->evalIntElement(idx);      return array->evalIntElement(idx);
1282  }  }
1283    
1284    vmfloat IntArrayElement::unitFactor() const {
1285        if (!index) return VM_NO_FACTOR;
1286        vmint idx = currentIndex;
1287        if (idx < 0 || idx >= array->arraySize()) return 0;
1288    
1289        return array->unitFactorOfElement(idx);
1290    }
1291    
1292  void IntArrayElement::dump(int level) {  void IntArrayElement::dump(int level) {
1293      printIndents(level);      printIndents(level);
1294      printf("IntArrayElement\n");      printf("IntArrayElement\n");
1295  }  }
1296    
1297  StringVariable::StringVariable(ParserContext* ctx)  RealArrayElement::RealArrayElement(RealArrayExprRef array, IntExprRef arrayIndex) :
1298      : Variable(ctx,ctx->globalStrVarCount++,false)      RealVariable({
1299            .ctx = NULL,
1300            .isPolyphonic = (array) ? array->isPolyphonic() : false,
1301            .isConst = (array) ? array->isConstExpr() : false,
1302            .elements = 0,
1303            .memPos = 0,
1304            .unitFactorMemPos = 0,
1305            .unitType = VM_NO_UNIT,
1306            .isFinal = false,
1307        }),
1308        Unit(VM_NO_UNIT),
1309        array(array), index(arrayIndex), currentIndex(-1)
1310    {
1311    }
1312    
1313    void RealArrayElement::assign(Expression* expr) {
1314        RealExpr* valueExpr = dynamic_cast<RealExpr*>(expr);
1315        if (!valueExpr) return;
1316        vmfloat value = valueExpr->evalReal();
1317        vmfloat unitFactor = valueExpr->unitFactor();
1318    
1319        if (!index) return;
1320        vmint idx = currentIndex = index->evalInt();
1321        if (idx < 0 || idx >= array->arraySize()) return;
1322    
1323        array->assignRealElement(idx, value);
1324        array->assignElementUnitFactor(idx, unitFactor);
1325    }
1326    
1327    vmfloat RealArrayElement::evalReal() {
1328        if (!index) return 0;
1329        vmint idx = currentIndex = index->evalInt();
1330        if (idx < 0 || idx >= array->arraySize()) return 0;
1331    
1332        return array->evalRealElement(idx);
1333    }
1334    
1335    vmfloat RealArrayElement::unitFactor() const {
1336        if (!index) return VM_NO_FACTOR;
1337        vmint idx = currentIndex;
1338        if (idx < 0 || idx >= array->arraySize()) return 0;
1339    
1340        return array->unitFactorOfElement(idx);
1341    }
1342    
1343    void RealArrayElement::dump(int level) {
1344        printIndents(level);
1345        printf("RealArrayElement\n");
1346    }
1347    
1348    StringVariable::StringVariable(ParserContext* ctx) :
1349        Variable({
1350            .ctx = ctx,
1351            .elements = 1,
1352            .memPos = ctx->globalStrVarCount++
1353        })
1354  {  {
1355  }  }
1356    
1357  StringVariable::StringVariable(ParserContext* ctx, bool bConst)  StringVariable::StringVariable(ParserContext* ctx, bool bConst) :
1358      : Variable(ctx,0,bConst)      Variable({
1359            .ctx = ctx,
1360            .isConst = bConst,
1361            .memPos = 0,
1362        })
1363  {  {
1364  }  }
1365    
# Line 635  String StringVariable::evalStr() { Line 1375  String StringVariable::evalStr() {
1375    
1376  void StringVariable::dump(int level) {  void StringVariable::dump(int level) {
1377      printIndents(level);      printIndents(level);
1378      printf("StringVariable memPos=%lld\n", memPos);      printf("StringVariable memPos=%" PRId64 "\n", (int64_t)memPos);
1379  }  }
1380    
1381  ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)  ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value)
# Line 658  void ConstStringVariable::dump(int level Line 1398  void ConstStringVariable::dump(int level
1398      printf("ConstStringVariable val='%s'\n", value.c_str());      printf("ConstStringVariable val='%s'\n", value.c_str());
1399  }  }
1400    
1401  MetricPrefix_t IntBinaryOp::unitPrefix(vmuint i) const {  bool NumberBinaryOp::isFinal() const {
1402      IntExprRef l = (IntExprRef) lhs;      NumberExprRef l = (NumberExprRef) lhs;
1403      IntExprRef r = (IntExprRef) rhs;      NumberExprRef r = (NumberExprRef) rhs;
1404      return (r->unitFactor() < l->unitFactor()) ? r->unitPrefix(i) : l->unitPrefix(i);      return l->isFinal() || r->isFinal();
1405  }  }
1406    
1407  StdUnit_t IntBinaryOp::unitType() const {  ExprType_t VaritypeScalarBinaryOp::exprType() const {
1408      IntExprRef l = (IntExprRef) lhs;      return (lhs->exprType() == REAL_EXPR || rhs->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
     IntExprRef r = (IntExprRef) rhs;  
     return (l->unitType()) ? l->unitType() : r->unitType();  
1409  }  }
1410    
1411  bool IntBinaryOp::isFinal() const {  String VaritypeScalarBinaryOp::evalCastToStr() {
1412      IntExprRef l = (IntExprRef) lhs;      return (exprType() == REAL_EXPR) ?
1413      IntExprRef r = (IntExprRef) rhs;          RealExpr::evalCastToStr() : IntExpr::evalCastToStr();
     return l->isFinal() || r->isFinal();  
1414  }  }
1415    
1416  void If::dump(int level) {  void If::dump(int level) {
# Line 708  void SelectCase::dump(int level) { Line 1445  void SelectCase::dump(int level) {
1445      printIndents(level);      printIndents(level);
1446      if (select)      if (select)
1447          if (select->isConstExpr())          if (select->isConstExpr())
1448              printf("Case select %lld\n", select->evalInt());              printf("Case select %" PRId64 "\n", (int64_t)select->evalInt());
1449          else          else
1450              printf("Case select [runtime expr]\n");              printf("Case select [runtime expr]\n");
1451      else      else
# Line 718  void SelectCase::dump(int level) { Line 1455  void SelectCase::dump(int level) {
1455          CaseBranch& branch = branches[i];          CaseBranch& branch = branches[i];
1456          if (branch.from && branch.to)          if (branch.from && branch.to)
1457              if (branch.from->isConstExpr() && branch.to->isConstExpr())              if (branch.from->isConstExpr() && branch.to->isConstExpr())
1458                  printf("case %lld to %lld\n", branch.from->evalInt(), branch.to->evalInt());                  printf("case %" PRId64 " to %" PRId64 "\n", (int64_t)branch.from->evalInt(), (int64_t)branch.to->evalInt());
1459              else if (branch.from->isConstExpr() && !branch.to->isConstExpr())              else if (branch.from->isConstExpr() && !branch.to->isConstExpr())
1460                  printf("case %lld to [runtime expr]\n", branch.from->evalInt());                  printf("case %" PRId64 " to [runtime expr]\n", (int64_t)branch.from->evalInt());
1461              else if (!branch.from->isConstExpr() && branch.to->isConstExpr())              else if (!branch.from->isConstExpr() && branch.to->isConstExpr())
1462                  printf("case [runtime expr] to %lld\n", branch.to->evalInt());                  printf("case [runtime expr] to %" PRId64 "\n", (int64_t)branch.to->evalInt());
1463              else              else
1464                  printf("case [runtime expr] to [runtime expr]\n");                  printf("case [runtime expr] to [runtime expr]\n");
1465          else if (branch.from)          else if (branch.from)
1466              if (branch.from->isConstExpr())              if (branch.from->isConstExpr())
1467                  printf("case %lld\n", branch.from->evalInt());                  printf("case %" PRId64 "\n", (int64_t)branch.from->evalInt());
1468              else              else
1469                  printf("case [runtime expr]\n");                  printf("case [runtime expr]\n");
1470          else          else
# Line 762  bool SelectCase::isPolyphonic() const { Line 1499  bool SelectCase::isPolyphonic() const {
1499      return false;      return false;
1500  }  }
1501    
 // 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);  
 // }  
   
1502  void While::dump(int level) {  void While::dump(int level) {
1503      printIndents(level);      printIndents(level);
1504      if (m_condition)      if (m_condition)
1505          if (m_condition->isConstExpr())          if (m_condition->isConstExpr())
1506              printf("while (%lld) {\n", m_condition->evalInt());              printf("while (%" PRId64 ") {\n", (int64_t)m_condition->evalInt());
1507          else          else
1508              printf("while ([runtime expr]) {\n");              printf("while ([runtime expr]) {\n");
1509      else      else
# Line 816  Statements* SyncBlock::statements() cons Line 1534  Statements* SyncBlock::statements() cons
1534      return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;      return (m_statements) ? const_cast<Statements*>( &*m_statements ) : NULL;
1535  }  }
1536    
1537    String Neg::evalCastToStr() {
1538        return expr->evalCastToStr();
1539    }
1540    
1541  void Neg::dump(int level) {  void Neg::dump(int level) {
1542      printIndents(level);      printIndents(level);
1543      printf("Negative Expr\n");      printf("Negative Expr\n");
# Line 849  bool ConcatString::isConstExpr() const { Line 1571  bool ConcatString::isConstExpr() const {
1571      return lhs->isConstExpr() && rhs->isConstExpr();      return lhs->isConstExpr() && rhs->isConstExpr();
1572  }  }
1573    
1574  vmint Relation::evalInt() {  Relation::Relation(ExpressionRef lhs, Type type, ExpressionRef rhs) :
1575        Unit(VM_NO_UNIT),
1576        lhs(lhs), rhs(rhs), type(type)
1577    {
1578    }
1579    
1580    // Equal / unequal comparison of real numbers in NKSP scripts:
1581    //
1582    // Unlike system level languages like C/C++ we are less conservative about
1583    // comparing floating point numbers for 'equalness' or 'unequalness' in NKSP
1584    // scripts. Due to the musical context of the NKSP language we automatically
1585    // take the (to be) expected floating point tolerances into account when
1586    // comparing two floating point numbers with each other, however only for '='
1587    // and '#' operators. The '<=' and '>=' still use conservative low level
1588    // floating point comparison for not breaking their transitivity feature.
1589    
1590    template<typename T_LHS, typename T_RHS>
1591    struct RelComparer {
1592        static inline bool isEqual(T_LHS a, T_RHS b) { // for int comparison ('3 = 3')
1593            return a == b;
1594        }
1595        static inline bool isUnequal(T_LHS a, T_RHS b) { // for int comparison ('3 # 3')
1596            return a != b;
1597        }
1598    };
1599    
1600    template<>
1601    struct RelComparer<float,float> {
1602        static inline bool isEqual(float a, float b) { // for real number comparison ('3.1 = 3.1')
1603            return RTMath::fEqual32(a, b);
1604        }
1605        static inline bool isUnequal(float a, float b) { // for real number comparison ('3.1 # 3.1')
1606            return !RTMath::fEqual32(a, b);
1607        }
1608    };
1609    
1610    template<>
1611    struct RelComparer<double,double> {
1612        static inline bool isEqual(double a, double b) { // for future purpose
1613            return RTMath::fEqual64(a, b);
1614        }
1615        static inline bool isUnqqual(double a, double b) { // for future purpose
1616            return !RTMath::fEqual64(a, b);
1617        }
1618    };
1619    
1620    template<class T_LHS, class T_RHS>
1621    inline vmint _evalRelation(Relation::Type type, T_LHS lhs, T_RHS rhs) {
1622      switch (type) {      switch (type) {
1623          case LESS_THAN:          case Relation::LESS_THAN:
1624              return lhs->evalInt() < rhs->evalInt();              return lhs < rhs;
1625          case GREATER_THAN:          case Relation::GREATER_THAN:
1626              return lhs->evalInt() > rhs->evalInt();              return lhs > rhs;
1627          case LESS_OR_EQUAL:          case Relation::LESS_OR_EQUAL:
1628              return lhs->evalInt() <= rhs->evalInt();              return lhs <= rhs;
1629          case GREATER_OR_EQUAL:          case Relation::GREATER_OR_EQUAL:
1630              return lhs->evalInt() >= rhs->evalInt();              return lhs >= rhs;
1631          case EQUAL:          case Relation::EQUAL:
1632              if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR)              return RelComparer<typeof(lhs),typeof(rhs)>::isEqual(lhs, rhs);
1633            case Relation::NOT_EQUAL:
1634                return RelComparer<typeof(lhs),typeof(rhs)>::isUnequal(lhs, rhs);
1635        }
1636        return 0;
1637    }
1638    
1639    template<class T_LVALUE, class T_RVALUE, class T_LEXPR, class T_REXPR>
1640    inline vmint _evalRealRelation(Relation::Type type,
1641                                   T_LVALUE lvalue, T_RVALUE rvalue,
1642                                   T_LEXPR* pLHS, T_REXPR* pRHS)
1643    {
1644        if (pLHS->unitFactor() == pRHS->unitFactor())
1645            return _evalRelation(type, lvalue, rvalue);
1646        if (pLHS->unitFactor() < pRHS->unitFactor())
1647            return _evalRelation(type, lvalue, Unit::convRealToUnitFactor(rvalue, pRHS, pLHS));
1648        else
1649            return _evalRelation(type, Unit::convRealToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1650    }
1651    
1652    template<class T_LEXPR, class T_REXPR>
1653    inline vmint _evalIntRelation(Relation::Type type,
1654                                  vmint lvalue, vmint rvalue,
1655                                  T_LEXPR* pLHS, T_REXPR* pRHS)
1656    {
1657        if (pLHS->unitFactor() == pRHS->unitFactor())
1658            return _evalRelation(type, lvalue, rvalue);
1659        if (pLHS->unitFactor() < pRHS->unitFactor())
1660            return _evalRelation(type, lvalue, Unit::convIntToUnitFactor(rvalue, pRHS, pLHS));
1661        else
1662            return _evalRelation(type, Unit::convIntToUnitFactor(lvalue, pLHS, pRHS), rvalue);
1663    }
1664    
1665    vmint Relation::evalInt() {
1666        const ExprType_t lType = lhs->exprType();
1667        const ExprType_t rType = rhs->exprType();
1668        if (lType == STRING_EXPR || rType == STRING_EXPR) {
1669            switch (type) {
1670                case EQUAL:
1671                  return lhs->evalCastToStr() == rhs->evalCastToStr();                  return lhs->evalCastToStr() == rhs->evalCastToStr();
1672              else              case NOT_EQUAL:
                 return lhs->evalInt() == rhs->evalInt();  
         case NOT_EQUAL:  
             if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR)  
1673                  return lhs->evalCastToStr() != rhs->evalCastToStr();                  return lhs->evalCastToStr() != rhs->evalCastToStr();
1674              else              default:
1675                  return lhs->evalInt() != rhs->evalInt();                  return 0;
1676            }
1677        } else if (lType == REAL_EXPR && rType == REAL_EXPR) {
1678            vmfloat lvalue = lhs->asReal()->evalReal();
1679            vmfloat rvalue = rhs->asReal()->evalReal();
1680            return _evalRealRelation(
1681                type, lvalue, rvalue, lhs->asReal(), rhs->asReal()
1682            );
1683        } else if (lType == REAL_EXPR && rType == INT_EXPR) {
1684            vmfloat lvalue = lhs->asReal()->evalReal();
1685            vmint rvalue = rhs->asInt()->evalInt();
1686            return _evalRealRelation(
1687                type, lvalue, rvalue, lhs->asReal(), rhs->asInt()
1688            );
1689        } else if (lType == INT_EXPR && rType == REAL_EXPR) {
1690            vmint lvalue = lhs->asInt()->evalInt();
1691            vmfloat rvalue = rhs->asReal()->evalReal();
1692            return _evalRealRelation(
1693                type, lvalue, rvalue, lhs->asInt(), rhs->asReal()
1694            );
1695        } else {
1696            vmint lvalue = lhs->asInt()->evalInt();
1697            vmint rvalue = rhs->asInt()->evalInt();
1698            return _evalIntRelation(
1699                type, lvalue, rvalue, lhs->asInt(), rhs->asInt()
1700            );
1701      }      }
     return 0;  
1702  }  }
1703    
1704  void Relation::dump(int level) {  void Relation::dump(int level) {
# Line 910  bool Relation::isConstExpr() const { Line 1738  bool Relation::isConstExpr() const {
1738  vmint Or::evalInt() {  vmint Or::evalInt() {
1739      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);      IntExpr* pLHS = dynamic_cast<IntExpr*>(&*lhs);
1740      if (pLHS->evalInt()) return 1;      if (pLHS->evalInt()) return 1;
1741      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);;      IntExpr* pRHS = dynamic_cast<IntExpr*>(&*rhs);
1742      return (pRHS->evalInt()) ? 1 : 0;      return (pRHS->evalInt()) ? 1 : 0;
1743  }  }
1744    
# Line 993  void BitwiseNot::dump(int level) { Line 1821  void BitwiseNot::dump(int level) {
1821      printf(")\n");      printf(")\n");
1822  }  }
1823    
1824    String Final::evalCastToStr() {
1825        if (exprType() == REAL_EXPR)
1826            return ToString(evalReal());
1827        else
1828            return ToString(evalInt());
1829    }
1830    
1831  void Final::dump(int level) {  void Final::dump(int level) {
1832      printIndents(level);      printIndents(level);
1833      printf("Final(\n");      printf("Final(\n");
# Line 1001  void Final::dump(int level) { Line 1836  void Final::dump(int level) {
1836      printf(")\n");      printf(")\n");
1837  }  }
1838    
1839  StatementsRef ParserContext::userFunctionByName(const String& name) {  UserFunctionRef ParserContext::userFunctionByName(const String& name) {
1840      if (!userFnTable.count(name)) {      if (!userFnTable.count(name)) {
1841          return StatementsRef();          return UserFunctionRef();
1842      }      }
1843      return userFnTable.find(name)->second;      return userFnTable.find(name)->second;
1844  }  }
# Line 1029  IntVariableRef ParserContext::globalIntV Line 1864  IntVariableRef ParserContext::globalIntV
1864      return globalVar(name);      return globalVar(name);
1865  }  }
1866    
1867    RealVariableRef ParserContext::globalRealVar(const String& name) {
1868        return globalVar(name);
1869    }
1870    
1871  StringVariableRef ParserContext::globalStrVar(const String& name) {  StringVariableRef ParserContext::globalStrVar(const String& name) {
1872      return globalVar(name);      return globalVar(name);
1873  }  }
# Line 1039  ParserContext::~ParserContext() { Line 1878  ParserContext::~ParserContext() {
1878          delete globalIntMemory;          delete globalIntMemory;
1879          globalIntMemory = NULL;          globalIntMemory = NULL;
1880      }      }
1881        if (globalRealMemory) {
1882            delete globalRealMemory;
1883            globalRealMemory = NULL;
1884        }
1885  }  }
1886    
1887  void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {  void ParserContext::addErr(int firstLine, int lastLine, int firstColumn,
1888                               int lastColumn, int firstByte, int lengthBytes,
1889                               const char* txt)
1890    {
1891      ParserIssue e;      ParserIssue e;
1892      e.type = PARSER_ERROR;      e.type = PARSER_ERROR;
1893      e.txt = txt;      e.txt = txt;
# Line 1049  void ParserContext::addErr(int firstLine Line 1895  void ParserContext::addErr(int firstLine
1895      e.lastLine = lastLine;      e.lastLine = lastLine;
1896      e.firstColumn = firstColumn;      e.firstColumn = firstColumn;
1897      e.lastColumn = lastColumn;      e.lastColumn = lastColumn;
1898        e.firstByte = firstByte;
1899        e.lengthBytes = lengthBytes;
1900      vErrors.push_back(e);      vErrors.push_back(e);
1901      vIssues.push_back(e);      vIssues.push_back(e);
1902  }  }
1903    
1904  void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) {  void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn,
1905                               int lastColumn, int firstByte, int lengthBytes,
1906                               const char* txt)
1907    {
1908      ParserIssue w;      ParserIssue w;
1909      w.type = PARSER_WARNING;      w.type = PARSER_WARNING;
1910      w.txt = txt;      w.txt = txt;
# Line 1061  void ParserContext::addWrn(int firstLine Line 1912  void ParserContext::addWrn(int firstLine
1912      w.lastLine = lastLine;      w.lastLine = lastLine;
1913      w.firstColumn = firstColumn;      w.firstColumn = firstColumn;
1914      w.lastColumn = lastColumn;      w.lastColumn = lastColumn;
1915        w.firstByte = firstByte;
1916        w.lengthBytes = lengthBytes;
1917      vWarnings.push_back(w);      vWarnings.push_back(w);
1918      vIssues.push_back(w);      vIssues.push_back(w);
1919  }  }
1920    
1921  void ParserContext::addPreprocessorComment(int firstLine, int lastLine, int firstColumn, int lastColumn) {  void ParserContext::addPreprocessorComment(int firstLine, int lastLine,
1922                                               int firstColumn, int lastColumn,
1923                                               int firstByte, int lengthBytes)
1924    {
1925      CodeBlock block;      CodeBlock block;
1926      block.firstLine = firstLine;      block.firstLine = firstLine;
1927      block.lastLine = lastLine;      block.lastLine = lastLine;
1928      block.firstColumn = firstColumn;      block.firstColumn = firstColumn;
1929      block.lastColumn = lastColumn;      block.lastColumn = lastColumn;
1930        block.firstByte = firstByte;
1931        block.lengthBytes = lengthBytes;
1932      vPreprocessorComments.push_back(block);      vPreprocessorComments.push_back(block);
1933  }  }
1934    
# Line 1123  void ParserContext::registerBuiltInConst Line 1981  void ParserContext::registerBuiltInConst
1981      for (std::map<String,vmint>::const_iterator it = vars.begin();      for (std::map<String,vmint>::const_iterator it = vars.begin();
1982           it != vars.end(); ++it)           it != vars.end(); ++it)
1983      {      {
1984          ConstIntVariableRef ref = new ConstIntVariable(it->second);          ConstIntVariableRef ref = new ConstIntVariable({
1985                .value = it->second
1986            });
1987            vartable[it->first] = ref;
1988        }
1989    }
1990    
1991    void ParserContext::registerBuiltInConstRealVariables(const std::map<String,vmfloat>& vars) {
1992        for (std::map<String,vmfloat>::const_iterator it = vars.begin();
1993             it != vars.end(); ++it)
1994        {
1995            ConstRealVariableRef ref = new ConstRealVariable({
1996                .value = it->second
1997            });
1998          vartable[it->first] = ref;          vartable[it->first] = ref;
1999      }      }
2000  }  }
# Line 1166  void ExecContext::forkTo(VMExecContext* Line 2037  void ExecContext::forkTo(VMExecContext*
2037      ExecContext* child = dynamic_cast<ExecContext*>(ectx);      ExecContext* child = dynamic_cast<ExecContext*>(ectx);
2038    
2039      child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory);      child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory);
2040        child->polyphonicRealMemory.copyFlatFrom(polyphonicRealMemory);
2041      child->status = VM_EXEC_SUSPENDED;      child->status = VM_EXEC_SUSPENDED;
2042      child->flags = STMT_SUCCESS;      child->flags = STMT_SUCCESS;
2043      child->stack.copyFlatFrom(stack);      child->stack.copyFlatFrom(stack);

Legend:
Removed from v.3561  
changed lines
  Added in v.3804

  ViewVC Help
Powered by ViewVC