#include "scriptmanager.hpp" #include #include #include #include #include #include #include #include #include #include #include "../mwsound/extensions.hpp" #include "cellextensions.hpp" namespace MWScript { ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose, Compiler::Context& compilerContext) : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose), mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext) {} bool ScriptManager::compile (const std::string& name) { mParser.reset(); mErrorHandler.reset(); bool Success = true; if (const ESM::Script *script = mStore.scripts.find (name)) { if (mVerbose) std::cout << "compiling script: " << name << std::endl; try { std::istringstream input (script->scriptText); Compiler::Scanner scanner (mErrorHandler, input, mCompilerContext.getExtensions()); scanner.scan (mParser); if (!mErrorHandler.isGood()) Success = false; } catch (const std::exception& error) { Success = false; } if (!Success && mVerbose) { std::cerr << "compiling failed: " << name << std::endl << script->scriptText << std::endl << std::endl; } if (Success) { std::vector code; mParser.getCode (code); mScripts.insert (std::make_pair (name, code)); // TODO sanity check on generated locals return true; } } return false; } void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext) { // compile script std::map >::iterator iter = mScripts.find (name); if (iter==mScripts.end()) { if (!compile (name)) { // failed -> ignore script from now on. std::vector empty; mScripts.insert (std::make_pair (name, empty)); return; } iter = mScripts.find (name); assert (iter!=mScripts.end()); } // execute script if (!iter->second.empty()) try { Interpreter::Interpreter interpreter (interpreterContext); installOpcodes (interpreter); interpreter.run (&iter->second[0], iter->second.size()); } catch (const std::exception& e) { std::cerr << "exeution of script " << name << " failed." << std::endl; if (mVerbose) std::cerr << "(" << e.what() << ")" << std::endl; iter->second.clear(); // don't execute again. } } void ScriptManager::installOpcodes (Interpreter::Interpreter& interpreter) { Interpreter::installOpcodes (interpreter); Cell::installOpcodes (interpreter); MWSound::installOpcodes (interpreter); } }