@@ -314,9 +314,11 @@ class Parser {
314
314
FailureOr<ast::Expr *> parseExpr ();
315
315
316
316
// / Identifier expressions.
317
+ FailureOr<ast::Expr *> parseArrayAttrExpr ();
317
318
FailureOr<ast::Expr *> parseAttributeExpr ();
318
319
FailureOr<ast::Expr *> parseCallExpr (ast::Expr *parentExpr);
319
320
FailureOr<ast::Expr *> parseDeclRefExpr (StringRef name, SMRange loc);
321
+ FailureOr<ast::Expr *> parseDictAttrExpr ();
320
322
FailureOr<ast::Expr *> parseIdentifierExpr ();
321
323
FailureOr<ast::Expr *> parseInlineConstraintLambdaExpr ();
322
324
FailureOr<ast::Expr *> parseInlineRewriteLambdaExpr ();
@@ -329,7 +331,6 @@ class Parser {
329
331
FailureOr<ast::Expr *> parseTupleExpr ();
330
332
FailureOr<ast::Expr *> parseTypeExpr ();
331
333
FailureOr<ast::Expr *> parseUnderscoreExpr ();
332
-
333
334
// ===--------------------------------------------------------------------===//
334
335
// Stmts
335
336
@@ -413,6 +414,13 @@ class Parser {
413
414
FailureOr<ast::MemberAccessExpr *>
414
415
createMemberAccessExpr (ast::Expr *parentExpr, StringRef name, SMRange loc);
415
416
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
+
416
424
// / Validate the member access `name` into the given parent expression. On
417
425
// / success, this also returns the type of the member accessed.
418
426
FailureOr<ast::Type> validateMemberAccess (ast::Expr *parentExpr,
@@ -1815,6 +1823,15 @@ FailureOr<ast::Expr *> Parser::parseExpr() {
1815
1823
case Token::l_paren:
1816
1824
lhsExpr = parseTupleExpr ();
1817
1825
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 `{`." );
1818
1835
default :
1819
1836
return emitError (" expected expression" );
1820
1837
}
@@ -1838,6 +1855,40 @@ FailureOr<ast::Expr *> Parser::parseExpr() {
1838
1855
}
1839
1856
}
1840
1857
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
+
1841
1892
FailureOr<ast::Expr *> Parser::parseAttributeExpr () {
1842
1893
SMRange loc = curToken.getLoc ();
1843
1894
consumeToken (Token::kw_attr);
@@ -1896,6 +1947,62 @@ FailureOr<ast::Expr *> Parser::parseDeclRefExpr(StringRef name, SMRange loc) {
1896
1947
return createDeclRefExpr (loc, decl);
1897
1948
}
1898
1949
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
+
1899
2006
FailureOr<ast::Expr *> Parser::parseIdentifierExpr () {
1900
2007
StringRef name = curToken.getSpelling ();
1901
2008
SMRange nameLoc = curToken.getLoc ();
@@ -2769,6 +2876,35 @@ Parser::createMemberAccessExpr(ast::Expr *parentExpr, StringRef name,
2769
2876
return ast::MemberAccessExpr::create (ctx, loc, parentExpr, name, *memberType);
2770
2877
}
2771
2878
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
+
2772
2908
FailureOr<ast::Type> Parser::validateMemberAccess (ast::Expr *parentExpr,
2773
2909
StringRef name, SMRange loc) {
2774
2910
ast::Type parentType = parentExpr->getType ();
0 commit comments