--- linuxsampler/trunk/src/scriptvm/ScriptVM.cpp 2014/06/01 14:44:38 2588 +++ linuxsampler/trunk/src/scriptvm/ScriptVM.cpp 2016/07/18 09:42:28 2965 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Christian Schoenebeck + * Copyright (c) 2014 - 2016 Christian Schoenebeck * * http://www.linuxsampler.org * @@ -10,8 +10,12 @@ #include "ScriptVM.h" #include +#include #include "../common/global_private.h" #include "tree.h" +#include "CoreVMFunctions.h" +#include "CoreVMDynVars.h" +#include "editor/NkspScanner.h" #define DEBUG_SCRIPTVM_CORE 0 @@ -88,10 +92,34 @@ return max; } - ScriptVM::ScriptVM() : m_parserContext(NULL), fnWait(this) { + ScriptVM::ScriptVM() : m_eventHandler(NULL), m_parserContext(NULL) { + m_fnMessage = new CoreVMFunction_message; + m_fnExit = new CoreVMFunction_exit; + m_fnWait = new CoreVMFunction_wait(this); + m_fnAbs = new CoreVMFunction_abs; + m_fnRandom = new CoreVMFunction_random; + m_fnNumElements = new CoreVMFunction_num_elements; + m_fnInc = new CoreVMFunction_inc; + m_fnDec = new CoreVMFunction_dec; + m_varRealTimer = new CoreVMDynVar_NKSP_REAL_TIMER; + m_varPerfTimer = new CoreVMDynVar_NKSP_PERF_TIMER; + m_fnShLeft = new CoreVMFunction_sh_left; + m_fnShRight = new CoreVMFunction_sh_right; } ScriptVM::~ScriptVM() { + delete m_fnMessage; + delete m_fnExit; + delete m_fnWait; + delete m_fnAbs; + delete m_fnRandom; + delete m_fnNumElements; + delete m_fnInc; + delete m_fnDec; + delete m_fnShLeft; + delete m_fnShRight; + delete m_varRealTimer; + delete m_varPerfTimer; } VMParserContext* ScriptVM::loadScript(const String& s) { @@ -102,12 +130,17 @@ VMParserContext* ScriptVM::loadScript(std::istream* is) { ParserContext* context = new ParserContext(this); //printf("parserCtx=0x%lx\n", (uint64_t)context); - + + context->registerBuiltInConstIntVariables( builtInConstIntVariables() ); + context->registerBuiltInIntVariables( builtInIntVariables() ); + context->registerBuiltInIntArrayVariables( builtInIntArrayVariables() ); + context->registerBuiltInDynVariables( builtInDynamicVariables() ); + context->createScanner(is); InstrScript_parse(context); - std::cout << "Allocating " << context->globalIntVarCount * sizeof(int) << " bytes of global int VM memory.\n"; - std::cout << "Allocating " << context->globalStrVarCount << " of global VM string variables.\n"; + dmsg(2,("Allocating %ld bytes of global int VM memory.\n", long(context->globalIntVarCount * sizeof(int)))); + dmsg(2,("Allocating %d of global VM string variables.\n", context->globalStrVarCount)); if (!context->globalIntMemory) context->globalIntMemory = new ArrayList(); if (!context->globalStrMemory) @@ -148,26 +181,82 @@ _requiredMaxStackSizeFor(&*parserCtx->handlers); } execCtx->stack.resize(parserCtx->requiredMaxStackSize); - std::cout << "Created VM exec context with " - << parserCtx->requiredMaxStackSize * sizeof(ExecContext::StackFrame) - << " bytes VM stack size.\n"; + dmsg(2,("Created VM exec context with %ld bytes VM stack size.\n", + long(parserCtx->requiredMaxStackSize * sizeof(ExecContext::StackFrame)))); //printf("execCtx=0x%lx\n", (uint64_t)execCtx); const int polySize = parserCtx->polyphonicIntVarCount; execCtx->polyphonicIntMemory.resize(polySize); memset(&execCtx->polyphonicIntMemory[0], 0, polySize * sizeof(int)); - std::cout << "Allocated " << polySize * sizeof(int) - << " bytes polyphonic memory.\n"; + dmsg(2,("Allocated %ld bytes polyphonic memory.\n", long(polySize * sizeof(int)))); return execCtx; } + std::vector ScriptVM::syntaxHighlighting(const String& s) { + std::istringstream iss(s); + return syntaxHighlighting(&iss); + } + + std::vector ScriptVM::syntaxHighlighting(std::istream* is) { + NkspScanner scanner(is); + std::vector tokens = scanner.tokens(); + std::vector result; + result.resize(tokens.size()); + for (int i = 0; i < tokens.size(); ++i) { + SourceToken* st = new SourceToken; + *st = tokens[i]; + result[i] = VMSourceToken(st); + } + return result; + } + VMFunction* ScriptVM::functionByName(const String& name) { - if (name == "message") return &fnMessage; - else if (name == "exit") return &fnExit; - else if (name == "wait") return &fnWait; + if (name == "message") return m_fnMessage; + else if (name == "exit") return m_fnExit; + else if (name == "wait") return m_fnWait; + else if (name == "abs") return m_fnAbs; + else if (name == "random") return m_fnRandom; + else if (name == "num_elements") return m_fnNumElements; + else if (name == "inc") return m_fnInc; + else if (name == "dec") return m_fnDec; + else if (name == "sh_left") return m_fnShLeft; + else if (name == "sh_right") return m_fnShRight; return NULL; } + std::map ScriptVM::builtInIntVariables() { + return std::map(); + } + + std::map ScriptVM::builtInIntArrayVariables() { + return std::map(); + } + + std::map ScriptVM::builtInDynamicVariables() { + std::map m; + + m["$NKSP_PERF_TIMER"] = m_varPerfTimer; + m["$NKSP_REAL_TIMER"] = m_varRealTimer; + m["$KSP_TIMER"] = m_varRealTimer; + + return m; + } + + std::map ScriptVM::builtInConstIntVariables() { + std::map m; + + m["$NI_CB_TYPE_INIT"] = VM_EVENT_HANDLER_INIT; + m["$NI_CB_TYPE_NOTE"] = VM_EVENT_HANDLER_NOTE; + m["$NI_CB_TYPE_RELEASE"] = VM_EVENT_HANDLER_RELEASE; + m["$NI_CB_TYPE_CONTROLLER"] = VM_EVENT_HANDLER_CONTROLLER; + + return m; + } + + VMEventHandler* ScriptVM::currentVMEventHandler() { + return m_eventHandler; + } + VMParserContext* ScriptVM::currentVMParserContext() { return m_parserContext; } @@ -184,6 +273,9 @@ return VMExecStatus_t(VM_EXEC_NOT_RUNNING | VM_EXEC_ERROR); } + // a ParserContext object is always tied to exactly one ScriptVM object + assert(m_parserContext->functionProvider == this); + ExecContext* ctx = dynamic_cast(execContex); if (!ctx) { std::cerr << "Invalid VM exec context.\n"; @@ -191,6 +283,7 @@ } EventHandler* h = dynamic_cast(handler); if (!h) return VM_EXEC_NOT_RUNNING; + m_eventHandler = handler; m_parserContext->execContext = ctx; @@ -286,6 +379,7 @@ ctx->reset(); } + m_eventHandler = NULL; m_parserContext->execContext = NULL; m_parserContext = NULL; return ctx->status;