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
elif isa Trees.TypeExpressions.NAMED_TUPLE_ELEMENT(a) then
63
let named = a;
64
name = named.name.name;
65
variance = named.variance;
66
67
s = _symbol_table.current_declaration_context.declare_type(named.name.location, named.name.name, index, _symbol_definition_listener);
68
69
let constraint = cast Trees.TypeExpressions.TYPE_PARAMETER_CONSTRAINT?(named.type_expression);
70
71
if constraint? then
72
s.set_constraint_kind(constraint.kind);
73
fi
74
75
// Trailing kind constraint after a type bound
76
// (`[T: A class]`). The bound itself is in
77
// type_expression; combined_kind carries the kind.
78
if named.combined_kind != Semantic.Symbols.TypeParameterConstraintKind.NONE then
79
s.set_constraint_kind(named.combined_kind);
80
fi
81
82
if named.has_constructor then
83
s.set_has_constructor_constraint(true);
84
fi
85
fi
86
87
if variance != Semantic.Types.TypeVariance.INVARIANT then
88
any_variance = true;
89
fi
90
91
variances.add(variance);
92
93
if s? then
94
names.add(name!);
95
96
let type = Semantic.Types.FUNCTION_GENERIC_ARGUMENT(s);
97
types.add(type);
98
else
99
names.add("{index}");
100
101
types.add(Semantic.Types.NONE.instance);
102
fi
103
104
index = index + 1;
105
od
106
107
if any_variance then
108
apply_declared_variance(arguments.location, variances);
109
fi
110
111
return (names, types);
112
fi
113
return _;
114
si
115
116
// Records declared type-parameter variance (`out` / `in`) on the
117
// enclosing generic type. The CLR permits variance only on
118
// interfaces, so it is an error to declare it anywhere other
119
// than a trait.
120
apply_declared_variance(location: LOCATION, variances: Collections.List[Semantic.Types.TypeVariance]) is
121
if isa Semantic.Symbols.TRAIT(_symbol_table.current_declaration_context) then
122
let trait_symbol = cast Semantic.Symbols.Classy?(_symbol_table.current_declaration_context)!;
123
124
trait_symbol.argument_variances = variances;
125
else
126
_logger.error(location, "type-parameter variance can only be declared on a trait");
127
fi
128
si
129
130
si
131
si