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"
1211d26bd1SRiver Riddle #include "mlir/Support/LogicalResult.h"
1381f2f4dfSRiver Riddle #include "mlir/TableGen/Argument.h"
1481f2f4dfSRiver Riddle #include "mlir/TableGen/Attribute.h"
1581f2f4dfSRiver Riddle #include "mlir/TableGen/Constraint.h"
1681f2f4dfSRiver Riddle #include "mlir/TableGen/Format.h"
1781f2f4dfSRiver Riddle #include "mlir/TableGen/Operator.h"
1811d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Context.h"
1911d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Diagnostic.h"
2011d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Nodes.h"
2111d26bd1SRiver Riddle #include "mlir/Tools/PDLL/AST/Types.h"
2281f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Constraint.h"
2381f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Context.h"
2481f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Operation.h"
25008de486SRiver Riddle #include "mlir/Tools/PDLL/Parser/CodeComplete.h"
26f62a57a3SRiver Riddle #include "llvm/ADT/StringExtras.h"
2711d26bd1SRiver Riddle #include "llvm/ADT/TypeSwitch.h"
2811d26bd1SRiver Riddle #include "llvm/Support/FormatVariadic.h"
2981f2f4dfSRiver Riddle #include "llvm/Support/ManagedStatic.h"
3011d26bd1SRiver Riddle #include "llvm/Support/SaveAndRestore.h"
31f62a57a3SRiver Riddle #include "llvm/Support/ScopedPrinter.h"
3281f2f4dfSRiver Riddle #include "llvm/TableGen/Error.h"
3381f2f4dfSRiver Riddle #include "llvm/TableGen/Parser.h"
3411d26bd1SRiver Riddle #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:
Parser(ast::Context & ctx,llvm::SourceMgr & sourceMgr,bool enableDocumentation,CodeCompleteContext * codeCompleteContext)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),
50bf352e0bSRiver Riddle         valueTy(ast::ValueType::get(ctx)),
5111d26bd1SRiver Riddle         valueRangeTy(ast::ValueRangeType::get(ctx)),
5211d26bd1SRiver Riddle         typeTy(ast::TypeType::get(ctx)),
5381f2f4dfSRiver Riddle         typeRangeTy(ast::TypeRangeType::get(ctx)),
54008de486SRiver Riddle         attrTy(ast::AttributeType::get(ctx)),
55008de486SRiver Riddle         codeCompleteContext(codeCompleteContext) {}
5611d26bd1SRiver Riddle 
5711d26bd1SRiver Riddle   /// Try to parse a new module. Returns nullptr in the case of failure.
5811d26bd1SRiver Riddle   FailureOr<ast::Module *> parseModule();
5911d26bd1SRiver Riddle 
6011d26bd1SRiver Riddle private:
6111d26bd1SRiver Riddle   /// The current context of the parser. It allows for the parser to know a bit
6211d26bd1SRiver Riddle   /// about the construct it is nested within during parsing. This is used
6311d26bd1SRiver Riddle   /// specifically to provide additional verification during parsing, e.g. to
6411d26bd1SRiver Riddle   /// prevent using rewrites within a match context, matcher constraints within
6511d26bd1SRiver Riddle   /// a rewrite section, etc.
6611d26bd1SRiver Riddle   enum class ParserContext {
6711d26bd1SRiver Riddle     /// The parser is in the global context.
6811d26bd1SRiver Riddle     Global,
69faf42264SRiver Riddle     /// The parser is currently within a Constraint, which disallows all types
70faf42264SRiver Riddle     /// of rewrites (e.g. `erase`, `replace`, calls to Rewrites, etc.).
71faf42264SRiver Riddle     Constraint,
7211d26bd1SRiver Riddle     /// The parser is currently within the matcher portion of a Pattern, which
7311d26bd1SRiver Riddle     /// is allows a terminal operation rewrite statement but no other rewrite
7411d26bd1SRiver Riddle     /// transformations.
7511d26bd1SRiver Riddle     PatternMatch,
7612eebb8eSRiver Riddle     /// The parser is currently within a Rewrite, which disallows calls to
7712eebb8eSRiver Riddle     /// constraints, requires operation expressions to have names, etc.
7812eebb8eSRiver Riddle     Rewrite,
7911d26bd1SRiver Riddle   };
8011d26bd1SRiver Riddle 
8191b8d96fSRiver Riddle   /// The current specification context of an operations result type. This
8291b8d96fSRiver Riddle   /// indicates how the result types of an operation may be inferred.
8391b8d96fSRiver Riddle   enum class OpResultTypeContext {
8491b8d96fSRiver Riddle     /// The result types of the operation are not known to be inferred.
8591b8d96fSRiver Riddle     Explicit,
8691b8d96fSRiver Riddle     /// The result types of the operation are inferred from the root input of a
8791b8d96fSRiver Riddle     /// `replace` statement.
8891b8d96fSRiver Riddle     Replacement,
8991b8d96fSRiver Riddle     /// The result types of the operation are inferred by using the
9091b8d96fSRiver Riddle     /// `InferTypeOpInterface` interface provided by the operation.
9191b8d96fSRiver Riddle     Interface,
9291b8d96fSRiver Riddle   };
9391b8d96fSRiver Riddle 
9411d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
9511d26bd1SRiver Riddle   // Parsing
9611d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
9711d26bd1SRiver Riddle 
9811d26bd1SRiver Riddle   /// Push a new decl scope onto the lexer.
pushDeclScope()9911d26bd1SRiver Riddle   ast::DeclScope *pushDeclScope() {
10011d26bd1SRiver Riddle     ast::DeclScope *newScope =
10111d26bd1SRiver Riddle         new (scopeAllocator.Allocate()) ast::DeclScope(curDeclScope);
10211d26bd1SRiver Riddle     return (curDeclScope = newScope);
10311d26bd1SRiver Riddle   }
pushDeclScope(ast::DeclScope * scope)10411d26bd1SRiver Riddle   void pushDeclScope(ast::DeclScope *scope) { curDeclScope = scope; }
10511d26bd1SRiver Riddle 
10611d26bd1SRiver Riddle   /// Pop the last decl scope from the lexer.
popDeclScope()10711d26bd1SRiver Riddle   void popDeclScope() { curDeclScope = curDeclScope->getParentScope(); }
10811d26bd1SRiver Riddle 
10911d26bd1SRiver Riddle   /// Parse the body of an AST module.
11081f2f4dfSRiver Riddle   LogicalResult parseModuleBody(SmallVectorImpl<ast::Decl *> &decls);
11111d26bd1SRiver Riddle 
11211d26bd1SRiver Riddle   /// Try to convert the given expression to `type`. Returns failure and emits
11311d26bd1SRiver Riddle   /// an error if a conversion is not viable. On failure, `noteAttachFn` is
11411d26bd1SRiver Riddle   /// invoked to attach notes to the emitted error diagnostic. On success,
11511d26bd1SRiver Riddle   /// `expr` is updated to the expression used to convert to `type`.
11611d26bd1SRiver Riddle   LogicalResult convertExpressionTo(
11711d26bd1SRiver Riddle       ast::Expr *&expr, ast::Type type,
11811d26bd1SRiver Riddle       function_ref<void(ast::Diagnostic &diag)> noteAttachFn = {});
11911d26bd1SRiver Riddle 
12002670c3fSRiver Riddle   /// Given an operation expression, convert it to a Value or ValueRange
12102670c3fSRiver Riddle   /// typed expression.
12202670c3fSRiver Riddle   ast::Expr *convertOpToValue(const ast::Expr *opExpr);
12302670c3fSRiver Riddle 
12481f2f4dfSRiver Riddle   /// Lookup ODS information for the given operation, returns nullptr if no
12581f2f4dfSRiver Riddle   /// information is found.
lookupODSOperation(Optional<StringRef> opName)12681f2f4dfSRiver Riddle   const ods::Operation *lookupODSOperation(Optional<StringRef> opName) {
12781f2f4dfSRiver Riddle     return opName ? ctx.getODSContext().lookupOperation(*opName) : nullptr;
12881f2f4dfSRiver Riddle   }
12981f2f4dfSRiver Riddle 
130bf352e0bSRiver Riddle   /// Process the given documentation string, or return an empty string if
131bf352e0bSRiver Riddle   /// documentation isn't enabled.
processDoc(StringRef doc)132bf352e0bSRiver Riddle   StringRef processDoc(StringRef doc) {
133bf352e0bSRiver Riddle     return enableDocumentation ? doc : StringRef();
134bf352e0bSRiver Riddle   }
135bf352e0bSRiver Riddle 
136bf352e0bSRiver Riddle   /// Process the given documentation string and format it, or return an empty
137bf352e0bSRiver Riddle   /// string if documentation isn't enabled.
processAndFormatDoc(const Twine & doc)138bf352e0bSRiver Riddle   std::string processAndFormatDoc(const Twine &doc) {
139bf352e0bSRiver Riddle     if (!enableDocumentation)
140bf352e0bSRiver Riddle       return "";
141bf352e0bSRiver Riddle     std::string docStr;
142bf352e0bSRiver Riddle     {
143bf352e0bSRiver Riddle       llvm::raw_string_ostream docOS(docStr);
144bf352e0bSRiver Riddle       std::string tmpDocStr = doc.str();
145bf352e0bSRiver Riddle       raw_indented_ostream(docOS).printReindented(
146bf352e0bSRiver Riddle           StringRef(tmpDocStr).rtrim(" \t"));
147bf352e0bSRiver Riddle     }
148bf352e0bSRiver Riddle     return docStr;
149bf352e0bSRiver Riddle   }
150bf352e0bSRiver Riddle 
15111d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
15211d26bd1SRiver Riddle   // Directives
15311d26bd1SRiver Riddle 
15481f2f4dfSRiver Riddle   LogicalResult parseDirective(SmallVectorImpl<ast::Decl *> &decls);
15581f2f4dfSRiver Riddle   LogicalResult parseInclude(SmallVectorImpl<ast::Decl *> &decls);
15681f2f4dfSRiver Riddle   LogicalResult parseTdInclude(StringRef filename, SMRange fileLoc,
15781f2f4dfSRiver Riddle                                SmallVectorImpl<ast::Decl *> &decls);
15881f2f4dfSRiver Riddle 
15981f2f4dfSRiver Riddle   /// Process the records of a parsed tablegen include file.
16081f2f4dfSRiver Riddle   void processTdIncludeRecords(llvm::RecordKeeper &tdRecords,
16181f2f4dfSRiver Riddle                                SmallVectorImpl<ast::Decl *> &decls);
16281f2f4dfSRiver Riddle 
16381f2f4dfSRiver Riddle   /// Create a user defined native constraint for a constraint imported from
16481f2f4dfSRiver Riddle   /// ODS.
16581f2f4dfSRiver Riddle   template <typename ConstraintT>
166bf352e0bSRiver Riddle   ast::Decl *
167bf352e0bSRiver Riddle   createODSNativePDLLConstraintDecl(StringRef name, StringRef codeBlock,
168bf352e0bSRiver Riddle                                     SMRange loc, ast::Type type,
169bf352e0bSRiver Riddle                                     StringRef nativeType, StringRef docString);
17081f2f4dfSRiver Riddle   template <typename ConstraintT>
17181f2f4dfSRiver Riddle   ast::Decl *
17281f2f4dfSRiver Riddle   createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint,
1731c2edb02SRiver Riddle                                     SMRange loc, ast::Type type,
1741c2edb02SRiver Riddle                                     StringRef nativeType);
17511d26bd1SRiver Riddle 
17611d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
17711d26bd1SRiver Riddle   // Decls
17811d26bd1SRiver Riddle 
179322691abSRiver Riddle   /// This structure contains the set of pattern metadata that may be parsed.
180322691abSRiver Riddle   struct ParsedPatternMetadata {
181322691abSRiver Riddle     Optional<uint16_t> benefit;
182322691abSRiver Riddle     bool hasBoundedRecursion = false;
183322691abSRiver Riddle   };
184322691abSRiver Riddle 
18511d26bd1SRiver Riddle   FailureOr<ast::Decl *> parseTopLevelDecl();
186008de486SRiver Riddle   FailureOr<ast::NamedAttributeDecl *>
187008de486SRiver Riddle   parseNamedAttributeDecl(Optional<StringRef> parentOpName);
188faf42264SRiver Riddle 
189faf42264SRiver Riddle   /// Parse an argument variable as part of the signature of a
190faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
191faf42264SRiver Riddle   FailureOr<ast::VariableDecl *> parseArgumentDecl();
192faf42264SRiver Riddle 
193faf42264SRiver Riddle   /// Parse a result variable as part of the signature of a UserConstraintDecl
194faf42264SRiver Riddle   /// or UserRewriteDecl.
195faf42264SRiver Riddle   FailureOr<ast::VariableDecl *> parseResultDecl(unsigned resultNum);
196faf42264SRiver Riddle 
197faf42264SRiver Riddle   /// Parse a UserConstraintDecl. `isInline` signals if the constraint is being
198faf42264SRiver Riddle   /// defined in a non-global context.
199faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *>
200faf42264SRiver Riddle   parseUserConstraintDecl(bool isInline = false);
201faf42264SRiver Riddle 
202faf42264SRiver Riddle   /// Parse an inline UserConstraintDecl. An inline decl is one defined in a
203faf42264SRiver Riddle   /// non-global context, such as within a Pattern/Constraint/etc.
204faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> parseInlineUserConstraintDecl();
205faf42264SRiver Riddle 
206faf42264SRiver Riddle   /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using
207faf42264SRiver Riddle   /// PDLL constructs.
208faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> parseUserPDLLConstraintDecl(
209faf42264SRiver Riddle       const ast::Name &name, bool isInline,
210faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
211faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
212faf42264SRiver Riddle 
213faf42264SRiver Riddle   /// Parse a parseUserRewriteDecl. `isInline` signals if the rewrite is being
214faf42264SRiver Riddle   /// defined in a non-global context.
215faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseUserRewriteDecl(bool isInline = false);
216faf42264SRiver Riddle 
217faf42264SRiver Riddle   /// Parse an inline UserRewriteDecl. An inline decl is one defined in a
218faf42264SRiver Riddle   /// non-global context, such as within a Pattern/Rewrite/etc.
219faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseInlineUserRewriteDecl();
220faf42264SRiver Riddle 
221faf42264SRiver Riddle   /// Parse a PDLL (i.e. non-native) UserRewriteDecl whose body is defined using
222faf42264SRiver Riddle   /// PDLL constructs.
223faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> parseUserPDLLRewriteDecl(
224faf42264SRiver Riddle       const ast::Name &name, bool isInline,
225faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
226faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
227faf42264SRiver Riddle 
228faf42264SRiver Riddle   /// Parse either a UserConstraintDecl or UserRewriteDecl. These decls have
229faf42264SRiver Riddle   /// effectively the same syntax, and only differ on slight semantics (given
230faf42264SRiver Riddle   /// the different parsing contexts).
231faf42264SRiver Riddle   template <typename T, typename ParseUserPDLLDeclFnT>
232faf42264SRiver Riddle   FailureOr<T *> parseUserConstraintOrRewriteDecl(
233faf42264SRiver Riddle       ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
234faf42264SRiver Riddle       StringRef anonymousNamePrefix, bool isInline);
235faf42264SRiver Riddle 
236faf42264SRiver Riddle   /// Parse a native (i.e. non-PDLL) UserConstraintDecl or UserRewriteDecl.
237faf42264SRiver Riddle   /// These decls have effectively the same syntax.
238faf42264SRiver Riddle   template <typename T>
239faf42264SRiver Riddle   FailureOr<T *> parseUserNativeConstraintOrRewriteDecl(
240faf42264SRiver Riddle       const ast::Name &name, bool isInline,
241faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> arguments,
242faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType);
243faf42264SRiver Riddle 
244faf42264SRiver Riddle   /// Parse the functional signature (i.e. the arguments and results) of a
245faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
246faf42264SRiver Riddle   LogicalResult parseUserConstraintOrRewriteSignature(
247faf42264SRiver Riddle       SmallVectorImpl<ast::VariableDecl *> &arguments,
248faf42264SRiver Riddle       SmallVectorImpl<ast::VariableDecl *> &results,
249faf42264SRiver Riddle       ast::DeclScope *&argumentScope, ast::Type &resultType);
250faf42264SRiver Riddle 
251faf42264SRiver Riddle   /// Validate the return (which if present is specified by bodyIt) of a
252faf42264SRiver Riddle   /// UserConstraintDecl or UserRewriteDecl.
253faf42264SRiver Riddle   LogicalResult validateUserConstraintOrRewriteReturn(
254faf42264SRiver Riddle       StringRef declType, ast::CompoundStmt *body,
255faf42264SRiver Riddle       ArrayRef<ast::Stmt *>::iterator bodyIt,
256faf42264SRiver Riddle       ArrayRef<ast::Stmt *>::iterator bodyE,
257faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type &resultType);
258faf42264SRiver Riddle 
2593d8b9060SRiver Riddle   FailureOr<ast::CompoundStmt *>
2603d8b9060SRiver Riddle   parseLambdaBody(function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
2613d8b9060SRiver Riddle                   bool expectTerminalSemicolon = true);
2623d8b9060SRiver Riddle   FailureOr<ast::CompoundStmt *> parsePatternLambdaBody();
26311d26bd1SRiver Riddle   FailureOr<ast::Decl *> parsePatternDecl();
264322691abSRiver Riddle   LogicalResult parsePatternDeclMetadata(ParsedPatternMetadata &metadata);
26511d26bd1SRiver Riddle 
26611d26bd1SRiver Riddle   /// Check to see if a decl has already been defined with the given name, if
26711d26bd1SRiver Riddle   /// one has emit and error and return failure. Returns success otherwise.
26811d26bd1SRiver Riddle   LogicalResult checkDefineNamedDecl(const ast::Name &name);
26911d26bd1SRiver Riddle 
27011d26bd1SRiver Riddle   /// Try to define a variable decl with the given components, returns the
27111d26bd1SRiver Riddle   /// variable on success.
27211d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
2736842ec42SRiver Riddle   defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
27411d26bd1SRiver Riddle                      ast::Expr *initExpr,
27511d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
27611d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
2776842ec42SRiver Riddle   defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
27811d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
27911d26bd1SRiver Riddle 
28011d26bd1SRiver Riddle   /// Parse the constraint reference list for a variable decl.
28111d26bd1SRiver Riddle   LogicalResult parseVariableDeclConstraintList(
28211d26bd1SRiver Riddle       SmallVectorImpl<ast::ConstraintRef> &constraints);
28311d26bd1SRiver Riddle 
28411d26bd1SRiver Riddle   /// Parse the expression used within a type constraint, e.g. Attr<type-expr>.
28511d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseTypeConstraintExpr();
28611d26bd1SRiver Riddle 
28711d26bd1SRiver Riddle   /// Try to parse a single reference to a constraint. `typeConstraint` is the
28811d26bd1SRiver Riddle   /// location of a previously parsed type constraint for the entity that will
28911d26bd1SRiver Riddle   /// be constrained by the parsed constraint. `existingConstraints` are any
29011d26bd1SRiver Riddle   /// existing constraints that have already been parsed for the same entity
291faf42264SRiver Riddle   /// that will be constrained by this constraint. `allowInlineTypeConstraints`
292faf42264SRiver Riddle   /// allows the use of inline Type constraints, e.g. `Value<valueType: Type>`.
293008de486SRiver Riddle   /// If `allowNonCoreConstraints` is true, then complex (e.g. user defined
294008de486SRiver Riddle   /// constraints) may be used with the variable.
29511d26bd1SRiver Riddle   FailureOr<ast::ConstraintRef>
2966842ec42SRiver Riddle   parseConstraint(Optional<SMRange> &typeConstraint,
297faf42264SRiver Riddle                   ArrayRef<ast::ConstraintRef> existingConstraints,
298008de486SRiver Riddle                   bool allowInlineTypeConstraints,
299008de486SRiver Riddle                   bool allowNonCoreConstraints);
300faf42264SRiver Riddle 
301faf42264SRiver Riddle   /// Try to parse the constraint for a UserConstraintDecl/UserRewriteDecl
302faf42264SRiver Riddle   /// argument or result variable. The constraints for these variables do not
303faf42264SRiver Riddle   /// allow inline type constraints, and only permit a single constraint.
304faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> parseArgOrResultConstraint();
30511d26bd1SRiver Riddle 
30611d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
30711d26bd1SRiver Riddle   // Exprs
30811d26bd1SRiver Riddle 
30911d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseExpr();
31011d26bd1SRiver Riddle 
31111d26bd1SRiver Riddle   /// Identifier expressions.
312d7e7fdf3SRiver Riddle   FailureOr<ast::Expr *> parseAttributeExpr();
313faf42264SRiver Riddle   FailureOr<ast::Expr *> parseCallExpr(ast::Expr *parentExpr);
3146842ec42SRiver Riddle   FailureOr<ast::Expr *> parseDeclRefExpr(StringRef name, SMRange loc);
31511d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseIdentifierExpr();
316faf42264SRiver Riddle   FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr();
317faf42264SRiver Riddle   FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr();
31811d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseMemberAccessExpr(ast::Expr *parentExpr);
31912eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> parseOperationName(bool allowEmptyName = false);
32012eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> parseWrappedOperationName(bool allowEmptyName);
32191b8d96fSRiver Riddle   FailureOr<ast::Expr *>
32291b8d96fSRiver Riddle   parseOperationExpr(OpResultTypeContext inputResultTypeContext =
32391b8d96fSRiver Riddle                          OpResultTypeContext::Explicit);
324f62a57a3SRiver Riddle   FailureOr<ast::Expr *> parseTupleExpr();
325d7e7fdf3SRiver Riddle   FailureOr<ast::Expr *> parseTypeExpr();
32611d26bd1SRiver Riddle   FailureOr<ast::Expr *> parseUnderscoreExpr();
32711d26bd1SRiver Riddle 
32811d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
32911d26bd1SRiver Riddle   // Stmts
33011d26bd1SRiver Riddle 
33111d26bd1SRiver Riddle   FailureOr<ast::Stmt *> parseStmt(bool expectTerminalSemicolon = true);
33211d26bd1SRiver Riddle   FailureOr<ast::CompoundStmt *> parseCompoundStmt();
33311d26bd1SRiver Riddle   FailureOr<ast::EraseStmt *> parseEraseStmt();
33411d26bd1SRiver Riddle   FailureOr<ast::LetStmt *> parseLetStmt();
33512eebb8eSRiver Riddle   FailureOr<ast::ReplaceStmt *> parseReplaceStmt();
336faf42264SRiver Riddle   FailureOr<ast::ReturnStmt *> parseReturnStmt();
3373ee44cb7SRiver Riddle   FailureOr<ast::RewriteStmt *> parseRewriteStmt();
33811d26bd1SRiver Riddle 
33911d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34011d26bd1SRiver Riddle   // Creation+Analysis
34111d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34211d26bd1SRiver Riddle 
34311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
34411d26bd1SRiver Riddle   // Decls
34511d26bd1SRiver Riddle 
346faf42264SRiver Riddle   /// Try to extract a callable from the given AST node. Returns nullptr on
347faf42264SRiver Riddle   /// failure.
348faf42264SRiver Riddle   ast::CallableDecl *tryExtractCallableDecl(ast::Node *node);
349faf42264SRiver Riddle 
35011d26bd1SRiver Riddle   /// Try to create a pattern decl with the given components, returning the
35111d26bd1SRiver Riddle   /// Pattern on success.
352322691abSRiver Riddle   FailureOr<ast::PatternDecl *>
3536842ec42SRiver Riddle   createPatternDecl(SMRange loc, const ast::Name *name,
354322691abSRiver Riddle                     const ParsedPatternMetadata &metadata,
35511d26bd1SRiver Riddle                     ast::CompoundStmt *body);
35611d26bd1SRiver Riddle 
357faf42264SRiver Riddle   /// Build the result type for a UserConstraintDecl/UserRewriteDecl given a set
358faf42264SRiver Riddle   /// of results, defined as part of the signature.
359faf42264SRiver Riddle   ast::Type
360faf42264SRiver Riddle   createUserConstraintRewriteResultType(ArrayRef<ast::VariableDecl *> results);
361faf42264SRiver Riddle 
362faf42264SRiver Riddle   /// Create a PDLL (i.e. non-native) UserConstraintDecl or UserRewriteDecl.
363faf42264SRiver Riddle   template <typename T>
364faf42264SRiver Riddle   FailureOr<T *> createUserPDLLConstraintOrRewriteDecl(
365faf42264SRiver Riddle       const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
366faf42264SRiver Riddle       ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
367faf42264SRiver Riddle       ast::CompoundStmt *body);
368faf42264SRiver Riddle 
36911d26bd1SRiver Riddle   /// Try to create a variable decl with the given components, returning the
37011d26bd1SRiver Riddle   /// Variable on success.
37111d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *>
3726842ec42SRiver Riddle   createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
37311d26bd1SRiver Riddle                      ArrayRef<ast::ConstraintRef> constraints);
37411d26bd1SRiver Riddle 
375faf42264SRiver Riddle   /// Create a variable for an argument or result defined as part of the
376faf42264SRiver Riddle   /// signature of a UserConstraintDecl/UserRewriteDecl.
377faf42264SRiver Riddle   FailureOr<ast::VariableDecl *>
378faf42264SRiver Riddle   createArgOrResultVariableDecl(StringRef name, SMRange loc,
379faf42264SRiver Riddle                                 const ast::ConstraintRef &constraint);
380faf42264SRiver Riddle 
38111d26bd1SRiver Riddle   /// Validate the constraints used to constraint a variable decl.
38211d26bd1SRiver Riddle   /// `inferredType` is the type of the variable inferred by the constraints
38311d26bd1SRiver Riddle   /// within the list, and is updated to the most refined type as determined by
38411d26bd1SRiver Riddle   /// the constraints. Returns success if the constraint list is valid, failure
385008de486SRiver Riddle   /// otherwise. If `allowNonCoreConstraints` is true, then complex (e.g. user
386008de486SRiver Riddle   /// defined constraints) may be used with the variable.
38711d26bd1SRiver Riddle   LogicalResult
38811d26bd1SRiver Riddle   validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
389008de486SRiver Riddle                               ast::Type &inferredType,
390008de486SRiver Riddle                               bool allowNonCoreConstraints = true);
39111d26bd1SRiver Riddle   /// Validate a single reference to a constraint. `inferredType` contains the
39211d26bd1SRiver Riddle   /// currently inferred variabled type and is refined within the type defined
39311d26bd1SRiver Riddle   /// by the constraint. Returns success if the constraint is valid, failure
394faf42264SRiver Riddle   /// otherwise. If `allowNonCoreConstraints` is true, then complex (e.g. user
395faf42264SRiver Riddle   /// defined constraints) may be used with the variable.
39611d26bd1SRiver Riddle   LogicalResult validateVariableConstraint(const ast::ConstraintRef &ref,
397faf42264SRiver Riddle                                            ast::Type &inferredType,
398faf42264SRiver Riddle                                            bool allowNonCoreConstraints = true);
39911d26bd1SRiver Riddle   LogicalResult validateTypeConstraintExpr(const ast::Expr *typeExpr);
40011d26bd1SRiver Riddle   LogicalResult validateTypeRangeConstraintExpr(const ast::Expr *typeExpr);
40111d26bd1SRiver Riddle 
40211d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
40311d26bd1SRiver Riddle   // Exprs
40411d26bd1SRiver Riddle 
405faf42264SRiver Riddle   FailureOr<ast::CallExpr *>
406faf42264SRiver Riddle   createCallExpr(SMRange loc, ast::Expr *parentExpr,
407faf42264SRiver Riddle                  MutableArrayRef<ast::Expr *> arguments);
408faf42264SRiver Riddle   FailureOr<ast::DeclRefExpr *> createDeclRefExpr(SMRange loc, ast::Decl *decl);
40911d26bd1SRiver Riddle   FailureOr<ast::DeclRefExpr *>
4106842ec42SRiver Riddle   createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
41111d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints);
41211d26bd1SRiver Riddle   FailureOr<ast::MemberAccessExpr *>
413faf42264SRiver Riddle   createMemberAccessExpr(ast::Expr *parentExpr, StringRef name, SMRange loc);
41411d26bd1SRiver Riddle 
41511d26bd1SRiver Riddle   /// Validate the member access `name` into the given parent expression. On
41611d26bd1SRiver Riddle   /// success, this also returns the type of the member accessed.
41711d26bd1SRiver Riddle   FailureOr<ast::Type> validateMemberAccess(ast::Expr *parentExpr,
4186842ec42SRiver Riddle                                             StringRef name, SMRange loc);
41902670c3fSRiver Riddle   FailureOr<ast::OperationExpr *>
4206842ec42SRiver Riddle   createOperationExpr(SMRange loc, const ast::OpNameDecl *name,
42191b8d96fSRiver Riddle                       OpResultTypeContext resultTypeContext,
42202670c3fSRiver Riddle                       MutableArrayRef<ast::Expr *> operands,
42302670c3fSRiver Riddle                       MutableArrayRef<ast::NamedAttributeDecl *> attributes,
42402670c3fSRiver Riddle                       MutableArrayRef<ast::Expr *> results);
42502670c3fSRiver Riddle   LogicalResult
4266842ec42SRiver Riddle   validateOperationOperands(SMRange loc, Optional<StringRef> name,
42781f2f4dfSRiver Riddle                             const ods::Operation *odsOp,
42802670c3fSRiver Riddle                             MutableArrayRef<ast::Expr *> operands);
429faf42264SRiver Riddle   LogicalResult validateOperationResults(SMRange loc, Optional<StringRef> name,
43081f2f4dfSRiver Riddle                                          const ods::Operation *odsOp,
43102670c3fSRiver Riddle                                          MutableArrayRef<ast::Expr *> results);
43291b8d96fSRiver Riddle   void checkOperationResultTypeInferrence(SMRange loc, StringRef name,
43391b8d96fSRiver Riddle                                           const ods::Operation *odsOp);
43481f2f4dfSRiver Riddle   LogicalResult validateOperationOperandsOrResults(
43581f2f4dfSRiver Riddle       StringRef groupName, SMRange loc, Optional<SMRange> odsOpLoc,
43681f2f4dfSRiver Riddle       Optional<StringRef> name, MutableArrayRef<ast::Expr *> values,
43781f2f4dfSRiver Riddle       ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
43881f2f4dfSRiver Riddle       ast::Type rangeTy);
4396842ec42SRiver Riddle   FailureOr<ast::TupleExpr *> createTupleExpr(SMRange loc,
440f62a57a3SRiver Riddle                                               ArrayRef<ast::Expr *> elements,
441f62a57a3SRiver Riddle                                               ArrayRef<StringRef> elementNames);
44211d26bd1SRiver Riddle 
44311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
44411d26bd1SRiver Riddle   // Stmts
44511d26bd1SRiver Riddle 
446faf42264SRiver Riddle   FailureOr<ast::EraseStmt *> createEraseStmt(SMRange loc, ast::Expr *rootOp);
44712eebb8eSRiver Riddle   FailureOr<ast::ReplaceStmt *>
4486842ec42SRiver Riddle   createReplaceStmt(SMRange loc, ast::Expr *rootOp,
44912eebb8eSRiver Riddle                     MutableArrayRef<ast::Expr *> replValues);
4503ee44cb7SRiver Riddle   FailureOr<ast::RewriteStmt *>
4516842ec42SRiver Riddle   createRewriteStmt(SMRange loc, ast::Expr *rootOp,
4523ee44cb7SRiver Riddle                     ast::CompoundStmt *rewriteBody);
45311d26bd1SRiver Riddle 
45411d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
455008de486SRiver Riddle   // Code Completion
456008de486SRiver Riddle   //===--------------------------------------------------------------------===//
457008de486SRiver Riddle 
458008de486SRiver Riddle   /// The set of various code completion methods. Every completion method
459008de486SRiver Riddle   /// returns `failure` to stop the parsing process after providing completion
460008de486SRiver Riddle   /// results.
461008de486SRiver Riddle 
462008de486SRiver Riddle   LogicalResult codeCompleteMemberAccess(ast::Expr *parentExpr);
463008de486SRiver Riddle   LogicalResult codeCompleteAttributeName(Optional<StringRef> opName);
464008de486SRiver Riddle   LogicalResult codeCompleteConstraintName(ast::Type inferredType,
465008de486SRiver Riddle                                            bool allowNonCoreConstraints,
466008de486SRiver Riddle                                            bool allowInlineTypeConstraints);
467008de486SRiver Riddle   LogicalResult codeCompleteDialectName();
468008de486SRiver Riddle   LogicalResult codeCompleteOperationName(StringRef dialectName);
469008de486SRiver Riddle   LogicalResult codeCompletePatternMetadata();
47041d2c6dfSRiver Riddle   LogicalResult codeCompleteIncludeFilename(StringRef curPath);
471008de486SRiver Riddle 
472469c5894SRiver Riddle   void codeCompleteCallSignature(ast::Node *parent, unsigned currentNumArgs);
473469c5894SRiver Riddle   void codeCompleteOperationOperandsSignature(Optional<StringRef> opName,
474469c5894SRiver Riddle                                               unsigned currentNumOperands);
475469c5894SRiver Riddle   void codeCompleteOperationResultsSignature(Optional<StringRef> opName,
476469c5894SRiver Riddle                                              unsigned currentNumResults);
477469c5894SRiver Riddle 
478008de486SRiver Riddle   //===--------------------------------------------------------------------===//
47911d26bd1SRiver Riddle   // Lexer Utilities
48011d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
48111d26bd1SRiver Riddle 
48211d26bd1SRiver Riddle   /// If the current token has the specified kind, consume it and return true.
48311d26bd1SRiver Riddle   /// If not, return false.
consumeIf(Token::Kind kind)48411d26bd1SRiver Riddle   bool consumeIf(Token::Kind kind) {
48511d26bd1SRiver Riddle     if (curToken.isNot(kind))
48611d26bd1SRiver Riddle       return false;
48711d26bd1SRiver Riddle     consumeToken(kind);
48811d26bd1SRiver Riddle     return true;
48911d26bd1SRiver Riddle   }
49011d26bd1SRiver Riddle 
49111d26bd1SRiver Riddle   /// Advance the current lexer onto the next token.
consumeToken()49211d26bd1SRiver Riddle   void consumeToken() {
49311d26bd1SRiver Riddle     assert(curToken.isNot(Token::eof, Token::error) &&
49411d26bd1SRiver Riddle            "shouldn't advance past EOF or errors");
49511d26bd1SRiver Riddle     curToken = lexer.lexToken();
49611d26bd1SRiver Riddle   }
49711d26bd1SRiver Riddle 
49811d26bd1SRiver Riddle   /// Advance the current lexer onto the next token, asserting what the expected
49911d26bd1SRiver Riddle   /// current token is. This is preferred to the above method because it leads
50011d26bd1SRiver Riddle   /// to more self-documenting code with better checking.
consumeToken(Token::Kind kind)50111d26bd1SRiver Riddle   void consumeToken(Token::Kind kind) {
50211d26bd1SRiver Riddle     assert(curToken.is(kind) && "consumed an unexpected token");
50311d26bd1SRiver Riddle     consumeToken();
50411d26bd1SRiver Riddle   }
50511d26bd1SRiver Riddle 
506d7e7fdf3SRiver Riddle   /// Reset the lexer to the location at the given position.
resetToken(SMRange tokLoc)5076842ec42SRiver Riddle   void resetToken(SMRange tokLoc) {
508d7e7fdf3SRiver Riddle     lexer.resetPointer(tokLoc.Start.getPointer());
509d7e7fdf3SRiver Riddle     curToken = lexer.lexToken();
510d7e7fdf3SRiver Riddle   }
511d7e7fdf3SRiver Riddle 
51211d26bd1SRiver Riddle   /// Consume the specified token if present and return success. On failure,
51311d26bd1SRiver Riddle   /// output a diagnostic and return failure.
parseToken(Token::Kind kind,const Twine & msg)51411d26bd1SRiver Riddle   LogicalResult parseToken(Token::Kind kind, const Twine &msg) {
51511d26bd1SRiver Riddle     if (curToken.getKind() != kind)
51611d26bd1SRiver Riddle       return emitError(curToken.getLoc(), msg);
51711d26bd1SRiver Riddle     consumeToken();
51811d26bd1SRiver Riddle     return success();
51911d26bd1SRiver Riddle   }
emitError(SMRange loc,const Twine & msg)5206842ec42SRiver Riddle   LogicalResult emitError(SMRange loc, const Twine &msg) {
52111d26bd1SRiver Riddle     lexer.emitError(loc, msg);
52211d26bd1SRiver Riddle     return failure();
52311d26bd1SRiver Riddle   }
emitError(const Twine & msg)52411d26bd1SRiver Riddle   LogicalResult emitError(const Twine &msg) {
52511d26bd1SRiver Riddle     return emitError(curToken.getLoc(), msg);
52611d26bd1SRiver Riddle   }
emitErrorAndNote(SMRange loc,const Twine & msg,SMRange noteLoc,const Twine & note)527faf42264SRiver Riddle   LogicalResult emitErrorAndNote(SMRange loc, const Twine &msg, SMRange noteLoc,
528faf42264SRiver Riddle                                  const Twine &note) {
52911d26bd1SRiver Riddle     lexer.emitErrorAndNote(loc, msg, noteLoc, note);
53011d26bd1SRiver Riddle     return failure();
53111d26bd1SRiver Riddle   }
53211d26bd1SRiver Riddle 
53311d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
53411d26bd1SRiver Riddle   // Fields
53511d26bd1SRiver Riddle   //===--------------------------------------------------------------------===//
53611d26bd1SRiver Riddle 
53711d26bd1SRiver Riddle   /// The owning AST context.
53811d26bd1SRiver Riddle   ast::Context &ctx;
53911d26bd1SRiver Riddle 
54011d26bd1SRiver Riddle   /// The lexer of this parser.
54111d26bd1SRiver Riddle   Lexer lexer;
54211d26bd1SRiver Riddle 
54311d26bd1SRiver Riddle   /// The current token within the lexer.
54411d26bd1SRiver Riddle   Token curToken;
54511d26bd1SRiver Riddle 
546bf352e0bSRiver Riddle   /// A flag indicating if the parser should add documentation to AST nodes when
547bf352e0bSRiver Riddle   /// viable.
548bf352e0bSRiver Riddle   bool enableDocumentation;
549bf352e0bSRiver Riddle 
55011d26bd1SRiver Riddle   /// The most recently defined decl scope.
551671e30a1SMehdi Amini   ast::DeclScope *curDeclScope = nullptr;
55211d26bd1SRiver Riddle   llvm::SpecificBumpPtrAllocator<ast::DeclScope> scopeAllocator;
55311d26bd1SRiver Riddle 
55411d26bd1SRiver Riddle   /// The current context of the parser.
55511d26bd1SRiver Riddle   ParserContext parserContext = ParserContext::Global;
55611d26bd1SRiver Riddle 
55711d26bd1SRiver Riddle   /// Cached types to simplify verification and expression creation.
55811d26bd1SRiver Riddle   ast::Type valueTy, valueRangeTy;
55911d26bd1SRiver Riddle   ast::Type typeTy, typeRangeTy;
56081f2f4dfSRiver Riddle   ast::Type attrTy;
561faf42264SRiver Riddle 
562faf42264SRiver Riddle   /// A counter used when naming anonymous constraints and rewrites.
563faf42264SRiver Riddle   unsigned anonymousDeclNameCounter = 0;
564008de486SRiver Riddle 
565008de486SRiver Riddle   /// The optional code completion context.
566008de486SRiver Riddle   CodeCompleteContext *codeCompleteContext;
56711d26bd1SRiver Riddle };
56811d26bd1SRiver Riddle } // namespace
56911d26bd1SRiver Riddle 
parseModule()57011d26bd1SRiver Riddle FailureOr<ast::Module *> Parser::parseModule() {
5716842ec42SRiver Riddle   SMLoc moduleLoc = curToken.getStartLoc();
57211d26bd1SRiver Riddle   pushDeclScope();
57311d26bd1SRiver Riddle 
57411d26bd1SRiver Riddle   // Parse the top-level decls of the module.
57511d26bd1SRiver Riddle   SmallVector<ast::Decl *> decls;
57611d26bd1SRiver Riddle   if (failed(parseModuleBody(decls)))
57711d26bd1SRiver Riddle     return popDeclScope(), failure();
57811d26bd1SRiver Riddle 
57911d26bd1SRiver Riddle   popDeclScope();
58011d26bd1SRiver Riddle   return ast::Module::create(ctx, moduleLoc, decls);
58111d26bd1SRiver Riddle }
58211d26bd1SRiver Riddle 
parseModuleBody(SmallVectorImpl<ast::Decl * > & decls)58381f2f4dfSRiver Riddle LogicalResult Parser::parseModuleBody(SmallVectorImpl<ast::Decl *> &decls) {
58411d26bd1SRiver Riddle   while (curToken.isNot(Token::eof)) {
58511d26bd1SRiver Riddle     if (curToken.is(Token::directive)) {
58611d26bd1SRiver Riddle       if (failed(parseDirective(decls)))
58711d26bd1SRiver Riddle         return failure();
58811d26bd1SRiver Riddle       continue;
58911d26bd1SRiver Riddle     }
59011d26bd1SRiver Riddle 
59111d26bd1SRiver Riddle     FailureOr<ast::Decl *> decl = parseTopLevelDecl();
59211d26bd1SRiver Riddle     if (failed(decl))
59311d26bd1SRiver Riddle       return failure();
59411d26bd1SRiver Riddle     decls.push_back(*decl);
59511d26bd1SRiver Riddle   }
59611d26bd1SRiver Riddle   return success();
59711d26bd1SRiver Riddle }
59811d26bd1SRiver Riddle 
convertOpToValue(const ast::Expr * opExpr)59902670c3fSRiver Riddle ast::Expr *Parser::convertOpToValue(const ast::Expr *opExpr) {
60002670c3fSRiver Riddle   return ast::AllResultsMemberAccessExpr::create(ctx, opExpr->getLoc(), opExpr,
60102670c3fSRiver Riddle                                                  valueRangeTy);
60202670c3fSRiver Riddle }
60302670c3fSRiver Riddle 
convertExpressionTo(ast::Expr * & expr,ast::Type type,function_ref<void (ast::Diagnostic & diag)> noteAttachFn)60411d26bd1SRiver Riddle LogicalResult Parser::convertExpressionTo(
60511d26bd1SRiver Riddle     ast::Expr *&expr, ast::Type type,
60611d26bd1SRiver Riddle     function_ref<void(ast::Diagnostic &diag)> noteAttachFn) {
60711d26bd1SRiver Riddle   ast::Type exprType = expr->getType();
60811d26bd1SRiver Riddle   if (exprType == type)
60911d26bd1SRiver Riddle     return success();
61011d26bd1SRiver Riddle 
61111d26bd1SRiver Riddle   auto emitConvertError = [&]() -> ast::InFlightDiagnostic {
61211d26bd1SRiver Riddle     ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitError(
61311d26bd1SRiver Riddle         expr->getLoc(), llvm::formatv("unable to convert expression of type "
61411d26bd1SRiver Riddle                                       "`{0}` to the expected type of "
61511d26bd1SRiver Riddle                                       "`{1}`",
61611d26bd1SRiver Riddle                                       exprType, type));
61711d26bd1SRiver Riddle     if (noteAttachFn)
61811d26bd1SRiver Riddle       noteAttachFn(*diag);
61911d26bd1SRiver Riddle     return diag;
62011d26bd1SRiver Riddle   };
62111d26bd1SRiver Riddle 
62211d26bd1SRiver Riddle   if (auto exprOpType = exprType.dyn_cast<ast::OperationType>()) {
62311d26bd1SRiver Riddle     // Two operation types are compatible if they have the same name, or if the
62411d26bd1SRiver Riddle     // expected type is more general.
62511d26bd1SRiver Riddle     if (auto opType = type.dyn_cast<ast::OperationType>()) {
62611d26bd1SRiver Riddle       if (opType.getName())
62711d26bd1SRiver Riddle         return emitConvertError();
62811d26bd1SRiver Riddle       return success();
62911d26bd1SRiver Riddle     }
63011d26bd1SRiver Riddle 
63111d26bd1SRiver Riddle     // An operation can always convert to a ValueRange.
63211d26bd1SRiver Riddle     if (type == valueRangeTy) {
63302670c3fSRiver Riddle       expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr,
63402670c3fSRiver Riddle                                                      valueRangeTy);
63511d26bd1SRiver Riddle       return success();
63611d26bd1SRiver Riddle     }
63711d26bd1SRiver Riddle 
63811d26bd1SRiver Riddle     // Allow conversion to a single value by constraining the result range.
63911d26bd1SRiver Riddle     if (type == valueTy) {
64081f2f4dfSRiver Riddle       // If the operation is registered, we can verify if it can ever have a
64181f2f4dfSRiver Riddle       // single result.
6421c2edb02SRiver Riddle       if (const ods::Operation *odsOp = exprOpType.getODSOperation()) {
64381f2f4dfSRiver Riddle         if (odsOp->getResults().empty()) {
64481f2f4dfSRiver Riddle           return emitConvertError()->attachNote(
64581f2f4dfSRiver Riddle               llvm::formatv("see the definition of `{0}`, which was defined "
64681f2f4dfSRiver Riddle                             "with zero results",
64781f2f4dfSRiver Riddle                             odsOp->getName()),
64881f2f4dfSRiver Riddle               odsOp->getLoc());
64981f2f4dfSRiver Riddle         }
65081f2f4dfSRiver Riddle 
65181f2f4dfSRiver Riddle         unsigned numSingleResults = llvm::count_if(
65281f2f4dfSRiver Riddle             odsOp->getResults(), [](const ods::OperandOrResult &result) {
65381f2f4dfSRiver Riddle               return result.getVariableLengthKind() ==
65481f2f4dfSRiver Riddle                      ods::VariableLengthKind::Single;
65581f2f4dfSRiver Riddle             });
65681f2f4dfSRiver Riddle         if (numSingleResults > 1) {
65781f2f4dfSRiver Riddle           return emitConvertError()->attachNote(
65881f2f4dfSRiver Riddle               llvm::formatv("see the definition of `{0}`, which was defined "
65981f2f4dfSRiver Riddle                             "with at least {1} results",
66081f2f4dfSRiver Riddle                             odsOp->getName(), numSingleResults),
66181f2f4dfSRiver Riddle               odsOp->getLoc());
66281f2f4dfSRiver Riddle         }
66381f2f4dfSRiver Riddle       }
66481f2f4dfSRiver Riddle 
66502670c3fSRiver Riddle       expr = ast::AllResultsMemberAccessExpr::create(ctx, expr->getLoc(), expr,
66602670c3fSRiver Riddle                                                      valueTy);
66711d26bd1SRiver Riddle       return success();
66811d26bd1SRiver Riddle     }
66911d26bd1SRiver Riddle     return emitConvertError();
67011d26bd1SRiver Riddle   }
67111d26bd1SRiver Riddle 
67211d26bd1SRiver Riddle   // FIXME: Decide how to allow/support converting a single result to multiple,
67311d26bd1SRiver Riddle   // and multiple to a single result. For now, we just allow Single->Range,
67411d26bd1SRiver Riddle   // but this isn't something really supported in the PDL dialect. We should
67511d26bd1SRiver Riddle   // figure out some way to support both.
67611d26bd1SRiver Riddle   if ((exprType == valueTy || exprType == valueRangeTy) &&
67711d26bd1SRiver Riddle       (type == valueTy || type == valueRangeTy))
67811d26bd1SRiver Riddle     return success();
67911d26bd1SRiver Riddle   if ((exprType == typeTy || exprType == typeRangeTy) &&
68011d26bd1SRiver Riddle       (type == typeTy || type == typeRangeTy))
68111d26bd1SRiver Riddle     return success();
68211d26bd1SRiver Riddle 
683f62a57a3SRiver Riddle   // Handle tuple types.
684f62a57a3SRiver Riddle   if (auto exprTupleType = exprType.dyn_cast<ast::TupleType>()) {
685f62a57a3SRiver Riddle     auto tupleType = type.dyn_cast<ast::TupleType>();
686f62a57a3SRiver Riddle     if (!tupleType || tupleType.size() != exprTupleType.size())
687f62a57a3SRiver Riddle       return emitConvertError();
688f62a57a3SRiver Riddle 
689f62a57a3SRiver Riddle     // Build a new tuple expression using each of the elements of the current
690f62a57a3SRiver Riddle     // tuple.
691f62a57a3SRiver Riddle     SmallVector<ast::Expr *> newExprs;
692f62a57a3SRiver Riddle     for (unsigned i = 0, e = exprTupleType.size(); i < e; ++i) {
693f62a57a3SRiver Riddle       newExprs.push_back(ast::MemberAccessExpr::create(
694f62a57a3SRiver Riddle           ctx, expr->getLoc(), expr, llvm::to_string(i),
695f62a57a3SRiver Riddle           exprTupleType.getElementTypes()[i]));
696f62a57a3SRiver Riddle 
697f62a57a3SRiver Riddle       auto diagFn = [&](ast::Diagnostic &diag) {
698f62a57a3SRiver Riddle         diag.attachNote(llvm::formatv("when converting element #{0} of `{1}`",
699f62a57a3SRiver Riddle                                       i, exprTupleType));
700f62a57a3SRiver Riddle         if (noteAttachFn)
701f62a57a3SRiver Riddle           noteAttachFn(diag);
702f62a57a3SRiver Riddle       };
703f62a57a3SRiver Riddle       if (failed(convertExpressionTo(newExprs.back(),
704f62a57a3SRiver Riddle                                      tupleType.getElementTypes()[i], diagFn)))
705f62a57a3SRiver Riddle         return failure();
706f62a57a3SRiver Riddle     }
707f62a57a3SRiver Riddle     expr = ast::TupleExpr::create(ctx, expr->getLoc(), newExprs,
708f62a57a3SRiver Riddle                                   tupleType.getElementNames());
709f62a57a3SRiver Riddle     return success();
710f62a57a3SRiver Riddle   }
711f62a57a3SRiver Riddle 
71211d26bd1SRiver Riddle   return emitConvertError();
71311d26bd1SRiver Riddle }
71411d26bd1SRiver Riddle 
71511d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
71611d26bd1SRiver Riddle // Directives
71711d26bd1SRiver Riddle 
parseDirective(SmallVectorImpl<ast::Decl * > & decls)71881f2f4dfSRiver Riddle LogicalResult Parser::parseDirective(SmallVectorImpl<ast::Decl *> &decls) {
71911d26bd1SRiver Riddle   StringRef directive = curToken.getSpelling();
72011d26bd1SRiver Riddle   if (directive == "#include")
72111d26bd1SRiver Riddle     return parseInclude(decls);
72211d26bd1SRiver Riddle 
72311d26bd1SRiver Riddle   return emitError("unknown directive `" + directive + "`");
72411d26bd1SRiver Riddle }
72511d26bd1SRiver Riddle 
parseInclude(SmallVectorImpl<ast::Decl * > & decls)72681f2f4dfSRiver Riddle LogicalResult Parser::parseInclude(SmallVectorImpl<ast::Decl *> &decls) {
7276842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
72811d26bd1SRiver Riddle   consumeToken(Token::directive);
72911d26bd1SRiver Riddle 
73041d2c6dfSRiver Riddle   // Handle code completion of the include file path.
73141d2c6dfSRiver Riddle   if (curToken.is(Token::code_complete_string))
73241d2c6dfSRiver Riddle     return codeCompleteIncludeFilename(curToken.getStringValue());
73341d2c6dfSRiver Riddle 
73411d26bd1SRiver Riddle   // Parse the file being included.
73511d26bd1SRiver Riddle   if (!curToken.isString())
73611d26bd1SRiver Riddle     return emitError(loc,
73711d26bd1SRiver Riddle                      "expected string file name after `include` directive");
7386842ec42SRiver Riddle   SMRange fileLoc = curToken.getLoc();
73911d26bd1SRiver Riddle   std::string filenameStr = curToken.getStringValue();
74011d26bd1SRiver Riddle   StringRef filename = filenameStr;
74111d26bd1SRiver Riddle   consumeToken();
74211d26bd1SRiver Riddle 
74311d26bd1SRiver Riddle   // Check the type of include. If ending with `.pdll`, this is another pdl file
74411d26bd1SRiver Riddle   // to be parsed along with the current module.
74511d26bd1SRiver Riddle   if (filename.endswith(".pdll")) {
74609af7fefSRiver Riddle     if (failed(lexer.pushInclude(filename, fileLoc)))
74711d26bd1SRiver Riddle       return emitError(fileLoc,
74811d26bd1SRiver Riddle                        "unable to open include file `" + filename + "`");
74911d26bd1SRiver Riddle 
75011d26bd1SRiver Riddle     // If we added the include successfully, parse it into the current module.
75109af7fefSRiver Riddle     // Make sure to update to the next token after we finish parsing the nested
75209af7fefSRiver Riddle     // file.
75311d26bd1SRiver Riddle     curToken = lexer.lexToken();
75411d26bd1SRiver Riddle     LogicalResult result = parseModuleBody(decls);
75509af7fefSRiver Riddle     curToken = lexer.lexToken();
75611d26bd1SRiver Riddle     return result;
75711d26bd1SRiver Riddle   }
75811d26bd1SRiver Riddle 
75981f2f4dfSRiver Riddle   // Otherwise, this must be a `.td` include.
76081f2f4dfSRiver Riddle   if (filename.endswith(".td"))
76181f2f4dfSRiver Riddle     return parseTdInclude(filename, fileLoc, decls);
76281f2f4dfSRiver Riddle 
76381f2f4dfSRiver Riddle   return emitError(fileLoc,
76481f2f4dfSRiver Riddle                    "expected include filename to end with `.pdll` or `.td`");
76581f2f4dfSRiver Riddle }
76681f2f4dfSRiver Riddle 
parseTdInclude(StringRef filename,llvm::SMRange fileLoc,SmallVectorImpl<ast::Decl * > & decls)76781f2f4dfSRiver Riddle LogicalResult Parser::parseTdInclude(StringRef filename, llvm::SMRange fileLoc,
76881f2f4dfSRiver Riddle                                      SmallVectorImpl<ast::Decl *> &decls) {
76981f2f4dfSRiver Riddle   llvm::SourceMgr &parserSrcMgr = lexer.getSourceMgr();
77081f2f4dfSRiver Riddle 
7715a9a438aSRiver Riddle   // Use the source manager to open the file, but don't yet add it.
7725a9a438aSRiver Riddle   std::string includedFile;
7735a9a438aSRiver Riddle   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> includeBuffer =
7745a9a438aSRiver Riddle       parserSrcMgr.OpenIncludeFile(filename.str(), includedFile);
7755a9a438aSRiver Riddle   if (!includeBuffer)
7765a9a438aSRiver Riddle     return emitError(fileLoc, "unable to open include file `" + filename + "`");
7775a9a438aSRiver Riddle 
7785a9a438aSRiver Riddle   // Setup the source manager for parsing the tablegen file.
7795a9a438aSRiver Riddle   llvm::SourceMgr tdSrcMgr;
7805a9a438aSRiver Riddle   tdSrcMgr.AddNewSourceBuffer(std::move(*includeBuffer), SMLoc());
7815a9a438aSRiver Riddle   tdSrcMgr.setIncludeDirs(parserSrcMgr.getIncludeDirs());
7825a9a438aSRiver Riddle 
78381f2f4dfSRiver Riddle   // This class provides a context argument for the llvm::SourceMgr diagnostic
78481f2f4dfSRiver Riddle   // handler.
78581f2f4dfSRiver Riddle   struct DiagHandlerContext {
78681f2f4dfSRiver Riddle     Parser &parser;
78781f2f4dfSRiver Riddle     StringRef filename;
78881f2f4dfSRiver Riddle     llvm::SMRange loc;
78981f2f4dfSRiver Riddle   } handlerContext{*this, filename, fileLoc};
79081f2f4dfSRiver Riddle 
79181f2f4dfSRiver Riddle   // Set the diagnostic handler for the tablegen source manager.
7925a9a438aSRiver Riddle   tdSrcMgr.setDiagHandler(
79381f2f4dfSRiver Riddle       [](const llvm::SMDiagnostic &diag, void *rawHandlerContext) {
79481f2f4dfSRiver Riddle         auto *ctx = reinterpret_cast<DiagHandlerContext *>(rawHandlerContext);
79581f2f4dfSRiver Riddle         (void)ctx->parser.emitError(
79681f2f4dfSRiver Riddle             ctx->loc,
79781f2f4dfSRiver Riddle             llvm::formatv("error while processing include file `{0}`: {1}",
79881f2f4dfSRiver Riddle                           ctx->filename, diag.getMessage()));
79981f2f4dfSRiver Riddle       },
80081f2f4dfSRiver Riddle       &handlerContext);
80181f2f4dfSRiver Riddle 
8025a9a438aSRiver Riddle   // Parse the tablegen file.
8035a9a438aSRiver Riddle   llvm::RecordKeeper tdRecords;
8045a9a438aSRiver Riddle   if (llvm::TableGenParseFile(tdSrcMgr, tdRecords))
80581f2f4dfSRiver Riddle     return failure();
80681f2f4dfSRiver Riddle 
8075a9a438aSRiver Riddle   // Process the parsed records.
8085a9a438aSRiver Riddle   processTdIncludeRecords(tdRecords, decls);
8095a9a438aSRiver Riddle 
8105a9a438aSRiver Riddle   // After we are done processing, move all of the tablegen source buffers to
8115a9a438aSRiver Riddle   // the main parser source mgr. This allows for directly using source locations
8125a9a438aSRiver Riddle   // from the .td files without needing to remap them.
8135a9a438aSRiver Riddle   parserSrcMgr.takeSourceBuffersFrom(tdSrcMgr, fileLoc.End);
81481f2f4dfSRiver Riddle   return success();
81581f2f4dfSRiver Riddle }
81681f2f4dfSRiver Riddle 
processTdIncludeRecords(llvm::RecordKeeper & tdRecords,SmallVectorImpl<ast::Decl * > & decls)81781f2f4dfSRiver Riddle void Parser::processTdIncludeRecords(llvm::RecordKeeper &tdRecords,
81881f2f4dfSRiver Riddle                                      SmallVectorImpl<ast::Decl *> &decls) {
81981f2f4dfSRiver Riddle   // Return the length kind of the given value.
82081f2f4dfSRiver Riddle   auto getLengthKind = [](const auto &value) {
82181f2f4dfSRiver Riddle     if (value.isOptional())
82281f2f4dfSRiver Riddle       return ods::VariableLengthKind::Optional;
82381f2f4dfSRiver Riddle     return value.isVariadic() ? ods::VariableLengthKind::Variadic
82481f2f4dfSRiver Riddle                               : ods::VariableLengthKind::Single;
82581f2f4dfSRiver Riddle   };
82681f2f4dfSRiver Riddle 
82781f2f4dfSRiver Riddle   // Insert a type constraint into the ODS context.
82881f2f4dfSRiver Riddle   ods::Context &odsContext = ctx.getODSContext();
82981f2f4dfSRiver Riddle   auto addTypeConstraint = [&](const tblgen::NamedTypeConstraint &cst)
83081f2f4dfSRiver Riddle       -> const ods::TypeConstraint & {
831bf352e0bSRiver Riddle     return odsContext.insertTypeConstraint(
832bf352e0bSRiver Riddle         cst.constraint.getUniqueDefName(),
833bf352e0bSRiver Riddle         processDoc(cst.constraint.getSummary()),
83481f2f4dfSRiver Riddle         cst.constraint.getCPPClassName());
83581f2f4dfSRiver Riddle   };
83681f2f4dfSRiver Riddle   auto convertLocToRange = [&](llvm::SMLoc loc) -> llvm::SMRange {
83781f2f4dfSRiver Riddle     return {loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)};
83881f2f4dfSRiver Riddle   };
83981f2f4dfSRiver Riddle 
84081f2f4dfSRiver Riddle   // Process the parsed tablegen records to build ODS information.
84181f2f4dfSRiver Riddle   /// Operations.
84281f2f4dfSRiver Riddle   for (llvm::Record *def : tdRecords.getAllDerivedDefinitions("Op")) {
84381f2f4dfSRiver Riddle     tblgen::Operator op(def);
84481f2f4dfSRiver Riddle 
84591b8d96fSRiver Riddle     // Check to see if this operation is known to support type inferrence.
84691b8d96fSRiver Riddle     bool supportsResultTypeInferrence =
84791b8d96fSRiver Riddle         op.getTrait("::mlir::InferTypeOpInterface::Trait");
84891b8d96fSRiver Riddle 
84981f2f4dfSRiver Riddle     bool inserted = false;
85081f2f4dfSRiver Riddle     ods::Operation *odsOp = nullptr;
85191b8d96fSRiver Riddle     std::tie(odsOp, inserted) = odsContext.insertOperation(
852bf352e0bSRiver Riddle         op.getOperationName(), processDoc(op.getSummary()),
853bf352e0bSRiver Riddle         processAndFormatDoc(op.getDescription()), op.getQualCppClassName(),
854bf352e0bSRiver Riddle         supportsResultTypeInferrence, op.getLoc().front());
85581f2f4dfSRiver Riddle 
85681f2f4dfSRiver Riddle     // Ignore operations that have already been added.
85781f2f4dfSRiver Riddle     if (!inserted)
85881f2f4dfSRiver Riddle       continue;
85981f2f4dfSRiver Riddle 
86081f2f4dfSRiver Riddle     for (const tblgen::NamedAttribute &attr : op.getAttributes()) {
861bf352e0bSRiver Riddle       odsOp->appendAttribute(attr.name, attr.attr.isOptional(),
862bf352e0bSRiver Riddle                              odsContext.insertAttributeConstraint(
863bf352e0bSRiver Riddle                                  attr.attr.getUniqueDefName(),
864bf352e0bSRiver Riddle                                  processDoc(attr.attr.getSummary()),
86581f2f4dfSRiver Riddle                                  attr.attr.getStorageType()));
86681f2f4dfSRiver Riddle     }
86781f2f4dfSRiver Riddle     for (const tblgen::NamedTypeConstraint &operand : op.getOperands()) {
86881f2f4dfSRiver Riddle       odsOp->appendOperand(operand.name, getLengthKind(operand),
86981f2f4dfSRiver Riddle                            addTypeConstraint(operand));
87081f2f4dfSRiver Riddle     }
87181f2f4dfSRiver Riddle     for (const tblgen::NamedTypeConstraint &result : op.getResults()) {
87281f2f4dfSRiver Riddle       odsOp->appendResult(result.name, getLengthKind(result),
87381f2f4dfSRiver Riddle                           addTypeConstraint(result));
87481f2f4dfSRiver Riddle     }
87581f2f4dfSRiver Riddle   }
876*9f186bb1SMarkus Böck 
877*9f186bb1SMarkus Böck   auto shouldBeSkipped = [this](llvm::Record *def) {
878*9f186bb1SMarkus Böck     return def->isAnonymous() || curDeclScope->lookup(def->getName()) ||
879*9f186bb1SMarkus Böck            def->isSubClassOf("DeclareInterfaceMethods");
880*9f186bb1SMarkus Böck   };
881*9f186bb1SMarkus Böck 
88281f2f4dfSRiver Riddle   /// Attr constraints.
88381f2f4dfSRiver Riddle   for (llvm::Record *def : tdRecords.getAllDerivedDefinitions("Attr")) {
884*9f186bb1SMarkus Böck     if (shouldBeSkipped(def))
885*9f186bb1SMarkus Böck       continue;
886*9f186bb1SMarkus Böck 
8871c2edb02SRiver Riddle     tblgen::Attribute constraint(def);
888*9f186bb1SMarkus Böck     decls.push_back(createODSNativePDLLConstraintDecl<ast::AttrConstraintDecl>(
8891c2edb02SRiver Riddle         constraint, convertLocToRange(def->getLoc().front()), attrTy,
8901c2edb02SRiver Riddle         constraint.getStorageType()));
89181f2f4dfSRiver Riddle   }
89281f2f4dfSRiver Riddle   /// Type constraints.
89381f2f4dfSRiver Riddle   for (llvm::Record *def : tdRecords.getAllDerivedDefinitions("Type")) {
894*9f186bb1SMarkus Böck     if (shouldBeSkipped(def))
895*9f186bb1SMarkus Böck       continue;
896*9f186bb1SMarkus Böck 
8971c2edb02SRiver Riddle     tblgen::TypeConstraint constraint(def);
898*9f186bb1SMarkus Böck     decls.push_back(createODSNativePDLLConstraintDecl<ast::TypeConstraintDecl>(
8991c2edb02SRiver Riddle         constraint, convertLocToRange(def->getLoc().front()), typeTy,
9001c2edb02SRiver Riddle         constraint.getCPPClassName()));
90181f2f4dfSRiver Riddle   }
902*9f186bb1SMarkus Böck   /// OpInterfaces.
90381f2f4dfSRiver Riddle   ast::Type opTy = ast::OperationType::get(ctx);
904*9f186bb1SMarkus Böck   for (llvm::Record *def : tdRecords.getAllDerivedDefinitions("OpInterface")) {
905*9f186bb1SMarkus Böck     if (shouldBeSkipped(def))
90681f2f4dfSRiver Riddle       continue;
907*9f186bb1SMarkus Böck 
90881f2f4dfSRiver Riddle     SMRange loc = convertLocToRange(def->getLoc().front());
90981f2f4dfSRiver Riddle 
9101c2edb02SRiver Riddle     std::string cppClassName =
9111c2edb02SRiver Riddle         llvm::formatv("{0}::{1}", def->getValueAsString("cppNamespace"),
912*9f186bb1SMarkus Böck                       def->getValueAsString("cppInterfaceName"))
9131c2edb02SRiver Riddle             .str();
91481f2f4dfSRiver Riddle     std::string codeBlock =
9151c2edb02SRiver Riddle         llvm::formatv("return ::mlir::success(llvm::isa<{0}>(self));",
9161c2edb02SRiver Riddle                       cppClassName)
91781f2f4dfSRiver Riddle             .str();
91881f2f4dfSRiver Riddle 
919bf352e0bSRiver Riddle     std::string desc =
920bf352e0bSRiver Riddle         processAndFormatDoc(def->getValueAsString("description"));
92181f2f4dfSRiver Riddle     decls.push_back(createODSNativePDLLConstraintDecl<ast::OpConstraintDecl>(
922*9f186bb1SMarkus Böck         def->getName(), codeBlock, loc, opTy, cppClassName, desc));
92381f2f4dfSRiver Riddle   }
92481f2f4dfSRiver Riddle }
92581f2f4dfSRiver Riddle 
92681f2f4dfSRiver Riddle template <typename ConstraintT>
createODSNativePDLLConstraintDecl(StringRef name,StringRef codeBlock,SMRange loc,ast::Type type,StringRef nativeType,StringRef docString)927bf352e0bSRiver Riddle ast::Decl *Parser::createODSNativePDLLConstraintDecl(
928bf352e0bSRiver Riddle     StringRef name, StringRef codeBlock, SMRange loc, ast::Type type,
929bf352e0bSRiver Riddle     StringRef nativeType, StringRef docString) {
93081f2f4dfSRiver Riddle   // Build the single input parameter.
93181f2f4dfSRiver Riddle   ast::DeclScope *argScope = pushDeclScope();
93281f2f4dfSRiver Riddle   auto *paramVar = ast::VariableDecl::create(
93381f2f4dfSRiver Riddle       ctx, ast::Name::create(ctx, "self", loc), type,
93481f2f4dfSRiver Riddle       /*initExpr=*/nullptr, ast::ConstraintRef(ConstraintT::create(ctx, loc)));
93581f2f4dfSRiver Riddle   argScope->add(paramVar);
93681f2f4dfSRiver Riddle   popDeclScope();
93781f2f4dfSRiver Riddle 
93881f2f4dfSRiver Riddle   // Build the native constraint.
93981f2f4dfSRiver Riddle   auto *constraintDecl = ast::UserConstraintDecl::createNative(
94081f2f4dfSRiver Riddle       ctx, ast::Name::create(ctx, name, loc), paramVar,
9411c2edb02SRiver Riddle       /*results=*/llvm::None, codeBlock, ast::TupleType::get(ctx), nativeType);
942bf352e0bSRiver Riddle   constraintDecl->setDocComment(ctx, docString);
94381f2f4dfSRiver Riddle   curDeclScope->add(constraintDecl);
94481f2f4dfSRiver Riddle   return constraintDecl;
94581f2f4dfSRiver Riddle }
94681f2f4dfSRiver Riddle 
94781f2f4dfSRiver Riddle template <typename ConstraintT>
94881f2f4dfSRiver Riddle ast::Decl *
createODSNativePDLLConstraintDecl(const tblgen::Constraint & constraint,SMRange loc,ast::Type type,StringRef nativeType)94981f2f4dfSRiver Riddle Parser::createODSNativePDLLConstraintDecl(const tblgen::Constraint &constraint,
9501c2edb02SRiver Riddle                                           SMRange loc, ast::Type type,
9511c2edb02SRiver Riddle                                           StringRef nativeType) {
95281f2f4dfSRiver Riddle   // Format the condition template.
95381f2f4dfSRiver Riddle   tblgen::FmtContext fmtContext;
95481f2f4dfSRiver Riddle   fmtContext.withSelf("self");
955651d9f70SRiver Riddle   std::string codeBlock = tblgen::tgfmt(
956651d9f70SRiver Riddle       "return ::mlir::success(" + constraint.getConditionTemplate() + ");",
957651d9f70SRiver Riddle       &fmtContext);
95881f2f4dfSRiver Riddle 
959bf352e0bSRiver Riddle   // If documentation was enabled, build the doc string for the generated
960bf352e0bSRiver Riddle   // constraint. It would be nice to do this lazily, but TableGen information is
961bf352e0bSRiver Riddle   // destroyed after we finish parsing the file.
962bf352e0bSRiver Riddle   std::string docString;
963bf352e0bSRiver Riddle   if (enableDocumentation) {
964bf352e0bSRiver Riddle     StringRef desc = constraint.getDescription();
965bf352e0bSRiver Riddle     docString = processAndFormatDoc(
966bf352e0bSRiver Riddle         constraint.getSummary() +
967bf352e0bSRiver Riddle         (desc.empty() ? "" : ("\n\n" + constraint.getDescription())));
968bf352e0bSRiver Riddle   }
969bf352e0bSRiver Riddle 
970b3fc0fa8SRiver Riddle   return createODSNativePDLLConstraintDecl<ConstraintT>(
971bf352e0bSRiver Riddle       constraint.getUniqueDefName(), codeBlock, loc, type, nativeType,
972bf352e0bSRiver Riddle       docString);
97311d26bd1SRiver Riddle }
97411d26bd1SRiver Riddle 
97511d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
97611d26bd1SRiver Riddle // Decls
97711d26bd1SRiver Riddle 
parseTopLevelDecl()97811d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parseTopLevelDecl() {
97911d26bd1SRiver Riddle   FailureOr<ast::Decl *> decl;
98011d26bd1SRiver Riddle   switch (curToken.getKind()) {
981faf42264SRiver Riddle   case Token::kw_Constraint:
982faf42264SRiver Riddle     decl = parseUserConstraintDecl();
983faf42264SRiver Riddle     break;
98411d26bd1SRiver Riddle   case Token::kw_Pattern:
98511d26bd1SRiver Riddle     decl = parsePatternDecl();
98611d26bd1SRiver Riddle     break;
987faf42264SRiver Riddle   case Token::kw_Rewrite:
988faf42264SRiver Riddle     decl = parseUserRewriteDecl();
989faf42264SRiver Riddle     break;
99011d26bd1SRiver Riddle   default:
99111d26bd1SRiver Riddle     return emitError("expected top-level declaration, such as a `Pattern`");
99211d26bd1SRiver Riddle   }
99311d26bd1SRiver Riddle   if (failed(decl))
99411d26bd1SRiver Riddle     return failure();
99511d26bd1SRiver Riddle 
99611d26bd1SRiver Riddle   // If the decl has a name, add it to the current scope.
99711d26bd1SRiver Riddle   if (const ast::Name *name = (*decl)->getName()) {
99811d26bd1SRiver Riddle     if (failed(checkDefineNamedDecl(*name)))
99911d26bd1SRiver Riddle       return failure();
100011d26bd1SRiver Riddle     curDeclScope->add(*decl);
100111d26bd1SRiver Riddle   }
100211d26bd1SRiver Riddle   return decl;
100311d26bd1SRiver Riddle }
100411d26bd1SRiver Riddle 
1005008de486SRiver Riddle FailureOr<ast::NamedAttributeDecl *>
parseNamedAttributeDecl(Optional<StringRef> parentOpName)1006008de486SRiver Riddle Parser::parseNamedAttributeDecl(Optional<StringRef> parentOpName) {
1007008de486SRiver Riddle   // Check for name code completion.
1008008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1009008de486SRiver Riddle     return codeCompleteAttributeName(parentOpName);
1010008de486SRiver Riddle 
101102670c3fSRiver Riddle   std::string attrNameStr;
101202670c3fSRiver Riddle   if (curToken.isString())
101302670c3fSRiver Riddle     attrNameStr = curToken.getStringValue();
101402670c3fSRiver Riddle   else if (curToken.is(Token::identifier) || curToken.isKeyword())
101502670c3fSRiver Riddle     attrNameStr = curToken.getSpelling().str();
101602670c3fSRiver Riddle   else
101702670c3fSRiver Riddle     return emitError("expected identifier or string attribute name");
101802670c3fSRiver Riddle   const auto &name = ast::Name::create(ctx, attrNameStr, curToken.getLoc());
101902670c3fSRiver Riddle   consumeToken();
102002670c3fSRiver Riddle 
102102670c3fSRiver Riddle   // Check for a value of the attribute.
102202670c3fSRiver Riddle   ast::Expr *attrValue = nullptr;
102302670c3fSRiver Riddle   if (consumeIf(Token::equal)) {
102402670c3fSRiver Riddle     FailureOr<ast::Expr *> attrExpr = parseExpr();
102502670c3fSRiver Riddle     if (failed(attrExpr))
102602670c3fSRiver Riddle       return failure();
102702670c3fSRiver Riddle     attrValue = *attrExpr;
102802670c3fSRiver Riddle   } else {
102902670c3fSRiver Riddle     // If there isn't a concrete value, create an expression representing a
103002670c3fSRiver Riddle     // UnitAttr.
103102670c3fSRiver Riddle     attrValue = ast::AttributeExpr::create(ctx, name.getLoc(), "unit");
103202670c3fSRiver Riddle   }
103302670c3fSRiver Riddle 
103402670c3fSRiver Riddle   return ast::NamedAttributeDecl::create(ctx, name, attrValue);
103502670c3fSRiver Riddle }
103602670c3fSRiver Riddle 
parseLambdaBody(function_ref<LogicalResult (ast::Stmt * &)> processStatementFn,bool expectTerminalSemicolon)10373d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseLambdaBody(
10383d8b9060SRiver Riddle     function_ref<LogicalResult(ast::Stmt *&)> processStatementFn,
10393d8b9060SRiver Riddle     bool expectTerminalSemicolon) {
10403d8b9060SRiver Riddle   consumeToken(Token::equal_arrow);
10413d8b9060SRiver Riddle 
10423d8b9060SRiver Riddle   // Parse the single statement of the lambda body.
10433d8b9060SRiver Riddle   SMLoc bodyStartLoc = curToken.getStartLoc();
10443d8b9060SRiver Riddle   pushDeclScope();
10453d8b9060SRiver Riddle   FailureOr<ast::Stmt *> singleStatement = parseStmt(expectTerminalSemicolon);
10463d8b9060SRiver Riddle   bool failedToParse =
10473d8b9060SRiver Riddle       failed(singleStatement) || failed(processStatementFn(*singleStatement));
10483d8b9060SRiver Riddle   popDeclScope();
10493d8b9060SRiver Riddle   if (failedToParse)
10503d8b9060SRiver Riddle     return failure();
10513d8b9060SRiver Riddle 
10523d8b9060SRiver Riddle   SMRange bodyLoc(bodyStartLoc, curToken.getStartLoc());
10533d8b9060SRiver Riddle   return ast::CompoundStmt::create(ctx, bodyLoc, *singleStatement);
10543d8b9060SRiver Riddle }
10553d8b9060SRiver Riddle 
parseArgumentDecl()1056faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseArgumentDecl() {
1057faf42264SRiver Riddle   // Ensure that the argument is named.
1058faf42264SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword())
1059faf42264SRiver Riddle     return emitError("expected identifier argument name");
1060faf42264SRiver Riddle 
1061faf42264SRiver Riddle   // Parse the argument similarly to a normal variable.
1062faf42264SRiver Riddle   StringRef name = curToken.getSpelling();
1063faf42264SRiver Riddle   SMRange nameLoc = curToken.getLoc();
1064faf42264SRiver Riddle   consumeToken();
1065faf42264SRiver Riddle 
1066faf42264SRiver Riddle   if (failed(
1067faf42264SRiver Riddle           parseToken(Token::colon, "expected `:` before argument constraint")))
1068faf42264SRiver Riddle     return failure();
1069faf42264SRiver Riddle 
1070faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1071faf42264SRiver Riddle   if (failed(cst))
1072faf42264SRiver Riddle     return failure();
1073faf42264SRiver Riddle 
1074faf42264SRiver Riddle   return createArgOrResultVariableDecl(name, nameLoc, *cst);
1075faf42264SRiver Riddle }
1076faf42264SRiver Riddle 
parseResultDecl(unsigned resultNum)1077faf42264SRiver Riddle FailureOr<ast::VariableDecl *> Parser::parseResultDecl(unsigned resultNum) {
1078faf42264SRiver Riddle   // Check to see if this result is named.
1079faf42264SRiver Riddle   if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) {
1080faf42264SRiver Riddle     // Check to see if this name actually refers to a Constraint.
1081faf42264SRiver Riddle     ast::Decl *existingDecl = curDeclScope->lookup(curToken.getSpelling());
1082faf42264SRiver Riddle     if (isa_and_nonnull<ast::ConstraintDecl>(existingDecl)) {
1083faf42264SRiver Riddle       // If yes, and this is a Rewrite, give a nice error message as non-Core
1084faf42264SRiver Riddle       // constraints are not supported on Rewrite results.
1085faf42264SRiver Riddle       if (parserContext == ParserContext::Rewrite) {
1086faf42264SRiver Riddle         return emitError(
1087faf42264SRiver Riddle             "`Rewrite` results are only permitted to use core constraints, "
1088faf42264SRiver Riddle             "such as `Attr`, `Op`, `Type`, `TypeRange`, `Value`, `ValueRange`");
1089faf42264SRiver Riddle       }
1090faf42264SRiver Riddle 
1091faf42264SRiver Riddle       // Otherwise, parse this as an unnamed result variable.
1092faf42264SRiver Riddle     } else {
1093faf42264SRiver Riddle       // If it wasn't a constraint, parse the result similarly to a variable. If
1094faf42264SRiver Riddle       // there is already an existing decl, we will emit an error when defining
1095faf42264SRiver Riddle       // this variable later.
1096faf42264SRiver Riddle       StringRef name = curToken.getSpelling();
1097faf42264SRiver Riddle       SMRange nameLoc = curToken.getLoc();
1098faf42264SRiver Riddle       consumeToken();
1099faf42264SRiver Riddle 
1100faf42264SRiver Riddle       if (failed(parseToken(Token::colon,
1101faf42264SRiver Riddle                             "expected `:` before result constraint")))
1102faf42264SRiver Riddle         return failure();
1103faf42264SRiver Riddle 
1104faf42264SRiver Riddle       FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1105faf42264SRiver Riddle       if (failed(cst))
1106faf42264SRiver Riddle         return failure();
1107faf42264SRiver Riddle 
1108faf42264SRiver Riddle       return createArgOrResultVariableDecl(name, nameLoc, *cst);
1109faf42264SRiver Riddle     }
1110faf42264SRiver Riddle   }
1111faf42264SRiver Riddle 
1112faf42264SRiver Riddle   // If it isn't named, we parse the constraint directly and create an unnamed
1113faf42264SRiver Riddle   // result variable.
1114faf42264SRiver Riddle   FailureOr<ast::ConstraintRef> cst = parseArgOrResultConstraint();
1115faf42264SRiver Riddle   if (failed(cst))
1116faf42264SRiver Riddle     return failure();
1117faf42264SRiver Riddle 
1118faf42264SRiver Riddle   return createArgOrResultVariableDecl("", cst->referenceLoc, *cst);
1119faf42264SRiver Riddle }
1120faf42264SRiver Riddle 
1121faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *>
parseUserConstraintDecl(bool isInline)1122faf42264SRiver Riddle Parser::parseUserConstraintDecl(bool isInline) {
1123faf42264SRiver Riddle   // Constraints and rewrites have very similar formats, dispatch to a shared
1124faf42264SRiver Riddle   // interface for parsing.
1125faf42264SRiver Riddle   return parseUserConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1126ceb5dc55SRiver Riddle       [&](auto &&...args) {
1127ceb5dc55SRiver Riddle         return this->parseUserPDLLConstraintDecl(args...);
1128ceb5dc55SRiver Riddle       },
1129faf42264SRiver Riddle       ParserContext::Constraint, "constraint", isInline);
1130faf42264SRiver Riddle }
1131faf42264SRiver Riddle 
parseInlineUserConstraintDecl()1132faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseInlineUserConstraintDecl() {
1133faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> decl =
1134faf42264SRiver Riddle       parseUserConstraintDecl(/*isInline=*/true);
1135faf42264SRiver Riddle   if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName())))
1136faf42264SRiver Riddle     return failure();
1137faf42264SRiver Riddle 
1138faf42264SRiver Riddle   curDeclScope->add(*decl);
1139faf42264SRiver Riddle   return decl;
1140faf42264SRiver Riddle }
1141faf42264SRiver Riddle 
parseUserPDLLConstraintDecl(const ast::Name & name,bool isInline,ArrayRef<ast::VariableDecl * > arguments,ast::DeclScope * argumentScope,ArrayRef<ast::VariableDecl * > results,ast::Type resultType)1142faf42264SRiver Riddle FailureOr<ast::UserConstraintDecl *> Parser::parseUserPDLLConstraintDecl(
1143faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1144faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1145faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1146faf42264SRiver Riddle   // Push the argument scope back onto the list, so that the body can
1147faf42264SRiver Riddle   // reference arguments.
1148faf42264SRiver Riddle   pushDeclScope(argumentScope);
1149faf42264SRiver Riddle 
1150faf42264SRiver Riddle   // Parse the body of the constraint. The body is either defined as a compound
1151faf42264SRiver Riddle   // block, i.e. `{ ... }`, or a lambda body, i.e. `=> <expr>`.
1152faf42264SRiver Riddle   ast::CompoundStmt *body;
1153faf42264SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
1154faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1155faf42264SRiver Riddle         [&](ast::Stmt *&stmt) -> LogicalResult {
1156faf42264SRiver Riddle           ast::Expr *stmtExpr = dyn_cast<ast::Expr>(stmt);
1157faf42264SRiver Riddle           if (!stmtExpr) {
1158faf42264SRiver Riddle             return emitError(stmt->getLoc(),
1159faf42264SRiver Riddle                              "expected `Constraint` lambda body to contain a "
1160faf42264SRiver Riddle                              "single expression");
1161faf42264SRiver Riddle           }
1162faf42264SRiver Riddle           stmt = ast::ReturnStmt::create(ctx, stmt->getLoc(), stmtExpr);
1163faf42264SRiver Riddle           return success();
1164faf42264SRiver Riddle         },
1165faf42264SRiver Riddle         /*expectTerminalSemicolon=*/!isInline);
1166faf42264SRiver Riddle     if (failed(bodyResult))
1167faf42264SRiver Riddle       return failure();
1168faf42264SRiver Riddle     body = *bodyResult;
1169faf42264SRiver Riddle   } else {
1170faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1171faf42264SRiver Riddle     if (failed(bodyResult))
1172faf42264SRiver Riddle       return failure();
1173faf42264SRiver Riddle     body = *bodyResult;
1174faf42264SRiver Riddle 
1175faf42264SRiver Riddle     // Verify the structure of the body.
1176faf42264SRiver Riddle     auto bodyIt = body->begin(), bodyE = body->end();
1177faf42264SRiver Riddle     for (; bodyIt != bodyE; ++bodyIt)
1178faf42264SRiver Riddle       if (isa<ast::ReturnStmt>(*bodyIt))
1179faf42264SRiver Riddle         break;
1180faf42264SRiver Riddle     if (failed(validateUserConstraintOrRewriteReturn(
1181faf42264SRiver Riddle             "Constraint", body, bodyIt, bodyE, results, resultType)))
1182faf42264SRiver Riddle       return failure();
1183faf42264SRiver Riddle   }
1184faf42264SRiver Riddle   popDeclScope();
1185faf42264SRiver Riddle 
1186faf42264SRiver Riddle   return createUserPDLLConstraintOrRewriteDecl<ast::UserConstraintDecl>(
1187faf42264SRiver Riddle       name, arguments, results, resultType, body);
1188faf42264SRiver Riddle }
1189faf42264SRiver Riddle 
parseUserRewriteDecl(bool isInline)1190faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserRewriteDecl(bool isInline) {
1191faf42264SRiver Riddle   // Constraints and rewrites have very similar formats, dispatch to a shared
1192faf42264SRiver Riddle   // interface for parsing.
1193faf42264SRiver Riddle   return parseUserConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1194ceb5dc55SRiver Riddle       [&](auto &&...args) { return this->parseUserPDLLRewriteDecl(args...); },
1195faf42264SRiver Riddle       ParserContext::Rewrite, "rewrite", isInline);
1196faf42264SRiver Riddle }
1197faf42264SRiver Riddle 
parseInlineUserRewriteDecl()1198faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseInlineUserRewriteDecl() {
1199faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> decl =
1200faf42264SRiver Riddle       parseUserRewriteDecl(/*isInline=*/true);
1201faf42264SRiver Riddle   if (failed(decl) || failed(checkDefineNamedDecl((*decl)->getName())))
1202faf42264SRiver Riddle     return failure();
1203faf42264SRiver Riddle 
1204faf42264SRiver Riddle   curDeclScope->add(*decl);
1205faf42264SRiver Riddle   return decl;
1206faf42264SRiver Riddle }
1207faf42264SRiver Riddle 
parseUserPDLLRewriteDecl(const ast::Name & name,bool isInline,ArrayRef<ast::VariableDecl * > arguments,ast::DeclScope * argumentScope,ArrayRef<ast::VariableDecl * > results,ast::Type resultType)1208faf42264SRiver Riddle FailureOr<ast::UserRewriteDecl *> Parser::parseUserPDLLRewriteDecl(
1209faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1210faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments, ast::DeclScope *argumentScope,
1211faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1212faf42264SRiver Riddle   // Push the argument scope back onto the list, so that the body can
1213faf42264SRiver Riddle   // reference arguments.
1214faf42264SRiver Riddle   curDeclScope = argumentScope;
1215faf42264SRiver Riddle   ast::CompoundStmt *body;
1216faf42264SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
1217faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseLambdaBody(
1218faf42264SRiver Riddle         [&](ast::Stmt *&statement) -> LogicalResult {
1219faf42264SRiver Riddle           if (isa<ast::OpRewriteStmt>(statement))
1220faf42264SRiver Riddle             return success();
1221faf42264SRiver Riddle 
1222faf42264SRiver Riddle           ast::Expr *statementExpr = dyn_cast<ast::Expr>(statement);
1223faf42264SRiver Riddle           if (!statementExpr) {
1224faf42264SRiver Riddle             return emitError(
1225faf42264SRiver Riddle                 statement->getLoc(),
1226faf42264SRiver Riddle                 "expected `Rewrite` lambda body to contain a single expression "
1227faf42264SRiver Riddle                 "or an operation rewrite statement; such as `erase`, "
1228faf42264SRiver Riddle                 "`replace`, or `rewrite`");
1229faf42264SRiver Riddle           }
1230faf42264SRiver Riddle           statement =
1231faf42264SRiver Riddle               ast::ReturnStmt::create(ctx, statement->getLoc(), statementExpr);
1232faf42264SRiver Riddle           return success();
1233faf42264SRiver Riddle         },
1234faf42264SRiver Riddle         /*expectTerminalSemicolon=*/!isInline);
1235faf42264SRiver Riddle     if (failed(bodyResult))
1236faf42264SRiver Riddle       return failure();
1237faf42264SRiver Riddle     body = *bodyResult;
1238faf42264SRiver Riddle   } else {
1239faf42264SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
1240faf42264SRiver Riddle     if (failed(bodyResult))
1241faf42264SRiver Riddle       return failure();
1242faf42264SRiver Riddle     body = *bodyResult;
1243faf42264SRiver Riddle   }
1244faf42264SRiver Riddle   popDeclScope();
1245faf42264SRiver Riddle 
1246faf42264SRiver Riddle   // Verify the structure of the body.
1247faf42264SRiver Riddle   auto bodyIt = body->begin(), bodyE = body->end();
1248faf42264SRiver Riddle   for (; bodyIt != bodyE; ++bodyIt)
1249faf42264SRiver Riddle     if (isa<ast::ReturnStmt>(*bodyIt))
1250faf42264SRiver Riddle       break;
1251faf42264SRiver Riddle   if (failed(validateUserConstraintOrRewriteReturn("Rewrite", body, bodyIt,
1252faf42264SRiver Riddle                                                    bodyE, results, resultType)))
1253faf42264SRiver Riddle     return failure();
1254faf42264SRiver Riddle   return createUserPDLLConstraintOrRewriteDecl<ast::UserRewriteDecl>(
1255faf42264SRiver Riddle       name, arguments, results, resultType, body);
1256faf42264SRiver Riddle }
1257faf42264SRiver Riddle 
1258faf42264SRiver Riddle template <typename T, typename ParseUserPDLLDeclFnT>
parseUserConstraintOrRewriteDecl(ParseUserPDLLDeclFnT && parseUserPDLLFn,ParserContext declContext,StringRef anonymousNamePrefix,bool isInline)1259faf42264SRiver Riddle FailureOr<T *> Parser::parseUserConstraintOrRewriteDecl(
1260faf42264SRiver Riddle     ParseUserPDLLDeclFnT &&parseUserPDLLFn, ParserContext declContext,
1261faf42264SRiver Riddle     StringRef anonymousNamePrefix, bool isInline) {
1262faf42264SRiver Riddle   SMRange loc = curToken.getLoc();
1263faf42264SRiver Riddle   consumeToken();
1264faf42264SRiver Riddle   llvm::SaveAndRestore<ParserContext> saveCtx(parserContext, declContext);
1265faf42264SRiver Riddle 
1266faf42264SRiver Riddle   // Parse the name of the decl.
1267faf42264SRiver Riddle   const ast::Name *name = nullptr;
1268faf42264SRiver Riddle   if (curToken.isNot(Token::identifier)) {
1269faf42264SRiver Riddle     // Only inline decls can be un-named. Inline decls are similar to "lambdas"
1270faf42264SRiver Riddle     // in C++, so being unnamed is fine.
1271faf42264SRiver Riddle     if (!isInline)
1272faf42264SRiver Riddle       return emitError("expected identifier name");
1273faf42264SRiver Riddle 
1274faf42264SRiver Riddle     // Create a unique anonymous name to use, as the name for this decl is not
1275faf42264SRiver Riddle     // important.
1276faf42264SRiver Riddle     std::string anonName =
1277faf42264SRiver Riddle         llvm::formatv("<anonymous_{0}_{1}>", anonymousNamePrefix,
1278faf42264SRiver Riddle                       anonymousDeclNameCounter++)
1279faf42264SRiver Riddle             .str();
1280faf42264SRiver Riddle     name = &ast::Name::create(ctx, anonName, loc);
1281faf42264SRiver Riddle   } else {
1282faf42264SRiver Riddle     // If a name was provided, we can use it directly.
1283faf42264SRiver Riddle     name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc());
1284faf42264SRiver Riddle     consumeToken(Token::identifier);
1285faf42264SRiver Riddle   }
1286faf42264SRiver Riddle 
1287faf42264SRiver Riddle   // Parse the functional signature of the decl.
1288faf42264SRiver Riddle   SmallVector<ast::VariableDecl *> arguments, results;
1289faf42264SRiver Riddle   ast::DeclScope *argumentScope;
1290faf42264SRiver Riddle   ast::Type resultType;
1291faf42264SRiver Riddle   if (failed(parseUserConstraintOrRewriteSignature(arguments, results,
1292faf42264SRiver Riddle                                                    argumentScope, resultType)))
1293faf42264SRiver Riddle     return failure();
1294faf42264SRiver Riddle 
1295faf42264SRiver Riddle   // Check to see which type of constraint this is. If the constraint contains a
1296faf42264SRiver Riddle   // compound body, this is a PDLL decl.
1297faf42264SRiver Riddle   if (curToken.isAny(Token::l_brace, Token::equal_arrow))
1298faf42264SRiver Riddle     return parseUserPDLLFn(*name, isInline, arguments, argumentScope, results,
1299faf42264SRiver Riddle                            resultType);
1300faf42264SRiver Riddle 
1301faf42264SRiver Riddle   // Otherwise, this is a native decl.
1302faf42264SRiver Riddle   return parseUserNativeConstraintOrRewriteDecl<T>(*name, isInline, arguments,
1303faf42264SRiver Riddle                                                    results, resultType);
1304faf42264SRiver Riddle }
1305faf42264SRiver Riddle 
1306faf42264SRiver Riddle template <typename T>
parseUserNativeConstraintOrRewriteDecl(const ast::Name & name,bool isInline,ArrayRef<ast::VariableDecl * > arguments,ArrayRef<ast::VariableDecl * > results,ast::Type resultType)1307faf42264SRiver Riddle FailureOr<T *> Parser::parseUserNativeConstraintOrRewriteDecl(
1308faf42264SRiver Riddle     const ast::Name &name, bool isInline,
1309faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> arguments,
1310faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType) {
1311faf42264SRiver Riddle   // If followed by a string, the native code body has also been specified.
1312faf42264SRiver Riddle   std::string codeStrStorage;
1313faf42264SRiver Riddle   Optional<StringRef> optCodeStr;
1314faf42264SRiver Riddle   if (curToken.isString()) {
1315faf42264SRiver Riddle     codeStrStorage = curToken.getStringValue();
1316faf42264SRiver Riddle     optCodeStr = codeStrStorage;
1317faf42264SRiver Riddle     consumeToken();
1318faf42264SRiver Riddle   } else if (isInline) {
1319faf42264SRiver Riddle     return emitError(name.getLoc(),
1320faf42264SRiver Riddle                      "external declarations must be declared in global scope");
1321ebb1e900SRiver Riddle   } else if (curToken.is(Token::error)) {
1322ebb1e900SRiver Riddle     return failure();
1323faf42264SRiver Riddle   }
1324faf42264SRiver Riddle   if (failed(parseToken(Token::semicolon,
1325faf42264SRiver Riddle                         "expected `;` after native declaration")))
1326faf42264SRiver Riddle     return failure();
1327b474ca1dSRiver Riddle   // TODO: PDL should be able to support constraint results in certain
1328b474ca1dSRiver Riddle   // situations, we should revise this.
1329b474ca1dSRiver Riddle   if (std::is_same<ast::UserConstraintDecl, T>::value && !results.empty()) {
1330b474ca1dSRiver Riddle     return emitError(
1331b474ca1dSRiver Riddle         "native Constraints currently do not support returning results");
1332b474ca1dSRiver Riddle   }
1333faf42264SRiver Riddle   return T::createNative(ctx, name, arguments, results, optCodeStr, resultType);
1334faf42264SRiver Riddle }
1335faf42264SRiver Riddle 
parseUserConstraintOrRewriteSignature(SmallVectorImpl<ast::VariableDecl * > & arguments,SmallVectorImpl<ast::VariableDecl * > & results,ast::DeclScope * & argumentScope,ast::Type & resultType)1336faf42264SRiver Riddle LogicalResult Parser::parseUserConstraintOrRewriteSignature(
1337faf42264SRiver Riddle     SmallVectorImpl<ast::VariableDecl *> &arguments,
1338faf42264SRiver Riddle     SmallVectorImpl<ast::VariableDecl *> &results,
1339faf42264SRiver Riddle     ast::DeclScope *&argumentScope, ast::Type &resultType) {
1340faf42264SRiver Riddle   // Parse the argument list of the decl.
1341faf42264SRiver Riddle   if (failed(parseToken(Token::l_paren, "expected `(` to start argument list")))
1342faf42264SRiver Riddle     return failure();
1343faf42264SRiver Riddle 
1344faf42264SRiver Riddle   argumentScope = pushDeclScope();
1345faf42264SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
1346faf42264SRiver Riddle     do {
1347faf42264SRiver Riddle       FailureOr<ast::VariableDecl *> argument = parseArgumentDecl();
1348faf42264SRiver Riddle       if (failed(argument))
1349faf42264SRiver Riddle         return failure();
1350faf42264SRiver Riddle       arguments.emplace_back(*argument);
1351faf42264SRiver Riddle     } while (consumeIf(Token::comma));
1352faf42264SRiver Riddle   }
1353faf42264SRiver Riddle   popDeclScope();
1354faf42264SRiver Riddle   if (failed(parseToken(Token::r_paren, "expected `)` to end argument list")))
1355faf42264SRiver Riddle     return failure();
1356faf42264SRiver Riddle 
1357faf42264SRiver Riddle   // Parse the results of the decl.
1358faf42264SRiver Riddle   pushDeclScope();
1359faf42264SRiver Riddle   if (consumeIf(Token::arrow)) {
1360faf42264SRiver Riddle     auto parseResultFn = [&]() -> LogicalResult {
1361faf42264SRiver Riddle       FailureOr<ast::VariableDecl *> result = parseResultDecl(results.size());
1362faf42264SRiver Riddle       if (failed(result))
1363faf42264SRiver Riddle         return failure();
1364faf42264SRiver Riddle       results.emplace_back(*result);
1365faf42264SRiver Riddle       return success();
1366faf42264SRiver Riddle     };
1367faf42264SRiver Riddle 
1368faf42264SRiver Riddle     // Check for a list of results.
1369faf42264SRiver Riddle     if (consumeIf(Token::l_paren)) {
1370faf42264SRiver Riddle       do {
1371faf42264SRiver Riddle         if (failed(parseResultFn()))
1372faf42264SRiver Riddle           return failure();
1373faf42264SRiver Riddle       } while (consumeIf(Token::comma));
1374faf42264SRiver Riddle       if (failed(parseToken(Token::r_paren, "expected `)` to end result list")))
1375faf42264SRiver Riddle         return failure();
1376faf42264SRiver Riddle 
1377faf42264SRiver Riddle       // Otherwise, there is only one result.
1378faf42264SRiver Riddle     } else if (failed(parseResultFn())) {
1379faf42264SRiver Riddle       return failure();
1380faf42264SRiver Riddle     }
1381faf42264SRiver Riddle   }
1382faf42264SRiver Riddle   popDeclScope();
1383faf42264SRiver Riddle 
1384faf42264SRiver Riddle   // Compute the result type of the decl.
1385faf42264SRiver Riddle   resultType = createUserConstraintRewriteResultType(results);
1386faf42264SRiver Riddle 
1387faf42264SRiver Riddle   // Verify that results are only named if there are more than one.
1388faf42264SRiver Riddle   if (results.size() == 1 && !results.front()->getName().getName().empty()) {
1389faf42264SRiver Riddle     return emitError(
1390faf42264SRiver Riddle         results.front()->getLoc(),
1391faf42264SRiver Riddle         "cannot create a single-element tuple with an element label");
1392faf42264SRiver Riddle   }
1393faf42264SRiver Riddle   return success();
1394faf42264SRiver Riddle }
1395faf42264SRiver Riddle 
validateUserConstraintOrRewriteReturn(StringRef declType,ast::CompoundStmt * body,ArrayRef<ast::Stmt * >::iterator bodyIt,ArrayRef<ast::Stmt * >::iterator bodyE,ArrayRef<ast::VariableDecl * > results,ast::Type & resultType)1396faf42264SRiver Riddle LogicalResult Parser::validateUserConstraintOrRewriteReturn(
1397faf42264SRiver Riddle     StringRef declType, ast::CompoundStmt *body,
1398faf42264SRiver Riddle     ArrayRef<ast::Stmt *>::iterator bodyIt,
1399faf42264SRiver Riddle     ArrayRef<ast::Stmt *>::iterator bodyE,
1400faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type &resultType) {
1401faf42264SRiver Riddle   // Handle if a `return` was provided.
1402faf42264SRiver Riddle   if (bodyIt != bodyE) {
1403faf42264SRiver Riddle     // Emit an error if we have trailing statements after the return.
1404faf42264SRiver Riddle     if (std::next(bodyIt) != bodyE) {
1405faf42264SRiver Riddle       return emitError(
1406faf42264SRiver Riddle           (*std::next(bodyIt))->getLoc(),
1407faf42264SRiver Riddle           llvm::formatv("`return` terminated the `{0}` body, but found "
1408faf42264SRiver Riddle                         "trailing statements afterwards",
1409faf42264SRiver Riddle                         declType));
1410faf42264SRiver Riddle     }
1411faf42264SRiver Riddle 
1412faf42264SRiver Riddle     // Otherwise if a return wasn't provided, check that no results are
1413faf42264SRiver Riddle     // expected.
1414faf42264SRiver Riddle   } else if (!results.empty()) {
1415faf42264SRiver Riddle     return emitError(
1416faf42264SRiver Riddle         {body->getLoc().End, body->getLoc().End},
1417faf42264SRiver Riddle         llvm::formatv("missing return in a `{0}` expected to return `{1}`",
1418faf42264SRiver Riddle                       declType, resultType));
1419faf42264SRiver Riddle   }
1420faf42264SRiver Riddle   return success();
1421faf42264SRiver Riddle }
1422faf42264SRiver Riddle 
parsePatternLambdaBody()14233d8b9060SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parsePatternLambdaBody() {
14243d8b9060SRiver Riddle   return parseLambdaBody([&](ast::Stmt *&statement) -> LogicalResult {
14253d8b9060SRiver Riddle     if (isa<ast::OpRewriteStmt>(statement))
14263d8b9060SRiver Riddle       return success();
14273d8b9060SRiver Riddle     return emitError(
14283d8b9060SRiver Riddle         statement->getLoc(),
14293d8b9060SRiver Riddle         "expected Pattern lambda body to contain a single operation "
14303d8b9060SRiver Riddle         "rewrite statement, such as `erase`, `replace`, or `rewrite`");
14313d8b9060SRiver Riddle   });
14323d8b9060SRiver Riddle }
14333d8b9060SRiver Riddle 
parsePatternDecl()143411d26bd1SRiver Riddle FailureOr<ast::Decl *> Parser::parsePatternDecl() {
14356842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
143611d26bd1SRiver Riddle   consumeToken(Token::kw_Pattern);
143711d26bd1SRiver Riddle   llvm::SaveAndRestore<ParserContext> saveCtx(parserContext,
143811d26bd1SRiver Riddle                                               ParserContext::PatternMatch);
143911d26bd1SRiver Riddle 
144011d26bd1SRiver Riddle   // Check for an optional identifier for the pattern name.
144111d26bd1SRiver Riddle   const ast::Name *name = nullptr;
144211d26bd1SRiver Riddle   if (curToken.is(Token::identifier)) {
144311d26bd1SRiver Riddle     name = &ast::Name::create(ctx, curToken.getSpelling(), curToken.getLoc());
144411d26bd1SRiver Riddle     consumeToken(Token::identifier);
144511d26bd1SRiver Riddle   }
144611d26bd1SRiver Riddle 
1447322691abSRiver Riddle   // Parse any pattern metadata.
1448322691abSRiver Riddle   ParsedPatternMetadata metadata;
1449322691abSRiver Riddle   if (consumeIf(Token::kw_with) && failed(parsePatternDeclMetadata(metadata)))
1450322691abSRiver Riddle     return failure();
145111d26bd1SRiver Riddle 
145211d26bd1SRiver Riddle   // Parse the pattern body.
145311d26bd1SRiver Riddle   ast::CompoundStmt *body;
145411d26bd1SRiver Riddle 
14553d8b9060SRiver Riddle   // Handle a lambda body.
14563d8b9060SRiver Riddle   if (curToken.is(Token::equal_arrow)) {
14573d8b9060SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parsePatternLambdaBody();
14583d8b9060SRiver Riddle     if (failed(bodyResult))
14593d8b9060SRiver Riddle       return failure();
14603d8b9060SRiver Riddle     body = *bodyResult;
14613d8b9060SRiver Riddle   } else {
146211d26bd1SRiver Riddle     if (curToken.isNot(Token::l_brace))
14633d8b9060SRiver Riddle       return emitError("expected `{` or `=>` to start pattern body");
146411d26bd1SRiver Riddle     FailureOr<ast::CompoundStmt *> bodyResult = parseCompoundStmt();
146511d26bd1SRiver Riddle     if (failed(bodyResult))
146611d26bd1SRiver Riddle       return failure();
146711d26bd1SRiver Riddle     body = *bodyResult;
146811d26bd1SRiver Riddle 
146911d26bd1SRiver Riddle     // Verify the body of the pattern.
147011d26bd1SRiver Riddle     auto bodyIt = body->begin(), bodyE = body->end();
147111d26bd1SRiver Riddle     for (; bodyIt != bodyE; ++bodyIt) {
1472faf42264SRiver Riddle       if (isa<ast::ReturnStmt>(*bodyIt)) {
1473faf42264SRiver Riddle         return emitError((*bodyIt)->getLoc(),
1474faf42264SRiver Riddle                          "`return` statements are only permitted within a "
1475faf42264SRiver Riddle                          "`Constraint` or `Rewrite` body");
1476faf42264SRiver Riddle       }
147711d26bd1SRiver Riddle       // Break when we've found the rewrite statement.
147811d26bd1SRiver Riddle       if (isa<ast::OpRewriteStmt>(*bodyIt))
147911d26bd1SRiver Riddle         break;
148011d26bd1SRiver Riddle     }
148111d26bd1SRiver Riddle     if (bodyIt == bodyE) {
148211d26bd1SRiver Riddle       return emitError(loc,
148311d26bd1SRiver Riddle                        "expected Pattern body to terminate with an operation "
148411d26bd1SRiver Riddle                        "rewrite statement, such as `erase`");
148511d26bd1SRiver Riddle     }
148611d26bd1SRiver Riddle     if (std::next(bodyIt) != bodyE) {
148711d26bd1SRiver Riddle       return emitError((*std::next(bodyIt))->getLoc(),
148811d26bd1SRiver Riddle                        "Pattern body was terminated by an operation "
148911d26bd1SRiver Riddle                        "rewrite statement, but found trailing statements");
149011d26bd1SRiver Riddle     }
14913d8b9060SRiver Riddle   }
149211d26bd1SRiver Riddle 
1493322691abSRiver Riddle   return createPatternDecl(loc, name, metadata, body);
1494322691abSRiver Riddle }
1495322691abSRiver Riddle 
1496322691abSRiver Riddle LogicalResult
parsePatternDeclMetadata(ParsedPatternMetadata & metadata)1497322691abSRiver Riddle Parser::parsePatternDeclMetadata(ParsedPatternMetadata &metadata) {
14986842ec42SRiver Riddle   Optional<SMRange> benefitLoc;
14996842ec42SRiver Riddle   Optional<SMRange> hasBoundedRecursionLoc;
1500322691abSRiver Riddle 
1501322691abSRiver Riddle   do {
1502008de486SRiver Riddle     // Handle metadata code completion.
1503008de486SRiver Riddle     if (curToken.is(Token::code_complete))
1504008de486SRiver Riddle       return codeCompletePatternMetadata();
1505008de486SRiver Riddle 
1506322691abSRiver Riddle     if (curToken.isNot(Token::identifier))
1507322691abSRiver Riddle       return emitError("expected pattern metadata identifier");
1508322691abSRiver Riddle     StringRef metadataStr = curToken.getSpelling();
15096842ec42SRiver Riddle     SMRange metadataLoc = curToken.getLoc();
1510322691abSRiver Riddle     consumeToken(Token::identifier);
1511322691abSRiver Riddle 
1512322691abSRiver Riddle     // Parse the benefit metadata: benefit(<integer-value>)
1513322691abSRiver Riddle     if (metadataStr == "benefit") {
1514322691abSRiver Riddle       if (benefitLoc) {
1515322691abSRiver Riddle         return emitErrorAndNote(metadataLoc,
1516322691abSRiver Riddle                                 "pattern benefit has already been specified",
1517322691abSRiver Riddle                                 *benefitLoc, "see previous definition here");
1518322691abSRiver Riddle       }
1519322691abSRiver Riddle       if (failed(parseToken(Token::l_paren,
1520322691abSRiver Riddle                             "expected `(` before pattern benefit")))
1521322691abSRiver Riddle         return failure();
1522322691abSRiver Riddle 
1523322691abSRiver Riddle       uint16_t benefitValue = 0;
1524322691abSRiver Riddle       if (curToken.isNot(Token::integer))
1525322691abSRiver Riddle         return emitError("expected integral pattern benefit");
1526322691abSRiver Riddle       if (curToken.getSpelling().getAsInteger(/*Radix=*/10, benefitValue))
1527322691abSRiver Riddle         return emitError(
1528322691abSRiver Riddle             "expected pattern benefit to fit within a 16-bit integer");
1529322691abSRiver Riddle       consumeToken(Token::integer);
1530322691abSRiver Riddle 
1531322691abSRiver Riddle       metadata.benefit = benefitValue;
1532322691abSRiver Riddle       benefitLoc = metadataLoc;
1533322691abSRiver Riddle 
1534322691abSRiver Riddle       if (failed(
1535322691abSRiver Riddle               parseToken(Token::r_paren, "expected `)` after pattern benefit")))
1536322691abSRiver Riddle         return failure();
1537322691abSRiver Riddle       continue;
1538322691abSRiver Riddle     }
1539322691abSRiver Riddle 
1540322691abSRiver Riddle     // Parse the bounded recursion metadata: recursion
1541322691abSRiver Riddle     if (metadataStr == "recursion") {
1542322691abSRiver Riddle       if (hasBoundedRecursionLoc) {
1543322691abSRiver Riddle         return emitErrorAndNote(
1544322691abSRiver Riddle             metadataLoc,
1545322691abSRiver Riddle             "pattern recursion metadata has already been specified",
1546322691abSRiver Riddle             *hasBoundedRecursionLoc, "see previous definition here");
1547322691abSRiver Riddle       }
1548322691abSRiver Riddle       metadata.hasBoundedRecursion = true;
1549322691abSRiver Riddle       hasBoundedRecursionLoc = metadataLoc;
1550322691abSRiver Riddle       continue;
1551322691abSRiver Riddle     }
1552322691abSRiver Riddle 
1553322691abSRiver Riddle     return emitError(metadataLoc, "unknown pattern metadata");
1554322691abSRiver Riddle   } while (consumeIf(Token::comma));
1555322691abSRiver Riddle 
1556322691abSRiver Riddle   return success();
155711d26bd1SRiver Riddle }
155811d26bd1SRiver Riddle 
parseTypeConstraintExpr()155911d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeConstraintExpr() {
156011d26bd1SRiver Riddle   consumeToken(Token::less);
156111d26bd1SRiver Riddle 
156211d26bd1SRiver Riddle   FailureOr<ast::Expr *> typeExpr = parseExpr();
156311d26bd1SRiver Riddle   if (failed(typeExpr) ||
156411d26bd1SRiver Riddle       failed(parseToken(Token::greater,
156511d26bd1SRiver Riddle                         "expected `>` after variable type constraint")))
156611d26bd1SRiver Riddle     return failure();
156711d26bd1SRiver Riddle   return typeExpr;
156811d26bd1SRiver Riddle }
156911d26bd1SRiver Riddle 
checkDefineNamedDecl(const ast::Name & name)157011d26bd1SRiver Riddle LogicalResult Parser::checkDefineNamedDecl(const ast::Name &name) {
157111d26bd1SRiver Riddle   assert(curDeclScope && "defining decl outside of a decl scope");
157211d26bd1SRiver Riddle   if (ast::Decl *lastDecl = curDeclScope->lookup(name.getName())) {
157311d26bd1SRiver Riddle     return emitErrorAndNote(
157411d26bd1SRiver Riddle         name.getLoc(), "`" + name.getName() + "` has already been defined",
157511d26bd1SRiver Riddle         lastDecl->getName()->getLoc(), "see previous definition here");
157611d26bd1SRiver Riddle   }
157711d26bd1SRiver Riddle   return success();
157811d26bd1SRiver Riddle }
157911d26bd1SRiver Riddle 
158011d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
defineVariableDecl(StringRef name,SMRange nameLoc,ast::Type type,ast::Expr * initExpr,ArrayRef<ast::ConstraintRef> constraints)1581faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
1582faf42264SRiver Riddle                            ast::Expr *initExpr,
158311d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
158411d26bd1SRiver Riddle   assert(curDeclScope && "defining variable outside of decl scope");
158511d26bd1SRiver Riddle   const ast::Name &nameDecl = ast::Name::create(ctx, name, nameLoc);
158611d26bd1SRiver Riddle 
158711d26bd1SRiver Riddle   // If the name of the variable indicates a special variable, we don't add it
158811d26bd1SRiver Riddle   // to the scope. This variable is local to the definition point.
158911d26bd1SRiver Riddle   if (name.empty() || name == "_") {
159011d26bd1SRiver Riddle     return ast::VariableDecl::create(ctx, nameDecl, type, initExpr,
159111d26bd1SRiver Riddle                                      constraints);
159211d26bd1SRiver Riddle   }
159311d26bd1SRiver Riddle   if (failed(checkDefineNamedDecl(nameDecl)))
159411d26bd1SRiver Riddle     return failure();
159511d26bd1SRiver Riddle 
159611d26bd1SRiver Riddle   auto *varDecl =
159711d26bd1SRiver Riddle       ast::VariableDecl::create(ctx, nameDecl, type, initExpr, constraints);
159811d26bd1SRiver Riddle   curDeclScope->add(varDecl);
159911d26bd1SRiver Riddle   return varDecl;
160011d26bd1SRiver Riddle }
160111d26bd1SRiver Riddle 
160211d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
defineVariableDecl(StringRef name,SMRange nameLoc,ast::Type type,ArrayRef<ast::ConstraintRef> constraints)1603faf42264SRiver Riddle Parser::defineVariableDecl(StringRef name, SMRange nameLoc, ast::Type type,
160411d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
160511d26bd1SRiver Riddle   return defineVariableDecl(name, nameLoc, type, /*initExpr=*/nullptr,
160611d26bd1SRiver Riddle                             constraints);
160711d26bd1SRiver Riddle }
160811d26bd1SRiver Riddle 
parseVariableDeclConstraintList(SmallVectorImpl<ast::ConstraintRef> & constraints)160911d26bd1SRiver Riddle LogicalResult Parser::parseVariableDeclConstraintList(
161011d26bd1SRiver Riddle     SmallVectorImpl<ast::ConstraintRef> &constraints) {
16116842ec42SRiver Riddle   Optional<SMRange> typeConstraint;
161211d26bd1SRiver Riddle   auto parseSingleConstraint = [&] {
1613faf42264SRiver Riddle     FailureOr<ast::ConstraintRef> constraint = parseConstraint(
1614008de486SRiver Riddle         typeConstraint, constraints, /*allowInlineTypeConstraints=*/true,
1615008de486SRiver Riddle         /*allowNonCoreConstraints=*/true);
161611d26bd1SRiver Riddle     if (failed(constraint))
161711d26bd1SRiver Riddle       return failure();
161811d26bd1SRiver Riddle     constraints.push_back(*constraint);
161911d26bd1SRiver Riddle     return success();
162011d26bd1SRiver Riddle   };
162111d26bd1SRiver Riddle 
162211d26bd1SRiver Riddle   // Check to see if this is a single constraint, or a list.
162311d26bd1SRiver Riddle   if (!consumeIf(Token::l_square))
162411d26bd1SRiver Riddle     return parseSingleConstraint();
162511d26bd1SRiver Riddle 
162611d26bd1SRiver Riddle   do {
162711d26bd1SRiver Riddle     if (failed(parseSingleConstraint()))
162811d26bd1SRiver Riddle       return failure();
162911d26bd1SRiver Riddle   } while (consumeIf(Token::comma));
163011d26bd1SRiver Riddle   return parseToken(Token::r_square, "expected `]` after constraint list");
163111d26bd1SRiver Riddle }
163211d26bd1SRiver Riddle 
163311d26bd1SRiver Riddle FailureOr<ast::ConstraintRef>
parseConstraint(Optional<SMRange> & typeConstraint,ArrayRef<ast::ConstraintRef> existingConstraints,bool allowInlineTypeConstraints,bool allowNonCoreConstraints)16346842ec42SRiver Riddle Parser::parseConstraint(Optional<SMRange> &typeConstraint,
1635faf42264SRiver Riddle                         ArrayRef<ast::ConstraintRef> existingConstraints,
1636008de486SRiver Riddle                         bool allowInlineTypeConstraints,
1637008de486SRiver Riddle                         bool allowNonCoreConstraints) {
163811d26bd1SRiver Riddle   auto parseTypeConstraint = [&](ast::Expr *&typeExpr) -> LogicalResult {
1639faf42264SRiver Riddle     if (!allowInlineTypeConstraints) {
1640faf42264SRiver Riddle       return emitError(
1641faf42264SRiver Riddle           curToken.getLoc(),
1642faf42264SRiver Riddle           "inline `Attr`, `Value`, and `ValueRange` type constraints are not "
1643faf42264SRiver Riddle           "permitted on arguments or results");
1644faf42264SRiver Riddle     }
164511d26bd1SRiver Riddle     if (typeConstraint)
164611d26bd1SRiver Riddle       return emitErrorAndNote(
164711d26bd1SRiver Riddle           curToken.getLoc(),
164811d26bd1SRiver Riddle           "the type of this variable has already been constrained",
164911d26bd1SRiver Riddle           *typeConstraint, "see previous constraint location here");
165011d26bd1SRiver Riddle     FailureOr<ast::Expr *> constraintExpr = parseTypeConstraintExpr();
165111d26bd1SRiver Riddle     if (failed(constraintExpr))
165211d26bd1SRiver Riddle       return failure();
165311d26bd1SRiver Riddle     typeExpr = *constraintExpr;
165411d26bd1SRiver Riddle     typeConstraint = typeExpr->getLoc();
165511d26bd1SRiver Riddle     return success();
165611d26bd1SRiver Riddle   };
165711d26bd1SRiver Riddle 
16586842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
165911d26bd1SRiver Riddle   switch (curToken.getKind()) {
166011d26bd1SRiver Riddle   case Token::kw_Attr: {
166111d26bd1SRiver Riddle     consumeToken(Token::kw_Attr);
166211d26bd1SRiver Riddle 
166311d26bd1SRiver Riddle     // Check for a type constraint.
166411d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
166511d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
166611d26bd1SRiver Riddle       return failure();
166711d26bd1SRiver Riddle     return ast::ConstraintRef(
166811d26bd1SRiver Riddle         ast::AttrConstraintDecl::create(ctx, loc, typeExpr), loc);
166911d26bd1SRiver Riddle   }
167011d26bd1SRiver Riddle   case Token::kw_Op: {
167111d26bd1SRiver Riddle     consumeToken(Token::kw_Op);
167211d26bd1SRiver Riddle 
167312eebb8eSRiver Riddle     // Parse an optional operation name. If the name isn't provided, this refers
167412eebb8eSRiver Riddle     // to "any" operation.
167512eebb8eSRiver Riddle     FailureOr<ast::OpNameDecl *> opName =
167612eebb8eSRiver Riddle         parseWrappedOperationName(/*allowEmptyName=*/true);
167711d26bd1SRiver Riddle     if (failed(opName))
167811d26bd1SRiver Riddle       return failure();
167911d26bd1SRiver Riddle 
168011d26bd1SRiver Riddle     return ast::ConstraintRef(ast::OpConstraintDecl::create(ctx, loc, *opName),
168111d26bd1SRiver Riddle                               loc);
168211d26bd1SRiver Riddle   }
168311d26bd1SRiver Riddle   case Token::kw_Type:
168411d26bd1SRiver Riddle     consumeToken(Token::kw_Type);
168511d26bd1SRiver Riddle     return ast::ConstraintRef(ast::TypeConstraintDecl::create(ctx, loc), loc);
168611d26bd1SRiver Riddle   case Token::kw_TypeRange:
168711d26bd1SRiver Riddle     consumeToken(Token::kw_TypeRange);
168811d26bd1SRiver Riddle     return ast::ConstraintRef(ast::TypeRangeConstraintDecl::create(ctx, loc),
168911d26bd1SRiver Riddle                               loc);
169011d26bd1SRiver Riddle   case Token::kw_Value: {
169111d26bd1SRiver Riddle     consumeToken(Token::kw_Value);
169211d26bd1SRiver Riddle 
169311d26bd1SRiver Riddle     // Check for a type constraint.
169411d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
169511d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
169611d26bd1SRiver Riddle       return failure();
169711d26bd1SRiver Riddle 
169811d26bd1SRiver Riddle     return ast::ConstraintRef(
169911d26bd1SRiver Riddle         ast::ValueConstraintDecl::create(ctx, loc, typeExpr), loc);
170011d26bd1SRiver Riddle   }
170111d26bd1SRiver Riddle   case Token::kw_ValueRange: {
170211d26bd1SRiver Riddle     consumeToken(Token::kw_ValueRange);
170311d26bd1SRiver Riddle 
170411d26bd1SRiver Riddle     // Check for a type constraint.
170511d26bd1SRiver Riddle     ast::Expr *typeExpr = nullptr;
170611d26bd1SRiver Riddle     if (curToken.is(Token::less) && failed(parseTypeConstraint(typeExpr)))
170711d26bd1SRiver Riddle       return failure();
170811d26bd1SRiver Riddle 
170911d26bd1SRiver Riddle     return ast::ConstraintRef(
171011d26bd1SRiver Riddle         ast::ValueRangeConstraintDecl::create(ctx, loc, typeExpr), loc);
171111d26bd1SRiver Riddle   }
1712faf42264SRiver Riddle 
1713faf42264SRiver Riddle   case Token::kw_Constraint: {
1714faf42264SRiver Riddle     // Handle an inline constraint.
1715faf42264SRiver Riddle     FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1716faf42264SRiver Riddle     if (failed(decl))
1717faf42264SRiver Riddle       return failure();
1718faf42264SRiver Riddle     return ast::ConstraintRef(*decl, loc);
1719faf42264SRiver Riddle   }
172011d26bd1SRiver Riddle   case Token::identifier: {
172111d26bd1SRiver Riddle     StringRef constraintName = curToken.getSpelling();
172211d26bd1SRiver Riddle     consumeToken(Token::identifier);
172311d26bd1SRiver Riddle 
172411d26bd1SRiver Riddle     // Lookup the referenced constraint.
172511d26bd1SRiver Riddle     ast::Decl *cstDecl = curDeclScope->lookup<ast::Decl>(constraintName);
172611d26bd1SRiver Riddle     if (!cstDecl) {
172711d26bd1SRiver Riddle       return emitError(loc, "unknown reference to constraint `" +
172811d26bd1SRiver Riddle                                 constraintName + "`");
172911d26bd1SRiver Riddle     }
173011d26bd1SRiver Riddle 
173111d26bd1SRiver Riddle     // Handle a reference to a proper constraint.
173211d26bd1SRiver Riddle     if (auto *cst = dyn_cast<ast::ConstraintDecl>(cstDecl))
173311d26bd1SRiver Riddle       return ast::ConstraintRef(cst, loc);
173411d26bd1SRiver Riddle 
173511d26bd1SRiver Riddle     return emitErrorAndNote(
173611d26bd1SRiver Riddle         loc, "invalid reference to non-constraint", cstDecl->getLoc(),
173711d26bd1SRiver Riddle         "see the definition of `" + constraintName + "` here");
173811d26bd1SRiver Riddle   }
1739008de486SRiver Riddle     // Handle single entity constraint code completion.
1740008de486SRiver Riddle   case Token::code_complete: {
1741008de486SRiver Riddle     // Try to infer the current type for use by code completion.
1742008de486SRiver Riddle     ast::Type inferredType;
1743008de486SRiver Riddle     if (failed(validateVariableConstraints(existingConstraints, inferredType,
1744008de486SRiver Riddle                                            allowNonCoreConstraints)))
1745008de486SRiver Riddle       return failure();
1746008de486SRiver Riddle 
1747008de486SRiver Riddle     return codeCompleteConstraintName(inferredType, allowNonCoreConstraints,
1748008de486SRiver Riddle                                       allowInlineTypeConstraints);
1749008de486SRiver Riddle   }
175011d26bd1SRiver Riddle   default:
175111d26bd1SRiver Riddle     break;
175211d26bd1SRiver Riddle   }
175311d26bd1SRiver Riddle   return emitError(loc, "expected identifier constraint");
175411d26bd1SRiver Riddle }
175511d26bd1SRiver Riddle 
parseArgOrResultConstraint()1756faf42264SRiver Riddle FailureOr<ast::ConstraintRef> Parser::parseArgOrResultConstraint() {
1757008de486SRiver Riddle   // Constraint arguments may apply more complex constraints via the arguments.
1758008de486SRiver Riddle   bool allowNonCoreConstraints = parserContext == ParserContext::Constraint;
1759008de486SRiver Riddle 
1760faf42264SRiver Riddle   Optional<SMRange> typeConstraint;
1761faf42264SRiver Riddle   return parseConstraint(typeConstraint, /*existingConstraints=*/llvm::None,
1762008de486SRiver Riddle                          /*allowInlineTypeConstraints=*/false,
1763008de486SRiver Riddle                          allowNonCoreConstraints);
1764faf42264SRiver Riddle }
1765faf42264SRiver Riddle 
176611d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
176711d26bd1SRiver Riddle // Exprs
176811d26bd1SRiver Riddle 
parseExpr()176911d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseExpr() {
177011d26bd1SRiver Riddle   if (curToken.is(Token::underscore))
177111d26bd1SRiver Riddle     return parseUnderscoreExpr();
177211d26bd1SRiver Riddle 
177311d26bd1SRiver Riddle   // Parse the LHS expression.
177411d26bd1SRiver Riddle   FailureOr<ast::Expr *> lhsExpr;
177511d26bd1SRiver Riddle   switch (curToken.getKind()) {
1776d7e7fdf3SRiver Riddle   case Token::kw_attr:
1777d7e7fdf3SRiver Riddle     lhsExpr = parseAttributeExpr();
1778d7e7fdf3SRiver Riddle     break;
1779faf42264SRiver Riddle   case Token::kw_Constraint:
1780faf42264SRiver Riddle     lhsExpr = parseInlineConstraintLambdaExpr();
1781faf42264SRiver Riddle     break;
178211d26bd1SRiver Riddle   case Token::identifier:
178311d26bd1SRiver Riddle     lhsExpr = parseIdentifierExpr();
178411d26bd1SRiver Riddle     break;
178502670c3fSRiver Riddle   case Token::kw_op:
178602670c3fSRiver Riddle     lhsExpr = parseOperationExpr();
178702670c3fSRiver Riddle     break;
1788faf42264SRiver Riddle   case Token::kw_Rewrite:
1789faf42264SRiver Riddle     lhsExpr = parseInlineRewriteLambdaExpr();
1790faf42264SRiver Riddle     break;
1791d7e7fdf3SRiver Riddle   case Token::kw_type:
1792d7e7fdf3SRiver Riddle     lhsExpr = parseTypeExpr();
1793d7e7fdf3SRiver Riddle     break;
1794f62a57a3SRiver Riddle   case Token::l_paren:
1795f62a57a3SRiver Riddle     lhsExpr = parseTupleExpr();
1796f62a57a3SRiver Riddle     break;
179711d26bd1SRiver Riddle   default:
179811d26bd1SRiver Riddle     return emitError("expected expression");
179911d26bd1SRiver Riddle   }
180011d26bd1SRiver Riddle   if (failed(lhsExpr))
180111d26bd1SRiver Riddle     return failure();
180211d26bd1SRiver Riddle 
180311d26bd1SRiver Riddle   // Check for an operator expression.
180411d26bd1SRiver Riddle   while (true) {
180511d26bd1SRiver Riddle     switch (curToken.getKind()) {
180611d26bd1SRiver Riddle     case Token::dot:
180711d26bd1SRiver Riddle       lhsExpr = parseMemberAccessExpr(*lhsExpr);
180811d26bd1SRiver Riddle       break;
1809faf42264SRiver Riddle     case Token::l_paren:
1810faf42264SRiver Riddle       lhsExpr = parseCallExpr(*lhsExpr);
1811faf42264SRiver Riddle       break;
181211d26bd1SRiver Riddle     default:
181311d26bd1SRiver Riddle       return lhsExpr;
181411d26bd1SRiver Riddle     }
181511d26bd1SRiver Riddle     if (failed(lhsExpr))
181611d26bd1SRiver Riddle       return failure();
181711d26bd1SRiver Riddle   }
181811d26bd1SRiver Riddle }
181911d26bd1SRiver Riddle 
parseAttributeExpr()1820d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseAttributeExpr() {
18216842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
1822d7e7fdf3SRiver Riddle   consumeToken(Token::kw_attr);
1823d7e7fdf3SRiver Riddle 
1824d7e7fdf3SRiver Riddle   // If we aren't followed by a `<`, the `attr` keyword is treated as a normal
1825d7e7fdf3SRiver Riddle   // identifier.
1826d7e7fdf3SRiver Riddle   if (!consumeIf(Token::less)) {
1827d7e7fdf3SRiver Riddle     resetToken(loc);
1828d7e7fdf3SRiver Riddle     return parseIdentifierExpr();
1829d7e7fdf3SRiver Riddle   }
1830d7e7fdf3SRiver Riddle 
1831d7e7fdf3SRiver Riddle   if (!curToken.isString())
1832d7e7fdf3SRiver Riddle     return emitError("expected string literal containing MLIR attribute");
1833d7e7fdf3SRiver Riddle   std::string attrExpr = curToken.getStringValue();
1834d7e7fdf3SRiver Riddle   consumeToken();
1835d7e7fdf3SRiver Riddle 
18366d4471efSRiver Riddle   loc.End = curToken.getEndLoc();
1837d7e7fdf3SRiver Riddle   if (failed(
1838d7e7fdf3SRiver Riddle           parseToken(Token::greater, "expected `>` after attribute literal")))
1839d7e7fdf3SRiver Riddle     return failure();
1840d7e7fdf3SRiver Riddle   return ast::AttributeExpr::create(ctx, loc, attrExpr);
1841d7e7fdf3SRiver Riddle }
1842d7e7fdf3SRiver Riddle 
parseCallExpr(ast::Expr * parentExpr)1843faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseCallExpr(ast::Expr *parentExpr) {
1844faf42264SRiver Riddle   consumeToken(Token::l_paren);
1845faf42264SRiver Riddle 
1846faf42264SRiver Riddle   // Parse the arguments of the call.
1847faf42264SRiver Riddle   SmallVector<ast::Expr *> arguments;
1848faf42264SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
1849faf42264SRiver Riddle     do {
1850469c5894SRiver Riddle       // Handle code completion for the call arguments.
1851469c5894SRiver Riddle       if (curToken.is(Token::code_complete)) {
1852469c5894SRiver Riddle         codeCompleteCallSignature(parentExpr, arguments.size());
1853469c5894SRiver Riddle         return failure();
1854469c5894SRiver Riddle       }
1855469c5894SRiver Riddle 
1856faf42264SRiver Riddle       FailureOr<ast::Expr *> argument = parseExpr();
1857faf42264SRiver Riddle       if (failed(argument))
1858faf42264SRiver Riddle         return failure();
1859faf42264SRiver Riddle       arguments.push_back(*argument);
1860faf42264SRiver Riddle     } while (consumeIf(Token::comma));
1861faf42264SRiver Riddle   }
18626d4471efSRiver Riddle 
18636d4471efSRiver Riddle   SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc());
1864faf42264SRiver Riddle   if (failed(parseToken(Token::r_paren, "expected `)` after argument list")))
1865faf42264SRiver Riddle     return failure();
1866faf42264SRiver Riddle 
1867faf42264SRiver Riddle   return createCallExpr(loc, parentExpr, arguments);
1868faf42264SRiver Riddle }
1869faf42264SRiver Riddle 
parseDeclRefExpr(StringRef name,SMRange loc)1870faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
187111d26bd1SRiver Riddle   ast::Decl *decl = curDeclScope->lookup(name);
187211d26bd1SRiver Riddle   if (!decl)
187311d26bd1SRiver Riddle     return emitError(loc, "undefined reference to `" + name + "`");
187411d26bd1SRiver Riddle 
187511d26bd1SRiver Riddle   return createDeclRefExpr(loc, decl);
187611d26bd1SRiver Riddle }
187711d26bd1SRiver Riddle 
parseIdentifierExpr()187811d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseIdentifierExpr() {
187911d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
18806842ec42SRiver Riddle   SMRange nameLoc = curToken.getLoc();
188111d26bd1SRiver Riddle   consumeToken();
188211d26bd1SRiver Riddle 
188311d26bd1SRiver Riddle   // Check to see if this is a decl ref expression that defines a variable
188411d26bd1SRiver Riddle   // inline.
188511d26bd1SRiver Riddle   if (consumeIf(Token::colon)) {
188611d26bd1SRiver Riddle     SmallVector<ast::ConstraintRef> constraints;
188711d26bd1SRiver Riddle     if (failed(parseVariableDeclConstraintList(constraints)))
188811d26bd1SRiver Riddle       return failure();
188911d26bd1SRiver Riddle     ast::Type type;
189011d26bd1SRiver Riddle     if (failed(validateVariableConstraints(constraints, type)))
189111d26bd1SRiver Riddle       return failure();
189211d26bd1SRiver Riddle     return createInlineVariableExpr(type, name, nameLoc, constraints);
189311d26bd1SRiver Riddle   }
189411d26bd1SRiver Riddle 
189511d26bd1SRiver Riddle   return parseDeclRefExpr(name, nameLoc);
189611d26bd1SRiver Riddle }
189711d26bd1SRiver Riddle 
parseInlineConstraintLambdaExpr()1898faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineConstraintLambdaExpr() {
1899faf42264SRiver Riddle   FailureOr<ast::UserConstraintDecl *> decl = parseInlineUserConstraintDecl();
1900faf42264SRiver Riddle   if (failed(decl))
1901faf42264SRiver Riddle     return failure();
1902faf42264SRiver Riddle 
1903faf42264SRiver Riddle   return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl,
1904faf42264SRiver Riddle                                   ast::ConstraintType::get(ctx));
1905faf42264SRiver Riddle }
1906faf42264SRiver Riddle 
parseInlineRewriteLambdaExpr()1907faf42264SRiver Riddle FailureOr<ast::Expr *> Parser::parseInlineRewriteLambdaExpr() {
1908faf42264SRiver Riddle   FailureOr<ast::UserRewriteDecl *> decl = parseInlineUserRewriteDecl();
1909faf42264SRiver Riddle   if (failed(decl))
1910faf42264SRiver Riddle     return failure();
1911faf42264SRiver Riddle 
1912faf42264SRiver Riddle   return ast::DeclRefExpr::create(ctx, (*decl)->getLoc(), *decl,
1913faf42264SRiver Riddle                                   ast::RewriteType::get(ctx));
1914faf42264SRiver Riddle }
1915faf42264SRiver Riddle 
parseMemberAccessExpr(ast::Expr * parentExpr)191611d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseMemberAccessExpr(ast::Expr *parentExpr) {
19176d4471efSRiver Riddle   SMRange dotLoc = curToken.getLoc();
191811d26bd1SRiver Riddle   consumeToken(Token::dot);
191911d26bd1SRiver Riddle 
1920008de486SRiver Riddle   // Check for code completion of the member name.
1921008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1922008de486SRiver Riddle     return codeCompleteMemberAccess(parentExpr);
1923008de486SRiver Riddle 
192411d26bd1SRiver Riddle   // Parse the member name.
192511d26bd1SRiver Riddle   Token memberNameTok = curToken;
192611d26bd1SRiver Riddle   if (memberNameTok.isNot(Token::identifier, Token::integer) &&
192711d26bd1SRiver Riddle       !memberNameTok.isKeyword())
19286d4471efSRiver Riddle     return emitError(dotLoc, "expected identifier or numeric member name");
192911d26bd1SRiver Riddle   StringRef memberName = memberNameTok.getSpelling();
19306d4471efSRiver Riddle   SMRange loc(parentExpr->getLoc().Start, curToken.getEndLoc());
193111d26bd1SRiver Riddle   consumeToken();
193211d26bd1SRiver Riddle 
193311d26bd1SRiver Riddle   return createMemberAccessExpr(parentExpr, memberName, loc);
193411d26bd1SRiver Riddle }
193511d26bd1SRiver Riddle 
parseOperationName(bool allowEmptyName)193612eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *> Parser::parseOperationName(bool allowEmptyName) {
19376842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
193811d26bd1SRiver Riddle 
1939008de486SRiver Riddle   // Check for code completion for the dialect name.
1940008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1941008de486SRiver Riddle     return codeCompleteDialectName();
1942008de486SRiver Riddle 
194311d26bd1SRiver Riddle   // Handle the case of an no operation name.
194412eebb8eSRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isKeyword()) {
194512eebb8eSRiver Riddle     if (allowEmptyName)
19466842ec42SRiver Riddle       return ast::OpNameDecl::create(ctx, SMRange());
194712eebb8eSRiver Riddle     return emitError("expected dialect namespace");
194812eebb8eSRiver Riddle   }
194911d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
195011d26bd1SRiver Riddle   consumeToken();
195111d26bd1SRiver Riddle 
195211d26bd1SRiver Riddle   // Otherwise, this is a literal operation name.
195311d26bd1SRiver Riddle   if (failed(parseToken(Token::dot, "expected `.` after dialect namespace")))
195411d26bd1SRiver Riddle     return failure();
195511d26bd1SRiver Riddle 
1956008de486SRiver Riddle   // Check for code completion for the operation name.
1957008de486SRiver Riddle   if (curToken.is(Token::code_complete))
1958008de486SRiver Riddle     return codeCompleteOperationName(name);
1959008de486SRiver Riddle 
196011d26bd1SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isKeyword())
196111d26bd1SRiver Riddle     return emitError("expected operation name after dialect namespace");
196211d26bd1SRiver Riddle 
196311d26bd1SRiver Riddle   name = StringRef(name.data(), name.size() + 1);
196411d26bd1SRiver Riddle   do {
196511d26bd1SRiver Riddle     name = StringRef(name.data(), name.size() + curToken.getSpelling().size());
196611d26bd1SRiver Riddle     loc.End = curToken.getEndLoc();
196711d26bd1SRiver Riddle     consumeToken();
196811d26bd1SRiver Riddle   } while (curToken.isAny(Token::identifier, Token::dot) ||
196911d26bd1SRiver Riddle            curToken.isKeyword());
197011d26bd1SRiver Riddle   return ast::OpNameDecl::create(ctx, ast::Name::create(ctx, name, loc));
197111d26bd1SRiver Riddle }
197211d26bd1SRiver Riddle 
197312eebb8eSRiver Riddle FailureOr<ast::OpNameDecl *>
parseWrappedOperationName(bool allowEmptyName)197412eebb8eSRiver Riddle Parser::parseWrappedOperationName(bool allowEmptyName) {
197511d26bd1SRiver Riddle   if (!consumeIf(Token::less))
19766842ec42SRiver Riddle     return ast::OpNameDecl::create(ctx, SMRange());
197711d26bd1SRiver Riddle 
197812eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> opNameDecl = parseOperationName(allowEmptyName);
197911d26bd1SRiver Riddle   if (failed(opNameDecl))
198011d26bd1SRiver Riddle     return failure();
198111d26bd1SRiver Riddle 
198211d26bd1SRiver Riddle   if (failed(parseToken(Token::greater, "expected `>` after operation name")))
198311d26bd1SRiver Riddle     return failure();
198411d26bd1SRiver Riddle   return opNameDecl;
198511d26bd1SRiver Riddle }
198611d26bd1SRiver Riddle 
198791b8d96fSRiver Riddle FailureOr<ast::Expr *>
parseOperationExpr(OpResultTypeContext inputResultTypeContext)198891b8d96fSRiver Riddle Parser::parseOperationExpr(OpResultTypeContext inputResultTypeContext) {
19896842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
199002670c3fSRiver Riddle   consumeToken(Token::kw_op);
199102670c3fSRiver Riddle 
199202670c3fSRiver Riddle   // If it isn't followed by a `<`, the `op` keyword is treated as a normal
199302670c3fSRiver Riddle   // identifier.
199402670c3fSRiver Riddle   if (curToken.isNot(Token::less)) {
199502670c3fSRiver Riddle     resetToken(loc);
199602670c3fSRiver Riddle     return parseIdentifierExpr();
199702670c3fSRiver Riddle   }
199802670c3fSRiver Riddle 
199902670c3fSRiver Riddle   // Parse the operation name. The name may be elided, in which case the
200002670c3fSRiver Riddle   // operation refers to "any" operation(i.e. a difference between `MyOp` and
200112eebb8eSRiver Riddle   // `Operation*`). Operation names within a rewrite context must be named.
200212eebb8eSRiver Riddle   bool allowEmptyName = parserContext != ParserContext::Rewrite;
200312eebb8eSRiver Riddle   FailureOr<ast::OpNameDecl *> opNameDecl =
200412eebb8eSRiver Riddle       parseWrappedOperationName(allowEmptyName);
200502670c3fSRiver Riddle   if (failed(opNameDecl))
200602670c3fSRiver Riddle     return failure();
2007008de486SRiver Riddle   Optional<StringRef> opName = (*opNameDecl)->getName();
200802670c3fSRiver Riddle 
2009a486cf5eSRiver Riddle   // Functor used to create an implicit range variable, used for implicit "all"
2010a486cf5eSRiver Riddle   // operand or results variables.
2011a486cf5eSRiver Riddle   auto createImplicitRangeVar = [&](ast::ConstraintDecl *cst, ast::Type type) {
2012a486cf5eSRiver Riddle     FailureOr<ast::VariableDecl *> rangeVar =
2013a486cf5eSRiver Riddle         defineVariableDecl("_", loc, type, ast::ConstraintRef(cst, loc));
2014a486cf5eSRiver Riddle     assert(succeeded(rangeVar) && "expected range variable to be valid");
2015a486cf5eSRiver Riddle     return ast::DeclRefExpr::create(ctx, loc, *rangeVar, type);
2016a486cf5eSRiver Riddle   };
2017a486cf5eSRiver Riddle 
201802670c3fSRiver Riddle   // Check for the optional list of operands.
201902670c3fSRiver Riddle   SmallVector<ast::Expr *> operands;
2020a486cf5eSRiver Riddle   if (!consumeIf(Token::l_paren)) {
2021a486cf5eSRiver Riddle     // If the operand list isn't specified and we are in a match context, define
2022a486cf5eSRiver Riddle     // an inplace unconstrained operand range corresponding to all of the
2023a486cf5eSRiver Riddle     // operands of the operation. This avoids treating zero operands the same
2024a486cf5eSRiver Riddle     // way as "unconstrained operands".
2025a486cf5eSRiver Riddle     if (parserContext != ParserContext::Rewrite) {
2026a486cf5eSRiver Riddle       operands.push_back(createImplicitRangeVar(
2027a486cf5eSRiver Riddle           ast::ValueRangeConstraintDecl::create(ctx, loc), valueRangeTy));
2028a486cf5eSRiver Riddle     }
2029a486cf5eSRiver Riddle   } else if (!consumeIf(Token::r_paren)) {
20300429472eSRiver Riddle     // If the operand list was specified and non-empty, parse the operands.
20310429472eSRiver Riddle     do {
2032469c5894SRiver Riddle       // Check for operand signature code completion.
2033469c5894SRiver Riddle       if (curToken.is(Token::code_complete)) {
2034469c5894SRiver Riddle         codeCompleteOperationOperandsSignature(opName, operands.size());
2035469c5894SRiver Riddle         return failure();
2036469c5894SRiver Riddle       }
2037469c5894SRiver Riddle 
203802670c3fSRiver Riddle       FailureOr<ast::Expr *> operand = parseExpr();
203902670c3fSRiver Riddle       if (failed(operand))
204002670c3fSRiver Riddle         return failure();
204102670c3fSRiver Riddle       operands.push_back(*operand);
204202670c3fSRiver Riddle     } while (consumeIf(Token::comma));
204302670c3fSRiver Riddle 
204402670c3fSRiver Riddle     if (failed(parseToken(Token::r_paren,
204502670c3fSRiver Riddle                           "expected `)` after operation operand list")))
204602670c3fSRiver Riddle       return failure();
204702670c3fSRiver Riddle   }
204802670c3fSRiver Riddle 
204902670c3fSRiver Riddle   // Check for the optional list of attributes.
205002670c3fSRiver Riddle   SmallVector<ast::NamedAttributeDecl *> attributes;
205102670c3fSRiver Riddle   if (consumeIf(Token::l_brace)) {
205202670c3fSRiver Riddle     do {
2053008de486SRiver Riddle       FailureOr<ast::NamedAttributeDecl *> decl =
2054008de486SRiver Riddle           parseNamedAttributeDecl(opName);
205502670c3fSRiver Riddle       if (failed(decl))
205602670c3fSRiver Riddle         return failure();
205702670c3fSRiver Riddle       attributes.emplace_back(*decl);
205802670c3fSRiver Riddle     } while (consumeIf(Token::comma));
205902670c3fSRiver Riddle 
206002670c3fSRiver Riddle     if (failed(parseToken(Token::r_brace,
206102670c3fSRiver Riddle                           "expected `}` after operation attribute list")))
206202670c3fSRiver Riddle       return failure();
206302670c3fSRiver Riddle   }
206402670c3fSRiver Riddle 
206591b8d96fSRiver Riddle   // Handle the result types of the operation.
206602670c3fSRiver Riddle   SmallVector<ast::Expr *> resultTypes;
206791b8d96fSRiver Riddle   OpResultTypeContext resultTypeContext = inputResultTypeContext;
206891b8d96fSRiver Riddle 
206991b8d96fSRiver Riddle   // Check for an explicit list of result types.
207002670c3fSRiver Riddle   if (consumeIf(Token::arrow)) {
207102670c3fSRiver Riddle     if (failed(parseToken(Token::l_paren,
207202670c3fSRiver Riddle                           "expected `(` before operation result type list")))
207302670c3fSRiver Riddle       return failure();
207402670c3fSRiver Riddle 
207591b8d96fSRiver Riddle     // If result types are provided, initially assume that the operation does
207691b8d96fSRiver Riddle     // not rely on type inferrence. We don't assert that it isn't, because we
207791b8d96fSRiver Riddle     // may be inferring the value of some type/type range variables, but given
207891b8d96fSRiver Riddle     // that these variables may be defined in calls we can't always discern when
207991b8d96fSRiver Riddle     // this is the case.
208091b8d96fSRiver Riddle     resultTypeContext = OpResultTypeContext::Explicit;
208191b8d96fSRiver Riddle 
2082a486cf5eSRiver Riddle     // Handle the case of an empty result list.
2083a486cf5eSRiver Riddle     if (!consumeIf(Token::r_paren)) {
208402670c3fSRiver Riddle       do {
2085469c5894SRiver Riddle         // Check for result signature code completion.
2086469c5894SRiver Riddle         if (curToken.is(Token::code_complete)) {
2087469c5894SRiver Riddle           codeCompleteOperationResultsSignature(opName, resultTypes.size());
2088469c5894SRiver Riddle           return failure();
2089469c5894SRiver Riddle         }
2090469c5894SRiver Riddle 
209102670c3fSRiver Riddle         FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
209202670c3fSRiver Riddle         if (failed(resultTypeExpr))
209302670c3fSRiver Riddle           return failure();
209402670c3fSRiver Riddle         resultTypes.push_back(*resultTypeExpr);
209502670c3fSRiver Riddle       } while (consumeIf(Token::comma));
209602670c3fSRiver Riddle 
209702670c3fSRiver Riddle       if (failed(parseToken(Token::r_paren,
209802670c3fSRiver Riddle                             "expected `)` after operation result type list")))
209902670c3fSRiver Riddle         return failure();
210002670c3fSRiver Riddle     }
2101a486cf5eSRiver Riddle   } else if (parserContext != ParserContext::Rewrite) {
2102a486cf5eSRiver Riddle     // If the result list isn't specified and we are in a match context, define
2103a486cf5eSRiver Riddle     // an inplace unconstrained result range corresponding to all of the results
2104a486cf5eSRiver Riddle     // of the operation. This avoids treating zero results the same way as
2105a486cf5eSRiver Riddle     // "unconstrained results".
2106a486cf5eSRiver Riddle     resultTypes.push_back(createImplicitRangeVar(
2107a486cf5eSRiver Riddle         ast::TypeRangeConstraintDecl::create(ctx, loc), typeRangeTy));
210891b8d96fSRiver Riddle   } else if (resultTypeContext == OpResultTypeContext::Explicit) {
210991b8d96fSRiver Riddle     // If the result list isn't specified and we are in a rewrite, try to infer
211091b8d96fSRiver Riddle     // them at runtime instead.
211191b8d96fSRiver Riddle     resultTypeContext = OpResultTypeContext::Interface;
2112a486cf5eSRiver Riddle   }
211302670c3fSRiver Riddle 
211491b8d96fSRiver Riddle   return createOperationExpr(loc, *opNameDecl, resultTypeContext, operands,
211591b8d96fSRiver Riddle                              attributes, resultTypes);
211602670c3fSRiver Riddle }
211702670c3fSRiver Riddle 
parseTupleExpr()2118f62a57a3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTupleExpr() {
21196842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
2120f62a57a3SRiver Riddle   consumeToken(Token::l_paren);
2121f62a57a3SRiver Riddle 
21226842ec42SRiver Riddle   DenseMap<StringRef, SMRange> usedNames;
2123f62a57a3SRiver Riddle   SmallVector<StringRef> elementNames;
2124f62a57a3SRiver Riddle   SmallVector<ast::Expr *> elements;
2125f62a57a3SRiver Riddle   if (curToken.isNot(Token::r_paren)) {
2126f62a57a3SRiver Riddle     do {
2127f62a57a3SRiver Riddle       // Check for the optional element name assignment before the value.
2128f62a57a3SRiver Riddle       StringRef elementName;
2129f62a57a3SRiver Riddle       if (curToken.is(Token::identifier) || curToken.isDependentKeyword()) {
2130f62a57a3SRiver Riddle         Token elementNameTok = curToken;
2131f62a57a3SRiver Riddle         consumeToken();
2132f62a57a3SRiver Riddle 
2133f62a57a3SRiver Riddle         // The element name is only present if followed by an `=`.
2134f62a57a3SRiver Riddle         if (consumeIf(Token::equal)) {
2135f62a57a3SRiver Riddle           elementName = elementNameTok.getSpelling();
2136f62a57a3SRiver Riddle 
2137f62a57a3SRiver Riddle           // Check to see if this name is already used.
2138f62a57a3SRiver Riddle           auto elementNameIt =
2139f62a57a3SRiver Riddle               usedNames.try_emplace(elementName, elementNameTok.getLoc());
2140f62a57a3SRiver Riddle           if (!elementNameIt.second) {
2141f62a57a3SRiver Riddle             return emitErrorAndNote(
2142f62a57a3SRiver Riddle                 elementNameTok.getLoc(),
2143f62a57a3SRiver Riddle                 llvm::formatv("duplicate tuple element label `{0}`",
2144f62a57a3SRiver Riddle                               elementName),
2145f62a57a3SRiver Riddle                 elementNameIt.first->getSecond(),
2146f62a57a3SRiver Riddle                 "see previous label use here");
2147f62a57a3SRiver Riddle           }
2148f62a57a3SRiver Riddle         } else {
2149f62a57a3SRiver Riddle           // Otherwise, we treat this as part of an expression so reset the
2150f62a57a3SRiver Riddle           // lexer.
2151f62a57a3SRiver Riddle           resetToken(elementNameTok.getLoc());
2152f62a57a3SRiver Riddle         }
2153f62a57a3SRiver Riddle       }
2154f62a57a3SRiver Riddle       elementNames.push_back(elementName);
2155f62a57a3SRiver Riddle 
2156f62a57a3SRiver Riddle       // Parse the tuple element value.
2157f62a57a3SRiver Riddle       FailureOr<ast::Expr *> element = parseExpr();
2158f62a57a3SRiver Riddle       if (failed(element))
2159f62a57a3SRiver Riddle         return failure();
2160f62a57a3SRiver Riddle       elements.push_back(*element);
2161f62a57a3SRiver Riddle     } while (consumeIf(Token::comma));
2162f62a57a3SRiver Riddle   }
2163f62a57a3SRiver Riddle   loc.End = curToken.getEndLoc();
2164f62a57a3SRiver Riddle   if (failed(
2165f62a57a3SRiver Riddle           parseToken(Token::r_paren, "expected `)` after tuple element list")))
2166f62a57a3SRiver Riddle     return failure();
2167f62a57a3SRiver Riddle   return createTupleExpr(loc, elements, elementNames);
2168f62a57a3SRiver Riddle }
2169f62a57a3SRiver Riddle 
parseTypeExpr()2170d7e7fdf3SRiver Riddle FailureOr<ast::Expr *> Parser::parseTypeExpr() {
21716842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
2172d7e7fdf3SRiver Riddle   consumeToken(Token::kw_type);
2173d7e7fdf3SRiver Riddle 
2174d7e7fdf3SRiver Riddle   // If we aren't followed by a `<`, the `type` keyword is treated as a normal
2175d7e7fdf3SRiver Riddle   // identifier.
2176d7e7fdf3SRiver Riddle   if (!consumeIf(Token::less)) {
2177d7e7fdf3SRiver Riddle     resetToken(loc);
2178d7e7fdf3SRiver Riddle     return parseIdentifierExpr();
2179d7e7fdf3SRiver Riddle   }
2180d7e7fdf3SRiver Riddle 
2181d7e7fdf3SRiver Riddle   if (!curToken.isString())
2182d7e7fdf3SRiver Riddle     return emitError("expected string literal containing MLIR type");
2183d7e7fdf3SRiver Riddle   std::string attrExpr = curToken.getStringValue();
2184d7e7fdf3SRiver Riddle   consumeToken();
2185d7e7fdf3SRiver Riddle 
21866d4471efSRiver Riddle   loc.End = curToken.getEndLoc();
2187d7e7fdf3SRiver Riddle   if (failed(parseToken(Token::greater, "expected `>` after type literal")))
2188d7e7fdf3SRiver Riddle     return failure();
2189d7e7fdf3SRiver Riddle   return ast::TypeExpr::create(ctx, loc, attrExpr);
2190d7e7fdf3SRiver Riddle }
2191d7e7fdf3SRiver Riddle 
parseUnderscoreExpr()219211d26bd1SRiver Riddle FailureOr<ast::Expr *> Parser::parseUnderscoreExpr() {
219311d26bd1SRiver Riddle   StringRef name = curToken.getSpelling();
21946842ec42SRiver Riddle   SMRange nameLoc = curToken.getLoc();
219511d26bd1SRiver Riddle   consumeToken(Token::underscore);
219611d26bd1SRiver Riddle 
219711d26bd1SRiver Riddle   // Underscore expressions require a constraint list.
219811d26bd1SRiver Riddle   if (failed(parseToken(Token::colon, "expected `:` after `_` variable")))
219911d26bd1SRiver Riddle     return failure();
220011d26bd1SRiver Riddle 
220111d26bd1SRiver Riddle   // Parse the constraints for the expression.
220211d26bd1SRiver Riddle   SmallVector<ast::ConstraintRef> constraints;
220311d26bd1SRiver Riddle   if (failed(parseVariableDeclConstraintList(constraints)))
220411d26bd1SRiver Riddle     return failure();
220511d26bd1SRiver Riddle 
220611d26bd1SRiver Riddle   ast::Type type;
220711d26bd1SRiver Riddle   if (failed(validateVariableConstraints(constraints, type)))
220811d26bd1SRiver Riddle     return failure();
220911d26bd1SRiver Riddle   return createInlineVariableExpr(type, name, nameLoc, constraints);
221011d26bd1SRiver Riddle }
221111d26bd1SRiver Riddle 
221211d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
221311d26bd1SRiver Riddle // Stmts
221411d26bd1SRiver Riddle 
parseStmt(bool expectTerminalSemicolon)221511d26bd1SRiver Riddle FailureOr<ast::Stmt *> Parser::parseStmt(bool expectTerminalSemicolon) {
221611d26bd1SRiver Riddle   FailureOr<ast::Stmt *> stmt;
221711d26bd1SRiver Riddle   switch (curToken.getKind()) {
221811d26bd1SRiver Riddle   case Token::kw_erase:
221911d26bd1SRiver Riddle     stmt = parseEraseStmt();
222011d26bd1SRiver Riddle     break;
222111d26bd1SRiver Riddle   case Token::kw_let:
222211d26bd1SRiver Riddle     stmt = parseLetStmt();
222311d26bd1SRiver Riddle     break;
222412eebb8eSRiver Riddle   case Token::kw_replace:
222512eebb8eSRiver Riddle     stmt = parseReplaceStmt();
222612eebb8eSRiver Riddle     break;
2227faf42264SRiver Riddle   case Token::kw_return:
2228faf42264SRiver Riddle     stmt = parseReturnStmt();
2229faf42264SRiver Riddle     break;
22303ee44cb7SRiver Riddle   case Token::kw_rewrite:
22313ee44cb7SRiver Riddle     stmt = parseRewriteStmt();
22323ee44cb7SRiver Riddle     break;
223311d26bd1SRiver Riddle   default:
223411d26bd1SRiver Riddle     stmt = parseExpr();
223511d26bd1SRiver Riddle     break;
223611d26bd1SRiver Riddle   }
223711d26bd1SRiver Riddle   if (failed(stmt) ||
223811d26bd1SRiver Riddle       (expectTerminalSemicolon &&
223911d26bd1SRiver Riddle        failed(parseToken(Token::semicolon, "expected `;` after statement"))))
224011d26bd1SRiver Riddle     return failure();
224111d26bd1SRiver Riddle   return stmt;
224211d26bd1SRiver Riddle }
224311d26bd1SRiver Riddle 
parseCompoundStmt()224411d26bd1SRiver Riddle FailureOr<ast::CompoundStmt *> Parser::parseCompoundStmt() {
22456842ec42SRiver Riddle   SMLoc startLoc = curToken.getStartLoc();
224611d26bd1SRiver Riddle   consumeToken(Token::l_brace);
224711d26bd1SRiver Riddle 
224811d26bd1SRiver Riddle   // Push a new block scope and parse any nested statements.
224911d26bd1SRiver Riddle   pushDeclScope();
225011d26bd1SRiver Riddle   SmallVector<ast::Stmt *> statements;
225111d26bd1SRiver Riddle   while (curToken.isNot(Token::r_brace)) {
225211d26bd1SRiver Riddle     FailureOr<ast::Stmt *> statement = parseStmt();
225311d26bd1SRiver Riddle     if (failed(statement))
225411d26bd1SRiver Riddle       return popDeclScope(), failure();
225511d26bd1SRiver Riddle     statements.push_back(*statement);
225611d26bd1SRiver Riddle   }
225711d26bd1SRiver Riddle   popDeclScope();
225811d26bd1SRiver Riddle 
225911d26bd1SRiver Riddle   // Consume the end brace.
22606842ec42SRiver Riddle   SMRange location(startLoc, curToken.getEndLoc());
226111d26bd1SRiver Riddle   consumeToken(Token::r_brace);
226211d26bd1SRiver Riddle 
226311d26bd1SRiver Riddle   return ast::CompoundStmt::create(ctx, location, statements);
226411d26bd1SRiver Riddle }
226511d26bd1SRiver Riddle 
parseEraseStmt()226611d26bd1SRiver Riddle FailureOr<ast::EraseStmt *> Parser::parseEraseStmt() {
2267faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2268faf42264SRiver Riddle     return emitError("`erase` cannot be used within a Constraint");
22696842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
227011d26bd1SRiver Riddle   consumeToken(Token::kw_erase);
227111d26bd1SRiver Riddle 
227211d26bd1SRiver Riddle   // Parse the root operation expression.
227311d26bd1SRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
227411d26bd1SRiver Riddle   if (failed(rootOp))
227511d26bd1SRiver Riddle     return failure();
227611d26bd1SRiver Riddle 
227711d26bd1SRiver Riddle   return createEraseStmt(loc, *rootOp);
227811d26bd1SRiver Riddle }
227911d26bd1SRiver Riddle 
parseLetStmt()228011d26bd1SRiver Riddle FailureOr<ast::LetStmt *> Parser::parseLetStmt() {
22816842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
228211d26bd1SRiver Riddle   consumeToken(Token::kw_let);
228311d26bd1SRiver Riddle 
228411d26bd1SRiver Riddle   // Parse the name of the new variable.
22856842ec42SRiver Riddle   SMRange varLoc = curToken.getLoc();
228611d26bd1SRiver Riddle   if (curToken.isNot(Token::identifier) && !curToken.isDependentKeyword()) {
228711d26bd1SRiver Riddle     // `_` is a reserved variable name.
228811d26bd1SRiver Riddle     if (curToken.is(Token::underscore)) {
228911d26bd1SRiver Riddle       return emitError(varLoc,
229011d26bd1SRiver Riddle                        "`_` may only be used to define \"inline\" variables");
229111d26bd1SRiver Riddle     }
229211d26bd1SRiver Riddle     return emitError(varLoc,
229311d26bd1SRiver Riddle                      "expected identifier after `let` to name a new variable");
229411d26bd1SRiver Riddle   }
229511d26bd1SRiver Riddle   StringRef varName = curToken.getSpelling();
229611d26bd1SRiver Riddle   consumeToken();
229711d26bd1SRiver Riddle 
229811d26bd1SRiver Riddle   // Parse the optional set of constraints.
229911d26bd1SRiver Riddle   SmallVector<ast::ConstraintRef> constraints;
230011d26bd1SRiver Riddle   if (consumeIf(Token::colon) &&
230111d26bd1SRiver Riddle       failed(parseVariableDeclConstraintList(constraints)))
230211d26bd1SRiver Riddle     return failure();
230311d26bd1SRiver Riddle 
230411d26bd1SRiver Riddle   // Parse the optional initializer expression.
230511d26bd1SRiver Riddle   ast::Expr *initializer = nullptr;
230611d26bd1SRiver Riddle   if (consumeIf(Token::equal)) {
230711d26bd1SRiver Riddle     FailureOr<ast::Expr *> initOrFailure = parseExpr();
230811d26bd1SRiver Riddle     if (failed(initOrFailure))
230911d26bd1SRiver Riddle       return failure();
231011d26bd1SRiver Riddle     initializer = *initOrFailure;
231111d26bd1SRiver Riddle 
231211d26bd1SRiver Riddle     // Check that the constraints are compatible with having an initializer,
231311d26bd1SRiver Riddle     // e.g. type constraints cannot be used with initializers.
231411d26bd1SRiver Riddle     for (ast::ConstraintRef constraint : constraints) {
231511d26bd1SRiver Riddle       LogicalResult result =
231611d26bd1SRiver Riddle           TypeSwitch<const ast::Node *, LogicalResult>(constraint.constraint)
231711d26bd1SRiver Riddle               .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl,
231811d26bd1SRiver Riddle                     ast::ValueRangeConstraintDecl>([&](const auto *cst) {
231911d26bd1SRiver Riddle                 if (auto *typeConstraintExpr = cst->getTypeExpr()) {
2320e76043acSRiver Riddle                   return this->emitError(
232111d26bd1SRiver Riddle                       constraint.referenceLoc,
232211d26bd1SRiver Riddle                       "type constraints are not permitted on variables with "
232311d26bd1SRiver Riddle                       "initializers");
232411d26bd1SRiver Riddle                 }
232511d26bd1SRiver Riddle                 return success();
232611d26bd1SRiver Riddle               })
232711d26bd1SRiver Riddle               .Default(success());
232811d26bd1SRiver Riddle       if (failed(result))
232911d26bd1SRiver Riddle         return failure();
233011d26bd1SRiver Riddle     }
233111d26bd1SRiver Riddle   }
233211d26bd1SRiver Riddle 
233311d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> varDecl =
233411d26bd1SRiver Riddle       createVariableDecl(varName, varLoc, initializer, constraints);
233511d26bd1SRiver Riddle   if (failed(varDecl))
233611d26bd1SRiver Riddle     return failure();
233711d26bd1SRiver Riddle   return ast::LetStmt::create(ctx, loc, *varDecl);
233811d26bd1SRiver Riddle }
233911d26bd1SRiver Riddle 
parseReplaceStmt()234012eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *> Parser::parseReplaceStmt() {
2341faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2342faf42264SRiver Riddle     return emitError("`replace` cannot be used within a Constraint");
23436842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
234412eebb8eSRiver Riddle   consumeToken(Token::kw_replace);
234512eebb8eSRiver Riddle 
234612eebb8eSRiver Riddle   // Parse the root operation expression.
234712eebb8eSRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
234812eebb8eSRiver Riddle   if (failed(rootOp))
234912eebb8eSRiver Riddle     return failure();
235012eebb8eSRiver Riddle 
235112eebb8eSRiver Riddle   if (failed(
235212eebb8eSRiver Riddle           parseToken(Token::kw_with, "expected `with` after root operation")))
235312eebb8eSRiver Riddle     return failure();
235412eebb8eSRiver Riddle 
235512eebb8eSRiver Riddle   // The replacement portion of this statement is within a rewrite context.
235612eebb8eSRiver Riddle   llvm::SaveAndRestore<ParserContext> saveCtx(parserContext,
235712eebb8eSRiver Riddle                                               ParserContext::Rewrite);
235812eebb8eSRiver Riddle 
235912eebb8eSRiver Riddle   // Parse the replacement values.
236012eebb8eSRiver Riddle   SmallVector<ast::Expr *> replValues;
236112eebb8eSRiver Riddle   if (consumeIf(Token::l_paren)) {
236212eebb8eSRiver Riddle     if (consumeIf(Token::r_paren)) {
236312eebb8eSRiver Riddle       return emitError(
236412eebb8eSRiver Riddle           loc, "expected at least one replacement value, consider using "
236512eebb8eSRiver Riddle                "`erase` if no replacement values are desired");
236612eebb8eSRiver Riddle     }
236712eebb8eSRiver Riddle 
236812eebb8eSRiver Riddle     do {
236912eebb8eSRiver Riddle       FailureOr<ast::Expr *> replExpr = parseExpr();
237012eebb8eSRiver Riddle       if (failed(replExpr))
237112eebb8eSRiver Riddle         return failure();
237212eebb8eSRiver Riddle       replValues.emplace_back(*replExpr);
237312eebb8eSRiver Riddle     } while (consumeIf(Token::comma));
237412eebb8eSRiver Riddle 
237512eebb8eSRiver Riddle     if (failed(parseToken(Token::r_paren,
237612eebb8eSRiver Riddle                           "expected `)` after replacement values")))
237712eebb8eSRiver Riddle       return failure();
237812eebb8eSRiver Riddle   } else {
237991b8d96fSRiver Riddle     // Handle replacement with an operation uniquely, as the replacement
238091b8d96fSRiver Riddle     // operation supports type inferrence from the root operation.
238191b8d96fSRiver Riddle     FailureOr<ast::Expr *> replExpr;
238291b8d96fSRiver Riddle     if (curToken.is(Token::kw_op))
238391b8d96fSRiver Riddle       replExpr = parseOperationExpr(OpResultTypeContext::Replacement);
238491b8d96fSRiver Riddle     else
238591b8d96fSRiver Riddle       replExpr = parseExpr();
238612eebb8eSRiver Riddle     if (failed(replExpr))
238712eebb8eSRiver Riddle       return failure();
238812eebb8eSRiver Riddle     replValues.emplace_back(*replExpr);
238912eebb8eSRiver Riddle   }
239012eebb8eSRiver Riddle 
239112eebb8eSRiver Riddle   return createReplaceStmt(loc, *rootOp, replValues);
239212eebb8eSRiver Riddle }
239312eebb8eSRiver Riddle 
parseReturnStmt()2394faf42264SRiver Riddle FailureOr<ast::ReturnStmt *> Parser::parseReturnStmt() {
2395faf42264SRiver Riddle   SMRange loc = curToken.getLoc();
2396faf42264SRiver Riddle   consumeToken(Token::kw_return);
2397faf42264SRiver Riddle 
2398faf42264SRiver Riddle   // Parse the result value.
2399faf42264SRiver Riddle   FailureOr<ast::Expr *> resultExpr = parseExpr();
2400faf42264SRiver Riddle   if (failed(resultExpr))
2401faf42264SRiver Riddle     return failure();
2402faf42264SRiver Riddle 
2403faf42264SRiver Riddle   return ast::ReturnStmt::create(ctx, loc, *resultExpr);
2404faf42264SRiver Riddle }
2405faf42264SRiver Riddle 
parseRewriteStmt()24063ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *> Parser::parseRewriteStmt() {
2407faf42264SRiver Riddle   if (parserContext == ParserContext::Constraint)
2408faf42264SRiver Riddle     return emitError("`rewrite` cannot be used within a Constraint");
24096842ec42SRiver Riddle   SMRange loc = curToken.getLoc();
24103ee44cb7SRiver Riddle   consumeToken(Token::kw_rewrite);
24113ee44cb7SRiver Riddle 
24123ee44cb7SRiver Riddle   // Parse the root operation.
24133ee44cb7SRiver Riddle   FailureOr<ast::Expr *> rootOp = parseExpr();
24143ee44cb7SRiver Riddle   if (failed(rootOp))
24153ee44cb7SRiver Riddle     return failure();
24163ee44cb7SRiver Riddle 
24173ee44cb7SRiver Riddle   if (failed(parseToken(Token::kw_with, "expected `with` before rewrite body")))
24183ee44cb7SRiver Riddle     return failure();
24193ee44cb7SRiver Riddle 
24203ee44cb7SRiver Riddle   if (curToken.isNot(Token::l_brace))
24213ee44cb7SRiver Riddle     return emitError("expected `{` to start rewrite body");
24223ee44cb7SRiver Riddle 
24233ee44cb7SRiver Riddle   // The rewrite body of this statement is within a rewrite context.
24243ee44cb7SRiver Riddle   llvm::SaveAndRestore<ParserContext> saveCtx(parserContext,
24253ee44cb7SRiver Riddle                                               ParserContext::Rewrite);
24263ee44cb7SRiver Riddle 
24273ee44cb7SRiver Riddle   FailureOr<ast::CompoundStmt *> rewriteBody = parseCompoundStmt();
24283ee44cb7SRiver Riddle   if (failed(rewriteBody))
24293ee44cb7SRiver Riddle     return failure();
24303ee44cb7SRiver Riddle 
2431faf42264SRiver Riddle   // Verify the rewrite body.
2432faf42264SRiver Riddle   for (const ast::Stmt *stmt : (*rewriteBody)->getChildren()) {
2433faf42264SRiver Riddle     if (isa<ast::ReturnStmt>(stmt)) {
2434faf42264SRiver Riddle       return emitError(stmt->getLoc(),
2435faf42264SRiver Riddle                        "`return` statements are only permitted within a "
2436faf42264SRiver Riddle                        "`Constraint` or `Rewrite` body");
2437faf42264SRiver Riddle     }
2438faf42264SRiver Riddle   }
2439faf42264SRiver Riddle 
24403ee44cb7SRiver Riddle   return createRewriteStmt(loc, *rootOp, *rewriteBody);
24413ee44cb7SRiver Riddle }
24423ee44cb7SRiver Riddle 
244311d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
244411d26bd1SRiver Riddle // Creation+Analysis
244511d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
244611d26bd1SRiver Riddle 
244711d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
244811d26bd1SRiver Riddle // Decls
244911d26bd1SRiver Riddle 
tryExtractCallableDecl(ast::Node * node)2450faf42264SRiver Riddle ast::CallableDecl *Parser::tryExtractCallableDecl(ast::Node *node) {
2451faf42264SRiver Riddle   // Unwrap reference expressions.
2452faf42264SRiver Riddle   if (auto *init = dyn_cast<ast::DeclRefExpr>(node))
2453faf42264SRiver Riddle     node = init->getDecl();
2454faf42264SRiver Riddle   return dyn_cast<ast::CallableDecl>(node);
2455faf42264SRiver Riddle }
2456faf42264SRiver Riddle 
245711d26bd1SRiver Riddle FailureOr<ast::PatternDecl *>
createPatternDecl(SMRange loc,const ast::Name * name,const ParsedPatternMetadata & metadata,ast::CompoundStmt * body)24586842ec42SRiver Riddle Parser::createPatternDecl(SMRange loc, const ast::Name *name,
2459322691abSRiver Riddle                           const ParsedPatternMetadata &metadata,
246011d26bd1SRiver Riddle                           ast::CompoundStmt *body) {
2461322691abSRiver Riddle   return ast::PatternDecl::create(ctx, loc, name, metadata.benefit,
2462322691abSRiver Riddle                                   metadata.hasBoundedRecursion, body);
246311d26bd1SRiver Riddle }
246411d26bd1SRiver Riddle 
createUserConstraintRewriteResultType(ArrayRef<ast::VariableDecl * > results)2465faf42264SRiver Riddle ast::Type Parser::createUserConstraintRewriteResultType(
2466faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results) {
2467faf42264SRiver Riddle   // Single result decls use the type of the single result.
2468faf42264SRiver Riddle   if (results.size() == 1)
2469faf42264SRiver Riddle     return results[0]->getType();
2470faf42264SRiver Riddle 
2471faf42264SRiver Riddle   // Multiple results use a tuple type, with the types and names grabbed from
2472faf42264SRiver Riddle   // the result variable decls.
2473faf42264SRiver Riddle   auto resultTypes = llvm::map_range(
2474faf42264SRiver Riddle       results, [&](const auto *result) { return result->getType(); });
2475faf42264SRiver Riddle   auto resultNames = llvm::map_range(
2476faf42264SRiver Riddle       results, [&](const auto *result) { return result->getName().getName(); });
2477faf42264SRiver Riddle   return ast::TupleType::get(ctx, llvm::to_vector(resultTypes),
2478faf42264SRiver Riddle                              llvm::to_vector(resultNames));
2479faf42264SRiver Riddle }
2480faf42264SRiver Riddle 
2481faf42264SRiver Riddle template <typename T>
createUserPDLLConstraintOrRewriteDecl(const ast::Name & name,ArrayRef<ast::VariableDecl * > arguments,ArrayRef<ast::VariableDecl * > results,ast::Type resultType,ast::CompoundStmt * body)2482faf42264SRiver Riddle FailureOr<T *> Parser::createUserPDLLConstraintOrRewriteDecl(
2483faf42264SRiver Riddle     const ast::Name &name, ArrayRef<ast::VariableDecl *> arguments,
2484faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> results, ast::Type resultType,
2485faf42264SRiver Riddle     ast::CompoundStmt *body) {
2486faf42264SRiver Riddle   if (!body->getChildren().empty()) {
2487faf42264SRiver Riddle     if (auto *retStmt = dyn_cast<ast::ReturnStmt>(body->getChildren().back())) {
2488faf42264SRiver Riddle       ast::Expr *resultExpr = retStmt->getResultExpr();
2489faf42264SRiver Riddle 
2490faf42264SRiver Riddle       // Process the result of the decl. If no explicit signature results
2491faf42264SRiver Riddle       // were provided, check for return type inference. Otherwise, check that
2492faf42264SRiver Riddle       // the return expression can be converted to the expected type.
2493faf42264SRiver Riddle       if (results.empty())
2494faf42264SRiver Riddle         resultType = resultExpr->getType();
2495faf42264SRiver Riddle       else if (failed(convertExpressionTo(resultExpr, resultType)))
2496faf42264SRiver Riddle         return failure();
2497faf42264SRiver Riddle       else
2498faf42264SRiver Riddle         retStmt->setResultExpr(resultExpr);
2499faf42264SRiver Riddle     }
2500faf42264SRiver Riddle   }
2501faf42264SRiver Riddle   return T::createPDLL(ctx, name, arguments, results, body, resultType);
2502faf42264SRiver Riddle }
2503faf42264SRiver Riddle 
250411d26bd1SRiver Riddle FailureOr<ast::VariableDecl *>
createVariableDecl(StringRef name,SMRange loc,ast::Expr * initializer,ArrayRef<ast::ConstraintRef> constraints)2505faf42264SRiver Riddle Parser::createVariableDecl(StringRef name, SMRange loc, ast::Expr *initializer,
250611d26bd1SRiver Riddle                            ArrayRef<ast::ConstraintRef> constraints) {
250711d26bd1SRiver Riddle   // The type of the variable, which is expected to be inferred by either a
250811d26bd1SRiver Riddle   // constraint or an initializer expression.
250911d26bd1SRiver Riddle   ast::Type type;
251011d26bd1SRiver Riddle   if (failed(validateVariableConstraints(constraints, type)))
251111d26bd1SRiver Riddle     return failure();
251211d26bd1SRiver Riddle 
251311d26bd1SRiver Riddle   if (initializer) {
251411d26bd1SRiver Riddle     // Update the variable type based on the initializer, or try to convert the
251511d26bd1SRiver Riddle     // initializer to the existing type.
251611d26bd1SRiver Riddle     if (!type)
251711d26bd1SRiver Riddle       type = initializer->getType();
251811d26bd1SRiver Riddle     else if (ast::Type mergedType = type.refineWith(initializer->getType()))
251911d26bd1SRiver Riddle       type = mergedType;
252011d26bd1SRiver Riddle     else if (failed(convertExpressionTo(initializer, type)))
252111d26bd1SRiver Riddle       return failure();
252211d26bd1SRiver Riddle 
252311d26bd1SRiver Riddle     // Otherwise, if there is no initializer check that the type has already
252411d26bd1SRiver Riddle     // been resolved from the constraint list.
252511d26bd1SRiver Riddle   } else if (!type) {
252611d26bd1SRiver Riddle     return emitErrorAndNote(
252711d26bd1SRiver Riddle         loc, "unable to infer type for variable `" + name + "`", loc,
252811d26bd1SRiver Riddle         "the type of a variable must be inferable from the constraint "
252911d26bd1SRiver Riddle         "list or the initializer");
253011d26bd1SRiver Riddle   }
253111d26bd1SRiver Riddle 
2532faf42264SRiver Riddle   // Constraint types cannot be used when defining variables.
2533faf42264SRiver Riddle   if (type.isa<ast::ConstraintType, ast::RewriteType>()) {
2534faf42264SRiver Riddle     return emitError(
2535faf42264SRiver Riddle         loc, llvm::formatv("unable to define variable of `{0}` type", type));
2536faf42264SRiver Riddle   }
2537faf42264SRiver Riddle 
253811d26bd1SRiver Riddle   // Try to define a variable with the given name.
253911d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> varDecl =
254011d26bd1SRiver Riddle       defineVariableDecl(name, loc, type, initializer, constraints);
254111d26bd1SRiver Riddle   if (failed(varDecl))
254211d26bd1SRiver Riddle     return failure();
254311d26bd1SRiver Riddle 
254411d26bd1SRiver Riddle   return *varDecl;
254511d26bd1SRiver Riddle }
254611d26bd1SRiver Riddle 
2547faf42264SRiver Riddle FailureOr<ast::VariableDecl *>
createArgOrResultVariableDecl(StringRef name,SMRange loc,const ast::ConstraintRef & constraint)2548faf42264SRiver Riddle Parser::createArgOrResultVariableDecl(StringRef name, SMRange loc,
2549faf42264SRiver Riddle                                       const ast::ConstraintRef &constraint) {
2550faf42264SRiver Riddle   // Constraint arguments may apply more complex constraints via the arguments.
2551faf42264SRiver Riddle   bool allowNonCoreConstraints = parserContext == ParserContext::Constraint;
2552faf42264SRiver Riddle   ast::Type argType;
2553faf42264SRiver Riddle   if (failed(validateVariableConstraint(constraint, argType,
2554faf42264SRiver Riddle                                         allowNonCoreConstraints)))
2555faf42264SRiver Riddle     return failure();
2556faf42264SRiver Riddle   return defineVariableDecl(name, loc, argType, constraint);
2557faf42264SRiver Riddle }
2558faf42264SRiver Riddle 
255911d26bd1SRiver Riddle LogicalResult
validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,ast::Type & inferredType,bool allowNonCoreConstraints)256011d26bd1SRiver Riddle Parser::validateVariableConstraints(ArrayRef<ast::ConstraintRef> constraints,
2561008de486SRiver Riddle                                     ast::Type &inferredType,
2562008de486SRiver Riddle                                     bool allowNonCoreConstraints) {
256311d26bd1SRiver Riddle   for (const ast::ConstraintRef &ref : constraints)
2564008de486SRiver Riddle     if (failed(validateVariableConstraint(ref, inferredType,
2565008de486SRiver Riddle                                           allowNonCoreConstraints)))
256611d26bd1SRiver Riddle       return failure();
256711d26bd1SRiver Riddle   return success();
256811d26bd1SRiver Riddle }
256911d26bd1SRiver Riddle 
validateVariableConstraint(const ast::ConstraintRef & ref,ast::Type & inferredType,bool allowNonCoreConstraints)257011d26bd1SRiver Riddle LogicalResult Parser::validateVariableConstraint(const ast::ConstraintRef &ref,
2571faf42264SRiver Riddle                                                  ast::Type &inferredType,
2572faf42264SRiver Riddle                                                  bool allowNonCoreConstraints) {
257311d26bd1SRiver Riddle   ast::Type constraintType;
257411d26bd1SRiver Riddle   if (const auto *cst = dyn_cast<ast::AttrConstraintDecl>(ref.constraint)) {
257511d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
257611d26bd1SRiver Riddle       if (failed(validateTypeConstraintExpr(typeExpr)))
257711d26bd1SRiver Riddle         return failure();
257811d26bd1SRiver Riddle     }
257911d26bd1SRiver Riddle     constraintType = ast::AttributeType::get(ctx);
258011d26bd1SRiver Riddle   } else if (const auto *cst =
258111d26bd1SRiver Riddle                  dyn_cast<ast::OpConstraintDecl>(ref.constraint)) {
25821c2edb02SRiver Riddle     constraintType = ast::OperationType::get(
25831c2edb02SRiver Riddle         ctx, cst->getName(), lookupODSOperation(cst->getName()));
258411d26bd1SRiver Riddle   } else if (isa<ast::TypeConstraintDecl>(ref.constraint)) {
258511d26bd1SRiver Riddle     constraintType = typeTy;
258611d26bd1SRiver Riddle   } else if (isa<ast::TypeRangeConstraintDecl>(ref.constraint)) {
258711d26bd1SRiver Riddle     constraintType = typeRangeTy;
258811d26bd1SRiver Riddle   } else if (const auto *cst =
258911d26bd1SRiver Riddle                  dyn_cast<ast::ValueConstraintDecl>(ref.constraint)) {
259011d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
259111d26bd1SRiver Riddle       if (failed(validateTypeConstraintExpr(typeExpr)))
259211d26bd1SRiver Riddle         return failure();
259311d26bd1SRiver Riddle     }
259411d26bd1SRiver Riddle     constraintType = valueTy;
259511d26bd1SRiver Riddle   } else if (const auto *cst =
259611d26bd1SRiver Riddle                  dyn_cast<ast::ValueRangeConstraintDecl>(ref.constraint)) {
259711d26bd1SRiver Riddle     if (const ast::Expr *typeExpr = cst->getTypeExpr()) {
259811d26bd1SRiver Riddle       if (failed(validateTypeRangeConstraintExpr(typeExpr)))
259911d26bd1SRiver Riddle         return failure();
260011d26bd1SRiver Riddle     }
260111d26bd1SRiver Riddle     constraintType = valueRangeTy;
2602faf42264SRiver Riddle   } else if (const auto *cst =
2603faf42264SRiver Riddle                  dyn_cast<ast::UserConstraintDecl>(ref.constraint)) {
2604faf42264SRiver Riddle     if (!allowNonCoreConstraints) {
2605faf42264SRiver Riddle       return emitError(ref.referenceLoc,
2606faf42264SRiver Riddle                        "`Rewrite` arguments and results are only permitted to "
2607faf42264SRiver Riddle                        "use core constraints, such as `Attr`, `Op`, `Type`, "
2608faf42264SRiver Riddle                        "`TypeRange`, `Value`, `ValueRange`");
2609faf42264SRiver Riddle     }
2610faf42264SRiver Riddle 
2611faf42264SRiver Riddle     ArrayRef<ast::VariableDecl *> inputs = cst->getInputs();
2612faf42264SRiver Riddle     if (inputs.size() != 1) {
2613faf42264SRiver Riddle       return emitErrorAndNote(ref.referenceLoc,
2614faf42264SRiver Riddle                               "`Constraint`s applied via a variable constraint "
2615faf42264SRiver Riddle                               "list must take a single input, but got " +
2616faf42264SRiver Riddle                                   Twine(inputs.size()),
2617faf42264SRiver Riddle                               cst->getLoc(),
2618faf42264SRiver Riddle                               "see definition of constraint here");
2619faf42264SRiver Riddle     }
2620faf42264SRiver Riddle     constraintType = inputs.front()->getType();
262111d26bd1SRiver Riddle   } else {
262211d26bd1SRiver Riddle     llvm_unreachable("unknown constraint type");
262311d26bd1SRiver Riddle   }
262411d26bd1SRiver Riddle 
262511d26bd1SRiver Riddle   // Check that the constraint type is compatible with the current inferred
262611d26bd1SRiver Riddle   // type.
262711d26bd1SRiver Riddle   if (!inferredType) {
262811d26bd1SRiver Riddle     inferredType = constraintType;
262911d26bd1SRiver Riddle   } else if (ast::Type mergedTy = inferredType.refineWith(constraintType)) {
263011d26bd1SRiver Riddle     inferredType = mergedTy;
263111d26bd1SRiver Riddle   } else {
263211d26bd1SRiver Riddle     return emitError(ref.referenceLoc,
263311d26bd1SRiver Riddle                      llvm::formatv("constraint type `{0}` is incompatible "
263411d26bd1SRiver Riddle                                    "with the previously inferred type `{1}`",
263511d26bd1SRiver Riddle                                    constraintType, inferredType));
263611d26bd1SRiver Riddle   }
263711d26bd1SRiver Riddle   return success();
263811d26bd1SRiver Riddle }
263911d26bd1SRiver Riddle 
validateTypeConstraintExpr(const ast::Expr * typeExpr)264011d26bd1SRiver Riddle LogicalResult Parser::validateTypeConstraintExpr(const ast::Expr *typeExpr) {
264111d26bd1SRiver Riddle   ast::Type typeExprType = typeExpr->getType();
264211d26bd1SRiver Riddle   if (typeExprType != typeTy) {
264311d26bd1SRiver Riddle     return emitError(typeExpr->getLoc(),
264411d26bd1SRiver Riddle                      "expected expression of `Type` in type constraint");
264511d26bd1SRiver Riddle   }
264611d26bd1SRiver Riddle   return success();
264711d26bd1SRiver Riddle }
264811d26bd1SRiver Riddle 
264911d26bd1SRiver Riddle LogicalResult
validateTypeRangeConstraintExpr(const ast::Expr * typeExpr)265011d26bd1SRiver Riddle Parser::validateTypeRangeConstraintExpr(const ast::Expr *typeExpr) {
265111d26bd1SRiver Riddle   ast::Type typeExprType = typeExpr->getType();
265211d26bd1SRiver Riddle   if (typeExprType != typeRangeTy) {
265311d26bd1SRiver Riddle     return emitError(typeExpr->getLoc(),
265411d26bd1SRiver Riddle                      "expected expression of `TypeRange` in type constraint");
265511d26bd1SRiver Riddle   }
265611d26bd1SRiver Riddle   return success();
265711d26bd1SRiver Riddle }
265811d26bd1SRiver Riddle 
265911d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
266011d26bd1SRiver Riddle // Exprs
266111d26bd1SRiver Riddle 
2662faf42264SRiver Riddle FailureOr<ast::CallExpr *>
createCallExpr(SMRange loc,ast::Expr * parentExpr,MutableArrayRef<ast::Expr * > arguments)2663faf42264SRiver Riddle Parser::createCallExpr(SMRange loc, ast::Expr *parentExpr,
2664faf42264SRiver Riddle                        MutableArrayRef<ast::Expr *> arguments) {
2665faf42264SRiver Riddle   ast::Type parentType = parentExpr->getType();
2666faf42264SRiver Riddle 
2667faf42264SRiver Riddle   ast::CallableDecl *callableDecl = tryExtractCallableDecl(parentExpr);
2668faf42264SRiver Riddle   if (!callableDecl) {
2669faf42264SRiver Riddle     return emitError(loc,
2670faf42264SRiver Riddle                      llvm::formatv("expected a reference to a callable "
2671faf42264SRiver Riddle                                    "`Constraint` or `Rewrite`, but got: `{0}`",
2672faf42264SRiver Riddle                                    parentType));
2673faf42264SRiver Riddle   }
2674faf42264SRiver Riddle   if (parserContext == ParserContext::Rewrite) {
2675faf42264SRiver Riddle     if (isa<ast::UserConstraintDecl>(callableDecl))
2676faf42264SRiver Riddle       return emitError(
2677faf42264SRiver Riddle           loc, "unable to invoke `Constraint` within a rewrite section");
2678faf42264SRiver Riddle   } else if (isa<ast::UserRewriteDecl>(callableDecl)) {
2679faf42264SRiver Riddle     return emitError(loc, "unable to invoke `Rewrite` within a match section");
2680faf42264SRiver Riddle   }
2681faf42264SRiver Riddle 
2682faf42264SRiver Riddle   // Verify the arguments of the call.
2683faf42264SRiver Riddle   /// Handle size mismatch.
2684faf42264SRiver Riddle   ArrayRef<ast::VariableDecl *> callArgs = callableDecl->getInputs();
2685faf42264SRiver Riddle   if (callArgs.size() != arguments.size()) {
2686faf42264SRiver Riddle     return emitErrorAndNote(
2687faf42264SRiver Riddle         loc,
2688faf42264SRiver Riddle         llvm::formatv("invalid number of arguments for {0} call; expected "
2689faf42264SRiver Riddle                       "{1}, but got {2}",
2690faf42264SRiver Riddle                       callableDecl->getCallableType(), callArgs.size(),
2691faf42264SRiver Riddle                       arguments.size()),
2692faf42264SRiver Riddle         callableDecl->getLoc(),
2693faf42264SRiver Riddle         llvm::formatv("see the definition of {0} here",
2694faf42264SRiver Riddle                       callableDecl->getName()->getName()));
2695faf42264SRiver Riddle   }
2696faf42264SRiver Riddle 
2697faf42264SRiver Riddle   /// Handle argument type mismatch.
2698faf42264SRiver Riddle   auto attachDiagFn = [&](ast::Diagnostic &diag) {
2699faf42264SRiver Riddle     diag.attachNote(llvm::formatv("see the definition of `{0}` here",
2700faf42264SRiver Riddle                                   callableDecl->getName()->getName()),
2701faf42264SRiver Riddle                     callableDecl->getLoc());
2702faf42264SRiver Riddle   };
2703faf42264SRiver Riddle   for (auto it : llvm::zip(callArgs, arguments)) {
2704faf42264SRiver Riddle     if (failed(convertExpressionTo(std::get<1>(it), std::get<0>(it)->getType(),
2705faf42264SRiver Riddle                                    attachDiagFn)))
2706faf42264SRiver Riddle       return failure();
2707faf42264SRiver Riddle   }
2708faf42264SRiver Riddle 
2709faf42264SRiver Riddle   return ast::CallExpr::create(ctx, loc, parentExpr, arguments,
2710faf42264SRiver Riddle                                callableDecl->getResultType());
2711faf42264SRiver Riddle }
2712faf42264SRiver Riddle 
createDeclRefExpr(SMRange loc,ast::Decl * decl)27136842ec42SRiver Riddle FailureOr<ast::DeclRefExpr *> Parser::createDeclRefExpr(SMRange loc,
271411d26bd1SRiver Riddle                                                         ast::Decl *decl) {
271511d26bd1SRiver Riddle   // Check the type of decl being referenced.
271611d26bd1SRiver Riddle   ast::Type declType;
2717faf42264SRiver Riddle   if (isa<ast::ConstraintDecl>(decl))
2718faf42264SRiver Riddle     declType = ast::ConstraintType::get(ctx);
2719faf42264SRiver Riddle   else if (isa<ast::UserRewriteDecl>(decl))
2720faf42264SRiver Riddle     declType = ast::RewriteType::get(ctx);
2721faf42264SRiver Riddle   else if (auto *varDecl = dyn_cast<ast::VariableDecl>(decl))
272211d26bd1SRiver Riddle     declType = varDecl->getType();
272311d26bd1SRiver Riddle   else
272411d26bd1SRiver Riddle     return emitError(loc, "invalid reference to `" +
272511d26bd1SRiver Riddle                               decl->getName()->getName() + "`");
272611d26bd1SRiver Riddle 
272711d26bd1SRiver Riddle   return ast::DeclRefExpr::create(ctx, loc, decl, declType);
272811d26bd1SRiver Riddle }
272911d26bd1SRiver Riddle 
273011d26bd1SRiver Riddle FailureOr<ast::DeclRefExpr *>
createInlineVariableExpr(ast::Type type,StringRef name,SMRange loc,ArrayRef<ast::ConstraintRef> constraints)2731faf42264SRiver Riddle Parser::createInlineVariableExpr(ast::Type type, StringRef name, SMRange loc,
273211d26bd1SRiver Riddle                                  ArrayRef<ast::ConstraintRef> constraints) {
273311d26bd1SRiver Riddle   FailureOr<ast::VariableDecl *> decl =
273411d26bd1SRiver Riddle       defineVariableDecl(name, loc, type, constraints);
273511d26bd1SRiver Riddle   if (failed(decl))
273611d26bd1SRiver Riddle     return failure();
273711d26bd1SRiver Riddle   return ast::DeclRefExpr::create(ctx, loc, *decl, type);
273811d26bd1SRiver Riddle }
273911d26bd1SRiver Riddle 
274011d26bd1SRiver Riddle FailureOr<ast::MemberAccessExpr *>
createMemberAccessExpr(ast::Expr * parentExpr,StringRef name,SMRange loc)274111d26bd1SRiver Riddle Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name,
27426842ec42SRiver Riddle                                SMRange loc) {
274311d26bd1SRiver Riddle   // Validate the member name for the given parent expression.
274411d26bd1SRiver Riddle   FailureOr<ast::Type> memberType = validateMemberAccess(parentExpr, name, loc);
274511d26bd1SRiver Riddle   if (failed(memberType))
274611d26bd1SRiver Riddle     return failure();
274711d26bd1SRiver Riddle 
274811d26bd1SRiver Riddle   return ast::MemberAccessExpr::create(ctx, loc, parentExpr, name, *memberType);
274911d26bd1SRiver Riddle }
275011d26bd1SRiver Riddle 
validateMemberAccess(ast::Expr * parentExpr,StringRef name,SMRange loc)275111d26bd1SRiver Riddle FailureOr<ast::Type> Parser::validateMemberAccess(ast::Expr *parentExpr,
2752faf42264SRiver Riddle                                                   StringRef name, SMRange loc) {
275311d26bd1SRiver Riddle   ast::Type parentType = parentExpr->getType();
275481f2f4dfSRiver Riddle   if (ast::OperationType opType = parentType.dyn_cast<ast::OperationType>()) {
275502670c3fSRiver Riddle     if (name == ast::AllResultsMemberAccessExpr::getMemberName())
275611d26bd1SRiver Riddle       return valueRangeTy;
275781f2f4dfSRiver Riddle 
275881f2f4dfSRiver Riddle     // Verify member access based on the operation type.
27591c2edb02SRiver Riddle     if (const ods::Operation *odsOp = opType.getODSOperation()) {
276081f2f4dfSRiver Riddle       auto results = odsOp->getResults();
276181f2f4dfSRiver Riddle 
276281f2f4dfSRiver Riddle       // Handle indexed results.
276381f2f4dfSRiver Riddle       unsigned index = 0;
276481f2f4dfSRiver Riddle       if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) &&
276581f2f4dfSRiver Riddle           index < results.size()) {
276681f2f4dfSRiver Riddle         return results[index].isVariadic() ? valueRangeTy : valueTy;
276781f2f4dfSRiver Riddle       }
276881f2f4dfSRiver Riddle 
276981f2f4dfSRiver Riddle       // Handle named results.
277081f2f4dfSRiver Riddle       const auto *it = llvm::find_if(results, [&](const auto &result) {
277181f2f4dfSRiver Riddle         return result.getName() == name;
277281f2f4dfSRiver Riddle       });
277381f2f4dfSRiver Riddle       if (it != results.end())
277481f2f4dfSRiver Riddle         return it->isVariadic() ? valueRangeTy : valueTy;
2775c088fbe7SChia-hung Duan     } else if (llvm::isDigit(name[0])) {
2776c088fbe7SChia-hung Duan       // Allow unchecked numeric indexing of the results of unregistered
2777c088fbe7SChia-hung Duan       // operations. It returns a single value.
2778c088fbe7SChia-hung Duan       return valueTy;
277981f2f4dfSRiver Riddle     }
2780f62a57a3SRiver Riddle   } else if (auto tupleType = parentType.dyn_cast<ast::TupleType>()) {
2781f62a57a3SRiver Riddle     // Handle indexed results.
2782f62a57a3SRiver Riddle     unsigned index = 0;
2783f62a57a3SRiver Riddle     if (llvm::isDigit(name[0]) && !name.getAsInteger(/*Radix=*/10, index) &&
2784f62a57a3SRiver Riddle         index < tupleType.size()) {
2785f62a57a3SRiver Riddle       return tupleType.getElementTypes()[index];
2786f62a57a3SRiver Riddle     }
2787f62a57a3SRiver Riddle 
2788f62a57a3SRiver Riddle     // Handle named results.
2789f62a57a3SRiver Riddle     auto elementNames = tupleType.getElementNames();
279002b6fb21SMehdi Amini     const auto *it = llvm::find(elementNames, name);
2791f62a57a3SRiver Riddle     if (it != elementNames.end())
2792f62a57a3SRiver Riddle       return tupleType.getElementTypes()[it - elementNames.begin()];
279311d26bd1SRiver Riddle   }
279411d26bd1SRiver Riddle   return emitError(
279511d26bd1SRiver Riddle       loc,
279611d26bd1SRiver Riddle       llvm::formatv("invalid member access `{0}` on expression of type `{1}`",
279711d26bd1SRiver Riddle                     name, parentType));
279811d26bd1SRiver Riddle }
279911d26bd1SRiver Riddle 
createOperationExpr(SMRange loc,const ast::OpNameDecl * name,OpResultTypeContext resultTypeContext,MutableArrayRef<ast::Expr * > operands,MutableArrayRef<ast::NamedAttributeDecl * > attributes,MutableArrayRef<ast::Expr * > results)280002670c3fSRiver Riddle FailureOr<ast::OperationExpr *> Parser::createOperationExpr(
28016842ec42SRiver Riddle     SMRange loc, const ast::OpNameDecl *name,
280291b8d96fSRiver Riddle     OpResultTypeContext resultTypeContext,
280302670c3fSRiver Riddle     MutableArrayRef<ast::Expr *> operands,
280402670c3fSRiver Riddle     MutableArrayRef<ast::NamedAttributeDecl *> attributes,
280502670c3fSRiver Riddle     MutableArrayRef<ast::Expr *> results) {
280602670c3fSRiver Riddle   Optional<StringRef> opNameRef = name->getName();
280781f2f4dfSRiver Riddle   const ods::Operation *odsOp = lookupODSOperation(opNameRef);
280802670c3fSRiver Riddle 
280902670c3fSRiver Riddle   // Verify the inputs operands.
281081f2f4dfSRiver Riddle   if (failed(validateOperationOperands(loc, opNameRef, odsOp, operands)))
281102670c3fSRiver Riddle     return failure();
281202670c3fSRiver Riddle 
281302670c3fSRiver Riddle   // Verify the attribute list.
281402670c3fSRiver Riddle   for (ast::NamedAttributeDecl *attr : attributes) {
281502670c3fSRiver Riddle     // Check for an attribute type, or a type awaiting resolution.
281602670c3fSRiver Riddle     ast::Type attrType = attr->getValue()->getType();
281702670c3fSRiver Riddle     if (!attrType.isa<ast::AttributeType>()) {
281802670c3fSRiver Riddle       return emitError(
281902670c3fSRiver Riddle           attr->getValue()->getLoc(),
282002670c3fSRiver Riddle           llvm::formatv("expected `Attr` expression, but got `{0}`", attrType));
282102670c3fSRiver Riddle     }
282202670c3fSRiver Riddle   }
282302670c3fSRiver Riddle 
282491b8d96fSRiver Riddle   assert(
282591b8d96fSRiver Riddle       (resultTypeContext == OpResultTypeContext::Explicit || results.empty()) &&
282691b8d96fSRiver Riddle       "unexpected inferrence when results were explicitly specified");
282791b8d96fSRiver Riddle 
282891b8d96fSRiver Riddle   // If we aren't relying on type inferrence, or explicit results were provided,
282991b8d96fSRiver Riddle   // validate them.
283091b8d96fSRiver Riddle   if (resultTypeContext == OpResultTypeContext::Explicit) {
283181f2f4dfSRiver Riddle     if (failed(validateOperationResults(loc, opNameRef, odsOp, results)))
283202670c3fSRiver Riddle       return failure();
283302670c3fSRiver Riddle 
283491b8d96fSRiver Riddle     // Validate the use of interface based type inferrence for this operation.
283591b8d96fSRiver Riddle   } else if (resultTypeContext == OpResultTypeContext::Interface) {
283691b8d96fSRiver Riddle     assert(opNameRef &&
283791b8d96fSRiver Riddle            "expected valid operation name when inferring operation results");
283891b8d96fSRiver Riddle     checkOperationResultTypeInferrence(loc, *opNameRef, odsOp);
283991b8d96fSRiver Riddle   }
284091b8d96fSRiver Riddle 
28411c2edb02SRiver Riddle   return ast::OperationExpr::create(ctx, loc, odsOp, name, operands, results,
284202670c3fSRiver Riddle                                     attributes);
284302670c3fSRiver Riddle }
284402670c3fSRiver Riddle 
284502670c3fSRiver Riddle LogicalResult
validateOperationOperands(SMRange loc,Optional<StringRef> name,const ods::Operation * odsOp,MutableArrayRef<ast::Expr * > operands)28466842ec42SRiver Riddle Parser::validateOperationOperands(SMRange loc, Optional<StringRef> name,
284781f2f4dfSRiver Riddle                                   const ods::Operation *odsOp,
284802670c3fSRiver Riddle                                   MutableArrayRef<ast::Expr *> operands) {
284981f2f4dfSRiver Riddle   return validateOperationOperandsOrResults(
285081f2f4dfSRiver Riddle       "operand", loc, odsOp ? odsOp->getLoc() : Optional<SMRange>(), name,
285181f2f4dfSRiver Riddle       operands, odsOp ? odsOp->getOperands() : llvm::None, valueTy,
285202670c3fSRiver Riddle       valueRangeTy);
285302670c3fSRiver Riddle }
285402670c3fSRiver Riddle 
285502670c3fSRiver Riddle LogicalResult
validateOperationResults(SMRange loc,Optional<StringRef> name,const ods::Operation * odsOp,MutableArrayRef<ast::Expr * > results)28566842ec42SRiver Riddle Parser::validateOperationResults(SMRange loc, Optional<StringRef> name,
285781f2f4dfSRiver Riddle                                  const ods::Operation *odsOp,
285802670c3fSRiver Riddle                                  MutableArrayRef<ast::Expr *> results) {
285981f2f4dfSRiver Riddle   return validateOperationOperandsOrResults(
286081f2f4dfSRiver Riddle       "result", loc, odsOp ? odsOp->getLoc() : Optional<SMRange>(), name,
286181f2f4dfSRiver Riddle       results, odsOp ? odsOp->getResults() : llvm::None, typeTy, typeRangeTy);
286202670c3fSRiver Riddle }
286302670c3fSRiver Riddle 
checkOperationResultTypeInferrence(SMRange loc,StringRef opName,const ods::Operation * odsOp)286491b8d96fSRiver Riddle void Parser::checkOperationResultTypeInferrence(SMRange loc, StringRef opName,
286591b8d96fSRiver Riddle                                                 const ods::Operation *odsOp) {
286691b8d96fSRiver Riddle   // If the operation might not have inferrence support, emit a warning to the
286791b8d96fSRiver Riddle   // user. We don't emit an error because the interface might be added to the
286891b8d96fSRiver Riddle   // operation at runtime. It's rare, but it could still happen. We emit a
286991b8d96fSRiver Riddle   // warning here instead.
287091b8d96fSRiver Riddle 
287191b8d96fSRiver Riddle   // Handle inferrence warnings for unknown operations.
287291b8d96fSRiver Riddle   if (!odsOp) {
287391b8d96fSRiver Riddle     ctx.getDiagEngine().emitWarning(
287491b8d96fSRiver Riddle         loc, llvm::formatv(
287591b8d96fSRiver Riddle                  "operation result types are marked to be inferred, but "
287691b8d96fSRiver Riddle                  "`{0}` is unknown. Ensure that `{0}` supports zero "
287791b8d96fSRiver Riddle                  "results or implements `InferTypeOpInterface`. Include "
287891b8d96fSRiver Riddle                  "the ODS definition of this operation to remove this warning.",
287991b8d96fSRiver Riddle                  opName));
288091b8d96fSRiver Riddle     return;
288191b8d96fSRiver Riddle   }
288291b8d96fSRiver Riddle 
288391b8d96fSRiver Riddle   // Handle inferrence warnings for known operations that expected at least one
288491b8d96fSRiver Riddle   // result, but don't have inference support. An elided results list can mean
288591b8d96fSRiver Riddle   // "zero-results", and we don't want to warn when that is the expected
288691b8d96fSRiver Riddle   // behavior.
288791b8d96fSRiver Riddle   bool requiresInferrence =
288891b8d96fSRiver Riddle       llvm::any_of(odsOp->getResults(), [](const ods::OperandOrResult &result) {
288991b8d96fSRiver Riddle         return !result.isVariableLength();
289091b8d96fSRiver Riddle       });
289191b8d96fSRiver Riddle   if (requiresInferrence && !odsOp->hasResultTypeInferrence()) {
289291b8d96fSRiver Riddle     ast::InFlightDiagnostic diag = ctx.getDiagEngine().emitWarning(
289391b8d96fSRiver Riddle         loc,
289491b8d96fSRiver Riddle         llvm::formatv("operation result types are marked to be inferred, but "
289591b8d96fSRiver Riddle                       "`{0}` does not provide an implementation of "
289691b8d96fSRiver Riddle                       "`InferTypeOpInterface`. Ensure that `{0}` attaches "
289791b8d96fSRiver Riddle                       "`InferTypeOpInterface` at runtime, or add support to "
289891b8d96fSRiver Riddle                       "the ODS definition to remove this warning.",
289991b8d96fSRiver Riddle                       opName));
290091b8d96fSRiver Riddle     diag->attachNote(llvm::formatv("see the definition of `{0}` here", opName),
290191b8d96fSRiver Riddle                      odsOp->getLoc());
290291b8d96fSRiver Riddle     return;
290391b8d96fSRiver Riddle   }
290491b8d96fSRiver Riddle }
290591b8d96fSRiver Riddle 
validateOperationOperandsOrResults(StringRef groupName,SMRange loc,Optional<SMRange> odsOpLoc,Optional<StringRef> name,MutableArrayRef<ast::Expr * > values,ArrayRef<ods::OperandOrResult> odsValues,ast::Type singleTy,ast::Type rangeTy)290602670c3fSRiver Riddle LogicalResult Parser::validateOperationOperandsOrResults(
290781f2f4dfSRiver Riddle     StringRef groupName, SMRange loc, Optional<SMRange> odsOpLoc,
290881f2f4dfSRiver Riddle     Optional<StringRef> name, MutableArrayRef<ast::Expr *> values,
290981f2f4dfSRiver Riddle     ArrayRef<ods::OperandOrResult> odsValues, ast::Type singleTy,
291081f2f4dfSRiver Riddle     ast::Type rangeTy) {
291102670c3fSRiver Riddle   // All operation types accept a single range parameter.
291202670c3fSRiver Riddle   if (values.size() == 1) {
291302670c3fSRiver Riddle     if (failed(convertExpressionTo(values[0], rangeTy)))
291402670c3fSRiver Riddle       return failure();
291502670c3fSRiver Riddle     return success();
291602670c3fSRiver Riddle   }
291702670c3fSRiver Riddle 
291881f2f4dfSRiver Riddle   /// If the operation has ODS information, we can more accurately verify the
291981f2f4dfSRiver Riddle   /// values.
292081f2f4dfSRiver Riddle   if (odsOpLoc) {
292181f2f4dfSRiver Riddle     if (odsValues.size() != values.size()) {
292281f2f4dfSRiver Riddle       return emitErrorAndNote(
292381f2f4dfSRiver Riddle           loc,
292481f2f4dfSRiver Riddle           llvm::formatv("invalid number of {0} groups for `{1}`; expected "
292581f2f4dfSRiver Riddle                         "{2}, but got {3}",
292681f2f4dfSRiver Riddle                         groupName, *name, odsValues.size(), values.size()),
292781f2f4dfSRiver Riddle           *odsOpLoc, llvm::formatv("see the definition of `{0}` here", *name));
292881f2f4dfSRiver Riddle     }
292981f2f4dfSRiver Riddle     auto diagFn = [&](ast::Diagnostic &diag) {
293081f2f4dfSRiver Riddle       diag.attachNote(llvm::formatv("see the definition of `{0}` here", *name),
293181f2f4dfSRiver Riddle                       *odsOpLoc);
293281f2f4dfSRiver Riddle     };
293381f2f4dfSRiver Riddle     for (unsigned i = 0, e = values.size(); i < e; ++i) {
293481f2f4dfSRiver Riddle       ast::Type expectedType = odsValues[i].isVariadic() ? rangeTy : singleTy;
293581f2f4dfSRiver Riddle       if (failed(convertExpressionTo(values[i], expectedType, diagFn)))
293681f2f4dfSRiver Riddle         return failure();
293781f2f4dfSRiver Riddle     }
293881f2f4dfSRiver Riddle     return success();
293981f2f4dfSRiver Riddle   }
294081f2f4dfSRiver Riddle 
294102670c3fSRiver Riddle   // Otherwise, accept the value groups as they have been defined and just
294202670c3fSRiver Riddle   // ensure they are one of the expected types.
294302670c3fSRiver Riddle   for (ast::Expr *&valueExpr : values) {
294402670c3fSRiver Riddle     ast::Type valueExprType = valueExpr->getType();
294502670c3fSRiver Riddle 
294602670c3fSRiver Riddle     // Check if this is one of the expected types.
294702670c3fSRiver Riddle     if (valueExprType == rangeTy || valueExprType == singleTy)
294802670c3fSRiver Riddle       continue;
294902670c3fSRiver Riddle 
295002670c3fSRiver Riddle     // If the operand is an Operation, allow converting to a Value or
295102670c3fSRiver Riddle     // ValueRange. This situations arises quite often with nested operation
295202670c3fSRiver Riddle     // expressions: `op<my_dialect.foo>(op<my_dialect.bar>)`
295302670c3fSRiver Riddle     if (singleTy == valueTy) {
295402670c3fSRiver Riddle       if (valueExprType.isa<ast::OperationType>()) {
295502670c3fSRiver Riddle         valueExpr = convertOpToValue(valueExpr);
295602670c3fSRiver Riddle         continue;
295702670c3fSRiver Riddle       }
295802670c3fSRiver Riddle     }
295902670c3fSRiver Riddle 
296002670c3fSRiver Riddle     return emitError(
296102670c3fSRiver Riddle         valueExpr->getLoc(),
296202670c3fSRiver Riddle         llvm::formatv(
296302670c3fSRiver Riddle             "expected `{0}` or `{1}` convertible expression, but got `{2}`",
296402670c3fSRiver Riddle             singleTy, rangeTy, valueExprType));
296502670c3fSRiver Riddle   }
296602670c3fSRiver Riddle   return success();
296702670c3fSRiver Riddle }
296802670c3fSRiver Riddle 
2969f62a57a3SRiver Riddle FailureOr<ast::TupleExpr *>
createTupleExpr(SMRange loc,ArrayRef<ast::Expr * > elements,ArrayRef<StringRef> elementNames)29706842ec42SRiver Riddle Parser::createTupleExpr(SMRange loc, ArrayRef<ast::Expr *> elements,
2971f62a57a3SRiver Riddle                         ArrayRef<StringRef> elementNames) {
2972f62a57a3SRiver Riddle   for (const ast::Expr *element : elements) {
2973f62a57a3SRiver Riddle     ast::Type eleTy = element->getType();
2974faf42264SRiver Riddle     if (eleTy.isa<ast::ConstraintType, ast::RewriteType, ast::TupleType>()) {
2975f62a57a3SRiver Riddle       return emitError(
2976f62a57a3SRiver Riddle           element->getLoc(),
2977f62a57a3SRiver Riddle           llvm::formatv("unable to build a tuple with `{0}` element", eleTy));
2978f62a57a3SRiver Riddle     }
2979f62a57a3SRiver Riddle   }
2980f62a57a3SRiver Riddle   return ast::TupleExpr::create(ctx, loc, elements, elementNames);
2981f62a57a3SRiver Riddle }
2982f62a57a3SRiver Riddle 
298311d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
298411d26bd1SRiver Riddle // Stmts
298511d26bd1SRiver Riddle 
createEraseStmt(SMRange loc,ast::Expr * rootOp)29866842ec42SRiver Riddle FailureOr<ast::EraseStmt *> Parser::createEraseStmt(SMRange loc,
298711d26bd1SRiver Riddle                                                     ast::Expr *rootOp) {
298811d26bd1SRiver Riddle   // Check that root is an Operation.
298911d26bd1SRiver Riddle   ast::Type rootType = rootOp->getType();
299011d26bd1SRiver Riddle   if (!rootType.isa<ast::OperationType>())
299111d26bd1SRiver Riddle     return emitError(rootOp->getLoc(), "expected `Op` expression");
299211d26bd1SRiver Riddle 
299311d26bd1SRiver Riddle   return ast::EraseStmt::create(ctx, loc, rootOp);
299411d26bd1SRiver Riddle }
299511d26bd1SRiver Riddle 
299612eebb8eSRiver Riddle FailureOr<ast::ReplaceStmt *>
createReplaceStmt(SMRange loc,ast::Expr * rootOp,MutableArrayRef<ast::Expr * > replValues)29976842ec42SRiver Riddle Parser::createReplaceStmt(SMRange loc, ast::Expr *rootOp,
299812eebb8eSRiver Riddle                           MutableArrayRef<ast::Expr *> replValues) {
299912eebb8eSRiver Riddle   // Check that root is an Operation.
300012eebb8eSRiver Riddle   ast::Type rootType = rootOp->getType();
300112eebb8eSRiver Riddle   if (!rootType.isa<ast::OperationType>()) {
300212eebb8eSRiver Riddle     return emitError(
300312eebb8eSRiver Riddle         rootOp->getLoc(),
300412eebb8eSRiver Riddle         llvm::formatv("expected `Op` expression, but got `{0}`", rootType));
300512eebb8eSRiver Riddle   }
300612eebb8eSRiver Riddle 
300712eebb8eSRiver Riddle   // If there are multiple replacement values, we implicitly convert any Op
300812eebb8eSRiver Riddle   // expressions to the value form.
300912eebb8eSRiver Riddle   bool shouldConvertOpToValues = replValues.size() > 1;
301012eebb8eSRiver Riddle   for (ast::Expr *&replExpr : replValues) {
301112eebb8eSRiver Riddle     ast::Type replType = replExpr->getType();
301212eebb8eSRiver Riddle 
301312eebb8eSRiver Riddle     // Check that replExpr is an Operation, Value, or ValueRange.
301412eebb8eSRiver Riddle     if (replType.isa<ast::OperationType>()) {
301512eebb8eSRiver Riddle       if (shouldConvertOpToValues)
301612eebb8eSRiver Riddle         replExpr = convertOpToValue(replExpr);
301712eebb8eSRiver Riddle       continue;
301812eebb8eSRiver Riddle     }
301912eebb8eSRiver Riddle 
302012eebb8eSRiver Riddle     if (replType != valueTy && replType != valueRangeTy) {
302112eebb8eSRiver Riddle       return emitError(replExpr->getLoc(),
302212eebb8eSRiver Riddle                        llvm::formatv("expected `Op`, `Value` or `ValueRange` "
302312eebb8eSRiver Riddle                                      "expression, but got `{0}`",
302412eebb8eSRiver Riddle                                      replType));
302512eebb8eSRiver Riddle     }
302612eebb8eSRiver Riddle   }
302712eebb8eSRiver Riddle 
302812eebb8eSRiver Riddle   return ast::ReplaceStmt::create(ctx, loc, rootOp, replValues);
302912eebb8eSRiver Riddle }
303012eebb8eSRiver Riddle 
30313ee44cb7SRiver Riddle FailureOr<ast::RewriteStmt *>
createRewriteStmt(SMRange loc,ast::Expr * rootOp,ast::CompoundStmt * rewriteBody)30326842ec42SRiver Riddle Parser::createRewriteStmt(SMRange loc, ast::Expr *rootOp,
30333ee44cb7SRiver Riddle                           ast::CompoundStmt *rewriteBody) {
30343ee44cb7SRiver Riddle   // Check that root is an Operation.
30353ee44cb7SRiver Riddle   ast::Type rootType = rootOp->getType();
30363ee44cb7SRiver Riddle   if (!rootType.isa<ast::OperationType>()) {
30373ee44cb7SRiver Riddle     return emitError(
30383ee44cb7SRiver Riddle         rootOp->getLoc(),
30393ee44cb7SRiver Riddle         llvm::formatv("expected `Op` expression, but got `{0}`", rootType));
30403ee44cb7SRiver Riddle   }
30413ee44cb7SRiver Riddle 
30423ee44cb7SRiver Riddle   return ast::RewriteStmt::create(ctx, loc, rootOp, rewriteBody);
30433ee44cb7SRiver Riddle }
30443ee44cb7SRiver Riddle 
304511d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
3046008de486SRiver Riddle // Code Completion
3047008de486SRiver Riddle //===----------------------------------------------------------------------===//
3048008de486SRiver Riddle 
codeCompleteMemberAccess(ast::Expr * parentExpr)3049008de486SRiver Riddle LogicalResult Parser::codeCompleteMemberAccess(ast::Expr *parentExpr) {
3050008de486SRiver Riddle   ast::Type parentType = parentExpr->getType();
3051008de486SRiver Riddle   if (ast::OperationType opType = parentType.dyn_cast<ast::OperationType>())
3052008de486SRiver Riddle     codeCompleteContext->codeCompleteOperationMemberAccess(opType);
3053008de486SRiver Riddle   else if (ast::TupleType tupleType = parentType.dyn_cast<ast::TupleType>())
3054008de486SRiver Riddle     codeCompleteContext->codeCompleteTupleMemberAccess(tupleType);
3055008de486SRiver Riddle   return failure();
3056008de486SRiver Riddle }
3057008de486SRiver Riddle 
codeCompleteAttributeName(Optional<StringRef> opName)3058008de486SRiver Riddle LogicalResult Parser::codeCompleteAttributeName(Optional<StringRef> opName) {
3059008de486SRiver Riddle   if (opName)
3060008de486SRiver Riddle     codeCompleteContext->codeCompleteOperationAttributeName(*opName);
3061008de486SRiver Riddle   return failure();
3062008de486SRiver Riddle }
3063008de486SRiver Riddle 
3064008de486SRiver Riddle LogicalResult
codeCompleteConstraintName(ast::Type inferredType,bool allowNonCoreConstraints,bool allowInlineTypeConstraints)3065008de486SRiver Riddle Parser::codeCompleteConstraintName(ast::Type inferredType,
3066008de486SRiver Riddle                                    bool allowNonCoreConstraints,
3067008de486SRiver Riddle                                    bool allowInlineTypeConstraints) {
3068008de486SRiver Riddle   codeCompleteContext->codeCompleteConstraintName(
3069008de486SRiver Riddle       inferredType, allowNonCoreConstraints, allowInlineTypeConstraints,
3070008de486SRiver Riddle       curDeclScope);
3071008de486SRiver Riddle   return failure();
3072008de486SRiver Riddle }
3073008de486SRiver Riddle 
codeCompleteDialectName()3074008de486SRiver Riddle LogicalResult Parser::codeCompleteDialectName() {
3075008de486SRiver Riddle   codeCompleteContext->codeCompleteDialectName();
3076008de486SRiver Riddle   return failure();
3077008de486SRiver Riddle }
3078008de486SRiver Riddle 
codeCompleteOperationName(StringRef dialectName)3079008de486SRiver Riddle LogicalResult Parser::codeCompleteOperationName(StringRef dialectName) {
3080008de486SRiver Riddle   codeCompleteContext->codeCompleteOperationName(dialectName);
3081008de486SRiver Riddle   return failure();
3082008de486SRiver Riddle }
3083008de486SRiver Riddle 
codeCompletePatternMetadata()3084008de486SRiver Riddle LogicalResult Parser::codeCompletePatternMetadata() {
3085008de486SRiver Riddle   codeCompleteContext->codeCompletePatternMetadata();
3086008de486SRiver Riddle   return failure();
3087008de486SRiver Riddle }
3088008de486SRiver Riddle 
codeCompleteIncludeFilename(StringRef curPath)308941d2c6dfSRiver Riddle LogicalResult Parser::codeCompleteIncludeFilename(StringRef curPath) {
309041d2c6dfSRiver Riddle   codeCompleteContext->codeCompleteIncludeFilename(curPath);
309141d2c6dfSRiver Riddle   return failure();
309241d2c6dfSRiver Riddle }
309341d2c6dfSRiver Riddle 
codeCompleteCallSignature(ast::Node * parent,unsigned currentNumArgs)3094469c5894SRiver Riddle void Parser::codeCompleteCallSignature(ast::Node *parent,
3095469c5894SRiver Riddle                                        unsigned currentNumArgs) {
3096469c5894SRiver Riddle   ast::CallableDecl *callableDecl = tryExtractCallableDecl(parent);
3097469c5894SRiver Riddle   if (!callableDecl)
3098469c5894SRiver Riddle     return;
3099469c5894SRiver Riddle 
3100469c5894SRiver Riddle   codeCompleteContext->codeCompleteCallSignature(callableDecl, currentNumArgs);
3101469c5894SRiver Riddle }
3102469c5894SRiver Riddle 
codeCompleteOperationOperandsSignature(Optional<StringRef> opName,unsigned currentNumOperands)3103469c5894SRiver Riddle void Parser::codeCompleteOperationOperandsSignature(
3104469c5894SRiver Riddle     Optional<StringRef> opName, unsigned currentNumOperands) {
3105469c5894SRiver Riddle   codeCompleteContext->codeCompleteOperationOperandsSignature(
3106469c5894SRiver Riddle       opName, currentNumOperands);
3107469c5894SRiver Riddle }
3108469c5894SRiver Riddle 
codeCompleteOperationResultsSignature(Optional<StringRef> opName,unsigned currentNumResults)3109469c5894SRiver Riddle void Parser::codeCompleteOperationResultsSignature(Optional<StringRef> opName,
3110469c5894SRiver Riddle                                                    unsigned currentNumResults) {
3111469c5894SRiver Riddle   codeCompleteContext->codeCompleteOperationResultsSignature(opName,
3112469c5894SRiver Riddle                                                              currentNumResults);
3113469c5894SRiver Riddle }
3114469c5894SRiver Riddle 
3115008de486SRiver Riddle //===----------------------------------------------------------------------===//
311611d26bd1SRiver Riddle // Parser
311711d26bd1SRiver Riddle //===----------------------------------------------------------------------===//
311811d26bd1SRiver Riddle 
3119008de486SRiver Riddle FailureOr<ast::Module *>
parsePDLLAST(ast::Context & ctx,llvm::SourceMgr & sourceMgr,bool enableDocumentation,CodeCompleteContext * codeCompleteContext)3120bf352e0bSRiver Riddle mlir::pdll::parsePDLLAST(ast::Context &ctx, llvm::SourceMgr &sourceMgr,
3121bf352e0bSRiver Riddle                          bool enableDocumentation,
3122008de486SRiver Riddle                          CodeCompleteContext *codeCompleteContext) {
3123bf352e0bSRiver Riddle   Parser parser(ctx, sourceMgr, enableDocumentation, codeCompleteContext);
312411d26bd1SRiver Riddle   return parser.parseModule();
312511d26bd1SRiver Riddle }
3126