git.fiddlerwoaroof.com
src/ops-backup.lisp
5092d8a5
 ;;; ****************************************************************
 ;;; OPS5 Interpreter ***********************************************
 ;;; ****************************************************************
 ;;; This Common Lisp version of OPS5 is in the public domain.  It is based
 ;;; in part on based on a Franz Lisp implementation done by Charles L. Forgy
 ;;; at Carnegie-Mellon University, which was placed in the public domain by
 ;;; the author in accordance with CMU policies.  Ported to Common Lisp by 
 ;;; George Wood and Jim Kowalski. CMU Common Lisp modifications by
 ;;; Dario Guise, Skef Wholey, Michael Parzen, and Dan Kuokka. 
 ;;; Modified to work in CLtL1, CLtL2 and X3J13 compatible lisps by 
 ;;; Mark Kantrowitz on 14-OCT-92.
 ;;; 
 ;;; This code is made available is, and without warranty of any kind by the
 ;;; authors or by Carnegie-Mellon University.
 ;;;
 
 ;;;; Definitions and functions for backing up.
 
 (in-package "OPS")
 
 
 ;;; Internal Global Variables
 
6c4d2158
 (defvar *refracts* nil)
 (defvar *record* nil)
 (defvar *record-array* nil)
 (defvar *recording* nil)
 (defvar *max-record-index* nil)
 (defvar *record-index* nil)
5092d8a5
 
 
 
 (defun backup-init ()
   (setq *recording* nil)
   (setq *refracts* nil)
   (setq *record-array* (make-array 256 :initial-element ()))  ;jgk
   (initialize-record))
 
 
 (defun back (k)
   (dotimes (i k)
     (declare (ignore i))
     (let ((r (aref *record-array* *record-index*))) ; (('))
       (when (null r) (return '|nothing more stored|))
       (setf (aref *record-array* *record-index*) nil)
       (record-index-plus -1.)
       (undo-record r))))
 
 
 ; *max-record-index* holds the maximum legal index for record-array
 ; so it and the following must be changed at the same time
 
 (defun begin-record (p data)
   (setq *recording* t)
   (setq *record* (list '=>refract p data))) 
 
 (defun end-record ()
   (when *recording*
     (setq *record*
 	  (cons *cycle-count* (cons *p-name* *record*)))
     (record-index-plus 1.)
     (setf (aref *record-array* *record-index*) *record*)
     (setq *record* nil)
     (setq *recording* nil))) 
 
 (defun record-change (direct time elm)
   (when *recording*
     (setq *record*
 	  (cons direct (cons time (cons elm *record*)))))) 
 
 ; to maintain refraction information, need keep only one piece of information:
 ; need to record all unsuccessful attempts to delete things from the conflict
 ; set.  unsuccessful deletes are caused by attempting to delete refracted
 ; instantiations.  when backing up, have to avoid putting things back into the
 ; conflict set if they were not deleted when running forward
 
 (defun record-refract (rule data)
   (when *recording*
     (setq *record* (cons '<=refract (cons rule (cons data *record*))))))
 
 (defun refracted (rule data)
   (when *refracts*
     (let ((z (cons rule data)))
       (member z *refracts* :test #'equal)))
   #|(prog (z)
     (and (null *refracts*) (return nil))
     (setq z (cons rule data))
     (return (member z *refracts* :test #'equal)))|#
   )
 
 
 (defun record-index-plus (k)
   (incf *record-index* k)
   (cond ((< *record-index* 0.)
 	 (setq *record-index* *max-record-index*))
 	((> *record-index* *max-record-index*)
 	 (setq *record-index* 0.)))) 
 
 ; the following routine initializes the record.  putting nil in the
 ; first slot indicates that that the record does not go back further
 ; than that.  (when the system backs up, it writes nil over the used
 ; records so that it will recognize which records it has used.  thus
 ; the system is set up anyway never to back over a nil.)
 
 (defun initialize-record nil
   (setq *record-index* 0.)
   (setq *recording* nil)
   (setq *max-record-index* 31.)
   (setf (aref *record-array* 0.) nil)) 
 
 
 ;; replaced per jcp
 ;;; Commented out
 #|
 (defun undo-record (r)
   (prog (save act a b rate)
     ;###	(comment *recording* must be off during back up)
     (setq save *recording*)
     (setq *refracts* nil)
     (setq *recording* nil)
     (and *ptrace* (back-print (list '|undo:| (car r) (cadr r))))
     (setq r (cddr r))
     top  (and (atom r) (go fin))
     (setq act (car r))
     (setq a (cadr r))
     (setq b (caddr r))
     (setq r (cdddr r))
     (and *wtrace* (back-print (list '|undo:| act a)))
     (cond ((eq act '<=wm) (add-to-wm b a))
 	  ((eq act '=>wm) (remove-from-wm b))
 	  ((eq act '<=refract)
 	   (setq *refracts* (cons (cons a b) *refracts*)))
 	  ((and (eq act '=>refract) (still-present b))
 	   (setq *refracts* (delete (cons a b) *refracts*))
 	   (setq rate (rating-part (gethash a *topnode-table*)))
 	   (removecs a b)
 	   (insertcs a b rate))
 	  (t (%warn '|back: cannot undo action| (list act a))))
     (go top)
     fin  (setq *recording* save)
     (setq *refracts* nil)
     (return nil)))
 ;;; End commented out
 |#
 
 
 (defun undo-record (r)
   (prog (save act a b rate)
     ;###	(comment *recording* must be off during back up)
     (setq save *recording*)
     (setq *refracts* nil)
     (setq *recording* nil)
     (and *ptrace* (back-print (list '|undo:| (car r) (cadr r))))
     (setq r (cddr r))
     top  (and (atom r) (go fin))
     (setq act (car r))
     (setq a (cadr r))
     (setq b (caddr r))
     (setq r (cdddr r))
     (and *wtrace* (back-print (list '|undo:| act a)))
     (cond ((eq act '<=wm) (add-to-wm b a))
 	  ((eq act '=>wm) (remove-from-wm b))
 	  ((eq act '<=refract)
 	   (setq *refracts* (cons (cons a b) *refracts*)))
 	  ((and (eq act '=>refract) (still-present b))
 	   (setq *refracts* (tree-remove (cons a b) *refracts*))
 	   (setq rate (rating-part (gethash a *topnode-table*)))
 	   (removecs a b)
 	   (insertcs a b rate))
 	  (t (%warn '|back: cannot undo action| (list act a))))
     (go top)
     fin  (setq *recording* save)
     (setq *refracts* nil)
     (return nil))) 
 
 
 
 ; still-present makes sure that the user has not deleted something
 ; from wm which occurs in the instantiation about to be restored; it
 ; makes the check by determining whether each wme still has a time tag.
 
 (defun still-present (data)
   (prog nil
     loop
     (cond ((atom data) (return t))
 	  ((creation-time (car data))
 	   (setq data (cdr data))
 	   (go loop))
 	  (t (return nil))))) 
 
 (defun back-print (x) 
   (let ((stream (trace-file)))
     (format stream "~&~S" x)))
 
 ;;; *EOF*