Skip to content
← Back

src/semantic/range_slice_resolver.ghul

1
namespace Semantic is
2
use IR.Values.Value
3
use Ghul.Disposable
4
5
use Types.Type
6
7
// Resolves an index whose argument is a `System.Range`, `Ghul.INT_RANGE`
8
// or `Ghul.INT_RANGE_INCLUSIVE` to a slice of the source:
9
// `Ghul.Pipes.slice(source, range)`.
10
//
11
// The slice cannot be supplied as a member of the types that want it.
12
// `Collections.List[E]` is the interface every list-shaped receiver
13
// satisfies, and a member added there does not reach the types that
14
// implement it: a reflected type arrives from .NET with its inherited
15
// members already pulled down, so nothing propagates a later addition.
16
// Supplying it per receiver instead reaches an array and a string,
17
// which are the receiver types themselves, and then owes the same work
18
// to the next collection and to every user type. Resolving it as an
19
// ordinary call lets the receiver's own type select the overload.
20
class RANGE_SLICE_RESOLVER(
21
_innate_symbol_lookup: Lookups.InnateSymbolLookup,
22
_overload_resolver: OVERLOAD_RESOLVER,
23
_function_caller: FUNCTION_CALLER,
24
_logger: Logging.Logger
25
) is
26
// The `slice` overload serving this index, or null when there is
27
// none: the argument is not a range, or nothing in scope takes one
28
// over this source. A caller reports its own diagnostic then.
29
try_resolve(
30
location: Source.LOCATION,
31
source: Value,
32
index_type: Type
33
) -> OVERLOAD_RESOLVE_RESULT? is
34
if !is_range(index_type) then
35
return null
36
fi
37
38
let functions = _innate_symbol_lookup.get_slice_functions()
39
40
if !functions? then
41
return null
42
fi
43
44
let source_type = source.type
45
46
if !source_type? then
47
return null
48
fi
49
50
let types = Collections.LIST[Type]([source_type, index_type])
51
52
let use logger_snapshot = _logger.speculate_then_backtrack()
53
54
let resolved = _overload_resolver.resolve(location, functions, types, false, false, false)
55
56
logger_snapshot.backtrack()
57
58
return resolved
59
si
60
61
is_range(index_type: Type) -> bool =>
62
index_type.compare(_innate_symbol_lookup.get_range_type()) == Types.MATCH.SAME \/
63
index_type.compare(_innate_symbol_lookup.get_int_range_type()) == Types.MATCH.SAME \/
64
index_type.compare(_innate_symbol_lookup.get_int_range_inclusive_type()) == Types.MATCH.SAME
65
66
// The call itself, once the caller has recorded the use it wants
67
// recorded against the resolved function.
68
call(
69
location: Source.LOCATION,
70
resolved: OVERLOAD_RESOLVE_RESULT,
71
source: Value,
72
range: Value
73
) -> Value =>
74
resolved.function.call(
75
location,
76
null,
77
Collections.LIST[Value]([source, range]),
78
null,
79
_function_caller)
80
si
81
si