File: to-string.rkt

package info (click to toggle)
racket 7.9%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 178,684 kB
  • sloc: ansic: 282,112; lisp: 234,887; pascal: 70,954; sh: 27,112; asm: 16,268; makefile: 4,613; cpp: 2,715; ada: 1,681; javascript: 1,244; cs: 879; exp: 499; csh: 422; python: 274; xml: 106; perl: 104
file content (115 lines) | stat: -rw-r--r-- 4,706 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
(module to-string racket/base
  (require racket/contract/base
           syntax/stx)
  
  (require racket/list)

  (define (syntax->string c)
    (let* ([s (open-output-string)]
           [l (syntax->list c)]
           [init-col (or (syntax-column (first l)) 0)]
           [col init-col]
           [line (or (syntax-line (first l)) 0)])
      (define (advance c init-line!)
        (let ([c (syntax-column c)]
              [l (syntax-line c)])
          (when (and l (l . > . line))
            (for-each (λ (_) (newline)) (range (- l line)))
            (set! line l)
            (init-line!))
          (when c
            (display (make-string (max 0 (- c col)) #\space))
            (set! col c))))
      (define quotes-table
        #hasheq((quote . "'")
                (quasiquote . "`")
                (unquote . ",")
                (unquote-splicing . ",@")
                (syntax . "#'")
                (quasisyntax . "#`")
                (unsyntax . "#,")
                (unsyntax-splicing . "#,@")))
      (define (get-quote c)
        (hash-ref quotes-table (syntax-e (car (syntax-e c)))))
      (parameterize ([current-output-port s]
                     [read-case-sensitive #t])
        (define (loop init-line!)
          (lambda (c)
            (cond
              [(eq? 'code:blank (syntax-e c))
               (advance c init-line!)]
              [(eq? '_ (syntax-e c)) 
               (advance c init-line!)
               (printf "_")
               (set! col (+ col 1))]
              [(eq? '... (syntax-e c))
               (void)]
              [(and (pair? (syntax-e c))
                    (eq? (syntax-e (car (syntax-e c))) 'code:comment))
               (advance c init-line!)
               (printf "; ")
               (display (syntax-e (cadr (syntax->list c))))]
              [(and (pair? (syntax-e c))
                    (eq? (syntax-e (car (syntax-e c))) 'code:contract))
               (advance c init-line!)
               (printf "; ")
               (let* ([l (cdr (syntax->list c))]
                      [s-col (or (syntax-column (first l)) col)])
                 (set! col s-col)
                 (for-each (loop (lambda ()
                                   (set! col s-col)
                                   (printf "; ")))
                           l))]
              [(and (pair? (syntax-e c))
                    (hash-has-key? quotes-table (syntax-e (car (syntax-e c))))
                    (eq? (syntax-span (car (syntax-e c)))
                         (string-length (get-quote c))))
               ;; The above conditions detect the shorthand form of quote and friends
               ;; The shorthand form will read, for instance, '<form>
               ;; as (quote <form>), so the result is guaranteed to be a syntax list
               ;; with exactly two elements in it.
               (advance c init-line!)
               (printf (get-quote c))
               (set! col (+ col (string-length (get-quote c))))
               (let ([i (cadr (syntax->list c))])
                 ((loop init-line!) i))]
              [(pair? (syntax-e c))
               (advance c init-line!)
               (define c-paren-shape (syntax-property c 'paren-shape))
               (printf "~a" (or c-paren-shape #\())
               (set! col (+ col 1))
               (define se (syntax-e c))
               (define (build-string-from-pair sp)
                 (cond
                   [(syntax? sp)
                    (printf " . ")
                    (set! col (+ col 3))
                    ((loop init-line!) sp)]
                   [else
                    ((loop init-line!) (car sp))
                    (build-string-from-pair (cdr sp))]))
               (if (list? se)
                   (map (loop init-line!) se)
                   (build-string-from-pair se))
               (printf (case c-paren-shape
                         [(#\[) "]"]
                         [(#\{) "}"]
                         [else ")"]))
               (set! col (+ col 1))]
              [(vector? (syntax-e c))
               (advance c init-line!)
               (printf "#(")
               (set! col (+ col 2))
               (map (loop init-line!) (vector->list (syntax-e c)))
               (printf ")")
               (set! col (+ col 1))]
              [else
               (advance c init-line!)
               (let ([s (format "~s" (syntax-e c))])
                 (set! col (+ col (string-length s)))
                 (display s))])))
        (for-each (loop (lambda () (set! col init-col))) l))
      (get-output-string s)))
  
  (provide/contract [syntax->string (-> (and/c syntax? stx-list?)
                                        string?)]))