/hertfordstreet/schemes/pp-syntax.ss

https://github.com/GunioRobot/hobby-code · Scheme · 235 lines · 115 code · 25 blank · 95 comment · 1 complexity · 559392590d9182d7287c72283090fc17 MD5 · raw file

  1. ;;; pp-syntax.ss -- Jens Axel Soegaard -- 27th july 2005
  2. (module pp-syntax mzscheme
  3. (provide unexpand unexpand-to-datum pp-syntax)
  4. ;; PURPOSE
  5. ;; This file contains functions that pretty prints the
  6. ;; output of EXPAND. The pretty printer attempts to present
  7. ;; the output of EXPAND using simple expression. E.g.
  8. ;; EXPAND will expand (let ((x 1)) 2) into (let-values (((x) 1)) 2),
  9. ;; which the pretty printer will "unexpand" into (let ((x 1)) 2).
  10. ;; FUNCTIONS
  11. ; unexpand : fully-expanded-syntax -> syntax
  12. ; Unexpand a piece of fully expanded syntax.
  13. ; E.g. simple occurences of let-values are rewritten to use let.
  14. ; unexpand-to-datum : fully-expanded-syntax -> datum
  15. ; Unexpand a piece of fully expanded syntax, and return
  16. ; the result as a datum.
  17. ; pp-syntax : fully-expanded-syntax ->
  18. ; Pretty-prints the unexpanded piece of syntax
  19. ;; EXAMPLE
  20. ;> (pp-syntax (expand
  21. ; '(begin
  22. ; (letrec ((f (lambda (n)
  23. ; (if (= n 0)
  24. ; 1
  25. ; (* n (f (- n 1)))))))
  26. ; (begin0 (f 5)
  27. ; (set! x 1)))
  28. ; (define y (let ((z 3)) 2)))))
  29. ;; [prints]
  30. ; (begin
  31. ; (letrec ((f (lambda (n) (if (= n 0) 1 (* n (f (- n 1)))))))
  32. ; (begin0 (f 5) (set! x 1)))
  33. ; (define y (let ((z 3)) 2)))
  34. ;; For comparison
  35. ; (pretty-print (syntax-object->datum (expand <same expression>)))
  36. ; prints
  37. ; (begin
  38. ; (letrec-values (((f)
  39. ; (lambda (n)
  40. ; (if (#%app (#%top . =) n (#%datum . 0))
  41. ; (#%datum . 1)
  42. ; (#%app
  43. ; (#%top . *)
  44. ; n
  45. ; (#%app
  46. ; f
  47. ; (#%app (#%top . -) n (#%datum . 1))))))))
  48. ; (begin0 (#%app f (#%datum . 5)) (set! x (#%datum . 1))))
  49. ; (define-values
  50. ; (y)
  51. ; (let-values (((z) (#%datum . 3))) (#%datum . 2))))
  52. (require (lib "pretty.ss"))
  53. (pretty-print-columns 70)
  54. (define (self-evaluating? o)
  55. (or (boolean? o)
  56. (number? o)
  57. (string? o)
  58. (char? o)))
  59. (define (smap f . sl)
  60. (define (->list o)
  61. (if (syntax? o) (syntax->list o) o))
  62. (apply map f (map ->list sl)))
  63. ;expr is one of
  64. ; variable
  65. ; (lambda formals expr ···1)
  66. ; (case-lambda (formals expr ···1) ···)
  67. ; (if expr expr)
  68. ; (if expr expr expr)
  69. ; (begin expr ···1)
  70. ; (begin0 expr expr ···)
  71. ; (let-values (((variable ···) expr) ···) expr ···1)
  72. ; (letrec-values (((variable ···) expr) ···) expr ···1)
  73. ; (set! variable expr)
  74. ; (quote datum)
  75. ; (quote-syntax datum)
  76. ; (with-continuation-mark expr expr expr)
  77. ; (#%app expr ···1)
  78. ; (#%datum . datum)
  79. ; (#%top . variable)
  80. ; (#%variable-reference variable)
  81. ; (#%variable-reference (#%top . variable))
  82. ; pp-expr : syntax-object -> syntax-object
  83. (define (pp-expr so)
  84. (define pe pp-expr)
  85. (define (pe* sl) (smap pe sl))
  86. (syntax-case so (lambda if begin begin0 let-values letrec-values set!
  87. with-continuation-mark #%datum #%app #%top #%variable-reference
  88. and or)
  89. ; AND
  90. [(if e1 e2 (#%datum . #f))
  91. (pe #`(and #,(pe #'e1) #,(pe #'e2)))]
  92. [(and e1 ... (and e2 ...))
  93. (pe #'(and e1 ... e2 ...))]
  94. [(and (and e1 ...) e2 ...)
  95. (pe #'(and e1 ... e2 ...))]
  96. [(and expr ...)
  97. #`(and #,@(pe* #'(expr ...)))]
  98. ; OR
  99. [(let-values (((or-part1) x)) (if or-part2 or-part3 y))
  100. (and (and (identifier? #'or-part2)
  101. (identifier? #'or-part3))
  102. (eq? (syntax-e #'or-part1) (syntax-e #'or-part2))
  103. (eq? (syntax-e #'or-part2) (syntax-e #'or-part3)))
  104. (pe #`(or #,(pe #'x) #,(pe #'y)))]
  105. [(or expr1 ... (or expr2 ...))
  106. (pe #'(or expr1 ... expr2 ...))]
  107. [(or (or expr1 ...) expr2 ...)
  108. (pe #'(or expr1 ... expr2 ...))]
  109. [(or expr ...)
  110. #`(or #,@(pe* #'(expr ...)))]
  111. ; OTHER
  112. [(lambda formals expr ...)
  113. #`(lambda formals #,@(pe* #'(expr ...)))]
  114. [(if expr1 expr2)
  115. #`(if #,(pe #'expr1) #,(pe #'expr2))]
  116. [(if expr1 expr2 expr3)
  117. #`(if #,(pe #'expr1) #,(pe #'expr2) #,(pe #'expr3))]
  118. [(begin expr ...)
  119. #`(begin #,@(pe* #'(expr ...)))]
  120. [(begin0 expr ...)
  121. #`(begin0 #,@(pe* #'(expr ...)))]
  122. [(let-values (((id) expr) ...) body ...)
  123. #`(let #,(smap list #'(id ...) (pe* #'(expr ...)))
  124. #,@(pe* #'(body ...)))]
  125. [(letrec-values (((id) expr) ...) body ...)
  126. #`(letrec #,(smap list #'(id ...) (pe* #'(expr ...)))
  127. #,@(pe* #'(body ...)))]
  128. [(set! var expr)
  129. #`(set! var #,(pe #'expr))]
  130. [(with-continuation-mark expr1 expr2 expr3)
  131. #`(with-continuation-mark #,(pe #'expr1) #,(pe #'expr2) #,(pe #'expr3))]
  132. [(#%datum . o)
  133. (self-evaluating? (syntax-object->datum #'o))
  134. #'o]
  135. [(#%app expr ...)
  136. (smap pe #'(expr ...))]
  137. [(#%top . id)
  138. #'id]
  139. ; #%variable-reference is left untouched
  140. [_
  141. so]))
  142. ;general-top-level-expr is one of
  143. ; expr
  144. ; (define-values (variable ···) expr)
  145. ; (define-syntaxes (identifier ···) expr)
  146. ; (define-values-for-syntax (variable ···) expr)
  147. ; (require require-spec ···)
  148. ; (require-for-syntax require-spec ···)
  149. ; (require-for-template require-spec ···)
  150. ; pp-general-top-level-expr : syntax-object -> syntax-object
  151. (define (pp-general-top-level-expr so)
  152. (syntax-case so (define-values define-syntaxes define-values-for-syntax
  153. require require-for-syntax require-for-template)
  154. [(define-values (var) expr)
  155. #`(define var #,(pp-expr #'expr))]
  156. [(define-values (var ...) expr)
  157. #`(define-values (var ...) #,(pp-expr #'expr))]
  158. [(define-syntaxes id expr)
  159. #`(define-syntax id #,(pp-expr #'expr))]
  160. [(define-syntaxes (id ...) expr)
  161. #`(define-syntaxes (id ...) #,(pp-expr #'expr))]
  162. [(define-values-for-syntax (var ...) expr)
  163. #`(define-values-for-syntax (var ...) #,(pp-expr #'expr))]
  164. [(require require-spec ...)
  165. #'(require require-spec ...)]
  166. [(require-for-syntax require-spec ...)
  167. #'(require-for-syntax require-spec ...)]
  168. [(require-for-template require-spec ...)
  169. #'(require-for-template require-spec ...)]
  170. [_
  171. (pp-expr so)]))
  172. ;top-level-expr is one of
  173. ; general-top-level-expr
  174. ; (module identifier name (#%plain-module-begin module-level-expr ···))
  175. ; (begin top-level-expr ···)
  176. ; pp-top-level-expr : syntax-object -> syntax-object
  177. (define (pp-top-level-expr so)
  178. (syntax-case so (module begin #%plain-module-begin)
  179. [(module id name (#%plain-module-begin module-level-expr ...))
  180. #`(module id name (#%plain-module-begin #,@(smap pp-module-level-expr #'(module-level-expr ...))))]
  181. [(begin top-level-expr ...)
  182. #`(begin #,@(smap pp-top-level-expr #'(top-level-expr ...)))]
  183. [_
  184. (pp-general-top-level-expr so)]))
  185. ;module-level-expr is one of
  186. ; general-top-level-expr
  187. ; (provide provide-spec ...)
  188. ; (begin module-level-expr ···)
  189. ; pp-module-level-expr : syntax-object -> syntax-object
  190. (define (pp-module-level-expr so)
  191. (syntax-case so (provide begin)
  192. [(provide provide-spec ...)
  193. #'(provide provide-spec ...)]
  194. [(begin module-level-expr ...)
  195. #`(begin #,@(smap pp-module-level-expr #'(module-level-expr ...)))]
  196. [_
  197. (pp-general-top-level-expr so)]))
  198. ; unexpand : fully-expanded-syntax -> syntax
  199. (define (unexpand so)
  200. (pp-module-level-expr
  201. (expand so)))
  202. ; unexpand-to-datum : fully-expanded-syntax -> datum
  203. (define (unexpand-to-datum so)
  204. (syntax-object->datum
  205. #`#,(unexpand so)))
  206. ; pp-syntax : fully-expanded-syntax ->
  207. (define (pp-syntax so)
  208. (pretty-display
  209. (unexpand-to-datum so)))
  210. )