--- linuxsampler/trunk/src/scriptvm/tree.h 2014/05/30 12:48:05 2581 +++ linuxsampler/trunk/src/scriptvm/tree.h 2017/05/31 21:07:44 3260 @@ -1,6 +1,6 @@ /* -*- c++ -*- * - * Copyright (c) 2014 Christian Schoenebeck and Andreas Persson + * Copyright (c) 2014 - 2017 Christian Schoenebeck and Andreas Persson * * http://www.linuxsampler.org * @@ -20,6 +20,7 @@ #include #include #include +#include // for memset() #include "../common/global.h" #include "../common/Ref.h" #include "../common/ArrayList.h" @@ -35,6 +36,7 @@ STMT_LIST, STMT_BRANCH, STMT_LOOP, + STMT_SYNC, }; class Node { @@ -42,6 +44,7 @@ Node(); virtual ~Node(); virtual void dump(int level = 0) = 0; + virtual bool isPolyphonic() const = 0; void printIndents(int n); }; typedef Ref NodeRef; @@ -62,6 +65,13 @@ }; typedef Ref IntExprRef; +/*class IntArrayExpr : virtual public VMIntArrayExpr, virtual public Expression { +public: + ExprType_t exprType() const { return INT_ARR_EXPR; } + String evalCastToStr(); +}; +typedef Ref IntArrayExprRef;*/ + class StringExpr : virtual public VMStringExpr, virtual public Expression { public: ExprType_t exprType() const { return STRING_EXPR; } @@ -77,6 +87,7 @@ int evalInt(); void dump(int level = 0); bool isConstExpr() const { return true; } + bool isPolyphonic() const { return false; } }; typedef Ref IntLiteralRef; @@ -87,6 +98,7 @@ bool isConstExpr() const { return true; } void dump(int level = 0); String evalStr() { return value; } + bool isPolyphonic() const { return false; } }; typedef Ref StringLiteralRef; @@ -95,15 +107,18 @@ std::vector args; void add(ExpressionRef arg) { args.push_back(arg); } void dump(int level = 0); - int argsCount() const { return args.size(); } + int argsCount() const { return (int) args.size(); } VMExpr* arg(int i) { return (i >= 0 && i < argsCount()) ? &*args.at(i) : NULL; } + bool isPolyphonic() const; }; typedef Ref ArgsRef; -class Variable : virtual public Expression { +class Variable : virtual public VMVariable, virtual public Expression { public: - virtual bool isConstExpr() const { return bConst; } + bool isConstExpr() const OVERRIDE { return bConst; } + bool isAssignable() const OVERRIDE { return !bConst; } virtual void assign(Expression* expr) = 0; + void assignExpr(VMExpr* expr) OVERRIDE { Expression* e = dynamic_cast(expr); if (e) assign(e); } protected: Variable(ParserContext* ctx, int _memPos, bool _bConst) : context(ctx), memPos(_memPos), bConst(_bConst) {} @@ -139,6 +154,18 @@ }; typedef Ref ConstIntVariableRef; +class BuiltInIntVariable : public IntVariable { + String name; + VMIntRelPtr* ptr; +public: + BuiltInIntVariable(const String& name, VMIntRelPtr* ptr); + bool isAssignable() const OVERRIDE { return !ptr->readonly; } + void assign(Expression* expr) OVERRIDE; + int evalInt() OVERRIDE; + void dump(int level = 0) OVERRIDE; +}; +typedef Ref BuiltInIntVariableRef; + class PolyphonicIntVariable : public IntVariable { public: PolyphonicIntVariable(ParserContext* ctx); @@ -146,20 +173,36 @@ }; typedef Ref PolyphonicIntVariableRef; -class IntArrayVariable : public Variable { +class IntArrayVariable : public Variable, virtual public VMIntArrayExpr { ArrayList values; public: IntArrayVariable(ParserContext* ctx, int size); - IntArrayVariable(ParserContext* ctx, int size, ArgsRef values); + IntArrayVariable(ParserContext* ctx, int size, ArgsRef values, bool _bConst = false); void assign(Expression* expr) {} // ignore scalar assignment - String evalCastToStr() { return ""; } // ignore cast to string + String evalCastToStr() { return ""; } // ignore scalar cast to string ExprType_t exprType() const { return INT_ARR_EXPR; } - const int arraySize() const { return values.size(); } + virtual int arraySize() const { return values.size(); } + virtual int evalIntElement(uint i); + virtual void assignIntElement(uint i, int value); + void dump(int level = 0); + bool isPolyphonic() const { return false; } +protected: + IntArrayVariable(ParserContext* ctx, bool bConst); +}; +typedef Ref IntArrayVariableRef; + +class BuiltInIntArrayVariable : public IntArrayVariable { + String name; + VMInt8Array* array; +public: + BuiltInIntArrayVariable(const String& name, VMInt8Array* array); + int arraySize() const { return array->size; } int evalIntElement(uint i); + bool isAssignable() const OVERRIDE { return !array->readonly; } void assignIntElement(uint i, int value); void dump(int level = 0); }; -typedef Ref IntArrayVariableRef; +typedef Ref BuiltInIntArrayVariableRef; class IntArrayElement : public IntVariable { IntArrayVariableRef array; @@ -178,6 +221,7 @@ void assign(Expression* expr); String evalStr(); void dump(int level = 0); + bool isPolyphonic() const { return false; } protected: StringVariable(ParserContext* ctx, bool bConst); }; @@ -201,6 +245,7 @@ public: BinaryOp(ExpressionRef lhs, ExpressionRef rhs) : lhs(lhs), rhs(rhs) { } bool isConstExpr() const { return lhs->isConstExpr() && rhs->isConstExpr(); } + bool isPolyphonic() const { return lhs->isPolyphonic() || rhs->isPolyphonic(); } }; typedef Ref BinaryOpRef; @@ -257,6 +302,7 @@ NoOperation() : Statement() {} StmtType_t statementType() const { return STMT_LEAF; } void dump(int level = 0) {} + bool isPolyphonic() const { return false; } }; typedef Ref NoOperationRef; @@ -276,6 +322,7 @@ void dump(int level = 0); StmtType_t statementType() const { return STMT_LIST; } virtual Statement* statement(uint i); + bool isPolyphonic() const; }; typedef Ref StatementsRef; @@ -286,6 +333,24 @@ virtual Statements* branch(uint i) const = 0; }; +class DynamicVariableCall : public Variable, virtual public IntExpr, virtual public StringExpr { + VMDynVar* dynVar; + String varName; +public: + DynamicVariableCall(const String& name, ParserContext* ctx, VMDynVar* v); + ExprType_t exprType() const OVERRIDE { return dynVar->exprType(); } + bool isConstExpr() const OVERRIDE { return dynVar->isConstExpr(); } + bool isAssignable() const OVERRIDE { return dynVar->isAssignable(); } + bool isPolyphonic() const OVERRIDE { return false; } + void assign(Expression* expr) OVERRIDE { dynVar->assignExpr(expr); } + VMIntArrayExpr* asIntArray() const OVERRIDE { return dynVar->asIntArray(); } + int evalInt() OVERRIDE; + String evalStr() OVERRIDE; + String evalCastToStr() OVERRIDE; + void dump(int level = 0) OVERRIDE; +}; +typedef Ref DynamicVariableCallRef; + class FunctionCall : virtual public LeafStatement, virtual public IntExpr, virtual public StringExpr { String functionName; ArgsRef args; @@ -293,13 +358,15 @@ public: FunctionCall(const char* function, ArgsRef args, VMFunction* fn) : functionName(function), args(args), fn(fn) { } - void dump(int level = 0); - StmtFlags_t exec(); - int evalInt(); - String evalStr(); - bool isConstExpr() const { return false; } - ExprType_t exprType() const; - String evalCastToStr(); + void dump(int level = 0) OVERRIDE; + StmtFlags_t exec() OVERRIDE; + int evalInt() OVERRIDE; + VMIntArrayExpr* asIntArray() const OVERRIDE; + String evalStr() OVERRIDE; + bool isConstExpr() const OVERRIDE { return false; } + ExprType_t exprType() const OVERRIDE; + String evalCastToStr() OVERRIDE; + bool isPolyphonic() const OVERRIDE { return args->isPolyphonic(); } protected: VMFnResult* execVMFn(); }; @@ -307,17 +374,20 @@ class EventHandler : virtual public Statements, virtual public VMEventHandler { StatementsRef statements; + bool usingPolyphonics; public: void dump(int level = 0); StmtFlags_t exec(); - EventHandler(StatementsRef statements) { this->statements = statements; } + EventHandler(StatementsRef statements); Statement* statement(uint i) { return statements->statement(i); } + bool isPolyphonic() const { return usingPolyphonics; } }; typedef Ref EventHandlerRef; class OnNote : public EventHandler { public: OnNote(StatementsRef statements) : EventHandler(statements) {} + VMEventHandlerType_t eventHandlerType() const { return VM_EVENT_HANDLER_NOTE; } String eventHandlerName() const { return "note"; } }; typedef Ref OnNoteRef; @@ -325,6 +395,7 @@ class OnInit : public EventHandler { public: OnInit(StatementsRef statements) : EventHandler(statements) {} + VMEventHandlerType_t eventHandlerType() const { return VM_EVENT_HANDLER_INIT; } String eventHandlerName() const { return "init"; } }; typedef Ref OnInitRef; @@ -332,6 +403,7 @@ class OnRelease : public EventHandler { public: OnRelease(StatementsRef statements) : EventHandler(statements) {} + VMEventHandlerType_t eventHandlerType() const { return VM_EVENT_HANDLER_RELEASE; } String eventHandlerName() const { return "release"; } }; typedef Ref OnReleaseRef; @@ -339,6 +411,7 @@ class OnController : public EventHandler { public: OnController(StatementsRef statements) : EventHandler(statements) {} + VMEventHandlerType_t eventHandlerType() const { return VM_EVENT_HANDLER_CONTROLLER; } String eventHandlerName() const { return "controller"; } }; typedef Ref OnControllerRef; @@ -353,7 +426,8 @@ int evalInt() { return 0; } EventHandler* eventHandlerByName(const String& name) const; EventHandler* eventHandler(uint index) const; - inline uint size() const { return args.size(); } + inline uint size() const { return (int) args.size(); } + bool isPolyphonic() const; }; typedef Ref EventHandlersRef; @@ -365,6 +439,7 @@ Assignment(VariableRef variable, ExpressionRef value); void dump(int level = 0); StmtFlags_t exec(); + bool isPolyphonic() const { return (variable && variable->isPolyphonic()) || (value && value->isPolyphonic()); } }; typedef Ref AssignmentRef; @@ -380,6 +455,7 @@ void dump(int level = 0); int evalBranch(); Statements* branch(uint i) const; + bool isPolyphonic() const; }; typedef Ref IfRef; @@ -403,6 +479,7 @@ //void addBranch(IntExprRef from, IntExprRef to, StatementsRef statements); //void addBranch(CaseBranchRef branch); //void addBranches(CaseBranchesRef branches); + bool isPolyphonic() const; }; typedef Ref SelectCaseRef; @@ -416,8 +493,20 @@ void dump(int level = 0); bool evalLoopStartCondition(); Statements* statements() const; + bool isPolyphonic() const { return m_condition->isPolyphonic() || m_statements->isPolyphonic(); } }; +class SyncBlock : public Statement { + StatementsRef m_statements; +public: + SyncBlock(StatementsRef statements) : m_statements(statements) {} + StmtType_t statementType() const { return STMT_SYNC; } + void dump(int level = 0); + Statements* statements() const; + bool isPolyphonic() const { return m_statements->isPolyphonic(); } +}; +typedef Ref SyncBlockRef; + class Neg : public IntExpr { IntExprRef expr; public: @@ -425,6 +514,7 @@ int evalInt() { return (expr) ? -expr->evalInt() : 0; } void dump(int level = 0); bool isConstExpr() const { return expr->isConstExpr(); } + bool isPolyphonic() const { return expr->isPolyphonic(); } }; typedef Ref NegRef; @@ -436,6 +526,7 @@ String evalStr(); void dump(int level = 0); bool isConstExpr() const; + bool isPolyphonic() const { return lhs->isPolyphonic() || rhs->isPolyphonic(); } }; typedef Ref ConcatStringRef; @@ -454,6 +545,7 @@ int evalInt(); void dump(int level = 0); bool isConstExpr() const; + bool isPolyphonic() const { return lhs->isPolyphonic() || rhs->isPolyphonic(); } private: IntExprRef lhs; IntExprRef rhs; @@ -469,6 +561,14 @@ }; typedef Ref OrRef; +class BitwiseOr : virtual public BinaryOp, virtual public IntExpr { +public: + BitwiseOr(IntExprRef lhs, IntExprRef rhs) : BinaryOp(lhs,rhs) {} + int evalInt(); + void dump(int level = 0); +}; +typedef Ref BitwiseOrRef; + class And : virtual public BinaryOp, virtual public IntExpr { public: And(IntExprRef lhs, IntExprRef rhs) : BinaryOp(lhs,rhs) {} @@ -477,6 +577,14 @@ }; typedef Ref AndRef; +class BitwiseAnd : virtual public BinaryOp, virtual public IntExpr { +public: + BitwiseAnd(IntExprRef lhs, IntExprRef rhs) : BinaryOp(lhs,rhs) {} + int evalInt(); + void dump(int level = 0); +}; +typedef Ref BitwiseAndRef; + class Not : virtual public IntExpr { IntExprRef expr; public: @@ -484,9 +592,21 @@ int evalInt() { return !expr->evalInt(); } void dump(int level = 0); bool isConstExpr() const { return expr->isConstExpr(); } + bool isPolyphonic() const { return expr->isPolyphonic(); } }; typedef Ref NotRef; +class BitwiseNot : virtual public IntExpr { + IntExprRef expr; +public: + BitwiseNot(IntExprRef expr) : expr(expr) {} + int evalInt() { return ~expr->evalInt(); } + void dump(int level = 0); + bool isConstExpr() const { return expr->isConstExpr(); } + bool isPolyphonic() const { return expr->isPolyphonic(); } +}; +typedef Ref BitwiseNotRef; + class ParserContext : public VMParserContext { public: struct Error { @@ -497,14 +617,15 @@ void* scanner; std::istream* is; - std::vector errors; - std::vector warnings; - std::vector issues; + std::vector vErrors; + std::vector vWarnings; + std::vector vIssues; std::set builtinPreprocessorConditions; std::set userPreprocessorConditions; std::map vartable; + std::map userFnTable; int globalIntVarCount; int globalStrVarCount; int polyphonicIntVarCount; @@ -518,6 +639,7 @@ ArrayList* globalIntMemory; ArrayList* globalStrMemory; + int requiredMaxStackSize; VMFunctionProvider* functionProvider; @@ -526,22 +648,32 @@ ParserContext(VMFunctionProvider* parent) : scanner(NULL), is(NULL), globalIntVarCount(0), globalStrVarCount(0), polyphonicIntVarCount(0), - globalIntMemory(NULL), globalStrMemory(NULL), functionProvider(parent), - execContext(NULL) + globalIntMemory(NULL), globalStrMemory(NULL), requiredMaxStackSize(-1), + functionProvider(parent), execContext(NULL) { } - virtual ~ParserContext() { destroyScanner(); } + virtual ~ParserContext(); VariableRef globalVar(const String& name); IntVariableRef globalIntVar(const String& name); StringVariableRef globalStrVar(const String& name); VariableRef variableByName(const String& name); - void addErr(int line, const char* txt); - void addWrn(int line, const char* txt); + StatementsRef userFunctionByName(const String& name); + void addErr(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt); + void addWrn(int firstLine, int lastLine, int firstColumn, int lastColumn, const char* txt); void createScanner(std::istream* is); void destroyScanner(); bool setPreprocessorCondition(const char* name); bool resetPreprocessorCondition(const char* name); bool isPreprocessorConditionSet(const char* name); + std::vector issues() const OVERRIDE; + std::vector errors() const OVERRIDE; + std::vector warnings() const OVERRIDE; + VMEventHandler* eventHandler(uint index) OVERRIDE; + VMEventHandler* eventHandlerByName(const String& name) OVERRIDE; + void registerBuiltInConstIntVariables(const std::map& vars); + void registerBuiltInIntVariables(const std::map& vars); + void registerBuiltInIntArrayVariables(const std::map& vars); + void registerBuiltInDynVariables(const std::map& vars); }; class ExecContext : public VMExecContext { @@ -561,9 +693,11 @@ ArrayList stack; int stackFrame; int suspendMicroseconds; + size_t instructionsCount; ExecContext() : - status(VM_EXEC_NOT_RUNNING), stackFrame(-1), suspendMicroseconds(0) {} + status(VM_EXEC_NOT_RUNNING), stackFrame(-1), suspendMicroseconds(0), + instructionsCount(0) {} virtual ~ExecContext() {} @@ -588,9 +722,18 @@ stackFrame = -1; } - int suspensionTimeMicroseconds() const { + int suspensionTimeMicroseconds() const OVERRIDE { return suspendMicroseconds; } + + void resetPolyphonicData() OVERRIDE { + if (polyphonicIntMemory.empty()) return; + memset(&polyphonicIntMemory[0], 0, polyphonicIntMemory.size() * sizeof(int)); + } + + size_t instructionsPerformed() const OVERRIDE { + return instructionsCount; + } }; } // namespace LinuxSampler