Skip to content
← Back

src/syntax/process/variable_left_state.ghul

1
namespace Syntax.Process is
2
use Collections
3
4
use LOCATION = Source.LOCATION
5
use Type = Semantic.Types.Type
6
use Value = IR.Values.Value
7
use VariableLeft = Trees.Variables.VariableLeft
8
9
// Compile-expressions output for one variable binding target (a
10
// VariableLeft node). Owned by the compile-expressions pass and read
11
// by IL generation; kept here, keyed by node, rather than in fields
12
// on the node itself (see NodeStateStore).
13
class VARIABLE_LEFT_STATE is
14
// code to store into the bound variable, from the initializer
15
value: Value? public
16
explicit_type: Type? public
17
18
// For an `if let` / `while let` clause pattern: the clause's
19
// ascribed narrow type, specialized against the scrutinee's
20
// type so a variant of a generic union carries its type
21
// arguments. IL generation tests against this rather than the
22
// written type expression, which for a generic union names the
23
// open generic and is not a loadable `isinst` operand.
24
narrow_type: Type? public
25
26
// the compiled initializer, if any
27
right_value: Value? public
28
right_location: LOCATION? public
29
variable_location: LOCATION? public
30
31
// An untyped local initialized with an empty array literal and
32
// no context to type it: the local waits on its later uses
33
// rather than taking the literal's object fallback.
34
awaits_later_use: bool public
35
36
// Whether what the local waits on is an empty array literal,
37
// which the fixing step can default to an object element type,
38
// as against an initializer with no default at all.
39
awaits_empty_literal: bool public
40
41
// An untyped immutable local whose initializer has no type of its
42
// own to give it - a `_()` construction, or a call leaving a type
43
// parameter of its own unbound - once seen: from then on, every
44
// walk types the initializer from the local's later uses.
45
typed_by_later_use: bool public
46
47
// For a literal leaf in a destructure pattern: the value-equality
48
// test built the way `=~` (falling back to `<>`) would, and the
49
// hole standing in for the source position's value. The source
50
// value only exists once IL generation walks the pattern, so the
51
// test is built against `match_operand` and generation fills it
52
// in before emitting. Both null when no operator resolved, or for
53
// a `null` leaf, which is a presence test rather than a compare.
54
match_test: Value? public
55
match_operand: IR.Values.WRAPPER? public
56
57
init() is
58
si
59
si
60
61
// Entries are keyed by (file name, node id), not node object
62
// identity — see Node.node_id. Ids are never reused, so an entry
63
// orphaned by tree replacement can go stale but can never be
64
// served for a different node.
65
class VARIABLE_LEFT_STATE_STORE: NodeStateStore is
66
_state_by_file: MutableMap[string, MutableMap[int, VARIABLE_LEFT_STATE]]
67
68
name: string => "variable-left"
69
70
entry_count: int => _count_entries()
71
72
init(registry: STATE_STORE_REGISTRY) is
73
_state_by_file = MAP[string, MutableMap[int, VARIABLE_LEFT_STATE]]()
74
75
registry.register(self)
76
si
77
78
// The state recorded for `left`, or null when none has been.
79
get(left: VariableLeft) -> VARIABLE_LEFT_STATE? is
80
let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut
81
82
if !_state_by_file.try_get_value(left.location.file_name, by_node ref) then
83
return null
84
fi
85
86
let result: VARIABLE_LEFT_STATE mut
87
88
if by_node.try_get_value(left.node_id, result ref) then
89
return result
90
fi
91
92
return null
93
si
94
95
get_or_add(left: VariableLeft) -> VARIABLE_LEFT_STATE is
96
let file_name = left.location.file_name
97
98
let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut
99
100
if !_state_by_file.try_get_value(file_name, by_node ref) then
101
by_node = MAP[int, VARIABLE_LEFT_STATE]()
102
_state_by_file[file_name] = by_node
103
fi
104
105
let result: VARIABLE_LEFT_STATE mut
106
107
if !by_node.try_get_value(left.node_id, result ref) then
108
result = VARIABLE_LEFT_STATE()
109
by_node[left.node_id] = result
110
fi
111
112
return result
113
si
114
115
remove(left: VariableLeft) is
116
let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut
117
118
if _state_by_file.try_get_value(left.location.file_name, by_node ref) then
119
by_node.remove(left.node_id)
120
fi
121
si
122
123
drop_file(file_name: string) is
124
_state_by_file.remove(file_name)
125
si
126
127
clear_all() is
128
_state_by_file = MAP[string, MutableMap[int, VARIABLE_LEFT_STATE]]()
129
si
130
131
_count_entries() -> int is
132
let result mut = 0
133
134
for by_node in _state_by_file.values do
135
result = result + by_node.count
136
od
137
138
return result
139
si
140
si
141
si