1 //===- DialectImplementation.h ----------------------------------*- C++ -*-===//
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 // This file contains utilities classes for implementing dialect attributes and
10 // types.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_IR_DIALECTIMPLEMENTATION_H
15 #define MLIR_IR_DIALECTIMPLEMENTATION_H
16 
17 #include "mlir/IR/OpImplementation.h"
18 
19 namespace mlir {
20 
21 //===----------------------------------------------------------------------===//
22 // DialectAsmPrinter
23 //===----------------------------------------------------------------------===//
24 
25 /// This is a pure-virtual base class that exposes the asmprinter hooks
26 /// necessary to implement a custom printAttribute/printType() method on a
27 /// dialect.
28 class DialectAsmPrinter : public AsmPrinter {
29 public:
30   using AsmPrinter::AsmPrinter;
31   ~DialectAsmPrinter() override;
32 };
33 
34 //===----------------------------------------------------------------------===//
35 // DialectAsmParser
36 //===----------------------------------------------------------------------===//
37 
38 /// The DialectAsmParser has methods for interacting with the asm parser when
39 /// parsing attributes and types.
40 class DialectAsmParser : public AsmParser {
41 public:
42   using AsmParser::AsmParser;
43   ~DialectAsmParser() override;
44 
45   /// Returns the full specification of the symbol being parsed. This allows for
46   /// using a separate parser if necessary.
47   virtual StringRef getFullSymbolSpec() const = 0;
48 };
49 
50 //===----------------------------------------------------------------------===//
51 // Parse Fields
52 //===----------------------------------------------------------------------===//
53 
54 /// Provide a template class that can be specialized by users to dispatch to
55 /// parsers. Auto-generated parsers generate calls to `FieldParser<T>::parse`,
56 /// where `T` is the parameter storage type, to parse custom types.
57 template <typename T, typename = T>
58 struct FieldParser;
59 
60 /// Parse an attribute.
61 template <typename AttributeT>
62 struct FieldParser<
63     AttributeT, std::enable_if_t<std::is_base_of<Attribute, AttributeT>::value,
64                                  AttributeT>> {
65   static FailureOr<AttributeT> parse(AsmParser &parser) {
66     AttributeT value;
67     if (parser.parseCustomAttributeWithFallback(value))
68       return failure();
69     return value;
70   }
71 };
72 
73 /// Parse an attribute.
74 template <typename TypeT>
75 struct FieldParser<
76     TypeT, std::enable_if_t<std::is_base_of<Type, TypeT>::value, TypeT>> {
77   static FailureOr<TypeT> parse(AsmParser &parser) {
78     TypeT value;
79     if (parser.parseCustomTypeWithFallback(value))
80       return failure();
81     return value;
82   }
83 };
84 
85 /// Parse any integer.
86 template <typename IntT>
87 struct FieldParser<IntT,
88                    std::enable_if_t<std::is_integral<IntT>::value, IntT>> {
89   static FailureOr<IntT> parse(AsmParser &parser) {
90     IntT value;
91     if (parser.parseInteger(value))
92       return failure();
93     return value;
94   }
95 };
96 
97 /// Parse a string.
98 template <>
99 struct FieldParser<std::string> {
100   static FailureOr<std::string> parse(AsmParser &parser) {
101     std::string value;
102     if (parser.parseString(&value))
103       return failure();
104     return value;
105   }
106 };
107 
108 /// Parse any container that supports back insertion as a list.
109 template <typename ContainerT>
110 struct FieldParser<
111     ContainerT, std::enable_if_t<std::is_member_function_pointer<
112                                      decltype(&ContainerT::push_back)>::value,
113                                  ContainerT>> {
114   using ElementT = typename ContainerT::value_type;
115   static FailureOr<ContainerT> parse(AsmParser &parser) {
116     ContainerT elements;
117     auto elementParser = [&]() {
118       auto element = FieldParser<ElementT>::parse(parser);
119       if (failed(element))
120         return failure();
121       elements.push_back(*element);
122       return success();
123     };
124     if (parser.parseCommaSeparatedList(elementParser))
125       return failure();
126     return elements;
127   }
128 };
129 
130 /// Parse an affine map.
131 template <>
132 struct FieldParser<AffineMap> {
133   static FailureOr<AffineMap> parse(AsmParser &parser) {
134     AffineMap map;
135     if (failed(parser.parseAffineMap(map)))
136       return failure();
137     return map;
138   }
139 };
140 
141 } // namespace mlir
142 
143 #endif // MLIR_IR_DIALECTIMPLEMENTATION_H
144