91 lines
2.7 KiB
C++
91 lines
2.7 KiB
C++
//===- 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 <variant>
|
|
#include <vector>
|
|
|
|
namespace mlir::irdl::detail {
|
|
|
|
/// A dictionary stores a mapping of template variable names to their assigned
|
|
/// string values.
|
|
using dictionary = llvm::StringMap<llvm::SmallString<8>>;
|
|
|
|
/// 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<LiteralToken>(&instruction)) {
|
|
out << inst->text;
|
|
continue;
|
|
}
|
|
|
|
if (auto *inst = std::get_if<ReplacementToken>(&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<std::variant<LiteralToken, ReplacementToken>> bytecode;
|
|
};
|
|
|
|
} // namespace mlir::irdl::detail
|
|
|
|
#endif // MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
|