Add docs
This commit is contained in:
parent
c3ddab4f59
commit
3d9cef39a0
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,6 +1,8 @@
|
|||
compiled/*
|
||||
**/compiled
|
||||
*.bak
|
||||
*.html
|
||||
*.css
|
||||
*.js
|
||||
*.2
|
||||
*~
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
(with-derived-ids #'name ([?-expander-type "~a-expander-type"]
|
||||
[make-?-expander "make-~a-expander"]
|
||||
[?-expander? "~a-expander?"]
|
||||
[?-expander-stx? "~a-expander-stx?"]
|
||||
[define-?-expander "define-~a-expander"]
|
||||
[expand-all-?-expanders "expand-all-~a-expanders"])
|
||||
#'(begin
|
||||
|
@ -22,8 +21,6 @@
|
|||
(expander ?-expander-type transformer))
|
||||
(define-for-syntax (?-expander? v)
|
||||
(expander-of-type? ?-expander-type v))
|
||||
(define-for-syntax (?-expander-stx? v)
|
||||
(expander-stx-of-type? ?-expander-type v))
|
||||
(define-syntax-rule (define-?-expander expander-name transformer)
|
||||
(define-syntax expander-name (make-?-expander transformer)))
|
||||
(define-for-syntax (expand-all-?-expanders stx)
|
||||
|
|
16
generic-syntax-expanders/define-scoped-transformers.rkt
Normal file
16
generic-syntax-expanders/define-scoped-transformers.rkt
Normal file
|
@ -0,0 +1,16 @@
|
|||
#lang racket
|
||||
|
||||
(require (for-syntax "scoped-transformers.rkt"))
|
||||
|
||||
(provide define-syntax-with-scoped-pre-transformers)
|
||||
|
||||
(define-syntax define-syntax-with-scoped-pre-transformers
|
||||
(syntax-rules ()
|
||||
[(_ name ([stx-lens pre-transformer] ...) transformer-expr)
|
||||
(define-syntax name
|
||||
(with-scoped-pre-transformers transformer-expr
|
||||
(list (list stx-lens pre-transformer) ...)))]
|
||||
[(_ (name stx) ([stx-lens pre-transformer] ...) transformer-body ...)
|
||||
(define-syntax-with-scoped-pre-transformers name
|
||||
([stx-lens pre-transformer] ...)
|
||||
(lambda (stx) transformer-body ...))]))
|
34
generic-syntax-expanders/docs/define-expanders.scrbl
Normal file
34
generic-syntax-expanders/docs/define-expanders.scrbl
Normal file
|
@ -0,0 +1,34 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"defpredicate.rkt"
|
||||
"module-title.rkt"
|
||||
(for-label racket/base
|
||||
generic-syntax-expanders/expanders
|
||||
generic-syntax-expanders/expander-types
|
||||
generic-syntax-expanders/define-expanders))
|
||||
|
||||
@module-title[generic-syntax-expanders/define-expanders]{Defining Generic Syntax Expanders}
|
||||
|
||||
This module provides a high-level API for creating generic
|
||||
expanders for use with other macros.
|
||||
|
||||
@defform[(define-expander-type id)]{
|
||||
Creates an expander type and binds several derived values
|
||||
for working with the expander type:
|
||||
@itemlist[
|
||||
@item{@code{id-expander-type} - a new unique @racket[expander-type?]
|
||||
bound at phase level 1}
|
||||
@item{@code{make-id-expander} - a procedure bound at phase level 1
|
||||
that accepts a transformer procedure and returns an @racket[expander?]
|
||||
with @code{id-expander-type}}
|
||||
@item{@code{id-expander?} - a predicate bound at phase level 1
|
||||
recognizing expanders produced by @code{make-id-expander}}
|
||||
@item{@code{define-id-expander?} - a syntactic form at phase level
|
||||
0 that takes an identifier and a transformer procedure and binds the
|
||||
identifier as a @code{id-expander?} for use in a transformer
|
||||
environment}
|
||||
@item{@code{expand-all-id-expanders} - a procedure bound at phase
|
||||
level 1 that's equivalent to @racket[expand-all-expanders-of-type] with
|
||||
the @code{id-expander-type} as the type argument}
|
||||
]}
|
|
@ -0,0 +1,20 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"module-title.rkt"
|
||||
(for-label racket/base
|
||||
lenses
|
||||
generic-syntax-expanders/scoped-transformers
|
||||
generic-syntax-expanders/define-scoped-transformers))
|
||||
|
||||
@module-title[generic-syntax-expanders/define-scoped-transformers]{Lens Scoped Syntax Transformers - Definition Form}
|
||||
|
||||
Syntax definition forms built on @racket[with-scoped-pre-transformer]
|
||||
and friends.
|
||||
|
||||
@defform[(define-syntax-with-scoped-pre-transformers id
|
||||
([stx-lens pre-transformer] ...)
|
||||
transformer-expr)]{
|
||||
Binds @racket[id] as a syntax transformer equivalent to
|
||||
@racket[with-scoped-pre-transformers transformer-expr ([stx-lens pre-transformer] ...)].
|
||||
}
|
8
generic-syntax-expanders/docs/defpredicate.rkt
Normal file
8
generic-syntax-expanders/docs/defpredicate.rkt
Normal file
|
@ -0,0 +1,8 @@
|
|||
#lang racket
|
||||
|
||||
(require scribble/manual)
|
||||
|
||||
(provide defpredicate)
|
||||
|
||||
(define-syntax-rule (defpredicate id pre-flow ...)
|
||||
(defthing #:kind "predicate" id predicate/c pre-flow ...))
|
11
generic-syntax-expanders/docs/example-evaluator.rkt
Normal file
11
generic-syntax-expanders/docs/example-evaluator.rkt
Normal file
|
@ -0,0 +1,11 @@
|
|||
#lang racket
|
||||
|
||||
(require scribble/eval)
|
||||
|
||||
(provide package-examples)
|
||||
|
||||
(define generic-syntax-expanders-eval (make-base-eval))
|
||||
(generic-syntax-expanders-eval '(require generic-syntax-expanders))
|
||||
|
||||
(define-syntax-rule (package-examples example-body ...)
|
||||
(examples #:eval generic-syntax-expanders-eval example-body ...))
|
56
generic-syntax-expanders/docs/expander-types.scrbl
Normal file
56
generic-syntax-expanders/docs/expander-types.scrbl
Normal file
|
@ -0,0 +1,56 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"defpredicate.rkt"
|
||||
"module-title.rkt"
|
||||
(for-label racket/base
|
||||
generic-syntax-expanders/expanders
|
||||
generic-syntax-expanders/expander-types))
|
||||
|
||||
@module-title[generic-syntax-expanders/expander-types]{Expander Types}
|
||||
|
||||
Under the hood, each generic expander defined with this library has
|
||||
an associated @italic{expander type}. Syntax transformers built
|
||||
with this library examine this type to determine whether or not
|
||||
they should expand them.
|
||||
|
||||
@defpredicate[expander-type?]{
|
||||
A predicate for values produced by @racket[make-expander-type] and
|
||||
variants.
|
||||
@package-examples[
|
||||
(expander-type? (make-expander-type))
|
||||
(expander-type? 'foo)
|
||||
]}
|
||||
|
||||
@defproc[(make-expander-type) expander-type?]{
|
||||
Creates a unique @racket[expander-type?] for use in defining a new
|
||||
kind of generic expander.
|
||||
@package-examples[
|
||||
(make-expander-type)
|
||||
]}
|
||||
|
||||
@defproc[(make-union-expander-type [type expander-type?] ...+) expander-type?]{
|
||||
Creates a union @racket[expander-type?]. This union type includes
|
||||
all of the given types, as well as any union type of a subset of
|
||||
the given types.
|
||||
@package-examples[
|
||||
(make-union-expander-type (make-expander-type) (make-expander-type))
|
||||
]}
|
||||
|
||||
@defproc[(expander-type-includes? [type-1 expander-type?] [type-2 expander-type?]) boolean?]{
|
||||
Returns @racket[#t] if the two types are either identical, or if either
|
||||
type is a union type that contains the other, or if both types are
|
||||
union types and contain a nonempty intersection. Returns @racket[#f]
|
||||
otherwise.
|
||||
@package-examples[
|
||||
(define A (make-expander-type))
|
||||
(define B (make-expander-type))
|
||||
(define C (make-expander-type))
|
||||
(expander-type-includes? A A)
|
||||
(expander-type-includes? B C)
|
||||
(define AB (make-union-expander-type A B))
|
||||
(define BC (make-union-expander-type B C))
|
||||
(expander-type-includes? AB A)
|
||||
(expander-type-includes? AB C)
|
||||
(expander-type-includes? AB BC)
|
||||
]}
|
45
generic-syntax-expanders/docs/expanders.scrbl
Normal file
45
generic-syntax-expanders/docs/expanders.scrbl
Normal file
|
@ -0,0 +1,45 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"defpredicate.rkt"
|
||||
"module-title.rkt"
|
||||
(for-label racket/base
|
||||
generic-syntax-expanders/expanders
|
||||
generic-syntax-expanders/expander-types))
|
||||
|
||||
@module-title[generic-syntax-expanders/expanders]{Expanders And Transformers}
|
||||
|
||||
Generic expanders are implemented as values of the @racket[expander?] struct
|
||||
bound with @racket[define-syntax], that store both a type and a transformer
|
||||
procedure. Future versions of this library may support storing an additional
|
||||
transformer for use outside expander-contexts in normal syntax parsing. This
|
||||
could be used for better error messages, or for an expander meant to have
|
||||
meaning in both a particularly typed expansion context and a normal expression
|
||||
expansion context.
|
||||
|
||||
@defstruct[expander ([type expander-type?] [transformer (-> syntax? syntax?)])]{
|
||||
A structure type for generic syntax expanders. A generic syntax expander
|
||||
has an associated @italic{type} and @italic{transformer}. The transformer
|
||||
can be any arbitrary function that accepts a syntax object in the same
|
||||
manner a transformer given to @racket[define-syntax] would behave.
|
||||
}
|
||||
|
||||
@defproc[(expander-of-type? [type expander-type?] [expander expander?]) boolean?]{
|
||||
Returns @racket[#t] if the @racket[expander] has type @racket[type],
|
||||
according to the semantics of @racket[expander-type-includes?], and
|
||||
returns @racket[#f] otherwise.
|
||||
@package-examples[
|
||||
(define A (make-expander-type))
|
||||
(define exp (expander A (λ (stx) stx)))
|
||||
(expander-of-type? A exp)
|
||||
]}
|
||||
|
||||
@defproc[(expand-stx-tree-with-expanders-of-type [type expander-type?] [syntax syntax?]) syntax?]{
|
||||
Recursively searches through @racket[syntax] for identifiers bound to
|
||||
generic syntax expanders of the given type. When an expander is found,
|
||||
its transformer is called with the given syntax value of its location
|
||||
in the tree. The returned syntax object with have all expanders of the
|
||||
given type fully expanded, but nothing else will be expanded. Due to
|
||||
how expanders are bound to identifiers, this procedure can only be
|
||||
called in a transformer environment.
|
||||
}
|
32
generic-syntax-expanders/docs/generic-syntax-expanders.scrbl
Normal file
32
generic-syntax-expanders/docs/generic-syntax-expanders.scrbl
Normal file
|
@ -0,0 +1,32 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"defpredicate.rkt"
|
||||
"module-title.rkt"
|
||||
"source-code.rkt"
|
||||
(for-label racket/base
|
||||
racket/match
|
||||
generic-syntax-expanders))
|
||||
|
||||
@module-title[generic-syntax-expanders]{Generic Syntax Expanders}
|
||||
@author[@author+email["Jack Firth" "jackhfirth@gmail.com"]]
|
||||
|
||||
This library provides forms to define @italic{generic syntax
|
||||
expanders}. These are essentially macros that have no meaning
|
||||
on their own, but other macros can be told to expand all
|
||||
generic syntax expanders of some type in some portion of
|
||||
their body before themselves expanding. This is similar to
|
||||
how Racket's built in @racket[match] form has @italic{match
|
||||
expanders}, which allows the grammar of the @racket[match]
|
||||
form to be extended with custom match expanders using
|
||||
@racket[define-match-expander]. This library generalizes
|
||||
the concept, making complex macros more composable and
|
||||
extensible.
|
||||
|
||||
@source-code{https://github.com/jackfirth/generic-syntax-expanders}
|
||||
|
||||
@include-section{expanders.scrbl}
|
||||
@include-section{expander-types.scrbl}
|
||||
@include-section{define-expanders.scrbl}
|
||||
@include-section{scoped-transformers.scrbl}
|
||||
@include-section{define-scoped-transformers.scrbl}
|
10
generic-syntax-expanders/docs/module-title.rkt
Normal file
10
generic-syntax-expanders/docs/module-title.rkt
Normal file
|
@ -0,0 +1,10 @@
|
|||
#lang racket
|
||||
|
||||
(require scribble/manual)
|
||||
|
||||
(provide module-title)
|
||||
|
||||
(define-syntax-rule (module-title id title-text pre-flow ...)
|
||||
(begin
|
||||
(title title-text)
|
||||
(defmodule id pre-flow ...)))
|
44
generic-syntax-expanders/docs/scoped-transformers.scrbl
Normal file
44
generic-syntax-expanders/docs/scoped-transformers.scrbl
Normal file
|
@ -0,0 +1,44 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "example-evaluator.rkt"
|
||||
"module-title.rkt"
|
||||
(for-label racket/base
|
||||
lenses
|
||||
generic-syntax-expanders/define-expanders
|
||||
generic-syntax-expanders/scoped-transformers))
|
||||
|
||||
@module-title[generic-syntax-expanders/scoped-transformers]{Lens Scoped Syntax Transformers}
|
||||
|
||||
This module uses the @racket[lenses] package to create syntax transformers
|
||||
that affect only some small subpiece of a syntax object and compose them
|
||||
with other transformers. This allows for the creation of a macro that cedes
|
||||
control to other macros to pre-expand parts of its body before the macro
|
||||
expands. Combined with the syntax transformer produced by @racket[define-expander-type],
|
||||
this makes it easy to define a macro that expands all instances of a generic
|
||||
expander type in a specific subpiece of its body, turning it into an
|
||||
extensible macro.
|
||||
|
||||
@defproc[((with-scoped-pre-transformer
|
||||
[transformer (-> syntax? syntax?)]
|
||||
[stx-lens (lens/c syntax? syntax?)]
|
||||
[pre-transformer (-> syntax? syntax?)])
|
||||
[stx syntax?])
|
||||
syntax?]{
|
||||
Transformers @racket[stx] in two passes. First, the piece of @racket[stx]
|
||||
that @racket[stx-lens] views is transformed with @racket[pre-transformer].
|
||||
Then, the entire resulting syntax object is transformed with @racket[transformer].
|
||||
}
|
||||
|
||||
@defproc[((with-scoped-pre-transformers
|
||||
[transformer (-> syntax? syntax?)]
|
||||
[pre-transformer-lens-pairs
|
||||
(listof (list/c (lens/c syntax? syntax?)
|
||||
(-> syntax? syntax?)))])
|
||||
[stx syntax?])
|
||||
syntax?]{
|
||||
Similar to @racket[with-scoped-pre-transformer]. Given @racket[pre-transformer-lens-pairs],
|
||||
a list of pairs of lenses and transformers, @racket[transformer] is wrapped
|
||||
with @racket[with-scoped-pre-transformer] with the pair's pre-transformer
|
||||
and lens. The last pair in @racket[pre-transformer-lens-pairs] is applied
|
||||
to @racket[stx] first.
|
||||
}
|
9
generic-syntax-expanders/docs/source-code.rkt
Normal file
9
generic-syntax-expanders/docs/source-code.rkt
Normal file
|
@ -0,0 +1,9 @@
|
|||
#lang racket
|
||||
|
||||
(require scribble/manual
|
||||
scribble/text)
|
||||
|
||||
(provide source-code)
|
||||
|
||||
(define (source-code link)
|
||||
(list "Source code can be found at " (url link)))
|
|
@ -8,7 +8,7 @@
|
|||
(contract-out
|
||||
[expander-type? predicate/c]
|
||||
[make-expander-type (-> expander-type?)]
|
||||
[make-union-expander-type (->* (expander-type?) () #:rest expander-type? expander-type?)]
|
||||
[make-union-expander-type (->* (expander-type?) () #:rest (listof expander-type?) expander-type?)]
|
||||
[expander-type-includes? (-> expander-type? expander-type? boolean?)]))
|
||||
|
||||
(define (type-includes? symtree-type1 symtree-type2)
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(provide (struct-out expander)
|
||||
(contract-out
|
||||
[expander-of-type? (-> expander-type? expander? boolean?)]
|
||||
[expander-stx-of-type? (-> expander-type? expander-stx? boolean?)]
|
||||
[expand-syntax-tree-with-expanders-of-type (-> expander-type? syntax? syntax?)]))
|
||||
|
||||
(define (maybe-syntax-local-value stx)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang info
|
||||
|
||||
(define name "package-name")
|
||||
(define scribblings '(("package-name.scrbl" ())))
|
||||
(define name "generic-syntax-expanders")
|
||||
(define scribblings '(("docs/generic-syntax-expanders.scrbl" ())))
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
(require mischief)
|
||||
|
||||
(require/provide "define-expanders.rkt"
|
||||
"scoped-transformers.rkt")
|
||||
(require/provide "expander-types.rkt"
|
||||
"expanders.rkt"
|
||||
"define-expanders.rkt"
|
||||
"scoped-transformers.rkt"
|
||||
"define-scoped-transformers.rkt")
|
||||
|
|
|
@ -1,28 +1,16 @@
|
|||
#lang racket
|
||||
|
||||
(require (for-syntax racket/match
|
||||
lenses))
|
||||
(require racket/match
|
||||
lenses)
|
||||
|
||||
(provide define-syntax-with-scoped-pre-transformers
|
||||
(for-syntax with-scoped-pre-transformer
|
||||
with-scoped-pre-transformers))
|
||||
(provide with-scoped-pre-transformer
|
||||
with-scoped-pre-transformers)
|
||||
|
||||
(define-for-syntax ((with-scoped-pre-transformer transformer stx-lens pre-transformer) stx)
|
||||
(define ((with-scoped-pre-transformer transformer stx-lens pre-transformer) stx)
|
||||
(transformer (lens-transform stx-lens pre-transformer stx)))
|
||||
|
||||
(define-for-syntax (with-scoped-pre-transformers transformer pre-transformer-lens-pairs)
|
||||
(define (with-scoped-pre-transformers transformer pre-transformer-lens-pairs)
|
||||
(match pre-transformer-lens-pairs
|
||||
['() transformer]
|
||||
[(list (list stx-lens pre-transformer) rest ...)
|
||||
(with-scoped-pre-transformers (with-scoped-pre-transformer stx-lens transformer) rest)]))
|
||||
|
||||
(define-syntax define-syntax-with-scoped-pre-transformers
|
||||
(syntax-rules ()
|
||||
[(_ name ([stx-lens pre-transformer] ...) transformer-expr)
|
||||
(define-syntax name
|
||||
(with-scoped-pre-transformers transformer-expr
|
||||
(list (list stx-lens pre-transformer) ...)))]
|
||||
[(_ (name stx) ([stx-lens pre-transformer] ...) transformer-body ...)
|
||||
(define-syntax-with-scoped-pre-transformers name
|
||||
([stx-lens pre-transformer] ...)
|
||||
(lambda (stx) transformer-body ...))]))
|
||||
|
|
Loading…
Reference in New Issue
Block a user