--- linuxsampler/trunk/src/scriptvm/tree.cpp 2014/05/30 12:48:05 2581 +++ linuxsampler/trunk/src/scriptvm/tree.cpp 2019/08/27 21:36:53 3573 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Christian Schoenebeck and Andreas Persson + * Copyright (c) 2014 - 2019 Christian Schoenebeck and Andreas Persson * * http://www.linuxsampler.org * @@ -11,12 +11,12 @@ #include #include "tree.h" #include "../common/global_private.h" +#include namespace LinuxSampler { bool isNoOperation(StatementRef statement) { - NoOperation* noOp = dynamic_cast(&*statement); - return noOp; + return statement->statementType() == STMT_NOOP; } Node::Node() { @@ -34,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) { @@ -48,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"); @@ -65,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"); @@ -82,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"); @@ -99,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) { @@ -116,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; @@ -143,6 +270,13 @@ printf(")\n"); } +bool Args::isPolyphonic() const { + for (vmint i = 0; i < args.size(); ++i) + if (args[i]->isPolyphonic()) + return true; + return false; +} + EventHandlers::EventHandlers() { //printf("EventHandlers::Constructor 0x%lx\n", (long long)this); } @@ -165,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; @@ -176,6 +310,13 @@ return const_cast(&*args.at(index)); } +bool EventHandlers::isPolyphonic() const { + for (vmint i = 0; i < args.size(); ++i) + if (args[i]->isPolyphonic()) + return true; + return false; +} + Assignment::Assignment(VariableRef variable, ExpressionRef value) : variable(variable), value(value) { @@ -193,6 +334,11 @@ return STMT_SUCCESS; } +EventHandler::EventHandler(StatementsRef statements) { + this->statements = statements; + usingPolyphonics = statements->isPolyphonic(); +} + void EventHandler::dump(int level) { printIndents(level); printf("EventHandler {\n"); @@ -216,6 +362,44 @@ return &*args.at(i); } +bool Statements::isPolyphonic() const { + 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()); @@ -243,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()); @@ -251,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 ""; @@ -262,49 +468,129 @@ 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); } -IntVariable::IntVariable(ParserContext* ctx, bool polyphonic, bool bConst, int size) - : Variable(ctx, !ctx ? 0 : polyphonic ? ctx->polyphonicIntVarCount += size : ctx->globalIntVarCount += size, bConst), - polyphonic(polyphonic) +inline static vmint postfixInc(vmint& object, vmint incBy) { + const vmint i = object; + object += incBy; + return i; +} + +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("IntVar size=%d parserCtx=0x%lx\n", size, (uint64_t)ctx); + if (bPolyphonic) { + //printf("polyIntVar memPOS=%d\n", memPos); + assert(ctx); + } } 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]; + } return (*context->globalIntMemory)[memPos]; } void IntVariable::dump(int level) { printIndents(level); - printf("IntVariable memPos=%d\n", memPos); + 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) { } @@ -320,13 +606,51 @@ */ } -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, VMIntPtr* ptr) + : IntVariable(NULL,false,false), name(name), ptr(ptr) +{ +} + +void BuiltInIntVariable::assign(Expression* expr) { + IntExpr* valueExpr = dynamic_cast(expr); + if (!valueExpr) return; + ptr->assign(valueExpr->evalInt()); +} + +vmint BuiltInIntVariable::evalInt() { + return ptr->evalInt(); +} + +void BuiltInIntVariable::dump(int level) { + printIndents(level); + printf("Built-in IntVar '%s'\n", name.c_str()); } PolyphonicIntVariable::PolyphonicIntVariable(ParserContext* ctx) @@ -339,29 +663,44 @@ 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(); } } -int IntArrayVariable::evalIntElement(uint i) { +IntArrayVariable::IntArrayVariable(ParserContext* ctx, bool bConst) + : Variable(ctx, 0, bConst) +{ +} + +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; } @@ -369,18 +708,83 @@ 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("%d, ", values[i]); + printf("%lld, ", values[i]); } printIndents(level); printf(")\n"); } -IntArrayElement::IntArrayElement(IntArrayVariableRef array, IntExprRef arrayIndex) +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("%f, ", values[i]); + } + printIndents(level); + printf(")\n"); +} + +BuiltInIntArrayVariable::BuiltInIntArrayVariable(const String& name, VMInt8Array* array) + : IntArrayVariable(NULL, false), name(name), array(array) +{ +} + +vmint BuiltInIntArrayVariable::evalIntElement(vmuint i) { + return i >= array->size ? 0 : array->data[i]; +} + +void BuiltInIntArrayVariable::assignIntElement(vmuint i, vmint value) { + if (i >= array->size) return; + array->data[i] = value; +} + +void BuiltInIntArrayVariable::dump(int level) { + printIndents(level); + printf("Built-In Int Array Variable '%s'\n", name.c_str()); +} + +IntArrayElement::IntArrayElement(IntArrayExprRef array, IntExprRef arrayIndex) : IntVariable(NULL, false, false, 0), array(array), index(arrayIndex) { } @@ -388,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); @@ -410,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) { @@ -432,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) @@ -455,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) @@ -465,42 +926,48 @@ 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; } +bool If::isPolyphonic() const { + if (condition->isPolyphonic() || ifStatements->isPolyphonic()) + return true; + return elseStatements ? elseStatements->isPolyphonic() : false; +} + void SelectCase::dump(int level) { 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 @@ -508,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; @@ -521,12 +988,20 @@ 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; } +bool SelectCase::isPolyphonic() const { + if (select->isPolyphonic()) return true; + for (vmint i = 0; i < branches.size(); ++i) + if (branches[i].statements->isPolyphonic()) + return true; + return false; +} + // void Case::addBranch(IntExprRef condition, StatementsRef statements) { // CaseBranchRef b = new CaseBranchRef; // b->from = condition; @@ -550,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 @@ -569,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) { @@ -593,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) { @@ -651,10 +1173,11 @@ 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);; - return pLHS->evalInt() || pRHS->evalInt(); + return (pRHS->evalInt()) ? 1 : 0; } void Or::dump(int level) { @@ -668,10 +1191,28 @@ printf(")\n"); } -int And::evalInt() { +vmint BitwiseOr::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); - IntExpr* pRHS = dynamic_cast(&*rhs);; - return pLHS->evalInt() && pRHS->evalInt(); + IntExpr* pRHS = dynamic_cast(&*rhs); + return pLHS->evalInt() | pRHS->evalInt(); +} + +void BitwiseOr::dump(int level) { + printIndents(level); + printf("BitwiseOr(\n"); + lhs->dump(level+1); + printIndents(level); + printf(",\n"); + rhs->dump(level+1); + printIndents(level); + printf(")\n"); +} + +vmint And::evalInt() { + IntExpr* pLHS = dynamic_cast(&*lhs); + if (!pLHS->evalInt()) return 0; + IntExpr* pRHS = dynamic_cast(&*rhs); + return (pRHS->evalInt()) ? 1 : 0; } void And::dump(int level) { @@ -685,6 +1226,23 @@ printf(")\n"); } +vmint BitwiseAnd::evalInt() { + IntExpr* pLHS = dynamic_cast(&*lhs); + IntExpr* pRHS = dynamic_cast(&*rhs); + return pLHS->evalInt() & pRHS->evalInt(); +} + +void BitwiseAnd::dump(int level) { + printIndents(level); + printf("BitwiseAnd(\n"); + lhs->dump(level+1); + printIndents(level); + printf(",\n"); + rhs->dump(level+1); + printIndents(level); + printf(")\n"); +} + void Not::dump(int level) { printIndents(level); printf("Not(\n"); @@ -693,6 +1251,36 @@ printf(")\n"); } +void BitwiseNot::dump(int level) { + printIndents(level); + printf("BitwiseNot(\n"); + expr->dump(level+1); + printIndents(level); + 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(); @@ -714,26 +1302,57 @@ return globalVar(name); } +RealVariableRef ParserContext::globalRealVar(const String& name) { + return globalVar(name); +} + StringVariableRef ParserContext::globalStrVar(const String& name) { return globalVar(name); } -void ParserContext::addErr(int line, const char* txt) { +ParserContext::~ParserContext() { + destroyScanner(); + if (globalIntMemory) { + delete globalIntMemory; + globalIntMemory = NULL; + } + if (globalRealMemory) { + delete globalRealMemory; + globalRealMemory = NULL; + } +} + +void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { ParserIssue e; e.type = PARSER_ERROR; e.txt = txt; - e.line = line; - errors.push_back(e); - issues.push_back(e); + e.firstLine = firstLine; + e.lastLine = lastLine; + e.firstColumn = firstColumn; + e.lastColumn = lastColumn; + vErrors.push_back(e); + vIssues.push_back(e); } -void ParserContext::addWrn(int line, const char* txt) { +void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { ParserIssue w; w.type = PARSER_WARNING; w.txt = txt; - w.line = line; - warnings.push_back(w); - issues.push_back(w); + w.firstLine = firstLine; + w.lastLine = lastLine; + w.firstColumn = firstColumn; + w.lastColumn = lastColumn; + vWarnings.push_back(w); + 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) { @@ -755,4 +1374,86 @@ return userPreprocessorConditions.count(name); } +std::vector ParserContext::issues() const { + return vIssues; +} + +std::vector ParserContext::errors() const { + return vErrors; +} + +std::vector ParserContext::warnings() const { + return vWarnings; +} + +std::vector ParserContext::preprocessorComments() const { + return vPreprocessorComments; +} + +VMEventHandler* ParserContext::eventHandler(uint index) { + if (!handlers) return NULL; + return handlers->eventHandler(index); +} + +VMEventHandler* ParserContext::eventHandlerByName(const String& name) { + if (!handlers) return NULL; + return handlers->eventHandlerByName(name); +} + +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); + vartable[it->first] = ref; + } +} + +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); + vartable[it->first] = ref; + } +} + +void ParserContext::registerBuiltInIntArrayVariables(const std::map& vars) { + for (std::map::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + BuiltInIntArrayVariableRef ref = new BuiltInIntArrayVariable(it->first, it->second); + vartable[it->first] = ref; + } +} + +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