Skip to content
← Back

src/semantic/symbols/owner_instantiation_binder.ghul

1
namespace Semantic.Symbols is
2
use Types.Type
3
4
// Pairing formals with actuals can only bind an owner type argument
5
// that some formal's type mentions. One that appears only in the
6
// return type - TResult on IAdditionOperators[TSelf, TOther, TResult]
7
// - is unreachable that way, so the candidate is discarded as
8
// unbindable however well the arguments actually fit.
9
//
10
// Such an argument does not need inferring. An actual whose type is
11
// bounded by an instantiation of the owner has already pinned every
12
// one of the owner's arguments: `[T: INumber[T]]` instantiates
13
// IAdditionOperators[T, T, T], so TResult is T by declaration. Read
14
// the bindings off that instantiation instead of trying to infer
15
// them.
16
class OWNER_INSTANTIATION_BINDER is
17
_MAX_ANCESTOR_DEPTH: int static => 8
18
19
// Bind the type arguments of `owner_classy` that the formals
20
// left unbound, from the first actual that is, or descends
21
// from, an instantiation of it. Does nothing at all when the
22
// formals already covered every one, which is the ordinary
23
// case - the ancestor walk below only runs where the binding
24
// would otherwise be rejected as incomplete.
25
bind_unbound_from_actual_instantiations(
26
owner_classy: Classy,
27
args: Collections.List[Type],
28
results: Types.GENERIC_ARGUMENT_BIND_RESULTS
29
) static is
30
if _is_complete(owner_classy, results) then
31
return
32
fi
33
34
let names = owner_classy.argument_names
35
36
for actual in args do
37
let instantiation = _find_owner_instantiation(actual, owner_classy, 0)
38
39
if !instantiation? then
40
continue
41
fi
42
43
let arguments = instantiation.arguments
44
45
if arguments.count != names.count then
46
continue
47
fi
48
49
for i in 0..names.count do
50
let parameter = _type_parameter_at(owner_classy, i)
51
52
if !parameter? then
53
continue
54
fi
55
56
if results.bindings.contains_key(parameter.symbol) then
57
continue
58
fi
59
60
results.bind(parameter, arguments[i])
61
od
62
63
return
64
od
65
si
66
67
_type_parameter_at(owner_classy: Classy, index: int) -> Types.GenericArgument? static is
68
if let declared = cast GenericArgument?(owner_classy.type_parameter_at(index)) then
69
return cast Types.GenericArgument?(declared.type)
70
fi
71
72
return null
73
si
74
75
_is_complete(owner_classy: Classy, results: Types.GENERIC_ARGUMENT_BIND_RESULTS) -> bool static is
76
for i in 0..owner_classy.argument_names.count do
77
if let parameter = _type_parameter_at(owner_classy, i) then
78
if !results.bindings.contains_key(parameter.symbol) then
79
return false
80
fi
81
fi
82
od
83
84
return true
85
si
86
87
// The instantiation of `owner_classy` that `t` is, or that one
88
// of its ancestors is. A type variable reports its bound as its
89
// sole ancestor, so this reaches through `[T: INumber[T]]` to
90
// the interfaces INumber itself extends. Ancestors are read
91
// through `get_ancestor` so each hop carries the substitution
92
// of the hop above it.
93
_find_owner_instantiation(t: Type?, owner_classy: Classy, depth: int) -> GENERIC? static is
94
if !t? \/ depth > _MAX_ANCESTOR_DEPTH then
95
return null
96
fi
97
98
let symbol = t.symbol
99
100
if let generic = cast GENERIC?(symbol) /\ generic.symbol == owner_classy then
101
return generic
102
fi
103
104
for i in 0..symbol.ancestors.count do
105
let found = _find_owner_instantiation(symbol.get_ancestor(i), owner_classy, depth + 1)
106
107
if found? then
108
return found
109
fi
110
od
111
112
return null
113
si
114
si
115
si