/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
- ;;; pp-syntax.ss -- Jens Axel Soegaard -- 27th july 2005
- (module pp-syntax mzscheme
- (provide unexpand unexpand-to-datum pp-syntax)
-
- ;; PURPOSE
- ;; This file contains functions that pretty prints the
- ;; output of EXPAND. The pretty printer attempts to present
- ;; the output of EXPAND using simple expression. E.g.
- ;; EXPAND will expand (let ((x 1)) 2) into (let-values (((x) 1)) 2),
- ;; which the pretty printer will "unexpand" into (let ((x 1)) 2).
-
- ;; FUNCTIONS
-
- ; unexpand : fully-expanded-syntax -> syntax
- ; Unexpand a piece of fully expanded syntax.
- ; E.g. simple occurences of let-values are rewritten to use let.
- ; unexpand-to-datum : fully-expanded-syntax -> datum
- ; Unexpand a piece of fully expanded syntax, and return
- ; the result as a datum.
- ; pp-syntax : fully-expanded-syntax ->
- ; Pretty-prints the unexpanded piece of syntax
-
- ;; EXAMPLE
-
- ;> (pp-syntax (expand
- ; '(begin
- ; (letrec ((f (lambda (n)
- ; (if (= n 0)
- ; 1
- ; (* n (f (- n 1)))))))
- ; (begin0 (f 5)
- ; (set! x 1)))
- ; (define y (let ((z 3)) 2)))))
-
- ;; [prints]
-
- ; (begin
- ; (letrec ((f (lambda (n) (if (= n 0) 1 (* n (f (- n 1)))))))
- ; (begin0 (f 5) (set! x 1)))
- ; (define y (let ((z 3)) 2)))
-
- ;; For comparison
- ; (pretty-print (syntax-object->datum (expand <same expression>)))
- ; prints
-
- ; (begin
- ; (letrec-values (((f)
- ; (lambda (n)
- ; (if (#%app (#%top . =) n (#%datum . 0))
- ; (#%datum . 1)
- ; (#%app
- ; (#%top . *)
- ; n
- ; (#%app
- ; f
- ; (#%app (#%top . -) n (#%datum . 1))))))))
- ; (begin0 (#%app f (#%datum . 5)) (set! x (#%datum . 1))))
- ; (define-values
- ; (y)
- ; (let-values (((z) (#%datum . 3))) (#%datum . 2))))
-
-
- (require (lib "pretty.ss"))
- (pretty-print-columns 70)
-
- (define (self-evaluating? o)
- (or (boolean? o)
- (number? o)
- (string? o)
- (char? o)))
-
- (define (smap f . sl)
- (define (->list o)
- (if (syntax? o) (syntax->list o) o))
- (apply map f (map ->list sl)))
-
-
- ;expr is one of
- ; variable
- ; (lambda formals expr ···1)
- ; (case-lambda (formals expr ···1) ···)
- ; (if expr expr)
- ; (if expr expr expr)
- ; (begin expr ···1)
- ; (begin0 expr expr ···)
- ; (let-values (((variable ···) expr) ···) expr ···1)
- ; (letrec-values (((variable ···) expr) ···) expr ···1)
- ; (set! variable expr)
- ; (quote datum)
- ; (quote-syntax datum)
- ; (with-continuation-mark expr expr expr)
- ; (#%app expr ···1)
- ; (#%datum . datum)
- ; (#%top . variable)
- ; (#%variable-reference variable)
- ; (#%variable-reference (#%top . variable))
-
- ; pp-expr : syntax-object -> syntax-object
- (define (pp-expr so)
- (define pe pp-expr)
- (define (pe* sl) (smap pe sl))
- (syntax-case so (lambda if begin begin0 let-values letrec-values set!
- with-continuation-mark #%datum #%app #%top #%variable-reference
- and or)
- ; AND
- [(if e1 e2 (#%datum . #f))
- (pe #`(and #,(pe #'e1) #,(pe #'e2)))]
- [(and e1 ... (and e2 ...))
- (pe #'(and e1 ... e2 ...))]
- [(and (and e1 ...) e2 ...)
- (pe #'(and e1 ... e2 ...))]
- [(and expr ...)
- #`(and #,@(pe* #'(expr ...)))]
- ; OR
- [(let-values (((or-part1) x)) (if or-part2 or-part3 y))
- (and (and (identifier? #'or-part2)
- (identifier? #'or-part3))
- (eq? (syntax-e #'or-part1) (syntax-e #'or-part2))
- (eq? (syntax-e #'or-part2) (syntax-e #'or-part3)))
- (pe #`(or #,(pe #'x) #,(pe #'y)))]
- [(or expr1 ... (or expr2 ...))
- (pe #'(or expr1 ... expr2 ...))]
- [(or (or expr1 ...) expr2 ...)
- (pe #'(or expr1 ... expr2 ...))]
- [(or expr ...)
- #`(or #,@(pe* #'(expr ...)))]
- ; OTHER
- [(lambda formals expr ...)
- #`(lambda formals #,@(pe* #'(expr ...)))]
- [(if expr1 expr2)
- #`(if #,(pe #'expr1) #,(pe #'expr2))]
- [(if expr1 expr2 expr3)
- #`(if #,(pe #'expr1) #,(pe #'expr2) #,(pe #'expr3))]
- [(begin expr ...)
- #`(begin #,@(pe* #'(expr ...)))]
- [(begin0 expr ...)
- #`(begin0 #,@(pe* #'(expr ...)))]
- [(let-values (((id) expr) ...) body ...)
- #`(let #,(smap list #'(id ...) (pe* #'(expr ...)))
- #,@(pe* #'(body ...)))]
- [(letrec-values (((id) expr) ...) body ...)
- #`(letrec #,(smap list #'(id ...) (pe* #'(expr ...)))
- #,@(pe* #'(body ...)))]
- [(set! var expr)
- #`(set! var #,(pe #'expr))]
- [(with-continuation-mark expr1 expr2 expr3)
- #`(with-continuation-mark #,(pe #'expr1) #,(pe #'expr2) #,(pe #'expr3))]
- [(#%datum . o)
- (self-evaluating? (syntax-object->datum #'o))
- #'o]
- [(#%app expr ...)
- (smap pe #'(expr ...))]
- [(#%top . id)
- #'id]
- ; #%variable-reference is left untouched
- [_
- so]))
-
- ;general-top-level-expr is one of
- ; expr
- ; (define-values (variable ···) expr)
- ; (define-syntaxes (identifier ···) expr)
- ; (define-values-for-syntax (variable ···) expr)
- ; (require require-spec ···)
- ; (require-for-syntax require-spec ···)
- ; (require-for-template require-spec ···)
-
- ; pp-general-top-level-expr : syntax-object -> syntax-object
- (define (pp-general-top-level-expr so)
- (syntax-case so (define-values define-syntaxes define-values-for-syntax
- require require-for-syntax require-for-template)
- [(define-values (var) expr)
- #`(define var #,(pp-expr #'expr))]
- [(define-values (var ...) expr)
- #`(define-values (var ...) #,(pp-expr #'expr))]
- [(define-syntaxes id expr)
- #`(define-syntax id #,(pp-expr #'expr))]
- [(define-syntaxes (id ...) expr)
- #`(define-syntaxes (id ...) #,(pp-expr #'expr))]
- [(define-values-for-syntax (var ...) expr)
- #`(define-values-for-syntax (var ...) #,(pp-expr #'expr))]
- [(require require-spec ...)
- #'(require require-spec ...)]
- [(require-for-syntax require-spec ...)
- #'(require-for-syntax require-spec ...)]
- [(require-for-template require-spec ...)
- #'(require-for-template require-spec ...)]
- [_
- (pp-expr so)]))
-
- ;top-level-expr is one of
- ; general-top-level-expr
- ; (module identifier name (#%plain-module-begin module-level-expr ···))
- ; (begin top-level-expr ···)
-
- ; pp-top-level-expr : syntax-object -> syntax-object
- (define (pp-top-level-expr so)
- (syntax-case so (module begin #%plain-module-begin)
- [(module id name (#%plain-module-begin module-level-expr ...))
- #`(module id name (#%plain-module-begin #,@(smap pp-module-level-expr #'(module-level-expr ...))))]
- [(begin top-level-expr ...)
- #`(begin #,@(smap pp-top-level-expr #'(top-level-expr ...)))]
- [_
- (pp-general-top-level-expr so)]))
-
- ;module-level-expr is one of
- ; general-top-level-expr
- ; (provide provide-spec ...)
- ; (begin module-level-expr ···)
-
- ; pp-module-level-expr : syntax-object -> syntax-object
- (define (pp-module-level-expr so)
- (syntax-case so (provide begin)
- [(provide provide-spec ...)
- #'(provide provide-spec ...)]
- [(begin module-level-expr ...)
- #`(begin #,@(smap pp-module-level-expr #'(module-level-expr ...)))]
- [_
- (pp-general-top-level-expr so)]))
-
- ; unexpand : fully-expanded-syntax -> syntax
- (define (unexpand so)
- (pp-module-level-expr
- (expand so)))
-
- ; unexpand-to-datum : fully-expanded-syntax -> datum
- (define (unexpand-to-datum so)
- (syntax-object->datum
- #`#,(unexpand so)))
-
- ; pp-syntax : fully-expanded-syntax ->
- (define (pp-syntax so)
- (pretty-display
- (unexpand-to-datum so)))
- )