;;; ----------------------------------------------------------------------
;;;
;;; ITERM: 'For' iteration extension at runtime 
;;;
;;; ----------------------------------------------------------------------
;;;
;;; This file is part of ILOG Talk.
;;; Inquiries to ILOG S.A.
;;;              9 rue de Verdun, BP 85,
;;;              94253 Gentilly Cedex, France.
;;;
;;; Copyright (c) 1995-1996 by ILOG
;;; ----------------------------------------------------------------------
;;;

;;; Defines a for iterator which uses a runtime protocol based on the
;;; value of the iterator.  Given the form:
;;;   (for ((val in-object: <obj> [iterator: <iter>])) ...)
;;; The generic runtime protocol is:
;;;   (.iterator-default-iterator <obj>)          Computes default iterator
;;;                                               for <obj> when none
;;;                                               is given.
;;;   (.iterator-init-index <iter> <obj>)         Initialize the index.
;;;   (.iterator-init-value <iter> <obj>)         Compute the initial
;;;                                               value for VAL. 
;;;   (.iterator-done-p <iter> <obj> <index>)     Return true if finished.
;;;   (.iterator-next-index <iter> <obj> <index>) Increment the index
;;;   (.iterator-next-value <iter> <obj> <index>) Compute the next
;;;                                               value for VAL. 

(defglobal .unique "unq")

(.add-for-iterator 'in-object: #c.<for-iterator-in-object>)

(defmethod .for-iterator-legal-preps ((iter .<for-iterator-in-object>))
  (ignore iter)
  '(iterator:))

(defmethod initialize-instance ((iter .<for-iterator-in-object>)
				init-list)
  (call-next-method)
  (let* ((preps (.for-iterator-prepositions iter))
	 (iterator (plref preps 'iterator: .unique)))
    (setf (.for-iterator-iter-p iter) iterator))
  iter)

(defmethod .compute-for-iterator-temp-bindings
  ((iter .<for-iterator-in-object>))
  (let ((prev (call-next-method))
	(otmp (.for-iterator-obj-temp iter))
	(itmp (.for-iterator-iter-temp iter))
	(iterp (.for-iterator-iter-p iter)))
    `((,otmp ,(.for-iterator-value iter))
      (,itmp
       ,(if (eq iterp .unique)
	    ;; no iterator given
	    `(.iterator-default-iterator ,otmp)
	  iterp)
       ,@prev))))

(defmethod .compute-for-iterator-bindings ((iter .<for-iterator-in-object>))
  `((,(.for-iterator-var iter)
     (.iterator-init-value
      ,(.for-iterator-iter-temp iter)
      ,(.for-iterator-obj-temp iter)))))

(defmethod .compute-for-iterator-ivar-bindings
  ((iter .<for-iterator-in-object>))
  `((,(.for-iterator-ivar iter)
     (.iterator-init-index
      ,(.for-iterator-iter-temp iter)
      ,(.for-iterator-obj-temp iter)))))

(defmethod .compute-for-tests ((iter .<for-iterator-in-object>))
  `((.iterator-done-p
     ,(.for-iterator-iter-temp iter)
     ,(.for-iterator-obj-temp iter)
     ,(.for-iterator-ivar iter))))

(defmethod .compute-for-iteration-setters ((iter .<for-iterator-in-object>))
  `(,(.for-iterator-var iter)
    (.iterator-next-value
     ,(.for-iterator-iter-temp iter)
     ,(.for-iterator-obj-temp iter)
     ,(.for-iterator-ivar iter))))

(defmethod .compute-for-index-setters ((iter .<for-iterator-in-object>))
  `(,(.for-iterator-ivar iter)
    (.iterator-next-index
     ,(.for-iterator-iter-temp iter)
     ,(.for-iterator-obj-temp iter)
     ,(.for-iterator-ivar iter))))


  
  

