--- linuxsampler/trunk/src/scriptvm/tree.cpp 2019/08/30 12:23:40 3582 +++ linuxsampler/trunk/src/scriptvm/tree.cpp 2020/02/15 11:50:02 3744 @@ -13,12 +13,50 @@ #include "../common/global_private.h" #include "../common/RTMath.h" #include +#include "CoreVMFunctions.h" // for VMIntResult, VMRealResult namespace LinuxSampler { bool isNoOperation(StatementRef statement) { return statement->statementType() == STMT_NOOP; } + +String acceptedArgTypesStr(VMFunction* fn, vmint iArg) { + static const ExprType_t allTypes[] = { + INT_EXPR, + INT_ARR_EXPR, + REAL_EXPR, + REAL_ARR_EXPR, + STRING_EXPR, + STRING_ARR_EXPR, + }; + const size_t nTypes = sizeof(allTypes) / sizeof(ExprType_t); + + std::vector supportedTypes; + for (int iType = 0; iType < nTypes; ++iType) { + const ExprType_t& type = allTypes[iType]; + if (fn->acceptsArgType(iArg, type)) + supportedTypes.push_back(type); + } + assert(!supportedTypes.empty()); + + if (supportedTypes.size() == 1) { + return typeStr(*supportedTypes.begin()); + } else { + String s = "either "; + for (size_t i = 0; i < supportedTypes.size(); ++i) { + const ExprType_t& type = supportedTypes[i]; + if (i == 0) { + s += typeStr(type); + } else if (i == supportedTypes.size() - 1) { + s += " or " + typeStr(type); + } else { + s += ", " + typeStr(type); + } + } + return s; + } +} Node::Node() { } @@ -85,7 +123,7 @@ } } -static String _unitToStr(Unit* unit) { +static String _unitToStr(VMUnit* unit) { const StdUnit_t type = unit->unitType(); String sType; switch (type) { @@ -151,7 +189,7 @@ void IntLiteral::dump(int level) { printIndents(level); - printf("IntLiteral %lld\n", value); + printf("IntLiteral %" PRId64 "\n", (int64_t)value); } RealLiteral::RealLiteral(const RealLitDef& def) : @@ -575,7 +613,26 @@ if (!fn) return NULL; // assuming here that all argument checks (amount and types) have been made // at parse time, to avoid time intensive checks on each function call - return fn->exec(dynamic_cast(&*args)); + VMFnResult* res = fn->exec(dynamic_cast(&*args)); + if (!res) return res; + + VMExpr* expr = res->resultValue(); + if (!expr) return res; + + // For performance reasons we always only let 'FunctionCall' assign the unit + // type to the function's result expression, never by the function + // implementation itself, nor by other classes, because a FunctionCall + // object solely knows the unit type in O(1). + ExprType_t type = expr->exprType(); + if (type == INT_EXPR) { + VMIntResult* intRes = dynamic_cast(res); + intRes->unitBaseType = unitType(); + } else if (type == REAL_EXPR) { + VMRealResult* realRes = dynamic_cast(res); + realRes->unitBaseType = unitType(); + } + + return res; } StmtFlags_t FunctionCall::exec() { @@ -602,12 +659,30 @@ } VMIntArrayExpr* FunctionCall::asIntArray() const { + //FIXME: asIntArray() not intended for evaluation semantics (for both + // performance reasons with arrays, but also to prevent undesired value + // mutation by implied (hidden) evaluation, as actually done here. We must + // force function evaluation here though, because we need it for function + // calls to be evaluated at all. This issue should be addressed cleanly by + // adjusting the API appropriately. + FunctionCall* rwSelf = const_cast(this); + rwSelf->result = rwSelf->execVMFn(); + if (!result) return 0; VMIntArrayExpr* intArrExpr = dynamic_cast(result->resultValue()); return intArrExpr; } VMRealArrayExpr* FunctionCall::asRealArray() const { + //FIXME: asRealArray() not intended for evaluation semantics (for both + // performance reasons with arrays, but also to prevent undesired value + // mutation by implied (hidden) evaluation, as actually done here. We must + // force function evaluation here though, because we need it for function + // calls to be evaluated at all. This issue should be addressed cleanly by + // adjusting the API appropriately. + FunctionCall* rwSelf = const_cast(this); + rwSelf->result = rwSelf->execVMFn(); + if (!result) return 0; VMRealArrayExpr* realArrExpr = dynamic_cast(result->resultValue()); return realArrExpr; @@ -630,10 +705,10 @@ return strExpr ? strExpr->evalStr() : ""; } else if (resultType == REAL_EXPR) { VMRealExpr* realExpr = dynamic_cast(result->resultValue()); - return realExpr ? ToString(realExpr->evalReal()) : ""; + return realExpr ? ToString(realExpr->evalReal()) + _unitToStr(realExpr) : ""; } else { VMIntExpr* intExpr = dynamic_cast(result->resultValue()); - return intExpr ? ToString(intExpr->evalInt()) : ""; + return intExpr ? ToString(intExpr->evalInt()) + _unitToStr(intExpr) : ""; } } @@ -668,7 +743,6 @@ .ctx = decl.ctx, .isPolyphonic = decl.isPolyphonic, .isConst = decl.isConst, - .isFinal = decl.isFinal, .elements = decl.elements, .memPos = ( (!decl.ctx) ? 0 : @@ -682,7 +756,8 @@ postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) : postfixInc(decl.ctx->globalUnitFactorCount, decl.elements) ), - .unitType = decl.unitType + .unitType = decl.unitType, + .isFinal = decl.isFinal, }), Unit(decl.unitType) { @@ -724,7 +799,6 @@ .ctx = decl.ctx, .isPolyphonic = decl.isPolyphonic, .isConst = decl.isConst, - .isFinal = decl.isFinal, .elements = decl.elements, .memPos = ( (!decl.ctx) ? 0 : @@ -738,7 +812,8 @@ postfixInc(decl.ctx->polyphonicUnitFactorCount, decl.elements) : postfixInc(decl.ctx->globalUnitFactorCount, decl.elements) ), - .unitType = decl.unitType + .unitType = decl.unitType, + .isFinal = decl.isFinal, }), Unit(decl.unitType) { @@ -780,11 +855,11 @@ .ctx = def.ctx, .isPolyphonic = false, .isConst = true, - .isFinal = def.isFinal, .elements = 1, .memPos = def.memPos, .unitFactorMemPos = def.unitFactorMemPos, - .unitType = def.unitType + .unitType = def.unitType, + .isFinal = def.isFinal, }), Unit(def.unitType), value(def.value), unitPrefixFactor(def.unitFactor) @@ -808,7 +883,7 @@ void ConstIntVariable::dump(int level) { printIndents(level); - printf("ConstIntVariable val=%lld\n", value); + printf("ConstIntVariable val=%" PRId64 "\n", (int64_t)value); } ConstRealVariable::ConstRealVariable(const RealVarDef& def) : @@ -816,11 +891,11 @@ .ctx = def.ctx, .isPolyphonic = false, .isConst = true, - .isFinal = def.isFinal, .elements = 1, .memPos = def.memPos, .unitFactorMemPos = def.unitFactorMemPos, - .unitType = def.unitType + .unitType = def.unitType, + .isFinal = def.isFinal, }), Unit(def.unitType), value(def.value), unitPrefixFactor(def.unitFactor) @@ -845,11 +920,11 @@ .ctx = NULL, .isPolyphonic = false, .isConst = false, // may or may not be modifyable though! - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }), Unit(VM_NO_UNIT), name(name), ptr(ptr) @@ -876,11 +951,11 @@ .ctx = decl.ctx, .isPolyphonic = true, .isConst = decl.isConst, - .isFinal = decl.isFinal, .elements = 1, .memPos = 0, .unitFactorMemPos = 0, - .unitType = decl.unitType + .unitType = decl.unitType, + .isFinal = decl.isFinal, }), Unit(decl.unitType) { @@ -896,11 +971,11 @@ .ctx = decl.ctx, .isPolyphonic = true, .isConst = decl.isConst, - .isFinal = decl.isFinal, .elements = 1, .memPos = 0, .unitFactorMemPos = 0, - .unitType = decl.unitType + .unitType = decl.unitType, + .isFinal = decl.isFinal, }), Unit(decl.unitType) { @@ -916,11 +991,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = false, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { values.resize(size); @@ -937,11 +1012,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = _bConst, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { this->values.resize(size); @@ -960,11 +1035,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = bConst, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { } @@ -997,7 +1072,7 @@ printf("\n"); printIndents(level+1); } - printf("%lld, ", values[i]); + printf("%" PRId64 ", ", (int64_t)values[i]); } printIndents(level); printf(")\n"); @@ -1008,11 +1083,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = false, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { values.resize(size); @@ -1029,11 +1104,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = _bConst, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { this->values.resize(size); @@ -1052,11 +1127,11 @@ .ctx = ctx, .isPolyphonic = false, .isConst = bConst, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }) { } @@ -1121,15 +1196,15 @@ .ctx = NULL, .isPolyphonic = (array) ? array->isPolyphonic() : false, .isConst = (array) ? array->isConstExpr() : false, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }), Unit(VM_NO_UNIT), array(array), index(arrayIndex), currentIndex(-1) -{ +{ } void IntArrayElement::assign(Expression* expr) { @@ -1172,11 +1247,11 @@ .ctx = NULL, .isPolyphonic = (array) ? array->isPolyphonic() : false, .isConst = (array) ? array->isConstExpr() : false, - .isFinal = false, .elements = 0, .memPos = 0, .unitFactorMemPos = 0, - .unitType = VM_NO_UNIT + .unitType = VM_NO_UNIT, + .isFinal = false, }), Unit(VM_NO_UNIT), array(array), index(arrayIndex), currentIndex(-1) @@ -1230,8 +1305,8 @@ StringVariable::StringVariable(ParserContext* ctx, bool bConst) : Variable({ .ctx = ctx, + .isConst = bConst, .memPos = 0, - .isConst = bConst }) { } @@ -1248,7 +1323,7 @@ void StringVariable::dump(int level) { printIndents(level); - printf("StringVariable memPos=%lld\n", memPos); + printf("StringVariable memPos=%" PRId64 "\n", (int64_t)memPos); } ConstStringVariable::ConstStringVariable(ParserContext* ctx, String _value) @@ -1318,7 +1393,7 @@ printIndents(level); if (select) if (select->isConstExpr()) - printf("Case select %lld\n", select->evalInt()); + printf("Case select %" PRId64 "\n", (int64_t)select->evalInt()); else printf("Case select [runtime expr]\n"); else @@ -1328,16 +1403,16 @@ CaseBranch& branch = branches[i]; if (branch.from && branch.to) if (branch.from->isConstExpr() && branch.to->isConstExpr()) - 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()); else if (branch.from->isConstExpr() && !branch.to->isConstExpr()) - printf("case %lld to [runtime expr]\n", branch.from->evalInt()); + printf("case %" PRId64 " to [runtime expr]\n", (int64_t)branch.from->evalInt()); else if (!branch.from->isConstExpr() && branch.to->isConstExpr()) - printf("case [runtime expr] to %lld\n", branch.to->evalInt()); + printf("case [runtime expr] to %" PRId64 "\n", (int64_t)branch.to->evalInt()); else printf("case [runtime expr] to [runtime expr]\n"); else if (branch.from) if (branch.from->isConstExpr()) - printf("case %lld\n", branch.from->evalInt()); + printf("case %" PRId64 "\n", (int64_t)branch.from->evalInt()); else printf("case [runtime expr]\n"); else @@ -1376,7 +1451,7 @@ printIndents(level); if (m_condition) if (m_condition->isConstExpr()) - printf("while (%lld) {\n", m_condition->evalInt()); + printf("while (%" PRId64 ") {\n", (int64_t)m_condition->evalInt()); else printf("while ([runtime expr]) {\n"); else @@ -1757,7 +1832,10 @@ } } -void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { +void ParserContext::addErr(int firstLine, int lastLine, int firstColumn, + int lastColumn, int firstByte, int lengthBytes, + const char* txt) +{ ParserIssue e; e.type = PARSER_ERROR; e.txt = txt; @@ -1765,11 +1843,16 @@ e.lastLine = lastLine; e.firstColumn = firstColumn; e.lastColumn = lastColumn; + e.firstByte = firstByte; + e.lengthBytes = lengthBytes; vErrors.push_back(e); vIssues.push_back(e); } -void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt) { +void ParserContext::addWrn(int firstLine, int lastLine, int firstColumn, + int lastColumn, int firstByte, int lengthBytes, + const char* txt) +{ ParserIssue w; w.type = PARSER_WARNING; w.txt = txt; @@ -1777,16 +1860,23 @@ w.lastLine = lastLine; w.firstColumn = firstColumn; w.lastColumn = lastColumn; + w.firstByte = firstByte; + w.lengthBytes = lengthBytes; vWarnings.push_back(w); vIssues.push_back(w); } -void ParserContext::addPreprocessorComment(int firstLine, int lastLine, int firstColumn, int lastColumn) { +void ParserContext::addPreprocessorComment(int firstLine, int lastLine, + int firstColumn, int lastColumn, + int firstByte, int lengthBytes) +{ CodeBlock block; block.firstLine = firstLine; block.lastLine = lastLine; block.firstColumn = firstColumn; block.lastColumn = lastColumn; + block.firstByte = firstByte; + block.lengthBytes = lengthBytes; vPreprocessorComments.push_back(block); } @@ -1843,6 +1933,17 @@ .value = it->second }); vartable[it->first] = ref; + } +} + +void ParserContext::registerBuiltInConstRealVariables(const std::map& vars) { + for (std::map::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + ConstRealVariableRef ref = new ConstRealVariable({ + .value = it->second + }); + vartable[it->first] = ref; } }