Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions private/runtime/binding-spec.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
(struct-out group) ; []
(struct-out nest)
(struct-out nest-one)
(struct-out parallel)
(struct-out nested)
(struct-out suspend)
(struct-out fresh-env-expr-ctx)
Expand Down Expand Up @@ -65,6 +66,7 @@
(struct group [specs] #:transparent)
(struct nest [pvar nonterm spec] #:transparent)
(struct nest-one [pvar nonterm spec] #:transparent)
(struct parallel [pvar nonterm spec] #:transparent)
(struct nested [] #:transparent)
(struct suspend [pvar] #:transparent)
(struct fresh-env-expr-ctx [spec] #:transparent)
Expand Down Expand Up @@ -290,7 +292,17 @@
(match-define (nest-ret done-seq st^) res)

(set-pvar st^ pv (car done-seq))]


[(parallel pv f inner-spec)
(define init-seq (get-pvar st pv))

(define res
(start-nest f init-seq st inner-spec local-scopes #:parallel? #t))

(match-define (nest-ret done-seq st^) res)

(set-pvar st^ pv done-seq)]

[(nested)
(update-nest-state
st
Expand All @@ -305,7 +317,8 @@
; seq is (listof (treeof syntax?))
; inner-spec-st is exp-state?
; inner-spec is spec
(struct nest-call [f seq acc-scopes inner-spec-st inner-spec] #:transparent)
; parallel-scopes is (or/c #f list?) -- list of initial scopes if binding in parallel
(struct nest-call [f seq acc-scopes parallel-scopes inner-spec-st inner-spec] #:transparent)

; seq is (listof (treeof syntax?))
(struct nest-ret [done-seq inner-spec-st^] #:transparent)
Expand Down Expand Up @@ -343,13 +356,15 @@
;; TODO: if the meta-DSL supports binding macros in the future, we may need to add a scope
;; at every nest step rather than only the entry point to account for macros defined in one
;; nest step and used in the next without an intervening new scope.
(define (start-nest f init-seq st inner-spec local-scopes)
(define (start-nest f init-seq st inner-spec local-scopes #:parallel? [parallel? #f])
(with-scope sc
(simple-expand-nest (nest-call f init-seq '() st inner-spec) (cons sc local-scopes))))
(define initial-scopes (cons sc local-scopes))
(define parallel-scopes (if parallel? initial-scopes #f))
(simple-expand-nest (nest-call f init-seq '() parallel-scopes st inner-spec) initial-scopes)))

; nest-call? -> nest-ret?
(define (simple-expand-nest nest-st new-local-scopes)
(match-define (nest-call f seq acc-scopes inner-spec-st inner-spec) nest-st)
(match-define (nest-call f seq acc-scopes parallel-scopes inner-spec-st inner-spec) nest-st)

(define acc-scopes^ (append acc-scopes new-local-scopes))

Expand All @@ -360,8 +375,8 @@
;; Original:
(call-expand-function/nest
f
(add-scopes stx acc-scopes^)
(nest-call f rest acc-scopes^ inner-spec-st inner-spec)))
(add-scopes stx (or parallel-scopes acc-scopes^))
(nest-call f rest acc-scopes^ parallel-scopes inner-spec-st inner-spec)))

(match-define (nest-ret done-seq inner-spec-st^) nest-st^)
(nest-ret (cons stx^ done-seq) inner-spec-st^)]
Expand Down
36 changes: 30 additions & 6 deletions private/syntax/compile/binding-spec.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

;; Elaborated representation; variables are associated with expander-environment information

;; A Pattern VARiable called `id`.
(struct pvar [id info])

(struct with-stx [stx])
Expand All @@ -60,7 +61,8 @@
(struct export-syntax with-stx [pvar transformer-pvar] #:transparent)
(struct export-syntaxes with-stx [pvar transformer-pvar] #:transparent)
(struct nest with-stx [pvar spec] #:transparent)
(struct nest-one with-stx [pvar spec] #:transparent)
(struct nest-one with-stx [pvar spec] #:transparent)
(struct parallel with-stx [pvar spec] #:transparent)
(struct suspend with-stx [pvar] #:transparent)
(struct scope with-stx [spec] #:transparent)
(struct group [specs] #:transparent)
Expand All @@ -80,6 +82,9 @@
[(nest-one stx pv s)
(let ([s^ (map-bspec f s)])
(f (nest-one stx pv s^)))]
[(parallel stx pv s)
(let ([s^ (map-bspec f s)])
(f (parallel stx pv s^)))]
[(scope stx s)
(let ([s^ (map-bspec f s)])
(f (scope stx s^)))]
Expand All @@ -94,6 +99,7 @@
(match spec
[(or (s* nest [spec s])
(s* nest-one [spec s])
(s* parallel [spec s])
(s* scope [spec s]))
(let ([s^ (fold-bspec f s)])
(f spec (list s^)))]
Expand All @@ -109,7 +115,7 @@
; convert surface syntax for a bspec to a structure representation.
(define elaborate-bspec
(syntax-parser
#:datum-literals (scope bind bind-syntax bind-syntaxes import export export-syntax export-syntaxes re-export nest nest-one host)
#:datum-literals (scope bind bind-syntax bind-syntaxes import export export-syntax export-syntaxes re-export nest nest-one parallel host)
[v:nonref-id
(elaborate-ref (attribute v))]
[(bind ~! v:nonref-id ...+)
Expand Down Expand Up @@ -192,6 +198,13 @@
(s* nonterm-rep [variant-info (s* nesting-nonterm-info)])
"nesting nonterminal")
(elaborate-bspec (attribute spec)))]
[(parallel ~! v:nonref-id spec:bspec-term)
(parallel
this-syntax
(elaborate-pvar (attribute v)
(s* nonterm-rep [variant-info (s* nesting-nonterm-info)])
"nesting nonterminal")
(elaborate-bspec (attribute spec)))]
[(host ~! v:nonref-id)
(suspend
this-syntax
Expand Down Expand Up @@ -268,6 +281,7 @@
(s* export [pvar (pvar v _)])
(s* nest [pvar (pvar v _)])
(s* nest-one [pvar (pvar v _)])
(s* parallel [pvar (pvar v _)])
(s* suspend [pvar (pvar v _)]))
(list v)]
[(or (s* bind-syntax [pvar (pvar v1 _)] [transformer-pvar (pvar v2 _)])
Expand Down Expand Up @@ -331,7 +345,7 @@
; one-pass-spec: unscoped-spec
; exporting-spec: (seq (* (or (export _) (export-syntax _ _) (export-syntaxes _ _))) (* (re-export _)) refs+subexps)
; unscoped-spec: refs+subexps
; refs+subexps: (* (or (ref _) (nest _ unscoped-spec) (nest-one _ unscoped-spec) (scope scoped-spec)))
; refs+subexps: (* (or (ref _) (nest _ unscoped-spec) (nest-one _ unscoped-spec) (parallel _ unscoped-spec) (scope scoped-spec)))
; scoped-spec: (seq (* (or (bind-syntax _ _) (bind-syntaxes _ _) (bind _))) (? (rec _)) refs+subexps)
;
; The implementation below separately implements refs+subexps for each context in which it occurs to
Expand Down Expand Up @@ -369,7 +383,8 @@
[(and (s* re-export) (with-stx stx))
(re-export-context-error stx)]
[(or (s* nest [spec s])
(s* nest-one [spec s]))
(s* nest-one [spec s])
(s* parallel [spec s]))
(check-order/unscoped-expression s)]
[(s* scope [spec s])
(check-order/scoped-expression s)]))
Expand Down Expand Up @@ -409,7 +424,8 @@
[(or (s* ref) (s* suspend))
(check-sequence refs+subexps specs)]
[(or (s* nest [spec s])
(s* nest-one [spec s]))
(s* nest-one [spec s])
(s* parallel [spec s]))
(check-order/unscoped-expression s)
(check-sequence refs+subexps specs)]
[(s* scope [spec s])
Expand Down Expand Up @@ -445,7 +461,8 @@
[(or (s* ref) (s* suspend))
(check-sequence refs+subexps specs)]
[(or (s* nest [spec s])
(s* nest-one [spec s]))
(s* nest-one [spec s])
(s* parallel [spec s]))
(check-order/unscoped-expression s)
(check-sequence refs+subexps specs)]
[(s* scope [spec s])
Expand Down Expand Up @@ -504,6 +521,11 @@
[(nonterm-rep (nesting-nonterm-info expander))
(with-syntax ([spec-c (compile-bspec-term/single-pass spec)])
#`(nest-one '#,v #,expander spec-c))])]
[(parallel _ (pvar v info) spec)
(match info
[(nonterm-rep (nesting-nonterm-info expander))
(with-syntax ([spec-c (compile-bspec-term/single-pass spec)])
#`(parallel '#,v #,expander spec-c))])]
[(scope _ spec)
(with-syntax ([spec-c (compile-bspec-term/single-pass spec)])
#'(scope spec-c))]
Expand All @@ -524,6 +546,7 @@
[(or (ref _)
(nest _ _ _)
(nest-one _ _ _)
(parallel _ _ _)
(scope _ _)
(suspend _ _))
no-op]
Expand Down Expand Up @@ -551,6 +574,7 @@
[(or (ref _)
(nest _ _ _)
(nest-one _ _ _)
(parallel _ _ _)
(scope _ _)
(suspend _ _))
(compile-bspec-term/single-pass spec)]
Expand Down
18 changes: 18 additions & 0 deletions scribblings/reference/specifying.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ When a form production's form is used outside of the context of a syntax-spec DS
[spec ...]
(nest spec-variable-id binding-spec)
(nest-one spec-variable-id binding-spec)
(parallel spec-variable-id binding-spec)
(import spec-variable-id ...+)
(export spec-variable-id ...+)
(export-syntax spec-variable-id spec-variable-id)
Expand Down Expand Up @@ -371,6 +372,23 @@ When a form production's form is used outside of the context of a syntax-spec DS
#:binding (nest-one car-pat (nest-one cdr-pat nested))))
]
}
@item{
@racket[parallel] is like @racket[nest], but binds in parallel rather than in sequence. That is, while @racket[nest] allows each sequential spec to reference bindings in previous specs, @racket[parallel] does not. If @racket[nest] is @racket[let*], then @racket[parallel] is like @racket[let].

Example:
@racketblock[
(syntax-spec
(binding-class my-var)
(nonterminal my-expr
n:number
x:my-var
(my-let (b:binding-pair ...) body:my-expr)
#:binding (parallel b body))
(nonterminal/nesting binding-pair (nested)
[x:my-var e:my-expr]
#:binding (scope (bind x) nested)))
]
}
@item{
@racket[(import d)] imports the bindings exported from the sub-expression specified by @racket[d]. @racket[import] must be used inside of a @racket[scope] and must refer to a syntax spec associated with an @tech{exporting nonterminal}.

Expand Down