From 6f29abe5571eb68207986bdadb97b207264ac958 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sun, 29 May 2022 21:57:53 -0700 Subject: Changeset: 49 Convert codegen output to use template specialization --- buildtools/codegen/CodegenOutput.inl | 3 +- buildtools/codegen/main.cpp | 148 ++++++++++++++------- buildtools/codegen/tests/examples/TestEnum.hpp | 23 ---- buildtools/codegen/tests/examples/TestEnum.hpp.txt | 21 +++ 4 files changed, 124 insertions(+), 71 deletions(-) delete mode 100644 buildtools/codegen/tests/examples/TestEnum.hpp create mode 100644 buildtools/codegen/tests/examples/TestEnum.hpp.txt (limited to 'buildtools/codegen') 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 options) { +void GenerateForEnum(CodegenOutput& headerOut, CodegenOutput& sourceOut, const DeclEnum& decl, EnumFlags options) { bool useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics); if (options.IsSet(EMGO_ToString)) { @@ -281,7 +281,7 @@ void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags= %d) return {};", maxVal); - APPEND_FMT_LN(o, " return %s[value - %d];", arrayName.c_str(), minVal); - APPEND_LIT_LN(o, "}"); - - out.AddOutputThing(std::move(lookupFunction)); + 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()); + + 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 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)); + 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, "}"); + + 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 +)"""[1], + }); + state.sourceOutput.AddOutputThing(CodegenOutputThing{ .text = &R"""( // This file is generated. Any changes will be overidden when building. +#include "MetadataImpl.hpp" #include #include -#include -#include 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 [:]... -where : the _file_ to write generated contents to +where : the directory to write generated contents to. This will NOT automatically create the directory. is one of: "single" process this file only "rec" starting at the given directory , recursively process all .h .c .hpp .cpp files @@ -635,8 +673,33 @@ where : 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 + +#include +)"""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 : 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 deleted file mode 100644 index 6b4ab33..0000000 --- a/buildtools/codegen/tests/examples/TestEnum.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "MacrosCodegen.hpp" - -enum MyEnum { - EnumElement1, - EnumElement2, - EnumElement3, -}; -BRUSSEL_ENUM(MyEnum, ToString FromString); - -enum CountedEnumAll { - CEA_Foo, - CEA_Bar, - CEA_COUNT, -}; -BRUSSEL_ENUM(CountedEnumAll, ToString FromString); - -enum CountedEnum { - CE_Foo, - CE_Bar, - CE_FooBar, - CE_COUNT, -}; -BRUSSEL_ENUM(CountedEnum, ToString FromString ExcludeHeuristics); diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp.txt b/buildtools/codegen/tests/examples/TestEnum.hpp.txt new file mode 100644 index 0000000..e596c5e --- /dev/null +++ b/buildtools/codegen/tests/examples/TestEnum.hpp.txt @@ -0,0 +1,21 @@ +enum MyEnum { + EnumElement1, + EnumElement2, + EnumElement3, +}; +BRUSSEL_ENUM(MyEnum, ToString FromString); + +enum CountedEnumAll { + CEA_Foo, + CEA_Bar, + CEA_COUNT, +}; +BRUSSEL_ENUM(CountedEnumAll, ToString FromString); + +enum CountedEnum { + CE_Foo, + CE_Bar, + CE_FooBar, + CE_COUNT, +}; +BRUSSEL_ENUM(CountedEnum, ToString FromString ExcludeHeuristics); -- cgit v1.2.3-70-g09d2