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



Catch must return multiple values if multiple values are thrown,
or if the body returns multiple values.

Throw of a single value can clear the mv flag, throw of multiple
values can set it.  This is not hard.

CATCH-CONTINUE, the thing which pops the frame, must use RETURN-TAIL
and not mess up the flag.

If no throw happens, the body falls into the call to CATCH-CONTINUE
but it must set the flag appropriately


This will happen if the value of the body is the value of a function
   (catch 'tag (f))

but if the value is a variable,literal,or primop value
   (catch 'tag (case (pred)
		 (0 x)
		 (1 259)
		 (2 (+ x y))
		 (3 (values x y 259))))
the flag will not be set.


  1one solution would be to make a closure out of the body*
  1(STRATEGY/PROC)*
   1 (catch 'tag (funcall #'(lambda () 3)))*


The problem is the communication of the information that the flag must be
set.

 The value could be assigned by:
   generation of individual primops (get-destination)
   generate-continuation
   parallel-assign
     gen-label-call
     gen-known-return
     let
     gen-general-call (move to open)






****

mv's returned from catch body
looks very much like mv's returned
to dest RETURN

why can't code be similiar???

*****














;----------------------------------------------------------------

;(%VALUES)


(define-compilator (%values body)
  (multiple-value-bind (node c-parent c-role) (->node body)
    (cond ((or (literal-node? node)
	       (reference-node? node))
	   (make-call `(,primop/%values1 ,node)))
	  ((eq call-proc c-role)
	   (let ((args (copy-list (call-args c-parent))))
	     (mapc #'detach args)
	     (let ((new-call (make-call `(,primop/%values1 . ,args))))
	       (values new-call new-call (call-arg 1)))))
	  ((lambda-node? (call-proc c-parent))
	   (let ((jvar (car (lambda-variables (call-proc c-parent)))))
	     (dolist (ref (variable-refs jvar))
	       (cond ((eq (node-role ref) call-proc)
		      (let ((args (copy-list (call-args (node-parent ref)))))
			(mapc #'detach args)
			(replace-node
			  (node-parent ref)
			  (make-call-with-exits 1 `(,primop/%values1 ,(detach ref) . ,args)))))
		     (t
		      (cerror "foo" "bound cont passed"))))
	     (values node c-parent c-role)))
	  ((and (eq c-role (call-arg 1))
		(= 1 (call-exits c-parent)))
	   (let* ((var (create-variable 'v))
		    (lambda (create-lambda-node 'c (list nil var)))
		    (call (make-call `(,primop/%values1 ,var))))
	       (relate lambda-body lambda call)
	       (relate c-role c-parent lambda)
	       (values node call (call-arg 1))))
	  (t (cerror "foo" "whats this?" )))))
		      

(define-special-form %VALUES (body) (env)
  (list '%VALUES (alpha body env)))

(define-primop %values1 (&rest values)
  (:generate (node)
     (generate-values node)))


(defun generate-values (node)
  (let* ((args (cdr (call-args node)))
	 (cont (cont node))
	 (dest (get-destination cont))
	 (nargs (length args)))
    (cond
      ((and (lambda-node? (node-parent node))
	    (let ((proc (call-proc (node-parent (node-parent node)))))
	      (and (reference-node? proc)
		   (not (variable-known (reference-variable proc))))))
	 (generate-move (car args) dest)
	 dest)
      ((= 1 nargs)
       (generate-internal-call 'LI:SINGLE-VALUE dest (car args))
       dest)
      ((= 0 nargs)
       (emit 'K:OPEN)
       (generate-move ''0 'GR:*NUMBER-OF-RETURN-VALUES*)
       (generate-move ''NIL O0)
       (generate-general-call 'LI:MULTIPLE-VALUES nil dest 1)
       dest)
      (t (emit 'K:OPEN)
	 (parallel-assign `(',(+ nargs *mv-return-nargs-offset*)
			    ,@(cdr args)
			    ,(car args))
			  `(GR:*NUMBER-OF-RETURN-VALUES*
			     ,@(subseq *mv-return-registers* 0 (1- nargs))
			     ,O0))
	 (generate-general-call 'LI:MULTIPLE-VALUES nil dest 1)
	 dest))))
				
	   
		   
	       
	       
	       






jrd 
253-0314 office
    0316 lispm room
    0360 terminal garden

jrd@media-lab.edu
    oz
    mc

tues 7:30 pamplona