MLIR  22.0.0git
TemplatingUtils.h
Go to the documentation of this file.
1 //===- TemplatingUtils.h - Templater for text templates -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
10 #define MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
11 
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringMap.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include <variant>
18 #include <vector>
19 
20 namespace mlir::irdl::detail {
21 
22 /// A dictionary stores a mapping of template variable names to their assigned
23 /// string values.
24 using dictionary = llvm::StringMap<llvm::SmallString<8>>;
25 
26 /// Template Code as used by IRDL-to-Cpp.
27 ///
28 /// For efficiency, produces a bytecode representation of an input template.
29 /// - LiteralToken: A contiguous stream of characters to be printed
30 /// - ReplacementToken: A template variable that will be replaced
31 class Template {
32 public:
33  Template(llvm::StringRef str) {
34  bool processingReplacementToken = false;
35  while (!str.empty()) {
36  auto [token, remainder] = str.split("__");
37 
38  if (processingReplacementToken) {
39  assert(!token.empty() && "replacement name cannot be empty");
40  bytecode.emplace_back(ReplacementToken{token});
41  } else {
42  if (!token.empty())
43  bytecode.emplace_back(LiteralToken{token});
44  }
45 
46  processingReplacementToken = !processingReplacementToken;
47  str = remainder;
48  }
49  }
50 
51  /// Render will apply a dictionary to the Template and send the rendered
52  /// result to the specified output stream.
53  void render(llvm::raw_ostream &out, const dictionary &replacements) const {
54  for (auto instruction : bytecode) {
55  if (auto *inst = std::get_if<LiteralToken>(&instruction)) {
56  out << inst->text;
57  continue;
58  }
59 
60  if (auto *inst = std::get_if<ReplacementToken>(&instruction)) {
61  auto replacement = replacements.find(inst->keyName);
62 #ifndef NDEBUG
63  if (replacement == replacements.end()) {
64  llvm::errs() << "Missing template key: " << inst->keyName << "\n";
65  llvm_unreachable("Missing template key");
66  }
67 #endif
68  out << replacement->second;
69  continue;
70  }
71 
72  llvm_unreachable("non-exhaustive bytecode visit");
73  }
74  }
75 
76 private:
77  struct LiteralToken {
78  llvm::StringRef text;
79  };
80 
81  struct ReplacementToken {
82  llvm::StringRef keyName;
83  };
84 
85  std::vector<std::variant<LiteralToken, ReplacementToken>> bytecode;
86 };
87 
88 } // namespace mlir::irdl::detail
89 
90 #endif // MLIR_LIB_TARGET_IRDLTOCPP_TEMPLATINGUTILS_H
Template Code as used by IRDL-to-Cpp.
void render(llvm::raw_ostream &out, const dictionary &replacements) const
Render will apply a dictionary to the Template and send the rendered result to the specified output s...
Template(llvm::StringRef str)
llvm::StringMap< llvm::SmallString< 8 > > dictionary
A dictionary stores a mapping of template variable names to their assigned string values.