Skip to content

Commit 5e14c08

Browse files
Copilotjackfirth
andcommitted
Add syntax-immediate-properties and syntax-all-properties functions
Co-authored-by: jackfirth <[email protected]>
1 parent 4f89344 commit 5e14c08

File tree

1 file changed

+117
-1
lines changed

1 file changed

+117
-1
lines changed

private/syntax-property-bundle.rkt

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
[into-syntax-property-bundle (reducer/c syntax-property-entry? syntax-property-bundle?)]
2222
[property-hashes-into-syntax-property-bundle
2323
(reducer/c (entry/c syntax-path? immutable-hash?) syntax-property-bundle?)]
24-
[syntax-add-all-properties (-> syntax? syntax-property-bundle? syntax?)]))
24+
[syntax-add-all-properties (-> syntax? syntax-property-bundle? syntax?)]
25+
[syntax-immediate-properties (-> syntax? syntax-property-bundle?)]
26+
[syntax-all-properties (-> syntax? syntax-property-bundle?)]))
2527

2628

2729
(require guard
@@ -244,6 +246,22 @@
244246
(syntax-set stx path new-subform))
245247

246248

249+
(define (syntax-immediate-properties stx)
250+
(define keys (syntax-property-symbol-keys stx))
251+
(sequence->syntax-property-bundle
252+
(for/list ([key (in-list keys)])
253+
(define value (syntax-property stx key))
254+
(syntax-property-entry empty-syntax-path key value))))
255+
256+
257+
(define (syntax-all-properties stx)
258+
(sequence->syntax-property-bundle
259+
(for*/list ([path (in-syntax-paths stx)]
260+
[key (in-list (syntax-property-symbol-keys (syntax-ref stx path)))])
261+
(define value (syntax-property (syntax-ref stx path) key))
262+
(syntax-property-entry path key value))))
263+
264+
247265
(module+ test
248266
(test-case "syntax-add-all-properties"
249267
(define stx #'(a (b c) d))
@@ -266,3 +284,101 @@
266284
(define/syntax-parse (b* c*) #'bc*)
267285
(check-equal? (syntax-property #'b* 'headphone-shaped?) #true)
268286
(check-equal? (syntax-property #'c* 'headphone-shaped?) #false)))
287+
288+
289+
(module+ test
290+
(test-case "syntax-immediate-properties"
291+
292+
(test-case "syntax with no properties"
293+
(define stx #'(a b c))
294+
(define props (syntax-immediate-properties stx))
295+
(check-true (syntax-property-bundle? props))
296+
(check-equal? (syntax-property-bundle-get-immediate-properties props empty-syntax-path)
297+
(hash)))
298+
299+
(test-case "syntax with single property"
300+
(define stx (syntax-property #'(a b c) 'foo 42))
301+
(define props (syntax-immediate-properties stx))
302+
(check-true (syntax-property-bundle? props))
303+
(define immediate (syntax-property-bundle-get-immediate-properties props empty-syntax-path))
304+
(check-equal? (hash-ref immediate 'foo) 42))
305+
306+
(test-case "syntax with multiple properties"
307+
(define stx
308+
(syntax-property
309+
(syntax-property
310+
(syntax-property #'(a b c) 'foo 42)
311+
'bar #true)
312+
'baz "hello"))
313+
(define props (syntax-immediate-properties stx))
314+
(check-true (syntax-property-bundle? props))
315+
(define immediate (syntax-property-bundle-get-immediate-properties props empty-syntax-path))
316+
(check-equal? (hash-ref immediate 'foo) 42)
317+
(check-equal? (hash-ref immediate 'bar) #true)
318+
(check-equal? (hash-ref immediate 'baz) "hello"))
319+
320+
(test-case "only extracts immediate properties, not from subforms"
321+
(define inner-stx (syntax-property #'x 'inner-prop 123))
322+
(define outer-stx
323+
(syntax-property
324+
(datum->syntax #f (list inner-stx #'y) #f)
325+
'outer-prop 456))
326+
(define props (syntax-immediate-properties outer-stx))
327+
(define immediate (syntax-property-bundle-get-immediate-properties props empty-syntax-path))
328+
(check-equal? (hash-ref immediate 'outer-prop #false) 456)
329+
(check-equal? (hash-ref immediate 'inner-prop #false) #false))))
330+
331+
332+
(module+ test
333+
(test-case "syntax-all-properties"
334+
335+
(test-case "syntax with no properties"
336+
(define stx #'(a b c))
337+
(define props (syntax-all-properties stx))
338+
(check-true (syntax-property-bundle? props))
339+
(check-equal? (sequence-length (syntax-property-bundle-entries props)) 0))
340+
341+
(test-case "syntax with property only on root"
342+
(define stx (syntax-property #'(a b c) 'root-prop 42))
343+
(define props (syntax-all-properties stx))
344+
(check-true (syntax-property-bundle? props))
345+
(define root-props (syntax-property-bundle-get-immediate-properties props empty-syntax-path))
346+
(check-equal? (hash-ref root-props 'root-prop) 42))
347+
348+
(test-case "syntax with properties on multiple subforms"
349+
(define a-stx (syntax-property #'a 'a-prop 1))
350+
(define b-stx (syntax-property #'b 'b-prop 2))
351+
(define c-stx (syntax-property #'c 'c-prop 3))
352+
(define stx (datum->syntax #f (list a-stx b-stx c-stx) #f))
353+
(define stx-with-root (syntax-property stx 'root-prop 0))
354+
(define props (syntax-all-properties stx-with-root))
355+
(check-true (syntax-property-bundle? props))
356+
357+
(define root-props (syntax-property-bundle-get-immediate-properties props empty-syntax-path))
358+
(check-equal? (hash-ref root-props 'root-prop) 0)
359+
360+
(define a-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 0))))
361+
(check-equal? (hash-ref a-props 'a-prop) 1)
362+
363+
(define b-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 1))))
364+
(check-equal? (hash-ref b-props 'b-prop) 2)
365+
366+
(define c-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 2))))
367+
(check-equal? (hash-ref c-props 'c-prop) 3))
368+
369+
(test-case "nested syntax with properties"
370+
(define inner-b (syntax-property #'b 'inner-prop 42))
371+
(define inner-c (syntax-property #'c 'inner-prop 99))
372+
(define inner-list (datum->syntax #f (list inner-b inner-c) #f))
373+
(define inner-with-prop (syntax-property inner-list 'list-prop 10))
374+
(define outer (datum->syntax #f (list #'a inner-with-prop #'d) #f))
375+
(define props (syntax-all-properties outer))
376+
377+
(define inner-list-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 1))))
378+
(check-equal? (hash-ref inner-list-props 'list-prop) 10)
379+
380+
(define b-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 1 0))))
381+
(check-equal? (hash-ref b-props 'inner-prop) 42)
382+
383+
(define c-props (syntax-property-bundle-get-immediate-properties props (syntax-path (list 1 1))))
384+
(check-equal? (hash-ref c-props 'inner-prop) 99))))

0 commit comments

Comments
 (0)