aboutsummaryrefslogtreecommitdiff
path: root/buildtools/codegen/main.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-05-29 18:30:03 -0700
committerrtk0c <[email protected]>2022-05-29 18:30:03 -0700
commit5112858f9a4adcf76240bcddad19179a5c56d4f3 (patch)
tree22baae0ae1f74be2c9aee241f061cb91f3c30e88 /buildtools/codegen/main.cpp
parent32f00c086b35c5bc32d800b96253b378b9367580 (diff)
Changeset: 47 Add fromstring codegen for enums
Diffstat (limited to 'buildtools/codegen/main.cpp')
-rw-r--r--buildtools/codegen/main.cpp98
1 files changed, 71 insertions, 27 deletions
diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp
index 334b195..df52b66 100644
--- a/buildtools/codegen/main.cpp
+++ b/buildtools/codegen/main.cpp
@@ -1,5 +1,6 @@
#include "CodegenConfig.hpp"
#include "CodegenDecl.hpp"
+#include "CodegenMacros.hpp"
#include "CodegenInput.inl"
#include "CodegenOutput.inl"
@@ -10,6 +11,8 @@
#include <ScopeGuard.hpp>
#include <Utils.hpp>
+#include <frozen/string.h>
+#include <frozen/unordered_map.h>
#include <robin_hood.h>
#include <stb_c_lexer.h>
#include <cinttypes>
@@ -23,8 +26,11 @@
using namespace std::literals;
namespace fs = std::filesystem;
+// TODO handle namespace
+
struct AppState {
- CodegenOutput mainOutput;
+ CodegenOutput headerOutput;
+ CodegenOutput sourceOutput;
};
enum {
@@ -229,6 +235,7 @@ BSTR_LUT_DECL(StructMetaGenOptions, 0, SMGO_COUNT) {
enum EnumMetaGenOptions {
EMGO_ToString,
+ EMGO_FromString,
EMGO_ExcludeUseHeuristics,
EMGO_COUNT,
};
@@ -236,31 +243,24 @@ enum EnumMetaGenOptions {
BSTR_LUT_DECL(EnumMetaGenOptions, 0, EMGO_COUNT) {
BSTR_LUT_MAP_FOR(EnumMetaGenOptions);
BSTR_LUT_MAP(EMGO_ToString, "ToString");
+ BSTR_LUT_MAP(EMGO_FromString, "FromString");
BSTR_LUT_MAP(EMGO_ExcludeUseHeuristics, "ExcludeHeuristics");
}
-// I give up, hopefully nothing overflows this buffer
-#define APPEND_SPRINTF(out, format, ...) \
- { \
- char buffer[65536]; \
- snprintf(buffer, sizeof(buffer), format, __VA_ARGS__); \
- out += buffer; \
- }
-
std::string GenerateEnumStringArray(CodegenOutput& out, const DeclEnum& decl, bool useHeruistics) {
std::string arrayName;
- APPEND_SPRINTF(arrayName, "gCG_%s_StringTable", decl.name.c_str());
+ APPEND_FMT(arrayName, "gCG_%s_Val2Str", decl.name.c_str());
CodegenOutputThing thing;
- APPEND_SPRINTF(thing.text, "const char* %s[] = {\n", arrayName.c_str());
+ APPEND_FMT_LN(thing.text, "const char* %s[] = {", arrayName.c_str());
for (auto& elm : decl.elements) {
if (useHeruistics && elm.name.ends_with("COUNT")) {
continue;
}
- APPEND_SPRINTF(thing.text, "\"%s\",\n", elm.name.c_str());
+ APPEND_FMT_LN(thing.text, "\"%s\",", elm.name.c_str());
}
- thing.text += "};\n";
+ APPEND_LIT_LN(thing.text, "};");
out.AddOutputThing(std::move(thing));
return arrayName;
@@ -277,9 +277,9 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMet
bool useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics);
if (options.IsSet(EMGO_ToString)) {
- // Generate name lookup table
+ // Generate value -> string lookup table and function
- switch (decl.CalcPattern()) {
+ switch (decl.GetPattern()) {
case EVP_Continuous: {
auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics);
int minVal = decl.elements.front().value;
@@ -293,25 +293,57 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMet
}
CodegenOutputThing lookupFunction;
- APPEND_SPRINTF(lookupFunction.text, "std::string_view Stringify%s(%s value) {\n", decl.name.c_str(), decl.name.c_str());
- APPEND_SPRINTF(lookupFunction.text, " if (value < 0 || value >= %d) return {};\n", maxVal);
- APPEND_SPRINTF(lookupFunction.text, " return %s[value - %d];\n", arrayName.c_str(), minVal);
- lookupFunction.text += "}\n";
+ auto& o = lookupFunction.text;
+ APPEND_FMT_LN(o, "std::string_view EnumToString_%s(%s value) {", decl.name.c_str(), decl.name.c_str());
+ APPEND_FMT_LN(o, " if (value < 0 || value >= %d) return {};", maxVal);
+ APPEND_FMT_LN(o, " return %s[value - %d];", arrayName.c_str(), minVal);
+ APPEND_LIT_LN(o, "}");
out.AddOutputThing(std::move(lookupFunction));
} break;
case EVP_Bits: {
auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics);
+ // TODO
} break;
case EVP_Random: {
auto mapName = GenerateEnumStringMap(out, decl, useExcludeHeuristics);
+ // TODO
} break;
case EVP_COUNT: break;
}
}
+
+ if (options.IsSet(EMGO_FromString)) {
+ // Generate string -> value lookup table
+ char mapName[1024];
+ snprintf(mapName, sizeof(mapName), "gCG_%s_Str2Val", decl.name.c_str());
+
+ CodegenOutputThing lookupTable;
+ auto& o1 = lookupTable.text;
+ APPEND_FMT_LN(o1, "constinit frozen::unordered_map<frozen::string, %s, %" PRId64 "> %s = {", decl.name.c_str(), decl.elements.size(), mapName);
+ for (auto& elm : decl.elements) {
+ APPEND_FMT_LN(o1, "{\"%s\", %s::%s},", elm.name.c_str(), decl.name.c_str(), elm.name.c_str());
+ }
+ APPEND_LIT_LN(o1, "};");
+
+ // Generate lookup function
+ CodegenOutputThing lookupFunction;
+ auto& o2 = lookupFunction.text;
+ APPEND_FMT_LN(o2, "std::optional<%s> EnumFromString_%s(std::string_view value) {", decl.name.c_str(), decl.name.c_str());
+ APPEND_FMT_LN(o2, " auto iter = %s.find(value);", mapName);
+ APPEND_FMT_LN(o2, " if (iter != %s.end()) {", mapName);
+ APPEND_LIT_LN(o2, " return iter->second;");
+ APPEND_LIT_LN(o2, " } else {");
+ APPEND_LIT_LN(o2, " return {};");
+ APPEND_LIT_LN(o2, " }");
+ APPEND_LIT_LN(o2, "}");
+
+ out.AddOutputThing(std::move(lookupTable));
+ out.AddOutputThing(std::move(lookupFunction));
+ }
}
void HandleInputFile(AppState& state, std::string_view source) {
@@ -499,7 +531,7 @@ void HandleInputFile(AppState& state, std::string_view source) {
printf("[WARNING] unbalanced brace at end of file.");
}
- state.mainOutput.MergeContents(std::move(fileOutput));
+ state.sourceOutput.MergeContents(std::move(fileOutput));
}
std::string ReadFileAtOnce(const fs::path& path) {
@@ -577,17 +609,29 @@ int main(int argc, char* argv[]) {
AppState state;
+ state.sourceOutput.AddOutputThing(CodegenOutputThing{
+ .text = &R"""(
+// This file is generated. Any changes will be overidden when building.
+
+#include <frozen/string.h>
+#include <frozen/unordered_map.h>
+#include <optional>
+#include <string_view>
+using namespace std::literals;
+ )"""[1],
+ });
+
// If no cli is provided (argv[0] conventionally but not mandatorily the cli), this will do thing
// Otherwise, start with the 2nd element in the array, which is the 1st actual argument
if (argc < 2) {
// NOTE: keep in sync with various enum options and parser code
printf(&R"""(
- USAGE: codegen.exe <output path> [<opcode>:<input path>]...
- where <output path>: the _file_ to write generated contents to
- <opcode> is one of:
- "single" process this <input path> file only
- "rec" starting at the given directory <input path>, recursively process all .h .c .hpp .cpp files
- )"""[1]);
+USAGE: codegen.exe <output path> [<opcode>:<input path>]...
+where <output path>: the _file_ to write generated contents to
+ <opcode> is one of:
+ "single" process this <input path> file only
+ "rec" starting at the given directory <input path>, recursively process all .h .c .hpp .cpp files
+)"""[1]);
return -1;
}
@@ -615,7 +659,7 @@ int main(int argc, char* argv[]) {
return -1;
}
DEFER { fclose(outputFile); };
- state.mainOutput.Write(outputFile);
+ state.sourceOutput.Write(outputFile);
}
return 0;