|
9 | 9 | [identifier-usage-analyzer expansion-analyzer?])) |
10 | 10 |
|
11 | 11 |
|
12 | | -(require racket/hash |
13 | | - racket/list |
14 | | - racket/set |
| 12 | +(require racket/list |
15 | 13 | racket/stream |
16 | | - racket/treelist |
17 | | - rebellion/collection/hash |
| 14 | + rebellion/collection/entry |
18 | 15 | rebellion/streaming/transducer |
| 16 | + resyntax/default-recommendations/analyzers/private/expanded-id-table |
19 | 17 | resyntax/private/analyzer |
20 | 18 | resyntax/private/syntax-path |
21 | 19 | resyntax/private/syntax-property-bundle |
|
34 | 32 | ;@---------------------------------------------------------------------------------------------------- |
35 | 33 |
|
36 | 34 |
|
37 | | -(define (append-all-id-maps id-maps) |
38 | | - (for/fold ([combined (hash)]) |
39 | | - ([map id-maps]) |
40 | | - (hash-union combined map #:combine treelist-append))) |
41 | | - |
42 | | - |
43 | | -(define (id-map-shift-phase id-map levels) |
44 | | - (for/hash ([(phase ids) (in-hash id-map)]) |
45 | | - (values (and phase (+ phase levels)) ids))) |
46 | | - |
47 | | - |
48 | 35 | ;; Label syntax with phase information |
49 | 36 | (define (syntax-label-id-phases expanded-stx) |
50 | 37 | (let loop ([expanded-stx expanded-stx] [phase 0] [skip? #false]) |
|
166 | 153 | (stream (attribute id))]))) |
167 | 154 |
|
168 | 155 |
|
169 | | -(define (phase-binding-table bound-ids used-ids #:phase phase) |
170 | | - (define initial-map |
171 | | - (for/fold ([map (make-immutable-free-id-table #:phase phase)]) |
172 | | - ([bound bound-ids]) |
173 | | - (free-id-table-set map bound '()))) |
174 | | - (for*/fold ([map initial-map]) |
175 | | - ([bound bound-ids] |
176 | | - [used used-ids] |
177 | | - #:when (free-identifier=? bound used)) |
178 | | - (free-id-table-update map bound (λ (previous) (cons used previous)) '()))) |
179 | | - |
180 | | - |
181 | | -(define (identifier-binding-table bound-ids-by-phase used-ids-by-phase) |
182 | | - (for/hash |
183 | | - ([phase |
184 | | - (in-set (set-union (hash-key-set bound-ids-by-phase) (hash-key-set used-ids-by-phase)))]) |
185 | | - (define bound-ids (hash-ref bound-ids-by-phase phase '())) |
186 | | - (define used-ids (hash-ref used-ids-by-phase phase '())) |
187 | | - (values phase (phase-binding-table bound-ids used-ids #:phase phase)))) |
188 | | - |
189 | | - |
190 | 156 | (define (fully-expanded-syntax-binding-table stx) |
191 | 157 | (define labeled-stx (syntax-label-id-phases (syntax-label-paths stx 'expanded-path))) |
192 | 158 |
|
193 | | - ;; Get bound identifiers and group by phase |
194 | | - (define bound-ids-by-phase |
195 | | - (for/fold ([result (hash)]) |
196 | | - ([id (in-stream (binding-site-identifiers labeled-stx))]) |
197 | | - (define id-phase (syntax-property id 'phase)) |
198 | | - (hash-update result id-phase (λ (prev) (treelist-add prev id)) (treelist)))) |
| 159 | + ;; Create expanded-id-table to track bound identifiers with empty usage lists |
| 160 | + (define table (make-expanded-id-table)) |
| 161 | + |
| 162 | + ;; Initialize all bound identifiers with empty usage lists |
| 163 | + (for ([id (in-stream (binding-site-identifiers labeled-stx))]) |
| 164 | + (define id-phase (syntax-property id 'phase)) |
| 165 | + (expanded-id-table-set! table (expanded-identifier id id-phase) '())) |
199 | 166 |
|
200 | | - ;; Get used identifiers and group by phase |
201 | | - (define used-ids-by-phase |
202 | | - (for/fold ([result (hash)]) |
203 | | - ([id (in-stream (usage-site-identifiers labeled-stx))]) |
204 | | - (define id-phase (syntax-property id 'phase)) |
205 | | - (hash-update result id-phase (λ (prev) (treelist-add prev id)) (treelist)))) |
| 167 | + ;; For each usage, find its binding within the same phase and add it to the usage list |
| 168 | + (for ([used-id (in-stream (usage-site-identifiers labeled-stx))]) |
| 169 | + (define used-phase (syntax-property used-id 'phase)) |
| 170 | + (for ([bound-entry (in-expanded-id-table-phase table used-phase)]) |
| 171 | + (define bound-expanded-id (entry-key bound-entry)) |
| 172 | + (define bound-id (expanded-identifier-syntax bound-expanded-id)) |
| 173 | + (when (free-identifier=? bound-id used-id) |
| 174 | + (define current-usages (entry-value bound-entry)) |
| 175 | + (expanded-id-table-set! table bound-expanded-id (cons used-id current-usages))))) |
206 | 176 |
|
207 | | - (identifier-binding-table bound-ids-by-phase used-ids-by-phase)) |
| 177 | + table) |
208 | 178 |
|
209 | 179 |
|
210 | 180 | (define identifier-usage-analyzer |
211 | 181 | (make-expansion-analyzer |
212 | 182 | #:name 'identifier-usage-analyzer |
213 | 183 | (λ (expanded-stx) |
214 | 184 | (define table (fully-expanded-syntax-binding-table expanded-stx)) |
215 | | - (transduce (in-hash-values table) |
216 | | - (append-mapping |
217 | | - (λ (id-table) |
218 | | - (for/stream ([(bound-id usages) (in-free-id-table id-table)]) |
219 | | - (define exp-path (syntax-property bound-id 'expanded-path)) |
220 | | - (syntax-property-entry exp-path 'usage-count (length usages))))) |
| 185 | + (transduce (in-expanded-id-table table) |
| 186 | + (mapping |
| 187 | + (λ (entry) |
| 188 | + (define expanded-id (entry-key entry)) |
| 189 | + (define usages (entry-value entry)) |
| 190 | + (define bound-id (expanded-identifier-syntax expanded-id)) |
| 191 | + (define exp-path (syntax-property bound-id 'expanded-path)) |
| 192 | + (syntax-property-entry exp-path 'usage-count (length usages)))) |
221 | 193 | #:into into-syntax-property-bundle)))) |
0 commit comments