[Mlir-commits] [mlir] [mlir] Add struct parsing and printing utilities (PR #133939)

Jorn Tuyls llvmlistbot at llvm.org
Thu Apr 3 07:50:15 PDT 2025


================
@@ -316,6 +316,41 @@ static ParseResult parseCustomFloatAttr(AsmParser &p, StringAttr &typeStrAttr,
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// TestCustomStructAttr
+//===----------------------------------------------------------------------===//
+
+Attribute TestCustomStructAttr::parse(AsmParser &p, Type type) {
+  std::string typeStr;
+  int64_t value;
+  FailureOr<ArrayAttr> optParam;
+  if (failed(p.parseStruct(AsmParser::Delimiter::LessGreater,
+                           {"type_str", "value", "opt_param"},
+                           {[&]() { return p.parseString(&typeStr); },
+                            [&]() { return p.parseInteger(value); },
+                            [&]() {
+                              optParam = mlir::FieldParser<ArrayAttr>::parse(p);
+                              return success(succeeded(optParam));
+                            }}))) {
+    p.emitError(p.getCurrentLocation())
+        << "failed parsing `TestCustomStructAttr`";
+    return {};
+  }
+  return get(p.getContext(), StringAttr::get(p.getContext(), typeStr), value,
+             optParam.value_or(ArrayAttr()));
+}
+
+void TestCustomStructAttr::print(AsmPrinter &p) const {
+  p << "<";
+  p.printStruct(std::make_pair("type_str", getTypeStr()),
+                std::make_pair("value", getValue()));
----------------
jtuyls wrote:

Yeah, you can use interleaveComma instead, and am I happy to just remove the printStruct utility, but I think interleaveComma is a bit more bloated with different types of the operands:
```
SmallVector<StringRef> keywords = {"type_str", "value"};
llvm::interleaveComma(keywords, p, [&](StringRef kw) {
  p << kw << " = ";
  if (kw == "type_str") {
    p.printStrippedAttrOrType(getTypeStr()); //StringAttr
  } else if (kw == "value") {
    p.printStrippedAttrOrType(getValue()); // int64_t
  }
});
if (getOptParam() != ArrayAttr()) {
  p << ", opt_param = ";
  p.printStrippedAttrOrType(getOptParam());
}
```
Of course, you could just print the list manually as well, which might even be the most compact in a lot of instances:
```
p << "type_str = ";
p.printStrippedAttrOrType(getTypeStr());
p << ", value = ";
p.printStrippedAttrOrType(getValue());
if (getOptParam() != ArrayAttr()) {
  p << ", opt_param = ";
  p.printStrippedAttrOrType(getOptParam());
}
```
Alternatively, I could implement printStruct more in line with parseStruct like this:
```
void printStruct(ArrayRef<StringRef> keywords,
                   ArrayRef<llvm::function_ref<void(AsmPrinter &p)>> printFuncs) {
  DenseMap<StringRef, llvm::function_ref<void(AsmPrinter &p)>> keywordToFunc;
  for (auto &&[kw, printFunc] : llvm::zip(keywords, printFuncs))
    keywordToFunc[kw] = printFunc;
  auto &os = getStream();
  llvm::interleaveComma(keywords, os, [&](StringRef kw) {
    os << kw << " = ";
    keywordToFunc[kw](*this);
  });
}
```
And use it like this:
```
SmallVector<StringRef> keywords = {"type_str", "value"};
p.printStruct(keywords, {
  [&](AsmPrinter &p) { p.printStrippedAttrOrType(getTypeStr()); },
  [&](AsmPrinter &p) { p.printStrippedAttrOrType(getValue()); }
});
if (getOptParam() != ArrayAttr()) {
  p << ", opt_param = ";
  p.printStrippedAttrOrType(getOptParam());
}
```
Upon reconsideration, I like this latter approach or removing the printStruct utility the most. Let me know what you prefer?

https://github.com/llvm/llvm-project/pull/133939


More information about the Mlir-commits mailing list