Skip to content
← Back

src/semantic/delegate_shape.ghul

1
namespace Semantic is
2
use Types.Type;
3
4
// Recognises .NET delegate types and reports the function type that
5
// describes how they are called.
6
//
7
// `Func` and `Action` are excluded: they are already modelled as
8
// FUNCTION / ACTION, so `is_named_delegate` answers false for them
9
// and callers keep their existing path.
10
class DELEGATE_SHAPE is
11
MULTICAST_DELEGATE_NAME: string static => "System.MulticastDelegate";
12
13
init() is
14
si
15
16
// True for a delegate type ghūl does not already model as a
17
// function type.
18
is_named_delegate(type: Type) -> bool =>
19
!type.is_function /\ _inherits_multicast_delegate(type);
20
21
// The function type describing `type`'s call shape, or null when
22
// `type` is not a named delegate or carries no usable `invoke`.
23
try_get_function_type(type: Type, innate_symbol_lookup: Lookups.InnateSymbolLookup) -> Type? is
24
if !is_named_delegate(type) then
25
return null;
26
fi
27
28
let invoke = _find_invoke(type);
29
30
if !invoke? \/ !invoke.return_type? \/ !invoke.are_arguments_declared then
31
return null;
32
fi
33
34
return invoke.get_full_type(innate_symbol_lookup);
35
si
36
37
// A delegate declares exactly one `Invoke`, so the group it
38
// arrives in holds a single function.
39
_find_invoke(type: Type) -> Symbols.Function? is
40
let member = type.find_member("invoke");
41
42
if let group: Symbols.FUNCTION_GROUP = member then
43
if group.count == 1 then
44
return group.functions[0];
45
fi
46
47
return null;
48
fi
49
50
return cast Symbols.Function?(member);
51
si
52
53
_inherits_multicast_delegate(type: Type) -> bool is
54
for ancestor in type.ancestors do
55
if ancestor.symbol.qualified_name =~ MULTICAST_DELEGATE_NAME then
56
return true;
57
fi
58
59
if _inherits_multicast_delegate(ancestor) then
60
return true;
61
fi
62
od
63
64
return false;
65
si
66
si
67
si