;*********************************************************************
; Módulo: IERL
; Uso:    IAAA Experimental Representation Language
; Autor:  Roberto Sobreviela Ruiz
; email:  419245@cepsz.unizar.es
;         sobreviela@teleline.es
;*********************************************************************
; Fichero: IERL Streams.lsp Fecha Creación: 17 de noviembre de 1999
; Versión: 0.0.2          Fecha Modificación: 28 de diciembre de 1999
; Estado:  Desarrollo     Autor: Roberto Sobreviela Ruiz
;---------------------------------------------------------------------
; Uso: Extensión del lenguaje IERL.
; Comentarios:
;    Gestión de flujos de datos con evaluación diferida según la
;   propuesta de Patrick Henry Winston [Lisp, Winston & Horn 3th ed].
; Historia:
;   Versión 0.0.1:  Implementación de las funciones de manejo de 
;       flujos.
;   Versión 0.0.2:  Modificación sobre la implementación original
;       para introducir la evaluación diferida.
;*********************************************************************

;; Funciones para el manejo de flujos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun final-del-flujo-p (flujo)
    (eq flujo 'FLUJO-VACIO))

(defun principio-del-flujo (flujo)
    (first flujo))

(defmacro encapsula (forma)
    `#'(lambda () ,forma))

(defmacro evalua (procedimiento)
    `(funcall ,procedimiento))
    
;;; Modificación de la versión 0.0.2
;;;
;;; (defun resto-del-flujo (flujo)
;;;     (second flujo))

(defun resto-del-flujo (flujo)
    (let ((cola (second flujo)))
        (if (functionp cola)
            (setf (second flujo) (evalua cola))
            (second flujo))))

;;; Modificación de la versión 0.0.2
;;;
;;; (defun construye-flujo (objeto flujo)
;;;     (list objeto flujo))

(defmacro construye-flujo (objeto flujo)
    `(list ,objeto (encapsula ,flujo)))
    
(defun agrega-a-flujo (flujo1 flujo2)
    (if (final-del-flujo-p flujo1)
        flujo2
        (construye-flujo (principio-del-flujo flujo1)
                         (agrega-a-flujo (resto-del-flujo flujo1)
                                         flujo2))))

(defun concatena-flujo (flujos)
    (if (final-del-flujo-p flujos)
        'FLUJO-VACIO
        (if (final-del-flujo-p (principio-del-flujo flujos))
            (concatena-flujo (resto-del-flujo flujos))
            (construye-flujo (principio-del-flujo (principio-del-flujo flujos))
                             (concatena-flujo 
                                (construye-flujo (resto-del-flujo 
                                                 (principio-del-flujo flujos))
                                                 (resto-del-flujo flujos)))))))
                                
(defun transforma-flujo (procedimiento flujo)
    (if (final-del-flujo-p flujo)
        'FLUJO-VACIO
        (construye-flujo (funcall procedimiento (principio-del-flujo flujo))
                         (transforma-flujo procedimiento (resto-del-flujo flujo)))))


(defun miembro-de-flujo (objeto flujo)
    (cond ((final-del-flujo-p flujo) nil)
          ((equal objeto (principio-del-flujo flujo)) t)
          (t (miembro-de-flujo objeto (resto-del-flujo flujo)))))

(defmacro recuerda-flujo (objeto variable)
    `(unless (miembro-de-flujo ,objeto ,variable)
        (setf ,variable (agrega-a-flujo ,variable (construye-flujo ,objeto 'FLUJO-VACIO)))
        ,objeto))
