xref: /llvm-project/mlir/lib/Tools/PDLL/Parser/Parser.cpp (revision 095b41c6eedb3acc908dc63ee91ff77944c07d75)
111d26bd1SRiver Riddle //===- Parser.cpp ---------------------------------------------------------===//
211d26bd1SRiver Riddle //
311d26bd1SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
411d26bd1SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
511d26bd1SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
611d26bd1SRiver Riddle //
711d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
811d26bd1SRiver Riddle 
911d26bd1SRiver Riddle #include "mlir/Tools/PDLL/Parser/Parser.h"
1011d26bd1SRiver Riddle #include "Lexer.h"
11bf352e0bSRiver Riddle #include "mlir/Support/IndentedOstream.h"
1281f2f4dfSRiver Riddle #include "mlir/TableGen/Argument.h"
1381f2f4dfSRiver Riddle #include "mlir/TableGen/Attribute.h"
1481f2f4dfSRiver Riddle #include "mlir/TableGen/Constraint.h"
1581f2f4dfSRiver Riddle #include "mlir/TableGen/Format.h"
1681f2f4dfSRiver Riddle #include "mlir/TableGen/Operator.h"
1711d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Context.h"
1811d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Diagnostic.h"
1911d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Nodes.h"
2011d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Types.h"
2181f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Constraint.h"
2281f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Context.h"
2381f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Operation.h"
24008de486SRiver Riddle #include "mlir/Tools/PDLL/Parser/CodeComplete.h"
25f62a57a3SRiver Riddle #include "llvm/ADT/StringExtras.h"
2611d26bd1SRiver Riddle #include "llvm/ADT/TypeSwitch.h"
2711d26bd1SRiver Riddle #include "llvm/Support/FormatVariadic.h"
2881f2f4dfSRiver Riddle #include "llvm/Support/ManagedStatic.h"
2911d26bd1SRiver Riddle #include "llvm/Support/SaveAndRestore.h"
30f62a57a3SRiver Riddle #include "llvm/Support/ScopedPrinter.h"
3181f2f4dfSRiver Riddle #include "llvm/TableGen/Error.h"
3281f2f4dfSRiver Riddle #include "llvm/TableGen/Parser.h"
33a1fe1f5fSKazu Hirata #include <optional>
342545cac5SMehdi Amini #include <string>
3511d26bd1SRiver Riddle 
3611d26bd1SRiver Riddle using namespace mlir;
3711d26bd1SRiver Riddle using namespace mlir::pdll;
3811d26bd1SRiver Riddle 
3911d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
4011d26bd1SRiver Riddle // Parser
4111d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
4211d26bd1SRiver Riddle 
4311d26bd1SRiver Riddle namespace {
4411d26bd1SRiver Riddle class Parser {
4511d26bd1SRiver Riddle public:
46008de486SRiver Riddle   Parser(ast::Context &ctx, llvm::SourceMgr &sourceMgr,
47bf352e0bSRiver Riddle          bool enableDocumentation, CodeCompleteContext *codeCompleteContext)
48008de486SRiver Riddle       : ctx(ctx), lexer(sourceMgr, ctx.getDiagEngine(), codeCompleteContext),
49bf352e0bSRiver Riddle         curToken(lexer.lexToken()), enableDocumentation(enableDocumentation),
509e57210aSRiver Riddle         typeTy(ast::TypeType::get(ctx)), valueTy(ast::ValueType::get(ctx)),
5181f2f4dfSRiver Riddle         typeRangeTy(ast::TypeRangeType::get(ctx)),
529e57210aSRiver Riddle         valueRangeTy(ast::ValueRangeType::get(ctx)),
53008de486SRiver Riddle         attrTy(ast::AttributeType::get(ctx)),
54008de486SRiver Riddle         codeCompleteContext(codeCompleteContext) {}
5511d26bd1SRiver Riddle 
5611d26bd1SRiver Riddle   /// Try to parse a new module. Returns nullptr in the case of failure.
5711d26bd1SRiver Riddle   FailureOr<ast::Module *> parseModule();
5811d26bd1SRiver Riddle 
5911d26bd1SRiver Riddle private:
6011d26bd1SRiver Riddle   /// The current context of the parser. It allows for the parser to know a bit
6111d26bd1SRiver Riddle   /// about the construct it is nested within during parsing. This is used
6211d26bd1SRiver Riddle   /// specifically to provide additional verification during parsing, e.g. to
6311d26bd1SRiver Riddle   /// prevent using rewrites within a match context, matcher constraints within
6411d26bd1SRiver Riddle   /// a rewrite section, etc.
6511d26bd1SRiver Riddle   enum class ParserContext {
6611d26bd1SRiver Riddle     /// The parser is in the global context.
6711d26bd1SRiver Riddle     Global,
68faf42264SRiver Riddle     /// The parser is currently within a Constraint, which disallows all types
69faf42264SRiver Riddle     /// of rewrites (e.g. `erase`, `replace`, calls to Rewrites, etc.).
70faf42264SRiver Riddle     Constraint,
7111d26bd1SRiver Riddle     /// The parser is currently within the matcher portion of a Pattern, which
7211d26bd1SRiver Riddle     /// is allows a terminal operation rewrite statement but no other rewrite
7311d26bd1SRiver Riddle     /// transformations.
7411d26bd1SRiver Riddle     PatternMatch,
7512eebb8eSRiver Riddle     /// The parser is currently within a Rewrite, which disallows calls to
7612eebb8eSRiver Riddle     /// constraints, requires operation expressions to have names, etc.
7712eebb8eSRiver Riddle     Rewrite,
7811d26bd1SRiver Riddle   };
7911d26bd1SRiver Riddle 
8091b8d96fSRiver Riddle   /// The current specification context of an operations result type. This
8191b8d96fSRiver Riddle   /// indicates how the result types of an operation may be inferred.
8291b8d96fSRiver Riddle   enum class OpResultTypeContext {
8391b8d96fSRiver Riddle     /// The result types of the operation are not known to be inferred.
8491b8d96fSRiver Riddle     Explicit,
8591b8d96fSRiver Riddle     /// The result types of the operation are inferred from the root input of a
8691b8d96fSRiver Riddle     /// `replace` statement.
8791b8d96fSRiver Riddle     Replacement,
8891b8d96fSRiver Riddle     /// The result types of the operation are inferred by using the
8991b8d96fSRiver Riddle     /// `InferTypeOpInterface` interface provided by the operation.
9091b8d96fSRiver Riddle     Interface,
9191b8d96fSRiver Riddle   };
9291b8d96fSRiver Riddle 
9311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
9411d26bd1SRiver Riddle   // Parsing
9511d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
9611d26bd1SRiver Riddle 
9711d26bd1SRiver Riddle   /// Push a new decl scope onto the lexer.
9811d26bd1SRiver Riddle   ast::DeclScope *pushDeclScope() {
9911d26bd1SRiver Riddle     ast::DeclScope *newScope =
10011d26bd1SRiver Riddle         new (scopeAllocator.Allocate()) ast::DeclScope(curDeclScope);
10111d26bd1SRiver Riddle     return (curDeclScope = newScope);
10211d26bd1SRiver Riddle   }
10311d26bd1SRiver Riddle   void pushDeclScope(ast::DeclScope *scope) { curDeclScope = scope; }
10411d26bd1SRiver Riddle 
10511d26bd1SRiver Riddle   /// Pop the last decl scope from the lexer.
10611d26bd1SRiver Riddle   void popDeclScope() { curDeclScope = curDeclScope->getParentScope(); }
10711d26bd1SRiver Riddle 
10811d26bd1SRiver Riddle   /// Parse the body of an AST module.
10981f2f4dfSRiver Riddle   LogicalResult parseModuleBody(SmallVectorImpl<ast::Decl *> &decls);
11011d26bd1SRiver Riddle 
11111d26bd1SRiver Riddle   /// Try to convert the given expression to `type`. Returns failure and emits
11211d26bd1SRiver Riddle   /// an error if a conversion is not viable. On failure, `noteAttachFn` is
11311d26bd1SRiver Riddle   /// invoked to attach notes to the emitted error diagnostic. On success,
11411d26bd1SRiver Riddle   /// `expr` is updated to the expression used to convert to `type`.
11511d26bd1SRiver Riddle   LogicalResult convertExpressionTo(
11611d26bd1SRiver Riddle       ast::Expr *&expr, ast::Type type,
11711d26bd1SRiver Riddle       function_ref<void(ast::Diagnostic &diag)> noteAttachFn = {});
1189e57210aSRiver Riddle   LogicalResult
1199e57210aSRiver Riddle   convertOpExpressionTo(ast::Expr *&expr, ast::OperationType exprType,
1209e57210aSRiver Riddle                         ast::Type type,
1219e57210aSRiver Riddle                         function_ref<ast::InFlightDiagnostic()> emitErrorFn);
1229e57210aSRiver Riddle   LogicalResult convertTupleExpressionTo(
1239e57210aSRiver Riddle       ast::Expr *&expr, ast::TupleType exprType, ast::Type type,
1249e57210aSRiver Riddle       function_ref<ast::InFlightDiagnostic()> emitErrorFn,
1259e57210aSRiver Riddle       function_ref<void(ast::Diagnostic &diag)> noteAttachFn);
12611d26bd1SRiver Riddle 
12702670c3fSRiver Riddle   /// Given an operation expression, convert it to a Value or ValueRange
12802670c3fSRiver Riddle   /// typed expression.
12902670c3fSRiver Riddle   ast::Expr *convertOpToValue(const ast::Expr *opExpr);
13002670c3fSRiver Riddle 
13181f2f4dfSRiver Riddle   /// Lookup ODS information for the given operation, returns nullptr if no
13281f2f4dfSRiver Riddle   /// information is found.
1330a81ace0SKazu Hirata   const ods::Operation *lookupODSOperation(std::optional<StringRef> opName) {
13481f2f4dfSRiver Riddle     return opName ? ctx.getODSContext().lookupOperation(*opName) : nullptr;
13581f2f4dfSRiver Riddle   }
13681f2f4dfSRiver Riddle 
137bf352e0bSRiver Riddle   /// Process the given documentation string, or return an empty string if
138bf352e0bSRiver Riddle   /// documentation isn't enabled.
139bf352e0bSRiver Riddle   StringRef processDoc(StringRef doc) {
140bf352e0bSRiver Riddle     return enableDocumentation ? doc : StringRef();
141bf352e0bSRiver Riddle   }
142bf352e0bSRiver Riddle 
143bf352e0bSRiver Riddle   /// Process the given documentation string and format it, or return an empty
144bf352e0bSRiver Riddle   /// string if documentation isn't enabled.
145bf352e0bSRiver Riddle   std::string processAndFormatDoc(const Twine &doc) {
146bf352e0bSRiver Riddle     if (!enableDocumentation)
147bf352e0bSRiver Riddle       return "";
148bf352e0bSRiver Riddle     std::string docStr;
149bf352e0bSRiver Riddle     {
150bf352e0bSRiver Riddle       llvm::raw_string_ostream docOS(docStr);
151bf352e0bSRiver Riddle       raw_indented_ostream(docOS).printReindented(
152*095b41c6SJOE1994           StringRef(docStr).rtrim(" \t"));
153bf352e0bSRiver Riddle     }
154bf352e0bSRiver Riddle     return docStr;
155bf352e0bSRiver Riddle   }
156bf352e0bSRiver Riddle 
15711d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
15811d26bd1SRiver Riddle   // Directives
15911d26bd1SRiver Riddle 
16081f2f4dfSRiver Riddle   LogicalResult parseDirective(SmallVectorImpl<ast::Decl *> &decls);
16181f2f4dfSRiver Riddle   LogicalResult parseInclude(SmallVectorImpl<ast::Decl *> &decls);
16281f2f4dfSRiver Riddle   LogicalResult parseTdInclude(StringRef filename, SMRange fileLoc,
16381f2f4dfSRiver Riddle                                SmallVectorImpl<ast::Decl *> &decls);
16481f2f4dfSRiver Riddle 
16581f2f4dfSRiver Riddle   /// Process the records of a parsed tablegen include file.
166b60c6cbcSRahul Joshi   void processTdIncludeRecords(const llvm::RecordKeeper &tdRecords,
16781f2f4dfSRiver Riddle                                SmallVectorImpl<ast::Decl *> &decls);
16881f2f4dfSRiver Riddle 
16981f2f4dfSRiver Riddle   /// Create a user defined native constraint for a constraint imported from
17081f2f4dfSRiver Riddle   /// ODS.
17181f2f4dfSRiver Riddle   template <typename ConstraintT>
172bf352e0bSRiver Riddle   ast::Decl *
173bf352e0bSRiver Riddle   createODSNativePDLLConstraintDecl(StringRef name, StringRef codeBlock,
174bf352e0bSRiver Riddle                                     SMRange loc, ast::Type type,
175bf352e0bSRiver Riddle                                     StringRef nativeType, StringRef docString);
17681f2f4dfSRiver Riddle   template <typename ConstraintT>
17781f2f4dfSRiver Riddle   ast::Decl *
17881f2f4dfSRiver Riddle   createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint,
1791c2edb02SRiver Riddle                                     SMRange loc, ast::Type type,
1801c2edb02SRiver Riddle                                     StringRef nativeType);
18111d26bd1SRiver Riddle 
18211d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
18311d26bd1SRiver Riddle   // Decls
18411d26bd1SRiver Riddle 
185322691abSRiver Riddle   /// This structure contains the set of pattern metadata that may be parsed.
186322691abSRiver Riddle   struct ParsedPatternMetadata {
1870a81ace0SKazu Hirata     std::optional<uint16_t> benefit;
188322691abSRiver Riddle     bool hasBoundedRecursion = false;
189322691abSRiver Riddle   };
190322691abSRiver Riddle 
19111d26bd1SRiver Riddle   FailureOr<ast::Decl *> parseTopLevelDecl();
192008de486SRiver Riddle   FailureOr<ast::NamedAttributeDecl *>
1930a81ace0SKazu Hirata   parseNamedAttributeDecl(std::optional<StringRef> parentOpName);
194faf42264SRiver Riddle 
195faf42264SRiver Riddle   /// Parse an argument variable as part of the signature of a
196faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
197faf42264SRiver Riddle   FailureOr<ast::VariableDecl *> parseArgumentDecl();
198faf42264SRiver Riddle 
199faf42264SRiver Riddle   /// Parse a result variable as part of the signature of a UserConstraintDecl
200faf42264SRiver Riddle   /// or UserRewriteDecl.
201faf42264SRiver Riddle   FailureOr<ast::VariableDecl *> parseResultDecl(unsigned resultNum);
202faf42264SRiver Riddle 
203faf42264SRiver Riddle   /// Parse a UserConstraintDecl. `isInline` signals if the constraint is being
204faf42264SRiver Riddle   /// defined in a non-global context.
205faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *>
206faf42264SRiver Riddle   parseUserConstraintDecl(bool isInline = false);
207faf42264SRiver Riddle 
208faf42264SRiver Riddle   /// Parse an inline UserConstraintDecl. An inline decl is one defined in a
209faf42264SRiver Riddle   /// non-global context, such as within a Pattern/Constraint/etc.
210faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> parseInlineUserConstraintDecl();
211faf42264SRiver Riddle 
212faf42264SRiver Riddle   /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using
213faf42264SRiver Riddle   /// PDLL constructs.
214faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> parseUserPDLLConstraintDecl(
215faf42264SRiver Riddle       const ast::Name &name, bool isInline,
216faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
217faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
218faf42264SRiver Riddle 
219faf42264SRiver Riddle   /// Parse a parseUserRewriteDecl. `isInline` signals if the rewrite is being
220faf42264SRiver Riddle   /// defined in a non-global context.
221faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseUserRewriteDecl(bool isInline = false);
222faf42264SRiver Riddle 
223faf42264SRiver Riddle   /// Parse an inline UserRewriteDecl. An inline decl is one defined in a
224faf42264SRiver Riddle   /// non-global context, such as within a Pattern/Rewrite/etc.
225faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseInlineUserRewriteDecl();
226faf42264SRiver Riddle 
227faf42264SRiver Riddle   /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using
228faf42264SRiver Riddle   /// PDLL constructs.
229faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseUserPDLLRewriteDecl(
230faf42264SRiver Riddle       const ast::Name &name, bool isInline,
231faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
232faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
233faf42264SRiver Riddle 
234faf42264SRiver Riddle   /// Parse either a UserConstraintDecl or UserRewriteDecl. These decls have
235faf42264SRiver Riddle   /// effectively the same syntax, and only differ on slight semantics (given
236faf42264SRiver Riddle   /// the different parsing contexts).
237faf42264SRiver Riddle   template <typename T, typename ParseUserPDLLDeclFnT>
238faf42264SRiver Riddle   FailureOr<T *> parseUserConstraintOrRewriteDecl(
239faf42264SRiver Riddle       ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
240faf42264SRiver Riddle       StringRef anonymousNamePrefix, bool isInline);
241faf42264SRiver Riddle 
242faf42264SRiver Riddle   /// Parse a native (i.e. non-PDLL) UserConstraintDecl or UserRewriteDecl.
243faf42264SRiver Riddle   /// These decls have effectively the same syntax.
244faf42264SRiver Riddle   template <typename T>
245faf42264SRiver Riddle   FailureOr<T *> parseUserNativeConstraintOrRewriteDecl(
246faf42264SRiver Riddle       const ast::Name &name, bool isInline,
247faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments,
248faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
249faf42264SRiver Riddle 
250faf42264SRiver Riddle   /// Parse the functional signature (i.e. the arguments and results) of a
251faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
252faf42264SRiver Riddle   LogicalResult parseUserConstraintOrRewriteSignature(
253faf42264SRiver Riddle       SmallVectorImpl<ast::VariableDecl *> &arguments,
254faf42264SRiver Riddle       SmallVectorImpl<ast::VariableDecl *> &results,
255faf42264SRiver Riddle       ast::DeclScope *&argumentScope, ast::Type &resultType);
256faf42264SRiver Riddle 
257faf42264SRiver Riddle   /// Validate the return (which if present is specified by bodyIt) of a
258faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
259faf42264SRiver Riddle   LogicalResult validateUserConstraintOrRewriteReturn(
260faf42264SRiver Riddle       StringRef declType, ast::CompoundStmt *body,
261faf42264SRiver Riddle       ArrayRef<ast::Stmt *>::iterator bodyIt,
262faf42264SRiver Riddle       ArrayRef<ast::Stmt *>::iterator bodyE,
263faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type &resultType);
264faf42264SRiver Riddle 
2653d8b9060SRiver Riddle   FailureOr<ast::CompoundStmt *>
2663d8b9060SRiver Riddle   parseLambdaBody(function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
2673d8b9060SRiver Riddle                   bool expectTerminalSemicolon = true);
2683d8b9060SRiver Riddle   FailureOr<ast::CompoundStmt *> parsePatternLambdaBody();
26911d26bd1SRiver Riddle   FailureOr<ast::Decl *> parsePatternDecl();
270322691abSRiver Riddle   LogicalResult parsePatternDeclMetadata(ParsedPatternMetadata &metadata);
27111d26bd1SRiver Riddle 
27211d26bd1SRiver Riddle   /// Check to see if a decl has already been defined with the given name, if
27311d26bd1SRiver Riddle   /// one has emit and error and return failure. Returns success otherwise.
27411d26bd1SRiver Riddle   LogicalResult checkDefineNamedDecl(const ast::Name &name);
27511d26bd1SRiver Riddle 
27611d26bd1SRiver Riddle   /// Try to define a variable decl with the given components, returns the
27711d26bd1SRiver Riddle   /// variable on success.
27811d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
2796842ec42SRiver Riddle   defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
28011d26bd1SRiver Riddle                      ast::Expr *initExpr,
28111d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
28211d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
2836842ec42SRiver Riddle   defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
28411d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
28511d26bd1SRiver Riddle 
28611d26bd1SRiver Riddle   /// Parse the constraint reference list for a variable decl.
28711d26bd1SRiver Riddle   LogicalResult parseVariableDeclConstraintList(
28811d26bd1SRiver Riddle       SmallVectorImpl<ast::ConstraintRef> &constraints);
28911d26bd1SRiver Riddle 
29011d26bd1SRiver Riddle   /// Parse the expression used within a type constraint, e.g. Attr<type-expr>.
29111d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseTypeConstraintExpr();
29211d26bd1SRiver Riddle 
29311d26bd1SRiver Riddle   /// Try to parse a single reference to a constraint. `typeConstraint` is the
29411d26bd1SRiver Riddle   /// location of a previously parsed type constraint for the entity that will
29511d26bd1SRiver Riddle   /// be constrained by the parsed constraint. `existingConstraints` are any
29611d26bd1SRiver Riddle   /// existing constraints that have already been parsed for the same entity
297faf42264SRiver Riddle   /// that will be constrained by this constraint. `allowInlineTypeConstraints`
298faf42264SRiver Riddle   /// allows the use of inline Type constraints, e.g. `Value<valueType: Type>`.
29911d26bd1SRiver Riddle   FailureOr<ast::ConstraintRef>
3000a81ace0SKazu Hirata   parseConstraint(std::optional<SMRange> &typeConstraint,
301faf42264SRiver Riddle                   ArrayRef<ast::ConstraintRef> existingConstraints,
302b6ec1de7SRiver Riddle                   bool allowInlineTypeConstraints);
303faf42264SRiver Riddle 
304faf42264SRiver Riddle   /// Try to parse the constraint for a UserConstraintDecl/UserRewriteDecl
305faf42264SRiver Riddle   /// argument or result variable. The constraints for these variables do not
306faf42264SRiver Riddle   /// allow inline type constraints, and only permit a single constraint.
307faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> parseArgOrResultConstraint();
30811d26bd1SRiver Riddle 
30911d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
31011d26bd1SRiver Riddle   // Exprs
31111d26bd1SRiver Riddle 
31211d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseExpr();
31311d26bd1SRiver Riddle 
31411d26bd1SRiver Riddle   /// Identifier expressions.
315d7e7fdf3SRiver Riddle   FailureOr<ast::Expr *> parseAttributeExpr();
316930916c7SMogball   FailureOr<ast::Expr *> parseCallExpr(ast::Expr *parentExpr,
317930916c7SMogball                                        bool isNegated = false);
3186842ec42SRiver Riddle   FailureOr<ast::Expr *> parseDeclRefExpr(StringRef name, SMRange loc);
31911d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseIdentifierExpr();
320faf42264SRiver Riddle   FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr();
321faf42264SRiver Riddle   FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr();
32211d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseMemberAccessExpr(ast::Expr *parentExpr);
323930916c7SMogball   FailureOr<ast::Expr *> parseNegatedExpr();
32412eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> parseOperationName(bool allowEmptyName = false);
32512eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> parseWrappedOperationName(bool allowEmptyName);
32691b8d96fSRiver Riddle   FailureOr<ast::Expr *>
32791b8d96fSRiver Riddle   parseOperationExpr(OpResultTypeContext inputResultTypeContext =
32891b8d96fSRiver Riddle                          OpResultTypeContext::Explicit);
329f62a57a3SRiver Riddle   FailureOr<ast::Expr *> parseTupleExpr();
330d7e7fdf3SRiver Riddle   FailureOr<ast::Expr *> parseTypeExpr();
33111d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseUnderscoreExpr();
33211d26bd1SRiver Riddle 
33311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
33411d26bd1SRiver Riddle   // Stmts
33511d26bd1SRiver Riddle 
33611d26bd1SRiver Riddle   FailureOr<ast::Stmt *> parseStmt(bool expectTerminalSemicolon = true);
33711d26bd1SRiver Riddle   FailureOr<ast::CompoundStmt *> parseCompoundStmt();
33811d26bd1SRiver Riddle   FailureOr<ast::EraseStmt *> parseEraseStmt();
33911d26bd1SRiver Riddle   FailureOr<ast::LetStmt *> parseLetStmt();
34012eebb8eSRiver Riddle   FailureOr<ast::ReplaceStmt *> parseReplaceStmt();
341faf42264SRiver Riddle   FailureOr<ast::ReturnStmt *> parseReturnStmt();
3423ee44cb7SRiver Riddle   FailureOr<ast::RewriteStmt *> parseRewriteStmt();
34311d26bd1SRiver Riddle 
34411d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34511d26bd1SRiver Riddle   // Creation+Analysis
34611d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34711d26bd1SRiver Riddle 
34811d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34911d26bd1SRiver Riddle   // Decls
35011d26bd1SRiver Riddle 
351faf42264SRiver Riddle   /// Try to extract a callable from the given AST node. Returns nullptr on
352faf42264SRiver Riddle   /// failure.
353faf42264SRiver Riddle   ast::CallableDecl *tryExtractCallableDecl(ast::Node *node);
354faf42264SRiver Riddle 
35511d26bd1SRiver Riddle   /// Try to create a pattern decl with the given components, returning the
35611d26bd1SRiver Riddle   /// Pattern on success.
357322691abSRiver Riddle   FailureOr<ast::PatternDecl *>
3586842ec42SRiver Riddle   createPatternDecl(SMRange loc, const ast::Name *name,
359322691abSRiver Riddle                     const ParsedPatternMetadata &metadata,
36011d26bd1SRiver Riddle                     ast::CompoundStmt *body);
36111d26bd1SRiver Riddle 
362faf42264SRiver Riddle   /// Build the result type for a UserConstraintDecl/UserRewriteDecl given a set
363faf42264SRiver Riddle   /// of results, defined as part of the signature.
364faf42264SRiver Riddle   ast::Type
365faf42264SRiver Riddle   createUserConstraintRewriteResultType(ArrayRef<ast::VariableDecl *> results);
366faf42264SRiver Riddle 
367faf42264SRiver Riddle   /// Create a PDLL (i.e. non-native) UserConstraintDecl or UserRewriteDecl.
368faf42264SRiver Riddle   template <typename T>
369faf42264SRiver Riddle   FailureOr<T *> createUserPDLLConstraintOrRewriteDecl(
370faf42264SRiver Riddle       const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
371faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
372faf42264SRiver Riddle       ast::CompoundStmt *body);
373faf42264SRiver Riddle 
37411d26bd1SRiver Riddle   /// Try to create a variable decl with the given components, returning the
37511d26bd1SRiver Riddle   /// Variable on success.
37611d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
3776842ec42SRiver Riddle   createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
37811d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
37911d26bd1SRiver Riddle 
380faf42264SRiver Riddle   /// Create a variable for an argument or result defined as part of the
381faf42264SRiver Riddle   /// signature of a UserConstraintDecl/UserRewriteDecl.
382faf42264SRiver Riddle   FailureOr<ast::VariableDecl *>
383faf42264SRiver Riddle   createArgOrResultVariableDecl(StringRef name, SMRange loc,
384faf42264SRiver Riddle                                 const ast::ConstraintRef &constraint);
385faf42264SRiver Riddle 
38611d26bd1SRiver Riddle   /// Validate the constraints used to constraint a variable decl.
38711d26bd1SRiver Riddle   /// `inferredType` is the type of the variable inferred by the constraints
38811d26bd1SRiver Riddle   /// within the list, and is updated to the most refined type as determined by
38911d26bd1SRiver Riddle   /// the constraints. Returns success if the constraint list is valid, failure
390b6ec1de7SRiver Riddle   /// otherwise.
39111d26bd1SRiver Riddle   LogicalResult
39211d26bd1SRiver Riddle   validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
393b6ec1de7SRiver Riddle                               ast::Type &inferredType);
39411d26bd1SRiver Riddle   /// Validate a single reference to a constraint. `inferredType` contains the
39511d26bd1SRiver Riddle   /// currently inferred variabled type and is refined within the type defined
39611d26bd1SRiver Riddle   /// by the constraint. Returns success if the constraint is valid, failure
397b6ec1de7SRiver Riddle   /// otherwise.
39811d26bd1SRiver Riddle   LogicalResult validateVariableConstraint(const ast::ConstraintRef &ref,
399b6ec1de7SRiver Riddle                                            ast::Type &inferredType);
40011d26bd1SRiver Riddle   LogicalResult validateTypeConstraintExpr(const ast::Expr *typeExpr);
40111d26bd1SRiver Riddle   LogicalResult validateTypeRangeConstraintExpr(const ast::Expr *typeExpr);
40211d26bd1SRiver Riddle 
40311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
40411d26bd1SRiver Riddle   // Exprs
40511d26bd1SRiver Riddle 
406faf42264SRiver Riddle   FailureOr<ast::CallExpr *>
407faf42264SRiver Riddle   createCallExpr(SMRange loc, ast::Expr *parentExpr,
408930916c7SMogball                  MutableArrayRef<ast::Expr *> arguments,
409930916c7SMogball                  bool isNegated = false);
410faf42264SRiver Riddle   FailureOr<ast::DeclRefExpr *> createDeclRefExpr(SMRange loc, ast::Decl *decl);
41111d26bd1SRiver Riddle   FailureOr<ast::DeclRefExpr *>
4126842ec42SRiver Riddle   createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
41311d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints);
41411d26bd1SRiver Riddle   FailureOr<ast::MemberAccessExpr *>
415faf42264SRiver Riddle   createMemberAccessExpr(ast::Expr *parentExpr, StringRef name, SMRange loc);
41611d26bd1SRiver Riddle 
41711d26bd1SRiver Riddle   /// Validate the member access `name` into the given parent expression. On
41811d26bd1SRiver Riddle   /// success, this also returns the type of the member accessed.
41911d26bd1SRiver Riddle   FailureOr<ast::Type> validateMemberAccess(ast::Expr *parentExpr,
4206842ec42SRiver Riddle                                             StringRef name, SMRange loc);
42102670c3fSRiver Riddle   FailureOr<ast::OperationExpr *>
4226842ec42SRiver Riddle   createOperationExpr(SMRange loc, const ast::OpNameDecl *name,
42391b8d96fSRiver Riddle                       OpResultTypeContext resultTypeContext,
424ec92a125SRiver Riddle                       SmallVectorImpl<ast::Expr *> &operands,
42502670c3fSRiver Riddle                       MutableArrayRef<ast::NamedAttributeDecl *> attributes,
426ec92a125SRiver Riddle                       SmallVectorImpl<ast::Expr *> &results);
42702670c3fSRiver Riddle   LogicalResult
4280a81ace0SKazu Hirata   validateOperationOperands(SMRange loc, std::optional<StringRef> name,
42981f2f4dfSRiver Riddle                             const ods::Operation *odsOp,
430ec92a125SRiver Riddle                             SmallVectorImpl<ast::Expr *> &operands);
4310a81ace0SKazu Hirata   LogicalResult validateOperationResults(SMRange loc,
4320a81ace0SKazu Hirata                                          std::optional<StringRef> name,
43381f2f4dfSRiver Riddle                                          const ods::Operation *odsOp,
434ec92a125SRiver Riddle                                          SmallVectorImpl<ast::Expr *> &results);
43591b8d96fSRiver Riddle   void checkOperationResultTypeInferrence(SMRange loc, StringRef name,
43691b8d96fSRiver Riddle                                           const ods::Operation *odsOp);
43781f2f4dfSRiver Riddle   LogicalResult validateOperationOperandsOrResults(
4380a81ace0SKazu Hirata       StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
4390a81ace0SKazu Hirata       std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
44081f2f4dfSRiver Riddle       ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
441ec92a125SRiver Riddle       ast::RangeType rangeTy);
4426842ec42SRiver Riddle   FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc,
443f62a57a3SRiver Riddle                                               ArrayRef<ast::Expr *> elements,
444f62a57a3SRiver Riddle                                               ArrayRef<StringRef> elementNames);
44511d26bd1SRiver Riddle 
44611d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
44711d26bd1SRiver Riddle   // Stmts
44811d26bd1SRiver Riddle 
449faf42264SRiver Riddle   FailureOr<ast::EraseStmt *> createEraseStmt(SMRange loc, ast::Expr *rootOp);
45012eebb8eSRiver Riddle   FailureOr<ast::ReplaceStmt *>
4516842ec42SRiver Riddle   createReplaceStmt(SMRange loc, ast::Expr *rootOp,
45212eebb8eSRiver Riddle                     MutableArrayRef<ast::Expr *> replValues);
4533ee44cb7SRiver Riddle   FailureOr<ast::RewriteStmt *>
4546842ec42SRiver Riddle   createRewriteStmt(SMRange loc, ast::Expr *rootOp,
4553ee44cb7SRiver Riddle                     ast::CompoundStmt *rewriteBody);
45611d26bd1SRiver Riddle 
45711d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
458008de486SRiver Riddle   // Code Completion
459008de486SRiver Riddle   //===--------------------------------------------------------------------===//
460008de486SRiver Riddle 
461008de486SRiver Riddle   /// The set of various code completion methods. Every completion method
462008de486SRiver Riddle   /// returns `failure` to stop the parsing process after providing completion
463008de486SRiver Riddle   /// results.
464008de486SRiver Riddle 
465008de486SRiver Riddle   LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr);
4660a81ace0SKazu Hirata   LogicalResult codeCompleteAttributeName(std::optional<StringRef> opName);
467008de486SRiver Riddle   LogicalResult codeCompleteConstraintName(ast::Type inferredType,
468008de486SRiver Riddle                                            bool allowInlineTypeConstraints);
469008de486SRiver Riddle   LogicalResult codeCompleteDialectName();
470008de486SRiver Riddle   LogicalResult codeCompleteOperationName(StringRef dialectName);
471008de486SRiver Riddle   LogicalResult codeCompletePatternMetadata();
47241d2c6dfSRiver Riddle   LogicalResult codeCompleteIncludeFilename(StringRef curPath);
473008de486SRiver Riddle 
474469c5894SRiver Riddle   void codeCompleteCallSignature(ast::Node *parent, unsigned currentNumArgs);
4750a81ace0SKazu Hirata   void codeCompleteOperationOperandsSignature(std::optional<StringRef> opName,
476469c5894SRiver Riddle                                               unsigned currentNumOperands);
4770a81ace0SKazu Hirata   void codeCompleteOperationResultsSignature(std::optional<StringRef> opName,
478469c5894SRiver Riddle                                              unsigned currentNumResults);
479469c5894SRiver Riddle 
480008de486SRiver Riddle   //===--------------------------------------------------------------------===//
48111d26bd1SRiver Riddle   // Lexer Utilities
48211d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
48311d26bd1SRiver Riddle 
48411d26bd1SRiver Riddle   /// If the current token has the specified kind, consume it and return true.
48511d26bd1SRiver Riddle   /// If not, return false.
48611d26bd1SRiver Riddle   bool consumeIf(Token::Kind kind) {
48711d26bd1SRiver Riddle     if (curToken.isNot(kind))
48811d26bd1SRiver Riddle       return false;
48911d26bd1SRiver Riddle     consumeToken(kind);
49011d26bd1SRiver Riddle     return true;
49111d26bd1SRiver Riddle   }
49211d26bd1SRiver Riddle 
49311d26bd1SRiver Riddle   /// Advance the current lexer onto the next token.
49411d26bd1SRiver Riddle   void consumeToken() {
49511d26bd1SRiver Riddle     assert(curToken.isNot(Token::eof, Token::error) &&
49611d26bd1SRiver Riddle            "shouldn't advance past EOF or errors");
49711d26bd1SRiver Riddle     curToken = lexer.lexToken();
49811d26bd1SRiver Riddle   }
49911d26bd1SRiver Riddle 
50011d26bd1SRiver Riddle   /// Advance the current lexer onto the next token, asserting what the expected
50111d26bd1SRiver Riddle   /// current token is. This is preferred to the above method because it leads
50211d26bd1SRiver Riddle   /// to more self-documenting code with better checking.
50311d26bd1SRiver Riddle   void consumeToken(Token::Kind kind) {
50411d26bd1SRiver Riddle     assert(curToken.is(kind) && "consumed an unexpected token");
50511d26bd1SRiver Riddle     consumeToken();
50611d26bd1SRiver Riddle   }
50711d26bd1SRiver Riddle 
508d7e7fdf3SRiver Riddle   /// Reset the lexer to the location at the given position.
5096842ec42SRiver Riddle   void resetToken(SMRange tokLoc) {
510d7e7fdf3SRiver Riddle     lexer.resetPointer(tokLoc.Start.getPointer());
511d7e7fdf3SRiver Riddle     curToken = lexer.lexToken();
512d7e7fdf3SRiver Riddle   }
513d7e7fdf3SRiver Riddle 
51411d26bd1SRiver Riddle   /// Consume the specified token if present and return success. On failure,
51511d26bd1SRiver Riddle   /// output a diagnostic and return failure.
51611d26bd1SRiver Riddle   LogicalResult parseToken(Token::Kind kind, const Twine &msg) {
51711d26bd1SRiver Riddle     if (curToken.getKind() != kind)
51811d26bd1SRiver Riddle       return emitError(curToken.getLoc(), msg);
51911d26bd1SRiver Riddle     consumeToken();
52011d26bd1SRiver Riddle     return success();
52111d26bd1SRiver Riddle   }
5226842ec42SRiver Riddle   LogicalResult emitError(SMRange loc, const Twine &msg) {
52311d26bd1SRiver Riddle     lexer.emitError(loc, msg);
52411d26bd1SRiver Riddle     return failure();
52511d26bd1SRiver Riddle   }
52611d26bd1SRiver Riddle   LogicalResult emitError(const Twine &msg) {
52711d26bd1SRiver Riddle     return emitError(curToken.getLoc(), msg);
52811d26bd1SRiver Riddle   }
529faf42264SRiver Riddle   LogicalResult emitErrorAndNote(SMRange loc, const Twine &msg, SMRange noteLoc,
530faf42264SRiver Riddle                                  const Twine &note) {
53111d26bd1SRiver Riddle     lexer.emitErrorAndNote(loc, msg, noteLoc, note);
53211d26bd1SRiver Riddle     return failure();
53311d26bd1SRiver Riddle   }
53411d26bd1SRiver Riddle 
53511d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
53611d26bd1SRiver Riddle   // Fields
53711d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
53811d26bd1SRiver Riddle 
53911d26bd1SRiver Riddle   /// The owning AST context.
54011d26bd1SRiver Riddle   ast::Context &ctx;
54111d26bd1SRiver Riddle 
54211d26bd1SRiver Riddle   /// The lexer of this parser.
54311d26bd1SRiver Riddle   Lexer lexer;
54411d26bd1SRiver Riddle 
54511d26bd1SRiver Riddle   /// The current token within the lexer.
54611d26bd1SRiver Riddle   Token curToken;
54711d26bd1SRiver Riddle 
548bf352e0bSRiver Riddle   /// A flag indicating if the parser should add documentation to AST nodes when
549bf352e0bSRiver Riddle   /// viable.
550bf352e0bSRiver Riddle   bool enableDocumentation;
551bf352e0bSRiver Riddle 
55211d26bd1SRiver Riddle   /// The most recently defined decl scope.
553671e30a1SMehdi Amini   ast::DeclScope *curDeclScope = nullptr;
55411d26bd1SRiver Riddle   llvm::SpecificBumpPtrAllocator<ast::DeclScope> scopeAllocator;
55511d26bd1SRiver Riddle 
55611d26bd1SRiver Riddle   /// The current context of the parser.
55711d26bd1SRiver Riddle   ParserContext parserContext = ParserContext::Global;
55811d26bd1SRiver Riddle 
55911d26bd1SRiver Riddle   /// Cached types to simplify verification and expression creation.
5609e57210aSRiver Riddle   ast::Type typeTy, valueTy;
5619e57210aSRiver Riddle   ast::RangeType typeRangeTy, valueRangeTy;
56281f2f4dfSRiver Riddle   ast::Type attrTy;
563faf42264SRiver Riddle 
564faf42264SRiver Riddle   /// A counter used when naming anonymous constraints and rewrites.
565faf42264SRiver Riddle   unsigned anonymousDeclNameCounter = 0;
566008de486SRiver Riddle 
567008de486SRiver Riddle   /// The optional code completion context.
568008de486SRiver Riddle   CodeCompleteContext *codeCompleteContext;
56911d26bd1SRiver Riddle };
57011d26bd1SRiver Riddle } // namespace
57111d26bd1SRiver Riddle 
57211d26bd1SRiver Riddle FailureOr<ast::Module *> Parser::parseModule() {
5736842ec42SRiver Riddle   SMLoc moduleLoc = curToken.getStartLoc();
57411d26bd1SRiver Riddle   pushDeclScope();
57511d26bd1SRiver Riddle 
57611d26bd1SRiver Riddle   // Parse the top-level decls of the module.
57711d26bd1SRiver Riddle   SmallVector<ast::Decl *> decls;
57811d26bd1SRiver Riddle   if (failed(parseModuleBody(decls)))
57911d26bd1SRiver Riddle     return popDeclScope(), failure();
58011d26bd1SRiver Riddle 
58111d26bd1SRiver Riddle   popDeclScope();
58211d26bd1SRiver Riddle   return ast::Module::create(ctx, moduleLoc, decls);
58311d26bd1SRiver Riddle }
58411d26bd1SRiver Riddle 
58581f2f4dfSRiver Riddle LogicalResult Parser::parseModuleBody(SmallVectorImpl<ast::Decl *> &decls) {
58611d26bd1SRiver Riddle   while (curToken.isNot(Token::eof)) {
58711d26bd1SRiver Riddle     if (curToken.is(Token::directive)) {
58811d26bd1SRiver Riddle       if (failed(parseDirective(decls)))
58911d26bd1SRiver Riddle         return failure();
59011d26bd1SRiver Riddle       continue;
59111d26bd1SRiver Riddle     }
59211d26bd1SRiver Riddle 
59311d26bd1SRiver Riddle     FailureOr<ast::Decl *> decl = parseTopLevelDecl();
59411d26bd1SRiver Riddle     if (failed(decl))
59511d26bd1SRiver Riddle       return failure();
59611d26bd1SRiver Riddle     decls.push_back(*decl);
59711d26bd1SRiver Riddle   }
59811d26bd1SRiver Riddle   return success();
59911d26bd1SRiver Riddle }
60011d26bd1SRiver Riddle 
60102670c3fSRiver Riddle ast::Expr *Parser::convertOpToValue(const ast::Expr *opExpr) {
60202670c3fSRiver Riddle   return ast::AllResultsMemberAccessExpr::create(ctx, opExpr->getLoc(), opExpr,
60302670c3fSRiver Riddle                                                  valueRangeTy);
60402670c3fSRiver Riddle }
60502670c3fSRiver Riddle 
60611d26bd1SRiver Riddle LogicalResult Parser::convertExpressionTo(
60711d26bd1SRiver Riddle     ast::Expr *&expr, ast::Type type,
60811d26bd1SRiver Riddle     function_ref<void(ast::Diagnostic &diag)> noteAttachFn) {
60911d26bd1SRiver Riddle   ast::Type exprType = expr->getType();
61011d26bd1SRiver Riddle   if (exprType == type)
61111d26bd1SRiver Riddle     return success();
61211d26bd1SRiver Riddle 
61311d26bd1SRiver Riddle   auto emitConvertError = [&]() -> ast::InFlightDiagnostic {
61411d26bd1SRiver Riddle     ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitError(
61511d26bd1SRiver Riddle         expr->getLoc(), llvm::formatv("unable to convert expression of type "
61611d26bd1SRiver Riddle                                       "`{0}` to the expected type of "
61711d26bd1SRiver Riddle                                       "`{1}`",
61811d26bd1SRiver Riddle                                       exprType, type));
61911d26bd1SRiver Riddle     if (noteAttachFn)
62011d26bd1SRiver Riddle       noteAttachFn(*diag);
62111d26bd1SRiver Riddle     return diag;
62211d26bd1SRiver Riddle   };
62311d26bd1SRiver Riddle 
624d2353695SPeiming Liu   if (auto exprOpType = dyn_cast<ast::OperationType>(exprType))
6259e57210aSRiver Riddle     return convertOpExpressionTo(expr, exprOpType, type, emitConvertError);
6269e57210aSRiver Riddle 
6279e57210aSRiver Riddle   // FIXME: Decide how to allow/support converting a single result to multiple,
6289e57210aSRiver Riddle   // and multiple to a single result. For now, we just allow Single->Range,
6299e57210aSRiver Riddle   // but this isn't something really supported in the PDL dialect. We should
6309e57210aSRiver Riddle   // figure out some way to support both.
6319e57210aSRiver Riddle   if ((exprType == valueTy || exprType == valueRangeTy) &&
6329e57210aSRiver Riddle       (type == valueTy || type == valueRangeTy))
6339e57210aSRiver Riddle     return success();
6349e57210aSRiver Riddle   if ((exprType == typeTy || exprType == typeRangeTy) &&
6359e57210aSRiver Riddle       (type == typeTy || type == typeRangeTy))
6369e57210aSRiver Riddle     return success();
6379e57210aSRiver Riddle 
6389e57210aSRiver Riddle   // Handle tuple types.
639d2353695SPeiming Liu   if (auto exprTupleType = dyn_cast<ast::TupleType>(exprType))
6409e57210aSRiver Riddle     return convertTupleExpressionTo(expr, exprTupleType, type, emitConvertError,
6419e57210aSRiver Riddle                                     noteAttachFn);
6429e57210aSRiver Riddle 
6439e57210aSRiver Riddle   return emitConvertError();
6449e57210aSRiver Riddle }
6459e57210aSRiver Riddle 
6469e57210aSRiver Riddle LogicalResult Parser::convertOpExpressionTo(
6479e57210aSRiver Riddle     ast::Expr *&expr, ast::OperationType exprType, ast::Type type,
6489e57210aSRiver Riddle     function_ref<ast::InFlightDiagnostic()> emitErrorFn) {
64911d26bd1SRiver Riddle   // Two operation types are compatible if they have the same name, or if the
65011d26bd1SRiver Riddle   // expected type is more general.
651d2353695SPeiming Liu   if (auto opType = dyn_cast<ast::OperationType>(type)) {
65211d26bd1SRiver Riddle     if (opType.getName())
6539e57210aSRiver Riddle       return emitErrorFn();
65411d26bd1SRiver Riddle     return success();
65511d26bd1SRiver Riddle   }
65611d26bd1SRiver Riddle 
65711d26bd1SRiver Riddle   // An operation can always convert to a ValueRange.
65811d26bd1SRiver Riddle   if (type == valueRangeTy) {
65902670c3fSRiver Riddle     expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr,
66002670c3fSRiver Riddle                                                    valueRangeTy);
66111d26bd1SRiver Riddle     return success();
66211d26bd1SRiver Riddle   }
66311d26bd1SRiver Riddle 
66411d26bd1SRiver Riddle   // Allow conversion to a single value by constraining the result range.
66511d26bd1SRiver Riddle   if (type == valueTy) {
66681f2f4dfSRiver Riddle     // If the operation is registered, we can verify if it can ever have a
66781f2f4dfSRiver Riddle     // single result.
6689e57210aSRiver Riddle     if (const ods::Operation *odsOp = exprType.getODSOperation()) {
66981f2f4dfSRiver Riddle       if (odsOp->getResults().empty()) {
6709e57210aSRiver Riddle         return emitErrorFn()->attachNote(
67181f2f4dfSRiver Riddle             llvm::formatv("see the definition of `{0}`, which was defined "
67281f2f4dfSRiver Riddle                           "with zero results",
67381f2f4dfSRiver Riddle                           odsOp->getName()),
67481f2f4dfSRiver Riddle             odsOp->getLoc());
67581f2f4dfSRiver Riddle       }
67681f2f4dfSRiver Riddle 
67781f2f4dfSRiver Riddle       unsigned numSingleResults = llvm::count_if(
67881f2f4dfSRiver Riddle           odsOp->getResults(), [](const ods::OperandOrResult &result) {
67981f2f4dfSRiver Riddle             return result.getVariableLengthKind() ==
68081f2f4dfSRiver Riddle                    ods::VariableLengthKind::Single;
68181f2f4dfSRiver Riddle           });
68281f2f4dfSRiver Riddle       if (numSingleResults > 1) {
6839e57210aSRiver Riddle         return emitErrorFn()->attachNote(
68481f2f4dfSRiver Riddle             llvm::formatv("see the definition of `{0}`, which was defined "
68581f2f4dfSRiver Riddle                           "with at least {1} results",
68681f2f4dfSRiver Riddle                           odsOp->getName(), numSingleResults),
68781f2f4dfSRiver Riddle             odsOp->getLoc());
68881f2f4dfSRiver Riddle       }
68981f2f4dfSRiver Riddle     }
69081f2f4dfSRiver Riddle 
69102670c3fSRiver Riddle     expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr,
69202670c3fSRiver Riddle                                                    valueTy);
69311d26bd1SRiver Riddle     return success();
69411d26bd1SRiver Riddle   }
6959e57210aSRiver Riddle   return emitErrorFn();
69611d26bd1SRiver Riddle }
69711d26bd1SRiver Riddle 
6989e57210aSRiver Riddle LogicalResult Parser::convertTupleExpressionTo(
6999e57210aSRiver Riddle     ast::Expr *&expr, ast::TupleType exprType, ast::Type type,
7009e57210aSRiver Riddle     function_ref<ast::InFlightDiagnostic()> emitErrorFn,
7019e57210aSRiver Riddle     function_ref<void(ast::Diagnostic &diag)> noteAttachFn) {
7029e57210aSRiver Riddle   // Handle conversions between tuples.
703d2353695SPeiming Liu   if (auto tupleType = dyn_cast<ast::TupleType>(type)) {
7049e57210aSRiver Riddle     if (tupleType.size() != exprType.size())
7059e57210aSRiver Riddle       return emitErrorFn();
706f62a57a3SRiver Riddle 
707f62a57a3SRiver Riddle     // Build a new tuple expression using each of the elements of the current
708f62a57a3SRiver Riddle     // tuple.
709f62a57a3SRiver Riddle     SmallVector<ast::Expr *> newExprs;
7109e57210aSRiver Riddle     for (unsigned i = 0, e = exprType.size(); i < e; ++i) {
711f62a57a3SRiver Riddle       newExprs.push_back(ast::MemberAccessExpr::create(
712f62a57a3SRiver Riddle           ctx, expr->getLoc(), expr, llvm::to_string(i),
7139e57210aSRiver Riddle           exprType.getElementTypes()[i]));
714f62a57a3SRiver Riddle 
715f62a57a3SRiver Riddle       auto diagFn = [&](ast::Diagnostic &diag) {
716f62a57a3SRiver Riddle         diag.attachNote(llvm::formatv("when converting element #{0} of `{1}`",
7179e57210aSRiver Riddle                                       i, exprType));
718f62a57a3SRiver Riddle         if (noteAttachFn)
719f62a57a3SRiver Riddle           noteAttachFn(diag);
720f62a57a3SRiver Riddle       };
721f62a57a3SRiver Riddle       if (failed(convertExpressionTo(newExprs.back(),
722f62a57a3SRiver Riddle                                      tupleType.getElementTypes()[i], diagFn)))
723f62a57a3SRiver Riddle         return failure();
724f62a57a3SRiver Riddle     }
725f62a57a3SRiver Riddle     expr = ast::TupleExpr::create(ctx, expr->getLoc(), newExprs,
726f62a57a3SRiver Riddle                                   tupleType.getElementNames());
727f62a57a3SRiver Riddle     return success();
728f62a57a3SRiver Riddle   }
729f62a57a3SRiver Riddle 
7309e57210aSRiver Riddle   // Handle conversion to a range.
7319e57210aSRiver Riddle   auto convertToRange = [&](ArrayRef<ast::Type> allowedElementTypes,
7329e57210aSRiver Riddle                             ast::RangeType resultTy) -> LogicalResult {
7339e57210aSRiver Riddle     // TODO: We currently only allow range conversion within a rewrite context.
7349e57210aSRiver Riddle     if (parserContext != ParserContext::Rewrite) {
7359e57210aSRiver Riddle       return emitErrorFn()->attachNote("Tuple to Range conversion is currently "
7369e57210aSRiver Riddle                                        "only allowed within a rewrite context");
7379e57210aSRiver Riddle     }
7389e57210aSRiver Riddle 
7399e57210aSRiver Riddle     // All of the tuple elements must be allowed types.
7409e57210aSRiver Riddle     for (ast::Type elementType : exprType.getElementTypes())
7419e57210aSRiver Riddle       if (!llvm::is_contained(allowedElementTypes, elementType))
7429e57210aSRiver Riddle         return emitErrorFn();
7439e57210aSRiver Riddle 
7449e57210aSRiver Riddle     // Build a new tuple expression using each of the elements of the current
7459e57210aSRiver Riddle     // tuple.
7469e57210aSRiver Riddle     SmallVector<ast::Expr *> newExprs;
7479e57210aSRiver Riddle     for (unsigned i = 0, e = exprType.size(); i < e; ++i) {
7489e57210aSRiver Riddle       newExprs.push_back(ast::MemberAccessExpr::create(
7499e57210aSRiver Riddle           ctx, expr->getLoc(), expr, llvm::to_string(i),
7509e57210aSRiver Riddle           exprType.getElementTypes()[i]));
7519e57210aSRiver Riddle     }
7529e57210aSRiver Riddle     expr = ast::RangeExpr::create(ctx, expr->getLoc(), newExprs, resultTy);
7539e57210aSRiver Riddle     return success();
7549e57210aSRiver Riddle   };
7559e57210aSRiver Riddle   if (type == valueRangeTy)
7569e57210aSRiver Riddle     return convertToRange({valueTy, valueRangeTy}, valueRangeTy);
7579e57210aSRiver Riddle   if (type == typeRangeTy)
7589e57210aSRiver Riddle     return convertToRange({typeTy, typeRangeTy}, typeRangeTy);
7599e57210aSRiver Riddle 
7609e57210aSRiver Riddle   return emitErrorFn();
76111d26bd1SRiver Riddle }
76211d26bd1SRiver Riddle 
76311d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
76411d26bd1SRiver Riddle // Directives
76511d26bd1SRiver Riddle 
76681f2f4dfSRiver Riddle LogicalResult Parser::parseDirective(SmallVectorImpl<ast::Decl *> &decls) {
76711d26bd1SRiver Riddle   StringRef directive = curToken.getSpelling();
76811d26bd1SRiver Riddle   if (directive == "#include")
76911d26bd1SRiver Riddle     return parseInclude(decls);
77011d26bd1SRiver Riddle 
77111d26bd1SRiver Riddle   return emitError("unknown directive `" + directive + "`");
77211d26bd1SRiver Riddle }
77311d26bd1SRiver Riddle 
77481f2f4dfSRiver Riddle LogicalResult Parser::parseInclude(SmallVectorImpl<ast::Decl *> &decls) {
7756842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
77611d26bd1SRiver Riddle   consumeToken(Token::directive);
77711d26bd1SRiver Riddle 
77841d2c6dfSRiver Riddle   // Handle code completion of the include file path.
77941d2c6dfSRiver Riddle   if (curToken.is(Token::code_complete_string))
78041d2c6dfSRiver Riddle     return codeCompleteIncludeFilename(curToken.getStringValue());
78141d2c6dfSRiver Riddle 
78211d26bd1SRiver Riddle   // Parse the file being included.
78311d26bd1SRiver Riddle   if (!curToken.isString())
78411d26bd1SRiver Riddle     return emitError(loc,
78511d26bd1SRiver Riddle                      "expected string file name after `include` directive");
7866842ec42SRiver Riddle   SMRange fileLoc = curToken.getLoc();
78711d26bd1SRiver Riddle   std::string filenameStr = curToken.getStringValue();
78811d26bd1SRiver Riddle   StringRef filename = filenameStr;
78911d26bd1SRiver Riddle   consumeToken();
79011d26bd1SRiver Riddle 
79111d26bd1SRiver Riddle   // Check the type of include. If ending with `.pdll`, this is another pdl file
79211d26bd1SRiver Riddle   // to be parsed along with the current module.
79388d319a2SKazu Hirata   if (filename.ends_with(".pdll")) {
79409af7fefSRiver Riddle     if (failed(lexer.pushInclude(filename, fileLoc)))
79511d26bd1SRiver Riddle       return emitError(fileLoc,
79611d26bd1SRiver Riddle                        "unable to open include file `" + filename + "`");
79711d26bd1SRiver Riddle 
79811d26bd1SRiver Riddle     // If we added the include successfully, parse it into the current module.
79909af7fefSRiver Riddle     // Make sure to update to the next token after we finish parsing the nested
80009af7fefSRiver Riddle     // file.
80111d26bd1SRiver Riddle     curToken = lexer.lexToken();
80211d26bd1SRiver Riddle     LogicalResult result = parseModuleBody(decls);
80309af7fefSRiver Riddle     curToken = lexer.lexToken();
80411d26bd1SRiver Riddle     return result;
80511d26bd1SRiver Riddle   }
80611d26bd1SRiver Riddle 
80781f2f4dfSRiver Riddle   // Otherwise, this must be a `.td` include.
80888d319a2SKazu Hirata   if (filename.ends_with(".td"))
80981f2f4dfSRiver Riddle     return parseTdInclude(filename, fileLoc, decls);
81081f2f4dfSRiver Riddle 
81181f2f4dfSRiver Riddle   return emitError(fileLoc,
81281f2f4dfSRiver Riddle                    "expected include filename to end with `.pdll` or `.td`");
81381f2f4dfSRiver Riddle }
81481f2f4dfSRiver Riddle 
81581f2f4dfSRiver Riddle LogicalResult Parser::parseTdInclude(StringRef filename, llvm::SMRange fileLoc,
81681f2f4dfSRiver Riddle                                      SmallVectorImpl<ast::Decl *> &decls) {
81781f2f4dfSRiver Riddle   llvm::SourceMgr &parserSrcMgr = lexer.getSourceMgr();
81881f2f4dfSRiver Riddle 
8195a9a438aSRiver Riddle   // Use the source manager to open the file, but don't yet add it.
8205a9a438aSRiver Riddle   std::string includedFile;
8215a9a438aSRiver Riddle   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> includeBuffer =
8225a9a438aSRiver Riddle       parserSrcMgr.OpenIncludeFile(filename.str(), includedFile);
8235a9a438aSRiver Riddle   if (!includeBuffer)
8245a9a438aSRiver Riddle     return emitError(fileLoc, "unable to open include file `" + filename + "`");
8255a9a438aSRiver Riddle 
8265a9a438aSRiver Riddle   // Setup the source manager for parsing the tablegen file.
8275a9a438aSRiver Riddle   llvm::SourceMgr tdSrcMgr;
8285a9a438aSRiver Riddle   tdSrcMgr.AddNewSourceBuffer(std::move(*includeBuffer), SMLoc());
8295a9a438aSRiver Riddle   tdSrcMgr.setIncludeDirs(parserSrcMgr.getIncludeDirs());
8305a9a438aSRiver Riddle 
83181f2f4dfSRiver Riddle   // This class provides a context argument for the llvm::SourceMgr diagnostic
83281f2f4dfSRiver Riddle   // handler.
83381f2f4dfSRiver Riddle   struct DiagHandlerContext {
83481f2f4dfSRiver Riddle     Parser &parser;
83581f2f4dfSRiver Riddle     StringRef filename;
83681f2f4dfSRiver Riddle     llvm::SMRange loc;
83781f2f4dfSRiver Riddle   } handlerContext{*this, filename, fileLoc};
83881f2f4dfSRiver Riddle 
83981f2f4dfSRiver Riddle   // Set the diagnostic handler for the tablegen source manager.
8405a9a438aSRiver Riddle   tdSrcMgr.setDiagHandler(
84181f2f4dfSRiver Riddle       [](const llvm::SMDiagnostic &diag, void *rawHandlerContext) {
84281f2f4dfSRiver Riddle         auto *ctx = reinterpret_cast<DiagHandlerContext *>(rawHandlerContext);
84381f2f4dfSRiver Riddle         (void)ctx->parser.emitError(
84481f2f4dfSRiver Riddle             ctx->loc,
84581f2f4dfSRiver Riddle             llvm::formatv("error while processing include file `{0}`: {1}",
84681f2f4dfSRiver Riddle                           ctx->filename, diag.getMessage()));
84781f2f4dfSRiver Riddle       },
84881f2f4dfSRiver Riddle       &handlerContext);
84981f2f4dfSRiver Riddle 
8505a9a438aSRiver Riddle   // Parse the tablegen file.
8515a9a438aSRiver Riddle   llvm::RecordKeeper tdRecords;
8525a9a438aSRiver Riddle   if (llvm::TableGenParseFile(tdSrcMgr, tdRecords))
85381f2f4dfSRiver Riddle     return failure();
85481f2f4dfSRiver Riddle 
8555a9a438aSRiver Riddle   // Process the parsed records.
8565a9a438aSRiver Riddle   processTdIncludeRecords(tdRecords, decls);
8575a9a438aSRiver Riddle 
8585a9a438aSRiver Riddle   // After we are done processing, move all of the tablegen source buffers to
8595a9a438aSRiver Riddle   // the main parser source mgr. This allows for directly using source locations
8605a9a438aSRiver Riddle   // from the .td files without needing to remap them.
8615a9a438aSRiver Riddle   parserSrcMgr.takeSourceBuffersFrom(tdSrcMgr, fileLoc.End);
86281f2f4dfSRiver Riddle   return success();
86381f2f4dfSRiver Riddle }
86481f2f4dfSRiver Riddle 
865b60c6cbcSRahul Joshi void Parser::processTdIncludeRecords(const llvm::RecordKeeper &tdRecords,
86681f2f4dfSRiver Riddle                                      SmallVectorImpl<ast::Decl *> &decls) {
86781f2f4dfSRiver Riddle   // Return the length kind of the given value.
86881f2f4dfSRiver Riddle   auto getLengthKind = [](const auto &value) {
86981f2f4dfSRiver Riddle     if (value.isOptional())
87081f2f4dfSRiver Riddle       return ods::VariableLengthKind::Optional;
87181f2f4dfSRiver Riddle     return value.isVariadic() ? ods::VariableLengthKind::Variadic
87281f2f4dfSRiver Riddle                               : ods::VariableLengthKind::Single;
87381f2f4dfSRiver Riddle   };
87481f2f4dfSRiver Riddle 
87581f2f4dfSRiver Riddle   // Insert a type constraint into the ODS context.
87681f2f4dfSRiver Riddle   ods::Context &odsContext = ctx.getODSContext();
87781f2f4dfSRiver Riddle   auto addTypeConstraint = [&](const tblgen::NamedTypeConstraint &cst)
87881f2f4dfSRiver Riddle       -> const ods::TypeConstraint & {
879bf352e0bSRiver Riddle     return odsContext.insertTypeConstraint(
880bf352e0bSRiver Riddle         cst.constraint.getUniqueDefName(),
88135f55f53SMatthias Springer         processDoc(cst.constraint.getSummary()), cst.constraint.getCppType());
88281f2f4dfSRiver Riddle   };
88381f2f4dfSRiver Riddle   auto convertLocToRange = [&](llvm::SMLoc loc) -> llvm::SMRange {
88481f2f4dfSRiver Riddle     return {loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)};
88581f2f4dfSRiver Riddle   };
88681f2f4dfSRiver Riddle 
88781f2f4dfSRiver Riddle   // Process the parsed tablegen records to build ODS information.
88881f2f4dfSRiver Riddle   /// Operations.
889b60c6cbcSRahul Joshi   for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Op")) {
89081f2f4dfSRiver Riddle     tblgen::Operator op(def);
89181f2f4dfSRiver Riddle 
89291b8d96fSRiver Riddle     // Check to see if this operation is known to support type inferrence.
89391b8d96fSRiver Riddle     bool supportsResultTypeInferrence =
89491b8d96fSRiver Riddle         op.getTrait("::mlir::InferTypeOpInterface::Trait");
89591b8d96fSRiver Riddle 
8969fa59e76SBenjamin Kramer     auto [odsOp, inserted] = odsContext.insertOperation(
897bf352e0bSRiver Riddle         op.getOperationName(), processDoc(op.getSummary()),
898bf352e0bSRiver Riddle         processAndFormatDoc(op.getDescription()), op.getQualCppClassName(),
899bf352e0bSRiver Riddle         supportsResultTypeInferrence, op.getLoc().front());
90081f2f4dfSRiver Riddle 
90181f2f4dfSRiver Riddle     // Ignore operations that have already been added.
90281f2f4dfSRiver Riddle     if (!inserted)
90381f2f4dfSRiver Riddle       continue;
90481f2f4dfSRiver Riddle 
90581f2f4dfSRiver Riddle     for (const tblgen::NamedAttribute &attr : op.getAttributes()) {
906bf352e0bSRiver Riddle       odsOp->appendAttribute(attr.name, attr.attr.isOptional(),
907bf352e0bSRiver Riddle                              odsContext.insertAttributeConstraint(
908bf352e0bSRiver Riddle                                  attr.attr.getUniqueDefName(),
909bf352e0bSRiver Riddle                                  processDoc(attr.attr.getSummary()),
91081f2f4dfSRiver Riddle                                  attr.attr.getStorageType()));
91181f2f4dfSRiver Riddle     }
91281f2f4dfSRiver Riddle     for (const tblgen::NamedTypeConstraint &operand : op.getOperands()) {
91381f2f4dfSRiver Riddle       odsOp->appendOperand(operand.name, getLengthKind(operand),
91481f2f4dfSRiver Riddle                            addTypeConstraint(operand));
91581f2f4dfSRiver Riddle     }
91681f2f4dfSRiver Riddle     for (const tblgen::NamedTypeConstraint &result : op.getResults()) {
91781f2f4dfSRiver Riddle       odsOp->appendResult(result.name, getLengthKind(result),
91881f2f4dfSRiver Riddle                           addTypeConstraint(result));
91981f2f4dfSRiver Riddle     }
92081f2f4dfSRiver Riddle   }
9219f186bb1SMarkus Böck 
922b60c6cbcSRahul Joshi   auto shouldBeSkipped = [this](const llvm::Record *def) {
9239f186bb1SMarkus Böck     return def->isAnonymous() || curDeclScope->lookup(def->getName()) ||
9249f186bb1SMarkus Böck            def->isSubClassOf("DeclareInterfaceMethods");
9259f186bb1SMarkus Böck   };
9269f186bb1SMarkus Böck 
92781f2f4dfSRiver Riddle   /// Attr constraints.
928b60c6cbcSRahul Joshi   for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Attr")) {
9299f186bb1SMarkus Böck     if (shouldBeSkipped(def))
9309f186bb1SMarkus Böck       continue;
9319f186bb1SMarkus Böck 
9321c2edb02SRiver Riddle     tblgen::Attribute constraint(def);
9339f186bb1SMarkus Böck     decls.push_back(createODSNativePDLLConstraintDecl<ast::AttrConstraintDecl>(
9341c2edb02SRiver Riddle         constraint, convertLocToRange(def->getLoc().front()), attrTy,
9351c2edb02SRiver Riddle         constraint.getStorageType()));
93681f2f4dfSRiver Riddle   }
93781f2f4dfSRiver Riddle   /// Type constraints.
938b60c6cbcSRahul Joshi   for (const llvm::Record *def : tdRecords.getAllDerivedDefinitions("Type")) {
9399f186bb1SMarkus Böck     if (shouldBeSkipped(def))
9409f186bb1SMarkus Böck       continue;
9419f186bb1SMarkus Böck 
9421c2edb02SRiver Riddle     tblgen::TypeConstraint constraint(def);
9439f186bb1SMarkus Böck     decls.push_back(createODSNativePDLLConstraintDecl<ast::TypeConstraintDecl>(
9441c2edb02SRiver Riddle         constraint, convertLocToRange(def->getLoc().front()), typeTy,
94535f55f53SMatthias Springer         constraint.getCppType()));
94681f2f4dfSRiver Riddle   }
9479f186bb1SMarkus Böck   /// OpInterfaces.
94881f2f4dfSRiver Riddle   ast::Type opTy = ast::OperationType::get(ctx);
949b60c6cbcSRahul Joshi   for (const llvm::Record *def :
950b60c6cbcSRahul Joshi        tdRecords.getAllDerivedDefinitions("OpInterface")) {
9519f186bb1SMarkus Böck     if (shouldBeSkipped(def))
95281f2f4dfSRiver Riddle       continue;
9539f186bb1SMarkus Böck 
95481f2f4dfSRiver Riddle     SMRange loc = convertLocToRange(def->getLoc().front());
95581f2f4dfSRiver Riddle 
9561c2edb02SRiver Riddle     std::string cppClassName =
9571c2edb02SRiver Riddle         llvm::formatv("{0}::{1}", def->getValueAsString("cppNamespace"),
9589f186bb1SMarkus Böck                       def->getValueAsString("cppInterfaceName"))
9591c2edb02SRiver Riddle             .str();
96081f2f4dfSRiver Riddle     std::string codeBlock =
9611c2edb02SRiver Riddle         llvm::formatv("return ::mlir::success(llvm::isa<{0}>(self));",
9621c2edb02SRiver Riddle                       cppClassName)
96381f2f4dfSRiver Riddle             .str();
96481f2f4dfSRiver Riddle 
965bf352e0bSRiver Riddle     std::string desc =
966bf352e0bSRiver Riddle         processAndFormatDoc(def->getValueAsString("description"));
96781f2f4dfSRiver Riddle     decls.push_back(createODSNativePDLLConstraintDecl<ast::OpConstraintDecl>(
9689f186bb1SMarkus Böck         def->getName(), codeBlock, loc, opTy, cppClassName, desc));
96981f2f4dfSRiver Riddle   }
97081f2f4dfSRiver Riddle }
97181f2f4dfSRiver Riddle 
97281f2f4dfSRiver Riddle template <typename ConstraintT>
973bf352e0bSRiver Riddle ast::Decl *Parser::createODSNativePDLLConstraintDecl(
974bf352e0bSRiver Riddle     StringRef name, StringRef codeBlock, SMRange loc, ast::Type type,
975bf352e0bSRiver Riddle     StringRef nativeType, StringRef docString) {
97681f2f4dfSRiver Riddle   // Build the single input parameter.
97781f2f4dfSRiver Riddle   ast::DeclScope *argScope = pushDeclScope();
97881f2f4dfSRiver Riddle   auto *paramVar = ast::VariableDecl::create(
97981f2f4dfSRiver Riddle       ctx, ast::Name::create(ctx, "self", loc), type,
98081f2f4dfSRiver Riddle       /*initExpr=*/nullptr, ast::ConstraintRef(ConstraintT::create(ctx, loc)));
98181f2f4dfSRiver Riddle   argScope->add(paramVar);
98281f2f4dfSRiver Riddle   popDeclScope();
98381f2f4dfSRiver Riddle 
98481f2f4dfSRiver Riddle   // Build the native constraint.
98581f2f4dfSRiver Riddle   auto *constraintDecl = ast::UserConstraintDecl::createNative(
98681f2f4dfSRiver Riddle       ctx, ast::Name::create(ctx, name, loc), paramVar,
9871a36588eSKazu Hirata       /*results=*/std::nullopt, codeBlock, ast::TupleType::get(ctx),
9881a36588eSKazu Hirata       nativeType);
989bf352e0bSRiver Riddle   constraintDecl->setDocComment(ctx, docString);
99081f2f4dfSRiver Riddle   curDeclScope->add(constraintDecl);
99181f2f4dfSRiver Riddle   return constraintDecl;
99281f2f4dfSRiver Riddle }
99381f2f4dfSRiver Riddle 
99481f2f4dfSRiver Riddle template <typename ConstraintT>
99581f2f4dfSRiver Riddle ast::Decl *
99681f2f4dfSRiver Riddle Parser::createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint,
9971c2edb02SRiver Riddle                                           SMRange loc, ast::Type type,
9981c2edb02SRiver Riddle                                           StringRef nativeType) {
99981f2f4dfSRiver Riddle   // Format the condition template.
100081f2f4dfSRiver Riddle   tblgen::FmtContext fmtContext;
100181f2f4dfSRiver Riddle   fmtContext.withSelf("self");
1002651d9f70SRiver Riddle   std::string codeBlock = tblgen::tgfmt(
1003651d9f70SRiver Riddle       "return ::mlir::success(" + constraint.getConditionTemplate() + ");",
1004651d9f70SRiver Riddle       &fmtContext);
100581f2f4dfSRiver Riddle 
1006bf352e0bSRiver Riddle   // If documentation was enabled, build the doc string for the generated
1007bf352e0bSRiver Riddle   // constraint. It would be nice to do this lazily, but TableGen information is
1008bf352e0bSRiver Riddle   // destroyed after we finish parsing the file.
1009bf352e0bSRiver Riddle   std::string docString;
1010bf352e0bSRiver Riddle   if (enableDocumentation) {
1011bf352e0bSRiver Riddle     StringRef desc = constraint.getDescription();
1012bf352e0bSRiver Riddle     docString = processAndFormatDoc(
1013bf352e0bSRiver Riddle         constraint.getSummary() +
1014bf352e0bSRiver Riddle         (desc.empty() ? "" : ("\n\n" + constraint.getDescription())));
1015bf352e0bSRiver Riddle   }
1016bf352e0bSRiver Riddle 
1017b3fc0fa8SRiver Riddle   return createODSNativePDLLConstraintDecl<ConstraintT>(
1018bf352e0bSRiver Riddle       constraint.getUniqueDefName(), codeBlock, loc, type, nativeType,
1019bf352e0bSRiver Riddle       docString);
102011d26bd1SRiver Riddle }
102111d26bd1SRiver Riddle 
102211d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
102311d26bd1SRiver Riddle // Decls
102411d26bd1SRiver Riddle 
102511d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parseTopLevelDecl() {
102611d26bd1SRiver Riddle   FailureOr<ast::Decl *> decl;
102711d26bd1SRiver Riddle   switch (curToken.getKind()) {
1028faf42264SRiver Riddle   case Token::kw_Constraint:
1029faf42264SRiver Riddle     decl = parseUserConstraintDecl();
1030faf42264SRiver Riddle     break;
103111d26bd1SRiver Riddle   case Token::kw_Pattern:
103211d26bd1SRiver Riddle     decl = parsePatternDecl();
103311d26bd1SRiver Riddle     break;
1034faf42264SRiver Riddle   case Token::kw_Rewrite:
1035faf42264SRiver Riddle     decl = parseUserRewriteDecl();
1036faf42264SRiver Riddle     break;
103711d26bd1SRiver Riddle   default:
103811d26bd1SRiver Riddle     return emitError("expected top-level declaration, such as a `Pattern`");
103911d26bd1SRiver Riddle   }
104011d26bd1SRiver Riddle   if (failed(decl))
104111d26bd1SRiver Riddle     return failure();
104211d26bd1SRiver Riddle 
104311d26bd1SRiver Riddle   // If the decl has a name, add it to the current scope.
104411d26bd1SRiver Riddle   if (const ast::Name *name = (*decl)->getName()) {
104511d26bd1SRiver Riddle     if (failed(checkDefineNamedDecl(*name)))
104611d26bd1SRiver Riddle       return failure();
104711d26bd1SRiver Riddle     curDeclScope->add(*decl);
104811d26bd1SRiver Riddle   }
104911d26bd1SRiver Riddle   return decl;
105011d26bd1SRiver Riddle }
105111d26bd1SRiver Riddle 
1052008de486SRiver Riddle FailureOr<ast::NamedAttributeDecl *>
10530a81ace0SKazu Hirata Parser::parseNamedAttributeDecl(std::optional<StringRef> parentOpName) {
1054008de486SRiver Riddle   // Check for name code completion.
1055008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1056008de486SRiver Riddle     return codeCompleteAttributeName(parentOpName);
1057008de486SRiver Riddle 
105802670c3fSRiver Riddle   std::string attrNameStr;
105902670c3fSRiver Riddle   if (curToken.isString())
106002670c3fSRiver Riddle     attrNameStr = curToken.getStringValue();
106102670c3fSRiver Riddle   else if (curToken.is(Token::identifier) || curToken.isKeyword())
106202670c3fSRiver Riddle     attrNameStr = curToken.getSpelling().str();
106302670c3fSRiver Riddle   else
106402670c3fSRiver Riddle     return emitError("expected identifier or string attribute name");
106502670c3fSRiver Riddle   const auto &name = ast::Name::create(ctx, attrNameStr, curToken.getLoc());
106602670c3fSRiver Riddle   consumeToken();
106702670c3fSRiver Riddle 
106802670c3fSRiver Riddle   // Check for a value of the attribute.
106902670c3fSRiver Riddle   ast::Expr *attrValue = nullptr;
107002670c3fSRiver Riddle   if (consumeIf(Token::equal)) {
107102670c3fSRiver Riddle     FailureOr<ast::Expr *> attrExpr = parseExpr();
107202670c3fSRiver Riddle     if (failed(attrExpr))
107302670c3fSRiver Riddle       return failure();
107402670c3fSRiver Riddle     attrValue = *attrExpr;
107502670c3fSRiver Riddle   } else {
107602670c3fSRiver Riddle     // If there isn't a concrete value, create an expression representing a
107702670c3fSRiver Riddle     // UnitAttr.
107802670c3fSRiver Riddle     attrValue = ast::AttributeExpr::create(ctx, name.getLoc(), "unit");
107902670c3fSRiver Riddle   }
108002670c3fSRiver Riddle 
108102670c3fSRiver Riddle   return ast::NamedAttributeDecl::create(ctx, name, attrValue);
108202670c3fSRiver Riddle }
108302670c3fSRiver Riddle 
10843d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseLambdaBody(
10853d8b9060SRiver Riddle     function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
10863d8b9060SRiver Riddle     bool expectTerminalSemicolon) {
10873d8b9060SRiver Riddle   consumeToken(Token::equal_arrow);
10883d8b9060SRiver Riddle 
10893d8b9060SRiver Riddle   // Parse the single statement of the lambda body.
10903d8b9060SRiver Riddle   SMLoc bodyStartLoc = curToken.getStartLoc();
10913d8b9060SRiver Riddle   pushDeclScope();
10923d8b9060SRiver Riddle   FailureOr<ast::Stmt *> singleStatement = parseStmt(expectTerminalSemicolon);
10933d8b9060SRiver Riddle   bool failedToParse =
10943d8b9060SRiver Riddle       failed(singleStatement) || failed(processStatementFn(*singleStatement));
10953d8b9060SRiver Riddle   popDeclScope();
10963d8b9060SRiver Riddle   if (failedToParse)
10973d8b9060SRiver Riddle     return failure();
10983d8b9060SRiver Riddle 
10993d8b9060SRiver Riddle   SMRange bodyLoc(bodyStartLoc, curToken.getStartLoc());
11003d8b9060SRiver Riddle   return ast::CompoundStmt::create(ctx, bodyLoc, *singleStatement);
11013d8b9060SRiver Riddle }
11023d8b9060SRiver Riddle 
1103faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseArgumentDecl() {
1104faf42264SRiver Riddle   // Ensure that the argument is named.
1105faf42264SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword())
1106faf42264SRiver Riddle     return emitError("expected identifier argument name");
1107faf42264SRiver Riddle 
1108faf42264SRiver Riddle   // Parse the argument similarly to a normal variable.
1109faf42264SRiver Riddle   StringRef name = curToken.getSpelling();
1110faf42264SRiver Riddle   SMRange nameLoc = curToken.getLoc();
1111faf42264SRiver Riddle   consumeToken();
1112faf42264SRiver Riddle 
1113faf42264SRiver Riddle   if (failed(
1114faf42264SRiver Riddle           parseToken(Token::colon, "expected `:` before argument constraint")))
1115faf42264SRiver Riddle     return failure();
1116faf42264SRiver Riddle 
1117faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1118faf42264SRiver Riddle   if (failed(cst))
1119faf42264SRiver Riddle     return failure();
1120faf42264SRiver Riddle 
1121faf42264SRiver Riddle   return createArgOrResultVariableDecl(name, nameLoc, *cst);
1122faf42264SRiver Riddle }
1123faf42264SRiver Riddle 
1124faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseResultDecl(unsigned resultNum) {
1125faf42264SRiver Riddle   // Check to see if this result is named.
1126faf42264SRiver Riddle   if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) {
1127faf42264SRiver Riddle     // Check to see if this name actually refers to a Constraint.
1128b6ec1de7SRiver Riddle     if (!curDeclScope->lookup<ast::ConstraintDecl>(curToken.getSpelling())) {
1129faf42264SRiver Riddle       // If it wasn't a constraint, parse the result similarly to a variable. If
1130faf42264SRiver Riddle       // there is already an existing decl, we will emit an error when defining
1131faf42264SRiver Riddle       // this variable later.
1132faf42264SRiver Riddle       StringRef name = curToken.getSpelling();
1133faf42264SRiver Riddle       SMRange nameLoc = curToken.getLoc();
1134faf42264SRiver Riddle       consumeToken();
1135faf42264SRiver Riddle 
1136faf42264SRiver Riddle       if (failed(parseToken(Token::colon,
1137faf42264SRiver Riddle                             "expected `:` before result constraint")))
1138faf42264SRiver Riddle         return failure();
1139faf42264SRiver Riddle 
1140faf42264SRiver Riddle       FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1141faf42264SRiver Riddle       if (failed(cst))
1142faf42264SRiver Riddle         return failure();
1143faf42264SRiver Riddle 
1144faf42264SRiver Riddle       return createArgOrResultVariableDecl(name, nameLoc, *cst);
1145faf42264SRiver Riddle     }
1146faf42264SRiver Riddle   }
1147faf42264SRiver Riddle 
1148faf42264SRiver Riddle   // If it isn't named, we parse the constraint directly and create an unnamed
1149faf42264SRiver Riddle   // result variable.
1150faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1151faf42264SRiver Riddle   if (failed(cst))
1152faf42264SRiver Riddle     return failure();
1153faf42264SRiver Riddle 
1154faf42264SRiver Riddle   return createArgOrResultVariableDecl("", cst->referenceLoc, *cst);
1155faf42264SRiver Riddle }
1156faf42264SRiver Riddle 
1157faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *>
1158faf42264SRiver Riddle Parser::parseUserConstraintDecl(bool isInline) {
1159faf42264SRiver Riddle   // Constraints and rewrites have very similar formats, dispatch to a shared
1160faf42264SRiver Riddle   // interface for parsing.
1161faf42264SRiver Riddle   return parseUserConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1162ceb5dc55SRiver Riddle       [&](auto &&...args) {
1163ceb5dc55SRiver Riddle         return this->parseUserPDLLConstraintDecl(args...);
1164ceb5dc55SRiver Riddle       },
1165faf42264SRiver Riddle       ParserContext::Constraint, "constraint", isInline);
1166faf42264SRiver Riddle }
1167faf42264SRiver Riddle 
1168faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseInlineUserConstraintDecl() {
1169faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> decl =
1170faf42264SRiver Riddle       parseUserConstraintDecl(/*isInline=*/true);
1171faf42264SRiver Riddle   if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName())))
1172faf42264SRiver Riddle     return failure();
1173faf42264SRiver Riddle 
1174faf42264SRiver Riddle   curDeclScope->add(*decl);
1175faf42264SRiver Riddle   return decl;
1176faf42264SRiver Riddle }
1177faf42264SRiver Riddle 
1178faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseUserPDLLConstraintDecl(
1179faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1180faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1181faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1182faf42264SRiver Riddle   // Push the argument scope back onto the list, so that the body can
1183faf42264SRiver Riddle   // reference arguments.
1184faf42264SRiver Riddle   pushDeclScope(argumentScope);
1185faf42264SRiver Riddle 
1186faf42264SRiver Riddle   // Parse the body of the constraint. The body is either defined as a compound
1187faf42264SRiver Riddle   // block, i.e. `{ ... }`, or a lambda body, i.e. `=> <expr>`.
1188faf42264SRiver Riddle   ast::CompoundStmt *body;
1189faf42264SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
1190faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1191faf42264SRiver Riddle         [&](ast::Stmt *&stmt) -> LogicalResult {
1192faf42264SRiver Riddle           ast::Expr *stmtExpr = dyn_cast<ast::Expr>(stmt);
1193faf42264SRiver Riddle           if (!stmtExpr) {
1194faf42264SRiver Riddle             return emitError(stmt->getLoc(),
1195faf42264SRiver Riddle                              "expected `Constraint` lambda body to contain a "
1196faf42264SRiver Riddle                              "single expression");
1197faf42264SRiver Riddle           }
1198faf42264SRiver Riddle           stmt = ast::ReturnStmt::create(ctx, stmt->getLoc(), stmtExpr);
1199faf42264SRiver Riddle           return success();
1200faf42264SRiver Riddle         },
1201faf42264SRiver Riddle         /*expectTerminalSemicolon=*/!isInline);
1202faf42264SRiver Riddle     if (failed(bodyResult))
1203faf42264SRiver Riddle       return failure();
1204faf42264SRiver Riddle     body = *bodyResult;
1205faf42264SRiver Riddle   } else {
1206faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1207faf42264SRiver Riddle     if (failed(bodyResult))
1208faf42264SRiver Riddle       return failure();
1209faf42264SRiver Riddle     body = *bodyResult;
1210faf42264SRiver Riddle 
1211faf42264SRiver Riddle     // Verify the structure of the body.
1212faf42264SRiver Riddle     auto bodyIt = body->begin(), bodyE = body->end();
1213faf42264SRiver Riddle     for (; bodyIt != bodyE; ++bodyIt)
1214faf42264SRiver Riddle       if (isa<ast::ReturnStmt>(*bodyIt))
1215faf42264SRiver Riddle         break;
1216faf42264SRiver Riddle     if (failed(validateUserConstraintOrRewriteReturn(
1217faf42264SRiver Riddle             "Constraint", body, bodyIt, bodyE, results, resultType)))
1218faf42264SRiver Riddle       return failure();
1219faf42264SRiver Riddle   }
1220faf42264SRiver Riddle   popDeclScope();
1221faf42264SRiver Riddle 
1222faf42264SRiver Riddle   return createUserPDLLConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1223faf42264SRiver Riddle       name, arguments, results, resultType, body);
1224faf42264SRiver Riddle }
1225faf42264SRiver Riddle 
1226faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserRewriteDecl(bool isInline) {
1227faf42264SRiver Riddle   // Constraints and rewrites have very similar formats, dispatch to a shared
1228faf42264SRiver Riddle   // interface for parsing.
1229faf42264SRiver Riddle   return parseUserConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1230ceb5dc55SRiver Riddle       [&](auto &&...args) { return this->parseUserPDLLRewriteDecl(args...); },
1231faf42264SRiver Riddle       ParserContext::Rewrite, "rewrite", isInline);
1232faf42264SRiver Riddle }
1233faf42264SRiver Riddle 
1234faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseInlineUserRewriteDecl() {
1235faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> decl =
1236faf42264SRiver Riddle       parseUserRewriteDecl(/*isInline=*/true);
1237faf42264SRiver Riddle   if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName())))
1238faf42264SRiver Riddle     return failure();
1239faf42264SRiver Riddle 
1240faf42264SRiver Riddle   curDeclScope->add(*decl);
1241faf42264SRiver Riddle   return decl;
1242faf42264SRiver Riddle }
1243faf42264SRiver Riddle 
1244faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserPDLLRewriteDecl(
1245faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1246faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1247faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1248faf42264SRiver Riddle   // Push the argument scope back onto the list, so that the body can
1249faf42264SRiver Riddle   // reference arguments.
1250faf42264SRiver Riddle   curDeclScope = argumentScope;
1251faf42264SRiver Riddle   ast::CompoundStmt *body;
1252faf42264SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
1253faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1254faf42264SRiver Riddle         [&](ast::Stmt *&statement) -> LogicalResult {
1255faf42264SRiver Riddle           if (isa<ast::OpRewriteStmt>(statement))
1256faf42264SRiver Riddle             return success();
1257faf42264SRiver Riddle 
1258faf42264SRiver Riddle           ast::Expr *statementExpr = dyn_cast<ast::Expr>(statement);
1259faf42264SRiver Riddle           if (!statementExpr) {
1260faf42264SRiver Riddle             return emitError(
1261faf42264SRiver Riddle                 statement->getLoc(),
1262faf42264SRiver Riddle                 "expected `Rewrite` lambda body to contain a single expression "
1263faf42264SRiver Riddle                 "or an operation rewrite statement; such as `erase`, "
1264faf42264SRiver Riddle                 "`replace`, or `rewrite`");
1265faf42264SRiver Riddle           }
1266faf42264SRiver Riddle           statement =
1267faf42264SRiver Riddle               ast::ReturnStmt::create(ctx, statement->getLoc(), statementExpr);
1268faf42264SRiver Riddle           return success();
1269faf42264SRiver Riddle         },
1270faf42264SRiver Riddle         /*expectTerminalSemicolon=*/!isInline);
1271faf42264SRiver Riddle     if (failed(bodyResult))
1272faf42264SRiver Riddle       return failure();
1273faf42264SRiver Riddle     body = *bodyResult;
1274faf42264SRiver Riddle   } else {
1275faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1276faf42264SRiver Riddle     if (failed(bodyResult))
1277faf42264SRiver Riddle       return failure();
1278faf42264SRiver Riddle     body = *bodyResult;
1279faf42264SRiver Riddle   }
1280faf42264SRiver Riddle   popDeclScope();
1281faf42264SRiver Riddle 
1282faf42264SRiver Riddle   // Verify the structure of the body.
1283faf42264SRiver Riddle   auto bodyIt = body->begin(), bodyE = body->end();
1284faf42264SRiver Riddle   for (; bodyIt != bodyE; ++bodyIt)
1285faf42264SRiver Riddle     if (isa<ast::ReturnStmt>(*bodyIt))
1286faf42264SRiver Riddle       break;
1287faf42264SRiver Riddle   if (failed(validateUserConstraintOrRewriteReturn("Rewrite", body, bodyIt,
1288faf42264SRiver Riddle                                                    bodyE, results, resultType)))
1289faf42264SRiver Riddle     return failure();
1290faf42264SRiver Riddle   return createUserPDLLConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1291faf42264SRiver Riddle       name, arguments, results, resultType, body);
1292faf42264SRiver Riddle }
1293faf42264SRiver Riddle 
1294faf42264SRiver Riddle template <typename T, typename ParseUserPDLLDeclFnT>
1295faf42264SRiver Riddle FailureOr<T *> Parser::parseUserConstraintOrRewriteDecl(
1296faf42264SRiver Riddle     ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
1297faf42264SRiver Riddle     StringRef anonymousNamePrefix, bool isInline) {
1298faf42264SRiver Riddle   SMRange loc = curToken.getLoc();
1299faf42264SRiver Riddle   consumeToken();
1300abf0c6c0SJan Svoboda   llvm::SaveAndRestore saveCtx(parserContext, declContext);
1301faf42264SRiver Riddle 
1302faf42264SRiver Riddle   // Parse the name of the decl.
1303faf42264SRiver Riddle   const ast::Name *name = nullptr;
1304faf42264SRiver Riddle   if (curToken.isNot(Token::identifier)) {
1305faf42264SRiver Riddle     // Only inline decls can be un-named. Inline decls are similar to "lambdas"
1306faf42264SRiver Riddle     // in C++, so being unnamed is fine.
1307faf42264SRiver Riddle     if (!isInline)
1308faf42264SRiver Riddle       return emitError("expected identifier name");
1309faf42264SRiver Riddle 
1310faf42264SRiver Riddle     // Create a unique anonymous name to use, as the name for this decl is not
1311faf42264SRiver Riddle     // important.
1312faf42264SRiver Riddle     std::string anonName =
1313faf42264SRiver Riddle         llvm::formatv("<anonymous_{0}_{1}>", anonymousNamePrefix,
1314faf42264SRiver Riddle                       anonymousDeclNameCounter++)
1315faf42264SRiver Riddle             .str();
1316faf42264SRiver Riddle     name = &ast::Name::create(ctx, anonName, loc);
1317faf42264SRiver Riddle   } else {
1318faf42264SRiver Riddle     // If a name was provided, we can use it directly.
1319faf42264SRiver Riddle     name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc());
1320faf42264SRiver Riddle     consumeToken(Token::identifier);
1321faf42264SRiver Riddle   }
1322faf42264SRiver Riddle 
1323faf42264SRiver Riddle   // Parse the functional signature of the decl.
1324faf42264SRiver Riddle   SmallVector<ast::VariableDecl *> arguments, results;
1325faf42264SRiver Riddle   ast::DeclScope *argumentScope;
1326faf42264SRiver Riddle   ast::Type resultType;
1327faf42264SRiver Riddle   if (failed(parseUserConstraintOrRewriteSignature(arguments, results,
1328faf42264SRiver Riddle                                                    argumentScope, resultType)))
1329faf42264SRiver Riddle     return failure();
1330faf42264SRiver Riddle 
1331faf42264SRiver Riddle   // Check to see which type of constraint this is. If the constraint contains a
1332faf42264SRiver Riddle   // compound body, this is a PDLL decl.
1333faf42264SRiver Riddle   if (curToken.isAny(Token::l_brace, Token::equal_arrow))
1334faf42264SRiver Riddle     return parseUserPDLLFn(*name, isInline, arguments, argumentScope, results,
1335faf42264SRiver Riddle                            resultType);
1336faf42264SRiver Riddle 
1337faf42264SRiver Riddle   // Otherwise, this is a native decl.
1338faf42264SRiver Riddle   return parseUserNativeConstraintOrRewriteDecl<T>(*name, isInline, arguments,
1339faf42264SRiver Riddle                                                    results, resultType);
1340faf42264SRiver Riddle }
1341faf42264SRiver Riddle 
1342faf42264SRiver Riddle template <typename T>
1343faf42264SRiver Riddle FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl(
1344faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1345faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments,
1346faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1347faf42264SRiver Riddle   // If followed by a string, the native code body has also been specified.
1348faf42264SRiver Riddle   std::string codeStrStorage;
13490a81ace0SKazu Hirata   std::optional<StringRef> optCodeStr;
1350faf42264SRiver Riddle   if (curToken.isString()) {
1351faf42264SRiver Riddle     codeStrStorage = curToken.getStringValue();
1352faf42264SRiver Riddle     optCodeStr = codeStrStorage;
1353faf42264SRiver Riddle     consumeToken();
1354faf42264SRiver Riddle   } else if (isInline) {
1355faf42264SRiver Riddle     return emitError(name.getLoc(),
1356faf42264SRiver Riddle                      "external declarations must be declared in global scope");
1357ebb1e900SRiver Riddle   } else if (curToken.is(Token::error)) {
1358ebb1e900SRiver Riddle     return failure();
1359faf42264SRiver Riddle   }
1360faf42264SRiver Riddle   if (failed(parseToken(Token::semicolon,
1361faf42264SRiver Riddle                         "expected `;` after native declaration")))
1362faf42264SRiver Riddle     return failure();
1363faf42264SRiver Riddle   return T::createNative(ctx, name, arguments, results, optCodeStr, resultType);
1364faf42264SRiver Riddle }
1365faf42264SRiver Riddle 
1366faf42264SRiver Riddle LogicalResult Parser::parseUserConstraintOrRewriteSignature(
1367faf42264SRiver Riddle     SmallVectorImpl<ast::VariableDecl *> &arguments,
1368faf42264SRiver Riddle     SmallVectorImpl<ast::VariableDecl *> &results,
1369faf42264SRiver Riddle     ast::DeclScope *&argumentScope, ast::Type &resultType) {
1370faf42264SRiver Riddle   // Parse the argument list of the decl.
1371faf42264SRiver Riddle   if (failed(parseToken(Token::l_paren, "expected `(` to start argument list")))
1372faf42264SRiver Riddle     return failure();
1373faf42264SRiver Riddle 
1374faf42264SRiver Riddle   argumentScope = pushDeclScope();
1375faf42264SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
1376faf42264SRiver Riddle     do {
1377faf42264SRiver Riddle       FailureOr<ast::VariableDecl *> argument = parseArgumentDecl();
1378faf42264SRiver Riddle       if (failed(argument))
1379faf42264SRiver Riddle         return failure();
1380faf42264SRiver Riddle       arguments.emplace_back(*argument);
1381faf42264SRiver Riddle     } while (consumeIf(Token::comma));
1382faf42264SRiver Riddle   }
1383faf42264SRiver Riddle   popDeclScope();
1384faf42264SRiver Riddle   if (failed(parseToken(Token::r_paren, "expected `)` to end argument list")))
1385faf42264SRiver Riddle     return failure();
1386faf42264SRiver Riddle 
1387faf42264SRiver Riddle   // Parse the results of the decl.
1388faf42264SRiver Riddle   pushDeclScope();
1389faf42264SRiver Riddle   if (consumeIf(Token::arrow)) {
1390faf42264SRiver Riddle     auto parseResultFn = [&]() -> LogicalResult {
1391faf42264SRiver Riddle       FailureOr<ast::VariableDecl *> result = parseResultDecl(results.size());
1392faf42264SRiver Riddle       if (failed(result))
1393faf42264SRiver Riddle         return failure();
1394faf42264SRiver Riddle       results.emplace_back(*result);
1395faf42264SRiver Riddle       return success();
1396faf42264SRiver Riddle     };
1397faf42264SRiver Riddle 
1398faf42264SRiver Riddle     // Check for a list of results.
1399faf42264SRiver Riddle     if (consumeIf(Token::l_paren)) {
1400faf42264SRiver Riddle       do {
1401faf42264SRiver Riddle         if (failed(parseResultFn()))
1402faf42264SRiver Riddle           return failure();
1403faf42264SRiver Riddle       } while (consumeIf(Token::comma));
1404faf42264SRiver Riddle       if (failed(parseToken(Token::r_paren, "expected `)` to end result list")))
1405faf42264SRiver Riddle         return failure();
1406faf42264SRiver Riddle 
1407faf42264SRiver Riddle       // Otherwise, there is only one result.
1408faf42264SRiver Riddle     } else if (failed(parseResultFn())) {
1409faf42264SRiver Riddle       return failure();
1410faf42264SRiver Riddle     }
1411faf42264SRiver Riddle   }
1412faf42264SRiver Riddle   popDeclScope();
1413faf42264SRiver Riddle 
1414faf42264SRiver Riddle   // Compute the result type of the decl.
1415faf42264SRiver Riddle   resultType = createUserConstraintRewriteResultType(results);
1416faf42264SRiver Riddle 
1417faf42264SRiver Riddle   // Verify that results are only named if there are more than one.
1418faf42264SRiver Riddle   if (results.size() == 1 && !results.front()->getName().getName().empty()) {
1419faf42264SRiver Riddle     return emitError(
1420faf42264SRiver Riddle         results.front()->getLoc(),
1421faf42264SRiver Riddle         "cannot create a single-element tuple with an element label");
1422faf42264SRiver Riddle   }
1423faf42264SRiver Riddle   return success();
1424faf42264SRiver Riddle }
1425faf42264SRiver Riddle 
1426faf42264SRiver Riddle LogicalResult Parser::validateUserConstraintOrRewriteReturn(
1427faf42264SRiver Riddle     StringRef declType, ast::CompoundStmt *body,
1428faf42264SRiver Riddle     ArrayRef<ast::Stmt *>::iterator bodyIt,
1429faf42264SRiver Riddle     ArrayRef<ast::Stmt *>::iterator bodyE,
1430faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type &resultType) {
1431faf42264SRiver Riddle   // Handle if a `return` was provided.
1432faf42264SRiver Riddle   if (bodyIt != bodyE) {
1433faf42264SRiver Riddle     // Emit an error if we have trailing statements after the return.
1434faf42264SRiver Riddle     if (std::next(bodyIt) != bodyE) {
1435faf42264SRiver Riddle       return emitError(
1436faf42264SRiver Riddle           (*std::next(bodyIt))->getLoc(),
1437faf42264SRiver Riddle           llvm::formatv("`return` terminated the `{0}` body, but found "
1438faf42264SRiver Riddle                         "trailing statements afterwards",
1439faf42264SRiver Riddle                         declType));
1440faf42264SRiver Riddle     }
1441faf42264SRiver Riddle 
1442faf42264SRiver Riddle     // Otherwise if a return wasn't provided, check that no results are
1443faf42264SRiver Riddle     // expected.
1444faf42264SRiver Riddle   } else if (!results.empty()) {
1445faf42264SRiver Riddle     return emitError(
1446faf42264SRiver Riddle         {body->getLoc().End, body->getLoc().End},
1447faf42264SRiver Riddle         llvm::formatv("missing return in a `{0}` expected to return `{1}`",
1448faf42264SRiver Riddle                       declType, resultType));
1449faf42264SRiver Riddle   }
1450faf42264SRiver Riddle   return success();
1451faf42264SRiver Riddle }
1452faf42264SRiver Riddle 
14533d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parsePatternLambdaBody() {
14543d8b9060SRiver Riddle   return parseLambdaBody([&](ast::Stmt *&statement) -> LogicalResult {
14553d8b9060SRiver Riddle     if (isa<ast::OpRewriteStmt>(statement))
14563d8b9060SRiver Riddle       return success();
14573d8b9060SRiver Riddle     return emitError(
14583d8b9060SRiver Riddle         statement->getLoc(),
14593d8b9060SRiver Riddle         "expected Pattern lambda body to contain a single operation "
14603d8b9060SRiver Riddle         "rewrite statement, such as `erase`, `replace`, or `rewrite`");
14613d8b9060SRiver Riddle   });
14623d8b9060SRiver Riddle }
14633d8b9060SRiver Riddle 
146411d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parsePatternDecl() {
14656842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
146611d26bd1SRiver Riddle   consumeToken(Token::kw_Pattern);
1467abf0c6c0SJan Svoboda   llvm::SaveAndRestore saveCtx(parserContext, ParserContext::PatternMatch);
146811d26bd1SRiver Riddle 
146911d26bd1SRiver Riddle   // Check for an optional identifier for the pattern name.
147011d26bd1SRiver Riddle   const ast::Name *name = nullptr;
147111d26bd1SRiver Riddle   if (curToken.is(Token::identifier)) {
147211d26bd1SRiver Riddle     name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc());
147311d26bd1SRiver Riddle     consumeToken(Token::identifier);
147411d26bd1SRiver Riddle   }
147511d26bd1SRiver Riddle 
1476322691abSRiver Riddle   // Parse any pattern metadata.
1477322691abSRiver Riddle   ParsedPatternMetadata metadata;
1478322691abSRiver Riddle   if (consumeIf(Token::kw_with) && failed(parsePatternDeclMetadata(metadata)))
1479322691abSRiver Riddle     return failure();
148011d26bd1SRiver Riddle 
148111d26bd1SRiver Riddle   // Parse the pattern body.
148211d26bd1SRiver Riddle   ast::CompoundStmt *body;
148311d26bd1SRiver Riddle 
14843d8b9060SRiver Riddle   // Handle a lambda body.
14853d8b9060SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
14863d8b9060SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parsePatternLambdaBody();
14873d8b9060SRiver Riddle     if (failed(bodyResult))
14883d8b9060SRiver Riddle       return failure();
14893d8b9060SRiver Riddle     body = *bodyResult;
14903d8b9060SRiver Riddle   } else {
149111d26bd1SRiver Riddle     if (curToken.isNot(Token::l_brace))
14923d8b9060SRiver Riddle       return emitError("expected `{` or `=>` to start pattern body");
149311d26bd1SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
149411d26bd1SRiver Riddle     if (failed(bodyResult))
149511d26bd1SRiver Riddle       return failure();
149611d26bd1SRiver Riddle     body = *bodyResult;
149711d26bd1SRiver Riddle 
149811d26bd1SRiver Riddle     // Verify the body of the pattern.
149911d26bd1SRiver Riddle     auto bodyIt = body->begin(), bodyE = body->end();
150011d26bd1SRiver Riddle     for (; bodyIt != bodyE; ++bodyIt) {
1501faf42264SRiver Riddle       if (isa<ast::ReturnStmt>(*bodyIt)) {
1502faf42264SRiver Riddle         return emitError((*bodyIt)->getLoc(),
1503faf42264SRiver Riddle                          "`return` statements are only permitted within a "
1504faf42264SRiver Riddle                          "`Constraint` or `Rewrite` body");
1505faf42264SRiver Riddle       }
150611d26bd1SRiver Riddle       // Break when we've found the rewrite statement.
150711d26bd1SRiver Riddle       if (isa<ast::OpRewriteStmt>(*bodyIt))
150811d26bd1SRiver Riddle         break;
150911d26bd1SRiver Riddle     }
151011d26bd1SRiver Riddle     if (bodyIt == bodyE) {
151111d26bd1SRiver Riddle       return emitError(loc,
151211d26bd1SRiver Riddle                        "expected Pattern body to terminate with an operation "
151311d26bd1SRiver Riddle                        "rewrite statement, such as `erase`");
151411d26bd1SRiver Riddle     }
151511d26bd1SRiver Riddle     if (std::next(bodyIt) != bodyE) {
151611d26bd1SRiver Riddle       return emitError((*std::next(bodyIt))->getLoc(),
151711d26bd1SRiver Riddle                        "Pattern body was terminated by an operation "
151811d26bd1SRiver Riddle                        "rewrite statement, but found trailing statements");
151911d26bd1SRiver Riddle     }
15203d8b9060SRiver Riddle   }
152111d26bd1SRiver Riddle 
1522322691abSRiver Riddle   return createPatternDecl(loc, name, metadata, body);
1523322691abSRiver Riddle }
1524322691abSRiver Riddle 
1525322691abSRiver Riddle LogicalResult
1526322691abSRiver Riddle Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) {
15270a81ace0SKazu Hirata   std::optional<SMRange> benefitLoc;
15280a81ace0SKazu Hirata   std::optional<SMRange> hasBoundedRecursionLoc;
1529322691abSRiver Riddle 
1530322691abSRiver Riddle   do {
1531008de486SRiver Riddle     // Handle metadata code completion.
1532008de486SRiver Riddle     if (curToken.is(Token::code_complete))
1533008de486SRiver Riddle       return codeCompletePatternMetadata();
1534008de486SRiver Riddle 
1535322691abSRiver Riddle     if (curToken.isNot(Token::identifier))
1536322691abSRiver Riddle       return emitError("expected pattern metadata identifier");
1537322691abSRiver Riddle     StringRef metadataStr = curToken.getSpelling();
15386842ec42SRiver Riddle     SMRange metadataLoc = curToken.getLoc();
1539322691abSRiver Riddle     consumeToken(Token::identifier);
1540322691abSRiver Riddle 
1541322691abSRiver Riddle     // Parse the benefit metadata: benefit(<integer-value>)
1542322691abSRiver Riddle     if (metadataStr == "benefit") {
1543322691abSRiver Riddle       if (benefitLoc) {
1544322691abSRiver Riddle         return emitErrorAndNote(metadataLoc,
1545322691abSRiver Riddle                                 "pattern benefit has already been specified",
1546322691abSRiver Riddle                                 *benefitLoc, "see previous definition here");
1547322691abSRiver Riddle       }
1548322691abSRiver Riddle       if (failed(parseToken(Token::l_paren,
1549322691abSRiver Riddle                             "expected `(` before pattern benefit")))
1550322691abSRiver Riddle         return failure();
1551322691abSRiver Riddle 
1552322691abSRiver Riddle       uint16_t benefitValue = 0;
1553322691abSRiver Riddle       if (curToken.isNot(Token::integer))
1554322691abSRiver Riddle         return emitError("expected integral pattern benefit");
1555322691abSRiver Riddle       if (curToken.getSpelling().getAsInteger(/*Radix=*/10, benefitValue))
1556322691abSRiver Riddle         return emitError(
1557322691abSRiver Riddle             "expected pattern benefit to fit within a 16-bit integer");
1558322691abSRiver Riddle       consumeToken(Token::integer);
1559322691abSRiver Riddle 
1560322691abSRiver Riddle       metadata.benefit = benefitValue;
1561322691abSRiver Riddle       benefitLoc = metadataLoc;
1562322691abSRiver Riddle 
1563322691abSRiver Riddle       if (failed(
1564322691abSRiver Riddle               parseToken(Token::r_paren, "expected `)` after pattern benefit")))
1565322691abSRiver Riddle         return failure();
1566322691abSRiver Riddle       continue;
1567322691abSRiver Riddle     }
1568322691abSRiver Riddle 
1569322691abSRiver Riddle     // Parse the bounded recursion metadata: recursion
1570322691abSRiver Riddle     if (metadataStr == "recursion") {
1571322691abSRiver Riddle       if (hasBoundedRecursionLoc) {
1572322691abSRiver Riddle         return emitErrorAndNote(
1573322691abSRiver Riddle             metadataLoc,
1574322691abSRiver Riddle             "pattern recursion metadata has already been specified",
1575322691abSRiver Riddle             *hasBoundedRecursionLoc, "see previous definition here");
1576322691abSRiver Riddle       }
1577322691abSRiver Riddle       metadata.hasBoundedRecursion = true;
1578322691abSRiver Riddle       hasBoundedRecursionLoc = metadataLoc;
1579322691abSRiver Riddle       continue;
1580322691abSRiver Riddle     }
1581322691abSRiver Riddle 
1582322691abSRiver Riddle     return emitError(metadataLoc, "unknown pattern metadata");
1583322691abSRiver Riddle   } while (consumeIf(Token::comma));
1584322691abSRiver Riddle 
1585322691abSRiver Riddle   return success();
158611d26bd1SRiver Riddle }
158711d26bd1SRiver Riddle 
158811d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeConstraintExpr() {
158911d26bd1SRiver Riddle   consumeToken(Token::less);
159011d26bd1SRiver Riddle 
159111d26bd1SRiver Riddle   FailureOr<ast::Expr *> typeExpr = parseExpr();
159211d26bd1SRiver Riddle   if (failed(typeExpr) ||
159311d26bd1SRiver Riddle       failed(parseToken(Token::greater,
159411d26bd1SRiver Riddle                         "expected `>` after variable type constraint")))
159511d26bd1SRiver Riddle     return failure();
159611d26bd1SRiver Riddle   return typeExpr;
159711d26bd1SRiver Riddle }
159811d26bd1SRiver Riddle 
159911d26bd1SRiver Riddle LogicalResult Parser::checkDefineNamedDecl(const ast::Name &name) {
160011d26bd1SRiver Riddle   assert(curDeclScope && "defining decl outside of a decl scope");
160111d26bd1SRiver Riddle   if (ast::Decl *lastDecl = curDeclScope->lookup(name.getName())) {
160211d26bd1SRiver Riddle     return emitErrorAndNote(
160311d26bd1SRiver Riddle         name.getLoc(), "`" + name.getName() + "` has already been defined",
160411d26bd1SRiver Riddle         lastDecl->getName()->getLoc(), "see previous definition here");
160511d26bd1SRiver Riddle   }
160611d26bd1SRiver Riddle   return success();
160711d26bd1SRiver Riddle }
160811d26bd1SRiver Riddle 
160911d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
1610faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
1611faf42264SRiver Riddle                            ast::Expr *initExpr,
161211d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
161311d26bd1SRiver Riddle   assert(curDeclScope && "defining variable outside of decl scope");
161411d26bd1SRiver Riddle   const ast::Name &nameDecl = ast::Name::create(ctx, name, nameLoc);
161511d26bd1SRiver Riddle 
161611d26bd1SRiver Riddle   // If the name of the variable indicates a special variable, we don't add it
161711d26bd1SRiver Riddle   // to the scope. This variable is local to the definition point.
161811d26bd1SRiver Riddle   if (name.empty() || name == "_") {
161911d26bd1SRiver Riddle     return ast::VariableDecl::create(ctx, nameDecl, type, initExpr,
162011d26bd1SRiver Riddle                                      constraints);
162111d26bd1SRiver Riddle   }
162211d26bd1SRiver Riddle   if (failed(checkDefineNamedDecl(nameDecl)))
162311d26bd1SRiver Riddle     return failure();
162411d26bd1SRiver Riddle 
162511d26bd1SRiver Riddle   auto *varDecl =
162611d26bd1SRiver Riddle       ast::VariableDecl::create(ctx, nameDecl, type, initExpr, constraints);
162711d26bd1SRiver Riddle   curDeclScope->add(varDecl);
162811d26bd1SRiver Riddle   return varDecl;
162911d26bd1SRiver Riddle }
163011d26bd1SRiver Riddle 
163111d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
1632faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
163311d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
163411d26bd1SRiver Riddle   return defineVariableDecl(name, nameLoc, type, /*initExpr=*/nullptr,
163511d26bd1SRiver Riddle                             constraints);
163611d26bd1SRiver Riddle }
163711d26bd1SRiver Riddle 
163811d26bd1SRiver Riddle LogicalResult Parser::parseVariableDeclConstraintList(
163911d26bd1SRiver Riddle     SmallVectorImpl<ast::ConstraintRef> &constraints) {
16400a81ace0SKazu Hirata   std::optional<SMRange> typeConstraint;
164111d26bd1SRiver Riddle   auto parseSingleConstraint = [&] {
1642faf42264SRiver Riddle     FailureOr<ast::ConstraintRef> constraint = parseConstraint(
1643b6ec1de7SRiver Riddle         typeConstraint, constraints, /*allowInlineTypeConstraints=*/true);
164411d26bd1SRiver Riddle     if (failed(constraint))
164511d26bd1SRiver Riddle       return failure();
164611d26bd1SRiver Riddle     constraints.push_back(*constraint);
164711d26bd1SRiver Riddle     return success();
164811d26bd1SRiver Riddle   };
164911d26bd1SRiver Riddle 
165011d26bd1SRiver Riddle   // Check to see if this is a single constraint, or a list.
165111d26bd1SRiver Riddle   if (!consumeIf(Token::l_square))
165211d26bd1SRiver Riddle     return parseSingleConstraint();
165311d26bd1SRiver Riddle 
165411d26bd1SRiver Riddle   do {
165511d26bd1SRiver Riddle     if (failed(parseSingleConstraint()))
165611d26bd1SRiver Riddle       return failure();
165711d26bd1SRiver Riddle   } while (consumeIf(Token::comma));
165811d26bd1SRiver Riddle   return parseToken(Token::r_square, "expected `]` after constraint list");
165911d26bd1SRiver Riddle }
166011d26bd1SRiver Riddle 
166111d26bd1SRiver Riddle FailureOr<ast::ConstraintRef>
16620a81ace0SKazu Hirata Parser::parseConstraint(std::optional<SMRange> &typeConstraint,
1663faf42264SRiver Riddle                         ArrayRef<ast::ConstraintRef> existingConstraints,
1664b6ec1de7SRiver Riddle                         bool allowInlineTypeConstraints) {
166511d26bd1SRiver Riddle   auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult {
1666faf42264SRiver Riddle     if (!allowInlineTypeConstraints) {
1667faf42264SRiver Riddle       return emitError(
1668faf42264SRiver Riddle           curToken.getLoc(),
1669faf42264SRiver Riddle           "inline `Attr`, `Value`, and `ValueRange` type constraints are not "
1670faf42264SRiver Riddle           "permitted on arguments or results");
1671faf42264SRiver Riddle     }
167211d26bd1SRiver Riddle     if (typeConstraint)
167311d26bd1SRiver Riddle       return emitErrorAndNote(
167411d26bd1SRiver Riddle           curToken.getLoc(),
167511d26bd1SRiver Riddle           "the type of this variable has already been constrained",
167611d26bd1SRiver Riddle           *typeConstraint, "see previous constraint location here");
167711d26bd1SRiver Riddle     FailureOr<ast::Expr *> constraintExpr = parseTypeConstraintExpr();
167811d26bd1SRiver Riddle     if (failed(constraintExpr))
167911d26bd1SRiver Riddle       return failure();
168011d26bd1SRiver Riddle     typeExpr = *constraintExpr;
168111d26bd1SRiver Riddle     typeConstraint = typeExpr->getLoc();
168211d26bd1SRiver Riddle     return success();
168311d26bd1SRiver Riddle   };
168411d26bd1SRiver Riddle 
16856842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
168611d26bd1SRiver Riddle   switch (curToken.getKind()) {
168711d26bd1SRiver Riddle   case Token::kw_Attr: {
168811d26bd1SRiver Riddle     consumeToken(Token::kw_Attr);
168911d26bd1SRiver Riddle 
169011d26bd1SRiver Riddle     // Check for a type constraint.
169111d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
169211d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
169311d26bd1SRiver Riddle       return failure();
169411d26bd1SRiver Riddle     return ast::ConstraintRef(
169511d26bd1SRiver Riddle         ast::AttrConstraintDecl::create(ctx, loc, typeExpr), loc);
169611d26bd1SRiver Riddle   }
169711d26bd1SRiver Riddle   case Token::kw_Op: {
169811d26bd1SRiver Riddle     consumeToken(Token::kw_Op);
169911d26bd1SRiver Riddle 
170012eebb8eSRiver Riddle     // Parse an optional operation name. If the name isn't provided, this refers
170112eebb8eSRiver Riddle     // to "any" operation.
170212eebb8eSRiver Riddle     FailureOr<ast::OpNameDecl *> opName =
170312eebb8eSRiver Riddle         parseWrappedOperationName(/*allowEmptyName=*/true);
170411d26bd1SRiver Riddle     if (failed(opName))
170511d26bd1SRiver Riddle       return failure();
170611d26bd1SRiver Riddle 
170711d26bd1SRiver Riddle     return ast::ConstraintRef(ast::OpConstraintDecl::create(ctx, loc, *opName),
170811d26bd1SRiver Riddle                               loc);
170911d26bd1SRiver Riddle   }
171011d26bd1SRiver Riddle   case Token::kw_Type:
171111d26bd1SRiver Riddle     consumeToken(Token::kw_Type);
171211d26bd1SRiver Riddle     return ast::ConstraintRef(ast::TypeConstraintDecl::create(ctx, loc), loc);
171311d26bd1SRiver Riddle   case Token::kw_TypeRange:
171411d26bd1SRiver Riddle     consumeToken(Token::kw_TypeRange);
171511d26bd1SRiver Riddle     return ast::ConstraintRef(ast::TypeRangeConstraintDecl::create(ctx, loc),
171611d26bd1SRiver Riddle                               loc);
171711d26bd1SRiver Riddle   case Token::kw_Value: {
171811d26bd1SRiver Riddle     consumeToken(Token::kw_Value);
171911d26bd1SRiver Riddle 
172011d26bd1SRiver Riddle     // Check for a type constraint.
172111d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
172211d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
172311d26bd1SRiver Riddle       return failure();
172411d26bd1SRiver Riddle 
172511d26bd1SRiver Riddle     return ast::ConstraintRef(
172611d26bd1SRiver Riddle         ast::ValueConstraintDecl::create(ctx, loc, typeExpr), loc);
172711d26bd1SRiver Riddle   }
172811d26bd1SRiver Riddle   case Token::kw_ValueRange: {
172911d26bd1SRiver Riddle     consumeToken(Token::kw_ValueRange);
173011d26bd1SRiver Riddle 
173111d26bd1SRiver Riddle     // Check for a type constraint.
173211d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
173311d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
173411d26bd1SRiver Riddle       return failure();
173511d26bd1SRiver Riddle 
173611d26bd1SRiver Riddle     return ast::ConstraintRef(
173711d26bd1SRiver Riddle         ast::ValueRangeConstraintDecl::create(ctx, loc, typeExpr), loc);
173811d26bd1SRiver Riddle   }
1739faf42264SRiver Riddle 
1740faf42264SRiver Riddle   case Token::kw_Constraint: {
1741faf42264SRiver Riddle     // Handle an inline constraint.
1742faf42264SRiver Riddle     FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1743faf42264SRiver Riddle     if (failed(decl))
1744faf42264SRiver Riddle       return failure();
1745faf42264SRiver Riddle     return ast::ConstraintRef(*decl, loc);
1746faf42264SRiver Riddle   }
174711d26bd1SRiver Riddle   case Token::identifier: {
174811d26bd1SRiver Riddle     StringRef constraintName = curToken.getSpelling();
174911d26bd1SRiver Riddle     consumeToken(Token::identifier);
175011d26bd1SRiver Riddle 
175111d26bd1SRiver Riddle     // Lookup the referenced constraint.
175211d26bd1SRiver Riddle     ast::Decl *cstDecl = curDeclScope->lookup<ast::Decl>(constraintName);
175311d26bd1SRiver Riddle     if (!cstDecl) {
175411d26bd1SRiver Riddle       return emitError(loc, "unknown reference to constraint `" +
175511d26bd1SRiver Riddle                                 constraintName + "`");
175611d26bd1SRiver Riddle     }
175711d26bd1SRiver Riddle 
175811d26bd1SRiver Riddle     // Handle a reference to a proper constraint.
175911d26bd1SRiver Riddle     if (auto *cst = dyn_cast<ast::ConstraintDecl>(cstDecl))
176011d26bd1SRiver Riddle       return ast::ConstraintRef(cst, loc);
176111d26bd1SRiver Riddle 
176211d26bd1SRiver Riddle     return emitErrorAndNote(
176311d26bd1SRiver Riddle         loc, "invalid reference to non-constraint", cstDecl->getLoc(),
176411d26bd1SRiver Riddle         "see the definition of `" + constraintName + "` here");
176511d26bd1SRiver Riddle   }
1766008de486SRiver Riddle     // Handle single entity constraint code completion.
1767008de486SRiver Riddle   case Token::code_complete: {
1768008de486SRiver Riddle     // Try to infer the current type for use by code completion.
1769008de486SRiver Riddle     ast::Type inferredType;
1770b6ec1de7SRiver Riddle     if (failed(validateVariableConstraints(existingConstraints, inferredType)))
1771008de486SRiver Riddle       return failure();
1772008de486SRiver Riddle 
1773b6ec1de7SRiver Riddle     return codeCompleteConstraintName(inferredType, allowInlineTypeConstraints);
1774008de486SRiver Riddle   }
177511d26bd1SRiver Riddle   default:
177611d26bd1SRiver Riddle     break;
177711d26bd1SRiver Riddle   }
177811d26bd1SRiver Riddle   return emitError(loc, "expected identifier constraint");
177911d26bd1SRiver Riddle }
178011d26bd1SRiver Riddle 
1781faf42264SRiver Riddle FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
17820a81ace0SKazu Hirata   std::optional<SMRange> typeConstraint;
17831a36588eSKazu Hirata   return parseConstraint(typeConstraint, /*existingConstraints=*/std::nullopt,
1784b6ec1de7SRiver Riddle                          /*allowInlineTypeConstraints=*/false);
1785faf42264SRiver Riddle }
1786faf42264SRiver Riddle 
178711d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
178811d26bd1SRiver Riddle // Exprs
178911d26bd1SRiver Riddle 
179011d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseExpr() {
179111d26bd1SRiver Riddle   if (curToken.is(Token::underscore))
179211d26bd1SRiver Riddle     return parseUnderscoreExpr();
179311d26bd1SRiver Riddle 
179411d26bd1SRiver Riddle   // Parse the LHS expression.
179511d26bd1SRiver Riddle   FailureOr<ast::Expr *> lhsExpr;
179611d26bd1SRiver Riddle   switch (curToken.getKind()) {
1797d7e7fdf3SRiver Riddle   case Token::kw_attr:
1798d7e7fdf3SRiver Riddle     lhsExpr = parseAttributeExpr();
1799d7e7fdf3SRiver Riddle     break;
1800faf42264SRiver Riddle   case Token::kw_Constraint:
1801faf42264SRiver Riddle     lhsExpr = parseInlineConstraintLambdaExpr();
1802faf42264SRiver Riddle     break;
1803930916c7SMogball   case Token::kw_not:
1804930916c7SMogball     lhsExpr = parseNegatedExpr();
1805930916c7SMogball     break;
180611d26bd1SRiver Riddle   case Token::identifier:
180711d26bd1SRiver Riddle     lhsExpr = parseIdentifierExpr();
180811d26bd1SRiver Riddle     break;
180902670c3fSRiver Riddle   case Token::kw_op:
181002670c3fSRiver Riddle     lhsExpr = parseOperationExpr();
181102670c3fSRiver Riddle     break;
1812faf42264SRiver Riddle   case Token::kw_Rewrite:
1813faf42264SRiver Riddle     lhsExpr = parseInlineRewriteLambdaExpr();
1814faf42264SRiver Riddle     break;
1815d7e7fdf3SRiver Riddle   case Token::kw_type:
1816d7e7fdf3SRiver Riddle     lhsExpr = parseTypeExpr();
1817d7e7fdf3SRiver Riddle     break;
1818f62a57a3SRiver Riddle   case Token::l_paren:
1819f62a57a3SRiver Riddle     lhsExpr = parseTupleExpr();
1820f62a57a3SRiver Riddle     break;
182111d26bd1SRiver Riddle   default:
182211d26bd1SRiver Riddle     return emitError("expected expression");
182311d26bd1SRiver Riddle   }
182411d26bd1SRiver Riddle   if (failed(lhsExpr))
182511d26bd1SRiver Riddle     return failure();
182611d26bd1SRiver Riddle 
182711d26bd1SRiver Riddle   // Check for an operator expression.
182811d26bd1SRiver Riddle   while (true) {
182911d26bd1SRiver Riddle     switch (curToken.getKind()) {
183011d26bd1SRiver Riddle     case Token::dot:
183111d26bd1SRiver Riddle       lhsExpr = parseMemberAccessExpr(*lhsExpr);
183211d26bd1SRiver Riddle       break;
1833faf42264SRiver Riddle     case Token::l_paren:
1834faf42264SRiver Riddle       lhsExpr = parseCallExpr(*lhsExpr);
1835faf42264SRiver Riddle       break;
183611d26bd1SRiver Riddle     default:
183711d26bd1SRiver Riddle       return lhsExpr;
183811d26bd1SRiver Riddle     }
183911d26bd1SRiver Riddle     if (failed(lhsExpr))
184011d26bd1SRiver Riddle       return failure();
184111d26bd1SRiver Riddle   }
184211d26bd1SRiver Riddle }
184311d26bd1SRiver Riddle 
1844d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseAttributeExpr() {
18456842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
1846d7e7fdf3SRiver Riddle   consumeToken(Token::kw_attr);
1847d7e7fdf3SRiver Riddle 
1848d7e7fdf3SRiver Riddle   // If we aren't followed by a `<`, the `attr` keyword is treated as a normal
1849d7e7fdf3SRiver Riddle   // identifier.
1850d7e7fdf3SRiver Riddle   if (!consumeIf(Token::less)) {
1851d7e7fdf3SRiver Riddle     resetToken(loc);
1852d7e7fdf3SRiver Riddle     return parseIdentifierExpr();
1853d7e7fdf3SRiver Riddle   }
1854d7e7fdf3SRiver Riddle 
1855d7e7fdf3SRiver Riddle   if (!curToken.isString())
1856d7e7fdf3SRiver Riddle     return emitError("expected string literal containing MLIR attribute");
1857d7e7fdf3SRiver Riddle   std::string attrExpr = curToken.getStringValue();
1858d7e7fdf3SRiver Riddle   consumeToken();
1859d7e7fdf3SRiver Riddle 
18606d4471efSRiver Riddle   loc.End = curToken.getEndLoc();
1861d7e7fdf3SRiver Riddle   if (failed(
1862d7e7fdf3SRiver Riddle           parseToken(Token::greater, "expected `>` after attribute literal")))
1863d7e7fdf3SRiver Riddle     return failure();
1864d7e7fdf3SRiver Riddle   return ast::AttributeExpr::create(ctx, loc, attrExpr);
1865d7e7fdf3SRiver Riddle }
1866d7e7fdf3SRiver Riddle 
1867930916c7SMogball FailureOr<ast::Expr *> Parser::parseCallExpr(ast::Expr *parentExpr,
1868930916c7SMogball                                              bool isNegated) {
1869faf42264SRiver Riddle   consumeToken(Token::l_paren);
1870faf42264SRiver Riddle 
1871faf42264SRiver Riddle   // Parse the arguments of the call.
1872faf42264SRiver Riddle   SmallVector<ast::Expr *> arguments;
1873faf42264SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
1874faf42264SRiver Riddle     do {
1875469c5894SRiver Riddle       // Handle code completion for the call arguments.
1876469c5894SRiver Riddle       if (curToken.is(Token::code_complete)) {
1877469c5894SRiver Riddle         codeCompleteCallSignature(parentExpr, arguments.size());
1878469c5894SRiver Riddle         return failure();
1879469c5894SRiver Riddle       }
1880469c5894SRiver Riddle 
1881faf42264SRiver Riddle       FailureOr<ast::Expr *> argument = parseExpr();
1882faf42264SRiver Riddle       if (failed(argument))
1883faf42264SRiver Riddle         return failure();
1884faf42264SRiver Riddle       arguments.push_back(*argument);
1885faf42264SRiver Riddle     } while (consumeIf(Token::comma));
1886faf42264SRiver Riddle   }
18876d4471efSRiver Riddle 
18886d4471efSRiver Riddle   SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc());
1889faf42264SRiver Riddle   if (failed(parseToken(Token::r_paren, "expected `)` after argument list")))
1890faf42264SRiver Riddle     return failure();
1891faf42264SRiver Riddle 
1892930916c7SMogball   return createCallExpr(loc, parentExpr, arguments, isNegated);
1893faf42264SRiver Riddle }
1894faf42264SRiver Riddle 
1895faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
189611d26bd1SRiver Riddle   ast::Decl *decl = curDeclScope->lookup(name);
189711d26bd1SRiver Riddle   if (!decl)
189811d26bd1SRiver Riddle     return emitError(loc, "undefined reference to `" + name + "`");
189911d26bd1SRiver Riddle 
190011d26bd1SRiver Riddle   return createDeclRefExpr(loc, decl);
190111d26bd1SRiver Riddle }
190211d26bd1SRiver Riddle 
190311d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseIdentifierExpr() {
190411d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
19056842ec42SRiver Riddle   SMRange nameLoc = curToken.getLoc();
190611d26bd1SRiver Riddle   consumeToken();
190711d26bd1SRiver Riddle 
190811d26bd1SRiver Riddle   // Check to see if this is a decl ref expression that defines a variable
190911d26bd1SRiver Riddle   // inline.
191011d26bd1SRiver Riddle   if (consumeIf(Token::colon)) {
191111d26bd1SRiver Riddle     SmallVector<ast::ConstraintRef> constraints;
191211d26bd1SRiver Riddle     if (failed(parseVariableDeclConstraintList(constraints)))
191311d26bd1SRiver Riddle       return failure();
191411d26bd1SRiver Riddle     ast::Type type;
191511d26bd1SRiver Riddle     if (failed(validateVariableConstraints(constraints, type)))
191611d26bd1SRiver Riddle       return failure();
191711d26bd1SRiver Riddle     return createInlineVariableExpr(type, name, nameLoc, constraints);
191811d26bd1SRiver Riddle   }
191911d26bd1SRiver Riddle 
192011d26bd1SRiver Riddle   return parseDeclRefExpr(name, nameLoc);
192111d26bd1SRiver Riddle }
192211d26bd1SRiver Riddle 
1923faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineConstraintLambdaExpr() {
1924faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1925faf42264SRiver Riddle   if (failed(decl))
1926faf42264SRiver Riddle     return failure();
1927faf42264SRiver Riddle 
1928faf42264SRiver Riddle   return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl,
1929faf42264SRiver Riddle                                   ast::ConstraintType::get(ctx));
1930faf42264SRiver Riddle }
1931faf42264SRiver Riddle 
1932faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineRewriteLambdaExpr() {
1933faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> decl = parseInlineUserRewriteDecl();
1934faf42264SRiver Riddle   if (failed(decl))
1935faf42264SRiver Riddle     return failure();
1936faf42264SRiver Riddle 
1937faf42264SRiver Riddle   return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl,
1938faf42264SRiver Riddle                                   ast::RewriteType::get(ctx));
1939faf42264SRiver Riddle }
1940faf42264SRiver Riddle 
194111d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseMemberAccessExpr(ast::Expr *parentExpr) {
19426d4471efSRiver Riddle   SMRange dotLoc = curToken.getLoc();
194311d26bd1SRiver Riddle   consumeToken(Token::dot);
194411d26bd1SRiver Riddle 
1945008de486SRiver Riddle   // Check for code completion of the member name.
1946008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1947008de486SRiver Riddle     return codeCompleteMemberAccess(parentExpr);
1948008de486SRiver Riddle 
194911d26bd1SRiver Riddle   // Parse the member name.
195011d26bd1SRiver Riddle   Token memberNameTok = curToken;
195111d26bd1SRiver Riddle   if (memberNameTok.isNot(Token::identifier, Token::integer) &&
195211d26bd1SRiver Riddle       !memberNameTok.isKeyword())
19536d4471efSRiver Riddle     return emitError(dotLoc, "expected identifier or numeric member name");
195411d26bd1SRiver Riddle   StringRef memberName = memberNameTok.getSpelling();
19556d4471efSRiver Riddle   SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc());
195611d26bd1SRiver Riddle   consumeToken();
195711d26bd1SRiver Riddle 
195811d26bd1SRiver Riddle   return createMemberAccessExpr(parentExpr, memberName, loc);
195911d26bd1SRiver Riddle }
196011d26bd1SRiver Riddle 
1961930916c7SMogball FailureOr<ast::Expr *> Parser::parseNegatedExpr() {
1962930916c7SMogball   consumeToken(Token::kw_not);
1963930916c7SMogball   // Only native constraints are supported after negation
1964930916c7SMogball   if (!curToken.is(Token::identifier))
1965930916c7SMogball     return emitError("expected native constraint");
1966930916c7SMogball   FailureOr<ast::Expr *> identifierExpr = parseIdentifierExpr();
1967930916c7SMogball   if (failed(identifierExpr))
1968930916c7SMogball     return failure();
1969780a2098SMatthias Gehre   if (!curToken.is(Token::l_paren))
1970780a2098SMatthias Gehre     return emitError("expected `(` after function name");
1971930916c7SMogball   return parseCallExpr(*identifierExpr, /*isNegated = */ true);
1972930916c7SMogball }
1973930916c7SMogball 
197412eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> Parser::parseOperationName(bool allowEmptyName) {
19756842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
197611d26bd1SRiver Riddle 
1977008de486SRiver Riddle   // Check for code completion for the dialect name.
1978008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1979008de486SRiver Riddle     return codeCompleteDialectName();
1980008de486SRiver Riddle 
198111d26bd1SRiver Riddle   // Handle the case of an no operation name.
198212eebb8eSRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isKeyword()) {
198312eebb8eSRiver Riddle     if (allowEmptyName)
19846842ec42SRiver Riddle       return ast::OpNameDecl::create(ctx, SMRange());
198512eebb8eSRiver Riddle     return emitError("expected dialect namespace");
198612eebb8eSRiver Riddle   }
198711d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
198811d26bd1SRiver Riddle   consumeToken();
198911d26bd1SRiver Riddle 
199011d26bd1SRiver Riddle   // Otherwise, this is a literal operation name.
199111d26bd1SRiver Riddle   if (failed(parseToken(Token::dot, "expected `.` after dialect namespace")))
199211d26bd1SRiver Riddle     return failure();
199311d26bd1SRiver Riddle 
1994008de486SRiver Riddle   // Check for code completion for the operation name.
1995008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1996008de486SRiver Riddle     return codeCompleteOperationName(name);
1997008de486SRiver Riddle 
199811d26bd1SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isKeyword())
199911d26bd1SRiver Riddle     return emitError("expected operation name after dialect namespace");
200011d26bd1SRiver Riddle 
200111d26bd1SRiver Riddle   name = StringRef(name.data(), name.size() + 1);
200211d26bd1SRiver Riddle   do {
200311d26bd1SRiver Riddle     name = StringRef(name.data(), name.size() + curToken.getSpelling().size());
200411d26bd1SRiver Riddle     loc.End = curToken.getEndLoc();
200511d26bd1SRiver Riddle     consumeToken();
200611d26bd1SRiver Riddle   } while (curToken.isAny(Token::identifier, Token::dot) ||
200711d26bd1SRiver Riddle            curToken.isKeyword());
200811d26bd1SRiver Riddle   return ast::OpNameDecl::create(ctx, ast::Name::create(ctx, name, loc));
200911d26bd1SRiver Riddle }
201011d26bd1SRiver Riddle 
201112eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *>
201212eebb8eSRiver Riddle Parser::parseWrappedOperationName(bool allowEmptyName) {
201311d26bd1SRiver Riddle   if (!consumeIf(Token::less))
20146842ec42SRiver Riddle     return ast::OpNameDecl::create(ctx, SMRange());
201511d26bd1SRiver Riddle 
201612eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> opNameDecl = parseOperationName(allowEmptyName);
201711d26bd1SRiver Riddle   if (failed(opNameDecl))
201811d26bd1SRiver Riddle     return failure();
201911d26bd1SRiver Riddle 
202011d26bd1SRiver Riddle   if (failed(parseToken(Token::greater, "expected `>` after operation name")))
202111d26bd1SRiver Riddle     return failure();
202211d26bd1SRiver Riddle   return opNameDecl;
202311d26bd1SRiver Riddle }
202411d26bd1SRiver Riddle 
202591b8d96fSRiver Riddle FailureOr<ast::Expr *>
202691b8d96fSRiver Riddle Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) {
20276842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
202802670c3fSRiver Riddle   consumeToken(Token::kw_op);
202902670c3fSRiver Riddle 
203002670c3fSRiver Riddle   // If it isn't followed by a `<`, the `op` keyword is treated as a normal
203102670c3fSRiver Riddle   // identifier.
203202670c3fSRiver Riddle   if (curToken.isNot(Token::less)) {
203302670c3fSRiver Riddle     resetToken(loc);
203402670c3fSRiver Riddle     return parseIdentifierExpr();
203502670c3fSRiver Riddle   }
203602670c3fSRiver Riddle 
203702670c3fSRiver Riddle   // Parse the operation name. The name may be elided, in which case the
203802670c3fSRiver Riddle   // operation refers to "any" operation(i.e. a difference between `MyOp` and
203912eebb8eSRiver Riddle   // `Operation*`). Operation names within a rewrite context must be named.
204012eebb8eSRiver Riddle   bool allowEmptyName = parserContext != ParserContext::Rewrite;
204112eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> opNameDecl =
204212eebb8eSRiver Riddle       parseWrappedOperationName(allowEmptyName);
204302670c3fSRiver Riddle   if (failed(opNameDecl))
204402670c3fSRiver Riddle     return failure();
20450a81ace0SKazu Hirata   std::optional<StringRef> opName = (*opNameDecl)->getName();
204602670c3fSRiver Riddle 
2047a486cf5eSRiver Riddle   // Functor used to create an implicit range variable, used for implicit "all"
2048a486cf5eSRiver Riddle   // operand or results variables.
2049a486cf5eSRiver Riddle   auto createImplicitRangeVar = [&](ast::ConstraintDecl *cst, ast::Type type) {
2050a486cf5eSRiver Riddle     FailureOr<ast::VariableDecl *> rangeVar =
2051a486cf5eSRiver Riddle         defineVariableDecl("_", loc, type, ast::ConstraintRef(cst, loc));
2052a486cf5eSRiver Riddle     assert(succeeded(rangeVar) && "expected range variable to be valid");
2053a486cf5eSRiver Riddle     return ast::DeclRefExpr::create(ctx, loc, *rangeVar, type);
2054a486cf5eSRiver Riddle   };
2055a486cf5eSRiver Riddle 
205602670c3fSRiver Riddle   // Check for the optional list of operands.
205702670c3fSRiver Riddle   SmallVector<ast::Expr *> operands;
2058a486cf5eSRiver Riddle   if (!consumeIf(Token::l_paren)) {
2059a486cf5eSRiver Riddle     // If the operand list isn't specified and we are in a match context, define
2060a486cf5eSRiver Riddle     // an inplace unconstrained operand range corresponding to all of the
2061a486cf5eSRiver Riddle     // operands of the operation. This avoids treating zero operands the same
2062a486cf5eSRiver Riddle     // way as "unconstrained operands".
2063a486cf5eSRiver Riddle     if (parserContext != ParserContext::Rewrite) {
2064a486cf5eSRiver Riddle       operands.push_back(createImplicitRangeVar(
2065a486cf5eSRiver Riddle           ast::ValueRangeConstraintDecl::create(ctx, loc), valueRangeTy));
2066a486cf5eSRiver Riddle     }
2067a486cf5eSRiver Riddle   } else if (!consumeIf(Token::r_paren)) {
20680429472eSRiver Riddle     // If the operand list was specified and non-empty, parse the operands.
20690429472eSRiver Riddle     do {
2070469c5894SRiver Riddle       // Check for operand signature code completion.
2071469c5894SRiver Riddle       if (curToken.is(Token::code_complete)) {
2072469c5894SRiver Riddle         codeCompleteOperationOperandsSignature(opName, operands.size());
2073469c5894SRiver Riddle         return failure();
2074469c5894SRiver Riddle       }
2075469c5894SRiver Riddle 
207602670c3fSRiver Riddle       FailureOr<ast::Expr *> operand = parseExpr();
207702670c3fSRiver Riddle       if (failed(operand))
207802670c3fSRiver Riddle         return failure();
207902670c3fSRiver Riddle       operands.push_back(*operand);
208002670c3fSRiver Riddle     } while (consumeIf(Token::comma));
208102670c3fSRiver Riddle 
208202670c3fSRiver Riddle     if (failed(parseToken(Token::r_paren,
208302670c3fSRiver Riddle                           "expected `)` after operation operand list")))
208402670c3fSRiver Riddle       return failure();
208502670c3fSRiver Riddle   }
208602670c3fSRiver Riddle 
208702670c3fSRiver Riddle   // Check for the optional list of attributes.
208802670c3fSRiver Riddle   SmallVector<ast::NamedAttributeDecl *> attributes;
208902670c3fSRiver Riddle   if (consumeIf(Token::l_brace)) {
209002670c3fSRiver Riddle     do {
2091008de486SRiver Riddle       FailureOr<ast::NamedAttributeDecl *> decl =
2092008de486SRiver Riddle           parseNamedAttributeDecl(opName);
209302670c3fSRiver Riddle       if (failed(decl))
209402670c3fSRiver Riddle         return failure();
209502670c3fSRiver Riddle       attributes.emplace_back(*decl);
209602670c3fSRiver Riddle     } while (consumeIf(Token::comma));
209702670c3fSRiver Riddle 
209802670c3fSRiver Riddle     if (failed(parseToken(Token::r_brace,
209902670c3fSRiver Riddle                           "expected `}` after operation attribute list")))
210002670c3fSRiver Riddle       return failure();
210102670c3fSRiver Riddle   }
210202670c3fSRiver Riddle 
210391b8d96fSRiver Riddle   // Handle the result types of the operation.
210402670c3fSRiver Riddle   SmallVector<ast::Expr *> resultTypes;
210591b8d96fSRiver Riddle   OpResultTypeContext resultTypeContext = inputResultTypeContext;
210691b8d96fSRiver Riddle 
210791b8d96fSRiver Riddle   // Check for an explicit list of result types.
210802670c3fSRiver Riddle   if (consumeIf(Token::arrow)) {
210902670c3fSRiver Riddle     if (failed(parseToken(Token::l_paren,
211002670c3fSRiver Riddle                           "expected `(` before operation result type list")))
211102670c3fSRiver Riddle       return failure();
211202670c3fSRiver Riddle 
211391b8d96fSRiver Riddle     // If result types are provided, initially assume that the operation does
211491b8d96fSRiver Riddle     // not rely on type inferrence. We don't assert that it isn't, because we
211591b8d96fSRiver Riddle     // may be inferring the value of some type/type range variables, but given
211691b8d96fSRiver Riddle     // that these variables may be defined in calls we can't always discern when
211791b8d96fSRiver Riddle     // this is the case.
211891b8d96fSRiver Riddle     resultTypeContext = OpResultTypeContext::Explicit;
211991b8d96fSRiver Riddle 
2120a486cf5eSRiver Riddle     // Handle the case of an empty result list.
2121a486cf5eSRiver Riddle     if (!consumeIf(Token::r_paren)) {
212202670c3fSRiver Riddle       do {
2123469c5894SRiver Riddle         // Check for result signature code completion.
2124469c5894SRiver Riddle         if (curToken.is(Token::code_complete)) {
2125469c5894SRiver Riddle           codeCompleteOperationResultsSignature(opName, resultTypes.size());
2126469c5894SRiver Riddle           return failure();
2127469c5894SRiver Riddle         }
2128469c5894SRiver Riddle 
212902670c3fSRiver Riddle         FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
213002670c3fSRiver Riddle         if (failed(resultTypeExpr))
213102670c3fSRiver Riddle           return failure();
213202670c3fSRiver Riddle         resultTypes.push_back(*resultTypeExpr);
213302670c3fSRiver Riddle       } while (consumeIf(Token::comma));
213402670c3fSRiver Riddle 
213502670c3fSRiver Riddle       if (failed(parseToken(Token::r_paren,
213602670c3fSRiver Riddle                             "expected `)` after operation result type list")))
213702670c3fSRiver Riddle         return failure();
213802670c3fSRiver Riddle     }
2139a486cf5eSRiver Riddle   } else if (parserContext != ParserContext::Rewrite) {
2140a486cf5eSRiver Riddle     // If the result list isn't specified and we are in a match context, define
2141a486cf5eSRiver Riddle     // an inplace unconstrained result range corresponding to all of the results
2142a486cf5eSRiver Riddle     // of the operation. This avoids treating zero results the same way as
2143a486cf5eSRiver Riddle     // "unconstrained results".
2144a486cf5eSRiver Riddle     resultTypes.push_back(createImplicitRangeVar(
2145a486cf5eSRiver Riddle         ast::TypeRangeConstraintDecl::create(ctx, loc), typeRangeTy));
214691b8d96fSRiver Riddle   } else if (resultTypeContext == OpResultTypeContext::Explicit) {
214791b8d96fSRiver Riddle     // If the result list isn't specified and we are in a rewrite, try to infer
214891b8d96fSRiver Riddle     // them at runtime instead.
214991b8d96fSRiver Riddle     resultTypeContext = OpResultTypeContext::Interface;
2150a486cf5eSRiver Riddle   }
215102670c3fSRiver Riddle 
215291b8d96fSRiver Riddle   return createOperationExpr(loc, *opNameDecl, resultTypeContext, operands,
215391b8d96fSRiver Riddle                              attributes, resultTypes);
215402670c3fSRiver Riddle }
215502670c3fSRiver Riddle 
2156f62a57a3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTupleExpr() {
21576842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
2158f62a57a3SRiver Riddle   consumeToken(Token::l_paren);
2159f62a57a3SRiver Riddle 
21606842ec42SRiver Riddle   DenseMap<StringRef, SMRange> usedNames;
2161f62a57a3SRiver Riddle   SmallVector<StringRef> elementNames;
2162f62a57a3SRiver Riddle   SmallVector<ast::Expr *> elements;
2163f62a57a3SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
2164f62a57a3SRiver Riddle     do {
2165f62a57a3SRiver Riddle       // Check for the optional element name assignment before the value.
2166f62a57a3SRiver Riddle       StringRef elementName;
2167f62a57a3SRiver Riddle       if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) {
2168f62a57a3SRiver Riddle         Token elementNameTok = curToken;
2169f62a57a3SRiver Riddle         consumeToken();
2170f62a57a3SRiver Riddle 
2171f62a57a3SRiver Riddle         // The element name is only present if followed by an `=`.
2172f62a57a3SRiver Riddle         if (consumeIf(Token::equal)) {
2173f62a57a3SRiver Riddle           elementName = elementNameTok.getSpelling();
2174f62a57a3SRiver Riddle 
2175f62a57a3SRiver Riddle           // Check to see if this name is already used.
2176f62a57a3SRiver Riddle           auto elementNameIt =
2177f62a57a3SRiver Riddle               usedNames.try_emplace(elementName, elementNameTok.getLoc());
2178f62a57a3SRiver Riddle           if (!elementNameIt.second) {
2179f62a57a3SRiver Riddle             return emitErrorAndNote(
2180f62a57a3SRiver Riddle                 elementNameTok.getLoc(),
2181f62a57a3SRiver Riddle                 llvm::formatv("duplicate tuple element label `{0}`",
2182f62a57a3SRiver Riddle                               elementName),
2183f62a57a3SRiver Riddle                 elementNameIt.first->getSecond(),
2184f62a57a3SRiver Riddle                 "see previous label use here");
2185f62a57a3SRiver Riddle           }
2186f62a57a3SRiver Riddle         } else {
2187f62a57a3SRiver Riddle           // Otherwise, we treat this as part of an expression so reset the
2188f62a57a3SRiver Riddle           // lexer.
2189f62a57a3SRiver Riddle           resetToken(elementNameTok.getLoc());
2190f62a57a3SRiver Riddle         }
2191f62a57a3SRiver Riddle       }
2192f62a57a3SRiver Riddle       elementNames.push_back(elementName);
2193f62a57a3SRiver Riddle 
2194f62a57a3SRiver Riddle       // Parse the tuple element value.
2195f62a57a3SRiver Riddle       FailureOr<ast::Expr *> element = parseExpr();
2196f62a57a3SRiver Riddle       if (failed(element))
2197f62a57a3SRiver Riddle         return failure();
2198f62a57a3SRiver Riddle       elements.push_back(*element);
2199f62a57a3SRiver Riddle     } while (consumeIf(Token::comma));
2200f62a57a3SRiver Riddle   }
2201f62a57a3SRiver Riddle   loc.End = curToken.getEndLoc();
2202f62a57a3SRiver Riddle   if (failed(
2203f62a57a3SRiver Riddle           parseToken(Token::r_paren, "expected `)` after tuple element list")))
2204f62a57a3SRiver Riddle     return failure();
2205f62a57a3SRiver Riddle   return createTupleExpr(loc, elements, elementNames);
2206f62a57a3SRiver Riddle }
2207f62a57a3SRiver Riddle 
2208d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeExpr() {
22096842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
2210d7e7fdf3SRiver Riddle   consumeToken(Token::kw_type);
2211d7e7fdf3SRiver Riddle 
2212d7e7fdf3SRiver Riddle   // If we aren't followed by a `<`, the `type` keyword is treated as a normal
2213d7e7fdf3SRiver Riddle   // identifier.
2214d7e7fdf3SRiver Riddle   if (!consumeIf(Token::less)) {
2215d7e7fdf3SRiver Riddle     resetToken(loc);
2216d7e7fdf3SRiver Riddle     return parseIdentifierExpr();
2217d7e7fdf3SRiver Riddle   }
2218d7e7fdf3SRiver Riddle 
2219d7e7fdf3SRiver Riddle   if (!curToken.isString())
2220d7e7fdf3SRiver Riddle     return emitError("expected string literal containing MLIR type");
2221d7e7fdf3SRiver Riddle   std::string attrExpr = curToken.getStringValue();
2222d7e7fdf3SRiver Riddle   consumeToken();
2223d7e7fdf3SRiver Riddle 
22246d4471efSRiver Riddle   loc.End = curToken.getEndLoc();
2225d7e7fdf3SRiver Riddle   if (failed(parseToken(Token::greater, "expected `>` after type literal")))
2226d7e7fdf3SRiver Riddle     return failure();
2227d7e7fdf3SRiver Riddle   return ast::TypeExpr::create(ctx, loc, attrExpr);
2228d7e7fdf3SRiver Riddle }
2229d7e7fdf3SRiver Riddle 
223011d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseUnderscoreExpr() {
223111d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
22326842ec42SRiver Riddle   SMRange nameLoc = curToken.getLoc();
223311d26bd1SRiver Riddle   consumeToken(Token::underscore);
223411d26bd1SRiver Riddle 
223511d26bd1SRiver Riddle   // Underscore expressions require a constraint list.
223611d26bd1SRiver Riddle   if (failed(parseToken(Token::colon, "expected `:` after `_` variable")))
223711d26bd1SRiver Riddle     return failure();
223811d26bd1SRiver Riddle 
223911d26bd1SRiver Riddle   // Parse the constraints for the expression.
224011d26bd1SRiver Riddle   SmallVector<ast::ConstraintRef> constraints;
224111d26bd1SRiver Riddle   if (failed(parseVariableDeclConstraintList(constraints)))
224211d26bd1SRiver Riddle     return failure();
224311d26bd1SRiver Riddle 
224411d26bd1SRiver Riddle   ast::Type type;
224511d26bd1SRiver Riddle   if (failed(validateVariableConstraints(constraints, type)))
224611d26bd1SRiver Riddle     return failure();
224711d26bd1SRiver Riddle   return createInlineVariableExpr(type, name, nameLoc, constraints);
224811d26bd1SRiver Riddle }
224911d26bd1SRiver Riddle 
225011d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
225111d26bd1SRiver Riddle // Stmts
225211d26bd1SRiver Riddle 
225311d26bd1SRiver Riddle FailureOr<ast::Stmt *> Parser::parseStmt(bool expectTerminalSemicolon) {
225411d26bd1SRiver Riddle   FailureOr<ast::Stmt *> stmt;
225511d26bd1SRiver Riddle   switch (curToken.getKind()) {
225611d26bd1SRiver Riddle   case Token::kw_erase:
225711d26bd1SRiver Riddle     stmt = parseEraseStmt();
225811d26bd1SRiver Riddle     break;
225911d26bd1SRiver Riddle   case Token::kw_let:
226011d26bd1SRiver Riddle     stmt = parseLetStmt();
226111d26bd1SRiver Riddle     break;
226212eebb8eSRiver Riddle   case Token::kw_replace:
226312eebb8eSRiver Riddle     stmt = parseReplaceStmt();
226412eebb8eSRiver Riddle     break;
2265faf42264SRiver Riddle   case Token::kw_return:
2266faf42264SRiver Riddle     stmt = parseReturnStmt();
2267faf42264SRiver Riddle     break;
22683ee44cb7SRiver Riddle   case Token::kw_rewrite:
22693ee44cb7SRiver Riddle     stmt = parseRewriteStmt();
22703ee44cb7SRiver Riddle     break;
227111d26bd1SRiver Riddle   default:
227211d26bd1SRiver Riddle     stmt = parseExpr();
227311d26bd1SRiver Riddle     break;
227411d26bd1SRiver Riddle   }
227511d26bd1SRiver Riddle   if (failed(stmt) ||
227611d26bd1SRiver Riddle       (expectTerminalSemicolon &&
227711d26bd1SRiver Riddle        failed(parseToken(Token::semicolon, "expected `;` after statement"))))
227811d26bd1SRiver Riddle     return failure();
227911d26bd1SRiver Riddle   return stmt;
228011d26bd1SRiver Riddle }
228111d26bd1SRiver Riddle 
228211d26bd1SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseCompoundStmt() {
22836842ec42SRiver Riddle   SMLoc startLoc = curToken.getStartLoc();
228411d26bd1SRiver Riddle   consumeToken(Token::l_brace);
228511d26bd1SRiver Riddle 
228611d26bd1SRiver Riddle   // Push a new block scope and parse any nested statements.
228711d26bd1SRiver Riddle   pushDeclScope();
228811d26bd1SRiver Riddle   SmallVector<ast::Stmt *> statements;
228911d26bd1SRiver Riddle   while (curToken.isNot(Token::r_brace)) {
229011d26bd1SRiver Riddle     FailureOr<ast::Stmt *> statement = parseStmt();
229111d26bd1SRiver Riddle     if (failed(statement))
229211d26bd1SRiver Riddle       return popDeclScope(), failure();
229311d26bd1SRiver Riddle     statements.push_back(*statement);
229411d26bd1SRiver Riddle   }
229511d26bd1SRiver Riddle   popDeclScope();
229611d26bd1SRiver Riddle 
229711d26bd1SRiver Riddle   // Consume the end brace.
22986842ec42SRiver Riddle   SMRange location(startLoc, curToken.getEndLoc());
229911d26bd1SRiver Riddle   consumeToken(Token::r_brace);
230011d26bd1SRiver Riddle 
230111d26bd1SRiver Riddle   return ast::CompoundStmt::create(ctx, location, statements);
230211d26bd1SRiver Riddle }
230311d26bd1SRiver Riddle 
230411d26bd1SRiver Riddle FailureOr<ast::EraseStmt *> Parser::parseEraseStmt() {
2305faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2306faf42264SRiver Riddle     return emitError("`erase` cannot be used within a Constraint");
23076842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
230811d26bd1SRiver Riddle   consumeToken(Token::kw_erase);
230911d26bd1SRiver Riddle 
231011d26bd1SRiver Riddle   // Parse the root operation expression.
231111d26bd1SRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
231211d26bd1SRiver Riddle   if (failed(rootOp))
231311d26bd1SRiver Riddle     return failure();
231411d26bd1SRiver Riddle 
231511d26bd1SRiver Riddle   return createEraseStmt(loc, *rootOp);
231611d26bd1SRiver Riddle }
231711d26bd1SRiver Riddle 
231811d26bd1SRiver Riddle FailureOr<ast::LetStmt *> Parser::parseLetStmt() {
23196842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
232011d26bd1SRiver Riddle   consumeToken(Token::kw_let);
232111d26bd1SRiver Riddle 
232211d26bd1SRiver Riddle   // Parse the name of the new variable.
23236842ec42SRiver Riddle   SMRange varLoc = curToken.getLoc();
232411d26bd1SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword()) {
232511d26bd1SRiver Riddle     // `_` is a reserved variable name.
232611d26bd1SRiver Riddle     if (curToken.is(Token::underscore)) {
232711d26bd1SRiver Riddle       return emitError(varLoc,
232811d26bd1SRiver Riddle                        "`_` may only be used to define \"inline\" variables");
232911d26bd1SRiver Riddle     }
233011d26bd1SRiver Riddle     return emitError(varLoc,
233111d26bd1SRiver Riddle                      "expected identifier after `let` to name a new variable");
233211d26bd1SRiver Riddle   }
233311d26bd1SRiver Riddle   StringRef varName = curToken.getSpelling();
233411d26bd1SRiver Riddle   consumeToken();
233511d26bd1SRiver Riddle 
233611d26bd1SRiver Riddle   // Parse the optional set of constraints.
233711d26bd1SRiver Riddle   SmallVector<ast::ConstraintRef> constraints;
233811d26bd1SRiver Riddle   if (consumeIf(Token::colon) &&
233911d26bd1SRiver Riddle       failed(parseVariableDeclConstraintList(constraints)))
234011d26bd1SRiver Riddle     return failure();
234111d26bd1SRiver Riddle 
234211d26bd1SRiver Riddle   // Parse the optional initializer expression.
234311d26bd1SRiver Riddle   ast::Expr *initializer = nullptr;
234411d26bd1SRiver Riddle   if (consumeIf(Token::equal)) {
234511d26bd1SRiver Riddle     FailureOr<ast::Expr *> initOrFailure = parseExpr();
234611d26bd1SRiver Riddle     if (failed(initOrFailure))
234711d26bd1SRiver Riddle       return failure();
234811d26bd1SRiver Riddle     initializer = *initOrFailure;
234911d26bd1SRiver Riddle 
235011d26bd1SRiver Riddle     // Check that the constraints are compatible with having an initializer,
235111d26bd1SRiver Riddle     // e.g. type constraints cannot be used with initializers.
235211d26bd1SRiver Riddle     for (ast::ConstraintRef constraint : constraints) {
235311d26bd1SRiver Riddle       LogicalResult result =
235411d26bd1SRiver Riddle           TypeSwitch<const ast::Node *, LogicalResult>(constraint.constraint)
235511d26bd1SRiver Riddle               .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl,
235611d26bd1SRiver Riddle                     ast::ValueRangeConstraintDecl>([&](const auto *cst) {
23570a0aff2dSMikhail Goncharov                 if (cst->getTypeExpr()) {
2358e76043acSRiver Riddle                   return this->emitError(
235911d26bd1SRiver Riddle                       constraint.referenceLoc,
236011d26bd1SRiver Riddle                       "type constraints are not permitted on variables with "
236111d26bd1SRiver Riddle                       "initializers");
236211d26bd1SRiver Riddle                 }
236311d26bd1SRiver Riddle                 return success();
236411d26bd1SRiver Riddle               })
236511d26bd1SRiver Riddle               .Default(success());
236611d26bd1SRiver Riddle       if (failed(result))
236711d26bd1SRiver Riddle         return failure();
236811d26bd1SRiver Riddle     }
236911d26bd1SRiver Riddle   }
237011d26bd1SRiver Riddle 
237111d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> varDecl =
237211d26bd1SRiver Riddle       createVariableDecl(varName, varLoc, initializer, constraints);
237311d26bd1SRiver Riddle   if (failed(varDecl))
237411d26bd1SRiver Riddle     return failure();
237511d26bd1SRiver Riddle   return ast::LetStmt::create(ctx, loc, *varDecl);
237611d26bd1SRiver Riddle }
237711d26bd1SRiver Riddle 
237812eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> Parser::parseReplaceStmt() {
2379faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2380faf42264SRiver Riddle     return emitError("`replace` cannot be used within a Constraint");
23816842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
238212eebb8eSRiver Riddle   consumeToken(Token::kw_replace);
238312eebb8eSRiver Riddle 
238412eebb8eSRiver Riddle   // Parse the root operation expression.
238512eebb8eSRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
238612eebb8eSRiver Riddle   if (failed(rootOp))
238712eebb8eSRiver Riddle     return failure();
238812eebb8eSRiver Riddle 
238912eebb8eSRiver Riddle   if (failed(
239012eebb8eSRiver Riddle           parseToken(Token::kw_with, "expected `with` after root operation")))
239112eebb8eSRiver Riddle     return failure();
239212eebb8eSRiver Riddle 
239312eebb8eSRiver Riddle   // The replacement portion of this statement is within a rewrite context.
2394abf0c6c0SJan Svoboda   llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
239512eebb8eSRiver Riddle 
239612eebb8eSRiver Riddle   // Parse the replacement values.
239712eebb8eSRiver Riddle   SmallVector<ast::Expr *> replValues;
239812eebb8eSRiver Riddle   if (consumeIf(Token::l_paren)) {
239912eebb8eSRiver Riddle     if (consumeIf(Token::r_paren)) {
240012eebb8eSRiver Riddle       return emitError(
240112eebb8eSRiver Riddle           loc, "expected at least one replacement value, consider using "
240212eebb8eSRiver Riddle                "`erase` if no replacement values are desired");
240312eebb8eSRiver Riddle     }
240412eebb8eSRiver Riddle 
240512eebb8eSRiver Riddle     do {
240612eebb8eSRiver Riddle       FailureOr<ast::Expr *> replExpr = parseExpr();
240712eebb8eSRiver Riddle       if (failed(replExpr))
240812eebb8eSRiver Riddle         return failure();
240912eebb8eSRiver Riddle       replValues.emplace_back(*replExpr);
241012eebb8eSRiver Riddle     } while (consumeIf(Token::comma));
241112eebb8eSRiver Riddle 
241212eebb8eSRiver Riddle     if (failed(parseToken(Token::r_paren,
241312eebb8eSRiver Riddle                           "expected `)` after replacement values")))
241412eebb8eSRiver Riddle       return failure();
241512eebb8eSRiver Riddle   } else {
241691b8d96fSRiver Riddle     // Handle replacement with an operation uniquely, as the replacement
241791b8d96fSRiver Riddle     // operation supports type inferrence from the root operation.
241891b8d96fSRiver Riddle     FailureOr<ast::Expr *> replExpr;
241991b8d96fSRiver Riddle     if (curToken.is(Token::kw_op))
242091b8d96fSRiver Riddle       replExpr = parseOperationExpr(OpResultTypeContext::Replacement);
242191b8d96fSRiver Riddle     else
242291b8d96fSRiver Riddle       replExpr = parseExpr();
242312eebb8eSRiver Riddle     if (failed(replExpr))
242412eebb8eSRiver Riddle       return failure();
242512eebb8eSRiver Riddle     replValues.emplace_back(*replExpr);
242612eebb8eSRiver Riddle   }
242712eebb8eSRiver Riddle 
242812eebb8eSRiver Riddle   return createReplaceStmt(loc, *rootOp, replValues);
242912eebb8eSRiver Riddle }
243012eebb8eSRiver Riddle 
2431faf42264SRiver Riddle FailureOr<ast::ReturnStmt *> Parser::parseReturnStmt() {
2432faf42264SRiver Riddle   SMRange loc = curToken.getLoc();
2433faf42264SRiver Riddle   consumeToken(Token::kw_return);
2434faf42264SRiver Riddle 
2435faf42264SRiver Riddle   // Parse the result value.
2436faf42264SRiver Riddle   FailureOr<ast::Expr *> resultExpr = parseExpr();
2437faf42264SRiver Riddle   if (failed(resultExpr))
2438faf42264SRiver Riddle     return failure();
2439faf42264SRiver Riddle 
2440faf42264SRiver Riddle   return ast::ReturnStmt::create(ctx, loc, *resultExpr);
2441faf42264SRiver Riddle }
2442faf42264SRiver Riddle 
24433ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> Parser::parseRewriteStmt() {
2444faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2445faf42264SRiver Riddle     return emitError("`rewrite` cannot be used within a Constraint");
24466842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
24473ee44cb7SRiver Riddle   consumeToken(Token::kw_rewrite);
24483ee44cb7SRiver Riddle 
24493ee44cb7SRiver Riddle   // Parse the root operation.
24503ee44cb7SRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
24513ee44cb7SRiver Riddle   if (failed(rootOp))
24523ee44cb7SRiver Riddle     return failure();
24533ee44cb7SRiver Riddle 
24543ee44cb7SRiver Riddle   if (failed(parseToken(Token::kw_with, "expected `with` before rewrite body")))
24553ee44cb7SRiver Riddle     return failure();
24563ee44cb7SRiver Riddle 
24573ee44cb7SRiver Riddle   if (curToken.isNot(Token::l_brace))
24583ee44cb7SRiver Riddle     return emitError("expected `{` to start rewrite body");
24593ee44cb7SRiver Riddle 
24603ee44cb7SRiver Riddle   // The rewrite body of this statement is within a rewrite context.
2461abf0c6c0SJan Svoboda   llvm::SaveAndRestore saveCtx(parserContext, ParserContext::Rewrite);
24623ee44cb7SRiver Riddle 
24633ee44cb7SRiver Riddle   FailureOr<ast::CompoundStmt *> rewriteBody = parseCompoundStmt();
24643ee44cb7SRiver Riddle   if (failed(rewriteBody))
24653ee44cb7SRiver Riddle     return failure();
24663ee44cb7SRiver Riddle 
2467faf42264SRiver Riddle   // Verify the rewrite body.
2468faf42264SRiver Riddle   for (const ast::Stmt *stmt : (*rewriteBody)->getChildren()) {
2469faf42264SRiver Riddle     if (isa<ast::ReturnStmt>(stmt)) {
2470faf42264SRiver Riddle       return emitError(stmt->getLoc(),
2471faf42264SRiver Riddle                        "`return` statements are only permitted within a "
2472faf42264SRiver Riddle                        "`Constraint` or `Rewrite` body");
2473faf42264SRiver Riddle     }
2474faf42264SRiver Riddle   }
2475faf42264SRiver Riddle 
24763ee44cb7SRiver Riddle   return createRewriteStmt(loc, *rootOp, *rewriteBody);
24773ee44cb7SRiver Riddle }
24783ee44cb7SRiver Riddle 
247911d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
248011d26bd1SRiver Riddle // Creation+Analysis
248111d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
248211d26bd1SRiver Riddle 
248311d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
248411d26bd1SRiver Riddle // Decls
248511d26bd1SRiver Riddle 
2486faf42264SRiver Riddle ast::CallableDecl *Parser::tryExtractCallableDecl(ast::Node *node) {
2487faf42264SRiver Riddle   // Unwrap reference expressions.
2488faf42264SRiver Riddle   if (auto *init = dyn_cast<ast::DeclRefExpr>(node))
2489faf42264SRiver Riddle     node = init->getDecl();
2490faf42264SRiver Riddle   return dyn_cast<ast::CallableDecl>(node);
2491faf42264SRiver Riddle }
2492faf42264SRiver Riddle 
249311d26bd1SRiver Riddle FailureOr<ast::PatternDecl *>
24946842ec42SRiver Riddle Parser::createPatternDecl(SMRange loc, const ast::Name *name,
2495322691abSRiver Riddle                           const ParsedPatternMetadata &metadata,
249611d26bd1SRiver Riddle                           ast::CompoundStmt *body) {
2497322691abSRiver Riddle   return ast::PatternDecl::create(ctx, loc, name, metadata.benefit,
2498322691abSRiver Riddle                                   metadata.hasBoundedRecursion, body);
249911d26bd1SRiver Riddle }
250011d26bd1SRiver Riddle 
2501faf42264SRiver Riddle ast::Type Parser::createUserConstraintRewriteResultType(
2502faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results) {
2503faf42264SRiver Riddle   // Single result decls use the type of the single result.
2504faf42264SRiver Riddle   if (results.size() == 1)
2505faf42264SRiver Riddle     return results[0]->getType();
2506faf42264SRiver Riddle 
2507faf42264SRiver Riddle   // Multiple results use a tuple type, with the types and names grabbed from
2508faf42264SRiver Riddle   // the result variable decls.
2509faf42264SRiver Riddle   auto resultTypes = llvm::map_range(
2510faf42264SRiver Riddle       results, [&](const auto *result) { return result->getType(); });
2511faf42264SRiver Riddle   auto resultNames = llvm::map_range(
2512faf42264SRiver Riddle       results, [&](const auto *result) { return result->getName().getName(); });
2513faf42264SRiver Riddle   return ast::TupleType::get(ctx, llvm::to_vector(resultTypes),
2514faf42264SRiver Riddle                              llvm::to_vector(resultNames));
2515faf42264SRiver Riddle }
2516faf42264SRiver Riddle 
2517faf42264SRiver Riddle template <typename T>
2518faf42264SRiver Riddle FailureOr<T *> Parser::createUserPDLLConstraintOrRewriteDecl(
2519faf42264SRiver Riddle     const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
2520faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
2521faf42264SRiver Riddle     ast::CompoundStmt *body) {
2522faf42264SRiver Riddle   if (!body->getChildren().empty()) {
2523faf42264SRiver Riddle     if (auto *retStmt = dyn_cast<ast::ReturnStmt>(body->getChildren().back())) {
2524faf42264SRiver Riddle       ast::Expr *resultExpr = retStmt->getResultExpr();
2525faf42264SRiver Riddle 
2526faf42264SRiver Riddle       // Process the result of the decl. If no explicit signature results
2527faf42264SRiver Riddle       // were provided, check for return type inference. Otherwise, check that
2528faf42264SRiver Riddle       // the return expression can be converted to the expected type.
2529faf42264SRiver Riddle       if (results.empty())
2530faf42264SRiver Riddle         resultType = resultExpr->getType();
2531faf42264SRiver Riddle       else if (failed(convertExpressionTo(resultExpr, resultType)))
2532faf42264SRiver Riddle         return failure();
2533faf42264SRiver Riddle       else
2534faf42264SRiver Riddle         retStmt->setResultExpr(resultExpr);
2535faf42264SRiver Riddle     }
2536faf42264SRiver Riddle   }
2537faf42264SRiver Riddle   return T::createPDLL(ctx, name, arguments, results, body, resultType);
2538faf42264SRiver Riddle }
2539faf42264SRiver Riddle 
254011d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
2541faf42264SRiver Riddle Parser::createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
254211d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
254311d26bd1SRiver Riddle   // The type of the variable, which is expected to be inferred by either a
254411d26bd1SRiver Riddle   // constraint or an initializer expression.
254511d26bd1SRiver Riddle   ast::Type type;
254611d26bd1SRiver Riddle   if (failed(validateVariableConstraints(constraints, type)))
254711d26bd1SRiver Riddle     return failure();
254811d26bd1SRiver Riddle 
254911d26bd1SRiver Riddle   if (initializer) {
255011d26bd1SRiver Riddle     // Update the variable type based on the initializer, or try to convert the
255111d26bd1SRiver Riddle     // initializer to the existing type.
255211d26bd1SRiver Riddle     if (!type)
255311d26bd1SRiver Riddle       type = initializer->getType();
255411d26bd1SRiver Riddle     else if (ast::Type mergedType = type.refineWith(initializer->getType()))
255511d26bd1SRiver Riddle       type = mergedType;
255611d26bd1SRiver Riddle     else if (failed(convertExpressionTo(initializer, type)))
255711d26bd1SRiver Riddle       return failure();
255811d26bd1SRiver Riddle 
255911d26bd1SRiver Riddle     // Otherwise, if there is no initializer check that the type has already
256011d26bd1SRiver Riddle     // been resolved from the constraint list.
256111d26bd1SRiver Riddle   } else if (!type) {
256211d26bd1SRiver Riddle     return emitErrorAndNote(
256311d26bd1SRiver Riddle         loc, "unable to infer type for variable `" + name + "`", loc,
256411d26bd1SRiver Riddle         "the type of a variable must be inferable from the constraint "
256511d26bd1SRiver Riddle         "list or the initializer");
256611d26bd1SRiver Riddle   }
256711d26bd1SRiver Riddle 
2568faf42264SRiver Riddle   // Constraint types cannot be used when defining variables.
2569d2353695SPeiming Liu   if (isa<ast::ConstraintType, ast::RewriteType>(type)) {
2570faf42264SRiver Riddle     return emitError(
2571faf42264SRiver Riddle         loc, llvm::formatv("unable to define variable of `{0}` type", type));
2572faf42264SRiver Riddle   }
2573faf42264SRiver Riddle 
257411d26bd1SRiver Riddle   // Try to define a variable with the given name.
257511d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> varDecl =
257611d26bd1SRiver Riddle       defineVariableDecl(name, loc, type, initializer, constraints);
257711d26bd1SRiver Riddle   if (failed(varDecl))
257811d26bd1SRiver Riddle     return failure();
257911d26bd1SRiver Riddle 
258011d26bd1SRiver Riddle   return *varDecl;
258111d26bd1SRiver Riddle }
258211d26bd1SRiver Riddle 
2583faf42264SRiver Riddle FailureOr<ast::VariableDecl *>
2584faf42264SRiver Riddle Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc,
2585faf42264SRiver Riddle                                       const ast::ConstraintRef &constraint) {
2586faf42264SRiver Riddle   ast::Type argType;
2587b6ec1de7SRiver Riddle   if (failed(validateVariableConstraint(constraint, argType)))
2588faf42264SRiver Riddle     return failure();
2589faf42264SRiver Riddle   return defineVariableDecl(name, loc, argType, constraint);
2590faf42264SRiver Riddle }
2591faf42264SRiver Riddle 
259211d26bd1SRiver Riddle LogicalResult
259311d26bd1SRiver Riddle Parser::validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
2594b6ec1de7SRiver Riddle                                     ast::Type &inferredType) {
259511d26bd1SRiver Riddle   for (const ast::ConstraintRef &ref : constraints)
2596b6ec1de7SRiver Riddle     if (failed(validateVariableConstraint(ref, inferredType)))
259711d26bd1SRiver Riddle       return failure();
259811d26bd1SRiver Riddle   return success();
259911d26bd1SRiver Riddle }
260011d26bd1SRiver Riddle 
260111d26bd1SRiver Riddle LogicalResult Parser::validateVariableConstraint(const ast::ConstraintRef &ref,
2602b6ec1de7SRiver Riddle                                                  ast::Type &inferredType) {
260311d26bd1SRiver Riddle   ast::Type constraintType;
260411d26bd1SRiver Riddle   if (const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.constraint)) {
260511d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
260611d26bd1SRiver Riddle       if (failed(validateTypeConstraintExpr(typeExpr)))
260711d26bd1SRiver Riddle         return failure();
260811d26bd1SRiver Riddle     }
260911d26bd1SRiver Riddle     constraintType = ast::AttributeType::get(ctx);
261011d26bd1SRiver Riddle   } else if (const auto *cst =
261111d26bd1SRiver Riddle                  dyn_cast<ast::OpConstraintDecl>(ref.constraint)) {
26121c2edb02SRiver Riddle     constraintType = ast::OperationType::get(
26131c2edb02SRiver Riddle         ctx, cst->getName(), lookupODSOperation(cst->getName()));
261411d26bd1SRiver Riddle   } else if (isa<ast::TypeConstraintDecl>(ref.constraint)) {
261511d26bd1SRiver Riddle     constraintType = typeTy;
261611d26bd1SRiver Riddle   } else if (isa<ast::TypeRangeConstraintDecl>(ref.constraint)) {
261711d26bd1SRiver Riddle     constraintType = typeRangeTy;
261811d26bd1SRiver Riddle   } else if (const auto *cst =
261911d26bd1SRiver Riddle                  dyn_cast<ast::ValueConstraintDecl>(ref.constraint)) {
262011d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
262111d26bd1SRiver Riddle       if (failed(validateTypeConstraintExpr(typeExpr)))
262211d26bd1SRiver Riddle         return failure();
262311d26bd1SRiver Riddle     }
262411d26bd1SRiver Riddle     constraintType = valueTy;
262511d26bd1SRiver Riddle   } else if (const auto *cst =
262611d26bd1SRiver Riddle                  dyn_cast<ast::ValueRangeConstraintDecl>(ref.constraint)) {
262711d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
262811d26bd1SRiver Riddle       if (failed(validateTypeRangeConstraintExpr(typeExpr)))
262911d26bd1SRiver Riddle         return failure();
263011d26bd1SRiver Riddle     }
263111d26bd1SRiver Riddle     constraintType = valueRangeTy;
2632faf42264SRiver Riddle   } else if (const auto *cst =
2633faf42264SRiver Riddle                  dyn_cast<ast::UserConstraintDecl>(ref.constraint)) {
2634faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> inputs = cst->getInputs();
2635faf42264SRiver Riddle     if (inputs.size() != 1) {
2636faf42264SRiver Riddle       return emitErrorAndNote(ref.referenceLoc,
2637faf42264SRiver Riddle                               "`Constraint`s applied via a variable constraint "
2638faf42264SRiver Riddle                               "list must take a single input, but got " +
2639faf42264SRiver Riddle                                   Twine(inputs.size()),
2640faf42264SRiver Riddle                               cst->getLoc(),
2641faf42264SRiver Riddle                               "see definition of constraint here");
2642faf42264SRiver Riddle     }
2643faf42264SRiver Riddle     constraintType = inputs.front()->getType();
264411d26bd1SRiver Riddle   } else {
264511d26bd1SRiver Riddle     llvm_unreachable("unknown constraint type");
264611d26bd1SRiver Riddle   }
264711d26bd1SRiver Riddle 
264811d26bd1SRiver Riddle   // Check that the constraint type is compatible with the current inferred
264911d26bd1SRiver Riddle   // type.
265011d26bd1SRiver Riddle   if (!inferredType) {
265111d26bd1SRiver Riddle     inferredType = constraintType;
265211d26bd1SRiver Riddle   } else if (ast::Type mergedTy = inferredType.refineWith(constraintType)) {
265311d26bd1SRiver Riddle     inferredType = mergedTy;
265411d26bd1SRiver Riddle   } else {
265511d26bd1SRiver Riddle     return emitError(ref.referenceLoc,
265611d26bd1SRiver Riddle                      llvm::formatv("constraint type `{0}` is incompatible "
265711d26bd1SRiver Riddle                                    "with the previously inferred type `{1}`",
265811d26bd1SRiver Riddle                                    constraintType, inferredType));
265911d26bd1SRiver Riddle   }
266011d26bd1SRiver Riddle   return success();
266111d26bd1SRiver Riddle }
266211d26bd1SRiver Riddle 
266311d26bd1SRiver Riddle LogicalResult Parser::validateTypeConstraintExpr(const ast::Expr *typeExpr) {
266411d26bd1SRiver Riddle   ast::Type typeExprType = typeExpr->getType();
266511d26bd1SRiver Riddle   if (typeExprType != typeTy) {
266611d26bd1SRiver Riddle     return emitError(typeExpr->getLoc(),
266711d26bd1SRiver Riddle                      "expected expression of `Type` in type constraint");
266811d26bd1SRiver Riddle   }
266911d26bd1SRiver Riddle   return success();
267011d26bd1SRiver Riddle }
267111d26bd1SRiver Riddle 
267211d26bd1SRiver Riddle LogicalResult
267311d26bd1SRiver Riddle Parser::validateTypeRangeConstraintExpr(const ast::Expr *typeExpr) {
267411d26bd1SRiver Riddle   ast::Type typeExprType = typeExpr->getType();
267511d26bd1SRiver Riddle   if (typeExprType != typeRangeTy) {
267611d26bd1SRiver Riddle     return emitError(typeExpr->getLoc(),
267711d26bd1SRiver Riddle                      "expected expression of `TypeRange` in type constraint");
267811d26bd1SRiver Riddle   }
267911d26bd1SRiver Riddle   return success();
268011d26bd1SRiver Riddle }
268111d26bd1SRiver Riddle 
268211d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
268311d26bd1SRiver Riddle // Exprs
268411d26bd1SRiver Riddle 
2685faf42264SRiver Riddle FailureOr<ast::CallExpr *>
2686faf42264SRiver Riddle Parser::createCallExpr(SMRange loc, ast::Expr *parentExpr,
2687930916c7SMogball                        MutableArrayRef<ast::Expr *> arguments, bool isNegated) {
2688faf42264SRiver Riddle   ast::Type parentType = parentExpr->getType();
2689faf42264SRiver Riddle 
2690faf42264SRiver Riddle   ast::CallableDecl *callableDecl = tryExtractCallableDecl(parentExpr);
2691faf42264SRiver Riddle   if (!callableDecl) {
2692faf42264SRiver Riddle     return emitError(loc,
2693faf42264SRiver Riddle                      llvm::formatv("expected a reference to a callable "
2694faf42264SRiver Riddle                                    "`Constraint` or `Rewrite`, but got: `{0}`",
2695faf42264SRiver Riddle                                    parentType));
2696faf42264SRiver Riddle   }
2697faf42264SRiver Riddle   if (parserContext == ParserContext::Rewrite) {
2698faf42264SRiver Riddle     if (isa<ast::UserConstraintDecl>(callableDecl))
2699faf42264SRiver Riddle       return emitError(
2700faf42264SRiver Riddle           loc, "unable to invoke `Constraint` within a rewrite section");
2701930916c7SMogball     if (isNegated)
2702930916c7SMogball       return emitError(loc, "unable to negate a Rewrite");
2703930916c7SMogball   } else {
2704930916c7SMogball     if (isa<ast::UserRewriteDecl>(callableDecl))
2705930916c7SMogball       return emitError(loc,
2706930916c7SMogball                        "unable to invoke `Rewrite` within a match section");
2707930916c7SMogball     if (isNegated && cast<ast::UserConstraintDecl>(callableDecl)->getBody())
2708930916c7SMogball       return emitError(loc, "unable to negate non native constraints");
2709faf42264SRiver Riddle   }
2710faf42264SRiver Riddle 
2711faf42264SRiver Riddle   // Verify the arguments of the call.
2712faf42264SRiver Riddle   /// Handle size mismatch.
2713faf42264SRiver Riddle   ArrayRef<ast::VariableDecl *> callArgs = callableDecl->getInputs();
2714faf42264SRiver Riddle   if (callArgs.size() != arguments.size()) {
2715faf42264SRiver Riddle     return emitErrorAndNote(
2716faf42264SRiver Riddle         loc,
2717faf42264SRiver Riddle         llvm::formatv("invalid number of arguments for {0} call; expected "
2718faf42264SRiver Riddle                       "{1}, but got {2}",
2719faf42264SRiver Riddle                       callableDecl->getCallableType(), callArgs.size(),
2720faf42264SRiver Riddle                       arguments.size()),
2721faf42264SRiver Riddle         callableDecl->getLoc(),
2722faf42264SRiver Riddle         llvm::formatv("see the definition of {0} here",
2723faf42264SRiver Riddle                       callableDecl->getName()->getName()));
2724faf42264SRiver Riddle   }
2725faf42264SRiver Riddle 
2726faf42264SRiver Riddle   /// Handle argument type mismatch.
2727faf42264SRiver Riddle   auto attachDiagFn = [&](ast::Diagnostic &diag) {
2728faf42264SRiver Riddle     diag.attachNote(llvm::formatv("see the definition of `{0}` here",
2729faf42264SRiver Riddle                                   callableDecl->getName()->getName()),
2730faf42264SRiver Riddle                     callableDecl->getLoc());
2731faf42264SRiver Riddle   };
2732faf42264SRiver Riddle   for (auto it : llvm::zip(callArgs, arguments)) {
2733faf42264SRiver Riddle     if (failed(convertExpressionTo(std::get<1>(it), std::get<0>(it)->getType(),
2734faf42264SRiver Riddle                                    attachDiagFn)))
2735faf42264SRiver Riddle       return failure();
2736faf42264SRiver Riddle   }
2737faf42264SRiver Riddle 
2738faf42264SRiver Riddle   return ast::CallExpr::create(ctx, loc, parentExpr, arguments,
2739930916c7SMogball                                callableDecl->getResultType(), isNegated);
2740faf42264SRiver Riddle }
2741faf42264SRiver Riddle 
27426842ec42SRiver Riddle FailureOr<ast::DeclRefExpr *> Parser::createDeclRefExpr(SMRange loc,
274311d26bd1SRiver Riddle                                                         ast::Decl *decl) {
274411d26bd1SRiver Riddle   // Check the type of decl being referenced.
274511d26bd1SRiver Riddle   ast::Type declType;
2746faf42264SRiver Riddle   if (isa<ast::ConstraintDecl>(decl))
2747faf42264SRiver Riddle     declType = ast::ConstraintType::get(ctx);
2748faf42264SRiver Riddle   else if (isa<ast::UserRewriteDecl>(decl))
2749faf42264SRiver Riddle     declType = ast::RewriteType::get(ctx);
2750faf42264SRiver Riddle   else if (auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
275111d26bd1SRiver Riddle     declType = varDecl->getType();
275211d26bd1SRiver Riddle   else
275311d26bd1SRiver Riddle     return emitError(loc, "invalid reference to `" +
275411d26bd1SRiver Riddle                               decl->getName()->getName() + "`");
275511d26bd1SRiver Riddle 
275611d26bd1SRiver Riddle   return ast::DeclRefExpr::create(ctx, loc, decl, declType);
275711d26bd1SRiver Riddle }
275811d26bd1SRiver Riddle 
275911d26bd1SRiver Riddle FailureOr<ast::DeclRefExpr *>
2760faf42264SRiver Riddle Parser::createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
276111d26bd1SRiver Riddle                                  ArrayRef<ast::ConstraintRef> constraints) {
276211d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> decl =
276311d26bd1SRiver Riddle       defineVariableDecl(name, loc, type, constraints);
276411d26bd1SRiver Riddle   if (failed(decl))
276511d26bd1SRiver Riddle     return failure();
276611d26bd1SRiver Riddle   return ast::DeclRefExpr::create(ctx, loc, *decl, type);
276711d26bd1SRiver Riddle }
276811d26bd1SRiver Riddle 
276911d26bd1SRiver Riddle FailureOr<ast::MemberAccessExpr *>
277011d26bd1SRiver Riddle Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name,
27716842ec42SRiver Riddle                                SMRange loc) {
277211d26bd1SRiver Riddle   // Validate the member name for the given parent expression.
277311d26bd1SRiver Riddle   FailureOr<ast::Type> memberType = validateMemberAccess(parentExpr, name, loc);
277411d26bd1SRiver Riddle   if (failed(memberType))
277511d26bd1SRiver Riddle     return failure();
277611d26bd1SRiver Riddle 
277711d26bd1SRiver Riddle   return ast::MemberAccessExpr::create(ctx, loc, parentExpr, name, *memberType);
277811d26bd1SRiver Riddle }
277911d26bd1SRiver Riddle 
278011d26bd1SRiver Riddle FailureOr<ast::Type> Parser::validateMemberAccess(ast::Expr *parentExpr,
2781faf42264SRiver Riddle                                                   StringRef name, SMRange loc) {
278211d26bd1SRiver Riddle   ast::Type parentType = parentExpr->getType();
2783d2353695SPeiming Liu   if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType)) {
278402670c3fSRiver Riddle     if (name == ast::AllResultsMemberAccessExpr::getMemberName())
278511d26bd1SRiver Riddle       return valueRangeTy;
278681f2f4dfSRiver Riddle 
278781f2f4dfSRiver Riddle     // Verify member access based on the operation type.
27881c2edb02SRiver Riddle     if (const ods::Operation *odsOp = opType.getODSOperation()) {
278981f2f4dfSRiver Riddle       auto results = odsOp->getResults();
279081f2f4dfSRiver Riddle 
279181f2f4dfSRiver Riddle       // Handle indexed results.
279281f2f4dfSRiver Riddle       unsigned index = 0;
279381f2f4dfSRiver Riddle       if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) &&
279481f2f4dfSRiver Riddle           index < results.size()) {
279581f2f4dfSRiver Riddle         return results[index].isVariadic() ? valueRangeTy : valueTy;
279681f2f4dfSRiver Riddle       }
279781f2f4dfSRiver Riddle 
279881f2f4dfSRiver Riddle       // Handle named results.
279981f2f4dfSRiver Riddle       const auto *it = llvm::find_if(results, [&](const auto &result) {
280081f2f4dfSRiver Riddle         return result.getName() == name;
280181f2f4dfSRiver Riddle       });
280281f2f4dfSRiver Riddle       if (it != results.end())
280381f2f4dfSRiver Riddle         return it->isVariadic() ? valueRangeTy : valueTy;
2804c088fbe7SChia-hung Duan     } else if (llvm::isDigit(name[0])) {
2805c088fbe7SChia-hung Duan       // Allow unchecked numeric indexing of the results of unregistered
2806c088fbe7SChia-hung Duan       // operations. It returns a single value.
2807c088fbe7SChia-hung Duan       return valueTy;
280881f2f4dfSRiver Riddle     }
2809d2353695SPeiming Liu   } else if (auto tupleType = dyn_cast<ast::TupleType>(parentType)) {
2810f62a57a3SRiver Riddle     // Handle indexed results.
2811f62a57a3SRiver Riddle     unsigned index = 0;
2812f62a57a3SRiver Riddle     if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) &&
2813f62a57a3SRiver Riddle         index < tupleType.size()) {
2814f62a57a3SRiver Riddle       return tupleType.getElementTypes()[index];
2815f62a57a3SRiver Riddle     }
2816f62a57a3SRiver Riddle 
2817f62a57a3SRiver Riddle     // Handle named results.
2818f62a57a3SRiver Riddle     auto elementNames = tupleType.getElementNames();
281902b6fb21SMehdi Amini     const auto *it = llvm::find(elementNames, name);
2820f62a57a3SRiver Riddle     if (it != elementNames.end())
2821f62a57a3SRiver Riddle       return tupleType.getElementTypes()[it - elementNames.begin()];
282211d26bd1SRiver Riddle   }
282311d26bd1SRiver Riddle   return emitError(
282411d26bd1SRiver Riddle       loc,
282511d26bd1SRiver Riddle       llvm::formatv("invalid member access `{0}` on expression of type `{1}`",
282611d26bd1SRiver Riddle                     name, parentType));
282711d26bd1SRiver Riddle }
282811d26bd1SRiver Riddle 
282902670c3fSRiver Riddle FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
28306842ec42SRiver Riddle     SMRange loc, const ast::OpNameDecl *name,
283191b8d96fSRiver Riddle     OpResultTypeContext resultTypeContext,
2832ec92a125SRiver Riddle     SmallVectorImpl<ast::Expr *> &operands,
283302670c3fSRiver Riddle     MutableArrayRef<ast::NamedAttributeDecl *> attributes,
2834ec92a125SRiver Riddle     SmallVectorImpl<ast::Expr *> &results) {
28350a81ace0SKazu Hirata   std::optional<StringRef> opNameRef = name->getName();
283681f2f4dfSRiver Riddle   const ods::Operation *odsOp = lookupODSOperation(opNameRef);
283702670c3fSRiver Riddle 
283802670c3fSRiver Riddle   // Verify the inputs operands.
283981f2f4dfSRiver Riddle   if (failed(validateOperationOperands(loc, opNameRef, odsOp, operands)))
284002670c3fSRiver Riddle     return failure();
284102670c3fSRiver Riddle 
284202670c3fSRiver Riddle   // Verify the attribute list.
284302670c3fSRiver Riddle   for (ast::NamedAttributeDecl *attr : attributes) {
284402670c3fSRiver Riddle     // Check for an attribute type, or a type awaiting resolution.
284502670c3fSRiver Riddle     ast::Type attrType = attr->getValue()->getType();
2846d2353695SPeiming Liu     if (!isa<ast::AttributeType>(attrType)) {
284702670c3fSRiver Riddle       return emitError(
284802670c3fSRiver Riddle           attr->getValue()->getLoc(),
284902670c3fSRiver Riddle           llvm::formatv("expected `Attr` expression, but got `{0}`", attrType));
285002670c3fSRiver Riddle     }
285102670c3fSRiver Riddle   }
285202670c3fSRiver Riddle 
285391b8d96fSRiver Riddle   assert(
285491b8d96fSRiver Riddle       (resultTypeContext == OpResultTypeContext::Explicit || results.empty()) &&
285591b8d96fSRiver Riddle       "unexpected inferrence when results were explicitly specified");
285691b8d96fSRiver Riddle 
285791b8d96fSRiver Riddle   // If we aren't relying on type inferrence, or explicit results were provided,
285891b8d96fSRiver Riddle   // validate them.
285991b8d96fSRiver Riddle   if (resultTypeContext == OpResultTypeContext::Explicit) {
286081f2f4dfSRiver Riddle     if (failed(validateOperationResults(loc, opNameRef, odsOp, results)))
286102670c3fSRiver Riddle       return failure();
286202670c3fSRiver Riddle 
286391b8d96fSRiver Riddle     // Validate the use of interface based type inferrence for this operation.
286491b8d96fSRiver Riddle   } else if (resultTypeContext == OpResultTypeContext::Interface) {
286591b8d96fSRiver Riddle     assert(opNameRef &&
286691b8d96fSRiver Riddle            "expected valid operation name when inferring operation results");
286791b8d96fSRiver Riddle     checkOperationResultTypeInferrence(loc, *opNameRef, odsOp);
286891b8d96fSRiver Riddle   }
286991b8d96fSRiver Riddle 
28701c2edb02SRiver Riddle   return ast::OperationExpr::create(ctx, loc, odsOp, name, operands, results,
287102670c3fSRiver Riddle                                     attributes);
287202670c3fSRiver Riddle }
287302670c3fSRiver Riddle 
287402670c3fSRiver Riddle LogicalResult
28750a81ace0SKazu Hirata Parser::validateOperationOperands(SMRange loc, std::optional<StringRef> name,
287681f2f4dfSRiver Riddle                                   const ods::Operation *odsOp,
2877ec92a125SRiver Riddle                                   SmallVectorImpl<ast::Expr *> &operands) {
287881f2f4dfSRiver Riddle   return validateOperationOperandsOrResults(
28790a81ace0SKazu Hirata       "operand", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name,
28801a36588eSKazu Hirata       operands, odsOp ? odsOp->getOperands() : std::nullopt, valueTy,
288102670c3fSRiver Riddle       valueRangeTy);
288202670c3fSRiver Riddle }
288302670c3fSRiver Riddle 
288402670c3fSRiver Riddle LogicalResult
28850a81ace0SKazu Hirata Parser::validateOperationResults(SMRange loc, std::optional<StringRef> name,
288681f2f4dfSRiver Riddle                                  const ods::Operation *odsOp,
2887ec92a125SRiver Riddle                                  SmallVectorImpl<ast::Expr *> &results) {
288881f2f4dfSRiver Riddle   return validateOperationOperandsOrResults(
28890a81ace0SKazu Hirata       "result", loc, odsOp ? odsOp->getLoc() : std::optional<SMRange>(), name,
28901a36588eSKazu Hirata       results, odsOp ? odsOp->getResults() : std::nullopt, typeTy, typeRangeTy);
289102670c3fSRiver Riddle }
289202670c3fSRiver Riddle 
289391b8d96fSRiver Riddle void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName,
289491b8d96fSRiver Riddle                                                 const ods::Operation *odsOp) {
289591b8d96fSRiver Riddle   // If the operation might not have inferrence support, emit a warning to the
289691b8d96fSRiver Riddle   // user. We don't emit an error because the interface might be added to the
289791b8d96fSRiver Riddle   // operation at runtime. It's rare, but it could still happen. We emit a
289891b8d96fSRiver Riddle   // warning here instead.
289991b8d96fSRiver Riddle 
290091b8d96fSRiver Riddle   // Handle inferrence warnings for unknown operations.
290191b8d96fSRiver Riddle   if (!odsOp) {
290291b8d96fSRiver Riddle     ctx.getDiagEngine().emitWarning(
290391b8d96fSRiver Riddle         loc, llvm::formatv(
290491b8d96fSRiver Riddle                  "operation result types are marked to be inferred, but "
290591b8d96fSRiver Riddle                  "`{0}` is unknown. Ensure that `{0}` supports zero "
290691b8d96fSRiver Riddle                  "results or implements `InferTypeOpInterface`. Include "
290791b8d96fSRiver Riddle                  "the ODS definition of this operation to remove this warning.",
290891b8d96fSRiver Riddle                  opName));
290991b8d96fSRiver Riddle     return;
291091b8d96fSRiver Riddle   }
291191b8d96fSRiver Riddle 
291291b8d96fSRiver Riddle   // Handle inferrence warnings for known operations that expected at least one
291391b8d96fSRiver Riddle   // result, but don't have inference support. An elided results list can mean
291491b8d96fSRiver Riddle   // "zero-results", and we don't want to warn when that is the expected
291591b8d96fSRiver Riddle   // behavior.
291691b8d96fSRiver Riddle   bool requiresInferrence =
291791b8d96fSRiver Riddle       llvm::any_of(odsOp->getResults(), [](const ods::OperandOrResult &result) {
291891b8d96fSRiver Riddle         return !result.isVariableLength();
291991b8d96fSRiver Riddle       });
292091b8d96fSRiver Riddle   if (requiresInferrence && !odsOp->hasResultTypeInferrence()) {
292191b8d96fSRiver Riddle     ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitWarning(
292291b8d96fSRiver Riddle         loc,
292391b8d96fSRiver Riddle         llvm::formatv("operation result types are marked to be inferred, but "
292491b8d96fSRiver Riddle                       "`{0}` does not provide an implementation of "
292591b8d96fSRiver Riddle                       "`InferTypeOpInterface`. Ensure that `{0}` attaches "
292691b8d96fSRiver Riddle                       "`InferTypeOpInterface` at runtime, or add support to "
292791b8d96fSRiver Riddle                       "the ODS definition to remove this warning.",
292891b8d96fSRiver Riddle                       opName));
292991b8d96fSRiver Riddle     diag->attachNote(llvm::formatv("see the definition of `{0}` here", opName),
293091b8d96fSRiver Riddle                      odsOp->getLoc());
293191b8d96fSRiver Riddle     return;
293291b8d96fSRiver Riddle   }
293391b8d96fSRiver Riddle }
293491b8d96fSRiver Riddle 
293502670c3fSRiver Riddle LogicalResult Parser::validateOperationOperandsOrResults(
29360a81ace0SKazu Hirata     StringRef groupName, SMRange loc, std::optional<SMRange> odsOpLoc,
29370a81ace0SKazu Hirata     std::optional<StringRef> name, SmallVectorImpl<ast::Expr *> &values,
293881f2f4dfSRiver Riddle     ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
2939ec92a125SRiver Riddle     ast::RangeType rangeTy) {
294002670c3fSRiver Riddle   // All operation types accept a single range parameter.
294102670c3fSRiver Riddle   if (values.size() == 1) {
294202670c3fSRiver Riddle     if (failed(convertExpressionTo(values[0], rangeTy)))
294302670c3fSRiver Riddle       return failure();
294402670c3fSRiver Riddle     return success();
294502670c3fSRiver Riddle   }
294602670c3fSRiver Riddle 
294781f2f4dfSRiver Riddle   /// If the operation has ODS information, we can more accurately verify the
294881f2f4dfSRiver Riddle   /// values.
294981f2f4dfSRiver Riddle   if (odsOpLoc) {
2950ec92a125SRiver Riddle     auto emitSizeMismatchError = [&] {
295181f2f4dfSRiver Riddle       return emitErrorAndNote(
295281f2f4dfSRiver Riddle           loc,
295381f2f4dfSRiver Riddle           llvm::formatv("invalid number of {0} groups for `{1}`; expected "
295481f2f4dfSRiver Riddle                         "{2}, but got {3}",
295581f2f4dfSRiver Riddle                         groupName, *name, odsValues.size(), values.size()),
295681f2f4dfSRiver Riddle           *odsOpLoc, llvm::formatv("see the definition of `{0}` here", *name));
2957ec92a125SRiver Riddle     };
2958ec92a125SRiver Riddle 
2959ec92a125SRiver Riddle     // Handle the case where no values were provided.
2960ec92a125SRiver Riddle     if (values.empty()) {
2961ec92a125SRiver Riddle       // If we don't expect any on the ODS side, we are done.
2962ec92a125SRiver Riddle       if (odsValues.empty())
2963ec92a125SRiver Riddle         return success();
2964ec92a125SRiver Riddle 
2965ec92a125SRiver Riddle       // If we do, check if we actually need to provide values (i.e. if any of
2966ec92a125SRiver Riddle       // the values are actually required).
2967ec92a125SRiver Riddle       unsigned numVariadic = 0;
2968ec92a125SRiver Riddle       for (const auto &odsValue : odsValues) {
2969ec92a125SRiver Riddle         if (!odsValue.isVariableLength())
2970ec92a125SRiver Riddle           return emitSizeMismatchError();
2971ec92a125SRiver Riddle         ++numVariadic;
297281f2f4dfSRiver Riddle       }
2973ec92a125SRiver Riddle 
2974ec92a125SRiver Riddle       // If we are in a non-rewrite context, we don't need to do anything more.
2975ec92a125SRiver Riddle       // Zero-values is a valid constraint on the operation.
2976ec92a125SRiver Riddle       if (parserContext != ParserContext::Rewrite)
2977ec92a125SRiver Riddle         return success();
2978ec92a125SRiver Riddle 
2979ec92a125SRiver Riddle       // Otherwise, when in a rewrite we may need to provide values to match the
2980ec92a125SRiver Riddle       // ODS signature of the operation to create.
2981ec92a125SRiver Riddle 
2982ec92a125SRiver Riddle       // If we only have one variadic value, just use an empty list.
2983ec92a125SRiver Riddle       if (numVariadic == 1)
2984ec92a125SRiver Riddle         return success();
2985ec92a125SRiver Riddle 
2986ec92a125SRiver Riddle       // Otherwise, create dummy values for each of the entries so that we
2987ec92a125SRiver Riddle       // adhere to the ODS signature.
2988ec92a125SRiver Riddle       for (unsigned i = 0, e = odsValues.size(); i < e; ++i) {
29891a36588eSKazu Hirata         values.push_back(ast::RangeExpr::create(
29901a36588eSKazu Hirata             ctx, loc, /*elements=*/std::nullopt, rangeTy));
2991ec92a125SRiver Riddle       }
2992ec92a125SRiver Riddle       return success();
2993ec92a125SRiver Riddle     }
2994ec92a125SRiver Riddle 
2995ec92a125SRiver Riddle     // Verify that the number of values provided matches the number of value
2996ec92a125SRiver Riddle     // groups ODS expects.
2997ec92a125SRiver Riddle     if (odsValues.size() != values.size())
2998ec92a125SRiver Riddle       return emitSizeMismatchError();
2999ec92a125SRiver Riddle 
300081f2f4dfSRiver Riddle     auto diagFn = [&](ast::Diagnostic &diag) {
300181f2f4dfSRiver Riddle       diag.attachNote(llvm::formatv("see the definition of `{0}` here", *name),
300281f2f4dfSRiver Riddle                       *odsOpLoc);
300381f2f4dfSRiver Riddle     };
300481f2f4dfSRiver Riddle     for (unsigned i = 0, e = values.size(); i < e; ++i) {
300581f2f4dfSRiver Riddle       ast::Type expectedType = odsValues[i].isVariadic() ? rangeTy : singleTy;
300681f2f4dfSRiver Riddle       if (failed(convertExpressionTo(values[i], expectedType, diagFn)))
300781f2f4dfSRiver Riddle         return failure();
300881f2f4dfSRiver Riddle     }
300981f2f4dfSRiver Riddle     return success();
301081f2f4dfSRiver Riddle   }
301181f2f4dfSRiver Riddle 
301202670c3fSRiver Riddle   // Otherwise, accept the value groups as they have been defined and just
301302670c3fSRiver Riddle   // ensure they are one of the expected types.
301402670c3fSRiver Riddle   for (ast::Expr *&valueExpr : values) {
301502670c3fSRiver Riddle     ast::Type valueExprType = valueExpr->getType();
301602670c3fSRiver Riddle 
301702670c3fSRiver Riddle     // Check if this is one of the expected types.
301802670c3fSRiver Riddle     if (valueExprType == rangeTy || valueExprType == singleTy)
301902670c3fSRiver Riddle       continue;
302002670c3fSRiver Riddle 
302102670c3fSRiver Riddle     // If the operand is an Operation, allow converting to a Value or
302202670c3fSRiver Riddle     // ValueRange. This situations arises quite often with nested operation
302302670c3fSRiver Riddle     // expressions: `op<my_dialect.foo>(op<my_dialect.bar>)`
302402670c3fSRiver Riddle     if (singleTy == valueTy) {
3025d2353695SPeiming Liu       if (isa<ast::OperationType>(valueExprType)) {
302602670c3fSRiver Riddle         valueExpr = convertOpToValue(valueExpr);
302702670c3fSRiver Riddle         continue;
302802670c3fSRiver Riddle       }
302902670c3fSRiver Riddle     }
303002670c3fSRiver Riddle 
30319e57210aSRiver Riddle     // Otherwise, try to convert the expression to a range.
30329e57210aSRiver Riddle     if (succeeded(convertExpressionTo(valueExpr, rangeTy)))
30339e57210aSRiver Riddle       continue;
30349e57210aSRiver Riddle 
303502670c3fSRiver Riddle     return emitError(
303602670c3fSRiver Riddle         valueExpr->getLoc(),
303702670c3fSRiver Riddle         llvm::formatv(
303802670c3fSRiver Riddle             "expected `{0}` or `{1}` convertible expression, but got `{2}`",
303902670c3fSRiver Riddle             singleTy, rangeTy, valueExprType));
304002670c3fSRiver Riddle   }
304102670c3fSRiver Riddle   return success();
304202670c3fSRiver Riddle }
304302670c3fSRiver Riddle 
3044f62a57a3SRiver Riddle FailureOr<ast::TupleExpr *>
30456842ec42SRiver Riddle Parser::createTupleExpr(SMRange loc, ArrayRef<ast::Expr *> elements,
3046f62a57a3SRiver Riddle                         ArrayRef<StringRef> elementNames) {
3047f62a57a3SRiver Riddle   for (const ast::Expr *element : elements) {
3048f62a57a3SRiver Riddle     ast::Type eleTy = element->getType();
3049d2353695SPeiming Liu     if (isa<ast::ConstraintType, ast::RewriteType, ast::TupleType>(eleTy)) {
3050f62a57a3SRiver Riddle       return emitError(
3051f62a57a3SRiver Riddle           element->getLoc(),
3052f62a57a3SRiver Riddle           llvm::formatv("unable to build a tuple with `{0}` element", eleTy));
3053f62a57a3SRiver Riddle     }
3054f62a57a3SRiver Riddle   }
3055f62a57a3SRiver Riddle   return ast::TupleExpr::create(ctx, loc, elements, elementNames);
3056f62a57a3SRiver Riddle }
3057f62a57a3SRiver Riddle 
305811d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
305911d26bd1SRiver Riddle // Stmts
306011d26bd1SRiver Riddle 
30616842ec42SRiver Riddle FailureOr<ast::EraseStmt *> Parser::createEraseStmt(SMRange loc,
306211d26bd1SRiver Riddle                                                     ast::Expr *rootOp) {
306311d26bd1SRiver Riddle   // Check that root is an Operation.
306411d26bd1SRiver Riddle   ast::Type rootType = rootOp->getType();
3065d2353695SPeiming Liu   if (!isa<ast::OperationType>(rootType))
306611d26bd1SRiver Riddle     return emitError(rootOp->getLoc(), "expected `Op` expression");
306711d26bd1SRiver Riddle 
306811d26bd1SRiver Riddle   return ast::EraseStmt::create(ctx, loc, rootOp);
306911d26bd1SRiver Riddle }
307011d26bd1SRiver Riddle 
307112eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *>
30726842ec42SRiver Riddle Parser::createReplaceStmt(SMRange loc, ast::Expr *rootOp,
307312eebb8eSRiver Riddle                           MutableArrayRef<ast::Expr *> replValues) {
307412eebb8eSRiver Riddle   // Check that root is an Operation.
307512eebb8eSRiver Riddle   ast::Type rootType = rootOp->getType();
3076d2353695SPeiming Liu   if (!isa<ast::OperationType>(rootType)) {
307712eebb8eSRiver Riddle     return emitError(
307812eebb8eSRiver Riddle         rootOp->getLoc(),
307912eebb8eSRiver Riddle         llvm::formatv("expected `Op` expression, but got `{0}`", rootType));
308012eebb8eSRiver Riddle   }
308112eebb8eSRiver Riddle 
308212eebb8eSRiver Riddle   // If there are multiple replacement values, we implicitly convert any Op
308312eebb8eSRiver Riddle   // expressions to the value form.
308412eebb8eSRiver Riddle   bool shouldConvertOpToValues = replValues.size() > 1;
308512eebb8eSRiver Riddle   for (ast::Expr *&replExpr : replValues) {
308612eebb8eSRiver Riddle     ast::Type replType = replExpr->getType();
308712eebb8eSRiver Riddle 
308812eebb8eSRiver Riddle     // Check that replExpr is an Operation, Value, or ValueRange.
3089d2353695SPeiming Liu     if (isa<ast::OperationType>(replType)) {
309012eebb8eSRiver Riddle       if (shouldConvertOpToValues)
309112eebb8eSRiver Riddle         replExpr = convertOpToValue(replExpr);
309212eebb8eSRiver Riddle       continue;
309312eebb8eSRiver Riddle     }
309412eebb8eSRiver Riddle 
309512eebb8eSRiver Riddle     if (replType != valueTy && replType != valueRangeTy) {
309612eebb8eSRiver Riddle       return emitError(replExpr->getLoc(),
309712eebb8eSRiver Riddle                        llvm::formatv("expected `Op`, `Value` or `ValueRange` "
309812eebb8eSRiver Riddle                                      "expression, but got `{0}`",
309912eebb8eSRiver Riddle                                      replType));
310012eebb8eSRiver Riddle     }
310112eebb8eSRiver Riddle   }
310212eebb8eSRiver Riddle 
310312eebb8eSRiver Riddle   return ast::ReplaceStmt::create(ctx, loc, rootOp, replValues);
310412eebb8eSRiver Riddle }
310512eebb8eSRiver Riddle 
31063ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *>
31076842ec42SRiver Riddle Parser::createRewriteStmt(SMRange loc, ast::Expr *rootOp,
31083ee44cb7SRiver Riddle                           ast::CompoundStmt *rewriteBody) {
31093ee44cb7SRiver Riddle   // Check that root is an Operation.
31103ee44cb7SRiver Riddle   ast::Type rootType = rootOp->getType();
3111d2353695SPeiming Liu   if (!isa<ast::OperationType>(rootType)) {
31123ee44cb7SRiver Riddle     return emitError(
31133ee44cb7SRiver Riddle         rootOp->getLoc(),
31143ee44cb7SRiver Riddle         llvm::formatv("expected `Op` expression, but got `{0}`", rootType));
31153ee44cb7SRiver Riddle   }
31163ee44cb7SRiver Riddle 
31173ee44cb7SRiver Riddle   return ast::RewriteStmt::create(ctx, loc, rootOp, rewriteBody);
31183ee44cb7SRiver Riddle }
31193ee44cb7SRiver Riddle 
312011d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
3121008de486SRiver Riddle // Code Completion
3122008de486SRiver Riddle //===----------------------------------------------------------------------===//
3123008de486SRiver Riddle 
3124008de486SRiver Riddle LogicalResult Parser::codeCompleteMemberAccess(ast::Expr *parentExpr) {
3125008de486SRiver Riddle   ast::Type parentType = parentExpr->getType();
3126d2353695SPeiming Liu   if (ast::OperationType opType = dyn_cast<ast::OperationType>(parentType))
3127008de486SRiver Riddle     codeCompleteContext->codeCompleteOperationMemberAccess(opType);
3128d2353695SPeiming Liu   else if (ast::TupleType tupleType = dyn_cast<ast::TupleType>(parentType))
3129008de486SRiver Riddle     codeCompleteContext->codeCompleteTupleMemberAccess(tupleType);
3130008de486SRiver Riddle   return failure();
3131008de486SRiver Riddle }
3132008de486SRiver Riddle 
31330a81ace0SKazu Hirata LogicalResult
31340a81ace0SKazu Hirata Parser::codeCompleteAttributeName(std::optional<StringRef> opName) {
3135008de486SRiver Riddle   if (opName)
3136008de486SRiver Riddle     codeCompleteContext->codeCompleteOperationAttributeName(*opName);
3137008de486SRiver Riddle   return failure();
3138008de486SRiver Riddle }
3139008de486SRiver Riddle 
3140008de486SRiver Riddle LogicalResult
3141008de486SRiver Riddle Parser::codeCompleteConstraintName(ast::Type inferredType,
3142008de486SRiver Riddle                                    bool allowInlineTypeConstraints) {
3143008de486SRiver Riddle   codeCompleteContext->codeCompleteConstraintName(
3144b6ec1de7SRiver Riddle       inferredType, allowInlineTypeConstraints, curDeclScope);
3145008de486SRiver Riddle   return failure();
3146008de486SRiver Riddle }
3147008de486SRiver Riddle 
3148008de486SRiver Riddle LogicalResult Parser::codeCompleteDialectName() {
3149008de486SRiver Riddle   codeCompleteContext->codeCompleteDialectName();
3150008de486SRiver Riddle   return failure();
3151008de486SRiver Riddle }
3152008de486SRiver Riddle 
3153008de486SRiver Riddle LogicalResult Parser::codeCompleteOperationName(StringRef dialectName) {
3154008de486SRiver Riddle   codeCompleteContext->codeCompleteOperationName(dialectName);
3155008de486SRiver Riddle   return failure();
3156008de486SRiver Riddle }
3157008de486SRiver Riddle 
3158008de486SRiver Riddle LogicalResult Parser::codeCompletePatternMetadata() {
3159008de486SRiver Riddle   codeCompleteContext->codeCompletePatternMetadata();
3160008de486SRiver Riddle   return failure();
3161008de486SRiver Riddle }
3162008de486SRiver Riddle 
316341d2c6dfSRiver Riddle LogicalResult Parser::codeCompleteIncludeFilename(StringRef curPath) {
316441d2c6dfSRiver Riddle   codeCompleteContext->codeCompleteIncludeFilename(curPath);
316541d2c6dfSRiver Riddle   return failure();
316641d2c6dfSRiver Riddle }
316741d2c6dfSRiver Riddle 
3168469c5894SRiver Riddle void Parser::codeCompleteCallSignature(ast::Node *parent,
3169469c5894SRiver Riddle                                        unsigned currentNumArgs) {
3170469c5894SRiver Riddle   ast::CallableDecl *callableDecl = tryExtractCallableDecl(parent);
3171469c5894SRiver Riddle   if (!callableDecl)
3172469c5894SRiver Riddle     return;
3173469c5894SRiver Riddle 
3174469c5894SRiver Riddle   codeCompleteContext->codeCompleteCallSignature(callableDecl, currentNumArgs);
3175469c5894SRiver Riddle }
3176469c5894SRiver Riddle 
3177469c5894SRiver Riddle void Parser::codeCompleteOperationOperandsSignature(
31780a81ace0SKazu Hirata     std::optional<StringRef> opName, unsigned currentNumOperands) {
3179469c5894SRiver Riddle   codeCompleteContext->codeCompleteOperationOperandsSignature(
3180469c5894SRiver Riddle       opName, currentNumOperands);
3181469c5894SRiver Riddle }
3182469c5894SRiver Riddle 
31830a81ace0SKazu Hirata void Parser::codeCompleteOperationResultsSignature(
31840a81ace0SKazu Hirata     std::optional<StringRef> opName, unsigned currentNumResults) {
3185469c5894SRiver Riddle   codeCompleteContext->codeCompleteOperationResultsSignature(opName,
3186469c5894SRiver Riddle                                                              currentNumResults);
3187469c5894SRiver Riddle }
3188469c5894SRiver Riddle 
3189008de486SRiver Riddle //===----------------------------------------------------------------------===//
319011d26bd1SRiver Riddle // Parser
319111d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
319211d26bd1SRiver Riddle 
3193008de486SRiver Riddle FailureOr<ast::Module *>
3194bf352e0bSRiver Riddle mlir::pdll::parsePDLLAST(ast::Context &ctx, llvm::SourceMgr &sourceMgr,
3195bf352e0bSRiver Riddle                          bool enableDocumentation,
3196008de486SRiver Riddle                          CodeCompleteContext *codeCompleteContext) {
3197bf352e0bSRiver Riddle   Parser parser(ctx, sourceMgr, enableDocumentation, codeCompleteContext);
319811d26bd1SRiver Riddle   return parser.parseModule();
319911d26bd1SRiver Riddle }
3200