Skip to content

Commit 1ad7dac

Browse files
committed
Move builtin type parsing from parser to assembly formats
1 parent 9bad920 commit 1ad7dac

13 files changed

Lines changed: 579 additions & 565 deletions

src/MLIR/Dialects/Builtin/BuiltinFunctionTypeAssemblyFormat.cs

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace MLIR.Dialects.Builtin;
1313
/// Binds and rebuilds the builtin <c>function</c> type, e.g. <c>(i32, f32) -> i64</c>.
1414
/// </summary>
1515
/// <remarks>
16-
/// Parsing is handled by the core type parser; this format only provides binding and CST rebuild.
1716
/// <c>BuildCustomAssemblySyntax</c> uses the builder context to recursively synthesize syntax for
1817
/// nested input and result types so that syntaxless child types are supported.
1918
/// </remarks>
@@ -22,8 +21,47 @@ public sealed class BuiltinFunctionTypeAssemblyFormat : ITypeAssemblyFormat
2221
/// <inheritdoc/>
2322
public ParseResult<TypeSyntax> TryParse(TypeParsingContext context)
2423
{
25-
// Parsing is handled by the core type parser, not by dialect custom syntax.
26-
return ParseResult<TypeSyntax>.NoMatch();
24+
if (!context.Is(TokenKind.LParen))
25+
{
26+
return ParseResult<TypeSyntax>.NoMatch();
27+
}
28+
29+
var inputsResult = TryParseTypeList(context, TokenKind.LParen, TokenKind.RParen);
30+
if (!inputsResult.IsSuccess)
31+
{
32+
return ParseResult<TypeSyntax>.Failure(inputsResult.Diagnostic!);
33+
}
34+
35+
if (!context.TryMatch(TokenKind.Arrow, out var arrowToken))
36+
{
37+
return ParseResult<TypeSyntax>.NoMatch();
38+
}
39+
40+
TypeSyntax? resultType = null;
41+
DelimitedSyntaxList<TypeSyntax> resultTypes;
42+
if (context.Is(TokenKind.LParen))
43+
{
44+
var resultTypesResult = TryParseTypeList(context, TokenKind.LParen, TokenKind.RParen);
45+
if (!resultTypesResult.IsSuccess)
46+
{
47+
return ParseResult<TypeSyntax>.Failure(resultTypesResult.Diagnostic!);
48+
}
49+
50+
resultTypes = resultTypesResult.Value;
51+
}
52+
else
53+
{
54+
resultTypes = new DelimitedSyntaxList<TypeSyntax>(null, [], [], null);
55+
var resultTypeResult = context.TryParseCurrentTypeSyntax();
56+
if (!resultTypeResult.IsSuccess)
57+
{
58+
return ParseResult<TypeSyntax>.Failure(resultTypeResult.Diagnostic!);
59+
}
60+
61+
resultType = resultTypeResult.Value;
62+
}
63+
64+
return ParseResult<TypeSyntax>.Success(new FunctionTypeSyntax(inputsResult.Value, arrowToken, resultType, resultTypes));
2765
}
2866

2967
/// <inheritdoc/>
@@ -90,4 +128,57 @@ public TypeSyntax BuildCustomAssemblySyntax(TypeReference type, ConcreteSyntaxBu
90128
new DelimitedSyntaxList<TypeSyntax>(
91129
TokenFactory.LParen(), resultSyntax, resultCommas, TokenFactory.RParen()));
92130
}
131+
132+
private static ParseResult<DelimitedSyntaxList<TypeSyntax>> TryParseTypeList(TypeParsingContext context, TokenKind openKind, TokenKind closeKind)
133+
{
134+
var openResult = context.Expect(openKind, $"Expected '{TokenText(openKind)}' to start the type list.");
135+
if (!openResult.IsSuccess)
136+
{
137+
return ParseResult<DelimitedSyntaxList<TypeSyntax>>.Failure(openResult.Diagnostic!);
138+
}
139+
140+
var items = new List<TypeSyntax>();
141+
var separators = new List<Token>();
142+
if (!context.Is(closeKind))
143+
{
144+
while (true)
145+
{
146+
var itemResult = context.TryParseTypeSyntax(TokenKind.Comma, closeKind);
147+
if (!itemResult.IsSuccess)
148+
{
149+
return ParseResult<DelimitedSyntaxList<TypeSyntax>>.Failure(itemResult.Diagnostic!);
150+
}
151+
152+
items.Add(itemResult.Value);
153+
if (!context.TryMatch(TokenKind.Comma, out var commaToken))
154+
{
155+
break;
156+
}
157+
158+
separators.Add(commaToken);
159+
}
160+
}
161+
162+
var closeResult = context.Expect(closeKind, $"Expected '{TokenText(closeKind)}' to close the type list.");
163+
if (!closeResult.IsSuccess)
164+
{
165+
return ParseResult<DelimitedSyntaxList<TypeSyntax>>.Failure(closeResult.Diagnostic!);
166+
}
167+
168+
return ParseResult<DelimitedSyntaxList<TypeSyntax>>.Success(new DelimitedSyntaxList<TypeSyntax>(
169+
openResult.Value,
170+
items,
171+
separators,
172+
closeResult.Value));
173+
}
174+
175+
private static string TokenText(TokenKind kind)
176+
{
177+
return kind switch
178+
{
179+
TokenKind.LParen => "(",
180+
TokenKind.RParen => ")",
181+
_ => kind.ToString(),
182+
};
183+
}
93184
}

