|
|
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 a
Length: 15205 (0x3b65)
Types: TextFile
Names: »advice.scm.77«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/gnu-31mar87/scheme/scm/advice.scm.77«
;;; -*-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.
;;;
;;;; Advice package
(declare (usual-integrations))
(define advice-package
(make-package advice-package
((the-args)
(the-procedure)
(the-result)
(entry-advice-population (make-population))
(exit-advice-population (make-population))
)
(define (*args*) the-args)
(define (*proc*) the-procedure)
(define (*result*) the-result)
\f
;;;; Advice Wrappers
(define (add-lambda-advice! lambda advice-transformation)
((access lambda-wrap-body! lambda-package) lambda
(lambda (body state cont)
(if (null? state)
(cont (make-advice-hook)
(advice-transformation '() '() cons))
(cont body
(advice-transformation (car state) (cdr state) cons))))))
(define (remove-lambda-advice! lambda advice-transformation)
(lambda-advice lambda
(lambda (entry-advice exit-advice)
(advice-transformation entry-advice exit-advice
(lambda (new-entry-advice new-exit-advice)
(if (conjunction (null? new-entry-advice)
(null? new-exit-advice))
((access lambda-unwrap-body! lambda-package) lambda)
((access lambda-wrap-body! lambda-package) lambda
(lambda (body state cont)
(cont body (cons new-entry-advice new-exit-advice))))))))))
(define (lambda-advice lambda cont)
((access lambda-wrapper-components lambda-package) lambda
(lambda (original-body state)
(if (null? state)
(error "Procedure has no advice -- LAMBDA-ADVICE" lambda)
(cont (car state)
(cdr state))))))
(define (make-advice-hook)
(make-combination syntaxed-advice-procedure
(list (make-the-environment))))
(define syntaxed-advice-procedure
(scode-quote
(ACCESS ADVISED-PROCEDURE-WRAPPER ADVICE-PACKAGE '())))
\f
;;;; The Advice Hook
;;; This procedure is called with the newly-created environment as its
;;; argument.
;;; Doing (PROCEED) from within entry or exit advice will cause that
;;; particular piece of advice to be terminated, but any remaining
;;; advice to be executed. Doing (PROCEED value), however,
;;; immediately terminates all advice and returns VALUE as if the
;;; procedure called had generated the value. Returning from a piece
;;; of exit advice is equivalent to doing (PROCEED value) from it.
(define (advised-procedure-wrapper environment)
(let ((procedure (environment-procedure environment))
(arguments (environment-arguments environment)))
((access lambda-wrapper-components lambda-package)
(procedure-lambda procedure)
(lambda (original-body state)
(catch
(lambda (continuation)
(define ((catching-proceeds receiver) advice)
(with-proceed-point
(lambda (value)
(if (null? value)
'()
(continuation (car value))))
(lambda ()
(receiver advice))))
(mapc (catching-proceeds
(lambda (advice)
(advice procedure arguments environment)))
(car state))
(let ((value (scode-eval original-body environment)))
(mapc (catching-proceeds
(lambda (advice)
(set! value
(advice procedure arguments value environment))))
(cdr state))
value)))))))
\f
;;;; Primitive Advisors
(define (primitive-advice lambda)
(lambda-advice lambda list))
(define (primitive-entry-advice lambda)
(lambda-advice lambda
(lambda (entry-advice exit-advice)
entry-advice)))
(define (primitive-exit-advice lambda)
(lambda-advice lambda
(lambda (entry-advice exit-advice)
exit-advice)))
(define (primitive-advise-entry lambda advice)
(add-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(cont (if (memq advice entry-advice)
entry-advice
(cons advice entry-advice))
exit-advice)))
(add-to-population! entry-advice-population lambda))
(define (primitive-advise-exit lambda advice)
(add-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(cont entry-advice
(if (memq advice exit-advice)
exit-advice
(append! exit-advice (list advice))))))
(add-to-population! exit-advice-population lambda))
(define ((primitive-advise-both new-entry-advice new-exit-advice) lambda)
(add-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(cont (if (memq new-entry-advice entry-advice)
entry-advice
(cons new-entry-advice entry-advice))
(if (memq new-exit-advice exit-advice)
exit-advice
(append! exit-advice (list new-exit-advice))))))
(add-to-population! entry-advice-population lambda)
(add-to-population! exit-advice-population lambda))
(define (eq?-adjoin object list)
(if (memq object list)
list
(cons object list)))
\f
(define (primitive-unadvise-entire-entry lambda)
(remove-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(cont '() exit-advice)))
(remove-from-population! entry-advice-population lambda))
(define (primitive-unadvise-entire-exit lambda)
(remove-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(cont entry-advice '())))
(remove-from-population! exit-advice-population lambda))
(define (primitive-unadvise-entire-lambda lambda)
((access lambda-unwrap-body! lambda-package) lambda)
(remove-from-population! entry-advice-population lambda)
(remove-from-population! exit-advice-population lambda))
(define ((primitive-unadvise-entry advice) lambda)
(remove-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(let ((new-entry-advice (delq! advice entry-advice)))
(if (null? new-entry-advice)
(remove-from-population! entry-advice-population lambda))
(cont new-entry-advice exit-advice)))))
(define ((primitive-unadvise-exit advice) lambda)
(remove-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(let ((new-exit-advice (delq! advice exit-advice)))
(if (null? new-exit-advice)
(remove-from-population! exit-advice-population lambda))
(cont entry-advice new-exit-advice)))))
(define ((primitive-unadvise-both old-entry-advice old-exit-advice) lambda)
(remove-lambda-advice! lambda
(lambda (entry-advice exit-advice cont)
(let ((new-entry-advice (delq! old-entry-advice entry-advice))
(new-exit-advice (delq! old-exit-advice exit-advice)))
(if (null? new-entry-advice)
(remove-from-population! entry-advice-population lambda))
(if (null? new-exit-advice)
(remove-from-population! exit-advice-population lambda))
(cont new-entry-advice new-exit-advice)))))
(define (((particular-advisor advisor) advice) lambda)
(advisor lambda advice))
(define particular-entry-advisor (particular-advisor primitive-advise-entry))
(define particular-exit-advisor (particular-advisor primitive-advise-exit))
(define particular-both-advisor primitive-advise-both)
(define particular-entry-unadvisor primitive-unadvise-entry)
(define particular-exit-unadvisor primitive-unadvise-exit)
(define particular-both-unadvisor primitive-unadvise-both)
\f
;;;; Trace
(define (trace-entry-advice proc args env)
(trace-display proc args))
(define (trace-exit-advice proc args result env)
(trace-display proc args result)
result)
(define (trace-display proc args #!optional result)
(newline)
(if (unassigned? result)
(princ "[Entering ")
(sequence (princ "[")
(prin1 result)
(princ " <== ")))
(princ "<")
(prin1 proc)
(if (not (null? args))
(sequence (princ " ")
(trace-display-loop args)))
(princ ">]"))
(define (trace-display-loop the-list)
(prin1 (car the-list))
(if (not (null? (cdr the-list)))
(sequence (princ " ")
(trace-display-loop (cdr the-list)))))
(define primitive-trace-entry
(particular-entry-advisor trace-entry-advice))
(define primitive-trace-exit
(particular-exit-advisor trace-exit-advice))
(define primitive-trace-both
(particular-both-advisor trace-entry-advice trace-exit-advice))
(define primitive-untrace
(particular-both-unadvisor trace-entry-advice trace-exit-advice))
(define primitive-untrace-entry
(particular-entry-unadvisor trace-entry-advice))
(define primitive-untrace-exit
(particular-exit-unadvisor trace-exit-advice))
\f
;;;; Break
(define (break-entry-advice proc args env)
(trace-display proc args)
(fluid-let ((the-procedure proc)
(the-args args))
(breakpoint "Breakpoint on entry" env)))
(define (break-exit-advice proc args result env)
(trace-display proc args result)
(fluid-let ((the-procedure proc)
(the-args args)
(the-result result))
(breakpoint "Breakpoint on exit" env))
result)
(define primitive-break-entry
(particular-entry-advisor break-entry-advice))
(define primitive-break-exit
(particular-exit-advisor break-exit-advice))
(define primitive-break-both
(particular-both-advisor break-entry-advice break-exit-advice))
(define primitive-unbreak
(particular-both-unadvisor break-entry-advice break-exit-advice))
(define primitive-unbreak-entry
(particular-entry-unadvisor break-entry-advice))
(define primitive-unbreak-exit
(particular-exit-unadvisor break-exit-advice))
\f
;;;; Top Level Wrappers
(define (find-internal-lambda procedure path)
(define (find-lambda lambda path)
(define (loop elements)
(cond ((null? elements)
(error "Couldn't find internal definition" path))
((definition? (car elements))
(definition-components (car elements)
(lambda (name value)
(if (eq? name (car path))
(if (lambda? value)
(find-lambda value (cdr path))
(error "Internal definition not a procedure" path))
(loop (cdr elements))))))
(else
(loop (cdr elements)))))
(if (null? path)
lambda
(lambda-components lambda
(lambda (name required optional rest auxiliary body)
(loop (sequence-actions (unscan-defines auxiliary body)))))))
(if (null? path)
(procedure-lambda procedure)
(find-lambda (procedure-lambda procedure) (car path))))
;; The LIST-COPY will prevent any mutation problems.
(define ((wrap-advice-extractor extractor) procedure . path)
(list-copy (extractor (find-internal-lambda procedure path))))
(define advice (wrap-advice-extractor primitive-advice))
(define entry-advice (wrap-advice-extractor primitive-entry-advice))
(define exit-advice (wrap-advice-extractor primitive-exit-advice))
(define ((wrap-general-advisor advisor) procedure advice . path)
(advisor (find-internal-lambda procedure path) advice)
*the-non-printing-object*)
(define advise-entry (wrap-general-advisor primitive-advise-entry))
(define advise-exit (wrap-general-advisor primitive-advise-exit))
\f
(define (((wrap-unadvisor map-over-population) unadvisor) . procedure&path)
(if (null? procedure&path)
(map-over-population unadvisor)
(unadvisor (find-internal-lambda (car procedure&path)
(cdr procedure&path))))
*the-non-printing-object*)
(define wrap-entry-unadvisor
(wrap-unadvisor
(lambda (operation)
(map-over-population entry-advice-population operation))))
(define wrap-exit-unadvisor
(wrap-unadvisor
(lambda (operation)
(map-over-population exit-advice-population operation))))
(define wrap-both-unadvisor
(wrap-unadvisor
(lambda (operation)
(map-over-population entry-advice-population operation)
(map-over-population exit-advice-population operation))))
(define unadvise (wrap-both-unadvisor primitive-unadvise-entire-lambda))
(define unadvise-entry (wrap-entry-unadvisor primitive-unadvise-entire-entry))
(define unadvise-exit (wrap-exit-unadvisor primitive-unadvise-entire-exit))
(define untrace (wrap-both-unadvisor primitive-untrace))
(define untrace-entry (wrap-entry-unadvisor primitive-untrace-entry))
(define untrace-exit (wrap-exit-unadvisor primitive-untrace-exit))
(define unbreak (wrap-both-unadvisor primitive-unbreak))
(define unbreak-entry (wrap-entry-unadvisor primitive-unbreak-entry))
(define unbreak-exit (wrap-exit-unadvisor primitive-unbreak-exit))
(define ((wrap-advisor advisor) procedure . path)
(advisor (find-internal-lambda procedure path))
*the-non-printing-object*)
(define trace-entry (wrap-advisor primitive-trace-entry))
(define trace-exit (wrap-advisor primitive-trace-exit))
(define trace-both (wrap-advisor primitive-trace-both))
(define break-entry (wrap-advisor primitive-break-entry))
(define break-exit (wrap-advisor primitive-break-exit))
(define break-both (wrap-advisor primitive-break-both))
\f
;;; end of ADVICE-PACKAGE.
))
;;;; Exports
(define advice (access advice advice-package))
(define entry-advice (access entry-advice advice-package))
(define exit-advice (access exit-advice advice-package))
(define advise-entry (access advise-entry advice-package))
(define advise-exit (access advise-exit advice-package))
(define unadvise (access unadvise advice-package))
(define unadvise-entry (access unadvise-entry advice-package))
(define unadvise-exit (access unadvise-exit advice-package))
(define trace (access trace-entry advice-package))
(define trace-entry (access trace-entry advice-package))
(define trace-exit (access trace-exit advice-package))
(define trace-both (access trace-both advice-package))
(define untrace (access untrace advice-package))
(define untrace-entry (access untrace-entry advice-package))
(define untrace-exit (access untrace-exit advice-package))
(define break (access break-entry advice-package))
(define break-entry (access break-entry advice-package))
(define break-exit (access break-exit advice-package))
(define break-both (access break-both advice-package))
(define unbreak (access unbreak advice-package))
(define unbreak-entry (access unbreak-entry advice-package))
(define unbreak-exit (access unbreak-exit advice-package))
(define *args* (access *args* advice-package))
(define *proc* (access *proc* advice-package))
(define *result* (access *result* advice-package))