diff options
Diffstat (limited to 'buildtools/codegen/main.cpp')
-rw-r--r-- | buildtools/codegen/main.cpp | 98 |
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; |