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 ¬e) {
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