2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
4
using System . Collections . Immutable ;
5
+ using System . Diagnostics ;
5
6
using System . Text . RegularExpressions ;
7
+ using Microsoft . Extensions . Logging ;
6
8
using Silk . NET . SilkTouch . Symbols ;
7
9
8
10
namespace Silk . NET . SilkTouch . TypeResolution ;
@@ -12,34 +14,80 @@ namespace Silk.NET.SilkTouch.TypeResolution;
12
14
/// </summary>
13
15
public class FunctionPointerTypeResolver : SimpleTypeResolverBase
14
16
{
15
- private static readonly Regex _regex = new
16
- ( /*lang=regex*/
17
- @"delegate\*\sunmanaged(\[((?'modifier'.(?=,\s?)?)+)*\])?\<((?'parameter'(.(?=,\s?)+))(,\s?))*(?'return_type'(.)+)\>" ,
18
- RegexOptions . CultureInvariant
19
- ) ;
17
+ private readonly ILogger _logger ;
20
18
21
19
/// <inheritdoc />
22
- public FunctionPointerTypeResolver ( TypeStore typeStore ) : base ( typeStore )
20
+ public FunctionPointerTypeResolver ( ILogger < FunctionPointerTypeResolver > logger , TypeStore typeStore ) : base ( typeStore )
23
21
{
22
+ _logger = logger ;
24
23
}
25
24
26
25
/// <inheritdoc />
27
26
protected override bool TryResolve ( UnresolvedTypeReference utr , out TypeReference ? resolved )
28
27
{
29
- if ( utr . Text . StartsWith ( "delegate*" ) )
28
+ int c = 0 ;
29
+ var text = utr . Text ;
30
+ if ( text . Length > "delegate*" . Length && text [ text . Length - 1 ] == '>' && text . Substring ( c , "delegate*" . Length ) == "delegate*" )
30
31
{
31
- var match = _regex . Match ( utr . Text ) ;
32
- if ( match . Success )
32
+ _logger . LogTrace ( "Attempting to resolve {text} to function pointer after passing preliminary tests" , utr . Text ) ;
33
+ c += "delegate*" . Length ;
34
+ if ( text . Substring ( c , " unmanaged" . Length ) == " unmanaged" )
33
35
{
34
- var parameters = match . Groups [ "parameter" ]
35
- . Captures . OfType < Capture > ( )
36
- . Select ( x => new UnresolvedTypeReference ( x . Value ) )
37
- . Cast < TypeReference > ( )
38
- . ToImmutableArray ( ) ;
39
- var returnType = new UnresolvedTypeReference ( match . Groups [ "return_type" ] . Value ) ;
36
+ c += " unmanaged" . Length ;
37
+ if ( text [ c ] == '[' )
38
+ {
39
+ var endOffset = text . AsSpan ( c ) . IndexOf ( ']' ) ;
40
+
41
+ var attributeText = text . Substring ( c + 1 , endOffset - 1 ) ;
42
+ _logger . LogDebug ( "{text} may be a function pointer and has unhandled attributes {attributes}" , utr . Text , attributeText ) ;
43
+ // TODO: parse out function attributes here
44
+
45
+ c += endOffset + 1 ;
46
+ }
47
+ var types = new List < TypeReference > ( ) ;
48
+ if ( text [ c ] == '<' )
49
+ {
50
+ c += 1 ;
51
+ while ( true )
52
+ {
53
+ var typeTextEndIndex = text . AsSpan ( c ) . IndexOf ( ',' ) ;
54
+ if ( typeTextEndIndex != - 1 )
55
+ {
56
+ var typeText = text . Substring ( c , typeTextEndIndex ) ;
57
+ c += typeTextEndIndex + 1 ;
58
+ if ( text [ c ] == ' ' ) c ++ ;
59
+ types . Add ( new UnresolvedTypeReference ( typeText ) ) ;
60
+ }
61
+ else
62
+ {
63
+ var l = text . Length - c - 1 ;
64
+ if ( l > 0 )
65
+ {
66
+ var typeText = text . Substring ( c , l ) ;
67
+ types . Add ( new UnresolvedTypeReference ( typeText ) ) ;
68
+ }
69
+ break ;
70
+ }
71
+ }
72
+ }
73
+ else
74
+ {
75
+ _logger . LogDebug ( "{text} may be a function pointer but generic params are somehow scrambled" , utr . Text ) ;
76
+ }
40
77
41
- resolved = new FunctionPointerTypeReference ( returnType , parameters ) ;
42
- return true ;
78
+
79
+ // at least a return type is required
80
+ if ( types . Count > 0 )
81
+ {
82
+ resolved = new FunctionPointerTypeReference
83
+ ( types . Last ( ) , types . Take ( types . Count - 1 ) . ToImmutableArray ( ) ) ;
84
+ _logger . LogTrace ( "{text} resolved to function pointer {ptr}" , utr . Text , resolved ) ;
85
+ return true ;
86
+ }
87
+ }
88
+ else
89
+ {
90
+ _logger . LogDebug ( "Rejecting {text} as it may be a function pointer, but not unmanaged" , utr . Text ) ;
43
91
}
44
92
}
45
93
resolved = null ;
0 commit comments