Skip to content
← Back

src/syntax/process/generic_argument_declarer.ghul

1
namespace Syntax.Process is
2
use Logging
3
use Source
4
use Trees
5
6
// Declares a definition's generic type parameters into the current
7
// declaration context and applies any declared variance. Shared by
8
// DECLARE_SYMBOLS (type-level parameter lists) and DECLARE_MEMBERS
9
// (generic functions).
10
class GENERIC_ARGUMENT_DECLARER(
11
_logger: Logger,
12
_symbol_table: Semantic.SYMBOL_TABLE,
13
_symbol_definition_listener: Semantic.SymbolDefinitionListener
14
) is
15
get_generic_arguments(arguments: Trees.TypeExpressions.LIST?) -> Collections.LIST[string] is
16
let result = Collections.LIST[string]()
17
18
if arguments? then
19
// FIXME: this is a bodge - generic class definition arguments are not type expressions, they're
20
// their own thing and should support type variance and type constraints - need syntax tree
21
// node classes to represent them:
22
for a in arguments do
23
if isa Trees.TypeExpressions.NAMED(a) then
24
let named = a
25
26
result.add(named.name.name)
27
elif isa Trees.TypeExpressions.NAMED_TUPLE_ELEMENT(a) then
28
let named = a
29
30
result.add(named.name.name)
31
elif !a.is_poisoned then
32
_logger.error(a.location, "argument must be an identifier or an identifer with a type constraint")
33
fi
34
od
35
fi
36
37
return result
38
si
39
40
declare_generic_arguments(arguments: Trees.TypeExpressions.LIST?) ->
41
(names: Collections.LIST[string], types: Collections.LIST[Semantic.Types.Type])
42
is
43
if arguments? then
44
let types = Collections.LIST[Semantic.Types.Type]()
45
let variances = Collections.LIST[Semantic.Types.TypeVariance]()
46
let any_variance mut = false
47
48
let index mut = 0
49
50
let names = Collections.LIST[string]()
51
52
for a in arguments do
53
let s: Semantic.Symbols.Symbol? mut = null
54
let name: string? mut = null
55
let variance mut = Semantic.Types.TypeVariance.INVARIANT
56
57
if isa Trees.TypeExpressions.NAMED(a) then
58
let named = a
59
name = named.name.name
60
61
s = _symbol_table.current_declaration_context.declare_type(named.name.location, name, index, _symbol_definition_listener)
62
63
if named.is_argument_pack then
64
s.set_is_argument_pack(true)
65
fi
66
elif isa Trees.TypeExpressions.NAMED_TUPLE_ELEMENT(a) then
67
let named = a
68
name = named.name.name
69
variance = named.variance
70
71
s = _symbol_table.current_declaration_context.declare_type(named.name.location, named.name.name, index, _symbol_definition_listener)
72
73
let constraint = cast Trees.TypeExpressions.TYPE_PARAMETER_CONSTRAINT?(named.type_expression)
74
75
if constraint? then
76
s.set_constraint_kind(constraint.kind)
77
fi
78
79
// Trailing kind constraint after a type bound
80
// (`[T: A class]`). The bound itself is in
81
// type_expression; combined_kind carries the kind.
82
if named.combined_kind != Semantic.Symbols.TypeParameterConstraintKind.NONE then
83
s.set_constraint_kind(named.combined_kind)
84
fi
85
86
if named.has_constructor then
87
s.set_has_constructor_constraint(true)
88
fi
89
fi
90
91
if variance != Semantic.Types.TypeVariance.INVARIANT then
92
any_variance = true
93
fi
94
95
variances.add(variance)
96
97
if s? then
98
names.add(name!)
99
100
let type = Semantic.Types.FUNCTION_GENERIC_ARGUMENT(s)
101
types.add(type)
102
else
103
names.add("{index}")
104
105
types.add(Semantic.Types.NONE.instance)
106
fi
107
108
index = index + 1
109
od
110
111
if any_variance then
112
apply_declared_variance(arguments.location, variances)
113
fi
114
115
return (names, types)
116
fi
117
return _
118
si
119
120
// Records declared type-parameter variance (`out` / `in`) on the
121
// enclosing generic type. The CLR permits variance only on
122
// interfaces, so it is an error to declare it anywhere other
123
// than a trait.
124
apply_declared_variance(location: LOCATION, variances: Collections.List[Semantic.Types.TypeVariance]) is
125
if isa Semantic.Symbols.TRAIT(_symbol_table.current_declaration_context) then
126
let trait_symbol = cast Semantic.Symbols.Classy?(_symbol_table.current_declaration_context)!
127
128
trait_symbol.argument_variances = variances
129
else
130
_logger.error(location, "type-parameter variance can only be declared on a trait")
131
fi
132
si
133
134
si
135
si