Skip to content

Commit 5c2e059

Browse files
Copilotjackfirth
andcommitted
WIP: Expansion context analyzer implementation
Co-authored-by: jackfirth <[email protected]>
1 parent 8c3d625 commit 5c2e059

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#lang resyntax/test
2+
3+
4+
require: resyntax/default-recommendations/analyzers/expansion-context-analyzer expansion-context-analyzer
5+
header: - #lang racket/base
6+
7+
8+
analysis-test: "code in a module is in a module context"
9+
- (+ 1 2 3)
10+
@inspect - (+ 1 2 3)
11+
@property expansion-context
12+
@assert module
13+
14+
15+
analysis-test: "function arguments are in an expression context"
16+
- (+ 1 2 3)
17+
@inspect - 2
18+
@property expansion-context
19+
@assert expression
20+
21+
22+
analysis-test: "code in a function body is in an internal definition context"
23+
--------------------
24+
(define (f)
25+
(+ 1 2 3))
26+
--------------------
27+
@inspect - (+ 1 2 3)
28+
@property expansion-context
29+
@assert internal-definition
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#lang racket/base
2+
3+
4+
(require racket/contract/base)
5+
6+
7+
(provide
8+
(contract-out
9+
[expansion-context-analyzer expansion-analyzer?]))
10+
11+
12+
(require racket/stream
13+
rebellion/streaming/transducer
14+
resyntax/private/analyzer
15+
resyntax/private/syntax-path
16+
resyntax/private/syntax-property-bundle
17+
resyntax/private/syntax-traversal
18+
syntax/parse)
19+
20+
21+
;@----------------------------------------------------------------------------------------------------
22+
23+
24+
(define (annotate-expansion-contexts expanded-stx)
25+
(let loop ([expanded-stx expanded-stx] [phase 0])
26+
(syntax-search expanded-stx
27+
#:literal-sets ([kernel-literals #:phase phase])
28+
29+
;; Phase mismatch - recurse with correct phase
30+
[(id:id _ ...)
31+
#:do [(define id-phase (syntax-property (attribute id) 'phase))]
32+
#:when (not (equal? id-phase phase))
33+
(loop this-syntax id-phase)]
34+
35+
;; Skip quote-syntax - no expansion context inside
36+
[(quote-syntax _) (stream)]
37+
38+
;; Forms directly under #%module-begin are in module context
39+
[(#%module-begin form ...)
40+
(for/stream ([form-stx (in-list (attribute form))])
41+
(define path (syntax-property form-stx 'expansion-path))
42+
(and path (syntax-property-entry path 'expansion-context 'module)))]
43+
44+
;; Body forms of lambda are in internal-definition context
45+
[(lambda formals body ...+)
46+
(for/stream ([body-stx (in-list (attribute body))])
47+
(define path (syntax-property body-stx 'expansion-path))
48+
(and path (syntax-property-entry path 'expansion-context 'internal-definition)))]
49+
50+
;; Body forms of case-lambda are in internal-definition context
51+
[(case-lambda [formals body ...+] ...)
52+
(for*/stream ([bodies (in-list (attribute body))]
53+
[body-stx (in-list bodies)])
54+
(define path (syntax-property body-stx 'expansion-path))
55+
(and path (syntax-property-entry path 'expansion-context 'internal-definition)))]
56+
57+
;; Body forms of let-values and letrec-values are in internal-definition context
58+
[(~or (let-values ([vars rhs] ...) body ...+)
59+
(letrec-values ([vars rhs] ...) body ...+))
60+
(stream-append
61+
;; RHS expressions are in expression context
62+
(for/stream ([rhs-stx (in-list (attribute rhs))])
63+
(define path (syntax-property rhs-stx 'expansion-path))
64+
(and path (syntax-property-entry path 'expansion-context 'expression)))
65+
;; Body forms are in internal-definition context
66+
(for/stream ([body-stx (in-list (attribute body))])
67+
(define path (syntax-property body-stx 'expansion-path))
68+
(and path (syntax-property-entry path 'expansion-context 'internal-definition))))]
69+
70+
;; Subforms of #%plain-app (function applications) are in expression context
71+
[(app-id:id subform ...)
72+
#:when (free-identifier=? (attribute app-id) #'#%plain-app)
73+
(stream-filter
74+
values
75+
(for/stream ([subform-stx (in-list (attribute subform))])
76+
(define path (syntax-property subform-stx 'expansion-path))
77+
(and path (syntax-property-entry path 'expansion-context 'expression))))])))
78+
79+
80+
(define expansion-context-analyzer
81+
(make-expansion-analyzer
82+
#:name 'expansion-context-analyzer
83+
(λ (expanded-stx)
84+
(define labeled-stx (syntax-label-paths expanded-stx 'expansion-path))
85+
(transduce (annotate-expansion-contexts labeled-stx)
86+
#:into into-syntax-property-bundle))))

0 commit comments

Comments
 (0)