;;; -*- Mode:LISP; Package:NC ; Base:10; Readtable:CL -*-

;;;; Live Variable Analysis

;;; This seems to be about as random a place to put this.

(defun analyze (top-node)
  (trace-analyze-top    top-node)
  (strategy-analyze-top top-node)
  (live-analyze-top     top-node)
  (close-analyze-top    top-node))

(defun live-analyze-top (node)
  (setq *unit-literals* '())
  (setq *unit-variables*
	(live-analyze-node (call-arg-n 1 (lambda-body node)))))

(defun live-analyze-node (node)
  (cond ((lambda-node? node) (live-analyze-lambda node))
	((leaf-node?   node) (live-analyze-leaf   node))
	(t (bug "live-analyze-node called on a call-node ~s" node))))

(defun live-analyze-leaf (node)
  (flet ((add-literal ()
	     (setq *unit-literals* (adjoin (leaf-value node) *unit-literals*))
	     '()))
    (cond ((literal-node? node) (add-literal))
	  ((primop-node? node)
	   (if (foreign-name (primop-value node))
	       (add-literal)
	       '()))
	  (t (list (leaf-value node))))))

(defun live-analyze-lambda (node)
  (let ((vars (live-analyze-call (lambda-body node))))
    (setf (lambda-live node)
	  (set-difference vars (lambda-all-variables node)))))

(defun live-analyze-call (node)
  (let ((proc (call-proc node)))
    (if (primop-node? proc)
	(cond ((eq (primop-value proc) primop/y)
	       (live-analyze-y (call-arg-n 1 node)))
	      ((eq (primop-value proc) primop/setq-lexical)
	       (delete (reference-variable (call-arg-n 2 node))
		       (live-analyze-call-args node)))
	      (t (live-analyze-call-args node)))
      (live-analyze-call-args node))))

(defun live-analyze-call-args (node)
  (do ((args (call-proc+args node) (rest args))
       (live '() (union live (live-analyze-node (first args)))))
      ((null args) live)))

(defun live-analyze-y (lambda-node)
  (do ((args (call-args (lambda-body lambda-node)) (rest args))
       (live '() (union live (live-analyze-lambda (first args)))))
      ((null args)
       (let ((live (set-difference live (lambda-all-variables lambda-node))))
	 (do ((args (call-args (lambda-body lambda-node)) (rest args)))
	     ((null args) live)
	   (setf (lambda-live (first args)) live))))))
