Skip to content
← Back

src/semantic/symbols/iterator_reset_synthesis.ghul

1
namespace Semantic.Symbols is
2
use Source.LOCATION
3
4
use Types.Type
5
6
// `Collections.Iterator[T]` maps to `IEnumerator[T]`, which carries
7
// `Reset` from the interface .NET's own iterators answer by
8
// throwing: it is there for COM and almost nothing calls it. An
9
// implementor that writes one is writing a method that will not be
10
// called, so one is synthesized where none is declared, throwing
11
// rather than doing nothing - a caller that did ask for a restart
12
// is owed the news that it did not happen.
13
//
14
// `dispose` is left an obligation: what a type holds and must
15
// release is the author's to answer.
16
class ITERATOR_RESET_SYNTHESIS is
17
_innate_symbol_lookup: Lookups.InnateSymbolLookup
18
19
init(innate_symbol_lookup: Lookups.InnateSymbolLookup) is
20
_innate_symbol_lookup = innate_symbol_lookup
21
si
22
23
// Answers the synthesized method, or null where the type wants
24
// none: one it declares itself always wins.
25
try_synthesize(type: Classy) -> Function? is
26
if type.is_trait \/ type.is_reflected \/ type.is_abstract then
27
return null
28
fi
29
30
if !_implements_iterator(type) then
31
return null
32
fi
33
34
if _has_reset_body(type) then
35
return null
36
fi
37
38
let reset =
39
if type.is_value_type then
40
STRUCT_METHOD(type.location, type.location, type, "reset", type)
41
else
42
INSTANCE_METHOD(type.location, type.location, type, "reset", type)
43
fi
44
45
reset.set_arguments(
46
Collections.LIST[string](), Collections.LIST[Type]())
47
48
reset.set_void_return_type()
49
reset.mark_throws_not_supported()
50
51
type.add_member(reset)
52
53
return reset
54
si
55
56
// Whether anything already answers `reset` with a body: the
57
// type's own, a base class's, or the default a trait supplies.
58
// Overrides have not been resolved yet, so the ancestors are
59
// walked rather than asked - and the interface's own
60
// declaration is passed over, since that is the obligation
61
// being answered rather than an answer to it.
62
_has_reset_body(type: Classy) -> bool is
63
if _declares_reset_body(type) then
64
return true
65
fi
66
67
for ancestor in type.ancestors do
68
if let classy: Classy = ancestor.symbol /\ _has_reset_body(classy) then
69
return true
70
fi
71
od
72
73
return false
74
si
75
76
_declares_reset_body(type: Classy) -> bool is
77
let found = type.find_direct("reset")
78
79
if let group: FUNCTION_GROUP = found then
80
for f in group.functions do
81
if _is_implementation(f) then
82
return true
83
fi
84
od
85
86
return false
87
fi
88
89
if let single: Function = found then
90
return _is_implementation(single)
91
fi
92
93
return false
94
si
95
96
_is_implementation(f: Function) -> bool static =>
97
f.arguments.count == 0 /\ !f.is_abstract
98
99
_implements_iterator(type: Classy) -> bool is
100
let iterator = _innate_symbol_lookup.get_unspecialized_iterator_type()
101
102
for ancestor in type.ancestors do
103
if !ancestor.is_trait then
104
continue
105
fi
106
107
if ancestor.find_ancestor(iterator)? then
108
return true
109
fi
110
od
111
112
return false
113
si
114
si
115
si