! Copyright (C) 2003, 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays assocs byte-arrays byte-vectors classes classes.algebra.private classes.intersection classes.maybe classes.tuple classes.tuple.private classes.union colors colors.constants combinators continuations effects generic hash-sets hashtables io io.pathnames io.styles kernel make math math.order math.parser namespaces prettyprint.config prettyprint.custom prettyprint.sections prettyprint.stylesheet quotations sbufs sequences strings vectors words words.symbol classes.private ; FROM: sets => members ; IN: prettyprint.backend M: effect pprint* effect>string text ; : ?effect-height ( word -- n ) stack-effect [ effect-height ] [ 0 ] if* ; : ?start-group ( word -- ) ?effect-height 0 > [ start-group ] when ; : ?end-group ( word -- ) ?effect-height 0 < [ end-group ] when ; ! Atoms GENERIC: word-name* ( obj -- str ) M: maybe word-name* class-name "maybe{ " " }" surround ; M: anonymous-complement word-name* class-name "not{ " " }" surround ; M: anonymous-union word-name* class-name "union{ " " }" surround ; M: anonymous-intersection word-name* class-name "intersection{ " " }" surround ; M: word word-name* ( word -- str ) [ name>> "( no name )" or ] [ record-vocab ] bi ; : pprint-word ( word -- ) [ word-name* ] [ word-style ] bi styled-text ; GENERIC: pprint-class ( obj -- ) M: classoid pprint-class pprint* ; M: class pprint-class \ f or pprint-word ; M: word pprint-class pprint-word ; : pprint-prefix ( word quot -- ) ; inline M: parsing-word pprint* \ POSTPONE: [ pprint-word ] pprint-prefix ; M: word pprint* [ pprint-word ] [ ?start-group ] [ ?end-group ] tri ; M: method pprint* ; : pprint-prefixed-number ( n quot: ( n -- n' ) pre -- ) pick neg? [ [ neg ] [ call ] [ prepend ] tri* "-" prepend text ] [ [ call ] [ prepend ] bi* text ] if ; inline M: real pprint* number-base get { { 16 [ [ >hex ] "0x" pprint-prefixed-number ] } { 8 [ [ >oct ] "0o" pprint-prefixed-number ] } { 2 [ [ >bin ] "0b" pprint-prefixed-number ] } [ drop number>string text ] } case ; M: float pprint* dup fp-nan? [ \ NAN: [ fp-nan-payload >hex text ] pprint-prefix ] [ number-base get { { 16 [ [ >hex ] "0x" pprint-prefixed-number ] } [ drop number>string text ] } case ] if ; M: f pprint* drop \ f pprint-word ; : pprint-effect ( effect -- ) [ effect>string ] [ effect-style ] bi styled-text ; ! Strings : ch>ascii-escape ( ch -- ch' ? ) H{ { CHAR: \a CHAR: a } { CHAR: \e CHAR: e } { CHAR: \n CHAR: n } { CHAR: \r CHAR: r } { CHAR: \t CHAR: t } { CHAR: \0 CHAR: 0 } { CHAR: \\ CHAR: \\ } { CHAR: \" CHAR: \" } } ?at ; inline : unparse-ch ( ch -- ) ch>ascii-escape [ "\\" % , ] [ dup 32 < [ dup 16 < "\\x0" "\\x" ? % >hex % ] [ , ] if ] if ; : do-string-limit ( str -- trimmed ) string-limit? get [ dup length margin get > [ margin get 3 - head "..." append ] when ] when ; : unparse-string ( str prefix suffix -- str ) [ [ % do-string-limit [ unparse-ch ] each ] dip % ] "" make ; : pprint-string ( obj str prefix suffix -- ) unparse-string swap string-style styled-text ; M: string pprint* dup "\"" "\"" pprint-string ; M: sbuf pprint* dup "SBUF\" " "\"" pprint-string ; M: pathname pprint* dup string>> "P\" " "\"" pprint-string ; ! Sequences : nesting-limit? ( -- ? ) nesting-limit get dup [ pprinter-stack get length < ] when ; : present-text ( str obj -- ) presented associate styled-text ; : check-recursion ( obj quot -- ) nesting-limit? [ drop [ class-of name>> "~" dup surround ] keep present-text ] [ over recursion-check get member-eq? [ drop "~circularity~" swap present-text ] [ over recursion-check get push call recursion-check get pop* ] if ] if ; inline : filter-tuple-assoc ( slot,value -- name,value ) [ [ initial>> ] dip = not ] assoc-filter [ [ name>> ] dip ] assoc-map ; : tuple>assoc ( tuple -- assoc ) [ class-of all-slots ] [ tuple-slots ] bi zip filter-tuple-assoc ; : pprint-slot-value ( name value -- ) ] bi* \ } pprint-word block> ; : (pprint-tuple) ( opener class slots closer -- ) ] [ pprint-word ] } spread block> ; : ?pprint-tuple ( tuple quot -- ) [ boa-tuples? get [ pprint-object ] ] dip [ check-recursion ] curry if ; inline : pprint-tuple ( tuple -- ) [ [ \ T{ ] dip [ class-of ] [ tuple>assoc ] bi \ } (pprint-tuple) ] ?pprint-tuple ; M: tuple pprint* pprint-tuple ; : recover-pprint ( try recovery -- ) pprinter-stack get clone [ pprinter-stack set ] curry prepose recover ; inline : pprint-c-object ( object content-quot pointer-quot -- ) [ c-object-pointers? get ] 2dip [ nip ] [ [ drop ] prepose [ recover-pprint ] 2curry ] 2bi if ; inline : do-length-limit ( seq -- trimmed n/f ) length-limit get dup [ 1 - over length over [-] dup 1 > [ [ head-slice ] dip ] [ 2drop f ] if ] when ; : pprint-elements ( seq -- ) do-length-limit [ [ pprint* ] each ] dip [ number>string "~" " more~" surround text ] when* ; M: quotation pprint-delims drop \ [ \ ] ; M: curry pprint-delims drop \ [ \ ] ; M: compose pprint-delims drop \ [ \ ] ; M: array pprint-delims drop \ { \ } ; M: byte-array pprint-delims drop \ B{ \ } ; M: byte-vector pprint-delims drop \ BV{ \ } ; M: vector pprint-delims drop \ V{ \ } ; M: hashtable pprint-delims drop \ H{ \ } ; M: tuple pprint-delims drop \ T{ \ } ; M: wrapper pprint-delims drop \ W{ \ } ; M: callstack pprint-delims drop \ CS{ \ } ; M: hash-set pprint-delims drop \ HS{ \ } ; M: anonymous-union pprint-delims drop \ union{ \ } ; M: anonymous-intersection pprint-delims drop \ intersection{ \ } ; M: anonymous-complement pprint-delims drop \ not{ \ } ; M: maybe pprint-delims drop \ maybe{ \ } ; M: object >pprint-sequence ; M: vector >pprint-sequence ; M: byte-vector >pprint-sequence ; M: callable >pprint-sequence ; M: hashtable >pprint-sequence >alist ; M: wrapper >pprint-sequence wrapped>> 1array ; M: callstack >pprint-sequence callstack>array ; M: hash-set >pprint-sequence members ; M: anonymous-union >pprint-sequence members>> ; M: anonymous-intersection >pprint-sequence participants>> ; M: anonymous-complement >pprint-sequence class>> 1array ; M: maybe >pprint-sequence class>> 1array ; : class-slot-sequence ( class slots -- sequence ) [ 1array ] [ [ f 2array ] dip append ] if-empty ; M: tuple >pprint-sequence [ class-of ] [ tuple-slots ] bi class-slot-sequence ; M: object pprint-narrow? drop f ; M: byte-vector pprint-narrow? drop f ; M: array pprint-narrow? drop t ; M: vector pprint-narrow? drop t ; M: hashtable pprint-narrow? drop t ; M: tuple pprint-narrow? drop t ; M: object pprint-object ( obj -- ) [ pprint-sequence pprint-elements block> ] dip pprint-word block> ] check-recursion ; M: object pprint* pprint-object ; M: vector pprint* pprint-object ; M: byte-vector pprint* pprint-object ; : with-extra-nesting-level ( quot -- ) nesting-limit [ dup [ 1 + ] [ f ] if* ] change [ nesting-limit set ] curry [ ] cleanup ; inline M: hashtable pprint* [ pprint-object ] with-extra-nesting-level ; M: curry pprint* pprint-object ; M: compose pprint* pprint-object ; M: hash-set pprint* pprint-object ; M: anonymous-union pprint* pprint-object ; M: anonymous-intersection pprint* pprint-object ; M: anonymous-complement pprint* pprint-object ; M: maybe pprint* pprint-object ; M: wrapper pprint* { { [ dup wrapped>> method? ] [ wrapped>> pprint* ] } { [ dup wrapped>> word? ] [ > pprint-word block> ] } [ pprint-object ] } cond ;