src/MLIR/Dialects/Builtin/BuiltinIndexTypeAssemblyFormat.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,19 @@ namespace MLIR.Dialects.Builtin;
1111
/// Binds and rebuilds the builtin <c>index</c> type.
1212
/// </summary>
1313
/// <remarks>
14-
/// Parsing is handled by the core type parser; this format only provides binding and CST rebuild.
14+
/// This format owns the builtin <c>index</c> spelling as well as binding and CST rebuild.
1515
/// </remarks>
1616
public sealed class BuiltinIndexTypeAssemblyFormat : ITypeAssemblyFormat
1717
{
1818
/// <inheritdoc/>
1919
public ParseResult<TypeSyntax> TryParse(TypeParsingContext context)
2020
{
21-
// Parsing is handled by the core type parser, not by dialect custom syntax.
22-
return ParseResult<TypeSyntax>.NoMatch();
21+
if (!context.TryMatch(TokenKind.Identifier, out var nameToken) || nameToken.Text != "index")
22+
{
23+
return ParseResult<TypeSyntax>.NoMatch();
24+
}
25+
26+
return ParseResult<TypeSyntax>.Success(new BuiltinIndexTypeSyntax(nameToken));
2327
}
2428

2529
/// <inheritdoc/>

src/MLIR/Dialects/Builtin/BuiltinMemRefTypeAssemblyFormat.cs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace MLIR.Dialects.Builtin;
1313
/// Binds and rebuilds the builtin <c>memref</c> type, e.g. <c>memref&lt;2x3xf32&gt;</c>.
1414
/// </summary>
1515
/// <remarks>
16-
/// Parsing is handled by the core type parser; this format only provides binding and CST rebuild.
1716
/// <c>BuildCustomAssemblySyntax</c> uses the builder context to recursively synthesize syntax for
1817
/// the element type so that syntaxless child types are supported.
1918
/// </remarks>
@@ -22,8 +21,70 @@ public sealed class BuiltinMemRefTypeAssemblyFormat : ITypeAssemblyFormat
2221
/// <inheritdoc/>
2322
public ParseResult<TypeSyntax> TryParse(TypeParsingContext context)
2423
{
25-
// Parsing is handled by the core type parser, not by dialect custom syntax.
26-
return ParseResult<TypeSyntax>.NoMatch();
24+
if (!context.IsKeyword("memref"))
25+
{
26+
return ParseResult<TypeSyntax>.NoMatch();
27+
}
28+
29+
var keywordResult = context.ExpectKeyword("memref", "Expected 'memref'.");
30+
if (!keywordResult.IsSuccess)
31+
{
32+
return ParseResult<TypeSyntax>.Failure(keywordResult.Diagnostic!);
33+
}
34+
35+
var lessThanResult = context.Expect(TokenKind.LessThan, "Expected '<' after 'memref'.");
36+
if (!lessThanResult.IsSuccess)
37+
{
38+
return ParseResult<TypeSyntax>.Failure(lessThanResult.Diagnostic!);
39+
}
40+
41+
var prefixResult = context.TryParseRawUntilDelimiter(TokenKind.Comma, TokenKind.GreaterThan);
42+
if (!prefixResult.IsSuccess)
43+
{
44+
return ParseResult<TypeSyntax>.Failure(prefixResult.Diagnostic!);
45+
}
46+
47+
if (!BuiltinShapedTypeHelpers.TryParseShapedTypeBody(prefixResult.Value.Text, allowUnranked: true, minimumDimensionCount: 0, out var dimensions, out var xTokens, out var unrankedToken, out var elementTypeText))
48+
{
49+
return ParseResult<TypeSyntax>.NoMatch();
50+
}
51+
52+
var elementTypeResult = context.TryParseStandaloneTypeText(elementTypeText);
53+
if (!elementTypeResult.IsSuccess)
54+
{
55+
return elementTypeResult;
56+
}
57+
58+
var trailingCommaTokens = new List<Token>();
59+
var trailingParameters = new List<RawSyntaxText>();
60+
while (context.TryMatch(TokenKind.Comma, out var commaToken))
61+
{
62+
trailingCommaTokens.Add(commaToken);
63+
var trailingResult = context.TryParseRawUntilDelimiter(TokenKind.Comma, TokenKind.GreaterThan);
64+
if (!trailingResult.IsSuccess)
65+
{
66+
return ParseResult<TypeSyntax>.Failure(trailingResult.Diagnostic!);
67+
}
68+
69+
trailingParameters.Add(trailingResult.Value);
70+
}
71+
72+
var greaterThanResult = context.Expect(TokenKind.GreaterThan, "Expected '>' to close the memref type.");
73+
if (!greaterThanResult.IsSuccess)
74+
{
75+
return ParseResult<TypeSyntax>.Failure(greaterThanResult.Diagnostic!);
76+
}
77+
78+
return ParseResult<TypeSyntax>.Success(new MemRefTypeSyntax(
79+
keywordResult.Value,
80+
lessThanResult.Value,
81+
dimensions,
82+
xTokens,
83+
unrankedToken,
84+
elementTypeResult.Value,
85+
trailingCommaTokens,
86+
trailingParameters,
87+
greaterThanResult.Value));
2788
}
2889

2990
/// <inheritdoc/>

src/MLIR/Dialects/Builtin/BuiltinNoneTypeAssemblyFormat.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,19 @@ namespace MLIR.Dialects.Builtin;
1111
/// Binds and rebuilds the builtin <c>none</c> type.
1212
/// </summary>
1313
/// <remarks>
14-
/// Parsing is handled by the core type parser; this format only provides binding and CST rebuild.
14+
/// This format owns the builtin <c>none</c> spelling as well as binding and CST rebuild.
1515
/// </remarks>
1616
public sealed class BuiltinNoneTypeAssemblyFormat : ITypeAssemblyFormat
1717
{
1818
/// <inheritdoc/>
1919
public ParseResult<TypeSyntax> TryParse(TypeParsingContext context)
2020
{
21-
// Parsing is handled by the core type parser, not by dialect custom syntax.
22-
return ParseResult<TypeSyntax>.NoMatch();
21+
if (!context.TryMatch(TokenKind.Identifier, out var nameToken) || nameToken.Text != "none")
22+
{
23+
return ParseResult<TypeSyntax>.NoMatch();
24+
}
25+
26+
return ParseResult<TypeSyntax>.Success(new BuiltinNoneTypeSyntax(nameToken));
2327
}
2428

2529
/// <inheritdoc/>

src/MLIR/Dialects/Builtin/BuiltinScalarFloatTypeAssemblyFormat.cs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ namespace MLIR.Dialects.Builtin;
1212
/// </summary>
1313
/// <remarks>
1414
/// <para>
15-
/// Parsing is handled by the core type parser; this format only provides binding and CST rebuild.
16-
/// </para>
17-
/// <para>
1815
/// Each generated scalar float <c>TypeDef</c> class supplies a constructor delegate so the shared
1916
/// <see cref="BuiltinScalarFloatTypeAssemblyFormat"/> can produce the correct concrete
2017
/// <see cref="TypeReference"/> subclass without knowing its type at compile time.
@@ -24,6 +21,43 @@ public sealed class BuiltinScalarFloatTypeAssemblyFormat : ITypeAssemblyFormat
2421
{
2522
private readonly Func<BuiltinFloatTypeSyntax?, TypeReference> _create;
2623

24+
/// <summary>
25+
/// Returns whether the supplied identifier is one of MLIR's canonical builtin float spellings.
26+
/// </summary>
27+
public static bool IsBuiltinFloatName(string text)
28+
{
29+
if (text is "bf16" or "tf32")
30+
{
31+
return true;
32+
}
33+
34+
if (text.Length < 2 || text[0] != 'f' || !char.IsDigit(text[1]))
35+
{
36+
return false;
37+
}
38+
39+
var index = 1;
40+
while (index < text.Length && char.IsDigit(text[index]))
41+
{
42+
index++;
43+
}
44+
45+
if (index == text.Length)
46+
{
47+
return true;
48+
}
49+
50+
for (; index < text.Length; index++)
51+
{
52+
if (!char.IsLetterOrDigit(text[index]))
53+
{
54+
return false;
55+
}
56+
}
57+
58+
return true;
59+
}
60+
2761
/// <summary>
2862
/// Initializes a new instance of the <see cref="BuiltinScalarFloatTypeAssemblyFormat"/> class.
2963
/// </summary>
@@ -38,8 +72,14 @@ public BuiltinScalarFloatTypeAssemblyFormat(Func<BuiltinFloatTypeSyntax?, TypeRe
3872
/// <inheritdoc/>
3973
public ParseResult<TypeSyntax> TryParse(TypeParsingContext context)
4074
{
41-
// Parsing is handled by the core type parser, not by dialect custom syntax.
42-
return ParseResult<TypeSyntax>.NoMatch();
75+
if (!context.TryMatch(TokenKind.Identifier, out var nameToken))
76+
{
77+
return ParseResult<TypeSyntax>.NoMatch();
78+
}
79+
80+
return IsBuiltinFloatName(nameToken.Text)
81+
? ParseResult<TypeSyntax>.Success(new BuiltinFloatTypeSyntax(nameToken))
82+
: ParseResult<TypeSyntax>.NoMatch();
4383
}
4484

4585
/// <inheritdoc/>

0 commit comments

Comments
 (0)