1 ! Copyright (C) 2003, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs byte-arrays byte-vectors classes
4 classes.algebra.private classes.maybe classes.private
5 classes.tuple combinators combinators.short-circuit
6 continuations effects generic hash-sets hashtables io.pathnames
7 io.styles kernel lists make math math.order math.parser
8 namespaces prettyprint.config prettyprint.custom
9 prettyprint.sections prettyprint.stylesheet quotations sbufs
10 sequences strings vectors words ;
12 IN: prettyprint.backend
14 M: effect pprint* effect>string text ;
16 : ?effect-height ( word -- n )
17 stack-effect [ effect-height ] [ 0 ] if* ;
19 : ?start-group ( word -- )
20 ?effect-height 0 > [ start-group ] when ;
22 : ?end-group ( word -- )
23 ?effect-height 0 < [ end-group ] when ;
26 GENERIC: word-name* ( obj -- str )
29 class-name "maybe{ " " }" surround ;
31 M: anonymous-complement word-name*
32 class-name "not{ " " }" surround ;
34 M: anonymous-union word-name*
35 class-name "union{ " " }" surround ;
37 M: anonymous-intersection word-name*
38 class-name "intersection{ " " }" surround ;
41 [ name>> "( no name )" or ] [ record-vocab ] bi ;
43 : pprint-word ( word -- )
44 [ word-name* ] [ word-style ] bi styled-text ;
46 GENERIC: pprint-class ( obj -- )
48 M: classoid pprint-class pprint* ;
50 M: class pprint-class \ f or pprint-word ;
52 M: word pprint-class pprint-word ;
54 : pprint-prefix ( word quot -- )
55 <block swap pprint-word call block> ; inline
57 M: parsing-word pprint*
58 \ POSTPONE: [ pprint-word ] pprint-prefix ;
61 [ pprint-word ] [ ?start-group ] [ ?end-group ] tri ;
65 [ \ M\ pprint-word "method-class" word-prop pprint* ]
66 [ "method-generic" word-prop pprint-word ] bi
69 : pprint-prefixed-number ( n quot: ( n -- n' ) pre -- )
71 [ [ neg ] [ call ] [ prepend ] tri* "-" prepend text ]
72 [ [ call ] [ prepend ] bi* text ] if ; inline
74 ERROR: unsupported-number-base n base ;
78 { 10 [ number>string text ] }
79 { 16 [ [ >hex ] "0x" pprint-prefixed-number ] }
80 { 8 [ [ >oct ] "0o" pprint-prefixed-number ] }
81 { 2 [ [ >bin ] "0b" pprint-prefixed-number ] }
82 [ unsupported-number-base ]
87 { [ dup 0/0. fp-bitwise= ] [ drop "0/0." text ] }
88 { [ dup -0/0. fp-bitwise= ] [ drop "-0/0." text ] }
91 [ fp-nan-payload ] [ fp-sign ] bi
92 [ 0xfffffffffffff bitxor 1 + neg ] when >hex text
95 { [ dup 1/0. = ] [ drop "1/0." text ] }
96 { [ dup -1/0. = ] [ drop "-1/0." text ] }
97 { [ dup 0.0 fp-bitwise= ] [ drop "0.0" text ] }
98 { [ dup -0.0 fp-bitwise= ] [ drop "-0.0" text ] }
102 M: f pprint* drop \ f pprint-word ;
104 : pprint-effect ( effect -- )
105 [ effect>string ] [ effect-style ] bi styled-text ;
108 : ch>ascii-escape ( ch -- ch' ? )
119 { CHAR: \\ CHAR: \\ }
120 { CHAR: \" CHAR: \" }
123 : unparse-ch ( ch -- )
124 ch>ascii-escape [ CHAR: \\ , , ] [
125 dup 32 < [ dup 16 < "\\x0" "\\x" ? % >hex % ] [ , ] if
128 : do-string-limit ( str -- trimmed )
130 dup length margin get > [
131 margin get 3 - head "..." append
135 : unparse-string ( str prefix suffix -- str )
136 [ [ % do-string-limit [ unparse-ch ] each ] dip % ] "" make ;
138 : pprint-string ( obj str prefix suffix -- )
139 unparse-string swap string-style styled-text ;
142 dup "\"" "\"" pprint-string ;
145 dup "SBUF\" " "\"" pprint-string ;
148 dup string>> "P\" " "\"" pprint-string ;
151 : nesting-limit? ( -- ? )
152 nesting-limit get dup [ pprinter-stack get length < ] when ;
154 : present-text ( str obj -- )
155 presented associate styled-text ;
157 : check-recursion ( obj quot: ( obj -- ) -- )
160 [ class-of name>> "~" 1surround ] keep present-text
162 over recursion-check get member-eq? [
163 drop "~circularity~" swap present-text
165 over recursion-check get push
167 recursion-check get pop*
171 : filter-tuple-assoc ( slot,value -- name,value )
172 [ [ initial>> ] dip = ] assoc-reject
173 [ [ name>> ] dip ] assoc-map ;
175 : tuple>assoc ( tuple -- assoc )
176 [ class-of all-slots ] [ tuple-slots ] bi zip filter-tuple-assoc ;
178 : pprint-slot-value ( name value -- )
179 <flow \ { pprint-word
180 [ text ] [ f <inset pprint* block> ] bi*
181 \ } pprint-word block> ;
183 : (pprint-tuple) ( opener class slots closer -- )
187 [ t <inset [ pprint-slot-value ] assoc-each block> ]
191 : ?pprint-tuple ( tuple quot -- )
192 [ boa-tuples? get [ pprint-object ] ] dip [ check-recursion ] curry if ; inline
194 : pprint-tuple ( tuple -- )
195 [ [ \ T{ ] dip [ class-of ] [ tuple>assoc ] bi \ } (pprint-tuple) ] ?pprint-tuple ;
200 : recover-pprint ( try recovery -- )
201 pprinter-stack get clone
202 [ pprinter-stack set ] curry prepose recover ; inline
204 : pprint-c-object ( object content-quot pointer-quot -- )
205 [ c-object-pointers? get ] 2dip
207 [ [ drop ] prepose [ recover-pprint ] 2curry ] 2bi if ; inline
209 : do-length-limit ( seq -- trimmed n/f )
210 length-limit get dup [
211 1 - over length over [-]
212 dup 1 > [ [ head-slice ] dip ] [ 2drop f ] if
215 : pprint-elements ( seq -- )
217 [ [ pprint* ] each ] dip
218 [ number>string "~" " more~" surround text ] when* ;
220 M: quotation pprint-delims drop \ [ \ ] ;
221 M: curried pprint-delims drop \ [ \ ] ;
222 M: composed pprint-delims drop \ [ \ ] ;
223 M: array pprint-delims drop \ { \ } ;
224 M: byte-array pprint-delims drop \ B{ \ } ;
225 M: byte-vector pprint-delims drop \ BV{ \ } ;
226 M: vector pprint-delims drop \ V{ \ } ;
227 M: cons-state pprint-delims drop \ L{ \ } ;
228 M: +nil+ pprint-delims drop \ L{ \ } ;
229 M: hashtable pprint-delims drop \ H{ \ } ;
230 M: tuple pprint-delims drop \ T{ \ } ;
231 M: wrapper pprint-delims drop \ W{ \ } ;
232 M: callstack pprint-delims drop \ CS{ \ } ;
233 M: hash-set pprint-delims drop \ HS{ \ } ;
234 M: anonymous-union pprint-delims drop \ union{ \ } ;
235 M: anonymous-intersection pprint-delims drop \ intersection{ \ } ;
236 M: anonymous-complement pprint-delims drop \ not{ \ } ;
237 M: maybe pprint-delims drop \ maybe{ \ } ;
239 M: object >pprint-sequence ;
240 M: vector >pprint-sequence ;
241 M: byte-vector >pprint-sequence ;
242 M: callable >pprint-sequence ;
243 M: hashtable >pprint-sequence >alist ;
244 M: wrapper >pprint-sequence wrapped>> 1array ;
245 M: callstack >pprint-sequence callstack>array ;
246 M: hash-set >pprint-sequence sets:members ;
247 M: anonymous-union >pprint-sequence members>> ;
248 M: anonymous-intersection >pprint-sequence participants>> ;
249 M: anonymous-complement >pprint-sequence class>> 1array ;
250 M: maybe >pprint-sequence class>> 1array ;
252 : class-slot-sequence ( class slots -- sequence )
253 [ 1array ] [ [ f 2array ] dip append ] if-empty ;
255 M: tuple >pprint-sequence
256 [ class-of ] [ tuple-slots ] bi class-slot-sequence ;
258 M: object pprint-narrow? drop f ;
259 M: byte-vector pprint-narrow? drop f ;
260 M: array pprint-narrow? drop t ;
261 M: vector pprint-narrow? drop t ;
262 M: hashtable pprint-narrow? drop t ;
263 M: tuple pprint-narrow? drop t ;
265 M: object pprint-object
270 dup pprint-narrow? <inset
271 >pprint-sequence pprint-elements
273 ] dip pprint-word block>
276 M: object pprint* pprint-object ;
277 M: vector pprint* pprint-object ;
278 M: byte-vector pprint* pprint-object ;
280 M: cons-state pprint*
285 dup pprint-narrow? <inset
289 '[ dup cons-state? _ length _ < and ]
290 [ uncons swap , ] while
294 nil? [ "~more~" text ] unless
299 ] dip pprint-word block>
303 <flow pprint-delims [ pprint-word ] bi@ block> ;
305 : with-extra-nesting-level ( quot -- )
306 nesting-limit [ dup [ 1 + ] [ f ] if* ] change
307 [ nesting-limit set ] curry finally ; inline
310 [ pprint-object ] with-extra-nesting-level ;
311 M: curried pprint* pprint-object ;
312 M: composed pprint* pprint-object ;
313 M: hash-set pprint* pprint-object ;
314 M: anonymous-union pprint* pprint-object ;
315 M: anonymous-intersection pprint* pprint-object ;
316 M: anonymous-complement pprint* pprint-object ;
317 M: maybe pprint* pprint-object ;
321 { [ dup wrapped>> method? ] [ wrapped>> pprint* ] }
322 { [ dup wrapped>> word? ] [ <block \ \ pprint-word wrapped>> pprint-word block> ] }