From 1a6f1ea3b76c3ed4cad5aba5502af390ce50a2c0 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sat, 28 May 2022 20:52:42 -0700 Subject: Changeset: 42 Change codegen input parsing to lookahead based; lookup table infra; input/output decl infra --- buildtools/codegen/CodegenDecl.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 buildtools/codegen/CodegenDecl.hpp (limited to 'buildtools/codegen/CodegenDecl.hpp') diff --git a/buildtools/codegen/CodegenDecl.hpp b/buildtools/codegen/CodegenDecl.hpp new file mode 100644 index 0000000..3414d80 --- /dev/null +++ b/buildtools/codegen/CodegenDecl.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +// Structs or classes +struct DeclStruct { + std::string name; +}; + +enum EnumUnderlyingType { + EUT_Int8, + EUT_Int16, + EUT_Int32, + EUT_Int64, + EUT_Uint8, + EUT_Uint16, + EUT_Uint32, + EUT_Uint64, + EUT_COUNT, +}; + +struct DeclEnumElement { + std::string name; + uint64_t value; +}; + +struct DeclEnum { + std::string name; + std::vector elements; + EnumUnderlyingType underlyingType; +}; -- cgit v1.2.3-70-g09d2 From 66b63ae887f553e1cac813546a6b827a9c85d80c Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sun, 29 May 2022 16:14:26 -0700 Subject: Changeset: 43 Add tostring code gen for enums --- buildtools/codegen/CodegenDecl.cpp | 48 ++++++ buildtools/codegen/CodegenDecl.hpp | 33 ++++ buildtools/codegen/CodegenInput.inl | 4 +- buildtools/codegen/CodegenOutput.inl | 18 ++- buildtools/codegen/main.cpp | 212 +++++++++++++++++++++---- buildtools/codegen/tests/examples/TestEnum.hpp | 17 +- source-common/Enum.hpp | 2 +- 7 files changed, 295 insertions(+), 39 deletions(-) create mode 100644 buildtools/codegen/CodegenDecl.cpp (limited to 'buildtools/codegen/CodegenDecl.hpp') diff --git a/buildtools/codegen/CodegenDecl.cpp b/buildtools/codegen/CodegenDecl.cpp new file mode 100644 index 0000000..ac6bb01 --- /dev/null +++ b/buildtools/codegen/CodegenDecl.cpp @@ -0,0 +1,48 @@ +#include "CodegenDecl.hpp" + +#include + +static EnumValuePattern NextPattern(EnumValuePattern val) { + return (EnumValuePattern)(val + 1); +} + +EnumValuePattern DeclEnum::CalcPattern() const { + if (elements.empty()) return EVP_Continuous; + + auto pattern = EVP_Continuous; +restart: + auto lastVal = elements[0].value; + for (size_t i = 1; i < elements.size(); ++i) { + auto currVal = elements[i].value; + switch (pattern) { + case EVP_Continuous: { + bool satisfy = lastVal + 1 == currVal; + if (!satisfy) { + pattern = NextPattern(pattern); + goto restart; + } + } break; + + case EVP_Bits: { + bool satisfy = (lastVal << 1) == currVal; + if (!satisfy) { + pattern = NextPattern(pattern); + goto restart; + } + } break; + + // A random pattern can match anything + case EVP_Random: + case EVP_COUNT: break; + } + lastVal = currVal; + } + + return pattern; +} + +void DeclEnum::CalcPatternIfNecessary() { + if (pattern == EVP_COUNT) { + CalcPattern(); + } +} diff --git a/buildtools/codegen/CodegenDecl.hpp b/buildtools/codegen/CodegenDecl.hpp index 3414d80..c2d8dbb 100644 --- a/buildtools/codegen/CodegenDecl.hpp +++ b/buildtools/codegen/CodegenDecl.hpp @@ -20,8 +20,22 @@ enum EnumUnderlyingType { EUT_COUNT, }; +enum EnumValuePattern { + // The numbers cover n..m with no gaps + EVP_Continuous, + // The numbers cover for i in n..m, 1 << i + // e.g. [0] = 1 << 0, + // [1] = 1 << 1. + // [2] = 1 << 2. etc. + EVP_Bits, + // The numbesr don't have a particular pattern + EVP_Random, + EVP_COUNT, +}; + struct DeclEnumElement { std::string name; + // TODO support int64_t, etc. enum underlying types uint64_t value; }; @@ -29,4 +43,23 @@ struct DeclEnum { std::string name; std::vector elements; EnumUnderlyingType underlyingType; + // Start with invalid value, calculate on demand + EnumValuePattern pattern = EVP_COUNT; + + EnumValuePattern CalcPattern() const; + void CalcPatternIfNecessary(); +}; + +struct DeclFunctionArgument { + std::string type; + std::string name; +}; + +struct DeclFunction { + // Things like extern, static, etc. that gets written before the function return type + std::string prefix; + std::string name; + std::string returnType; + std::vector arguments; + std::string body; }; diff --git a/buildtools/codegen/CodegenInput.inl b/buildtools/codegen/CodegenInput.inl index 9fae43c..80a39d0 100644 --- a/buildtools/codegen/CodegenInput.inl +++ b/buildtools/codegen/CodegenInput.inl @@ -13,7 +13,7 @@ class CodegenInput { private: std::vector mEnums; - robin_hood::unordered_map mDeclByName; + robin_hood::unordered_map mDeclByName; public: void AddEnum(DeclEnum decl) { @@ -24,7 +24,7 @@ public: } #endif - mDeclByName.try_emplace(decl.name, mEnums.size()); + mDeclByName.try_emplace(std::string(decl.name), mEnums.size()); mEnums.push_back(std::move(decl)); } diff --git a/buildtools/codegen/CodegenOutput.inl b/buildtools/codegen/CodegenOutput.inl index 6d59301..752682c 100644 --- a/buildtools/codegen/CodegenOutput.inl +++ b/buildtools/codegen/CodegenOutput.inl @@ -15,6 +15,14 @@ struct CodegenOutputThing { class CodegenOutput { private: std::vector mOutThings; + std::vector mOutStructs; + std::vector mOutEnums; + std::vector mOutFunctions; + +public: + std::string optionOutPrefix; + // Whether to add prefixes mOutPrefix to all global names or not + bool optionAutoAddPrefix : 1 = false; public: void AddOutputThing(CodegenOutputThing thing) { @@ -22,10 +30,16 @@ public: } void MergeContents(CodegenOutput other) { - std::move(other.mOutThings.begin(), other.mOutThings.end(), this->mOutThings.begin()); + std::move(other.mOutThings.begin(), other.mOutThings.end(), std::back_inserter(this->mOutThings)); } void Write(FILE* file) { - // TODO +#define WRITE_LITERAL(str) fwrite(str, sizeof(char), sizeof(str) - 1, file) + for (auto& thing : mOutThings) { + WRITE_LITERAL("// Output thing\n"); + fwrite(thing.text.c_str(), sizeof(char), thing.text.size(), file); + WRITE_LITERAL("\n"); + } +#undef WRITE_LITERAL } }; diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp index 74acd1c..ed8cbbe 100644 --- a/buildtools/codegen/main.cpp +++ b/buildtools/codegen/main.cpp @@ -76,6 +76,7 @@ BSTR_LUT_DECL(CppKeyword, 0, CKw_COUNT) { BSTR_LUT_MAP_FOR(CppKeyword); BSTR_LUT_MAP(CKw_Struct, "struct"); BSTR_LUT_MAP(CKw_Class, "class"); + BSTR_LUT_MAP(CKw_Enum, "enum"); } enum CodegenDirective { @@ -161,6 +162,10 @@ PeekDirectiveArgumentList(const std::vector& tokens, size_t curre } } + if (!currentArg.empty()) { + result.push_back(std::move(currentArg)); + } + return { result, i }; } @@ -223,21 +228,95 @@ BSTR_LUT_DECL(StructMetaGenOptions, 0, SMGO_COUNT) { } enum EnumMetaGenOptions { - EMGO_Basic, + EMGO_ToString, + EMGO_ExcludeUseHeuristics, EMGO_COUNT, }; BSTR_LUT_DECL(EnumMetaGenOptions, 0, EMGO_COUNT) { BSTR_LUT_MAP_FOR(EnumMetaGenOptions); - BSTR_LUT_MAP(EMGO_Basic, "GenBasic"); + BSTR_LUT_MAP(EMGO_ToString, "ToString"); + 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()); + + CodegenOutputThing thing; + APPEND_SPRINTF(thing.text, "const char* %s[] = {\n", 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()); + } + thing.text += "};\n"; + out.AddOutputThing(std::move(thing)); + + return arrayName; +} + +std::string GenerateEnumStringMap(CodegenOutput& out, const DeclEnum& decl, bool useHeruistics) { + std::string mapName; + // TODO + + return mapName; } void GenerateForEnum(CodegenOutput& out, const DeclEnum& decl, EnumFlags options) { + bool useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics); + + if (options.IsSet(EMGO_ToString)) { + // Generate name lookup table + + switch (decl.CalcPattern()) { + case EVP_Continuous: { + auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics); + int minVal = decl.elements.front().value; + int maxVal = decl.elements.back().value; + if (useExcludeHeuristics && + decl.elements.back().name.ends_with("COUNT") && + decl.elements.size() >= 2) + { + // Skip the last *_COUNT element if instructed to use heuristics + maxVal = decl.elements[decl.elements.size() - 2].value; + } + + 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"; + + out.AddOutputThing(std::move(lookupFunction)); + } break; + + case EVP_Bits: { + auto arrayName = GenerateEnumStringArray(out, decl, useExcludeHeuristics); + } break; + + case EVP_Random: { + auto mapName = GenerateEnumStringMap(out, decl, useExcludeHeuristics); + } break; + + case EVP_COUNT: break; + } + } } void HandleInputFile(AppState& state, std::string_view source) { auto tokens = RecordTokens(source); - size_t tokenIdx = 0; + size_t idx = 0; #if CODEGEN_DEBUG_PRINT printf("BEGIN tokens\n"); @@ -247,12 +326,12 @@ void HandleInputFile(AppState& state, std::string_view source) { printf("END tokens\n"); #endif - CodegenInput input; - CodegenOutput output; + CodegenInput fileInput; + CodegenOutput fileOutput; int bracePairDepth = 0; - while (tokenIdx < tokens.size()) { - auto& token = tokens[tokenIdx]; + while (idx < tokens.size()) { + auto& token = tokens[idx]; bool incrementTokenIdx = true; @@ -265,25 +344,77 @@ void HandleInputFile(AppState& state, std::string_view source) { if (iter != map.end()) { keyword = iter->second; } else { - break; + keyword = CKw_COUNT; // Skip keyword section } } switch (keyword) { case CKw_Struct: case CKw_Class: { - auto& idenTok = tokens[tokenIdx + 1]; // TODO handle end of list + auto& idenTok = tokens[idx + 1]; // TODO handle end of list DEBUG_PRINTF("[DEBUG] found struct named %s\n", idenTok.text.c_str()); - } break; + goto endIdenCase; + } case CKw_Enum: { - StbLexerToken* idenTok = &token + 1; // TODO handle end of list - if (idenTok->text == "class") { - idenTok += 1; - DEBUG_PRINTF("[DEBUG] found enum class named %s\n", idenTok->text.c_str()); + // Consume the "enum" keyword + ++idx; + incrementTokenIdx = false; + + DeclEnum enumDecl; + enumDecl.underlyingType = EUT_Int32; // TODO + + if (tokens[idx].text == "class") { + // Consume the "class" keyword + ++idx; + DEBUG_PRINTF("[DEBUG] found enum class named %s\n", tokens[idx].text.c_str()); } else { - DEBUG_PRINTF("[DEBUG] found enum named %s\n", idenTok->text.c_str()); + DEBUG_PRINTF("[DEBUG] found enum named %s\n", tokens[idx].text.c_str()); } - } break; + + // Consume the enum name identifier + enumDecl.name = tokens[idx].text; + ++idx; + + int enumClosingBraceCount = 0; + int enumBraceDepth = 0; + while (enumClosingBraceCount == 0 && idx < tokens.size()) { + auto& token = tokens[idx]; + switch (token.type) { + case CLEX_id: { + auto& vec = enumDecl.elements; + // Set to the previous enum element's value + 1, or starting from 0 if this is the first + // Also overridden in the CLEX_intlit branch + auto value = vec.empty() ? 0 : vec.back().value + 1; + vec.push_back(DeclEnumElement{ + .name = token.text, + .value = value, + }); + } break; + + case CLEX_intlit: { + + } break; + + case CLEX_ext_single_char: { + switch (token.text[0]) { + case '{': { + ++enumBraceDepth; + } break; + + case '}': { + --enumBraceDepth; + ++enumClosingBraceCount; + } break; + } + } break; + } + + ++idx; + } + + fileInput.AddEnum(std::move(enumDecl)); + goto endIdenCase; + } case CKw_COUNT: break; } @@ -295,24 +426,33 @@ void HandleInputFile(AppState& state, std::string_view source) { if (iter != map.end()) { directive = iter->second; } else { - break; + directive = CD_COUNT; // Skip directive section } } switch (directive) { case CD_ClassInfo: { // TODO - } break; + goto endIdenCase; + } case CD_EnumInfo: { + // Consume the directive + ++idx; + incrementTokenIdx = false; + auto& optionsStrMap = BSTR_LUT_S2V(EnumMetaGenOptions); - auto [argList, newIdx] = PeekDirectiveArgumentList(tokens, tokenIdx); + auto [argList, newIdx] = PeekDirectiveArgumentList(tokens, idx); if (argList.size() < 1) { printf("[ERROR] invalid syntax for BRUSSEL_ENUM\n"); - break; + break; // TODO handle this error case gracefully (advance to semicolon?) } auto& enumName = argList[0][0]->text; - auto enumDecl = input.FindEnumByName(enumName); + auto enumDecl = fileInput.FindEnumByName(enumName); + if (!enumDecl) { + printf("[ERROR] BRUSSEL_ENUM: referring to non-existent enum '%s'\n", enumName.c_str()); + break; + } auto& directiveOptions = argList[1]; EnumFlags options; @@ -321,19 +461,23 @@ void HandleInputFile(AppState& state, std::string_view source) { if (iter != optionsStrMap.end()) { options |= iter->second; } else { - printf("[ERROR] invalid option '%s' for BRUSSEL_ENUM", optionTok->text.c_str()); + printf("[ERROR] BRUSSEL_ENUM: invalid option '%s'\n", optionTok->text.c_str()); } } - GenerateForEnum(output, *enumDecl, options); + GenerateForEnum(fileOutput, *enumDecl, options); - tokenIdx = newIdx; + idx = newIdx; incrementTokenIdx = false; - } break; + goto endIdenCase; + } case CD_COUNT: break; } - } break; + + endIdenCase: + break; + } case '{': { bracePairDepth++; @@ -347,13 +491,15 @@ void HandleInputFile(AppState& state, std::string_view source) { } if (incrementTokenIdx) { - ++tokenIdx; + ++idx; } } if (bracePairDepth != 0) { printf("[WARNING] unbalanced brace at end of file."); } + + state.mainOutput.MergeContents(std::move(fileOutput)); } std::string ReadFileAtOnce(const fs::path& path) { @@ -436,12 +582,12 @@ int main(int argc, char* argv[]) { if (argc < 2) { // NOTE: keep in sync with various enum options and parser code printf(&R"""( -USAGE: codegen.exe [:]... -where : the _file_ to write generated contents to - is one of: - "single" process this file only - "rec" starting at the given directory , recursively process all .h .c .hpp .cpp files -)"""[1]); + USAGE: codegen.exe [:]... + where : the _file_ to write generated contents to + is one of: + "single" process this file only + "rec" starting at the given directory , recursively process all .h .c .hpp .cpp files + )"""[1]); return -1; } diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp b/buildtools/codegen/tests/examples/TestEnum.hpp index 2a93c01..c498cd9 100644 --- a/buildtools/codegen/tests/examples/TestEnum.hpp +++ b/buildtools/codegen/tests/examples/TestEnum.hpp @@ -5,4 +5,19 @@ enum MyEnum { EnumElement2, EnumElement3, }; -BRUSSEL_ENUM(MyEnum, GenBasic); +BRUSSEL_ENUM(MyEnum, ToString); + +enum CountedEnumAll { + CEA_Foo, + CEA_Bar, + CEA_COUNT, +}; +BRUSSEL_ENUM(CountedEnumAll, ToString); + +enum CountedEnum { + CE_Foo, + CE_Bar, + CE_FooBar, + CE_COUNT, +}; +BRUSSEL_ENUM(CountedEnum, ToString ExcludeHeuristics); diff --git a/source-common/Enum.hpp b/source-common/Enum.hpp index e8750f2..8ad75ba 100644 --- a/source-common/Enum.hpp +++ b/source-common/Enum.hpp @@ -18,7 +18,7 @@ public: } EnumFlags(TEnum e) - : mValue{ 1 << static_cast(e) } { + : mValue{ static_cast(1) << static_cast(e) } { } bool IsSet(EnumFlags mask) const { -- cgit v1.2.3-70-g09d2 From 5112858f9a4adcf76240bcddad19179a5c56d4f3 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sun, 29 May 2022 18:30:03 -0700 Subject: Changeset: 47 Add fromstring codegen for enums --- buildtools/codegen/CodegenDecl.cpp | 5 +- buildtools/codegen/CodegenDecl.hpp | 4 +- buildtools/codegen/CodegenMacros.hpp | 30 ++++++++ buildtools/codegen/CodegenOutput.inl | 25 +++++-- buildtools/codegen/main.cpp | 98 +++++++++++++++++++------- buildtools/codegen/tests/examples/TestEnum.hpp | 6 +- 6 files changed, 130 insertions(+), 38 deletions(-) create mode 100644 buildtools/codegen/CodegenMacros.hpp (limited to 'buildtools/codegen/CodegenDecl.hpp') diff --git a/buildtools/codegen/CodegenDecl.cpp b/buildtools/codegen/CodegenDecl.cpp index ac6bb01..7cf21ce 100644 --- a/buildtools/codegen/CodegenDecl.cpp +++ b/buildtools/codegen/CodegenDecl.cpp @@ -41,8 +41,9 @@ restart: return pattern; } -void DeclEnum::CalcPatternIfNecessary() { +EnumValuePattern DeclEnum::GetPattern() const { if (pattern == EVP_COUNT) { - CalcPattern(); + pattern = CalcPattern(); } + return pattern; } diff --git a/buildtools/codegen/CodegenDecl.hpp b/buildtools/codegen/CodegenDecl.hpp index c2d8dbb..b7c1ee4 100644 --- a/buildtools/codegen/CodegenDecl.hpp +++ b/buildtools/codegen/CodegenDecl.hpp @@ -44,10 +44,10 @@ struct DeclEnum { std::vector elements; EnumUnderlyingType underlyingType; // Start with invalid value, calculate on demand - EnumValuePattern pattern = EVP_COUNT; + mutable EnumValuePattern pattern = EVP_COUNT; EnumValuePattern CalcPattern() const; - void CalcPatternIfNecessary(); + EnumValuePattern GetPattern() const; }; struct DeclFunctionArgument { diff --git a/buildtools/codegen/CodegenMacros.hpp b/buildtools/codegen/CodegenMacros.hpp new file mode 100644 index 0000000..84c9d09 --- /dev/null +++ b/buildtools/codegen/CodegenMacros.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include + +// I give up, hopefully nothing overflows this buffer +// TODO handle buffer sizing properly + +#define APPEND_LIT(out, str) out += str + +#define APPEND_FMT(out, format, ...) \ + { \ + char buffer[65536]; \ + snprintf(buffer, sizeof(buffer), format, __VA_ARGS__); \ + out += buffer; \ + } + +#define WRITE_LIT(file, str) fwrite(str, sizeof(char), sizeof(str) - 1, file) + +// NOTE: snprintf() returns the size written (given an infinite buffer) not including \0 +#define WRITE_FMT(file, format, ...) \ + { \ + char buffer[65536]; \ + int size = snprintf(buffer, sizeof(buffer), format, __VA_ARGS__); \ + fwrite(buffer, sizeof(char), std::min(size, sizeof(buffer)), file); \ + } + +#define APPEND_LIT_LN(out, str) APPEND_LIT(out, (str "\n")) +#define APPEND_FMT_LN(out, format, ...) APPEND_FMT(out, (format "\n"), __VA_ARGS__) +#define WRITE_LIT_LN(out, str) WRITE_LIT(out, (str "\n")) +#define WRITE_FMT_LN(out, format, ...) WRITE_FMT(out, (format "\n"), __VA_ARGS__) diff --git a/buildtools/codegen/CodegenOutput.inl b/buildtools/codegen/CodegenOutput.inl index 752682c..d1f2e50 100644 --- a/buildtools/codegen/CodegenOutput.inl +++ b/buildtools/codegen/CodegenOutput.inl @@ -1,7 +1,9 @@ #pragma once #include "CodegenDecl.hpp" +#include "CodegenMacros.hpp" +#include #include #include #include @@ -31,15 +33,30 @@ public: void MergeContents(CodegenOutput other) { std::move(other.mOutThings.begin(), other.mOutThings.end(), std::back_inserter(this->mOutThings)); + std::move(other.mOutStructs.begin(), other.mOutStructs.end(), std::back_inserter(this->mOutStructs)); + std::move(other.mOutEnums.begin(), other.mOutEnums.end(), std::back_inserter(this->mOutEnums)); + std::move(other.mOutFunctions.begin(), other.mOutFunctions.end(), std::back_inserter(this->mOutFunctions)); } void Write(FILE* file) { -#define WRITE_LITERAL(str) fwrite(str, sizeof(char), sizeof(str) - 1, file) for (auto& thing : mOutThings) { - WRITE_LITERAL("// Output thing\n"); + WRITE_LIT(file, "// Output thing\n"); fwrite(thing.text.c_str(), sizeof(char), thing.text.size(), file); - WRITE_LITERAL("\n"); + WRITE_LIT(file, "\n"); + } + + for (auto& declStruct : mOutStructs) { + WRITE_FMT(file, "struct %s {\n", declStruct.name.c_str()); + // TODO + WRITE_LIT(file, "}\n"); + } + + for (auto& declEnum : mOutEnums) { + // TODO + } + + for (auto& declFunc : mOutFunctions) { + // TODO } -#undef WRITE_LITERAL } }; 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 #include +#include +#include #include #include #include @@ -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 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= %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 %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 +#include +#include +#include +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 [:]... - where : the _file_ to write generated contents to - is one of: - "single" process this file only - "rec" starting at the given directory , recursively process all .h .c .hpp .cpp files - )"""[1]); +USAGE: codegen.exe [:]... +where : the _file_ to write generated contents to + is one of: + "single" process this file only + "rec" starting at the given directory , 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; diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp b/buildtools/codegen/tests/examples/TestEnum.hpp index c498cd9..6b4ab33 100644 --- a/buildtools/codegen/tests/examples/TestEnum.hpp +++ b/buildtools/codegen/tests/examples/TestEnum.hpp @@ -5,14 +5,14 @@ enum MyEnum { EnumElement2, EnumElement3, }; -BRUSSEL_ENUM(MyEnum, ToString); +BRUSSEL_ENUM(MyEnum, ToString FromString); enum CountedEnumAll { CEA_Foo, CEA_Bar, CEA_COUNT, }; -BRUSSEL_ENUM(CountedEnumAll, ToString); +BRUSSEL_ENUM(CountedEnumAll, ToString FromString); enum CountedEnum { CE_Foo, @@ -20,4 +20,4 @@ enum CountedEnum { CE_FooBar, CE_COUNT, }; -BRUSSEL_ENUM(CountedEnum, ToString ExcludeHeuristics); +BRUSSEL_ENUM(CountedEnum, ToString FromString ExcludeHeuristics); -- cgit v1.2.3-70-g09d2 From 7d8bca09b3c4bf1418e758bd3bd0d6f85672153e Mon Sep 17 00:00:00 2001 From: rtk0c Date: Mon, 30 May 2022 15:52:19 -0700 Subject: Changeset: 52 Add support for namespaced enums --- buildtools/codegen/CodegenDecl.hpp | 9 + buildtools/codegen/CodegenInput.inl | 35 +++- buildtools/codegen/CodegenUtils.inl | 33 ++++ buildtools/codegen/main.cpp | 191 ++++++++++++++++----- buildtools/codegen/tests/examples/TestEnum.hpp.txt | 22 +++ source/GraphicsTags.hpp | 11 +- source/main.cpp | 5 - 7 files changed, 245 insertions(+), 61 deletions(-) (limited to 'buildtools/codegen/CodegenDecl.hpp') diff --git a/buildtools/codegen/CodegenDecl.hpp b/buildtools/codegen/CodegenDecl.hpp index b7c1ee4..32d5445 100644 --- a/buildtools/codegen/CodegenDecl.hpp +++ b/buildtools/codegen/CodegenDecl.hpp @@ -3,8 +3,15 @@ #include #include +struct DeclNamespace { + DeclNamespace* container = nullptr; + std::string name; + std::string_view fullname; // View into storage map key +}; + // Structs or classes struct DeclStruct { + DeclNamespace* container = nullptr; std::string name; }; @@ -40,6 +47,7 @@ struct DeclEnumElement { }; struct DeclEnum { + DeclNamespace* container = nullptr; std::string name; std::vector elements; EnumUnderlyingType underlyingType; @@ -56,6 +64,7 @@ struct DeclFunctionArgument { }; struct DeclFunction { + DeclNamespace* container = nullptr; // Things like extern, static, etc. that gets written before the function return type std::string prefix; std::string name; diff --git a/buildtools/codegen/CodegenInput.inl b/buildtools/codegen/CodegenInput.inl index 80a39d0..0809e7f 100644 --- a/buildtools/codegen/CodegenInput.inl +++ b/buildtools/codegen/CodegenInput.inl @@ -3,20 +3,26 @@ #include "CodegenConfig.hpp" #include "CodegenDecl.hpp" +#include "CodegenUtils.inl" + #include #include #include #include +#include #include +using namespace std::literals; + class CodegenInput { private: std::vector mEnums; - robin_hood::unordered_map mDeclByName; + robin_hood::unordered_flat_map mDeclByName; + robin_hood::unordered_node_map mNamespaces; public: - void AddEnum(DeclEnum decl) { + void AddEnum(std::string fullname, DeclEnum decl) { #if CODEGEN_DEBUG_PRINT printf("Committed enum '%s'\n", decl.name.c_str()); for (auto& elm : decl.elements) { @@ -24,10 +30,20 @@ public: } #endif - mDeclByName.try_emplace(std::string(decl.name), mEnums.size()); + mDeclByName.try_emplace(std::move(fullname), mEnums.size()); mEnums.push_back(std::move(decl)); } + DeclNamespace* AddNamespace(DeclNamespace ns) { + auto path = Utils::MakeFullName(""sv, &ns); + auto [iter, success] = mNamespaces.try_emplace(std::move(path), std::move(ns)); + auto& nsRef = iter->second; + if (success) { + nsRef.fullname = iter->first; + } + return &nsRef; + } + const DeclEnum* FindEnumByName(std::string_view name) const { // TODO handle multiple kinds of decl auto iter = mDeclByName.find(name); @@ -37,4 +53,17 @@ public: return nullptr; } } + + const DeclNamespace* FindNamespace(std::string_view fullname) const { + auto iter = mNamespaces.find(fullname); + if (iter != mNamespaces.end()) { + return &iter->second; + } else { + return nullptr; + } + } + + DeclNamespace* FindNamespace(std::string_view name) { + return const_cast(const_cast(this)->FindNamespace(name)); + } }; diff --git a/buildtools/codegen/CodegenUtils.inl b/buildtools/codegen/CodegenUtils.inl index ea46ac1..f9d913e 100644 --- a/buildtools/codegen/CodegenUtils.inl +++ b/buildtools/codegen/CodegenUtils.inl @@ -46,6 +46,34 @@ bool WriteOutputFile(const CodegenOutput& output, std::string_view dir, std::str return true; } +std::string MakeFullName(std::string_view name, DeclNamespace* ns = nullptr) { + size_t length = 0; + std::vector components; + if (!name.empty()) { + components.push_back(name); + length += name.length(); + } + + DeclNamespace* currentNamespace = ns; + while (currentNamespace) { + components.push_back(currentNamespace->name); + length += currentNamespace->name.size() + /*::*/ 2; + currentNamespace = currentNamespace->container; + } + + std::string fullname; + fullname.reserve(length); + for (auto it = components.rbegin(); it != components.rend(); ++it) { + fullname += *it; + fullname += "::"; + } + // Get rid of the last "::" + fullname.pop_back(); + fullname.pop_back(); + + return fullname; +} + void ProduceGeneratedHeaderFileHeader(CodegenOutput& output) { output.AddOutputThing(CodegenOutputThing{ .text = &R"""( @@ -53,6 +81,9 @@ void ProduceGeneratedHeaderFileHeader(CodegenOutput& output) { #pragma once #include + +#include +#include )"""[1], }); } @@ -63,6 +94,8 @@ void ProduceGeneratedSourceFileHeader(CodegenOutput& output) { // This file is generated. Any changes will be overidden when building. #include "GeneratedCode.hpp" +#include +#include #include #include using namespace std::literals; diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp index 3a3e443..2c259a4 100644 --- a/buildtools/codegen/main.cpp +++ b/buildtools/codegen/main.cpp @@ -75,6 +75,7 @@ STR_LUT_DECL(ClexNames, CLEX_eof, CLEX_ext_COUNT) { } enum CppKeyword { + CKw_Namespace, CKw_Struct, CKw_Class, CKw_Enum, @@ -83,6 +84,7 @@ enum CppKeyword { BSTR_LUT_DECL(CppKeyword, 0, CKw_COUNT) { BSTR_LUT_MAP_FOR(CppKeyword); + BSTR_LUT_MAP(CKw_Namespace, "namespace"); BSTR_LUT_MAP(CKw_Struct, "struct"); BSTR_LUT_MAP(CKw_Class, "class"); BSTR_LUT_MAP(CKw_Enum, "enum"); @@ -277,7 +279,27 @@ std::string GenerateEnumStringMap(CodegenOutput& out, const DeclEnum& decl, bool } void GenerateForEnum(CodegenOutput& headerOut, CodegenOutput& sourceOut, const DeclEnum& decl, EnumFlags options) { - bool useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics); + char enumName[2048]; + if (decl.container) { + snprintf(enumName, sizeof(enumName), "%.*s::%s", PRINTF_STRING_VIEW(decl.container->fullname), decl.name.c_str()); + } else { + strncpy(enumName, decl.name.c_str(), sizeof(enumName)); + } + + auto useExcludeHeuristics = options.IsSet(EMGO_ExcludeUseHeuristics); + auto filteredElements = [&]() { + if (useExcludeHeuristics) { + decltype(decl.elements) result; + for (auto& elm : decl.elements) { + if (elm.name.ends_with("COUNT")) continue; + + result.push_back(elm); + } + return result; + } else { + return decl.elements; + } + }(); if (options.IsSet(EMGO_ToString)) { // Generate value -> string lookup table and function @@ -285,23 +307,18 @@ void GenerateForEnum(CodegenOutput& headerOut, CodegenOutput& sourceOut, const D switch (decl.GetPattern()) { case EVP_Continuous: { auto arrayName = GenerateEnumStringArray(sourceOut, decl, useExcludeHeuristics); - int minVal = decl.elements.front().value; - int maxVal = decl.elements.back().value; - if (useExcludeHeuristics && - decl.elements.back().name.ends_with("COUNT") && - decl.elements.size() >= 2) - { - // Skip the last *_COUNT element if instructed to use heuristics - maxVal = decl.elements[decl.elements.size() - 2].value; - } + int minVal = filteredElements.empty() ? 0 : filteredElements.front().value; + int maxVal = filteredElements.empty() ? 0 : filteredElements.back().value; 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, "}"); + { + auto& o = lookupFunctionDef.text; + APPEND_LIT_LN(o, "template <>"); + APPEND_FMT_LN(o, "std::string_view Metadata::EnumToString<%s>(%s value) {", enumName, enumName); + APPEND_FMT_LN(o, " if (value < %d || value > %d) return {};", minVal, maxVal); + APPEND_FMT_LN(o, " return %s[value - %d];", arrayName.c_str(), minVal); + APPEND_LIT_LN(o, "}"); + } sourceOut.AddOutputThing(std::move(lookupFunctionDef)); } break; @@ -323,28 +340,34 @@ void GenerateForEnum(CodegenOutput& headerOut, CodegenOutput& sourceOut, const D if (options.IsSet(EMGO_FromString)) { // Generate string -> value lookup table char mapName[1024]; + // TODO mangle to prevent name conflicts of enum in different namespaces 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 %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()); + { + auto& o = lookupTable.text; + // TODO use correct underlying type + APPEND_FMT_LN(o, "constinit frozen::unordered_map %s = {", filteredElements.size(), mapName); + for (auto& elm : filteredElements) { + APPEND_FMT_LN(o, "{\"%s\", %" PRId64 "},", elm.name.c_str(), elm.value); + } + APPEND_LIT_LN(o, "};"); } - APPEND_LIT_LN(o1, "};"); // Generate lookup function 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, "}"); + { + auto& o = lookupFunctionDef.text; + APPEND_LIT_LN(o, "template <>"); + APPEND_FMT_LN(o, "std::optional<%s> Metadata::EnumFromString<%s>(std::string_view value) {", enumName, enumName); + APPEND_FMT_LN(o, " auto iter = %s.find(value);", mapName); + APPEND_FMT_LN(o, " if (iter != %s.end()) {", mapName); + APPEND_FMT_LN(o, " return (%s)iter->second;", enumName); + APPEND_LIT_LN(o, " } else {"); + APPEND_LIT_LN(o, " return {};"); + APPEND_LIT_LN(o, " }"); + APPEND_LIT_LN(o, "}"); + } sourceOut.AddOutputThing(std::move(lookupTable)); sourceOut.AddOutputThing(std::move(lookupFunctionDef)); @@ -369,7 +392,32 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string CodegenOutput cgSourceOutput; Utils::ProduceGeneratedSourceFileHeader(cgSourceOutput); - int bracePairDepth = 0; + int currentBraceDepth = 0; + // The current effective namespace, see example + DeclNamespace* currentNamespace = nullptr; + + struct NamespaceStackframe { + // The current namespace that owns the brace level, see example + DeclNamespace* ns = nullptr; + // Brace depth `ns` was created at (e.g. [std::details].depth == 0) + int depth = 0; + }; + std::vector nsStack; + + // Example: + // namespace std::details { + // /* [stack top].ns = std::details */ + // /* [stack top].depth = std */ + // } + // namespace foo { + // /* [stack top].ns = foo */ + // /* [stack top].depth = foo */ + // namespace details { + // /* [stack top].ns = foo::details */ + // /* [stack top].depth = foo::details */ + // } + // } + while (idx < tokens.size()) { auto& token = tokens[idx]; @@ -388,6 +436,40 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string } } switch (keyword) { + case CKw_Namespace: { + ++idx; + incrementTokenIdx = false; + + while (true) { + if (tokens[idx].type != CLEX_id) { + // TODO better error recovery + printf("[ERROR] invalid syntax for namespace\n"); + break; + } + + currentNamespace = cgInput.AddNamespace(DeclNamespace{ + .container = currentNamespace, + .name = tokens[idx].text, + }); + + if (tokens[idx + 1].text[0] == ':' && + tokens[idx + 2].text[0] == ':') + { + // Skip the two ':' tokens, try parse the next identifier + idx += 3; + } else { + break; + } + } + + nsStack.push_back(NamespaceStackframe{ + .ns = currentNamespace, + .depth = currentBraceDepth, + }); + + goto endIdenCase; + } + case CKw_Struct: case CKw_Class: { auto& idenTok = tokens[idx + 1]; // TODO handle end of list @@ -401,6 +483,7 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string incrementTokenIdx = false; DeclEnum enumDecl; + enumDecl.container = currentNamespace; enumDecl.underlyingType = EUT_Int32; // TODO if (tokens[idx].text == "class") { @@ -452,7 +535,8 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string ++idx; } - cgInput.AddEnum(std::move(enumDecl)); + auto fullname = Utils::MakeFullName(enumDecl.name, currentNamespace); + cgInput.AddEnum(std::move(fullname), std::move(enumDecl)); goto endIdenCase; } @@ -488,7 +572,7 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string } auto& enumName = argList[0][0]->text; - auto enumDecl = cgInput.FindEnumByName(enumName); + auto enumDecl = cgInput.FindEnumByName(Utils::MakeFullName(enumName, currentNamespace)); if (!enumDecl) { printf("[ERROR] BRUSSEL_ENUM: referring to non-existent enum '%s'\n", enumName.c_str()); break; @@ -519,15 +603,32 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string break; } - case '{': { - bracePairDepth++; - CheckBraceDepth(bracePairDepth); - } break; - - case '}': { - bracePairDepth--; - CheckBraceDepth(bracePairDepth); - } break; + case CLEX_ext_single_char: + switch (token.text[0]) { + case '{': { + currentBraceDepth++; + CheckBraceDepth(currentBraceDepth); + } break; + + case '}': { + currentBraceDepth--; + CheckBraceDepth(currentBraceDepth); + + if (!nsStack.empty()) { + auto& ns = nsStack.back(); + if (ns.depth == currentBraceDepth) { + nsStack.pop_back(); + + if (!nsStack.empty()) { + currentNamespace = nsStack.back().ns; + } else { + currentNamespace = nullptr; + } + } + } + } break; + } + break; } if (incrementTokenIdx) { @@ -535,7 +636,7 @@ void HandleInputFile(AppState& state, std::string_view filenameStem, std::string } } - if (bracePairDepth != 0) { + if (currentBraceDepth != 0) { printf("[WARNING] unbalanced brace at end of file."); } @@ -632,7 +733,7 @@ where : the directory to write generated contents to. This will N } state.outputDir = std::string_view(argv[1]); - DEBUG_PRINTF("Outputting to directory %s.\n", outputDir); + DEBUG_PRINTF("Outputting to directory %.*s.\n", PRINTF_STRING_VIEW(state.outputDir)); for (int i = 2; i < argc; ++i) { const char* argRaw = argv[i]; diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp.txt b/buildtools/codegen/tests/examples/TestEnum.hpp.txt index e596c5e..441d97c 100644 --- a/buildtools/codegen/tests/examples/TestEnum.hpp.txt +++ b/buildtools/codegen/tests/examples/TestEnum.hpp.txt @@ -19,3 +19,25 @@ enum CountedEnum { CE_COUNT, }; BRUSSEL_ENUM(CountedEnum, ToString FromString ExcludeHeuristics); + +namespace MyNamespace { +enum MyNamespacedEnum { + MNE_Foo, + MNE_Bar, +}; +BRUSSEL_ENUM(MyNamespacedEnum, ToString FromString ExcludeHeuristics); + +namespace details { + enum MyNamespacedEnum { + MNE_Foo, + MNE_Bar, + }; + BRUSSEL_ENUM(MyNamespacedEnum, ToString FromString ExcludeHeuristics); +} +} + +namespace foo::details { +enum Enum { +}; +BRUSSEL_ENUM(Enum, ToString FromString ExcludeHeuristics); +} diff --git a/source/GraphicsTags.hpp b/source/GraphicsTags.hpp index 09e62bf..f83b99c 100644 --- a/source/GraphicsTags.hpp +++ b/source/GraphicsTags.hpp @@ -7,14 +7,6 @@ #include -enum TestEnum { - TE_Position, - TE_Color, - TE_TexCoord, - TE_COUNT, -}; -BRUSSEL_ENUM(TestEnum, ToString FromString ExcludeHeuristics); - namespace Tags { /// Vertex element semantics, used to identify the meaning of vertex buffer contents enum VertexElementSemantic { @@ -42,6 +34,7 @@ enum VertexElementSemantic { VES_Generic, VES_COUNT, }; +BRUSSEL_ENUM(VertexElementSemantic, ToString FromString ExcludeHeuristics); std::string_view NameOf(VertexElementSemantic semantic); VertexElementSemantic FindVertexElementSemantic(std::string_view name); @@ -82,6 +75,8 @@ enum VertexElementType { VET_Ushort4Norm, VET_NORM_END = VET_Ushort4Norm, }; +// TODO this enum isn't continuous, not supported yet +// BRUSSEL_ENUM(VertexElementType, ToString FromString ExcludeHeuristics); int SizeOf(VertexElementType type); int VectorLenOf(VertexElementType type); diff --git a/source/main.cpp b/source/main.cpp index 353746b..c49fc0b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -3,11 +3,9 @@ #include "AppConfig.hpp" #include "CommonVertexIndex.hpp" #include "EditorGuizmo.hpp" -#include "GraphicsTags.hpp" #include "Ires.hpp" #include "Level.hpp" #include "Material.hpp" -#include "Metadata.hpp" #include "Shader.hpp" #define GLFW_INCLUDE_NONE @@ -104,9 +102,6 @@ fs::path GetEnvVar(const char* name, const char* backup) { int main(int argc, char* argv[]) { using namespace Tags; - auto str = Metadata::EnumToString(TE_Color); - printf("%.*s", PRINTF_STRING_VIEW(str)); - constexpr auto kImGuiBackend = "imgui-backend"; constexpr auto kGameDataDir = "game-data-directory"; constexpr auto kGameAssetDir = "game-asset-directory"; -- cgit v1.2.3-70-g09d2