[honu] use reified syntax classes to check for literals instead of direct comparisons with free-identifier=?

This commit is contained in:
Jon Rafkind 2011-11-15 17:16:59 -07:00
parent 3bffcae3c2
commit a38949d8ba
3 changed files with 53 additions and 14 deletions

View File

@ -6,6 +6,7 @@
(for-syntax racket/base (for-syntax racket/base
"literals.rkt" "literals.rkt"
"parse2.rkt" "parse2.rkt"
"util.rkt"
syntax/parse) syntax/parse)
racket/class) racket/class)
@ -17,7 +18,7 @@
(define-splicing-syntax-class honu-class-thing (define-splicing-syntax-class honu-class-thing
#:literals (honu-equal) #:literals (honu-equal)
[pattern method:honu-function [pattern method:honu-function
#:with result (replace-with-public #'method.result)] #:with result (replace-with-public (local-binding method.result))]
[pattern var:honu-declaration [pattern var:honu-declaration
#:with result #'(field [var.name var.expression] ...)])) #:with result #'(field [var.name var.expression] ...)]))
@ -25,14 +26,14 @@
(define-honu-syntax honu-class (define-honu-syntax honu-class
(lambda (code context) (lambda (code context)
(syntax-parse code #:literal-sets (cruft) (syntax-parse code #:literal-sets (cruft)
[(_ name (#%parens (~var constructor-argument (separate-ids #'honu-comma #'dont-care))) [(_ name (#%parens (~var constructor-argument (separate-ids (literal-syntax-class honu-comma) (literal-syntax-class honu-comma))))
(#%braces method:honu-class-thing ...) . rest) (#%braces method:honu-class-thing ...) . rest)
(define class (define class
#'(%racket (define name (class* object% () #'(%racket (define name (class* object% ()
(super-new) (super-new)
(init-field constructor-argument.id ...) (init-field constructor-argument.id ...)
method.result ...)))) method.result ...))))
(values class #'rest #t)]))) (values class (local-binding rest) #t)])))
(provide honu-new) (provide honu-new)
(define-honu-syntax honu-new (define-honu-syntax honu-new
@ -42,5 +43,5 @@
(define new #'(%racket (make-object name arg.result ...))) (define new #'(%racket (make-object name arg.result ...)))
(values (values
new new
#'rest (local-binding rest)
#f)]))) #f)])))

View File

@ -16,7 +16,9 @@
define-literal define-literal
%racket) %racket)
(for-syntax syntax/parse (for-syntax syntax/parse
syntax/parse/experimental/reflect
racket/syntax racket/syntax
"util.rkt"
"debug.rkt" "debug.rkt"
"literals.rkt" "literals.rkt"
"parse2.rkt" "parse2.rkt"
@ -261,16 +263,16 @@
(begin-for-syntax (begin-for-syntax
(define-splicing-syntax-class (id-must-be what) (define-splicing-syntax-class (id-must-be what)
[pattern x:id #:when (free-identifier=? #'x what)]) [pattern (~reflect x (what))])
(define-splicing-syntax-class (id-except ignores) (define-syntax-class (id-except ignore1 ignore2)
[pattern x:id #:when (not (for/fold ([ok #f]) [pattern (~and x:id (~not (~or (~reflect x1 (ignore1))
([ignore ignores]) (~reflect x2 (ignore2)))))])
(or ok (free-identifier=? #'x ignore))))])
(provide separate-ids) (provide separate-ids)
(define-splicing-syntax-class (separate-ids separator end) (define-splicing-syntax-class (separate-ids separator end)
[pattern (~seq (~var first (id-except (list separator end))) [pattern (~seq (~var first (id-except separator end))
(~seq (~var between (id-must-be separator)) (~seq (~var between (id-must-be separator))
(~var next (id-except (list separator end)))) ...) (~var next (id-except separator end))) ...)
#:with (id ...) #'(first.x next.x ...)])) #:with (id ...) #'(first.x next.x ...)]))
(begin-for-syntax (begin-for-syntax
@ -278,7 +280,8 @@
(define-literal-set declaration-literals (honu-comma honu-equal)) (define-literal-set declaration-literals (honu-comma honu-equal))
(define-splicing-syntax-class var-id (define-splicing-syntax-class var-id
[pattern x:id #:when (not ((literal-set->predicate declaration-literals) #'x))]) [pattern (~var x (id-except (literal-syntax-class honu-comma)
(literal-syntax-class honu-equal)))])
;; parses a declaration ;; parses a declaration
;; var x = 9 ;; var x = 9
@ -286,7 +289,8 @@
(define-splicing-syntax-class honu-declaration (define-splicing-syntax-class honu-declaration
#:literal-sets (cruft) #:literal-sets (cruft)
#:literals (honu-equal honu-var) #:literals (honu-equal honu-var)
[pattern (~seq honu-var (~var variables (separate-ids #'honu-comma #'honu-equal)) [pattern (~seq honu-var (~var variables (separate-ids (literal-syntax-class honu-comma)
(literal-syntax-class honu-equal)))
honu-equal one:honu-expression) honu-equal one:honu-expression)
#:with (name ...) #'(variables.id ...) #:with (name ...) #'(variables.id ...)
#:with expression #'one.result])) #:with expression #'one.result]))

View File

@ -3,7 +3,12 @@
(provide (except-out (all-defined-out) test-delimiter)) (provide (except-out (all-defined-out) test-delimiter))
(require "debug.rkt" (require "debug.rkt"
racket/match racket/match
(for-syntax racket/base) syntax/parse
syntax/parse/experimental/reflect
(for-syntax racket/base
syntax/parse
"debug.rkt"
)
syntax/stx syntax/stx
racket/list) racket/list)
@ -94,3 +99,32 @@
[match-variable (extract-variable #'pattern)]) [match-variable (extract-variable #'pattern)])
#'(match expression #'(match expression
[match-pattern match-variable]))])) [match-pattern match-variable]))]))
;; local-binding and module-binding check that the identifier is bound at the given phase
(define-syntax (local-binding stx)
(syntax-parse stx
[(_ name)
(define type (identifier-binding #'name))
(when (not (eq? type 'lexical))
(raise-syntax-error 'local-binding "not bound locally" #'name))
#'#'name]))
(define-syntax (module-binding stx)
(syntax-parse stx
[(_ name level)
(define type (identifier-binding #'name (syntax-e #'level)))
(when (not (and (list? type)
(= (length type) 7)))
(raise-syntax-error 'module-binding
(format "not bound by a module at phase ~a" (syntax-e #'level))
#'name))
#'#'name]))
(define-syntax-rule (literal-syntax-class literal)
(let ()
(define-literal-set set (literal))
(define-syntax-class class
#:literal-sets (set)
;; BUG! shouldn't need ~literal here since we are using literal sets
[pattern (~literal literal)])
(reify-syntax-class class)))