/racket-5-0-2-bin-i386-osx-mac-dmg/collects/lang/private/teach-module-begin.rkt

http://github.com/smorin/f4f.arc · Racket · 205 lines · 169 code · 14 blank · 22 comment · 16 complexity · 9000ac587727bb7ed43c62f870d09a37 MD5 · raw file

  1. #lang scheme/base
  2. ; Once upon a time, there were three different variants. Preserve the
  3. ; ability to do this.
  4. (provide (rename-out (module-begin beginner-module-begin)
  5. (module-begin intermediate-module-begin)
  6. (module-begin advanced-module-begin)))
  7. (require deinprogramm/signature/signature
  8. lang/private/signature-syntax)
  9. (require (for-syntax scheme/base)
  10. (for-syntax racket/list)
  11. (for-syntax syntax/boundmap)
  12. (for-syntax syntax/kerncase))
  13. (require (for-syntax "firstorder.ss"))
  14. (define-syntax (print-results stx)
  15. (syntax-case stx ()
  16. ((_ expr)
  17. (not (or (syntax-property #'expr 'stepper-hide-completed)
  18. (syntax-property #'expr 'stepper-skip-completely)
  19. (syntax-property #'expr 'test-call)))
  20. (syntax-property
  21. (syntax-property
  22. #'(#%app call-with-values (lambda () expr)
  23. do-print-results)
  24. 'stepper-skipto
  25. '(syntax-e cdr cdr car syntax-e cdr cdr car))
  26. 'certify-mode
  27. 'transparent))
  28. ((_ expr) #'expr)))
  29. (define (do-print-results . vs)
  30. (for-each (current-print) vs)
  31. ;; Returning 0 values avoids any further result printing
  32. ;; (even if void values are printed)
  33. (values))
  34. (define-syntaxes (module-begin module-continue)
  35. (let ()
  36. ;; takes a list of syntax objects (the result of syntax-e) and returns all the syntax objects that correspond to
  37. ;; a signature declaration. Syntax: (: id signature)
  38. (define extract-signatures
  39. (lambda (lostx)
  40. (let* ((table (make-bound-identifier-mapping))
  41. (non-signatures
  42. (filter-map (lambda (maybe)
  43. (syntax-case maybe (:)
  44. ((: ?exp ?sig)
  45. (not (identifier? #'?exp))
  46. #'(apply-signature/blame (signature ?sig) ?exp))
  47. ((: ?id ?sig)
  48. (begin
  49. (let ((real-id (first-order->higher-order #'?id)))
  50. (cond
  51. ((bound-identifier-mapping-get table real-id (lambda () #f))
  52. => (lambda (old-sig-stx)
  53. (unless (equal? (syntax->datum old-sig-stx)
  54. (syntax->datum #'?sig))
  55. (raise-syntax-error #f
  56. "Second signature declaration for the same name."
  57. maybe))))
  58. (else
  59. (bound-identifier-mapping-put! table real-id #'?sig)))
  60. #f)))
  61. ((: ?id)
  62. (raise-syntax-error #f "Signature declaration is missing a signature." maybe))
  63. ((: ?id ?sig ?stuff0 ?stuff1 ...)
  64. (raise-syntax-error #f "The : form expects a name and a signature; there is more."
  65. (syntax/loc #'?stuff0
  66. (?stuff0 ?stuff1 ...))))
  67. (_ maybe)))
  68. lostx)))
  69. (values table non-signatures))))
  70. (define local-expand-stop-list
  71. (append (list #': #'define-signature
  72. #'#%require #'#%provide)
  73. (kernel-form-identifier-list)))
  74. (define (expand-signature-expressions signature-table expressions)
  75. (let loop ((exprs expressions))
  76. (cond
  77. ((null? exprs)
  78. (bound-identifier-mapping-for-each signature-table
  79. (lambda (id thing)
  80. (when thing
  81. (if (identifier-binding id)
  82. (raise-syntax-error #f "Cannot declare a signature for a built-in form." id)
  83. (raise-syntax-error #f "There is no definition for this signature declaration." id)))))
  84. #'(begin))
  85. (else
  86. (let ((expanded (car exprs)))
  87. (syntax-case expanded (begin define-values)
  88. ((define-values (?id ...) ?e1)
  89. (with-syntax (((?enforced ...)
  90. (map (lambda (id)
  91. (cond
  92. ((bound-identifier-mapping-get signature-table id (lambda () #f))
  93. => (lambda (sig)
  94. (bound-identifier-mapping-put! signature-table id #f) ; check for orphaned signatures
  95. (with-syntax ((?id id)
  96. (?sig sig))
  97. #'(?id (signature ?sig)))))
  98. (else
  99. id)))
  100. (syntax->list #'(?id ...))))
  101. (?rest (loop (cdr exprs))))
  102. (with-syntax ((?defn
  103. (syntax-track-origin
  104. #'(define-values/signature (?enforced ...)
  105. ?e1)
  106. (car exprs)
  107. (car (syntax-e expanded)))))
  108. (syntax/loc (car exprs)
  109. (begin
  110. ?defn
  111. ?rest)))))
  112. ((begin e1 ...)
  113. (loop (append (syntax-e (syntax (e1 ...))) (cdr exprs))))
  114. (else
  115. (with-syntax ((?first expanded)
  116. (?rest (loop (cdr exprs))))
  117. (syntax/loc (car exprs)
  118. (begin
  119. ?first ?rest))))))))))
  120. (values
  121. ;; module-begin
  122. (lambda (stx)
  123. (syntax-case stx ()
  124. ((_ e1 ...)
  125. ;; module-begin-continue takes a sequence of expanded
  126. ;; exprs and a sequence of to-expand exprs; that way,
  127. ;; the module-expansion machinery can be used to handle
  128. ;; requires, etc.:
  129. #`(#%plain-module-begin
  130. (module-continue (e1 ...) () ())))))
  131. ;; module-continue
  132. (lambda (stx)
  133. (syntax-case stx ()
  134. ((_ () (e1 ...) (defined-id ...))
  135. ;; Local-expanded all body elements, lifted out requires, etc.
  136. ;; Now process the result.
  137. (begin
  138. ;; The expansion for signatures breaks the way that beginner-define, etc.,
  139. ;; check for duplicate definitions, so we have to re-check here.
  140. ;; A better strategy might be to turn every define into a define-syntax
  141. ;; to redirect the binding, and then the identifier-binding check in
  142. ;; beginner-define, etc. will work.
  143. (let ((defined-ids (make-bound-identifier-mapping)))
  144. (for-each (lambda (id)
  145. (when (bound-identifier-mapping-get defined-ids id (lambda () #f))
  146. (raise-syntax-error
  147. #f
  148. "this name was defined previously and cannot be re-defined"
  149. id))
  150. (bound-identifier-mapping-put! defined-ids id #t))
  151. (reverse (syntax->list #'(defined-id ...)))))
  152. ;; Now handle signatures:
  153. (let ((top-level (reverse (syntax->list (syntax (e1 ...))))))
  154. (let-values (((sig-table expr-list)
  155. (extract-signatures top-level)))
  156. (expand-signature-expressions sig-table expr-list)))))
  157. ((frm e3s e1s def-ids)
  158. (let loop ((e3s #'e3s)
  159. (e1s #'e1s)
  160. (def-ids #'def-ids))
  161. (syntax-case e3s ()
  162. (()
  163. #`(frm () #,e1s #,def-ids))
  164. ((e2 . e3s)
  165. (let ((e2 (local-expand #'e2 'module local-expand-stop-list)))
  166. ;; Lift out certain forms to make them visible to the module
  167. ;; expander:
  168. (syntax-case e2 (#%require #%provide
  169. define-syntaxes define-values-for-syntax define-values begin
  170. define-signature :)
  171. ((#%require . __)
  172. #`(begin #,e2 (frm e3s #,e1s #,def-ids)))
  173. ((#%provide . __)
  174. #`(begin #,e2 (frm e3s #,e1s #,def-ids)))
  175. ((define-syntaxes (id ...) . _)
  176. #`(begin #,e2 (frm e3s #,e1s (id ... . #,def-ids))))
  177. ((define-values-for-syntax . _)
  178. #`(begin #,e2 (frm e3s #,e1s #,def-ids)))
  179. ((begin b1 ...)
  180. (syntax-track-origin
  181. (loop (append (syntax->list #'(b1 ...)) #'e3s) e1s def-ids)
  182. e2
  183. (car (syntax-e e2))))
  184. ((define-values (id ...) . _)
  185. (loop #'e3s (cons e2 e1s) (append (syntax->list #'(id ...)) def-ids)))
  186. ((define-signature id ctr)
  187. (loop #'e3s (cons e2 e1s) def-ids))
  188. ((: stuff ...)
  189. (loop #'e3s (cons e2 e1s) def-ids))
  190. (_
  191. (loop #'e3s (cons #`(print-results #,e2) e1s) def-ids)))))))))))))