aboutsummaryrefslogtreecommitdiff
path: root/buildtools/codegen/main.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-05-29 21:57:53 -0700
committerrtk0c <[email protected]>2022-05-29 21:57:53 -0700
commit6f29abe5571eb68207986bdadb97b207264ac958 (patch)
treee30d5d36e550e8f08cc832f905c97cbeba3515aa /buildtools/codegen/main.cpp
parent5112858f9a4adcf76240bcddad19179a5c56d4f3 (diff)
Changeset: 49 Convert codegen output to use template specialization
Diffstat (limited to 'buildtools/codegen/main.cpp')
-rw-r--r--buildtools/codegen/main.cpp144
1 files changed, 100 insertions, 44 deletions
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;
}