blob: 8bf8222e259cfbb114bedbb196056f98968ec258 (
about) (
plain)
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
|
#lang racket
(require pict)
(define CELL-SIZE 30)
(define ARROW-LENGTH 40)
(define ARROW-SIZE 15)
(define (square n)
(rectangle n n))
(define (need-arrow? x)
(or (pair? x)
(< 2 (string-length (~a x)))))
(define (pict-cell x)
(cond
[(need-arrow? x)
(cc-superimpose (square CELL-SIZE)
(scale (filled-ellipse CELL-SIZE CELL-SIZE) 1/4))]
[else
(cc-superimpose (square CELL-SIZE)
(text (~a x)))]))
(define (pict-cons-cell pair)
(hc-append -1
(pict-cell (car pair))
(pict-cell (cdr pair))))
(define (cdr-find _ p)
(values (- (pict-width p) (/ CELL-SIZE 2.0))
(/ CELL-SIZE 2.0)))
(define (car-find p _)
(values (/ CELL-SIZE 2.0)
(/ CELL-SIZE 2.0)))
(define (left-find p p1)
(values (- (pict-width p) (pict-width p1))
(/ CELL-SIZE 2.0)))
(define (top-find p p1)
(values (/ CELL-SIZE 2.0)
(- (pict-height p) (pict-height p1))))
(define (horizontal-combined p1 p2)
(ht-append ARROW-LENGTH p1 p2))
(define (vertical-combined n p1 p2)
(vl-append (- (* (+ CELL-SIZE ARROW-LENGTH) n)
(pict-height p1))
p1 p2))
(define (arrow-from-cdr p1 p2)
(pin-arrow-line ARROW-SIZE
(horizontal-combined p1 p2)
p1 cdr-find
p2 left-find))
(define (arrow-from-car n p1 p2)
(pin-arrow-line ARROW-SIZE
(vertical-combined n p1 p2)
p1 car-find
p2 top-find))
(define (pict-atom x)
(cc-superimpose (cellophane (filled-rectangle CELL-SIZE CELL-SIZE) 0)
(text (~a x))))
(define (cdr* lst)
(if (null? lst)
'()
(cdr lst)))
(define (pict-sexp/helper sexp height-list fail)
(when (and (pair? height-list)
(<= 0 (car height-list)))
(fail))
(cond
[(pair? sexp)
(let*-values ([(cell) (pict-cons-cell sexp)]
[(cell-1 height-list)
(cond
[(need-arrow? (cdr sexp))
(let-values ([(pict-cdr cdr-height-list)
(pict-sexp/helper (cdr sexp)
(cdr* height-list)
fail)])
(values (arrow-from-cdr cell pict-cdr)
(cons 0 cdr-height-list)))]
[else (values cell (cons 0 (cdr* height-list)))])]
[(cell-2 height-list)
(cond
[(need-arrow? (car sexp))
(let retry ([len 1] [height-list (map sub1 height-list)])
(let/cc escape
(let/cc fail
(let-values ([(pict-car height-list)
(pict-sexp/helper (car sexp)
height-list
fail)])
(escape (arrow-from-car len cell pict-car)
(map (λ (x) (+ x len)) height-list))))
(retry (add1 len) (map sub1 height-list))))]
[else (values cell height-list)])])
(values (lt-superimpose cell-1 cell-2) height-list))]
[else
(values (pict-atom sexp) (cons 0 (cdr* height-list)))]))
(define (pict-sexp sexp)
(define-values (result height-list)
(pict-sexp/helper sexp '() (λ () (error "pict-sexp: implementation error"))))
result)
(provide pict-sexp)
|