1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Task 7 (NL-035): `expression_read_set` — a **deliberate, narrow exception
//! to Decision 1** (documented on `lattice.rs` and here): a bound
//! port-connection expression (`PortConnection::expression() ->
//! Option<Expression<'d>>`, `ast.rs:5743`) has no enclosing `always`/
//! `initial`/`final`/subroutine/continuous-assign `Symbol` to hand to
//! `EvalSession::run_dataflow` — `run_dataflow`'s own signature
//! (`fn run_dataflow<L: Lattice>(&self, procedure: Symbol<'_>) ->
//! Result<L, Error>`, `dataflow.rs:436`) and its own doc comment ("a
//! procedure symbol: an `always`/`initial`/`final` block, a subroutine, or
//! a continuous assign") together mean there is no `Symbol` a bare
//! port-connection expression can be wrapped as. A port-connection
//! expression also has no control flow of its own (no `if`/`case`/loop can
//! appear inside it — it's a single expression), so a full CFG-walking
//! `Lattice` pass would be doing strictly more work than the problem needs;
//! this small recursive walker is the narrow, justified exception.
//!
//! Built entirely on already-verified `Expression` accessors: `operands()`
//! (`ast.rs:18292`, the immediate sub-expressions, non-expression children
//! skipped) and `referenced_symbol()` (`ast.rs:16794`, the symbol a leaf
//! expression directly names, if any).
use crateSymbolKey;
use crateSymbolUid;
use ;
/// Recursively collects every signal `expr` reads, resolved to a
/// `SymbolKey` via `scope_keys` — a `SymbolId -> SymbolKey` table for the
/// scope `expr`'s symbols are declared in (the caller's responsibility to
/// build against the right scope: the PARENT instantiation's own body for a
/// port-connection expression, per NL-035's "read-set resolved at the
/// parent scope" requirement).
///
/// **Deviation from the plan's literal signature** (`fn
/// expression_read_set(expr: Expression<'_>) -> Vec<SymbolKey>`, no
/// `scope_keys` parameter) — the same root cause `lattice.rs`'s own doc
/// comment documents for `ReadSetLattice`: resolving an arbitrary `Symbol`
/// to a `SymbolKey` is inherently scope-relative (`SymbolKey` is a
/// position within ONE scope's `members()`), and nothing about a bare
/// `Expression` names which scope's table to consult, so the caller
/// (`elaborate.rs`) must supply it.
///
/// Recursive walk: if `expr.referenced_symbol()` resolves to a signal
/// already interned in `scope_keys`, record it (a leaf reference);
/// regardless, recurse into `expr.operands()` and union their read-sets too
/// — a reference expression, e.g. a bit-select `p[i]`, both names `p`
/// directly AND has `i` as a sub-operand, so this is "record, then always
/// recurse", never an if/else branch. Terminates because `operands()`
/// strictly decreases expression depth (a leaf expression's `operands()` is
/// empty). Returned sorted and deduplicated (a `BTreeSet` collected to
/// `Vec`) for deterministic, order-independent comparison.
pub
/// Whether `expr` contains a pattern-matching conditional (`e matches p ?
/// a : b`, LRM 12.6.2).
pub
/// The read-set of a continuous assignment's right-hand side that contains a
/// pattern-matching conditional, by a plain tree walk. slang's dataflow
/// analysis (`run_dataflow`) dereferences a null state on such a
/// conditional (it merges the arms of a `?:` whose condition binds pattern
/// variables), so it cannot be asked. A function call in the same
/// expression is refused: what the callee reads is the dataflow's job, and
/// guessing it would silently drop a sensitivity.
pub