mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Merge branch 'mwscript' into 'master'
Multiple mwscript optimizations and some refactoring See merge request OpenMW/openmw!2600
This commit is contained in:
commit
dc3ec1a0a0
@ -42,6 +42,7 @@
|
||||
Feature #7058: Implement TestModels (T3D) console command
|
||||
Feature #7087: Block resolution change in the Windowed Fullscreen mode
|
||||
Feature #7130: Ability to set MyGUI logging verbosity
|
||||
Feature #7148: Optimize string literal lookup in mwscript
|
||||
|
||||
0.48.0
|
||||
------
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
@ -187,10 +188,10 @@ namespace MWDialogue
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DialogueManager::compile(
|
||||
const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor)
|
||||
std::optional<Interpreter::Program> DialogueManager::compile(const std::string& cmd, const MWWorld::Ptr& actor)
|
||||
{
|
||||
bool success = true;
|
||||
std::optional<Interpreter::Program> program;
|
||||
|
||||
try
|
||||
{
|
||||
@ -220,7 +221,7 @@ namespace MWDialogue
|
||||
success = false;
|
||||
|
||||
if (success)
|
||||
parser.getCode(code);
|
||||
program = parser.getProgram();
|
||||
}
|
||||
catch (const Compiler::SourceException& /* error */)
|
||||
{
|
||||
@ -238,20 +239,19 @@ namespace MWDialogue
|
||||
Log(Debug::Error) << "Error: compiling failed (dialogue script): \n" << cmd << "\n";
|
||||
}
|
||||
|
||||
return success;
|
||||
return program;
|
||||
}
|
||||
|
||||
void DialogueManager::executeScript(const std::string& script, const MWWorld::Ptr& actor)
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
if (compile(script, code, actor))
|
||||
if (const std::optional<Interpreter::Program> program = compile(script, actor))
|
||||
{
|
||||
try
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext(&actor.getRefData().getLocals(), actor);
|
||||
Interpreter::Interpreter interpreter;
|
||||
MWScript::installOpcodes(interpreter);
|
||||
interpreter.run(code.data(), code.size(), interpreterContext);
|
||||
interpreter.run(*program, interpreterContext);
|
||||
}
|
||||
catch (const std::exception& error)
|
||||
{
|
||||
|
@ -4,11 +4,13 @@
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <components/compiler/streamerrorhandler.hpp>
|
||||
#include <components/esm3/loadinfo.hpp>
|
||||
#include <components/interpreter/program.hpp>
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
@ -63,7 +65,8 @@ namespace MWDialogue
|
||||
void updateActorKnownTopics();
|
||||
void updateGlobals();
|
||||
|
||||
bool compile(const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor);
|
||||
std::optional<Interpreter::Program> compile(const std::string& cmd, const MWWorld::Ptr& actor);
|
||||
|
||||
void executeScript(const std::string& script, const MWWorld::Ptr& actor);
|
||||
|
||||
void executeTopic(const ESM::RefId& topic, ResponseCallback* callback);
|
||||
|
@ -208,9 +208,8 @@ namespace MWGui
|
||||
ConsoleInterpreterContext interpreterContext(*this, mPtr);
|
||||
Interpreter::Interpreter interpreter;
|
||||
MWScript::installOpcodes(interpreter, mConsoleOnlyScripts);
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
output.getCode(code);
|
||||
interpreter.run(code.data(), code.size(), interpreterContext);
|
||||
const Interpreter::Program program = output.getProgram();
|
||||
interpreter.run(program, interpreterContext);
|
||||
}
|
||||
catch (const std::exception& error)
|
||||
{
|
||||
|
@ -79,9 +79,7 @@ namespace MWScript
|
||||
|
||||
if (Success)
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
mParser.getCode(code);
|
||||
mScripts.emplace(name, CompiledScript(code, mParser.getLocals()));
|
||||
mScripts.emplace(name, CompiledScript(mParser.getProgram(), mParser.getLocals()));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -100,8 +98,7 @@ namespace MWScript
|
||||
if (!compile(name))
|
||||
{
|
||||
// failed -> ignore script from now on.
|
||||
std::vector<Interpreter::Type_Code> empty;
|
||||
mScripts.emplace(name, CompiledScript(empty, Compiler::Locals()));
|
||||
mScripts.emplace(name, CompiledScript({}, Compiler::Locals()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -111,7 +108,8 @@ namespace MWScript
|
||||
|
||||
// execute script
|
||||
const auto& target = interpreterContext.getTarget();
|
||||
if (!iter->second.mByteCode.empty() && iter->second.mInactive.find(target) == iter->second.mInactive.end())
|
||||
if (!iter->second.mProgram.mInstructions.empty()
|
||||
&& iter->second.mInactive.find(target) == iter->second.mInactive.end())
|
||||
try
|
||||
{
|
||||
if (!mOpcodesInstalled)
|
||||
@ -120,7 +118,7 @@ namespace MWScript
|
||||
mOpcodesInstalled = true;
|
||||
}
|
||||
|
||||
mInterpreter.run(&iter->second.mByteCode[0], iter->second.mByteCode.size(), interpreterContext);
|
||||
mInterpreter.run(iter->second.mProgram, interpreterContext);
|
||||
return true;
|
||||
}
|
||||
catch (const MissingImplicitRefError& e)
|
||||
|
@ -46,12 +46,12 @@ namespace MWScript
|
||||
|
||||
struct CompiledScript
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> mByteCode;
|
||||
Interpreter::Program mProgram;
|
||||
Compiler::Locals mLocals;
|
||||
std::set<ESM::RefId> mInactive;
|
||||
|
||||
CompiledScript(const std::vector<Interpreter::Type_Code>& code, const Compiler::Locals& locals)
|
||||
: mByteCode(code)
|
||||
explicit CompiledScript(Interpreter::Program&& program, const Compiler::Locals& locals)
|
||||
: mProgram(std::move(program))
|
||||
, mLocals(locals)
|
||||
{
|
||||
}
|
||||
|
@ -21,11 +21,7 @@ namespace
|
||||
Compiler::Scanner scanner(mErrorHandler, input, mCompilerContext.getExtensions());
|
||||
scanner.scan(mParser);
|
||||
if (mErrorHandler.isGood())
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
mParser.getCode(code);
|
||||
return CompiledScript(code, mParser.getLocals());
|
||||
}
|
||||
return CompiledScript(mParser.getProgram(), mParser.getLocals());
|
||||
else if (!shouldFail)
|
||||
logErrors();
|
||||
return {};
|
||||
@ -50,7 +46,7 @@ namespace
|
||||
|
||||
void run(const CompiledScript& script, TestInterpreterContext& context)
|
||||
{
|
||||
mInterpreter.run(&script.mByteCode[0], static_cast<int>(script.mByteCode.size()), context);
|
||||
mInterpreter.run(script.mProgram, context);
|
||||
}
|
||||
|
||||
template <typename T, typename... TArgs>
|
||||
|
@ -249,11 +249,11 @@ namespace
|
||||
|
||||
struct CompiledScript
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> mByteCode;
|
||||
Interpreter::Program mProgram;
|
||||
Compiler::Locals mLocals;
|
||||
|
||||
CompiledScript(const std::vector<Interpreter::Type_Code>& code, const Compiler::Locals& locals)
|
||||
: mByteCode(code)
|
||||
CompiledScript(Interpreter::Program&& program, const Compiler::Locals& locals)
|
||||
: mProgram(std::move(program))
|
||||
, mLocals(locals)
|
||||
{
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ namespace Compiler
|
||||
return mName;
|
||||
}
|
||||
|
||||
void FileParser::getCode(std::vector<Interpreter::Type_Code>& code) const
|
||||
Interpreter::Program FileParser::getProgram() const
|
||||
{
|
||||
mScriptParser.getCode(code);
|
||||
return mScriptParser.getProgram();
|
||||
}
|
||||
|
||||
const Locals& FileParser::getLocals() const
|
||||
|
@ -31,8 +31,7 @@ namespace Compiler
|
||||
std::string getName() const;
|
||||
///< Return script name.
|
||||
|
||||
void getCode(std::vector<Interpreter::Type_Code>& code) const;
|
||||
///< store generated code in \a code.
|
||||
Interpreter::Program getProgram() const;
|
||||
|
||||
const Locals& getLocals() const;
|
||||
///< get local variable declarations.
|
||||
|
@ -1,56 +1,10 @@
|
||||
#include "literals.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
int Literals::getIntegerSize() const
|
||||
{
|
||||
return static_cast<int>(mIntegers.size() * sizeof(Interpreter::Type_Integer));
|
||||
}
|
||||
|
||||
int Literals::getFloatSize() const
|
||||
{
|
||||
return static_cast<int>(mFloats.size() * sizeof(Interpreter::Type_Float));
|
||||
}
|
||||
|
||||
int Literals::getStringSize() const
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter(mStrings.begin()); iter != mStrings.end(); ++iter)
|
||||
size += static_cast<int>(iter->size()) + 1;
|
||||
|
||||
if (size % 4) // padding
|
||||
size += 4 - size % 4;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Literals::append(std::vector<Interpreter::Type_Code>& code) const
|
||||
{
|
||||
for (const int& mInteger : mIntegers)
|
||||
code.push_back(*reinterpret_cast<const Interpreter::Type_Code*>(&mInteger));
|
||||
|
||||
for (const float& mFloat : mFloats)
|
||||
code.push_back(*reinterpret_cast<const Interpreter::Type_Code*>(&mFloat));
|
||||
|
||||
int stringBlockSize = getStringSize();
|
||||
int size = static_cast<int>(code.size());
|
||||
|
||||
code.resize(size + stringBlockSize / 4);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
for (const auto& mString : mStrings)
|
||||
{
|
||||
size_t stringSize = mString.size() + 1;
|
||||
|
||||
std::copy(mString.c_str(), mString.c_str() + stringSize, reinterpret_cast<char*>(&code[size]) + offset);
|
||||
offset += stringSize;
|
||||
}
|
||||
}
|
||||
|
||||
int Literals::addInteger(Interpreter::Type_Integer value)
|
||||
{
|
||||
int index = static_cast<int>(mIntegers.size());
|
||||
|
@ -17,18 +17,11 @@ namespace Compiler
|
||||
std::vector<std::string> mStrings;
|
||||
|
||||
public:
|
||||
int getIntegerSize() const;
|
||||
///< Return size of integer block (in bytes).
|
||||
const std::vector<Interpreter::Type_Integer>& getIntegers() const { return mIntegers; }
|
||||
|
||||
int getFloatSize() const;
|
||||
///< Return size of float block (in bytes).
|
||||
const std::vector<Interpreter::Type_Float>& getFloats() const { return mFloats; }
|
||||
|
||||
int getStringSize() const;
|
||||
///< Return size of string block (in bytes).
|
||||
|
||||
void append(std::vector<Interpreter::Type_Code>& code) const;
|
||||
///< Apepnd literal blocks to code.
|
||||
/// \note code blocks will be padded for 32-bit alignment.
|
||||
const std::vector<std::string>& getStrings() const { return mStrings; }
|
||||
|
||||
int addInteger(Interpreter::Type_Integer value);
|
||||
///< add integer liternal and return index.
|
||||
|
@ -13,27 +13,14 @@ namespace Compiler
|
||||
{
|
||||
}
|
||||
|
||||
void Output::getCode(std::vector<Interpreter::Type_Code>& code) const
|
||||
Interpreter::Program Output::getProgram() const
|
||||
{
|
||||
code.clear();
|
||||
|
||||
// header
|
||||
code.push_back(static_cast<Interpreter::Type_Code>(mCode.size()));
|
||||
|
||||
assert(mLiterals.getIntegerSize() % 4 == 0);
|
||||
code.push_back(static_cast<Interpreter::Type_Code>(mLiterals.getIntegerSize() / 4));
|
||||
|
||||
assert(mLiterals.getFloatSize() % 4 == 0);
|
||||
code.push_back(static_cast<Interpreter::Type_Code>(mLiterals.getFloatSize() / 4));
|
||||
|
||||
assert(mLiterals.getStringSize() % 4 == 0);
|
||||
code.push_back(static_cast<Interpreter::Type_Code>(mLiterals.getStringSize() / 4));
|
||||
|
||||
// code
|
||||
std::copy(mCode.begin(), mCode.end(), std::back_inserter(code));
|
||||
|
||||
// literals
|
||||
mLiterals.append(code);
|
||||
return Interpreter::Program{
|
||||
.mInstructions = mCode,
|
||||
.mIntegers = mLiterals.getIntegers(),
|
||||
.mFloats = mLiterals.getFloats(),
|
||||
.mStrings = mLiterals.getStrings(),
|
||||
};
|
||||
}
|
||||
|
||||
const Literals& Output::getLiterals() const
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <components/interpreter/program.hpp>
|
||||
#include <components/interpreter/types.hpp>
|
||||
|
||||
namespace Compiler
|
||||
@ -20,8 +21,7 @@ namespace Compiler
|
||||
public:
|
||||
Output(Locals& locals);
|
||||
|
||||
void getCode(std::vector<Interpreter::Type_Code>& code) const;
|
||||
///< store generated code in \a code.
|
||||
Interpreter::Program getProgram() const;
|
||||
|
||||
const Literals& getLiterals() const;
|
||||
|
||||
|
@ -15,9 +15,9 @@ namespace Compiler
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptParser::getCode(std::vector<Interpreter::Type_Code>& code) const
|
||||
Interpreter::Program ScriptParser::getProgram() const
|
||||
{
|
||||
mOutput.getCode(code);
|
||||
return mOutput.getProgram();
|
||||
}
|
||||
|
||||
bool ScriptParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner)
|
||||
|
@ -23,8 +23,7 @@ namespace Compiler
|
||||
/// \param end of script is marked by end keyword.
|
||||
ScriptParser(ErrorHandler& errorHandler, const Context& context, Locals& locals, bool end = false);
|
||||
|
||||
void getCode(std::vector<Interpreter::Type_Code>& code) const;
|
||||
///< store generated code in \a code.
|
||||
Interpreter::Program getProgram() const;
|
||||
|
||||
bool parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner) override;
|
||||
///< Handle a name token.
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "opcodes.hpp"
|
||||
#include "program.hpp"
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
@ -104,30 +105,19 @@ namespace Interpreter
|
||||
}
|
||||
}
|
||||
|
||||
Interpreter::Interpreter()
|
||||
: mRunning(false)
|
||||
void Interpreter::run(const Program& program, Context& context)
|
||||
{
|
||||
}
|
||||
|
||||
void Interpreter::run(const Type_Code* code, int codeSize, Context& context)
|
||||
{
|
||||
assert(codeSize >= 4);
|
||||
|
||||
begin();
|
||||
|
||||
try
|
||||
{
|
||||
mRuntime.configure(code, codeSize, context);
|
||||
mRuntime.configure(program, context);
|
||||
|
||||
int opcodes = static_cast<int>(code[0]);
|
||||
|
||||
const Type_Code* codeBlock = code + 4;
|
||||
|
||||
while (mRuntime.getPC() >= 0 && mRuntime.getPC() < opcodes)
|
||||
while (mRuntime.getPC() >= 0 && static_cast<std::size_t>(mRuntime.getPC()) < program.mInstructions.size())
|
||||
{
|
||||
Type_Code runCode = codeBlock[mRuntime.getPC()];
|
||||
const Type_Code instruction = program.mInstructions[mRuntime.getPC()];
|
||||
mRuntime.setPC(mRuntime.getPC() + 1);
|
||||
execute(runCode);
|
||||
execute(instruction);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
@ -7,26 +7,25 @@
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
|
||||
#include "components/interpreter/program.hpp"
|
||||
#include "opcodes.hpp"
|
||||
#include "runtime.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
struct Program;
|
||||
|
||||
class Interpreter
|
||||
{
|
||||
std::stack<Runtime> mCallstack;
|
||||
bool mRunning;
|
||||
bool mRunning = false;
|
||||
Runtime mRuntime;
|
||||
std::map<int, std::unique_ptr<Opcode1>> mSegment0;
|
||||
std::map<int, std::unique_ptr<Opcode1>> mSegment2;
|
||||
std::map<int, std::unique_ptr<Opcode1>> mSegment3;
|
||||
std::map<int, std::unique_ptr<Opcode0>> mSegment5;
|
||||
|
||||
// not implemented
|
||||
Interpreter(const Interpreter&);
|
||||
Interpreter& operator=(const Interpreter&);
|
||||
|
||||
void execute(Type_Code code);
|
||||
|
||||
void begin();
|
||||
@ -41,7 +40,10 @@ namespace Interpreter
|
||||
}
|
||||
|
||||
public:
|
||||
Interpreter();
|
||||
Interpreter() = default;
|
||||
|
||||
Interpreter(const Interpreter&) = delete;
|
||||
Interpreter& operator=(const Interpreter&) = delete;
|
||||
|
||||
template <typename T, typename... TArgs>
|
||||
void installSegment0(int code, TArgs&&... args)
|
||||
@ -67,7 +69,7 @@ namespace Interpreter
|
||||
installSegment(mSegment5, code, std::make_unique<T>(std::forward<TArgs>(args)...));
|
||||
}
|
||||
|
||||
void run(const Type_Code* code, int codeSize, Context& context);
|
||||
void run(const Program& program, Context& context);
|
||||
};
|
||||
}
|
||||
|
||||
|
20
components/interpreter/program.hpp
Normal file
20
components/interpreter/program.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef OPENMW_COMPONENTS_INTERPRETER_PROGRAM_H
|
||||
#define OPENMW_COMPONENTS_INTERPRETER_PROGRAM_H
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
struct Program
|
||||
{
|
||||
std::vector<Type_Code> mInstructions;
|
||||
std::vector<Type_Integer> mIntegers;
|
||||
std::vector<Type_Float> mFloats;
|
||||
std::vector<std::string> mStrings;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
#include "runtime.hpp"
|
||||
#include "program.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@ -6,81 +7,46 @@
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
Runtime::Runtime()
|
||||
: mContext(nullptr)
|
||||
, mCode(nullptr)
|
||||
, mCodeSize(0)
|
||||
, mPC(0)
|
||||
{
|
||||
}
|
||||
|
||||
int Runtime::getPC() const
|
||||
{
|
||||
return mPC;
|
||||
}
|
||||
|
||||
int Runtime::getIntegerLiteral(int index) const
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(mCode[1]))
|
||||
throw std::out_of_range("out of range");
|
||||
if (index < 0 || mProgram->mIntegers.size() <= static_cast<std::size_t>(index))
|
||||
throw std::out_of_range("Invalid integer index");
|
||||
|
||||
const Type_Code* literalBlock = mCode + 4 + mCode[0];
|
||||
|
||||
return *reinterpret_cast<const int*>(&literalBlock[index]);
|
||||
return mProgram->mIntegers[static_cast<std::size_t>(index)];
|
||||
}
|
||||
|
||||
float Runtime::getFloatLiteral(int index) const
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(mCode[2]))
|
||||
throw std::out_of_range("out of range");
|
||||
if (index < 0 || mProgram->mFloats.size() <= static_cast<std::size_t>(index))
|
||||
throw std::out_of_range("Invalid float index");
|
||||
|
||||
const Type_Code* literalBlock = mCode + 4 + mCode[0] + mCode[1];
|
||||
|
||||
return *reinterpret_cast<const float*>(&literalBlock[index]);
|
||||
return mProgram->mFloats[static_cast<std::size_t>(index)];
|
||||
}
|
||||
|
||||
std::string_view Runtime::getStringLiteral(int index) const
|
||||
{
|
||||
if (index < 0 || static_cast<int>(mCode[3]) <= 0)
|
||||
throw std::out_of_range("out of range");
|
||||
if (index < 0 || mProgram->mStrings.size() <= static_cast<std::size_t>(index))
|
||||
throw std::out_of_range("Invalid string literal index");
|
||||
|
||||
const char* literalBlock = reinterpret_cast<const char*>(mCode + 4 + mCode[0] + mCode[1] + mCode[2]);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
for (; index; --index)
|
||||
{
|
||||
offset += std::strlen(literalBlock + offset) + 1;
|
||||
if (offset / 4 >= mCode[3])
|
||||
throw std::out_of_range("out of range");
|
||||
}
|
||||
|
||||
return literalBlock + offset;
|
||||
return mProgram->mStrings[static_cast<std::size_t>(index)];
|
||||
}
|
||||
|
||||
void Runtime::configure(const Type_Code* code, int codeSize, Context& context)
|
||||
void Runtime::configure(const Program& program, Context& context)
|
||||
{
|
||||
clear();
|
||||
|
||||
mContext = &context;
|
||||
mCode = code;
|
||||
mCodeSize = codeSize;
|
||||
mProgram = &program;
|
||||
mPC = 0;
|
||||
}
|
||||
|
||||
void Runtime::clear()
|
||||
{
|
||||
mContext = nullptr;
|
||||
mCode = nullptr;
|
||||
mCodeSize = 0;
|
||||
mProgram = nullptr;
|
||||
mStack.clear();
|
||||
}
|
||||
|
||||
void Runtime::setPC(int PC)
|
||||
{
|
||||
mPC = PC;
|
||||
}
|
||||
|
||||
void Runtime::push(const Data& data)
|
||||
{
|
||||
mStack.push_back(data);
|
||||
@ -108,12 +74,12 @@ namespace Interpreter
|
||||
mStack.pop_back();
|
||||
}
|
||||
|
||||
Data& Runtime::operator[](int Index)
|
||||
Data& Runtime::operator[](int index)
|
||||
{
|
||||
if (Index < 0 || Index >= static_cast<int>(mStack.size()))
|
||||
if (index < 0 || index >= static_cast<int>(mStack.size()))
|
||||
throw std::runtime_error("stack index out of range");
|
||||
|
||||
return mStack[mStack.size() - Index - 1];
|
||||
return mStack[mStack.size() - index - 1];
|
||||
}
|
||||
|
||||
Context& Runtime::getContext()
|
||||
|
@ -9,21 +9,19 @@
|
||||
namespace Interpreter
|
||||
{
|
||||
class Context;
|
||||
struct Program;
|
||||
|
||||
/// Runtime data and engine interface
|
||||
|
||||
class Runtime
|
||||
{
|
||||
Context* mContext;
|
||||
const Type_Code* mCode;
|
||||
int mCodeSize;
|
||||
int mPC;
|
||||
Context* mContext = nullptr;
|
||||
const Program* mProgram = nullptr;
|
||||
int mPC = 0;
|
||||
std::vector<Data> mStack;
|
||||
|
||||
public:
|
||||
Runtime();
|
||||
|
||||
int getPC() const;
|
||||
int getPC() const { return mPC; }
|
||||
///< return program counter.
|
||||
|
||||
int getIntegerLiteral(int index) const;
|
||||
@ -32,13 +30,13 @@ namespace Interpreter
|
||||
|
||||
std::string_view getStringLiteral(int index) const;
|
||||
|
||||
void configure(const Type_Code* code, int codeSize, Context& context);
|
||||
void configure(const Program& program, Context& context);
|
||||
///< \a context and \a code must exist as least until either configure, clear or
|
||||
/// the destructor is called. \a codeSize is given in 32-bit words.
|
||||
/// the destructor is called.
|
||||
|
||||
void clear();
|
||||
|
||||
void setPC(int PC);
|
||||
void setPC(int value) { mPC = value; }
|
||||
///< set program counter.
|
||||
|
||||
void push(const Data& data);
|
||||
@ -53,7 +51,7 @@ namespace Interpreter
|
||||
void pop();
|
||||
///< pop stack
|
||||
|
||||
Data& operator[](int Index);
|
||||
Data& operator[](int index);
|
||||
///< Access stack member, counted from the top.
|
||||
|
||||
Context& getContext();
|
||||
|
@ -5,15 +5,13 @@
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
typedef unsigned int Type_Code; // 32 bit
|
||||
typedef std::uint32_t Type_Code;
|
||||
|
||||
typedef unsigned int Type_Data; // 32 bit
|
||||
typedef std::int16_t Type_Short;
|
||||
|
||||
typedef short Type_Short; // 16 bit
|
||||
typedef std::int32_t Type_Integer;
|
||||
|
||||
typedef int Type_Integer; // 32 bit
|
||||
|
||||
typedef float Type_Float; // 32 bit
|
||||
typedef float Type_Float;
|
||||
|
||||
union Data
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user