Replace mwscript program serialization into a vector with simple struct

Mostly to avoid string literal lookup by index with iteration over all preciding
literals and calling strlen. This is very inefficient. In genral this makes code
much more straightforward but also makes it portable since now int and float of
different sizes are properly supported.
This commit is contained in:
elsid 2023-01-10 04:10:18 +01:00
parent 60eede6a1d
commit b88f0d2dbd
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
21 changed files with 93 additions and 162 deletions

View file

@ -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

View file

@ -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.

View file

@ -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());

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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.