diff options
author | rtk0c <[email protected]> | 2022-06-03 23:26:44 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-06-03 23:26:44 -0700 |
commit | 60ccc62f4934e44ad5b905fdbcf458302b8d8a09 (patch) | |
tree | 02ec83cc8387abfd08bd5ee7ea4e8115f1bfb8d0 /source/CodegenCompiler/CodegenUtils.cpp | |
parent | c2ef7737536bf1f8c81fcfae95c0183b21c9753f (diff) |
Changeset: 63 [WIP] Rename directories
Diffstat (limited to 'source/CodegenCompiler/CodegenUtils.cpp')
-rw-r--r-- | source/CodegenCompiler/CodegenUtils.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/source/CodegenCompiler/CodegenUtils.cpp b/source/CodegenCompiler/CodegenUtils.cpp new file mode 100644 index 0000000..0c70cb6 --- /dev/null +++ b/source/CodegenCompiler/CodegenUtils.cpp @@ -0,0 +1,146 @@ +#include "CodegenUtils.hpp" + +#include <Macros.hpp> +#include <ScopeGuard.hpp> +#include <Utils.hpp> + +#include <cstdio> +#include <cstdlib> + +bool Utils::WriteOutputFile(const CodegenOutput& output, const char* path) { + auto outputFile = Utils::OpenCstdioFile(path, Utils::WriteTruncate); + if (!outputFile) { + printf("[ERROR] unable to open output file %s\n", path); + return false; + } + DEFER { fclose(outputFile); }; + + DEBUG_PRINTF("Writing output %s\n", path); + output.Write(outputFile); + + return true; +} + +std::string Utils::MakeFullName(std::string_view name, DeclNamespace* ns) { + size_t length = 0; + std::vector<std::string_view> 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; +} + +// NOTE: assuming we are only dealing with ASCII characters +static bool IsLowerCase(char c) { + return c >= 'a' && c <= 'z'; +} +static bool IsUpperCase(char c) { + return c >= 'A' && c <= 'Z'; +} +static bool IsAlphabetic(char c) { + return IsLowerCase(c) || IsUpperCase(c); +} +static char MakeUpperCase(char c) { + if (IsAlphabetic(c)) { + return IsUpperCase(c) + ? c + : ('A' + (c - 'a')); + } + return c; +} + +std::vector<std::string_view> Utils::SplitIdentifier(std::string_view name) { + // TODO handle SCREAMING_CASE + + size_t chunkStart = 0; + size_t chunkEnd = 0; + std::vector<std::string_view> result; + auto PushChunk = [&]() { result.push_back(std::string_view(name.begin() + chunkStart, name.begin() + chunkEnd)); }; + while (chunkEnd < name.size()) { + char c = name[chunkEnd]; + if (IsUpperCase(c)) { + // Start of next chunk, using camelCase or PascalCase + PushChunk(); + chunkStart = chunkEnd; + chunkEnd = chunkStart + 1; + continue; + } else if (c == '_') { + // End of this chunk, using snake_case + PushChunk(); + chunkStart = chunkEnd + 1; + chunkEnd = chunkStart + 1; + continue; + } else if (c == '-') { + // End of this chunk, using kebab-case + PushChunk(); + chunkStart = chunkEnd + 1; + chunkEnd = chunkStart + 1; + continue; + } + ++chunkEnd; + } + + if ((chunkEnd - chunkStart) >= 1) { + PushChunk(); + } + + return result; +} + +std::string Utils::MakePascalCase(std::string_view name) { + std::string result; + for (auto part : SplitIdentifier(name)) { + result += MakeUpperCase(part[0]); + result += part.substr(1); + } + return result; +} + +void Utils::ProduceGeneratedHeader(const char* headerFilename, CodegenOutput& header, const char* sourceFilename, CodegenOutput& source) { + CodegenOutputThing headerOut; + headerOut.text += &R"""( +// This file is generated. Any changes will be overidden when building. +#pragma once +#include <MetadataBase.hpp> +#include <cstddef> +#include <cstdint> +)"""[1]; + + CodegenOutputThing sourceOut; + APPEND_LIT_LN(sourceOut.text, "// This file is generated. Any changes will be overidden when building."); + APPEND_FMT_LN(sourceOut.text, "#include \"%s\"", headerFilename); + sourceOut.text += &R"""( +#include <MetadataDetails.hpp> +#include <frozen/string.h> +#include <frozen/unordered_map.h> +using namespace std::literals; +)"""[1]; + + header.AddOutputThing(std::move(headerOut)); + source.AddOutputThing(std::move(sourceOut)); +} + +void Utils::ProduceClassTypeInfo(CodegenOutput& source, std::string_view className, const DeclNamespace* ns) { + CodegenOutputThing thing; + + source.AddOutputThing(std::move(thing)); +} |