/racket-5-0-2-bin-i386-osx-mac-dmg/collects/scribble/private/manual-vars.rkt

http://github.com/smorin/f4f.arc · Racket · 155 lines · 141 code · 9 blank · 5 comment · 21 complexity · 069d930378ed9bafb801d57afb607769 MD5 · raw file

  1. #lang scheme/base
  2. (require "../decode.ss"
  3. "../scheme.ss"
  4. "../struct.ss"
  5. (only-in "../core.ss" style-name)
  6. scheme/contract
  7. (for-syntax scheme/base
  8. syntax/kerncase
  9. syntax/boundmap)
  10. (for-label scheme/base
  11. scheme/class))
  12. (define-struct (box-splice splice) ())
  13. (provide/contract
  14. [struct (box-splice splice) ([run list?])]) ; XXX ugly copying
  15. (provide deftogether *deftogether
  16. with-scheme-variables
  17. with-togetherable-scheme-variables)
  18. (begin-for-syntax (define-struct deftogether-tag () #:omit-define-syntaxes))
  19. (define-syntax (with-togetherable-scheme-variables stx)
  20. (syntax-case stx ()
  21. [(_ . rest)
  22. (let ([result (syntax/loc stx
  23. (with-togetherable-scheme-variables* . rest))]
  24. [ctx (syntax-local-context)])
  25. (if (and (pair? ctx) (deftogether-tag? (car ctx)))
  26. ;; Make it transparent, so deftogether is allowed to pull it apart
  27. (syntax-property result
  28. 'certify-mode
  29. 'transparent)
  30. ;; Otherwise, don't make it transparent, because that
  31. ;; removes certificates that will be needed on the `letrec-syntaxes'
  32. ;; that we introduce later.
  33. result))]))
  34. (define-syntax-rule (with-togetherable-scheme-variables* . rest)
  35. (with-scheme-variables . rest))
  36. (define-syntax (with-scheme-variables stx)
  37. (syntax-case stx ()
  38. [(_ lits ([kind s-exp] ...) body)
  39. (let ([ht (make-bound-identifier-mapping)]
  40. [lits (syntax->datum #'lits)])
  41. (for-each (lambda (kind s-exp)
  42. (case (syntax-e kind)
  43. [(proc)
  44. (letrec ([do-proc
  45. (lambda (s-exp)
  46. (let ([s-exp (syntax->list s-exp)])
  47. (for-each
  48. (lambda (arg)
  49. (if (identifier? arg)
  50. (unless (or (eq? (syntax-e arg) '...)
  51. (eq? (syntax-e arg) '...+)
  52. (eq? (syntax-e arg) '_...superclass-args...)
  53. (memq (syntax-e arg) lits))
  54. (bound-identifier-mapping-put! ht arg #t))
  55. (syntax-case arg ()
  56. [(kw arg . rest)
  57. (keyword? (syntax-e #'kw))
  58. (bound-identifier-mapping-put! ht #'arg #t)]
  59. [(arg . rest)
  60. (identifier? #'arg)
  61. (bound-identifier-mapping-put! ht #'arg #t)])))
  62. (cdr s-exp))
  63. (unless (identifier? (car s-exp))
  64. ;; Curried:
  65. (do-proc (car s-exp)))))])
  66. (do-proc s-exp))]
  67. [(form form/none form/maybe non-term)
  68. (let loop ([form (case (syntax-e kind)
  69. [(form) (if (identifier? s-exp)
  70. null
  71. (cdr (syntax-e s-exp)))]
  72. [(form/none) s-exp]
  73. [(form/maybe)
  74. (syntax-case s-exp ()
  75. [(#f form) #'form]
  76. [(#t (id . form)) #'form])]
  77. [(non-term) s-exp])])
  78. (if (identifier? form)
  79. (unless (or (eq? (syntax-e form) '...)
  80. (eq? (syntax-e form) '...+)
  81. (eq? (syntax-e form) 'code:line)
  82. (eq? (syntax-e form) 'code:blank)
  83. (eq? (syntax-e form) 'code:comment)
  84. (eq? (syntax-e form) '?)
  85. (memq (syntax-e form) lits))
  86. (bound-identifier-mapping-put! ht form #t))
  87. (syntax-case form (unsyntax)
  88. [(unsyntax _) (void)]
  89. [(a . b) (loop #'a) (loop #'b)]
  90. [#(a ...) (loop #'(a ...))]
  91. [_ (void)])))]
  92. [else
  93. (raise-syntax-error
  94. #f
  95. "unknown variable mode"
  96. stx
  97. kind)]))
  98. (syntax->list #'(kind ...))
  99. (syntax->list #'(s-exp ...)))
  100. (with-syntax ([(id ...) (bound-identifier-mapping-map ht (lambda (k v) k))])
  101. #'(letrec-syntaxes ([(id) (make-variable-id 'id)] ...)
  102. body)))]))
  103. (define (*deftogether boxes body-thunk)
  104. (make-box-splice
  105. (cons
  106. (make-table
  107. 'boxed
  108. (map
  109. (lambda (box)
  110. (unless (and (box-splice? box)
  111. (= 1 (length (splice-run box)))
  112. (table? (car (splice-run box)))
  113. (eq? 'boxed (style-name (table-style (car (splice-run box))))))
  114. (error 'deftogether
  115. "element is not a boxing splice containing a single table: ~e"
  116. box))
  117. (list (make-flow (list (make-table
  118. "together"
  119. (table-flowss (car (splice-run box))))))))
  120. boxes))
  121. (body-thunk))))
  122. (define-syntax (deftogether stx)
  123. (syntax-case stx ()
  124. [(_ (def ...) . body)
  125. (with-syntax ([((_ (lit ...) (var ...) decl) ...)
  126. (map (lambda (def)
  127. (let ([exp-def (local-expand
  128. def
  129. (list (make-deftogether-tag))
  130. (cons
  131. #'with-togetherable-scheme-variables*
  132. (kernel-form-identifier-list)))])
  133. (syntax-case exp-def (with-togetherable-scheme-variables*)
  134. [(with-togetherable-scheme-variables* lits vars decl)
  135. exp-def]
  136. [_
  137. (raise-syntax-error
  138. #f
  139. "sub-form is not a documentation form that can be combined"
  140. stx
  141. def)])))
  142. (syntax->list #'(def ...)))])
  143. #'(with-togetherable-scheme-variables
  144. (lit ... ...)
  145. (var ... ...)
  146. (*deftogether (list decl ...) (lambda () (list . body)))))]))