|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 12246 (0x2fd6)
Types: TextFile
Names: »unpars.scm.31«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/gnu-31mar87/scheme/scm/unpars.scm.31«
;;; -*-Scheme-*-
;;;
;;; Copyright (c) 1984 Massachusetts Institute of Technology
;;;
;;; This material was developed by the Scheme project at the
;;; Massachusetts Institute of Technology, Department of
;;; Electrical Engineering and Computer Science. Permission to
;;; copy this software, to redistribute it, and to use it for any
;;; purpose is granted, subject to the following restrictions and
;;; understandings.
;;;
;;; 1. Any copy made of this software must include this copyright
;;; notice in full.
;;;
;;; 2. Users of this software agree to make their best efforts (a)
;;; to return to the MIT Scheme project any improvements or
;;; extensions that they make, so that these may be included in
;;; future releases; and (b) to inform MIT of noteworthy uses of
;;; this software.
;;;
;;; 3. All materials developed as a consequence of the use of
;;; this software shall duly acknowledge such use, in accordance
;;; with the usual standards of acknowledging credit in academic
;;; research.
;;;
;;; 4. MIT has made no warrantee or representation that the
;;; operation of this software will be error-free, and MIT is
;;; under no obligation to provide any services, by way of
;;; maintenance, update, or otherwise.
;;;
;;; 5. In conjunction with products arising from the use of this
;;; material, there shall be no use of the name of the
;;; Massachusetts Institute of Technology nor of any adaptation
;;; thereof in any advertising, promotional, or sales literature
;;; without prior written consent from MIT in each case.
;;;
;;;; Unparsers
(declare (usual-integrations))
\f
;;; This package contains procedures that convert various kinds of
;;; objects into sequences of characters. It is defined in terms of
;;; the following procedures:
;;; (*UNPARSE-CHARACTER character)
;;; (*UNPARSE-STRING string)
;;; (*UNPARSE-OBJECT object)
;;; It is intended that the unparser procedures defined here be called
;;; by *UNPARSE-OBJECT, which is a dispatch procedure. They in turn
;;; refer to *UNPARSE-OBJECT, expecting that it will dispatch to the
;;; correct place.
(define *unparse-character)
(define *unparse-string)
(define *unparse-object)
;;; Control Variables
(define *unparser-radix* #o12)
(define *unparser-precision* 6)
(define *unparser-list-breadth-limit* #!FALSE)
(define *unparser-list-depth* 0)
(define *unparser-list-depth-limit* #!FALSE)
;;; Careful here... If this variable is already set up when the
;;; unparser is loaded, we will assume it has good stuff in it.
(define *unparser-special-objects*
(if (lexical-unreferenceable? (the-environment) '*UNPARSER-SPECIAL-OBJECTS*)
'()
*unparser-special-objects*))
(define (add-unparser-special-object! key unparser)
(set! *unparser-special-objects*
(cons (cons key unparser)
*unparser-special-objects*)))
(define unparse-with-brackets)
(define scheme-unparser
(make-package scheme-unparser ()
\f
;;;; Constants
(define (unparse-default object)
(unparse-with-brackets
(lambda ()
(*unparse-object
(disjunction (object-type object)
`(UNDEFINED-TYPE-CODE ,(primitive-type object))))
(*unparse-character #\SP)
(*unparse-object (primitive-datum object)))))
(set! unparse-with-brackets
(named-lambda (unparse-with-brackets thunk)
(*unparse-string "#[")
(thunk)
(*unparse-character #/])))
(define (unparse-null x)
(if (eq? x '())
(*unparse-string "()")
(unparse-default x)))
(define (unparse-true x)
(if (eq? x #!TRUE)
(*unparse-string "#!TRUE")
(unparse-default x)))
(define (unparse-unassigned x)
(unparse-with-brackets
(lambda ()
(*unparse-string "UNASSIGNED"))))
(define (unparse-unbound x)
(unparse-with-brackets
(lambda ()
(*unparse-string "UNBOUND"))))
(define (unparse-symbol s)
(*unparse-string (symbol-print-name s)))
(define (unparse-string string)
(*unparse-character #/") ;")
(*unparse-string string)
(*unparse-character #/")) ;"))
\f
;;;; Lists and Vectors
(define (unparse-list list)
(let ((entry (assq (car list) *unparser-special-objects*)))
(cond (entry
((cdr entry) list))
((conjunction (eq? (car list) 'QUOTE)
(pair? (cdr list))
(null? (cddr list)))
(*unparse-character #/')
(*unparse-object (cadr list)))
(else
(unparse-list-internal list)))))
(define (unparse-vector vector)
(if (zero? (vector-size vector))
(*unparse-string "#()")
(let ((entry (assq (vector-ref vector 0) *unparser-special-objects*)))
(cond (entry
((cdr entry) vector))
(else
(*unparse-character #/#)
(unparse-list-internal (vector->list vector)))))))
(define (unparse-list-internal list)
(if *unparser-list-depth-limit*
(dynamic-wind
(lambda ()
(set! *unparser-list-depth* (1+ *unparser-list-depth*)))
(lambda ()
(if (> *unparser-list-depth* *unparser-list-depth-limit*)
(*unparse-string "...")
(sequence (*unparse-character #/()
(*unparse-object (car list))
(unparse-tail (cdr list) 2)
(*unparse-character #/)))))
(lambda ()
(set! *unparser-list-depth* (-1+ *unparser-list-depth*))))
(sequence (*unparse-character #/()
(*unparse-object (car list))
(unparse-tail (cdr list) 2)
(*unparse-character #/)))))
(define (unparse-tail l n)
(cond ((pair? l)
(*unparse-character #\SP)
(*unparse-object (car l))
(if (conjunction *unparser-list-breadth-limit*
(>= n *unparser-list-breadth-limit*)
(cdr l))
(*unparse-string " ...")
(unparse-tail (cdr l) (1+ n))))
((not (null? l))
(*unparse-string " . ")
(*unparse-object l))))
\f
;;;; Procedures and Environments
(define (unparse-compound-procedure procedure)
(unparse-with-brackets
(lambda ()
(*unparse-string "COMPOUND-PROCEDURE ")
(lambda-components (procedure-lambda procedure)
(lambda (name required optional rest auxiliary body)
(if (eq? name lambda-tag:unnamed)
(unparse-number (primitive-datum procedure))
(*unparse-object name)))))))
(define (unparse-primitive-procedure proc)
(unparse-with-brackets
(lambda ()
(*unparse-string "PRIMITIVE-PROCEDURE ")
(*unparse-object (primitive-procedure-name proc)))))
(define (unparse-environment environment)
(if (lexical-unreferenceable? environment ':PRINT-SELF)
(unparse-default environment)
((access :print-self environment))))
\f
;;;; Numbers, ugh bletch
(define (unparse-number number)
(unparse-signed-number number))
(define (unparse-signed-number number)
(if (negative? number)
(sequence (*unparse-character #/-)
(unparse-positive-number (- 0 number)))
(unparse-positive-number number)))
(define (unparse-positive-number x)
(if (integer? x)
(unparse-integer x)
;; could have used the previous dispatch
(unparse-float x)))
(define bignum-type
(microcode-type 'BIG-FIXNUM))
(define listify-bignum
(make-primitive-procedure 'LISTIFY-BIGNUM))
(define (unparse-integer integer)
(local-declare
((compilable-primitive-function listify-bignum))
(cond ((zero? integer)
(*unparse-character #/0))
((primitive-type? bignum-type integer)
(spit-character-values (listify-bignum integer *unparser-radix*)))
(else
(let loop ((n integer))
(if (not (zero? n))
(let ((q (integer-divide n *unparser-radix*)))
(loop (integer-divide-quotient q))
(spit-character-value (integer-divide-remainder q)))))))))
(define mantissa-precision-base
(* (access floating-mantissa-bits implementation-dependencies)
(log 2)))
(define (mantissa-precision r)
(round (/ mantissa-precision-base (log r))))
(define (unparse-float x)
(let ((n (normalize x))
(precision
(disjunction *unparser-precision*
(mantissa-precision *unparser-radix*))))
(let ((digit-info (floating-digits (car n) precision))
(initial-exponent (cdr n)))
(let ((digits (cdr digit-info))
(exponent (if (car digit-info)
(1+ initial-exponent)
initial-exponent)))
(cond ((conjunction (>= exponent 0) ;type out as 100.3
(< exponent precision))
(spit-out-big digits exponent))
((conjunction (< exponent 0) ;type out as .0015
(<= (- (length digits)
(1+ exponent))
precision))
(spit-radix-point)
(spit-out-small digits (1+ exponent)))
(else ;type out as 9.2E16
(spit-out-scientific digits)
(unparse-signed-number exponent)))))))
\f
(define (normalize x)
(let loop ((x x) (count 0))
(cond ((< x 1)
(loop (* x *unparser-radix*)
(-1+ count)))
((>= x *unparser-radix*)
(loop (/ x *unparser-radix*)
(1+ count)))
(else
(cons x count)))))
(define (floating-digits x initial-precision)
(let ((radix-1 (-1+ *unparser-radix*)))
(let loop ((x x)
(precision-remaining initial-precision))
(if (zero? precision-remaining)
'()
(let ((digit (floor x)))
(let ((more (loop (* (- x digit) *unparser-radix*)
(-1+ precision-remaining))))
(cond ((eq? more #!TRUE)
(if (= digit radix-1)
(if (= initial-precision
precision-remaining)
'(#!TRUE 1)
#!TRUE)
(if (= initial-precision precision-remaining)
(list #!FALSE (1+ digit))
(cons (1+ digit) '()))))
((= initial-precision precision-remaining)
(cons #!FALSE (cons digit more)))
(more
(cons digit more))
((zero? digit)
'())
((conjunction (= precision-remaining 1)
(= digit radix-1))
#!TRUE)
(else
(cons digit '())))))))))
(define (spit-out-big digits exponent)
(spit-character-value (car digits))
(cond ((null? (cdr digits))
(fill-out-with-zeros exponent)
(spit-radix-point))
((zero? exponent)
(spit-radix-point)
(spit-character-values (cdr digits)))
(else
(spit-out-big (cdr digits)
(-1+ exponent)))))
(define (fill-out-with-zeros exponent)
(if (not (zero? exponent))
(sequence (spit-character-value 0)
(fill-out-with-zeros (-1+ exponent)))))
\f
(define (spit-out-small digits exponent)
(if (zero? exponent)
(spit-character-values digits)
(sequence (spit-character-value 0)
(spit-out-small digits (1+ exponent)))))
(define (spit-out-scientific digits)
(spit-character-value (car digits))
(spit-radix-point)
(spit-character-values (cdr digits))
(*unparse-character #/e))
(define (spit-character-values l)
(if (not (null? l))
(sequence (*unparse-character (character-value (car l)))
(spit-character-values (cdr l)))))
(define (spit-character-value n)
(*unparse-character (character-value n)))
(define character-value
(let ((A-10 (- #/A #o12)))
(named-lambda (character-value digit)
(+ (if (< digit #o12) #/0 A-10)
digit))))
(define (spit-radix-point)
(*unparse-character #/.))
\f
;;;; Default Unparser
(set! *unparse-object
(let ((dispatch-vector
(let ((dispatch-vector (vector-cons number-of-microcode-types
unparse-default)))
(define (set-dispatch! type dispatcher)
(vector-set! dispatch-vector (microcode-type type) dispatcher))
(set-dispatch! 'NULL unparse-null)
(set-dispatch! 'TRUE unparse-true)
(set-dispatch! 'STRING unparse-string)
(set-dispatch! 'LIST
(lambda (list)
((cond ((unassigned-object? list)
unparse-unassigned)
((unbound-object? list)
unparse-unbound)
(else unparse-list))
list)))
(set-dispatch! 'VECTOR unparse-vector)
(set-dispatch! 'UNINTERNED-SYMBOL unparse-symbol)
(set-dispatch! 'INTERNED-SYMBOL unparse-symbol)
(set-dispatch! 'PRIMITIVE unparse-primitive-procedure)
(set-dispatch! 'PRIMITIVE-EXTERNAL unparse-primitive-procedure)
(set-dispatch! 'FIXNUM unparse-number)
(set-dispatch! 'BIGNUM unparse-number)
(set-dispatch! 'FLONUM unparse-number)
(set-dispatch! 'ENVIRONMENT unparse-environment)
(set-dispatch! 'PROCEDURE unparse-compound-procedure)
(set-dispatch! 'EXTENDED-PROCEDURE unparse-compound-procedure)
dispatch-vector)))
(named-lambda (*unparse-object object)
((vector-ref dispatch-vector (primitive-type object)) object))))
;;; end SCHEME-UNPARSER package.
))