pcs/newpcs/pp.s

542 lines
13 KiB
Common Lisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; -*- Mode: Lisp -*- Filename: pp.s
; Last Revision: 29-August-85 1600ct
;--------------------------------------------------------------------------;
; ;
; SCHEME 84 -- PCS Compiler -- July 1984 ;
; ;
; David Bartley ;
; ;
; PrettyPrinter ;
; ;
;--------------------------------------------------------------------------;
(define pp ; PP
(lambda (exp . args)
(let ((port (car args))
(margin (or (cadr args) 72)))
(fluid-let
((output-port
(cond ((null? port) (fluid output-port))
((port? port) port)
((string? port)
(let ((p (open-output-file port)))
(set-line-length! (max margin (line-length p)) p)
p))
(else 'CONSOLE))))
(%pretty-printer exp
(min margin (line-length (fluid output-port))))
(when (string? port)
(close-output-port (fluid output-port)))
*the-non-printing-object*))))
(define %pp-me ; %PP-ME
(lambda (e)
(let ((m (and (pair? e)
(getprop (car e) 'PCS*MACRO))))
(cond ((null? m)
e)
((pair? m) ; alias
(cons (cdr m)(cdr e)))
(else ; macro
(pp (m e)))))))
(syntax (%pp-set-pattern id pat) ; %PP-SET-PATTERN
(PUTPROP id pat '%PRETTY-PRINTER-PATTERN))
(syntax (%pp-get-pattern id) ; %PP-GET-PATTERN
(GETPROP id '%PRETTY-PRINTER-PATTERN))
;;;
;;; Pretty Printer Pattern Definitions
;;;
(begin
(let ((pattern '(KEY . (2 . V-TAIL)))) ; BEGIN style
(%pp-set-pattern 'BEGIN pattern)
(%pp-set-pattern 'BEGIN0 pattern)
(%pp-set-pattern 'SEQUENCE pattern))
(let ((pattern '(NEAT (() . EXP) . (2 . V-TAIL)))) ; DEFINE style
(%pp-set-pattern 'ALIAS pattern)
(%pp-set-pattern 'ACCESS pattern)
(%pp-set-pattern 'APPLY-IF pattern)
(%pp-set-pattern 'DEFINE pattern)
(%pp-set-pattern 'DEFINE-INTEGRABLE
pattern)
(%pp-set-pattern 'MACRO pattern)
(%pp-set-pattern 'REC pattern)
(%pp-set-pattern 'SET-FLUID! pattern)
(%pp-set-pattern 'SYNTAX pattern))
(let ((pattern '(KEY (() . BVL) . (2 . V-TAIL)))) ; LAMBDA style
(%pp-set-pattern 'LAMBDA pattern)
(%pp-set-pattern 'FLUID-LAMBDA pattern)
(%pp-set-pattern 'NAMED-LAMBDA pattern))
(let ((pattern '(KEY (3 . TUPLES) . (2 . V-TAIL)))) ; LETREC style
(%pp-set-pattern 'LETREC pattern))
(let ((pattern '(0 . LET))) ; LET style
(%pp-set-pattern 'LET pattern)
(%pp-set-pattern 'LET* pattern)
(%pp-set-pattern 'FLUID-LET pattern))
;;(let ((pattern '(NEAT . (() . V-TAIL)))) ; SET! style
;; (%pp-set-pattern 'SET! pattern)
;; (%pp-set-pattern 'IF pattern) ; use default (0 . call)
;; (%pp-set-pattern 'WHEN pattern) ; for these short names
;; (%pp-set-pattern 'AND pattern)
;; (%pp-set-pattern 'OR pattern))
(%pp-set-pattern 'COND '(KEY . (() . COND-TAIL)))
(%pp-set-pattern 'CASE '(KEY (() . EXP) . (2 . CASE-TAIL)))
(%pp-set-pattern 'DO '(KEY (() . TUPLES)
(4 . COMB)
. (2 . V-TAIL)))
(%pp-set-pattern '%PP-FUN-CALL '(0 . CALL)) ; arbitrary function calls
(%pp-set-pattern '%PP-COMBINATION '(0 . COMB)) ; arbitrary combinations
'())
;;; --------------------------------------------------------------------------
(define %pretty-printer
(lambda (expression margin)
(letrec
;-------!
((cp margin) ; current position
(miser-cp (max 20 (quotient margin 2)))
(nice-fit (max 50 (quotient margin 2)))
(call-pat (%pp-get-pattern '%PP-FUN-CALL))
(comb-pat (%pp-get-pattern '%PP-COMBINATION))
;;
;; PP-EXP pretty-prints expression X at the current position
;;
(pp-exp
(lambda (x)
(cond ((atom? x) ; X = atom ?
(pp-atom x))
((atom? (cdr x)) ; X = (atom) or (atom . atom) ?
(pp-block x cp))
((pair? (car x)) ; X = ((...)...) ?
(pp-by-pattern x cp comb-pat))
((and (null? (cddr x)) ; X = (quote ...)
(memq (car x) '(QUOTE
QUASIQUOTE
%QQ-C %QQ-CA %QQ-CD)))
(pp-block x cp))
((and (pair? (cddr x)) ; X = (... . ,value)
(null? (cdddr x))
(eq? (cadr x) '%QQ-C))
(pp-block x cp))
((symbol? (car x)) ; X = (symbol . args) ?
(pp-by-pattern x cp
(or (%pp-get-pattern (car x))
call-pat)))
(else
(pp-block x cp))))) ; X = (?)
;; PP-BY-PATTERN pretty-prints expression X at the current position
;; (passed in IP) using the pattern PAT
;;
;; Assumptions:
;; PAT is a valid pattern
;; X is a pair and (cdr X) is a pair
;; (car X) is an atom
;; X might not be properly structured according to PAT
(pp-by-pattern
(lambda (x ip pat) ; ip = new base for -tabs
(cond
((number? (car pat)) ; PAT = (tab . fun) ?
(move (- ip (car pat)))
(pp-by-function x (cdr pat)))
((null? (car pat)) ; PAT = (() . fun) ?
(move (- cp 1))
(pp-by-function x (cdr pat)))
((and (eq? (car pat) 'NEAT)
(all-fits-nicely? x)) ; X fits neatly on this line?
(pp-block x cp))
;; ((and (eq? (car pat) 'ALL)
;; (all-fits? x)) ; X fits on this line?
;; (pp-block x cp))
(else ; PAT = (KEY ...)
(prin-op x) ; emit paren and keyword
(pp-by-pat-tail (cdr x)
ip ; emit the rest of X
(cdr pat)))
)))
(pp-by-pat-tail
(lambda (x ip pat)
(cond ((or (atom? x) ; X and PAT out of synch?
(null? pat))
(pp-v-tail x)) ; yes, use the default method
((eq? (car x) '%QQ-C)
(pp-block-tail x ip))
(else
(let ((pat1 (car pat))
(pat* (cdr pat)))
(if (atom? pat1)
(begin ; PAT matches the tail
(move (if (null? pat1)
(- cp 1) ; PAT = (() . fun)
(- ip pat1))) ; PAT = (num . fun)
(pp-by-function x pat*))
(let ((tab1 (car pat1))
(fun1 (cdr pat1)))
(move (if (null? tab1)
(- cp 1) ; PAT = ((() . fun) ...)
(- ip tab1))) ; PAT = ((num . fun)...)
(pp-by-function
(car x) fun1) ; pp the car
(pp-by-pat-tail ; pp the cdr
(cdr x) ip pat*))))))))
(pp-by-function
(lambda (x fun)
(if (null? fun)
(pp-call x)
(case fun
(exp (pp-exp x))
(v-tail (pp-v-tail x))
(call (pp-call x))
(bvl (pp-block x cp))
(tuples (pp-tuples x))
(let (pp-let x))
(cond-tail (pp-cond-tail x))
(case-tail (pp-case-tail x))
(comb (pp-comb x))
(else (pp-call x))))))
(pp-let
(lambda (x)
(if (atom? x)
(pp-atom x)
(let ((p cp))
(prin-op x)
(move (- cp 1))
(when (and (cadr x) ; named LET ?
(atom? (cadr x)))
(set! x (cdr x))
(pp-atom (car x)) ; name
(move (- p 5)))
(if (pair? (cdr x))
(begin
(pp-tuples (cadr x)) ; pairs
(move (- p 2))
(pp-v-tail (cddr x))) ; body
(pp-atomic-tail (cdr x)))))))
(pp-call
(lambda (x)
(cond ((or (atom? x)
(null? (cdr x)) ; no arguments
(all-fits-nicely? x))
(pp-block x cp))
((and (symbol? (car x))
( < (print-length (car x)) 5))
(pp-hang x))
(else
(let ((p cp))
(prin-op x)
(move (- p 3))
(pp-v-tail (cdr x)))))))
(pp-comb
(lambda (x)
(cond ((or (atom? x)
(and (pair? (cdr x)) ; length = 2 ?
(null? (cddr x))
(all-fits-nicely? x)))
(pp-block x cp))
((and (symbol? (car x))
( < (print-length (car x)) 5))
(pp-hang x))
(else
(pp-v x)))))
(pp-case-tail
(lambda (x)
(if (atom? x)
(pp-atomic-tail x)
(let ((p cp)
(next (car x))
(rest (cdr x)))
(pp-case-item next)
(if (null? rest)
(pp-atomic-tail rest)
(begin
(move p)
(pp-case-tail rest)))))))
(pp-case-item
(lambda (x)
(cond ((atom? x)
(pp-atom x))
((all-fits-nicely? x)
(pp-block x cp))
(else
(display "(")
(set! cp (- cp 1))
(let ((p cp))
(pp-block (car x) cp)
(move p)
(pp-v-tail (cdr x)))))))
(pp-cond-tail
(lambda (x)
(if (atom? x)
(pp-atomic-tail x)
(let ((p cp)
(next (car x))
(rest (cdr x)))
(pp-comb next)
(if (null? rest)
(pp-atomic-tail rest)
(begin
(move p)
(pp-cond-tail rest)))))))
(pp-tuples
(lambda (x)
(if (and x (atom? x))
(pp-atom x)
(begin
(display "(")
(set! cp (- cp 1))
(pp-tuples-tail x)))))
(pp-tuples-tail
(lambda (x)
(if (atom? x)
(pp-atomic-tail x)
(let ((p cp)
(next (car x))
(rest (cdr x)))
(if (or (atom? next)
(all-fits-nicely? next))
(pp-block next cp)
(pp-comb next))
(if (null? rest)
(pp-atomic-tail rest)
(begin
(move p)
(pp-tuples-tail rest)))))))
(pp-hang
(lambda (x)
(if (atom? x)
(pp-atom x)
(begin
(prin-op x)
(move (- cp 1))
(pp-v-tail (cdr x))))))
(pp-v
(lambda (x)
(if (and x (atom? x))
(pp-atom x)
(begin
(display "(")
(set! cp (- cp 1))
(pp-v-tail x)))))
(pp-v-tail
(lambda (x)
(cond ((atom? x)
(pp-atomic-tail x))
((eq? (car x) '%QQ-C)
(pp-block-tail x cp))
(else
(let ((p cp)
(next (car x))
(rest (cdr x)))
(pp-exp next)
(if (null? rest)
(pp-atomic-tail rest)
(begin
(move p)
(pp-v-tail rest))))))))
(pp-block
(lambda (x ip)
(if (atom? x)
(pp-atom x)
(let ((quasi (assq (car x)
'((QUOTE . "'")
(QUASIQUOTE . "`")
(%QQ-C . ",")
(%QQ-CA . ",@")
(%QQ-CD . ",.")))))
(cond ((and quasi
(pair? (cdr x))
(null? (cddr x)))
(let* ((prefix (cdr quasi))
(len (string-length prefix)))
(display prefix)
(set! cp (- cp len))
(pp-block (cadr x) (- ip len))))
(else
(display "(")
(set! cp (- cp 1))
(pp-block-tail x (- ip 1))) )))))
(pp-block-tail
(lambda (x ip)
(cond ((atom? x)
(pp-atomic-tail x))
((and (eq? (car x) '%QQ-C)
(pair? (cdr x))
(null? (cddr x)))
(display " . ,")
(set! cp (- cp 4))
(pp-block (cadr x)(- ip 4))
(display ")")
(set! cp (- cp 1)))
(else
(let* ((carx (car x))
(fits (all-fits? carx)))
(cond ((and (not fits)
(>? ip cp))
(move ip)
(pp-block-tail x ip))
(else
(if fits ; print the CAR
(pp-block carx ip)
(begin
(pp-exp carx)
(move ip)))
(if (atom? (cdr x)) ; print the CDR
(pp-atomic-tail (cdr x))
(begin
(move (- cp 1))
(pp-block-tail (cdr x) ip))))))))))
(pp-atom
(lambda (x)
(write x)
(set! cp (- margin
(- (current-column) 1)))))
(pp-atomic-tail
(lambda (x)
(cond ((null? x)
(display ")")
(set! cp (- cp 1)))
(else
(display " . ")
(set! cp (- cp 3))
(pp-atom x)
(display ")")
(set! cp (- cp 1))))))
(prin-op
(lambda (x)
(let ((op (car x))
(p cp))
(display "(")
(set! cp (- cp 1))
(pp-block op cp)
;; (when ( < cp miser-cp) ;; causes a bug??
;; (move (- p 2)))
)))
(move
(lambda (p)
(when ( < cp p)
(newline) ; move left
(set! cp margin))
(when ( > cp p)
(let ((cp4 (- cp 4))) ; move right
(if ( >= cp4 p)
(begin
(display " ")
(set! cp cp4))
(begin
(display " ")
(set! cp (- cp 1)))))
(move p))))
(all-fits?
(lambda (x)
(fits-in? x cp 0)))
(all-fits-nicely?
(lambda (x)
(fits-in? x (min cp nice-fit) 0)))
(fits-in? ; returns length[X] if <= SIZE
(lambda (x space acc) ; returns #!FALSE otherwise
(cond ((pair? x)
(fits-in-tail? x space acc))
((or (symbol? x) (number? x) (string? x)
(char? x) (null? x))
(let ((len (print-length x))) ; broken
(and ( >= space len)
(+ acc len))))
(else #!false))))
(fits-in-tail?
(lambda (x space acc)
(cond ((null? acc) #!false)
(( < space 2) #!false)
((null? x) (+ acc 1))
((atom? x) (fits-in? x (- space 4)(+ acc 4)))
(else
(let ((len (fits-in? (car x) space 0)))
(and len
(fits-in-tail? (cdr x)
(- (- space len) 1)
(+ (+ acc len) 1))))))))
(make-printable
(lambda (obj)
(cond ((closure? obj)
(apply-if (assq 'SOURCE (%reify obj 0))
(lambda (entry)
(display obj)
(display " =")
(newline)
(cdr entry))
obj))
;; other special cases ...
(else obj))))
;-------!
)
(begin
(pp-exp (make-printable expression))
*the-non-printing-object*))))