diff options
author | rtk0c <[email protected]> | 2022-05-29 21:57:53 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-05-29 21:57:53 -0700 |
commit | 6f29abe5571eb68207986bdadb97b207264ac958 (patch) | |
tree | e30d5d36e550e8f08cc832f905c97cbeba3515aa /buildtools/codegen | |
parent | 5112858f9a4adcf76240bcddad19179a5c56d4f3 (diff) |
Changeset: 49 Convert codegen output to use template specialization
Diffstat (limited to 'buildtools/codegen')
-rw-r--r-- | buildtools/codegen/CodegenOutput.inl | 3 | ||||
-rw-r--r-- | buildtools/codegen/main.cpp | 144 | ||||
-rw-r--r-- | buildtools/codegen/tests/examples/TestEnum.hpp.txt (renamed from buildtools/codegen/tests/examples/TestEnum.hpp) | 2 |
3 files changed, 101 insertions, 48 deletions
diff --git a/buildtools/codegen/CodegenOutput.inl b/buildtools/codegen/CodegenOutput.inl index d1f2e50..edd9abc 100644 --- a/buildtools/codegen/CodegenOutput.inl +++ b/buildtools/codegen/CodegenOutput.inl @@ -38,9 +38,8 @@ public: std::move(other.mOutFunctions.begin(), other.mOutFunctions.end(), std::back_inserter(this->mOutFunctions)); } - void Write(FILE* file) { + void Write(FILE* file) const { for (auto& thing : mOutThings) { - WRITE_LIT(file, "// Output thing\n"); fwrite(thing.text.c_str(), sizeof(char), thing.text.size(), file); WRITE_LIT(file, "\n"); } diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp index df52b66..e759c31 100644 --- a/buildtools/codegen/main.cpp +++ b/buildtools/codegen/main.cpp @@ -273,7 +273,7 @@ std::string GenerateEnumStringMap(CodegenOutput& out, const DeclEnum& decl, bool return mapName; } -void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMetaGenOptions> options) { +void GenerateForEnum(CodegenOutput& headerOut, CodegenOutput& sourceOut, const DeclEnum& decl, EnumFlags<EnumMetaGenOptions> options) { bool useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics); if (options.IsSet(EMGO_ToString)) { @@ -281,7 +281,7 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMet switch (decl.GetPattern()) { case EVP_Continuous: { - auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics); + auto arrayName = GenerateEnumStringArray(sourceOut, decl, useExcludeHeuristics); int minVal = decl.elements.front().value; int maxVal = decl.elements.back().value; if (useExcludeHeuristics && @@ -292,23 +292,30 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMet maxVal = decl.elements[decl.elements.size() - 2].value; } - CodegenOutputThing lookupFunction; - 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, "}"); + CodegenOutputThing lookupFunctionDecl; + auto& o1 = lookupFunctionDecl.text; + APPEND_LIT_LN(o1, "template <>"); + APPEND_FMT_LN(o1, "std::string_view Metadata::EnumToString<%s>(%s);", decl.name.c_str(), decl.name.c_str()); - out.AddOutputThing(std::move(lookupFunction)); + CodegenOutputThing lookupFunctionDef; + auto& o2 = lookupFunctionDef.text; + APPEND_LIT_LN(o2, "template <>"); + APPEND_FMT_LN(o2, "std::string_view Metadata::EnumToString<%s>(%s value) {", decl.name.c_str(), decl.name.c_str()); + APPEND_FMT_LN(o2, " if (value < 0 || value >= %d) return {};", maxVal); + APPEND_FMT_LN(o2, " return %s[value - %d];", arrayName.c_str(), minVal); + APPEND_LIT_LN(o2, "}"); + + headerOut.AddOutputThing(std::move(lookupFunctionDecl)); + sourceOut.AddOutputThing(std::move(lookupFunctionDef)); } break; case EVP_Bits: { - auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics); + auto arrayName = GenerateEnumStringArray(sourceOut, decl, useExcludeHeuristics); // TODO } break; case EVP_Random: { - auto mapName = GenerateEnumStringMap(out, decl, useExcludeHeuristics); + auto mapName = GenerateEnumStringMap(sourceOut, decl, useExcludeHeuristics); // TODO } break; @@ -330,19 +337,26 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags<EnumMet 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, "}"); + CodegenOutputThing lookupFunctionDecl; + auto& o2 = lookupFunctionDecl.text; + APPEND_LIT_LN(o2, "template <>"); + APPEND_FMT_LN(o2, "std::optional<%s> Metadata::EnumFromString<%s>(std::string_view);", decl.name.c_str(), decl.name.c_str()); + + CodegenOutputThing lookupFunctionDef; + auto& o3 = lookupFunctionDef.text; + APPEND_LIT_LN(o3, "template <>"); + APPEND_FMT_LN(o3, "std::optional<%s> Metadata::EnumFromString<%s>(std::string_view value) {", decl.name.c_str(), decl.name.c_str()); + APPEND_FMT_LN(o3, " auto iter = %s.find(value);", mapName); + APPEND_FMT_LN(o3, " if (iter != %s.end()) {", mapName); + APPEND_LIT_LN(o3, " return iter->second;"); + APPEND_LIT_LN(o3, " } else {"); + APPEND_LIT_LN(o3, " return {};"); + APPEND_LIT_LN(o3, " }"); + APPEND_LIT_LN(o3, "}"); - out.AddOutputThing(std::move(lookupTable)); - out.AddOutputThing(std::move(lookupFunction)); + sourceOut.AddOutputThing(std::move(lookupTable)); + headerOut.AddOutputThing(std::move(lookupFunctionDecl)); + sourceOut.AddOutputThing(std::move(lookupFunctionDef)); } } @@ -358,8 +372,9 @@ void HandleInputFile(AppState& state, std::string_view source) { printf("END tokens\n"); #endif - CodegenInput fileInput; - CodegenOutput fileOutput; + CodegenInput cgInput; + auto& cgHeaderOutput = state.headerOutput; + auto& cgSourceOutput = state.sourceOutput; int bracePairDepth = 0; while (idx < tokens.size()) { @@ -444,7 +459,7 @@ void HandleInputFile(AppState& state, std::string_view source) { ++idx; } - fileInput.AddEnum(std::move(enumDecl)); + cgInput.AddEnum(std::move(enumDecl)); goto endIdenCase; } @@ -480,7 +495,7 @@ void HandleInputFile(AppState& state, std::string_view source) { } auto& enumName = argList[0][0]->text; - auto enumDecl = fileInput.FindEnumByName(enumName); + auto enumDecl = cgInput.FindEnumByName(enumName); if (!enumDecl) { printf("[ERROR] BRUSSEL_ENUM: referring to non-existent enum '%s'\n", enumName.c_str()); break; @@ -497,7 +512,7 @@ void HandleInputFile(AppState& state, std::string_view source) { } } - GenerateForEnum(fileOutput, *enumDecl, options); + GenerateForEnum(cgHeaderOutput, cgSourceOutput, *enumDecl, options); idx = newIdx; incrementTokenIdx = false; @@ -530,8 +545,6 @@ void HandleInputFile(AppState& state, std::string_view source) { if (bracePairDepth != 0) { printf("[WARNING] unbalanced brace at end of file."); } - - state.sourceOutput.MergeContents(std::move(fileOutput)); } std::string ReadFileAtOnce(const fs::path& path) { @@ -596,6 +609,23 @@ InputOpcode ParseInputOpcode(std::string_view text) { return IOP_COUNT; } +bool WriteOutputFile(const CodegenOutput& output, const char* dirPath, const char* fileName) { + char path[2048]; + snprintf(path, sizeof(path), "%s/%s", dirPath, fileName); + + auto outputFile = Utils::OpenCstdioFile(path, Utils::WriteTruncate); + if (!outputFile) { + printf("[ERROR] unable to open output file %s", path); + return false; + } + DEFER { fclose(outputFile); }; + + DEBUG_PRINTF("Writing output %s", path); + output.Write(outputFile); + + return true; +} + int main(int argc, char* argv[]) { STR_LUT_INIT(ClexNames); BSTR_LUT_INIT(CppKeyword); @@ -609,14 +639,22 @@ int main(int argc, char* argv[]) { AppState state; + state.headerOutput.AddOutputThing(CodegenOutputThing{ + .text = &R"""( +// This file is generated. Any changes will be overidden when building. +#pragma once + +#include <MetadataBase.hpp> +)"""[1], + }); + state.sourceOutput.AddOutputThing(CodegenOutputThing{ .text = &R"""( // This file is generated. Any changes will be overidden when building. +#include "MetadataImpl.hpp" #include <frozen/string.h> #include <frozen/unordered_map.h> -#include <optional> -#include <string_view> using namespace std::literals; )"""[1], }); @@ -627,7 +665,7 @@ using namespace std::literals; // 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 +where <output path>: the directory to write generated contents to. This will NOT automatically create the directory. <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 @@ -635,8 +673,33 @@ where <output path>: the _file_ to write generated contents to return -1; } - const char* outputFilePath = argv[1]; - DEBUG_PRINTF("Outputting to file %s.\n", outputFilePath); + const char* outputDir = argv[1]; + DEBUG_PRINTF("Outputting to directory %s.\n", outputDirPath); + + { + char path[2048]; + snprintf(path, sizeof(path), "%s/%s", outputDir, "Metadata.hpp"); + + auto fileContent = R"""( +// This file is generated. Any changes will be overidden when building. +// This file is an umbrella header for all generated metadata. End users simply include this file to get access to everything. +#pragma once + +#include <MetadataBase.hpp> + +#include <generated/MetadataImpl.hpp> +)"""sv.substr(1); // Get rid of the \n at the beginning + + auto file = Utils::OpenCstdioFile(path, Utils::WriteTruncate); + if (!file) { + printf("[ERROR] unable to open output file %s", path); + return -1; + } + DEFER { fclose(file); }; + + DEBUG_PRINTF("Writing output file %s", path); + fwrite(fileContent.data(), sizeof(decltype(fileContent)::value_type), fileContent.size(), file); + } for (int i = 2; i < argc; ++i) { std::string_view arg(argv[i]); @@ -652,15 +715,8 @@ where <output path>: the _file_ to write generated contents to } } - { - auto outputFile = Utils::OpenCstdioFile(outputFilePath, Utils::WriteTruncate); - if (!outputFile) { - printf("[ERROR] unable to open output file %s", outputFilePath); - return -1; - } - DEFER { fclose(outputFile); }; - state.sourceOutput.Write(outputFile); - } + WriteOutputFile(state.headerOutput, outputDir, "MetadataImpl.hpp"); + WriteOutputFile(state.sourceOutput, outputDir, "MetadataImpl.cpp"); return 0; } diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp b/buildtools/codegen/tests/examples/TestEnum.hpp.txt index 6b4ab33..e596c5e 100644 --- a/buildtools/codegen/tests/examples/TestEnum.hpp +++ b/buildtools/codegen/tests/examples/TestEnum.hpp.txt @@ -1,5 +1,3 @@ -#include "MacrosCodegen.hpp" - enum MyEnum { EnumElement1, EnumElement2, |