;;; -*- Mode:Lisp; Package:(NC LISP); Readtable:CL; Base:10 -*- ;;; Copyright (c) 1985 Yale University ;;; Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees. ;;; This material was developed by the T Project at the Yale University Computer ;;; Science Department. Permission to copy this software, to redistribute it, ;;; and to use it for any purpose is granted, subject to the following restric- ;;; tions 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 T Project at Yale any improvements or extensions that they make, ;;; so that these may be included in future releases; and (b) to inform ;;; the T Project 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. Yale has made no warrantee or representation that the operation of ;;; this software will be error-free, and Yale 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 Yale University nor of any ;;; adaptation thereof in any advertising, promotional, or sales literature ;;; without prior written consent from Yale in each case. ;;; ;;; (lambda (x) ... x ... (set x ...) ...) ;;; ==> (lambda (x) ;;; (let ((x' (make-cell x))) ;;; ... (contents x') ... (set-contents x' ...) ...)) (defun introduce-cell (var) (let* ((node (variable-binder var)) (new-v (create-variable (variable-name var))) (cont (create-lambda-node 'c (list nil new-v))) (call (create-call-node 3 1))) (if (not (some #'identity (map-refs-safely #'(lambda (ref) (hack-reference ref new-v)) var))) (delayed-user-message 'warning (variable-binder var) "variable ~S is set but never referenced" nil (variable-name var))) (relate call-proc call (create-primop-node primop/make-cell)) (relate-call-args call cont (create-reference-node var)) (insert-call call cont node))) ;;; Replace references to variables with indirections through locatives. ;;; x ==> (contents x') ;;; (set x y) ==> (set-contents x' y) ;;; (locative x) ==> x' ;;; Returns T if the variable is being used, NIL if it is being set. (defun hack-reference (ref new-var) (let* ((parent (node-parent ref)) (proc (call-proc parent))) (cond ((or (not (eq (node-role ref) (call-arg 2))) (not (primop-node? proc))) (dereference parent ref new-var) t) ((eq (primop-value proc) primop/setq) ;*set-var) (replace-node parent (assigner parent new-var)) nil) ((eq (primop-value proc) primop/*locative) (replace-call-with-value parent (create-reference-node new-var)) t) (t (dereference parent ref new-var) t)))) ;;; x ==> (contents-location cell-value x') (defun dereference (call ref new-var) (let* ((new-v (create-variable (variable-name new-var))) (l-node (create-lambda-node 'c (list nil new-v))) (new-call (create-call-node 4 1))) (relate call-proc new-call (create-primop-node primop/contents-location)) (relate-call-args new-call l-node (create-primop-node primop/cell-value) (create-reference-node new-var)) (insert-call new-call l-node (node-parent call)) (replace-node ref (create-reference-node new-v)))) ;;; (set x y) ==> (set-location cell-value y x') (defun assigner (call new-var) (let ((node (create-call-node 5 1))) (relate call-proc node (create-primop-node primop/set-location)) (relate-call-args node (detach (call-arg-n 1 call)) (create-primop-node primop/cell-value) (detach (call-arg-n 3 call)) (create-reference-node new-var)) node))