Skip to content
← Back

src/syntax/parsers/definitions/impl.ghul

1
namespace Syntax.Parsers.Definitions is
2
use Source;
3
4
// impl <Interface> for <Target>[<params>] is <members> si
5
// Injects an interface implementation into an already-declared type. The
6
// interface's type parameters are the target's own, so they are written on
7
// the target (`for List[T]`), not as a separate binder.
8
class IMPL(
9
identifier_qualified_parser: Parser[Trees.Identifiers.Identifier],
10
type_parser: Parser[Trees.TypeExpressions.TypeExpression],
11
type_list_parser: Parser[Trees.TypeExpressions.LIST],
12
modifier_list_parser: Parser[Trees.Modifiers.LIST],
13
definition_list_parser: Parser[Trees.Definitions.LIST]
14
): Base[Trees.Definitions.IMPL] is
15
super();
16
17
parse(context: CONTEXT) -> Trees.Definitions.IMPL? is
18
let start = context.location;
19
context.in_classy = true;
20
context.global_indent = start.start_column;
21
22
try
23
context.next_token(Lexical.TOKEN.IMPL);
24
25
let interface = type_parser.parse(context);
26
27
if interface == null then
28
return null;
29
fi
30
31
let is_poisoned mut = interface.is_poisoned;
32
33
is_poisoned = !context.next_token(Lexical.TOKEN.FOR) \/ is_poisoned;
34
35
let identifier = identifier_qualified_parser.parse(context);
36
37
if !identifier? then
38
return null;
39
fi
40
41
let arguments: Trees.TypeExpressions.LIST? mut = null;
42
43
if context.current.token == Lexical.TOKEN.SQUARE_OPEN then
44
context.next_token();
45
46
context.in_type_parameters = true;
47
arguments = type_list_parser.parse(context)!;
48
context.in_type_parameters = false;
49
arguments.check_no_reference_types(context.logger);
50
51
is_poisoned = arguments.is_poisoned \/ is_poisoned;
52
53
if
54
!arguments.is_poisoned \/
55
context.current.token == Lexical.TOKEN.SQUARE_CLOSE
56
then
57
is_poisoned = !context.next_token(Lexical.TOKEN.SQUARE_CLOSE) \/ is_poisoned;
58
fi
59
fi
60
61
let ancestors =
62
Trees.TypeExpressions.LIST(
63
interface.location,
64
[interface]
65
);
66
67
let modifiers = modifier_list_parser.parse(context)!;
68
69
let expect_body = !is_poisoned \/ context.current.token == Lexical.TOKEN.IS;
70
let have_body mut = false;
71
72
let body: Trees.Definitions.LIST mut;
73
74
if expect_body /\ context.next_token(Lexical.TOKEN.IS) then
75
body = definition_list_parser.parse(context)!;
76
have_body = true;
77
else
78
body = Trees.Definitions.LIST(LOCATION.internal, Collections.LIST[Trees.Definitions.Definition](0));
79
is_poisoned = true;
80
fi
81
82
let result = Trees.Definitions.IMPL(
83
start::context.location,
84
identifier,
85
arguments,
86
ancestors,
87
modifiers,
88
body
89
);
90
91
result.poison(is_poisoned);
92
93
if have_body then
94
context.next_token(Lexical.TOKEN.SI);
95
fi
96
97
return result;
98
finally
99
context.in_classy = false;
100
yrt
101
si
102
si
103
si