@@ -314,9 +314,11 @@ class Parser {
314314 FailureOr<ast::Expr *> parseExpr ();
315315
316316 // / Identifier expressions.
317+ FailureOr<ast::Expr *> parseArrayAttrExpr ();
317318 FailureOr<ast::Expr *> parseAttributeExpr ();
318319 FailureOr<ast::Expr *> parseCallExpr (ast::Expr *parentExpr);
319320 FailureOr<ast::Expr *> parseDeclRefExpr (StringRef name, SMRange loc);
321+ FailureOr<ast::Expr *> parseDictAttrExpr ();
320322 FailureOr<ast::Expr *> parseIdentifierExpr ();
321323 FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr ();
322324 FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr ();
@@ -329,7 +331,6 @@ class Parser {
329331 FailureOr<ast::Expr *> parseTupleExpr ();
330332 FailureOr<ast::Expr *> parseTypeExpr ();
331333 FailureOr<ast::Expr *> parseUnderscoreExpr ();
332-
333334 // ===--------------------------------------------------------------------===//
334335 // Stmts
335336
@@ -413,6 +414,13 @@ class Parser {
413414 FailureOr<ast::MemberAccessExpr *>
414415 createMemberAccessExpr (ast::Expr *parentExpr, StringRef name, SMRange loc);
415416
417+ // Create a native call with \p nativeFuncName and \p arguments.
418+ // This should be accompanied by a C++ implementation of the function that
419+ // needs to be linked and registered in passes that process PDLL files.
420+ FailureOr<ast::DeclRefExpr *>
421+ createNativeCall (SMRange loc, StringRef nativeFuncName,
422+ MutableArrayRef<ast::Expr *> arguments);
423+
416424 // / Validate the member access `name` into the given parent expression. On
417425 // / success, this also returns the type of the member accessed.
418426 FailureOr<ast::Type> validateMemberAccess (ast::Expr *parentExpr,
@@ -1815,6 +1823,15 @@ FailureOr<ast::Expr *> Parser::parseExpr() {
18151823 case Token::l_paren:
18161824 lhsExpr = parseTupleExpr ();
18171825 break ;
1826+ case Token::l_brace:
1827+ lhsExpr = parseDictAttrExpr ();
1828+ break ;
1829+ case Token::l_square:
1830+ lhsExpr = parseArrayAttrExpr ();
1831+ break ;
1832+ case Token::string_block:
1833+ return emitError (" expected expression. If you are trying to create an "
1834+ " ArrayAttr, use a space between `[` and `{`." );
18181835 default :
18191836 return emitError (" expected expression" );
18201837 }
@@ -1838,6 +1855,40 @@ FailureOr<ast::Expr *> Parser::parseExpr() {
18381855 }
18391856}
18401857
1858+ FailureOr<ast::Expr *> Parser::parseArrayAttrExpr () {
1859+
1860+ consumeToken (Token::l_square);
1861+
1862+ if (parserContext != ParserContext::Rewrite)
1863+ return emitError (
1864+ " Parsing of array attributes as constraint not supported!" );
1865+
1866+ auto arrayAttrCall =
1867+ createNativeCall (curToken.getLoc (), " createArrayAttr" , {});
1868+ if (failed (arrayAttrCall))
1869+ return failure ();
1870+
1871+ do {
1872+ FailureOr<ast::Expr *> attr = parseExpr ();
1873+ if (failed (attr))
1874+ return failure ();
1875+
1876+ SmallVector<ast::Expr *> arrayAttrArgs{*arrayAttrCall, *attr};
1877+ auto elemToArrayCall = createNativeCall (
1878+ curToken.getLoc (), " addElemToArrayAttr" , arrayAttrArgs);
1879+ if (failed (elemToArrayCall))
1880+ return failure ();
1881+
1882+ // Uses the new array for the next element.
1883+ arrayAttrCall = elemToArrayCall;
1884+ } while (consumeIf (Token::comma));
1885+
1886+ if (failed (
1887+ parseToken (Token::r_square, " expected `]` to close array attribute" )))
1888+ return failure ();
1889+ return arrayAttrCall;
1890+ }
1891+
18411892FailureOr<ast::Expr *> Parser::parseAttributeExpr () {
18421893 SMRange loc = curToken.getLoc ();
18431894 consumeToken (Token::kw_attr);
@@ -1896,6 +1947,62 @@ FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
18961947 return createDeclRefExpr (loc, decl);
18971948}
18981949
1950+ FailureOr<ast::Expr *> Parser::parseDictAttrExpr () {
1951+ consumeToken (Token::l_brace);
1952+ SMRange loc = curToken.getLoc ();
1953+
1954+ if (parserContext != ParserContext::Rewrite)
1955+ return emitError (
1956+ " Parsing of dictionary attributes as constraint not supported!" );
1957+
1958+ auto dictAttrCall = createNativeCall (loc, " createDictionaryAttr" , {});
1959+ if (failed (dictAttrCall))
1960+ return failure ();
1961+
1962+ // Add each nested attribute to the dict
1963+ do {
1964+ FailureOr<ast::NamedAttributeDecl *> decl =
1965+ parseNamedAttributeDecl (std::nullopt );
1966+ if (failed (decl))
1967+ return failure ();
1968+
1969+ ast::NamedAttributeDecl *namedDecl = *decl;
1970+
1971+ std::string stringAttrValue =
1972+ " \" " + std::string ((*namedDecl).getName ().getName ()) + " \" " ;
1973+ auto *stringAttr = ast::AttributeExpr::create (ctx, loc, stringAttrValue);
1974+
1975+ // Declare it as a variable
1976+ std::string anonName =
1977+ llvm::formatv (" dict{0}" , anonymousDeclNameCounter++).str ();
1978+ FailureOr<ast::VariableDecl *> stringAttrDecl =
1979+ createVariableDecl (anonName, namedDecl->getLoc (), stringAttr, {});
1980+ if (failed (stringAttrDecl))
1981+ return failure ();
1982+
1983+ // Get its reference
1984+ auto stringAttrRef = parseDeclRefExpr (
1985+ (*stringAttrDecl)->getName ().getName (), namedDecl->getLoc ());
1986+ if (failed (stringAttrRef))
1987+ return failure ();
1988+
1989+ // Create addEntryToDictionaryAttr native call.
1990+ SmallVector<ast::Expr *> arrayAttrArgs{*dictAttrCall, *stringAttrRef,
1991+ namedDecl->getValue ()};
1992+ auto entryToDictionaryCall =
1993+ createNativeCall (loc, " addEntryToDictionaryAttr" , arrayAttrArgs);
1994+ if (failed (entryToDictionaryCall))
1995+ return failure ();
1996+
1997+ // Uses the new array for the next element.
1998+ dictAttrCall = entryToDictionaryCall;
1999+ } while (consumeIf (Token::comma));
2000+ if (failed (parseToken (Token::r_brace,
2001+ " expected `}` to close dictionary attribute" )))
2002+ return failure ();
2003+ return dictAttrCall;
2004+ }
2005+
18992006FailureOr<ast::Expr *> Parser::parseIdentifierExpr () {
19002007 StringRef name = curToken.getSpelling ();
19012008 SMRange nameLoc = curToken.getLoc ();
@@ -2769,6 +2876,35 @@ Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name,
27692876 return ast::MemberAccessExpr::create (ctx, loc, parentExpr, name, *memberType);
27702877}
27712878
2879+ FailureOr<ast::DeclRefExpr *>
2880+ Parser::createNativeCall (SMRange loc, StringRef nativeFuncName,
2881+ MutableArrayRef<ast::Expr *> arguments) {
2882+
2883+ FailureOr<ast::Expr *> nativeFuncExpr = parseDeclRefExpr (nativeFuncName, loc);
2884+ if (failed (nativeFuncExpr))
2885+ return failure ();
2886+
2887+ if (!(*nativeFuncExpr)->getType ().isa <ast::RewriteType>())
2888+ return emitError (nativeFuncName + " should be defined as a rewriter." );
2889+
2890+ FailureOr<ast::CallExpr *> nativeCall =
2891+ createCallExpr (loc, *nativeFuncExpr, arguments);
2892+ if (failed (nativeCall))
2893+ return failure ();
2894+
2895+ // Create a unique anonymous name declaration to use, as its name is not
2896+ // important.
2897+ std::string anonName =
2898+ llvm::formatv (" {0}_{1}" , nativeFuncName, anonymousDeclNameCounter++)
2899+ .str ();
2900+ FailureOr<ast::VariableDecl *> varDecl = defineVariableDecl (
2901+ anonName, loc, (*nativeCall)->getType (), *nativeCall, {});
2902+ if (failed (varDecl))
2903+ return failure ();
2904+
2905+ return createDeclRefExpr (loc, *varDecl);
2906+ }
2907+
27722908FailureOr<ast::Type> Parser::validateMemberAccess (ast::Expr *parentExpr,
27732909 StringRef name, SMRange loc) {
27742910 ast::Type parentType = parentExpr->getType ();
0 commit comments