//===- TemplatingUtils.h - Templater for text templates -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H #define MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include #include namespace mlir::irdl::detail { /// A dictionary stores a mapping of template variable names to their assigned /// string values. using dictionary = llvm::StringMap>; /// Template Code as used by IRDL-to-Cpp. /// /// For efficiency, produces a bytecode representation of an input template. /// - LiteralToken: A contiguous stream of characters to be printed /// - ReplacementToken: A template variable that will be replaced class Template { public: Template(llvm::StringRef str) { bool processingReplacementToken = false; while (!str.empty()) { auto [token, remainder] = str.split("__"); if (processingReplacementToken) { assert(!token.empty() && "replacement name cannot be empty"); bytecode.emplace_back(ReplacementToken{token}); } else { if (!token.empty()) bytecode.emplace_back(LiteralToken{token}); } processingReplacementToken = !processingReplacementToken; str = remainder; } } /// Render will apply a dictionary to the Template and send the rendered /// result to the specified output stream. void render(llvm::raw_ostream &out, const dictionary &replacements) const { for (auto instruction : bytecode) { if (auto *inst = std::get_if(&instruction)) { out << inst->text; continue; } if (auto *inst = std::get_if(&instruction)) { auto replacement = replacements.find(inst->keyName); #ifndef NDEBUG if (replacement == replacements.end()) { llvm::errs() << "Missing template key: " << inst->keyName << "\n"; llvm_unreachable("Missing template key"); } #endif out << replacement->second; continue; } llvm_unreachable("non-exhaustive bytecode visit"); } } private: struct LiteralToken { llvm::StringRef text; }; struct ReplacementToken { llvm::StringRef keyName; }; std::vector> bytecode; }; } // namespace mlir::irdl::detail #endif // MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H