|
|
|
@ -1,14 +1,18 @@
|
|
|
|
|
#lang racket/base
|
|
|
|
|
(require (for-syntax racket/base racket/syntax)
|
|
|
|
|
racket/list
|
|
|
|
|
racket/match
|
|
|
|
|
racket/syntax
|
|
|
|
|
racket/format
|
|
|
|
|
syntax/stx
|
|
|
|
|
syntax/strip-context
|
|
|
|
|
br/define
|
|
|
|
|
br/private/syntax-flatten)
|
|
|
|
|
(provide (all-defined-out)
|
|
|
|
|
syntax-flatten
|
|
|
|
|
(rename-out [strip-context strip-bindings]
|
|
|
|
|
[replace-context replace-bindings]))
|
|
|
|
|
[replace-context replace-bindings]
|
|
|
|
|
[stx-map syntax-map]))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit))
|
|
|
|
@ -55,45 +59,48 @@
|
|
|
|
|
|
|
|
|
|
(define-macro (format-string FMT ID0 ID ...)
|
|
|
|
|
#'(datum->syntax ID0 (format FMT (syntax->datum ID0) (syntax->datum ID) ...)))
|
|
|
|
|
#|
|
|
|
|
|
(define (format-string FMT ID0 . IDS)
|
|
|
|
|
(datum->syntax ID0 (apply format FMT (syntax->datum ID0) (map syntax->datum IDS))))
|
|
|
|
|
|#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-macro (->unsyntax X)
|
|
|
|
|
#'(if (syntax? X)
|
|
|
|
|
(syntax->datum X)
|
|
|
|
|
X))
|
|
|
|
|
(define (->unsyntax x)
|
|
|
|
|
(if (syntax? x) (syntax->datum x) x))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-macro (prefix-id PREFIX ... BASE-OR-BASES)
|
|
|
|
|
#'(let* ([bobs BASE-OR-BASES]
|
|
|
|
|
[got-single? (and (not (list? bobs)) (not (syntax->list bobs)))]
|
|
|
|
|
[bases (if got-single?
|
|
|
|
|
(list bobs)
|
|
|
|
|
bobs)]
|
|
|
|
|
[result (syntax-case-map
|
|
|
|
|
bases ()
|
|
|
|
|
[base (format-id #'base "~a~a"
|
|
|
|
|
(string-append (format "~a" (->unsyntax PREFIX)) ...)
|
|
|
|
|
(syntax-e #'base))])])
|
|
|
|
|
(if got-single? (car result) result)))
|
|
|
|
|
(define (fix-base loc-arg prefixes base-or-bases suffixes)
|
|
|
|
|
(define single-mode? (and (not (list? base-or-bases)) (not (syntax->list base-or-bases))))
|
|
|
|
|
(define bases (if single-mode? (list base-or-bases) (or (syntax->list base-or-bases) base-or-bases)))
|
|
|
|
|
(define (stx-join stxs) (apply string-append (map (compose1 ~a ->unsyntax) stxs)))
|
|
|
|
|
(define result (map (λ (base) (format-id base "~a~a~a" (stx-join prefixes) (syntax-e base) (stx-join suffixes)
|
|
|
|
|
#:source loc-arg)) bases))
|
|
|
|
|
(if single-mode? (car result) result))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-macro (infix-id PREFIX BASE-OR-BASES SUFFIX ...)
|
|
|
|
|
#'(let* ([bobs BASE-OR-BASES]
|
|
|
|
|
[got-single? (and (not (list? bobs)) (not (syntax->list bobs)))]
|
|
|
|
|
[bases (if got-single?
|
|
|
|
|
(list bobs)
|
|
|
|
|
bobs)]
|
|
|
|
|
[result (syntax-case-map
|
|
|
|
|
bases ()
|
|
|
|
|
[base (format-id #'base "~a~a~a"
|
|
|
|
|
(->unsyntax PREFIX)
|
|
|
|
|
(syntax-e #'base)
|
|
|
|
|
(string-append (format "~a" (->unsyntax SUFFIX)) ...))])])
|
|
|
|
|
(if got-single? (car result) result)))
|
|
|
|
|
(define (prefix-id #:source [loc-arg #f] . args)
|
|
|
|
|
((match-lambda
|
|
|
|
|
[(list prefixes ... base-or-bases)
|
|
|
|
|
(fix-base loc-arg prefixes base-or-bases empty)]) args))
|
|
|
|
|
|
|
|
|
|
(define (infix-id #:source [loc-arg #f] . args)
|
|
|
|
|
((match-lambda
|
|
|
|
|
[(list prefix base-or-bases suffixes ...)
|
|
|
|
|
(fix-base loc-arg (list prefix) base-or-bases suffixes)]) args))
|
|
|
|
|
|
|
|
|
|
(define-macro (suffix-id BASE-OR-BASES SUFFIX ...)
|
|
|
|
|
#'(infix-id "" BASE-OR-BASES SUFFIX ...))
|
|
|
|
|
(define (suffix-id #:source [loc-arg #f] . args)
|
|
|
|
|
((match-lambda
|
|
|
|
|
[(list base-or-bases suffixes ...)
|
|
|
|
|
(fix-base loc-arg empty base-or-bases suffixes)]) args))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(define-check (check-stx-equal? stx1 stx2)
|
|
|
|
|
(define stxs (list stx1 stx2))
|
|
|
|
|
(apply equal? (map syntax->datum stxs)))
|
|
|
|
|
(check-stx-equal? (prefix-id "foo" "bar" #'id) #'foobarid)
|
|
|
|
|
(check-stx-equal? (infix-id "foo" #'id "bar" "zam") #'fooidbarzam)
|
|
|
|
|
(check-stx-equal? (suffix-id #'id "foo" "bar" "zam") #'idfoobarzam)
|
|
|
|
|
(for-each check-stx-equal? (suffix-id #'(this that) "@") (list #'this@ #'that@)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-macro-cases syntax-property*
|
|
|
|
@ -110,6 +117,23 @@
|
|
|
|
|
[(_ STX ['PROP0 VAL0 . PRESERVED0] ['PROP VAL . PRESERVED] ...) ; write multiple
|
|
|
|
|
#'(syntax-property* (syntax-property STX 'PROP0 VAL0 . PRESERVED0) ['PROP VAL . PRESERVED] ...)])
|
|
|
|
|
|
|
|
|
|
#|
|
|
|
|
|
(define (syntax-property* . args)
|
|
|
|
|
((match-lambda*
|
|
|
|
|
[(list x) x]
|
|
|
|
|
[(list stx (list prop val others ...)) ; write one
|
|
|
|
|
(apply syntax-property stx prop val others)]
|
|
|
|
|
[(list stx (list prop val others ...) args ...) ; write multiple
|
|
|
|
|
#'(apply syntax-property* (apply syntax-property stx prop val others) args)]
|
|
|
|
|
[(list stx prop) ; read one
|
|
|
|
|
(syntax-property stx prop)]
|
|
|
|
|
[(list stx prop0 props ...) ; read multiple
|
|
|
|
|
(map (λ (prop) (syntax-property stx prop)) (cons prop0 props))]
|
|
|
|
|
[else 'huh]) args))
|
|
|
|
|
|#
|
|
|
|
|
|
|
|
|
|
(define (filter-stx-prop prop stxs)
|
|
|
|
|
(filter (λ (stx) (syntax-property stx prop)) stxs))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(define x (syntax-property* #'foo ['bar #t] ['zam 'boni]))
|
|
|
|
|