--- linuxsampler/trunk/src/scriptvm/tree.cpp 2016/07/10 14:24:13 2935 +++ linuxsampler/trunk/src/scriptvm/tree.cpp 2019/08/18 00:06:04 3557 @@ -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,24 @@ return ToString(evalInt()); } -int IntLiteral::evalInt() { +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; +} + +vmint IntLiteral::evalInt() { return value; } void IntLiteral::dump(int level) { printIndents(level); - printf("IntLiteral %d\n", value); + printf("IntLiteral %lld\n", value); } void StringLiteral::dump(int level) { @@ -49,7 +59,7 @@ 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; @@ -66,7 +76,7 @@ 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; @@ -83,7 +93,7 @@ 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; @@ -100,10 +110,14 @@ printf(")\n"); } -int Div::evalInt() { +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; } void Div::dump(int level) { @@ -117,7 +131,7 @@ printf(")\n"); } -int Mod::evalInt() { +vmint Mod::evalInt() { IntExpr* pLHS = dynamic_cast(&*lhs); IntExpr* pRHS = dynamic_cast(&*rhs);; return (pLHS && pRHS) ? pLHS->evalInt() % pRHS->evalInt() : 0; @@ -145,7 +159,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 +187,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 +199,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 +251,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 +315,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 +323,13 @@ return intExpr->evalInt(); } +VMIntArrayExpr* FunctionCall::asIntArray() const { + VMFnResult* result = const_cast(this)->execVMFn(); + if (!result) return 0; + VMIntArrayExpr* intArrExpr = dynamic_cast(result->resultValue()); + return intArrExpr; +} + String FunctionCall::evalStr() { VMFnResult* result = execVMFn(); if (!result) return ""; @@ -305,13 +357,13 @@ 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) +IntVariable::IntVariable(ParserContext* ctx, bool polyphonic, bool bConst, vmint size) : Variable(ctx, !ctx ? 0 : polyphonic ? postfixInc(ctx->polyphonicIntVarCount, size) : postfixInc(ctx->globalIntVarCount, size), bConst), polyphonic(polyphonic) { @@ -324,14 +376,15 @@ void IntVariable::assign(Expression* expr) { IntExpr* intExpr = dynamic_cast(expr); - if (intExpr) + if (intExpr) { if (polyphonic) 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) { //printf("evalInt() poly memPos=%d execCtx=0x%lx\n", memPos, (uint64_t)context->execContext); @@ -342,11 +395,12 @@ 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) +ConstIntVariable::ConstIntVariable(vmint value) : IntVariable(NULL,false,true), value(value) { } @@ -362,16 +416,16 @@ */ } -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); } -BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntRelPtr* ptr) +BuiltInIntVariable::BuiltInIntVariable(const String& name, VMIntPtr* ptr) : IntVariable(NULL,false,false), name(name), ptr(ptr) { } @@ -382,7 +436,7 @@ ptr->assign(valueExpr->evalInt()); } -int BuiltInIntVariable::evalInt() { +vmint BuiltInIntVariable::evalInt() { return ptr->evalInt(); } @@ -401,18 +455,18 @@ printf("PolyphonicIntVariable\n"); } -IntArrayVariable::IntArrayVariable(ParserContext* ctx, int size) +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 +477,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 +490,12 @@ 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"); @@ -452,11 +506,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 +520,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 +528,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); @@ -518,7 +572,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) @@ -551,13 +605,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 +627,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 +654,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 +667,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 +675,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 +704,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 +723,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,7 +768,7 @@ return lhs->isConstExpr() && rhs->isConstExpr(); } -int Relation::evalInt() { +vmint Relation::evalInt() { switch (type) { case LESS_THAN: return lhs->evalInt() < rhs->evalInt(); @@ -751,7 +826,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 +844,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 +861,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 +879,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 +912,13 @@ 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(); @@ -894,6 +976,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 +1016,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 +1030,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 +1039,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 +1057,32 @@ } } +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->status = VM_EXEC_SUSPENDED; + child->flags = STMT_SUCCESS; + child->stack.copyFlatFrom(stack); + child->stackFrame = stackFrame; + child->suspendMicroseconds = 0; + child->instructionsCount = 0; +} + } // namespace LinuxSampler