Use a custom generic tagged union Either instead of std::variant for efficiency (#1476)

* Implement custom generic tagged union `Either`

This should be more efficient than `std::variant`, while still
keeping runtime safety as it `assert`s when `get`ting values.

* Use `Either` for RPN expressions

* Use `Either` for file stack node data

* Use `Either` for `File` buffer

* Use `Either` for `STRFMT` args

* Use `Either` for RGBLINK symbol values

* Support an equivalent of `std::monostate` for `Either`

* Use `Either` for lexer tokens

* Use `Either` for symbol values

* Use `Either` for lexer mmap/buffer state
This commit is contained in:
Sylvie
2024-08-20 15:19:11 -04:00
committed by GitHub
parent 7d98b9a900
commit 57c3d74b9e
17 changed files with 303 additions and 174 deletions

View File

@@ -7,7 +7,6 @@
%code requires {
#include <stdint.h>
#include <string>
#include <variant>
#include <vector>
#include "asm/lexer.hpp"
@@ -15,6 +14,7 @@
#include "asm/rpn.hpp"
#include "asm/section.hpp"
#include "either.hpp"
#include "linkdefs.hpp"
struct AlignmentSpec {
@@ -30,7 +30,7 @@
struct StrFmtArgList {
std::string format;
std::vector<std::variant<uint32_t, std::string>> args;
std::vector<Either<uint32_t, std::string>> args;
StrFmtArgList() = default;
StrFmtArgList(StrFmtArgList &&) = default;
@@ -81,8 +81,7 @@
std::string_view str, std::string const &old, std::string const &rep
);
static std::string strfmt(
std::string const &spec,
std::vector<std::variant<uint32_t, std::string>> const &args
std::string const &spec, std::vector<Either<uint32_t, std::string>> const &args
);
static void compoundAssignment(std::string const &symName, RPNCommand op, int32_t constValue);
static void failAssert(AssertionType type);
@@ -2642,8 +2641,7 @@ static std::string strrpl(std::string_view str, std::string const &old, std::str
}
static std::string strfmt(
std::string const &spec,
std::vector<std::variant<uint32_t, std::string>> const &args
std::string const &spec, std::vector<Either<uint32_t, std::string>> const &args
) {
std::string str;
size_t argIndex = 0;
@@ -2684,12 +2682,10 @@ static std::string strfmt(
} else if (argIndex >= args.size()) {
// Will warn after formatting is done.
str += '%';
} else if (auto *n = std::get_if<uint32_t>(&args[argIndex]); n) {
fmt.appendNumber(str, *n);
} else if (args[argIndex].holds<uint32_t>()) {
fmt.appendNumber(str, args[argIndex].get<uint32_t>());
} else {
assume(std::holds_alternative<std::string>(args[argIndex]));
auto &s = std::get<std::string>(args[argIndex]);
fmt.appendString(str, s);
fmt.appendString(str, args[argIndex].get<std::string>());
}
argIndex++;