//----------------------------------------------------------------------------- // // Copyright (C) 2015-2017 David Hill // // See COPYING for license information. // //----------------------------------------------------------------------------- // // Environment. // //----------------------------------------------------------------------------- #include "Environment.h" #include "Code.h" #include "Module.h" #include "Thread.h" #include "ACSVM/CodeData.hpp" #include "ACSVM/Error.hpp" #include "ACSVM/Serial.hpp" extern "C" { //----------------------------------------------------------------------------| // Extern Functions | // // // ACSVM_Environment constructor // ACSVM_Environment::ACSVM_Environment(ACSVM_EnvironmentFuncs const &funcs_, void *data_) : funcs{funcs_}, data{data_} { if(funcs.ctor) funcs.ctor(this); } // // ACSVM_Environment destructor // ACSVM_Environment::~ACSVM_Environment() { if(funcs.dtor) funcs.dtor(this); } // // ACSVM_Environment::allocThread // ACSVM::Thread *ACSVM_Environment::allocThread() { if(!funcs.allocThread) return new ACSVM_Thread(this, {}, nullptr); if(ACSVM_Thread *thread = funcs.allocThread(this)) return thread; throw std::bad_alloc(); } // // ACSVM_Environment::callFunc // bool ACSVM_Environment::callFunc(ACSVM::Thread *thread, ACSVM::Word func, ACSVM::Word const *argV, ACSVM::Word argC) { if(func <= static_cast(ACSVM::Func::None)) return ACSVM::Environment::callFunc(thread, func, argV, argC); auto callFunc = callFuncV[func - static_cast(ACSVM::Func::None) - 1]; return callFunc(static_cast(thread), argV, argC); } // // ACSVM_Environment::callSpecImpl // ACSVM::Word ACSVM_Environment::callSpecImpl(ACSVM::Thread *thread, ACSVM::Word spec, ACSVM::Word const *argV, ACSVM::Word argC) { if(!funcs.callSpecImpl) return ACSVM::Environment::callSpecImpl(thread, spec, argV, argC); return funcs.callSpecImpl(this, static_cast(thread), spec, argV, argC); } // // ACSVM_Environment::checkLock // bool ACSVM_Environment::checkLock(ACSVM::Thread *thread, ACSVM::Word lock, bool door) { if(!funcs.checkLock) return ACSVM::Environment::checkLock(thread, lock, door); return funcs.checkLock(this, static_cast(thread), lock, door); } // // ACSVM_Environment::checkTag // bool ACSVM_Environment::checkTag(ACSVM::Word type, ACSVM::Word tag) { if(!funcs.checkTag) return ACSVM::Environment::checkTag(type, tag); return funcs.checkTag(this, type, tag); } // // ACSVM_Environment::getModuleName // ACSVM::ModuleName ACSVM_Environment::getModuleName(char const *str, std::size_t len) { if(!funcs.getModuleName) return ACSVM::Environment::getModuleName(str, len); auto name = funcs.getModuleName(this, str, len); return {reinterpret_cast(name.s), name.p, name.i}; } // // ACSVM_Environment::loadModule // void ACSVM_Environment::loadModule(ACSVM::Module *module) { if(!funcs.loadModule) throw ACSVM::ReadError(); if(!funcs.loadModule(this, reinterpret_cast(module))) throw ACSVM::ReadError(); } // // ACSVM_Environment::loadState // void ACSVM_Environment::loadState(ACSVM::Serial &in) { ACSVM::Environment::loadState(in); if(funcs.loadState) funcs.loadState(this, reinterpret_cast(&in)); } // // ACSVM_Environment::printArray // void ACSVM_Environment::printArray(ACSVM::PrintBuf &buf, ACSVM::Array const &array, ACSVM::Word index, ACSVM::Word limit) { if(!funcs.printArray) return ACSVM::Environment::printArray(buf, array, index, limit); funcs.printArray(this, reinterpret_cast(&buf), reinterpret_cast(&array), index, limit); } // // ACSVM_Environment::printKill // void ACSVM_Environment::printKill(ACSVM::Thread *thread, ACSVM::Word type, ACSVM::Word killData) { if(!funcs.printKill) return ACSVM::Environment::printKill(thread, type, killData); funcs.printKill(this, static_cast(thread), type, killData); } // // ACSVM_Environment::readModuleName // ACSVM::ModuleName ACSVM_Environment::readModuleName(ACSVM::Serial &in) const { if(!funcs.readModuleName) return ACSVM::Environment::readModuleName(in); auto name = funcs.readModuleName(this, reinterpret_cast(&in)); return {reinterpret_cast(name.s), name.p, name.i}; } // // ACSVM_Environment::refStrings // void ACSVM_Environment::refStrings() { ACSVM::Environment::refStrings(); if(funcs.refStrings) funcs.refStrings(this); } // // ACSVM_Environment::resetStrings // void ACSVM_Environment::resetStrings() { ACSVM::Environment::resetStrings(); if(funcs.resetStrings) funcs.resetStrings(this); } // // ACSVM_Environment::saveState // void ACSVM_Environment::saveState(ACSVM::Serial &out) const { ACSVM::Environment::saveState(out); if(funcs.saveState) funcs.saveState(this, reinterpret_cast(&out)); } // // ACSVM_Environment::writeModuleName // void ACSVM_Environment::writeModuleName(ACSVM::Serial &out, ACSVM::ModuleName const &in) const { if(!funcs.writeModuleName) return ACSVM::Environment::writeModuleName(out, in); funcs.writeModuleName(this, reinterpret_cast(&out), {reinterpret_cast(in.s), in.p, in.i}); } // // ACSVM_AllocEnvironment // ACSVM_Environment *ACSVM_AllocEnvironment(ACSVM_EnvironmentFuncs const *funcs, void *data) { return new(std::nothrow) ACSVM_Environment(*funcs, data); } // // ACSVM_FreeEnvironment // void ACSVM_FreeEnvironment(ACSVM_Environment *env) { delete env; } // // ACSVM_Environment_AddCallFunc // ACSVM_Word ACSVM_Environment_AddCallFunc(ACSVM_Environment *env, ACSVM_CallFunc func) { env->callFuncV.push_back(func); return env->callFuncV.size() + static_cast(ACSVM::Func::None); } // // ACSVM_Environment_AddCodeDataACS0 // void ACSVM_Environment_AddCodeDataACS0(ACSVM_Environment *env, ACSVM_Word code, char const *args, ACSVM_Code transCode_, ACSVM_Word stackArgC, ACSVM_Word transFunc) { try { auto transCode = static_cast(transCode_); env->addCodeDataACS0(code, {args, transCode, stackArgC, transFunc}); } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); } } // // ACSVM_Environment_AddFuncDataACS0 // void ACSVM_Environment_AddFuncDataACS0(ACSVM_Environment *env, ACSVM_Word func, ACSVM_Word transFunc, ACSVM_Word const *transCodeArgCV, ACSVM_Code const *transCodeV, size_t transCodeC) { try { if(transCodeC) { std::unique_ptr transCodes {new ACSVM::FuncDataACS0::TransCode[transCodeC]}; for(std::size_t i = 0; i != transCodeC; ++i) transCodes[i] = {transCodeArgCV[i], static_cast(transCodeV[i])}; env->addFuncDataACS0(func, {transFunc, std::move(transCodes), transCodeC}); } else env->addFuncDataACS0(func, transFunc); } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); } } // // ACSVM_Environment_CollectStrings // void ACSVM_Environment_CollectStrings(ACSVM_Environment *env) { env->collectStrings(); } // // ACSVM_Environment_Exec // void ACSVM_Environment_Exec(ACSVM_Environment *env) { try { env->exec(); } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); } } // // ACSVM_Environment_FreeGlobalScope // void ACSVM_Environment_FreeGlobalScope(ACSVM_Environment *env, ACSVM_GlobalScope *scope) { env->freeGlobalScope(reinterpret_cast(scope)); } // // ACSVM_Environment_FreeModule // void ACSVM_Environment_FreeModule(ACSVM_Environment *env, ACSVM_Module *module) { env->freeModule(reinterpret_cast(module)); } // // ACSVM_Environment_GetBranchLimit // ACSVM_Word ACSVM_Environment_GetBranchLimit(ACSVM_Environment const *env) { return env->branchLimit; } // // ACSVM_Environment_GetData // void *ACSVM_Environment_GetData(ACSVM_Environment const *env) { return env->data; } // // ACSVM_Environment_GetGlobalScope // ACSVM_GlobalScope *ACSVM_Environment_GetGlobalScope(ACSVM_Environment *env, ACSVM_Word id) { try { return reinterpret_cast(env->getGlobalScope(id)); } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); return nullptr; } } // // ACSVM_Environment_GetModule // ACSVM_Module *ACSVM_Environment_GetModule(ACSVM_Environment *env, ACSVM_ModuleName name) { try { return reinterpret_cast(env->getModule( {reinterpret_cast(name.s), name.p, name.i})); } catch(ACSVM::ReadError const &e) { if(env->funcs.readError) env->funcs.readError(env, e.what()); return nullptr; } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); return nullptr; } } // // ACSVM_Environment_GetScriptLocRegC // ACSVM_Word ACSVM_Environment_GetScriptLocRegC(ACSVM_Environment const *env) { return env->scriptLocRegC; } // // ACSVM_Environment_GetStringTable // ACSVM_StringTable *ACSVM_Environment_GetStringTable(ACSVM_Environment *env) { return reinterpret_cast(&env->stringTable); } // // ACSVM_Environment_HasActiveThread // bool ACSVM_Environment_HasActiveThread(ACSVM_Environment const *env) { return env->hasActiveThread(); } // // ACSVM_Environment_LoadState // bool ACSVM_Environment_LoadState(ACSVM_Environment *env, ACSVM_Serial *in) { try { env->loadState(*reinterpret_cast(in)); return true; } catch(ACSVM::SerialError const &e) { if(env->funcs.serialError) env->funcs.serialError(env, e.what()); return false; } catch(std::bad_alloc const &e) { if(env->funcs.bad_alloc) env->funcs.bad_alloc(env, e.what()); return false; } } // // ACSVM_Environment_SaveState // void ACSVM_Environment_SaveState(ACSVM_Environment *env, ACSVM_Serial *out) { env->saveState(*reinterpret_cast(out)); } // // ACSVM_Environment_SetBranchLimit // void ACSVM_Environment_SetBranchLimit(ACSVM_Environment *env, ACSVM_Word branchLimit) { env->branchLimit = branchLimit; } // // ACSVM_Environment_SetData // void ACSVM_Environment_SetData(ACSVM_Environment *env, void *data) { env->data = data; } // // ACSVM_Environment_SetScriptLocRegC // void ACSVM_Environment_SetScriptLocReg(ACSVM_Environment *env, ACSVM_Word scriptLocRegC) { env->scriptLocRegC = scriptLocRegC; } } // EOF