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

;;;; Simplify calls to PRIMOP/Y

(defun simplify-y (call-node)
  (simplify-call (call-arg-n 1 call-node))
  (let* ((y-lambda (call-arg-n 1 call-node))
	 (value-call (lambda-body y-lambda))
	 (changed-p nil))
    (unless (primop-ref? (call-proc (lambda-body (call-arg-n 1 value-call)))
			 primop/optional-setup)
    (do ((vars (lambda-variables y-lambda))
	 (args (call-args value-call))
	 (n 3))
	((null (cdr vars)))
      (let ((refs (variable-refs (cadr vars))))
      (cond
	;; ------------------------------
	;; If a label proc is not called,
	;; remove it
        ;; ------------------------------
	((null refs)
	 (debug-msg :simp "~&Removing unused label proc: ~a"
		    (lambda-name (cadr args)))
	 (setf (cdr vars) (cddr vars))		; Evil
	 (erase-all (cadr args))
	 (setf (cdr args) (cddr args)))		; Extremely Evil
	;; ------------------------------------
	;; If a label proc is called only once, 
	;; substitute it in.
	;; ------------------------------------
	((and (null (cdr refs))
	      ;; we sorta depend on go's to have variable tags
	      ;; particularly for dynamic state stuff
	      (not (primop-ref? (call-proc (node-parent (car refs)))
				primop/%go)))
	 (debug-msg :simp "~&Substituting once called label proc: ~a"
		    (lambda-name (cadr args)))
	 (replace-node (car refs)
		       (cadr args))
	 (setf (cdr vars) (cddr vars))		; Evil
	 (setf (cdr args) (cddr args))		; Extremely Evil
	 (debug :simp-tree
	   (pp-cps (node-base call-node)))
	 (setq changed-p t))
	(t
	 (setf (variable-number (cadr vars)) n)
	 (setf (node-role (cadr args)) (call-arg (1- n)))
	 (pop vars) (pop args) (incf n))))))
    (when (null (cdr (lambda-variables y-lambda)))
      (debug-msg :simp "~&Removing empty Y call: ~a"
		 (pp-cps-2 call-node))
      (replace-node call-node (detach (lambda-body y-lambda)))
      (replace-node value-call
		    (detach (lambda-body (car (call-args value-call)))))
      (setq changed-p t))
    changed-p))









