]> gitweb.factorcode.org Git - factor.git/blob - basis/prettyprint/backend/backend.factor
1976c84fd1348213b78f781451514851ecd337fb
[factor.git] / basis / prettyprint / backend / backend.factor
1 ! Copyright (C) 2003, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays byte-arrays generic hashtables io assocs
4 kernel math namespaces make sequences strings sbufs vectors
5 words prettyprint.config prettyprint.custom prettyprint.sections
6 quotations io io.pathnames io.styles math.parser effects
7 classes.tuple math.order classes.tuple.private classes
8 combinators colors ;
9 IN: prettyprint.backend
10
11 M: effect pprint* effect>string "(" ")" surround text ;
12
13 : ?effect-height ( word -- n )
14     stack-effect [ effect-height ] [ 0 ] if* ;
15
16 : ?start-group ( word -- )
17     ?effect-height 0 > [ start-group ] when ;
18
19 : ?end-group ( word -- )
20     ?effect-height 0 < [ end-group ] when ;
21
22 ! Atoms
23 : word-style ( word -- style )
24     dup "word-style" word-prop >hashtable [
25         [
26             [ presented set ]
27             [
28                 [ parsing-word? ] [ delimiter? ] [ t eq? ] tri or or
29                 [ bold font-style set ] when
30             ] bi
31         ] bind
32     ] keep ;
33
34 : word-name* ( word -- str )
35     name>> "( no name )" or ;
36
37 : pprint-word ( word -- )
38     [ record-vocab ]
39     [ [ word-name* ] [ word-style ] bi styled-text ] bi ;
40
41 : pprint-prefix ( word quot -- )
42     <block swap pprint-word call block> ; inline
43
44 M: parsing-word pprint*
45     \ POSTPONE: [ pprint-word ] pprint-prefix ;
46
47 M: word pprint*
48     [ pprint-word ] [ ?start-group ] [ ?end-group ] tri ;
49
50 M: method-body pprint*
51     [
52         [
53             [ "M\\ " % "method-class" word-prop word-name* % ]
54             [ " " % "method-generic" word-prop word-name* % ] bi
55         ] "" make
56     ] [ word-style ] bi styled-text ;
57
58 M: real pprint* number>string text ;
59
60 M: f pprint* drop \ f pprint-word ;
61
62 ! Strings
63 : ch>ascii-escape ( ch -- str )
64     H{
65         { CHAR: \a CHAR: a  }
66         { CHAR: \e CHAR: e  }
67         { CHAR: \n CHAR: n  }
68         { CHAR: \r CHAR: r  }
69         { CHAR: \t CHAR: t  }
70         { CHAR: \0 CHAR: 0  }
71         { CHAR: \\ CHAR: \\ }
72         { CHAR: \" CHAR: \" }
73     } at ;
74
75 : unparse-ch ( ch -- )
76     dup ch>ascii-escape [ "\\" % ] [ ] ?if , ;
77
78 : do-string-limit ( str -- trimmed )
79     string-limit? get [
80         dup length margin get > [
81             margin get 3 - head "..." append
82         ] when
83     ] when ;
84
85 : string-style ( obj -- hash )
86     [
87         presented set
88         T{ rgba f 0.3 0.3 0.3 1.0 } foreground set
89     ] H{ } make-assoc ;
90
91 : unparse-string ( str prefix suffix -- str )
92     [ [ % do-string-limit [ unparse-ch ] each ] dip % ] "" make ;
93
94 : pprint-string ( obj str prefix suffix -- )
95     unparse-string swap string-style styled-text ;
96
97 M: string pprint*
98     dup "\"" "\"" pprint-string ;
99
100 M: sbuf pprint*
101     dup "SBUF\" " "\"" pprint-string ;
102
103 M: pathname pprint*
104     dup string>> "P\" " "\"" pprint-string ;
105
106 ! Sequences
107 : nesting-limit? ( -- ? )
108     nesting-limit get dup [ pprinter-stack get length < ] when ;
109
110 : present-text ( str obj -- )
111     presented associate styled-text ;
112
113 : check-recursion ( obj quot -- )
114     nesting-limit? [
115         drop
116         "~" over class name>> "~" 3append
117         swap present-text
118     ] [
119         over recursion-check get memq? [
120             drop "~circularity~" swap present-text
121         ] [
122             over recursion-check get push
123             call
124             recursion-check get pop*
125         ] if
126     ] if ; inline
127
128 : tuple>assoc ( tuple -- assoc )
129     [ class all-slots ] [ tuple-slots ] bi zip
130     [ [ initial>> ] dip = not ] assoc-filter
131     [ [ name>> ] dip ] assoc-map ;
132
133 : pprint-slot-value ( name value -- )
134     <flow \ { pprint-word
135     [ text ] [ f <inset pprint* block> ] bi*
136     \ } pprint-word block> ;
137
138 M: tuple pprint*
139     boa-tuples? get [ call-next-method ] [
140         [
141             <flow
142             \ T{ pprint-word
143             dup class pprint-word
144             t <inset
145             tuple>assoc [ pprint-slot-value ] assoc-each
146             block>
147             \ } pprint-word
148             block>
149         ] check-recursion
150     ] if ;
151
152 : do-length-limit ( seq -- trimmed n/f )
153     length-limit get dup [
154         over length over [-]
155         dup zero? [ 2drop f ] [ [ head ] dip ] if
156     ] when ;
157
158 : pprint-elements ( seq -- )
159     do-length-limit
160     [ [ pprint* ] each ] dip
161     [ "~" swap number>string " more~" 3append text ] when* ;
162
163 M: quotation pprint-delims drop \ [ \ ] ;
164 M: curry pprint-delims drop \ [ \ ] ;
165 M: compose pprint-delims drop \ [ \ ] ;
166 M: array pprint-delims drop \ { \ } ;
167 M: byte-array pprint-delims drop \ B{ \ } ;
168 M: vector pprint-delims drop \ V{ \ } ;
169 M: hashtable pprint-delims drop \ H{ \ } ;
170 M: tuple pprint-delims drop \ T{ \ } ;
171 M: wrapper pprint-delims drop \ W{ \ } ;
172 M: callstack pprint-delims drop \ CS{ \ } ;
173
174 M: object >pprint-sequence ;
175 M: vector >pprint-sequence ;
176 M: curry >pprint-sequence ;
177 M: compose >pprint-sequence ;
178 M: hashtable >pprint-sequence >alist ;
179 M: wrapper >pprint-sequence wrapped>> 1array ;
180 M: callstack >pprint-sequence callstack>array ;
181
182 M: tuple >pprint-sequence
183     [ class ] [ tuple-slots ] bi
184     [ 1array ] [ [ f 2array ] dip append ] if-empty ;
185
186 M: object pprint-narrow? drop f ;
187 M: array pprint-narrow? drop t ;
188 M: vector pprint-narrow? drop t ;
189 M: hashtable pprint-narrow? drop t ;
190 M: tuple pprint-narrow? drop t ;
191
192 M: object pprint-object ( obj -- )
193     [
194         <flow
195         dup pprint-delims [
196             pprint-word
197             dup pprint-narrow? <inset
198             >pprint-sequence pprint-elements
199             block>
200         ] dip pprint-word block>
201     ] check-recursion ;
202
203 M: object pprint* pprint-object ;
204 M: vector pprint* pprint-object ;
205 M: hashtable pprint* pprint-object ;
206 M: curry pprint* pprint-object ;
207 M: compose pprint* pprint-object ;
208
209 M: wrapper pprint*
210     {
211         { [ dup wrapped>> method-body? ] [ wrapped>> pprint* ] }
212         { [ dup wrapped>> word? ] [ <block \ \ pprint-word wrapped>> pprint-word block> ] }
213         [ pprint-object ]
214     } cond ;