stxclass: created stxclass collection, with docs

svn: r13255
This commit is contained in:
Ryan Culpepper 2009-01-22 05:50:55 +00:00
parent 49f015d55b
commit eb9fe4847f
17 changed files with 154 additions and 83 deletions

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require (for-syntax scheme/base)
(for-syntax "../stxclass/stxclass.ss")
(for-syntax stxclass)
scheme/list
scheme/contract
"deriv.ss"

View File

@ -1,5 +0,0 @@
#lang setup/infotab
;; Not ready yet
;; (define scribblings '(("stxclass.scrbl")))
(define compile-omit-paths '("test.ss"))

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require (for-template scheme/base
scheme/class)
macro-debugger/stxclass/stxclass)
stxclass)
(provide static-interface?
make-static-interface

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require scheme/class
(for-syntax scheme/base
macro-debugger/stxclass/stxclass
stxclass
"class-ct.ss"))
(provide define-interface
define-interface/dynamic

View File

@ -0,0 +1,3 @@
#lang setup/infotab
(define scribblings '(("stxclass.scrbl")))

View File

@ -36,7 +36,7 @@
;; #:rename internal-id external-id
;; #:with pattern expr
;; #:with clauses are let*-scoped
;; #:where expr
;; #:when expr
;; A HeadDirective is one of
;; #:min nat/#f

View File

@ -14,12 +14,13 @@
(define-syntax-rule (define-pred-stxclass name pred)
(define-basic-syntax-class name
() ;; ([datum 0])
([datum 0])
(lambda (x)
(let ([d (if (syntax? x) (syntax-e x) x)])
(if (pred d)
null ;; (list d)
(fail-sc x #:pattern 'name))))))
(list d)
;; (fail-sc x #:pattern 'name)
#f)))))
(define-pred-stxclass identifier symbol?)
(define-pred-stxclass boolean boolean?)
@ -39,7 +40,8 @@
(lambda (x)
(if (and (identifier? x) (free-identifier=? x (quote-syntax kw)))
null
(fail-sc x #:pattern 'name)))))
;; (fail-sc x #:pattern 'name)
#f))))
(define-kw-stxclass lambda-kw #%lambda)
(define-kw-stxclass define-values-kw define-values)
@ -65,18 +67,20 @@
#:reason "not bound as syntax")))
(let ([value (syntax-local-value x bad)])
(list (syntax-e x) value)))
(fail-sc x
#:pattern 'static
#:reason "not an identifier"))))
;;(fail-sc x
;; #:pattern 'static
;; #:reason "not an identifier")
#f)))
(define-basic-syntax-class (static-of name pred)
([value 0])
(lambda (x name pred)
(let/ec escape
(define (bad)
(escape (fail-sc x
#:pattern 'name
#:reason (format "not bound as ~a" name))))
(escape ;;(fail-sc x
;; #:pattern 'name
;; #:reason (format "not bound as ~a" name))
#f))
(if (identifier? x)
(let ([value (syntax-local-value x bad)])
(unless (pred value) (bad))
@ -95,9 +99,10 @@
(let/ec escape
(define (bad)
(escape
(fail-sc x
#:pattern 'struct-name
#:reason "not bound as a struct name")))
;;(fail-sc x
;; #:pattern 'struct-name
;; #:reason "not bound as a struct name")
#f))
(let ([value (syntax-local-value x bad)])
(unless (struct-info? value) (bad))
(let ([lst (extract-struct-info value)])
@ -115,9 +120,10 @@
r-accessors)
super
(or (null? r-accessors) (not (eq? #f (car r-accessors))))))))))
(fail-sc x
#:pattern 'struct-name
#:reason "not bound as a struct name"))))
;;(fail-sc x
;; #:pattern 'struct-name
;; #:reason "not bound as a struct name")
#f)))
(define-basic-syntax-class expr/local-expand
([expanded 0])
@ -190,7 +196,8 @@
(quote-syntax #,(syntax/loc x (<there>))))
x)
(list x x))
(fail-sc x #:pattern 'expr #:reason "keyword"))))
;;(fail-sc x #:pattern 'expr #:reason "keyword")
#f)))
(define-basic-syntax-class (term parser)
()
@ -201,7 +208,8 @@
(lambda (x p)
(if (p x)
null
(fail-sc x #:pattern 'term/pred))))
;;(fail-sc x #:pattern 'term/pred)
#f)))
;; Aliases

View File

@ -100,7 +100,7 @@
(define (expr:convert-sides sides iattrs main-var k)
(match sides
['() (k iattrs)]
[(cons (struct clause:where (e)) rest)
[(cons (struct clause:when (e)) rest)
(let* ([k-rest (expr:convert-sides rest iattrs main-var k)])
(with-syntax ([(x) (generate-temporaries #'(x))])
#`(let ([x #,(wrap-pattern-body/attrs iattrs 0 e)])

View File

@ -22,7 +22,7 @@
(struct-out splice-pattern)
(struct-out pat:splice-id)
(struct-out head)
(struct-out clause:where)
(struct-out clause:when)
(struct-out clause:with)
get-stxclass
@ -59,7 +59,7 @@
;; An RHSPattern is
;; (make-rhs:pattern stx (listof SAttr) Pattern Env Env (listof SideClause))
(define-struct rhs:pattern (stx attrs pattern decls remap wheres)
(define-struct rhs:pattern (stx attrs pattern decls remap whens)
#:transparent)
;; A Pattern is one of
@ -68,7 +68,7 @@
;; (make-pat:pair <Pattern> Pattern Pattern)
;; (make-pat:seq <Pattern> Pattern Pattern)
;; (make-pat:gseq <Pattern> (listof Head) Pattern)
;; where <Pattern> = stx (listof IAttr) number
;; when <Pattern> = stx (listof IAttr) number
(define-struct pattern (orig-stx attrs depth) #:transparent)
(define-struct (pat:id pattern) (name stxclass args) #:transparent)
(define-struct (pat:datum pattern) (datum) #:transparent)
@ -91,9 +91,9 @@
;; A SideClause is one of
;; (make-clause:with pattern stx)
;; (make-clause:where stx)
;; (make-clause:when stx)
(define-struct clause:with (pattern expr) #:transparent)
(define-struct clause:where (expr) #:transparent)
(define-struct clause:when (expr) #:transparent)
;; make-empty-sc : identifier => SC
;; Dummy stxclass for calculating attributes of recursive stxclasses.
@ -497,7 +497,7 @@
(list (list '#:declare check-id values)
(list '#:rename check-id check-id)
(list '#:with values values)
(list '#:where values)))
(list '#:when values)))
(define-values (chunks rest) (chunk-kw-seq stx directive-table))
(define directives (map cdr chunks))
@ -534,9 +534,9 @@
(let* ([pattern (parse-pattern #'p decls 0)])
(set! rclauses
(cons (make clause:with pattern #'expr) rclauses)))]
[[#:where expr]
[[#:when expr]
(set! rclauses
(cons (make clause:where #'expr) rclauses))]
(cons (make clause:when #'expr) rclauses))]
[_ (void)]))
(for ([literal literals])

View File

@ -1,15 +1,25 @@
#lang scribble/doc
@(require scribble/manual
scribble/struct
(for-label macro-debugger/stxclass/stxclass))
scribble/decode
(for-label scheme/base stxclass))
@(define ellipses @scheme[...])
@(define (TODO . pre-flow)
(make-splice
(cons (bold "TODO: ")
(decode-content pre-flow))))
@title{Parsing Syntax and Syntax Classes}
@defmodule[macro-debugger/stxclass/stxclass]
@defmodule[stxclass]
@bold{Warning: This library is still very volatile! Its interface and
behavior are subject to frequent change. I highly recommend that you
avoid creating PLaneT package that depend on this library.}
@section{Parsing Syntax}
@declare-exporting[macro-debugger/stxclass/stxclass]
@declare-exporting[stxclass]
@defform/subs[(syntax-parse stx-expr maybe-literals clause ...)
([maybe-literals code:blank
@ -27,6 +37,8 @@ matches fail the corresponding clauses' side conditions), a syntax
error is raised. The syntax error indicates the first specific subterm
for which no pattern matches.
@TODO{Allow literal declarations of form @scheme[(_internal-name
_external-name)].}
}
@defform[(syntax-parser maybe-literals clause ...)]{
@ -39,18 +51,18 @@ procedure accepts a single argument, which should be a syntax object.
The grammar of patterns accepted by @scheme[syntax-parse] and
@scheme[syntax-parser] follows:
@schemegrammar*[#:literals (_ ... ...*)
@schemegrammar*[#:literals (_ ...*)
[syntax-pattern
pvar-id
pvar-id:syntax-class-id
literal-id
atomic-datum
(syntax-pattern . syntax-pattern)
(syntax-splice-pattern . syntax-pattern)
(syntax-pattern ... . syntax-pattern)
#| (syntax-splice-pattern . syntax-pattern) |#
(syntax-pattern #,ellipses . syntax-pattern)
((head ...+) ...* . syntax-pattern)]
[syntax-splice-pattern
pvar-id:syntax-splice-class-id]
#| [syntax-splice-pattern
pvar-id:syntax-splice-class-id] |#
[pvar-id
_
id]]
@ -71,8 +83,10 @@ syntax class's attributes are computed for the subterm and bound to
the pattern variables formed by prefixing @scheme[_pvar-id.] to the
name of the attribute. @scheme[_pvar-id] is typically bound to the
matched subterm, but the syntax class can substitute a transformed
subterm instead (for example, @scheme[expr/c] wraps the matched
subterm in a @scheme[contract] expression).
subterm instead.
@;{(for example, @scheme[expr/c] wraps the matched
subterm in a @scheme[contract] expression).}
If @scheme[_pvar-id] is @scheme[_], no pattern variables are bound.
@ -96,6 +110,7 @@ Matches a syntax pair whose head matches the first pattern and whose
tail matches the second.
}
@;{
@specsubform[(syntax-splice-pattern . syntax-pattern)]{
Matches a syntax object which consists of any sequence of syntax
@ -103,7 +118,9 @@ objects matching the splice pattern followed by a tail matching the
given tail pattern.
}
@specsubform[(syntax-pattern ... . syntax-pattern)]{
}
@specsubform[(syntax-pattern #,ellipses . syntax-pattern)]{
Matches a sequence of the first pattern ending in a tail matching the
second pattern.
@ -121,9 +138,10 @@ whose tail recursively matches the whole sequence pattern.
(code:line #:min min-reps)
(code:line #:max max-reps)
(code:line #:mand)
(code:line #:opt)
(code:line #:occurs occurs-pvar-id)
(code:line #:default default-form)])]{
#| (code:line #:opt)
(code:line #:occurs occurs-pvar-id)
(code:line #:default default-form)
|#])]{
Matches a sequence of any combination of the heads ending in a tail
matching the final pattern. The match is subject to constraints
@ -140,7 +158,8 @@ integer.
Requires that no more than @scheme[max-reps] occurrences of the
preceeding head to match. @scheme[max-reps] must be a literal exact
nonnegative integer, and it must be greater than @scheme[min-reps].
nonnegative integer, and it must be greater than or equal to
@scheme[min-reps].
}
@specsubform[#:mand]{
@ -150,13 +169,15 @@ in the preceding head are not bound at a higher ellipsis nesting
depth.
}
@;{
@specsubform[#:opt]{
(Probably a bad idea.)
}
}
}
@;{
The variants of @scheme[_syntax-splice-pattern] follow:
@specsubform[pvar-id:syntax-splice-class-id]{
@ -168,7 +189,7 @@ The name @scheme[_pvar-id] is bound, but not allowed within
expressions or @scheme[syntax] templates (since it does not refer to a
particular syntax object). Only the prefixed attributes of the splice
class are usable.
}
}
Both @scheme[syntax-parse] and @scheme[syntax-parser] support
@ -179,12 +200,12 @@ conditions. The grammar for pattern directives follows:
(code:line #:declare pattern-id syntax-class-id)
(code:line #:declare pattern-id (syntax-class-id expr ...))
(code:line #:with syntax-pattern expr)
(code:line #:where expr)]
(code:line #:when expr)]
@specsubform[(code:line #:declare pvar-id syntax-class-id)]
@specsubform[(code:line #:declare pvar-id (syntax-class-id expr ...))]{
The first form is entirely equivalent to using the
The first form is equivalent to using the
@scheme[_pvar-id:syntax-class-id] form in the pattern (but it is
illegal to use both for a single pattern variable). The
@scheme[#:declare] form may be preferred when writing macro-defining
@ -202,11 +223,11 @@ variable bindings and matches it against the pattern. If the match
succeeds, the new pattern variables are added to the environment for
the evaluation of subsequent side conditions. If the @scheme[#:with]
match fails, the matching process backtracks. Since a syntax object
may match a pattern in several ways, backtracking may try the same
clause multiple times before continuing to the next clause.
may match a pattern in several ways, backtracking may cause the same
clause to be tried multiple times before the next clause is reached.
}
@specsubform[(code:line #:where expr)]{
@specsubform[(code:line #:when expr)]{
Evaluates the @scheme[expr] in the context of all previous pattern
variable bindings. If it produces a false value, the matching process
@ -222,7 +243,7 @@ generalized sequences. It may not be used as an expression.
}
@section{Syntax Classes}
@declare-exporting[macro-debugger/stxclass/stxclass]
@declare-exporting[stxclass]
Syntax classes provide an abstraction mechanism for the specification
of syntax. Basic syntax classes include @scheme[identifier] and
@ -241,11 +262,11 @@ depth is fixed for each syntax class.
@defform*/subs[#:literals (pattern)
[(define-syntax-class name-id stxclass-option ...
stxclass-variant ...)
stxclass-variant ...+)
(define-syntax-class (name-id arg-id ...) stxclass-option ...
stxclass-variant ...)]
stxclass-variant ...+)]
([stxclass-options
(code:line #:description string)
(code:line #:description description)
(code:line #:transparent)]
[stxclass-variant
(pattern syntax-pattern pattern-directive ...)])]{
@ -261,13 +282,19 @@ present in every variant. Each such attribute must be defined with the
same ellipsis nesting depth and the same sub-attributes in each
component.
@specsubform[(code:line #:description string)]{
@TODO{Eliminate attribute inference, require explicit attribute
declaration?}
Specifies a string to use in error messages involving the syntax
class. For example, if a term is rejected by the syntax class, an
error of the form @scheme["expected <description>"] may be generated.
@specsubform[(code:line #:description description)]{
The @scheme[description] argument must be a string literal. It is used
in error messages involving the syntax class. For example, if a term
is rejected by the syntax class, an error of the form
@scheme["expected <description>"] may be generated.
If absent, the name of the syntax class is used instead.
@TODO{Allow string expressions with parameters in scope?}
}
@specsubform[#:transparent]{
@ -277,7 +304,7 @@ structure of the syntax class.
}
@specsubform/subs[#:literals (pattern)
(pattern syntax-pattern pattern-directive ...)
(pattern syntax-pattern stxclass-pattern-directive ...)
([stxclass-pattern-directive
pattern-directive
(code:line #:rename internal-id external-id)])]{
@ -305,13 +332,16 @@ syntax class and forward references to syntax classes defined in the
same scope are allowed. For the purpose of calculating provided
attributes, recursive and forward syntax-class references generate no
nested attributes. The full set of attributes is available, however,
to @scheme[#:with] and @scheme[#:where] expressions.
to @scheme[#:with] and @scheme[#:when] expressions.
This treatment of recursive and forward references prevents infinitely
nested attributes.
}
@TODO{Eliminate attribute inference. Explicit attribute declaration
eliminates infinitely nested attributes just as well.}
}
@;{
@defform*[[(define-syntax-splice-class (name-id arg-id ...) stxclass-body)
(define-syntax-splice-class name-id stxclass-body)]]{
@ -332,6 +362,7 @@ match only proper lists:
((head ...+) ...* . proper-list-pattern)]
}
}
@defidform[pattern]{
@ -357,13 +388,17 @@ syntax-class parameterization arguments. To indicate success, the
parser should return a list of attribute values, one for each
attribute listed. (For example, a parser for a syntax class that
defines no attributes returns the empty list when it succeeds.) To
indicate failure, the parser procedure should return the result of
calling @scheme[fail-sc].
indicate failure, the parser procedure should return @scheme[#f].
The parser procedure is encouraged to avoid side-effects.
}
@TODO{Add support for better error reporting within basic syntax
class.}
@TODO{Remove this form in favor of new stxclass-variant form.}
}
@;{
@defform[(define-basic-syntax-class* (name-id arg-id ...)
([attr-id attr-depth] ...)
parser-expr)]{
@ -379,8 +414,10 @@ Transforming matched syntax is useful for implementing syntax classes
that add interpretation or constraints to expressions, such as
@scheme[expr/c], which imposes run-time contracts on expressions.
}
}
@;{
@defform[(attrs-of syntax-class-id)]{
For debugging. Returns a representation of the attributes provided by
@ -395,10 +432,11 @@ the @scheme[arg-expr]s) on the syntax object produced by
@scheme[stx-expr].
}
}
@section{Library syntax classes}
@declare-exporting[macro-debugger/stxclass/stxclass]
@declare-exporting[stxclass]
@(define-syntax-rule (defstxclass name . pre-flows)
(defidform name . pre-flows))
@ -406,7 +444,13 @@ the @scheme[arg-expr]s) on the syntax object produced by
@(define-syntax-rule (defstxclass* (name arg ...) . pre-flows)
(defform (name arg ...) . pre-flows))
The following basic syntax classes are defined:
@defstxclass[expr]{
Matches anything except a keyword literal (to distinguish expressions
from the start of a keyword argument sequence). Does not expand or
otherwise inspect the term.
}
@deftogether[(
@defstxclass[identifier]
@ -418,15 +462,20 @@ The following basic syntax classes are defined:
@defstxclass[integer]
@defstxclass[exact-integer]
@defstxclass[exact-nonnegative-integer]
@defstxclass[exact-positive-integer])]
@defstxclass[exact-positive-integer])]{
Match syntax satisfying the corresponding predicates.
}
Two of the above have short aliases:
@defstxclass[id]{ Same as @scheme[identifier]. }
@defstxclass[nat]{ Same as @scheme[exact-nonnegative-integer]. }
The following syntax classes mirror parts of the macro API. They
may only be used in phase 1 expressions.
The following syntax classes mirror parts of the macro API. They may
only be used during transformation (when @scheme[syntax-transforming?]
returns true). Otherwise they may raise an error.
@defstxclass[static]{
@ -436,6 +485,17 @@ static information (see @scheme[syntax-local-value]). Attribute
}
@defform[(static-of predicate description)]{
Refines @scheme[static]: matches identifiers that are bound in the
syntactic environment to static information satisfying the given
@scheme[predicate]. Attribute @scheme[_value] contains the value the
name is bound to. The @scheme[description] argument is used for error
reporting.
}
@;{
@defstxclass[struct-name]{
Matches identifiers bound to static struct information. Attributes are
@ -443,7 +503,8 @@ Matches identifiers bound to static struct information. Attributes are
@scheme[(_accessor ...)], @scheme[_super], and @scheme[_complete?].
}
}
@;{
@defstxclass[expr/local-expand]{
Matches any term and @scheme[local-expand]s it as an expression with
@ -454,10 +515,13 @@ an empty stop list. Attribute @scheme[_expanded] is the expanded form.
@defstxclass[expr/head-local-expand]
@defstxclass[block/head-local-expand]
@defstxclass[internal-definitions]
}
@;{
@defform[(expr/c contract-expr-stx)]{
Accepts any term and returns as the match that term wrapped in a
@scheme[contract] expression enforcing @scheme[contract-expr-stx].
}
}

View File

@ -21,6 +21,7 @@
"srfi"
"srpersist"
"stepper"
"stxclass"
"syntax-color"
"typed-scheme"
"units"

View File

@ -2,8 +2,8 @@
(require (planet "test.ss" ("schematics" "schemeunit.plt" 2 9))
(planet "graphical-ui.ss" ("schematics" "schemeunit.plt" 2 9))
macro-debugger/stxclass/stxclass
(for-syntax scheme/base macro-debugger/stxclass/stxclass))
stxclass
(for-syntax scheme/base stxclass))
;; Testing stuff
@ -214,7 +214,7 @@
(define-syntax-class sorted
(pattern (n:nat ...)
#:where (sorted? (syntax->datum #'(n ...)))))
#:when (sorted? (syntax->datum #'(n ...)))))
(define (sorted? ns)
(define (loop ns min)

View File

@ -11,7 +11,7 @@
"subtype.ss"
"type-utils.ss"
scheme/promise
(for-syntax macro-debugger/stxclass/stxclass)
(for-syntax stxclass)
(for-syntax scheme/base)
(for-template scheme/base scheme/contract scheme/tcp))