--- linuxsampler/trunk/src/scriptvm/tree.cpp 2016/07/10 14:24:13 2935 +++ linuxsampler/trunk/src/scriptvm/tree.cpp 2019/08/27 21:36:53 3573 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2016 Christian Schoenebeck and Andreas Persson + * Copyright (c) 2014 - 2019 Christian Schoenebeck and Andreas Persson * * http://www.linuxsampler.org * @@ -16,8 +16,7 @@ namespace LinuxSampler { bool isNoOperation(StatementRef statement) { - NoOperation* noOp = dynamic_cast(&*statement); - return noOp; + return statement->statementType() == STMT_NOOP; } Node::Node() { @@ -35,13 +34,78 @@ return ToString(evalInt()); } -int IntLiteral::evalInt() { +String RealExpr::evalCastToStr() { + return ToString(evalReal()); +} + +String IntArrayExpr::evalCastToStr() { + String s = "{"; + for (vmint i = 0; i < arraySize(); ++i) { + vmint val = evalIntElement(i); + if (i) s += ","; + s += ToString(val); + } + s += "}"; + return s; +} + +String RealArrayExpr::evalCastToStr() { + String s = "{"; + for (vmint i = 0; i < arraySize(); ++i) { + vmfloat val = evalRealElement(i); + if (i) s += ","; + s += ToString(val); + } + s += "}"; + return s; +} + +MetricPrefix_t Unit::unitPrefix(vmuint i) const { + if (i >= prefix.size()) return VM_NO_PREFIX; + return prefix[i]; +} + +void Unit::setUnit(const std::vector& prefix, StdUnit_t type) { + this->prefix.resize( prefix.size() ); + for (vmuint i = 0; i < prefix.size(); ++i) + this->prefix[i] = prefix[i]; + + unit = type; +} + +void Unit::setUnit(const MetricPrefix_t* prefixes, StdUnit_t type) { + unit = type; + prefix.clear(); + for (int i = 0; i < 2 && prefixes[i]; ++i) + prefix.add(prefixes[i]); +} + +void Unit::copyUnitFrom(const UnitRef& src) { + unit = src->unitType(); + prefix.clear(); + for (int i = 0; true; ++i) { + MetricPrefix_t p = src->unitPrefix(i); + if (!p) return; + prefix.add(p); + } +} + +vmint IntLiteral::evalInt() { return value; } void IntLiteral::dump(int level) { printIndents(level); - printf("IntLiteral %d\n", value); + printf("IntLiteral %lld\n", value); +} + +vmfloat RealLiteral::evalReal() { + return value; +} + +void RealLiteral::dump(int level) { + printIndents(level); + printf("RealLiteral %f\n", value); } void StringLiteral::dump(int level) { @@ -49,12 +113,18 @@ printf("StringLiteral: '%s'\n", value.c_str()); } -int Add::evalInt() { +vmint Add::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs);; return (pLHS && pRHS) ? pLHS->evalInt() + pRHS->evalInt() : 0; } +vmfloat Add::evalReal() { + RealExpr* pLHS = dynamic_cast(&*lhs); + RealExpr* pRHS = dynamic_cast(&*rhs);; + return (pLHS && pRHS) ? pLHS->evalReal() + pRHS->evalReal() : 0; +} + void Add::dump(int level) { printIndents(level); printf("Add(\n"); @@ -66,12 +136,18 @@ printf(")\n"); } -int Sub::evalInt() { +vmint Sub::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs);; return (pLHS && pRHS) ? pLHS->evalInt() - pRHS->evalInt() : 0; } +vmfloat Sub::evalReal() { + RealExpr* pLHS = dynamic_cast(&*lhs); + RealExpr* pRHS = dynamic_cast(&*rhs);; + return (pLHS && pRHS) ? pLHS->evalReal() - pRHS->evalReal() : 0; +} + void Sub::dump(int level) { printIndents(level); printf("Sub(\n"); @@ -83,12 +159,18 @@ printf(")\n"); } -int Mul::evalInt() { +vmint Mul::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs);; return (pLHS && pRHS) ? pLHS->evalInt() * pRHS->evalInt() : 0; } +vmfloat Mul::evalReal() { + RealExpr* pLHS = dynamic_cast(&*lhs); + RealExpr* pRHS = dynamic_cast(&*rhs);; + return (pLHS && pRHS) ? pLHS->evalReal() * pRHS->evalReal() : 0; +} + void Mul::dump(int level) { printIndents(level); printf("Mul(\n"); @@ -100,10 +182,38 @@ printf(")\n"); } -int Div::evalInt() { +MetricPrefix_t Mul::unitPrefix(vmuint i) const { + const ScalarNumberExpr* pLHS = dynamic_cast(&*lhs); + const ScalarNumberExpr* pRHS = dynamic_cast(&*rhs); + // currently the NKSP parser only allows a unit prefix on either side + return (pLHS->unitPrefix(0)) ? pLHS->unitPrefix(i) : pRHS->unitPrefix(i); +} + +StdUnit_t Mul::unitType() const { + const ScalarNumberExpr* pLHS = dynamic_cast(&*lhs); + const ScalarNumberExpr* pRHS = dynamic_cast(&*rhs); + // currently the NKSP parser only allows a unit type on either side + return (pLHS->unitType()) ? pLHS->unitType() : pRHS->unitType(); +} + +vmint Div::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); - IntExpr* pRHS = dynamic_cast(&*rhs);; - return (pLHS && pRHS) ? pRHS->evalInt() == 0 ? 0 : pLHS->evalInt() / pRHS->evalInt() : 0; + IntExpr* pRHS = dynamic_cast(&*rhs); + if (!pLHS || !pRHS) return 0; + vmint l = pLHS->evalInt(); + vmint r = pRHS->evalInt(); + if (r == 0) return 0; + return l / r; +} + +vmfloat Div::evalReal() { + RealExpr* pLHS = dynamic_cast(&*lhs); + RealExpr* pRHS = dynamic_cast(&*rhs);; + if (!pLHS || !pRHS) return 0; + vmfloat l = pLHS->evalReal(); + vmfloat r = pRHS->evalReal(); + if (r == vmfloat(0)) return 0; + return l / r; } void Div::dump(int level) { @@ -117,7 +227,23 @@ printf(")\n"); } -int Mod::evalInt() { +MetricPrefix_t Div::unitPrefix(vmuint i) const { + const ScalarNumberExpr* pLHS = dynamic_cast(&*lhs); + const ScalarNumberExpr* pRHS = dynamic_cast(&*rhs); + // currently the NKSP parser only allows either A) a unit prefix on left + // 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 ScalarNumberExpr* pLHS = dynamic_cast(&*lhs); + const ScalarNumberExpr* pRHS = dynamic_cast(&*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(); +} + +vmint Mod::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs);; return (pLHS && pRHS) ? pLHS->evalInt() % pRHS->evalInt() : 0; @@ -145,7 +271,7 @@ } bool Args::isPolyphonic() const { - for (int i = 0; i < args.size(); ++i) + for (vmint i = 0; i < args.size(); ++i) if (args[i]->isPolyphonic()) return true; return false; @@ -173,7 +299,7 @@ } EventHandler* EventHandlers::eventHandlerByName(const String& name) const { - for (int i = 0; i < args.size(); ++i) + for (vmint i = 0; i < args.size(); ++i) if (args.at(i)->eventHandlerName() == name) return const_cast(&*args.at(i)); return NULL; @@ -185,7 +311,7 @@ } bool EventHandlers::isPolyphonic() const { - for (int i = 0; i < args.size(); ++i) + for (vmint i = 0; i < args.size(); ++i) if (args[i]->isPolyphonic()) return true; return false; @@ -237,12 +363,43 @@ } bool Statements::isPolyphonic() const { - for (int i = 0; i < args.size(); ++i) + for (vmint i = 0; i < args.size(); ++i) if (args[i]->isPolyphonic()) return true; return false; } +DynamicVariableCall::DynamicVariableCall(const String& name, ParserContext* ctx, VMDynVar* v) + : Variable(ctx, 0, false), dynVar(v), varName(name) +{ +} + +vmint DynamicVariableCall::evalInt() { + VMIntExpr* expr = dynamic_cast(dynVar); + if (!expr) return 0; + return expr->evalInt(); +} + +String DynamicVariableCall::evalStr() { + VMStringExpr* expr = dynamic_cast(dynVar); + if (!expr) return ""; + return expr->evalStr(); +} + +String DynamicVariableCall::evalCastToStr() { + if (dynVar->exprType() == STRING_EXPR) { + return evalStr(); + } else { + VMIntExpr* intExpr = dynamic_cast(dynVar); + return intExpr ? ToString(intExpr->evalInt()) : ""; + } +} + +void DynamicVariableCall::dump(int level) { + printIndents(level); + printf("Dynamic Variable '%s'\n", varName.c_str()); +} + void FunctionCall::dump(int level) { printIndents(level); printf("FunctionCall '%s' args={\n", functionName.c_str()); @@ -270,7 +427,7 @@ return result->resultFlags(); } -int FunctionCall::evalInt() { +vmint FunctionCall::evalInt() { VMFnResult* result = execVMFn(); if (!result) return 0; VMIntExpr* intExpr = dynamic_cast(result->resultValue()); @@ -278,6 +435,28 @@ return intExpr->evalInt(); } +vmfloat FunctionCall::evalReal() { + VMFnResult* result = execVMFn(); + if (!result) return 0; + VMRealExpr* realExpr = dynamic_cast(result->resultValue()); + if (!realExpr) return 0; + return realExpr->evalReal(); +} + +VMIntArrayExpr* FunctionCall::asIntArray() const { + VMFnResult* result = const_cast(this)->execVMFn(); + if (!result) return 0; + VMIntArrayExpr* intArrExpr = dynamic_cast(result->resultValue()); + return intArrExpr; +} + +VMRealArrayExpr* FunctionCall::asRealArray() const { + VMFnResult* result = const_cast(this)->execVMFn(); + if (!result) return 0; + VMRealArrayExpr* realArrExpr = dynamic_cast(result->resultValue()); + return realArrExpr; +} + String FunctionCall::evalStr() { VMFnResult* result = execVMFn(); if (!result) return ""; @@ -289,34 +468,51 @@ String FunctionCall::evalCastToStr() { VMFnResult* result = execVMFn(); if (!result) return ""; - if (result->resultValue()->exprType() == STRING_EXPR) { + const ExprType_t resultType = result->resultValue()->exprType(); + if (resultType == STRING_EXPR) { VMStringExpr* strExpr = dynamic_cast(result->resultValue()); return strExpr ? strExpr->evalStr() : ""; + } else if (resultType == REAL_EXPR) { + VMRealExpr* realExpr = dynamic_cast(result->resultValue()); + return realExpr ? ToString(realExpr->evalReal()) : ""; } else { VMIntExpr* intExpr = dynamic_cast(result->resultValue()); return intExpr ? ToString(intExpr->evalInt()) : ""; } } +ScalarNumberVariable::ScalarNumberVariable(ParserContext* ctx, vmint _memPos, + bool _bConst, bool _bPolyphonic, + bool _bFinal) + : Variable(ctx, _memPos, _bConst), + Unit(), + polyphonic(_bPolyphonic), finalVal(_bFinal) +{ +} + IntVariable::IntVariable(ParserContext* ctx) - : Variable(ctx, ctx ? ctx->globalIntVarCount++ : 0, false), polyphonic(false) + : ScalarNumberVariable(ctx, ctx ? ctx->globalIntVarCount++ : 0) { //printf("globalIntVar parserctx=0x%lx memPOS=%d\n", ctx, memPos); assert(ctx); } -inline static int postfixInc(int& object, int incBy) { - const int i = object; +inline static vmint postfixInc(vmint& object, vmint incBy) { + const vmint i = object; object += incBy; return i; } -IntVariable::IntVariable(ParserContext* ctx, bool polyphonic, bool bConst, int size) - : Variable(ctx, !ctx ? 0 : polyphonic ? postfixInc(ctx->polyphonicIntVarCount, size) : postfixInc(ctx->globalIntVarCount, size), bConst), - polyphonic(polyphonic) +IntVariable::IntVariable(ParserContext* ctx, bool bPolyphonic, bool bConst, vmint size) + : ScalarNumberVariable( + ctx, + !ctx ? 0 : bPolyphonic ? postfixInc(ctx->polyphonicIntVarCount, size) : + postfixInc(ctx->globalIntVarCount, size), + bConst, bPolyphonic + ) { - //printf("InvVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx); - if (polyphonic) { + //printf("IntVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx); + if (bPolyphonic) { //printf("polyIntVar memPOS=%d\n", memPos); assert(ctx); } @@ -324,16 +520,17 @@ void IntVariable::assign(Expression* expr) { IntExpr* intExpr = dynamic_cast(expr); - if (intExpr) - if (polyphonic) + if (intExpr) { + if (isPolyphonic()) context->execContext->polyphonicIntMemory[memPos] = intExpr->evalInt(); else (*context->globalIntMemory)[memPos] = intExpr->evalInt(); + } } -int IntVariable::evalInt() { +vmint IntVariable::evalInt() { //printf("IntVariable::eval pos=%d\n", memPos); - if (polyphonic) { + if (isPolyphonic()) { //printf("evalInt() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext); return context->execContext->polyphonicIntMemory[memPos]; } @@ -342,11 +539,58 @@ void IntVariable::dump(int level) { printIndents(level); + printf("IntVariable\n"); //printf("IntVariable memPos=%d\n", memPos); } -//ConstIntVariable::ConstIntVariable(ParserContext* ctx, int value) -ConstIntVariable::ConstIntVariable(int value) +RealVariable::RealVariable(ParserContext* ctx) + : ScalarNumberVariable(ctx, ctx ? ctx->globalRealVarCount++ : 0) +{ + //printf("globalRealVar parserctx=0x%lx memPOS=%d\n", ctx, memPos); + assert(ctx); +} + +RealVariable::RealVariable(ParserContext* ctx, bool bPolyphonic, bool bConst, vmint size) + : ScalarNumberVariable( + ctx, + !ctx ? 0 : bPolyphonic ? postfixInc(ctx->polyphonicRealVarCount, size) : + postfixInc(ctx->globalRealVarCount, size), + bConst, bPolyphonic + ) +{ + //printf("RealVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx); + if (bPolyphonic) { + //printf("polyRealVar memPOS=%d\n", memPos); + assert(ctx); + } +} + +void RealVariable::assign(Expression* expr) { + RealExpr* realExpr = dynamic_cast(expr); + if (realExpr) { + if (isPolyphonic()) + context->execContext->polyphonicRealMemory[memPos] = realExpr->evalReal(); + else + (*context->globalRealMemory)[memPos] = realExpr->evalReal(); + } +} + +vmfloat RealVariable::evalReal() { + //printf("RealVariable::eval pos=%d\n", memPos); + if (isPolyphonic()) { + //printf("evalReal() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext); + return context->execContext->polyphonicRealMemory[memPos]; + } + return (*context->globalRealMemory)[memPos]; +} + +void RealVariable::dump(int level) { + printIndents(level); + printf("RealVariable\n"); + //printf("RealVariable memPos=%d\n", memPos); +} + +ConstIntVariable::ConstIntVariable(vmint value) : IntVariable(NULL,false,true), value(value) { } @@ -362,16 +606,34 @@ */ } -int ConstIntVariable::evalInt() { +vmint ConstIntVariable::evalInt() { return value; } void ConstIntVariable::dump(int level) { printIndents(level); - printf("ConstIntVariable val=%d\n", value); + printf("ConstIntVariable val=%lld\n", value); +} + +ConstRealVariable::ConstRealVariable(vmfloat value) + : RealVariable(NULL,false,true), value(value) +{ +} + +void ConstRealVariable::assign(Expression* expr) { + // ignore assignment +} + +vmfloat ConstRealVariable::evalReal() { + return value; +} + +void ConstRealVariable::dump(int level) { + printIndents(level); + printf("ConstRealVariable val=%f\n", value); } -BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntRelPtr* ptr) +BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) : IntVariable(NULL,false,false), name(name), ptr(ptr) { } @@ -382,7 +644,7 @@ ptr->assign(valueExpr->evalInt()); } -int BuiltInIntVariable::evalInt() { +vmint BuiltInIntVariable::evalInt() { return ptr->evalInt(); } @@ -401,18 +663,28 @@ printf("PolyphonicIntVariable\n"); } -IntArrayVariable::IntArrayVariable(ParserContext* ctx, int size) +PolyphonicRealVariable::PolyphonicRealVariable(ParserContext* ctx) + : RealVariable(ctx,true,false) +{ +} + +void PolyphonicRealVariable::dump(int level) { + printIndents(level); + printf("PolyphonicRealVariable\n"); +} + +IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size) : Variable(ctx, 0, false) { values.resize(size); - memset(&values[0], 0, size * sizeof(int)); + memset(&values[0], 0, size * sizeof(vmint)); } -IntArrayVariable::IntArrayVariable(ParserContext* ctx, int size, ArgsRef values) - : Variable(ctx, 0, false) +IntArrayVariable::IntArrayVariable(ParserContext* ctx, vmint size, ArgsRef values, bool _bConst) + : Variable(ctx, 0, _bConst) { this->values.resize(size); - for (int i = 0; i < values->argsCount(); ++i) { + for (vmint i = 0; i < values->argsCount(); ++i) { VMIntExpr* expr = dynamic_cast(values->arg(i)); if (expr) this->values[i] = expr->evalInt(); } @@ -423,12 +695,12 @@ { } -int IntArrayVariable::evalIntElement(uint i) { +vmint IntArrayVariable::evalIntElement(vmuint i) { if (i >= values.size()) return 0; return values[i]; } -void IntArrayVariable::assignIntElement(uint i, int value) { +void IntArrayVariable::assignIntElement(vmuint i, vmint value) { if (i >= values.size()) return; values[i] = value; } @@ -436,12 +708,58 @@ void IntArrayVariable::dump(int level) { printIndents(level); printf("IntArray("); - for (int i = 0; i < values.size(); ++i) { + for (vmint i = 0; i < values.size(); ++i) { + if (i % 12 == 0) { + printf("\n"); + printIndents(level+1); + } + printf("%lld, ", values[i]); + } + printIndents(level); + printf(")\n"); +} + +RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size) + : Variable(ctx, 0, false) +{ + values.resize(size); + memset(&values[0], 0, size * sizeof(vmfloat)); +} + +RealArrayVariable::RealArrayVariable(ParserContext* ctx, vmint size, ArgsRef values, bool _bConst) + : Variable(ctx, 0, _bConst) +{ + this->values.resize(size); + for (vmint i = 0; i < values->argsCount(); ++i) { + VMRealExpr* expr = dynamic_cast(values->arg(i)); + if (expr) this->values[i] = expr->evalReal(); + } +} + +RealArrayVariable::RealArrayVariable(ParserContext* ctx, bool bConst) + : Variable(ctx, 0, bConst) +{ +} + +vmfloat RealArrayVariable::evalRealElement(vmuint i) { + if (i >= values.size()) return 0; + return values[i]; +} + +void RealArrayVariable::assignRealElement(vmuint i, vmfloat value) { + if (i >= values.size()) return; + values[i] = value; +} + +void RealArrayVariable::dump(int level) { + printIndents(level); + printf("RealArray("); + for (vmint i = 0; i < values.size(); ++i) { if (i % 12 == 0) { printf("\n"); printIndents(level+1); } - printf("%d, ", values[i]); + printf("%f, ", values[i]); } printIndents(level); printf(")\n"); @@ -452,11 +770,11 @@ { } -int BuiltInIntArrayVariable::evalIntElement(uint i) { +vmint BuiltInIntArrayVariable::evalIntElement(vmuint i) { return i >= array->size ? 0 : array->data[i]; } -void BuiltInIntArrayVariable::assignIntElement(uint i, int value) { +void BuiltInIntArrayVariable::assignIntElement(vmuint i, vmint value) { if (i >= array->size) return; array->data[i] = value; } @@ -466,7 +784,7 @@ printf("Built-In Int Array Variable '%s'\n", name.c_str()); } -IntArrayElement::IntArrayElement(IntArrayVariableRef array, IntExprRef arrayIndex) +IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) : IntVariable(NULL, false, false, 0), array(array), index(arrayIndex) { } @@ -474,18 +792,18 @@ void IntArrayElement::assign(Expression* expr) { IntExpr* valueExpr = dynamic_cast(expr); if (!valueExpr) return; - int value = valueExpr->evalInt(); + vmint value = valueExpr->evalInt(); if (!index) return; - int idx = index->evalInt(); + vmint idx = index->evalInt(); if (idx < 0 || idx >= array->arraySize()) return; array->assignIntElement(idx, value); } -int IntArrayElement::evalInt() { +vmint IntArrayElement::evalInt() { if (!index) return 0; - int idx = index->evalInt(); + vmint idx = index->evalInt(); if (idx < 0 || idx >= array->arraySize()) return 0; return array->evalIntElement(idx); @@ -496,6 +814,36 @@ printf("IntArrayElement\n"); } +RealArrayElement::RealArrayElement(RealArrayExprRef array, IntExprRef arrayIndex) + : RealVariable(NULL, false, false, 0), array(array), index(arrayIndex) +{ +} + +void RealArrayElement::assign(Expression* expr) { + RealExpr* valueExpr = dynamic_cast(expr); + if (!valueExpr) return; + vmfloat value = valueExpr->evalReal(); + + if (!index) return; + vmint idx = index->evalInt(); + if (idx < 0 || idx >= array->arraySize()) return; + + array->assignRealElement(idx, value); +} + +vmfloat RealArrayElement::evalReal() { + if (!index) return 0; + vmint idx = index->evalInt(); + if (idx < 0 || idx >= array->arraySize()) return 0; + + return array->evalRealElement(idx); +} + +void RealArrayElement::dump(int level) { + printIndents(level); + printf("RealArrayElement\n"); +} + StringVariable::StringVariable(ParserContext* ctx) : Variable(ctx,ctx->globalStrVarCount++,false) { @@ -518,7 +866,7 @@ void StringVariable::dump(int level) { printIndents(level); - printf("StringVariable memPos=%d\n", memPos); + printf("StringVariable memPos=%lld\n", memPos); } ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value) @@ -541,6 +889,33 @@ printf("ConstStringVariable val='%s'\n", value.c_str()); } +MetricPrefix_t ScalarNumberBinaryOp::unitPrefix(vmuint i) const { + ScalarNumberExprRef l = (ScalarNumberExprRef) lhs; + ScalarNumberExprRef r = (ScalarNumberExprRef) rhs; + return (r->unitFactor() < l->unitFactor()) ? r->unitPrefix(i) : l->unitPrefix(i); +} + +StdUnit_t ScalarNumberBinaryOp::unitType() const { + ScalarNumberExprRef l = (ScalarNumberExprRef) lhs; + ScalarNumberExprRef r = (ScalarNumberExprRef) rhs; + return (l->unitType()) ? l->unitType() : r->unitType(); +} + +bool ScalarNumberBinaryOp::isFinal() const { + ScalarNumberExprRef l = (ScalarNumberExprRef) lhs; + ScalarNumberExprRef r = (ScalarNumberExprRef) rhs; + return l->isFinal() || r->isFinal(); +} + +ExprType_t VaritypeScalarBinaryOp::exprType() const { + return (lhs->exprType() == REAL_EXPR || rhs->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR; +} + +String VaritypeScalarBinaryOp::evalCastToStr() { + return (exprType() == REAL_EXPR) ? + RealExpr::evalCastToStr() : IntExpr::evalCastToStr(); +} + void If::dump(int level) { printIndents(level); if (ifStatements && elseStatements) @@ -551,13 +926,13 @@ printf("if [INVALID]\n"); } -int If::evalBranch() { +vmint If::evalBranch() { if (condition->evalInt()) return 0; if (elseStatements) return 1; return -1; } -Statements* If::branch(uint i) const { +Statements* If::branch(vmuint i) const { if (i == 0) return (Statements*) &*ifStatements; if (i == 1) return (elseStatements) ? (Statements*) &*elseStatements : NULL; return NULL; @@ -573,26 +948,26 @@ printIndents(level); if (select) if (select->isConstExpr()) - printf("Case select %d\n", select->evalInt()); + printf("Case select %lld\n", select->evalInt()); else printf("Case select [runtime expr]\n"); else printf("Case select NULL\n"); - for (int i = 0; i < branches.size(); ++i) { + for (vmint i = 0; i < branches.size(); ++i) { printIndents(level+1); CaseBranch& branch = branches[i]; if (branch.from && branch.to) if (branch.from->isConstExpr() && branch.to->isConstExpr()) - printf("case %d to %d\n", branch.from->evalInt(), branch.to->evalInt()); + printf("case %lld to %lld\n", branch.from->evalInt(), branch.to->evalInt()); else if (branch.from->isConstExpr() && !branch.to->isConstExpr()) - printf("case %d to [runtime expr]\n", branch.from->evalInt()); + printf("case %lld to [runtime expr]\n", branch.from->evalInt()); else if (!branch.from->isConstExpr() && branch.to->isConstExpr()) - printf("case [runtime expr] to %d\n", branch.to->evalInt()); + printf("case [runtime expr] to %lld\n", branch.to->evalInt()); else printf("case [runtime expr] to [runtime expr]\n"); else if (branch.from) if (branch.from->isConstExpr()) - printf("case %d\n", branch.from->evalInt()); + printf("case %lld\n", branch.from->evalInt()); else printf("case [runtime expr]\n"); else @@ -600,9 +975,9 @@ } } -int SelectCase::evalBranch() { - int value = select->evalInt(); - for (int i = 0; i < branches.size(); ++i) { +vmint SelectCase::evalBranch() { + vmint value = select->evalInt(); + for (vmint i = 0; i < branches.size(); ++i) { if (branches.at(i).from && branches.at(i).to) { // i.e. "case 4 to 7" ... if (branches.at(i).from->evalInt() <= value && branches.at(i).to->evalInt() >= value) return i; @@ -613,7 +988,7 @@ return -1; } -Statements* SelectCase::branch(uint i) const { +Statements* SelectCase::branch(vmuint i) const { if (i < branches.size()) return const_cast( &*branches[i].statements ); return NULL; @@ -621,7 +996,7 @@ bool SelectCase::isPolyphonic() const { if (select->isPolyphonic()) return true; - for (int i = 0; i < branches.size(); ++i) + for (vmint i = 0; i < branches.size(); ++i) if (branches[i].statements->isPolyphonic()) return true; return false; @@ -650,7 +1025,7 @@ printIndents(level); if (m_condition) if (m_condition->isConstExpr()) - printf("while (%d) {\n", m_condition->evalInt()); + printf("while (%lld) {\n", m_condition->evalInt()); else printf("while ([runtime expr]) {\n"); else @@ -669,13 +1044,34 @@ return m_condition->evalInt(); } +void SyncBlock::dump(int level) { + printIndents(level); + printf("sync {\n"); + m_statements->dump(level+1); + printIndents(level); + printf("}\n"); +} + +Statements* SyncBlock::statements() const { + return (m_statements) ? const_cast( &*m_statements ) : NULL; +} + void Neg::dump(int level) { printIndents(level); printf("Negative Expr\n"); } String ConcatString::evalStr() { - return lhs->evalCastToStr() + rhs->evalCastToStr(); + // temporaries required here to enforce the associative left (to right) order + // ( required for GCC and Visual Studio, see: + // http://stackoverflow.com/questions/25842902/why-stdstring-concatenation-operator-works-like-right-associative-one + // Personally I am not convinced that this is "not a bug" of the + // compiler/STL implementation and the allegedly underlying "function call" + // nature causing this is IMO no profound reason that the C++ language's + // "+" operator's left associativity is ignored. -- Christian, 2016-07-14 ) + String l = lhs->evalCastToStr(); + String r = rhs->evalCastToStr(); + return l + r; } void ConcatString::dump(int level) { @@ -693,28 +1089,54 @@ return lhs->isConstExpr() && rhs->isConstExpr(); } -int Relation::evalInt() { +template +static inline vmint _evalRelation(Relation::Type type, T_LHS lhs, T_RHS rhs) { switch (type) { - case LESS_THAN: - return lhs->evalInt() < rhs->evalInt(); - case GREATER_THAN: - return lhs->evalInt() > rhs->evalInt(); - case LESS_OR_EQUAL: - return lhs->evalInt() <= rhs->evalInt(); - case GREATER_OR_EQUAL: - return lhs->evalInt() >= rhs->evalInt(); - case EQUAL: - if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR) + case Relation::LESS_THAN: + return lhs < rhs; + case Relation::GREATER_THAN: + return lhs > rhs; + case Relation::LESS_OR_EQUAL: + return lhs <= rhs; + case Relation::GREATER_OR_EQUAL: + return lhs >= rhs; + case Relation::EQUAL: + return lhs == rhs; + case Relation::NOT_EQUAL: + return lhs != rhs; + } + return 0; +} + +vmint Relation::evalInt() { + const ExprType_t lType = lhs->exprType(); + const ExprType_t rType = rhs->exprType(); + if (lType == STRING_EXPR || rType == STRING_EXPR) { + switch (type) { + case EQUAL: return lhs->evalCastToStr() == rhs->evalCastToStr(); - else - return lhs->evalInt() == rhs->evalInt(); - case NOT_EQUAL: - if (lhs->exprType() == STRING_EXPR || rhs->exprType() == STRING_EXPR) + case NOT_EQUAL: return lhs->evalCastToStr() != rhs->evalCastToStr(); - else - return lhs->evalInt() != rhs->evalInt(); + default: + return 0; + } + } else if (lType == REAL_EXPR && rType == REAL_EXPR) { + return _evalRelation( + type, lhs->asReal()->evalReal(), rhs->asReal()->evalReal() + ); + } else if (lType == REAL_EXPR && rType == INT_EXPR) { + return _evalRelation( + type, lhs->asReal()->evalReal(), rhs->asInt()->evalInt() + ); + } else if (lType == INT_EXPR && rType == REAL_EXPR) { + return _evalRelation( + type, lhs->asInt()->evalInt(), rhs->asReal()->evalReal() + ); + } else { + return _evalRelation( + type, lhs->asInt()->evalInt(), rhs->asInt()->evalInt() + ); } - return 0; } void Relation::dump(int level) { @@ -751,7 +1173,7 @@ return lhs->isConstExpr() && rhs->isConstExpr(); } -int Or::evalInt() { +vmint Or::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); if (pLHS->evalInt()) return 1; IntExpr* pRHS = dynamic_cast(&*rhs);; @@ -769,7 +1191,7 @@ printf(")\n"); } -int BitwiseOr::evalInt() { +vmint BitwiseOr::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs); return pLHS->evalInt() | pRHS->evalInt(); @@ -786,7 +1208,7 @@ printf(")\n"); } -int And::evalInt() { +vmint And::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); if (!pLHS->evalInt()) return 0; IntExpr* pRHS = dynamic_cast(&*rhs); @@ -804,7 +1226,7 @@ printf(")\n"); } -int BitwiseAnd::evalInt() { +vmint BitwiseAnd::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs); return pLHS->evalInt() & pRHS->evalInt(); @@ -837,6 +1259,28 @@ printf(")\n"); } +String Final::evalCastToStr() { + if (exprType() == REAL_EXPR) + return ToString(evalReal()); + else + return ToString(evalInt()); +} + +void Final::dump(int level) { + printIndents(level); + printf("Final(\n"); + expr->dump(level+1); + printIndents(level); + printf(")\n"); +} + +StatementsRef ParserContext::userFunctionByName(const String& name) { + if (!userFnTable.count(name)) { + return StatementsRef(); + } + return userFnTable.find(name)->second; +} + VariableRef ParserContext::variableByName(const String& name) { if (!vartable.count(name)) { return VariableRef(); @@ -858,6 +1302,10 @@ return globalVar(name); } +RealVariableRef ParserContext::globalRealVar(const String& name) { + return globalVar(name); +} + StringVariableRef ParserContext::globalStrVar(const String& name) { return globalVar(name); } @@ -868,6 +1316,10 @@ delete globalIntMemory; globalIntMemory = NULL; } + if (globalRealMemory) { + delete globalRealMemory; + globalRealMemory = NULL; + } } void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { @@ -894,6 +1346,15 @@ vIssues.push_back(w); } +void ParserContext::addPreprocessorComment(int firstLine, int lastLine, int firstColumn, int lastColumn) { + CodeBlock block; + block.firstLine = firstLine; + block.lastLine = lastLine; + block.firstColumn = firstColumn; + block.lastColumn = lastColumn; + vPreprocessorComments.push_back(block); +} + bool ParserContext::setPreprocessorCondition(const char* name) { if (builtinPreprocessorConditions.count(name)) return false; if (userPreprocessorConditions.count(name)) return false; @@ -925,6 +1386,10 @@ return vWarnings; } +std::vector ParserContext::preprocessorComments() const { + return vPreprocessorComments; +} + VMEventHandler* ParserContext::eventHandler(uint index) { if (!handlers) return NULL; return handlers->eventHandler(index); @@ -935,8 +1400,8 @@ return handlers->eventHandlerByName(name); } -void ParserContext::registerBuiltInConstIntVariables(const std::map& vars) { - for (std::map::const_iterator it = vars.begin(); +void ParserContext::registerBuiltInConstIntVariables(const std::map& vars) { + for (std::map::const_iterator it = vars.begin(); it != vars.end(); ++it) { ConstIntVariableRef ref = new ConstIntVariable(it->second); @@ -944,8 +1409,8 @@ } } -void ParserContext::registerBuiltInIntVariables(const std::map& vars) { - for (std::map::const_iterator it = vars.begin(); +void ParserContext::registerBuiltInIntVariables(const std::map& vars) { + for (std::map::const_iterator it = vars.begin(); it != vars.end(); ++it) { BuiltInIntVariableRef ref = new BuiltInIntVariable(it->first, it->second); @@ -962,4 +1427,33 @@ } } +void ParserContext::registerBuiltInDynVariables(const std::map& vars) { + for (std::map::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + DynamicVariableCallRef ref = new DynamicVariableCall(it->first, this, it->second); + vartable[it->first] = ref; + } +} + +ExecContext::ExecContext() : + status(VM_EXEC_NOT_RUNNING), flags(STMT_SUCCESS), stackFrame(-1), + suspendMicroseconds(0), instructionsCount(0) +{ + exitRes.value = NULL; +} + +void ExecContext::forkTo(VMExecContext* ectx) const { + ExecContext* child = dynamic_cast(ectx); + + child->polyphonicIntMemory.copyFlatFrom(polyphonicIntMemory); + child->polyphonicRealMemory.copyFlatFrom(polyphonicRealMemory); + child->status = VM_EXEC_SUSPENDED; + child->flags = STMT_SUCCESS; + child->stack.copyFlatFrom(stack); + child->stackFrame = stackFrame; + child->suspendMicroseconds = 0; + child->instructionsCount = 0; +} + } // namespace LinuxSampler