diff --git a/collects/stxclass/main.ss b/collects/stxclass/main.ss index b8e06462a2..f55c6ba21a 100644 --- a/collects/stxclass/main.ss +++ b/collects/stxclass/main.ss @@ -17,6 +17,8 @@ with-patterns attribute + this-syntax + current-expression current-macro-name diff --git a/collects/stxclass/private/codegen.ss b/collects/stxclass/private/codegen.ss index 7d9d458f03..81727b614f 100644 --- a/collects/stxclass/private/codegen.ss +++ b/collects/stxclass/private/codegen.ss @@ -14,7 +14,10 @@ "../util.ss") (provide/contract [parse:rhs (rhs? (listof sattr?) (listof identifier?) . -> . syntax?)] - [parse:clauses (syntax? identifier? identifier? . -> . syntax?)]) + [parse:clauses (syntax? identifier? identifier? . -> . syntax?)] + [announce-failures? parameter?]) + +(define announce-failures? (make-parameter #f)) ;; parse:rhs : RHS (listof SAttr) (listof identifier) -> stx ;; Takes a list of the relevant attrs; order is significant! @@ -27,15 +30,16 @@ #,(if (rhs-transparent? rhs) #`(make-failed x expected frontier frontier-stx) #'#f)) - #,(let ([pks (rhs->pks rhs relsattrs #'x)]) - (unless (pair? pks) - (wrong-syntax (rhs-orig-stx rhs) - "syntax class has no variants")) - (parse:pks (list #'x) - (list (empty-frontier #'x)) - #'fail-rhs - (list #f) - pks))))] + (syntax-parameterize ((this-syntax (make-rename-transformer #'x))) + #,(let ([pks (rhs->pks rhs relsattrs #'x)]) + (unless (pair? pks) + (wrong-syntax (rhs-orig-stx rhs) + "syntax class has no variants")) + (parse:pks (list #'x) + (list (empty-frontier #'x)) + #'fail-rhs + (list #f) + pks)))))] [(rhs:basic? rhs) (rhs:basic-parser rhs)])) @@ -140,6 +144,8 @@ [fstx-expr (frontier->fstx-expr fce)]) #`(let ([failcontext fc-expr] [failcontext-syntax fstx-expr]) + #,(when (announce-failures?) + #`(printf "failing on ~s\n reason: ~s\n" x p)) (k x p failcontext failcontext-syntax)))) ;; Parsing diff --git a/collects/stxclass/private/debug.ss b/collects/stxclass/private/debug.ss new file mode 100644 index 0000000000..670ba1eb8f --- /dev/null +++ b/collects/stxclass/private/debug.ss @@ -0,0 +1,15 @@ + +#lang scheme/base +(require (for-syntax scheme/base) + (for-syntax "codegen.ss")) + +(provide announce-parse-failures) + +(define-syntax (announce-parse-failures stx) + (syntax-case stx () + [(_ b) + (begin (announce-failures? (and (syntax-e #'b) #t)) + #'(void))] + [(_) + #'(announce-failures #t)])) + diff --git a/collects/stxclass/private/lib.ss b/collects/stxclass/private/lib.ss index 6497a307e4..5f2906f1f7 100644 --- a/collects/stxclass/private/lib.ss +++ b/collects/stxclass/private/lib.ss @@ -13,13 +13,10 @@ (provide (all-defined-out)) (define-syntax-rule (define-pred-stxclass name pred) - (define-basic-syntax-class name - ([datum 0]) - (lambda (x) - (let ([d (if (syntax? x) (syntax-e x) x)]) - (if (pred d) - (list d) - #f))))) + (define-syntax-class name #:attributes ([datum 0]) + (pattern x + #:with datum (if (syntax? #'x) (syntax-e #'x) #'x) + #:when (pred (attribute datum))))) (define-pred-stxclass identifier symbol?) (define-pred-stxclass boolean boolean?) @@ -33,160 +30,105 @@ (define-pred-stxclass exact-nonnegative-integer exact-nonnegative-integer?) (define-pred-stxclass exact-positive-integer exact-positive-integer?) -(define-syntax-rule (define-kw-stxclass name kw) - (define-basic-syntax-class name - () - (lambda (x) - (if (and (identifier? x) (free-identifier=? x (quote-syntax kw))) - null - #f)))) - -(define-kw-stxclass lambda-kw #%lambda) -(define-kw-stxclass define-values-kw define-values) -(define-kw-stxclass define-syntaxes-kw define-syntaxes) - -(define-syntax-class define-values-form - (pattern (kw:define-values-kw (var:identifier ...) rhs))) -(define-syntax-class define-syntaxes-form - (pattern (kw:define-syntaxes-kw (var:identifier ...) rhs))) -(define-syntax-class definition-form - (pattern :define-values-form) - (pattern :define-syntaxes-form)) - (define-syntax-class (static-of name pred) - #:description name - #:attributes ([value 0]) - (basic-syntax-class - (lambda (x name pred) - (let/ec escape - (define (bad) (escape #f)) - (if (identifier? x) - (let ([value (syntax-local-value x bad)]) - (unless (pred value) (bad)) - (list value)) - (bad)))))) - -(define-syntax-class static #:attributes (value) + (pattern x:id + #:with value-list (syntax-local-value* #'x) + #:when (pair? (attribute value-list)) + #:with value (car (attribute value-list)) + #:when (pred (attribute value)))) + +(define (syntax-local-value* id) + (let/ec escape + (list (syntax-local-value id (lambda () (escape null)))))) + +(define-syntax-class static #:attributes (value) (pattern x #:declare x (static-of "static" (lambda _ #t)) #:with value #'x.value)) -(define-basic-syntax-class struct-name - ([descriptor 0] - [constructor 0] - [predicate 0] - [accessor 1] - [super 0] - [complete? 0]) - (lambda (x) - (if (identifier? x) - (let/ec escape - (define (bad) (escape #f)) - (let ([value (syntax-local-value x bad)]) - (unless (struct-info? value) (bad)) - (let ([lst (extract-struct-info value)]) - (let ([descriptor (list-ref lst 0)] - [constructor (list-ref lst 1)] - [predicate (list-ref lst 2)] - [accessors (list-ref lst 3)] - [super (list-ref lst 5)]) - (let ([r-accessors (reverse accessors)]) - (list descriptor - constructor - predicate - (if (and (pair? r-accessors) - (eq? #f (car r-accessors))) - (cdr r-accessors) - r-accessors) - super - (or (null? r-accessors) - (not (eq? #f (car r-accessors)))))))))) - #f))) +(define-syntax-class struct-name + #:description "struct name" + #:attributes (descriptor + constructor + predicate + [accessor 1] + super + complete?) + (pattern s + #:declare s (static-of "struct name" struct-info?) + #:with info (extract-struct-info (attribute s.value)) + #:with descriptor (list-ref (attribute info) 0) + #:with constructor (list-ref (attribute info) 1) + #:with predicate (list-ref (attribute info) 2) + #:with r-accessors (reverse (list-ref (attribute info) 3)) + #:with (accessor ...) + (datum->syntax #f (let ([r-accessors (attribute r-accessors)]) + (if (and (pair? r-accessors) (eq? #f (car r-accessors))) + (cdr r-accessors) + r-accessors))) + #:with super (list-ref (attribute info) 5) + #:with complete? (or (null? (attribute r-accessors)) + (and (pair? (attribute r-accessors)) + (not (eq? #f (car (attribute r-accessors)))))))) -(define-basic-syntax-class expr/local-expand - ([expanded 0]) - (lambda (x) - (list (local-expand x 'expression null)))) +(define-syntax-class expr/local-expand + #:attributes (expanded) + (pattern x + #:with expanded (local-expand #'x 'expression null))) -(define-basic-syntax-class expr/head-local-expand - ([expanded 0]) - (lambda (x) - (list (local-expand x 'expression (kernel-form-identifier-list))))) +(define-syntax-class expr/head-local-expand + #:attributes (expanded) + (pattern x + #:with expanded (local-expand #'x 'expression (kernel-form-identifier-list)))) -(define-basic-syntax-class block/head-local-expand - ([expanded-block 0] - [expanded 1] - [def 1] - [vdef 1] - [sdef 1] - [expr 1]) - (lambda (x) - (let-values ([(ex1 ex2 defs vdefs sdefs exprs) - (head-local-expand-and-categorize-syntaxes x #f #; #t)]) - (list ex1 ex2 defs vdefs sdefs exprs)))) +(define-syntax-class block/head-local-expand + #:attributes (expanded-block + [expanded 1] + [def 1] + [vdef 1] + [sdef 1] + [expr 1]) + (pattern x + #:with (expanded-block (expanded ...) (def ...) (vdef ...) (sdef ...) (expr ...)) + (datum->syntax #f + (let-values ([(ex1 ex2 defs vdefs sdefs exprs) + (head-local-expand-and-categorize-syntaxes + #'x #f #| #t |#)]) + (list ex1 ex2 defs vdefs sdefs exprs))))) -(define-basic-syntax-class internal-definitions - ([expanded-block 0] - [expanded 1] - [def 1] - [vdef 1] - [sdef 1] - [expr 1]) - (lambda (x) - (let-values ([(ex1 ex2 defs vdefs sdefs exprs) - (head-local-expand-and-categorize-syntaxes x #t #; #f)]) - (list ex1 ex2 defs vdefs sdefs exprs)))) +(define-syntax-class internal-definitions + #:attributes (expanded-block + [expanded 1] + [def 1] + [vdef 1] + [sdef 1] + [expr 1]) + (pattern x + #:with (expanded-block (expanded ...) (def ...) (vdef ...) (sdef ...) (expr ...)) + (datum->syntax #f + (let-values ([(ex1 ex2 defs vdefs sdefs exprs) + (head-local-expand-and-categorize-syntaxes + #'x #t #| #f |#)]) + (list ex1 ex2 defs vdefs sdefs exprs))))) -(define-syntax-rule (define-contract-stxclass name c) - (define-basic-syntax-class* (name) - ([orig-stx 0]) - (lambda (x) - (list #`(contract c - #,x - (quote #,(string->symbol (or (build-src-loc-string x) ""))) - (quote #,(or (current-macro-name) ')) - (quote-syntax #,(syntax/loc x ()))) - x)))) +(define-syntax-class expr + #:attributes () + (pattern x + #:when (and (syntax? #'x) (not (keyword? (syntax-e #'x)))))) -(define-contract-stxclass expr/num number?) -(define-contract-stxclass expr/num->num (-> number? number?)) - -(define-basic-syntax-class* (expr) - () - (lambda (x) - (if (not (keyword? (syntax-e x))) - (list x) - #f))) ;; FIXME: hack (define expr/c-use-contracts? (make-parameter #t)) -(define-basic-syntax-class* (expr/c contract) - ([orig-stx 0]) - (lambda (x c) - (if (not (keyword? (syntax-e x))) - (if (expr/c-use-contracts?) - (list #`(contract #,c - #,x - (quote #,(string->symbol - (or (build-src-loc-string x) ""))) - (quote #,(or (current-macro-name) ')) - (quote-syntax #,(syntax/loc x ()))) - x) - (list x x)) - #f))) - -(define-basic-syntax-class (term parser) - () - (lambda (x p) (p x))) - -(define-basic-syntax-class (term/pred pred) - () - (lambda (x p) - (if (p x) - null - #f))) +(define-syntax-class (expr/c ctc) + #:attributes (c) + (pattern x:expr + #:with c #`(contract #,ctc + x + (quote #,(string->symbol (or (build-src-loc-string #'x) ""))) + (quote #,(or (current-macro-name) ')) + (quote-syntax #,(syntax/loc #'x ()))))) ;; Aliases diff --git a/collects/stxclass/private/rep.ss b/collects/stxclass/private/rep.ss index 6eaf1a90a9..dd96ade8d5 100644 --- a/collects/stxclass/private/rep.ss +++ b/collects/stxclass/private/rep.ss @@ -281,21 +281,20 @@ [(struct pattern (orig-stx iattrs depth)) (make head orig-stx iattrs depth (list p) #f #f #t)])) -(define head-directive-table - (list (list '#:min check-nat/f) - (list '#:max check-nat/f) - (list '#:opt) - (list '#:mand))) - (define (parse-heads stx decls enclosing-depth) (syntax-case stx () [({} . more) (wrong-syntax (stx-car stx) "empty head sequence not allowed")] [({p ...} . more) - (let-values ([(chunks rest) (chunk-kw-seq/no-dups #'more head-directive-table)]) + (let() + (define-values (chunks rest) + (chunk-kw-seq/no-dups #'more head-directive-table)) + (define-values (chunks2 rest2) + (chunk-kw-seq rest head-directive-table2)) + ;; FIXME FIXME: handle chunks2 !!!! (cons (parse-head/chunks (stx-car stx) decls enclosing-depth chunks) - (parse-heads rest decls enclosing-depth)))] + (parse-heads rest2 decls enclosing-depth)))] [() null] [_ @@ -483,3 +482,13 @@ ;; and-pattern-directive-table (define and-pattern-directive-table (list (list '#:description check-lit-string))) + +(define head-directive-table + (list (list '#:min check-nat/f) + (list '#:max check-nat/f) + (list '#:opt) + (list '#:mand))) + +(define head-directive-table2 + (list (list '#:with values values) + (list '#:declare check-id values))) diff --git a/collects/stxclass/private/runtime.ss b/collects/stxclass/private/runtime.ss index df7c7cc61a..22a3bdaaad 100644 --- a/collects/stxclass/private/runtime.ss +++ b/collects/stxclass/private/runtime.ss @@ -22,6 +22,8 @@ current-expression current-macro-name + this-syntax + (for-syntax expectation-of-stxclass expectation-of-constants expectation-of/message) @@ -62,6 +64,12 @@ (lambda (stx) (wrong-syntax stx "used out of context: not parsing pattern"))) +;; this-syntax +;; Bound to syntax being matched inside of syntax class +(define-syntax-parameter this-syntax + (lambda (stx) + (wrong-syntax stx "used out of context: not within a syntax class"))) + (define current-expression (make-parameter #f)) (define (current-macro-name) diff --git a/collects/stxclass/private/sc.ss b/collects/stxclass/private/sc.ss index 7e5d702c9f..1f9e10b039 100644 --- a/collects/stxclass/private/sc.ss +++ b/collects/stxclass/private/sc.ss @@ -1,4 +1,3 @@ - #lang scheme/base (require (for-syntax scheme/base scheme/match @@ -32,6 +31,8 @@ (struct-out failed) + this-syntax + current-expression current-macro-name) diff --git a/collects/stxclass/util/misc.ss b/collects/stxclass/util/misc.ss index 13aba13abc..17fb4f9f08 100644 --- a/collects/stxclass/util/misc.ss +++ b/collects/stxclass/util/misc.ss @@ -14,6 +14,7 @@ with-catching-disappeared-uses with-disappeared-uses syntax-local-value/catch + record-disappeared-uses format-symbol @@ -51,10 +52,13 @@ (define (syntax-local-value/catch id pred) (let ([value (syntax-local-value id (lambda () #f))]) (and (pred value) - (begin (let ([uses (current-caught-disappeared-uses)]) - (when uses (current-caught-disappeared-uses (cons id uses)))) + (begin (record-disappeared-uses (list id)) value)))) +(define (record-disappeared-uses ids) + (let ([uses (current-caught-disappeared-uses)]) + (when uses + (current-caught-disappeared-uses (append ids uses))))) ;; Generating temporaries