turner@imagen.UUCP (D'arc Angel) (01/19/87)
X (return nil))) X (setq old (get-ce-var-bind (car z))) X (cond ((null old) X (%warn '|modify: first argument must be an element variable| X (car z)) X (return nil))) X (remove-from-wm old) X (setq z (cdr z)) X ($reset) X copy (and (atom old) (go fin)) X ($change (car old)) X (setq old (cdr old)) X (go copy) X fin (eval-args z) X ($assert))) X X(defun bind fexpr (z) X (prog (val) X (cond ((not *in-rhs*) X (%warn '|cannot be called at top level| 'bind) X (return nil))) X (cond ((< (length z) 1.) X (%warn '|bind: wrong number of arguments to| z) X (return nil)) X ((not (symbolp (car z))) X (%warn '|bind: illegal argument| (car z)) X (return nil)) X ((= (length z) 1.) (setq val (gensym))) X (t ($reset) X (eval-args (cdr z)) X (setq val ($parameter 1.)))) X (make-var-bind (car z) val))) X X(defun cbind fexpr (z) X (cond ((not *in-rhs*) X (%warn '|cannot be called at top level| 'cbind)) X ((not (= (length z) 1.)) X (%warn '|cbind: wrong number of arguments| z)) X ((not (symbolp (car z))) X (%warn '|cbind: illegal argument| (car z))) X ((null *last*) X (%warn '|cbind: nothing added yet| (car z))) X (t (make-ce-var-bind (car z) *last*)))) X X(defun remove fexpr (z) X (prog (old) X (and (not *in-rhs*)(return (top-level-remove z))) X top (and (atom z) (return nil)) X (setq old (get-ce-var-bind (car z))) X (cond ((null old) X (%warn '|remove: argument not an element variable| (car z)) X (return nil))) X (remove-from-wm old) X (setq z (cdr z)) X (go top))) X X(defun call fexpr (z) X (prog (f) X (setq f (car z)) X ($reset) X (eval-args (cdr z)) X (funcall f))) X X(defun write fexpr (z) X (prog (port max k x needspace) X (cond ((not *in-rhs*) X (%warn '|cannot be called at top level| 'write) X (return nil))) X ($reset) X (eval-args z) X (setq k 1.) X (setq max ($parametercount)) X (cond ((< max 1.) X (%warn '|write: nothing to print| z) X (return nil))) X (setq port (default-write-file)) X (setq x ($parameter 1.)) X (cond ((and (symbolp x) ($ofile x)) X (setq port ($ofile x)) X (setq k 2.))) X (setq needspace t) X la (and (> k max) (return nil)) X (setq x ($parameter k)) X (cond ((eq x '|=== C R L F ===|) X (setq needspace nil) X (terpri port)) X ((eq x '|=== R J U S T ===|) X (setq k (+ 2 k)) X (do-rjust ($parameter (1- k)) ($parameter k) port)) X ((eq x '|=== T A B T O ===|) X (setq needspace nil) X (setq k (1+ k)) X (do-tabto ($parameter k) port)) X (t X (and needspace (princ '| | port)) X (setq needspace t) X (princ x port))) X (setq k (1+ k)) X (go la))) X X(defun default-write-file () X (prog (port) X (setq port t) X (cond (*write-file* X (setq port ($ofile *write-file*)) X (cond ((null port) X (%warn '|write: file has been closed| *write-file*) X (setq port t))))) X (return port))) X X(defun do-rjust (width value port) X (prog (size) X (cond ((eq value '|=== T A B T O ===|) X (%warn '|rjust cannot precede this function| 'tabto) X (return nil)) X ((eq value '|=== C R L F ===|) X (%warn '|rjust cannot precede this function| 'crlf) X (return nil)) X ((eq value '|=== R J U S T ===|) X (%warn '|rjust cannot precede this function| 'rjust) X (return nil))) X (setq size (flatc value (1+ width))) X (cond ((> size width) X (princ '| | port) X (princ value port) X (return nil))) X (do k (- width size) (1- k) (not (> k 0)) (princ '| | port)) X (princ value port))) X X(defun do-tabto (col port) X (prog (pos) X (setq pos (1+ (nwritn port))) X (cond ((> pos col) X (terpri port) X (setq pos 1))) X (do k (- col pos) (1- k) (not (> k 0)) (princ '| | port)) X (return nil))) X X X(defun halt nil X (cond ((not *in-rhs*) X (%warn '|cannot be called at top level| 'halt)) X (t (setq *halt-flag* t)))) X X(defun build fexpr (z) X (prog (r) X (cond ((not *in-rhs*) X (%warn '|cannot be called at top level| 'build) X (return nil))) X ($reset) X (build-collect z) X (setq r (unflat (use-result-array))) X (and *build-trace* (funcall *build-trace* r)) X (compile-production (car r) (cdr r)))) X X(defun openfile fexpr (z) X (prog (file mode id) X ($reset) X (eval-args z) X (cond ((not (equal ($parametercount) 3.)) X (%warn '|openfile: wrong number of arguments| z) X (return nil))) X (setq id ($parameter 1)) X (setq file ($parameter 2)) X (setq mode ($parameter 3)) X (cond ((not (symbolp id)) X (%warn '|openfile: file id must be a symbolic atom| id) X (return nil)) X ((null id) X (%warn '|openfile: 'nil' is reserved for the terminal| nil) X (return nil)) X ((or ($ifile id)($ofile id)) X (%warn '|openfile: name already in use| id) X (return nil))) X (cond ((eq mode 'in) (putprop id (infile file) 'inputfile)) X ((eq mode 'out) (putprop id (outfile file) 'outputfile)) X (t (%warn '|openfile: illegal mode| mode) X (return nil))) X (return nil))) X X(defun $ifile (x) X (cond ((symbolp x) (get x 'inputfile)) X (t nil))) X X(defun $ofile (x) X (cond ((symbolp x) (get x 'outputfile)) X (t nil))) X X X(defun closefile fexpr (z) X ($reset) X (eval-args z) X (mapc (function closefile2) (use-result-array))) X X(defun closefile2 (file) X (prog (port) X (cond ((not (symbolp file)) X (%warn '|closefile: illegal file identifier| file)) X ((setq port ($ifile file)) X (close port) X (remprop file 'inputfile)) X ((setq port ($ofile file)) X (close port) X (remprop file 'outputfile))) X (return nil))) X X(defun default fexpr (z) X (prog (file use) X ($reset) X (eval-args z) X (cond ((not (equal ($parametercount) 2.)) X (%warn '|default: wrong number of arguments| z) X (return nil))) X (setq file ($parameter 1)) X (setq use ($parameter 2)) X (cond ((not (symbolp file)) X (%warn '|default: illegal file identifier| file) X (return nil)) X ((not (memq use '(write accept trace))) X (%warn '|default: illegal use for a file| use) X (return nil)) X ((and (memq use '(write trace)) X (not (null file)) X (not ($ofile file))) X (%warn '|default: file has not been opened for output| file) X (return nil)) X ((and (eq use 'accept) X (not (null file)) X (not ($ifile file))) X (%warn '|default: file has not been opened for input| file) X (return nil)) X ((eq use 'write) (setq *write-file* file)) X ((eq use 'accept) (setq *accept-file* file)) X ((eq use 'trace) (setq *trace-file* file))) X (return nil))) X X X X;;; RHS Functions X X(defun accept fexpr (z) X (prog (port arg) X (cond ((> (length z) 1.) X (%warn '|accept: wrong number of arguments| z) X (return nil))) X (setq port t) X (cond (*accept-file* X (setq port ($ifile *accept-file*)) X (cond ((null port) X (%warn '|accept: file has been closed| *accept-file*) X (return nil))))) X (cond ((= (length z) 1) X (setq arg ($varbind (car z))) X (cond ((not (symbolp arg)) X (%warn '|accept: illegal file name| arg) X (return nil))) X (setq port ($ifile arg)) X (cond ((null port) X (%warn '|accept: file not open for input| arg) X (return nil))))) X (cond ((= (tyipeek port) -1.) X ($value 'end-of-file) X (return nil))) X (flat-value (read port)))) X X(defun flat-value (x) X (cond ((atom x) ($value x)) X (t (mapc (function flat-value) x)))) X X(defun span-chars (x prt) X (do ch (tyipeek prt) (tyipeek prt) (not (member ch x)) (readc prt))) X X(defun acceptline fexpr (z) X (prog (c def arg port) X (setq port t) X (setq def z) X (cond (*accept-file* X (setq port ($ifile *accept-file*)) X (cond ((null port) X (%warn '|acceptline: file has been closed| X *accept-file*) X (return nil))))) X (cond ((> (length def) 0) X (setq arg ($varbind (car def))) X (cond ((and (symbolp arg) ($ifile arg)) X (setq port ($ifile arg)) X (setq def (cdr def)))))) X (span-chars '(9. 41.) port) X; (setq c (tyi port)) no idea why this is here X (cond ((memq (tyipeek port) '(-1. 10.)) X (mapc (function $change) def) X (return nil))) X l: (flat-value (read port)) X (span-chars '(9. 41.) port) X (cond ((not (memq (tyipeek port) '(-1. 10.))) (go l:))))) X X(defun substr fexpr (l) X (prog (k elm start end) X (cond ((not (= (length l) 3.)) X (%warn '|substr: wrong number of arguments| l) X (return nil))) X (setq elm (get-ce-var-bind (car l))) X (cond ((null elm) X (%warn '|first argument to substr must be a ce var| X l) X (return nil))) X (setq start ($varbind (cadr l))) X (setq start ($litbind start)) X (cond ((not (numberp start)) X (%warn '|second argument to substr must be a number| X l) X (return nil))) X (comment |if a variable is bound to INF, the following| X |will get the binding and treat it as INF is| X |always treated. that may not be good|) X (setq end ($varbind (caddr l))) X (cond ((eq end 'inf) (setq end (length elm)))) X (setq end ($litbind end)) X (cond ((not (numberp end)) X (%warn '|third argument to substr must be a number| X l) X (return nil))) X (comment |this loop does not check for the end of elm| X |instead it relies on cdr of nil being nil| X |this may not work in all versions of lisp|) X (setq k 1.) X la (cond ((> k end) (return nil)) X ((not (< k start)) ($value (car elm)))) X (setq elm (cdr elm)) X (setq k (1+ k)) X (go la))) X X X(defun compute fexpr (z) ($value (ari z))) X X; arith is the obsolete form of compute X(defun arith fexpr (z) ($value (ari z))) X X(defun ari (x) X (cond ((atom x) X (%warn '|bad syntax in arithmetic expression | x) X 0.) X ((atom (cdr x)) (ari-unit (car x))) X ((eq (cadr x) '+) X (plus (ari-unit (car x)) (ari (cddr x)))) X ((eq (cadr x) '-) X (difference (ari-unit (car x)) (ari (cddr x)))) X ((eq (cadr x) '*) X (times (ari-unit (car x)) (ari (cddr x)))) X ((eq (cadr x) '//) X (quotient (ari-unit (car x)) (ari (cddr x)))) X ((eq (cadr x) '\\) X (mod (fix (ari-unit (car x))) (fix (ari (cddr x))))) X (t (%warn '|bad syntax in arithmetic expression | x) 0.))) X X(defun ari-unit (a) X (prog (r) X (cond ((dtpr a) (setq r (ari a))) X (t (setq r ($varbind a)))) X (cond ((not (numberp r)) X (%warn '|bad value in arithmetic expression| a) X (return 0.)) X (t (return r))))) X X(defun genatom nil ($value (gensym))) X X(defun litval fexpr (z) X (prog (r) X (cond ((not (= (length z) 1.)) X (%warn '|litval: wrong number of arguments| z) X ($value 0) X (return nil)) X ((numberp (car z)) ($value (car z)) (return nil))) X (setq r ($litbind ($varbind (car z)))) X (cond ((numberp r) ($value r) (return nil))) X (%warn '|litval: argument has no literal binding| (car z)) X ($value 0))) X X X(defun rjust fexpr (z) X (prog (val) X (cond ((not (= (length z) 1.)) X (%warn '|rjust: wrong number of arguments| z) X (return nil))) X (setq val ($varbind (car z))) X (cond ((or (not (numberp val)) (< val 1.) (> val 127.)) X (%warn '|rjust: illegal value for field width| val) X (return nil))) X ($value '|=== R J U S T ===|) X ($value val))) X X(defun crlf fexpr (z) X (cond (z (%warn '|crlf: does not take arguments| z)) X (t ($value '|=== C R L F ===|)))) X X(defun tabto fexpr (z) X (prog (val) X (cond ((not (= (length z) 1.)) X (%warn '|tabto: wrong number of arguments| z) X (return nil))) X (setq val ($varbind (car z))) X (cond ((or (not (numberp val)) (< val 1.) (> val 127.)) X (%warn '|tabto: illegal column number| z) X (return nil))) X ($value '|=== T A B T O ===|) X ($value val))) X X X X;;; Printing WM X X(defun ppwm fexpr (avlist) X (prog (next a) X (setq *filters* nil) X (setq next 1.) X l: (and (atom avlist) (go print)) X (setq a (car avlist)) X (setq avlist (cdr avlist)) X (cond ((eq a '^) X (setq next (car avlist)) X (setq avlist (cdr avlist)) X (setq next ($litbind next)) X (and (floatp next) (setq next (fix next))) X (cond ((or (not (numberp next)) X (> next *size-result-array*) X (> 1. next)) X (%warn '|illegal index after ^| next) X (return nil)))) X ((variablep a) X (%warn '|ppwm does not take variables| a) X (return nil)) X (t (setq *filters* (cons next (cons a *filters*))) X (setq next (1+ next)))) X (go l:) X print (mapwm (function ppwm2)) X (terpri) X (return nil))) X X(defun ppwm2 (elm-tag) X (cond ((filter (car elm-tag)) (terpri) (ppelm (car elm-tag) t)))) X X(defun filter (elm) X (prog (fl indx val) X (setq fl *filters*) X top (and (atom fl) (return t)) X (setq indx (car fl)) X (setq val (cadr fl)) X (setq fl (cddr fl)) X (and (ident (nth (1- indx) elm) val) (go top)) X (return nil))) X X(defun ident (x y) X (cond ((eq x y) t) X ((not (numberp x)) nil) X ((not (numberp y)) nil) X ((=alg x y) t) X (t nil))) X X; the new ppelm is designed especially to handle literalize format X; however, it will do as well as the old ppelm on other formats X X(defun ppelm (elm port) X (prog (ppdat sep val att mode lastpos) X (princ (creation-time elm) port) X (princ '|: | port) X (setq mode 'vector) X (setq ppdat (get (car elm) 'ppdat)) X (and ppdat (setq mode 'a-v)) X (setq sep '|(|) X (setq lastpos 0) X (do X ((curpos 1 (1+ curpos)) (vlist elm (cdr vlist))) X ((atom vlist) nil) X (setq val (car vlist)) X (setq att (assoc curpos ppdat)) X (cond (att (setq att (cdr att))) X (t (setq att curpos))) X (and (symbolp att) (is-vector-attribute att) (setq mode 'vector)) X (cond ((or (not (null val)) (eq mode 'vector)) X (princ sep port) X (ppval val att lastpos port) X (setq sep '| |) X (setq lastpos curpos)))) X (princ '|)| port))) X X(defun ppval (val att lastpos port) X (cond ((not (equal att (1+ lastpos))) X (princ '^ port) X (princ att port) X (princ '| | port))) X (princ val port)) X X X X;;; printing production memory X X(defun pm fexpr (z) (mapc (function pprule) z) (terpri) nil) X X(defun pprule (name) X (prog (matrix next lab) X (and (not (symbolp name)) (return nil)) X (setq matrix (get name 'production)) X (and (null matrix) (return nil)) X (terpri) X (princ '|(p |) X (princ name) X top (and (atom matrix) (go fin)) X (setq next (car matrix)) X (setq matrix (cdr matrix)) X (setq lab nil) X (terpri) X (cond ((eq next '-) X (princ '| - |) X (setq next (car matrix)) X (setq matrix (cdr matrix))) X ((eq next '-->) X (princ '| |)) X ((and (eq next '{) (atom (car matrix))) X (princ '| {|) X (setq lab (car matrix)) X (setq next (cadr matrix)) X (setq matrix (cdddr matrix))) X ((eq next '{) X (princ '| {|) X (setq lab (cadr matrix)) X (setq next (car matrix)) X (setq matrix (cdddr matrix))) X (t (princ '| |))) X (ppline next) X (cond (lab (princ '| |) (princ lab) (princ '}))) X (go top) X fin (princ '|)|))) X X(defun ppline (line) X (prog () X (cond ((atom line) (princ line)) X (t X (princ '|(|) X (setq *ppline* line) X (ppline2) X (princ '|)|))) X (return nil))) X X(defun ppline2 () X (prog (needspace) X (setq needspace nil) X top (and (atom *ppline*) (return nil)) X (and needspace (princ '| |)) X (cond ((eq (car *ppline*) '^) (ppattval)) X (t (pponlyval))) X (setq needspace t) X (go top))) X X(defun ppattval () X (prog (att val) X (setq att (cadr *ppline*)) X (setq *ppline* (cddr *ppline*)) X (setq val (getval)) X (cond ((> (+ (nwritn) (flatc att) (flatc val)) 76.) X (terpri) X (princ '| |))) X (princ '^) X (princ att) X (mapc (function (lambda (z) (princ '| |) (princ z))) val))) X X(defun pponlyval () X (prog (val needspace) X (setq val (getval)) X (setq needspace nil) X (cond ((> (+ (nwritn) (flatc val)) 76.) X (setq needspace nil) X (terpri) X (princ '| |))) X top (and (atom val) (return nil)) X (and needspace (princ '| |)) X (setq needspace t) X (princ (car val)) X (setq val (cdr val)) X (go top))) X X(defun getval () X (prog (res v1) X (setq v1 (car *ppline*)) X (setq *ppline* (cdr *ppline*)) X (cond ((memq v1 '(= <> < <= => > <=>)) X (setq res (cons v1 (getval)))) X ((eq v1 '{) X (setq res (cons v1 (getupto '})))) X ((eq v1 '<<) X (setq res (cons v1 (getupto '>>)))) X ((eq v1 '//) X (setq res (list v1 (car *ppline*))) X (setq *ppline* (cdr *ppline*))) X (t (setq res (list v1)))) X (return res))) X X(defun getupto (end) X (prog (v) X (and (atom *ppline*) (return nil)) X (setq v (car *ppline*)) X (setq *ppline* (cdr *ppline*)) X (cond ((eq v end) (return (list v))) X (t (return (cons v (getupto end))))))) X X X X X X X;;; backing up X X X X(defun record-index-plus (k) X (setq *record-index* (+ k *record-index*)) X (cond ((< *record-index* 0.) X (setq *record-index* *max-record-index*)) X ((> *record-index* *max-record-index*) X (setq *record-index* 0.)))) X X; the following routine initializes the record. putting nil in the X; first slot indicates that that the record does not go back further X; than that. (when the system backs up, it writes nil over the used X; records so that it will recognize which records it has used. thus X; the system is set up anyway never to back over a nil.) X X(defun initialize-record nil X (setq *record-index* 0.) X (setq *recording* nil) X (setq *max-record-index* 31.) X (putvector *record-array* 0. nil)) X X; *max-record-index* holds the maximum legal index for record-array X; so it and the following must be changed at the same time X X(defun begin-record (p data) X (setq *recording* t) X (setq *record* (list '=>refract p data))) X X(defun end-record nil X (cond (*recording* X (setq *record* X (cons *cycle-count* (cons *p-name* *record*))) X (record-index-plus 1.) X (putvector *record-array* *record-index* *record*) X (setq *record* nil) X (setq *recording* nil)))) X X(defun record-change (direct time elm) X (cond (*recording* X (setq *record* X (cons direct (cons time (cons elm *record*))))))) X X; to maintain refraction information, need keep only one piece of information: X; need to record all unsuccessful attempts to delete things from the conflict X; set. unsuccessful deletes are caused by attempting to delete refracted X; instantiations. when backing up, have to avoid putting things back into the X; conflict set if they were not deleted when running forward X X(defun record-refract (rule data) X (and *recording* X (setq *record* (cons '<=refract (cons rule (cons data *record*)] X X(defun refracted (rule data) X (prog (z) X (and (null *refracts*) (return nil)) X (setq z (cons rule data)) X (return (member z *refracts*)))) X X(defun back (k) X (prog (r) X l: (and (< k 1.) (return nil)) X (setq r (getvector *record-array* *record-index*)) X (and (null r) (return '|nothing more stored|)) X (putvector *record-array* *record-index* nil) X (record-index-plus -1.) X (undo-record r) X (setq k (1- k)) X (go l:))) X X(defun undo-record (r) X (prog (save act a b rate) X (comment *recording* must be off during back up) X (setq save *recording*) X (setq *refracts* nil) X (setq *recording* nil) X (and *ptrace* (back-print (list 'undo: (car r) (cadr r)))) X (setq r (cddr r)) X top (and (atom r) (go fin)) X (setq act (car r)) X (setq a (cadr r)) X (setq b (caddr r)) X (setq r (cdddr r)) X (and *wtrace* (back-print (list 'undo: act a))) X (cond ((eq act '<=wm) (add-to-wm b a)) X ((eq act '=>wm) (remove-from-wm b)) X ((eq act '<=refract) X (setq *refracts* (cons (cons a b) *refracts*))) X ((and (eq act '=>refract) (still-present b)) X (setq *refracts* (delete (cons a b) *refracts*)) X (setq rate (rating-part (get a 'topnode))) X (removecs a b) X (insertcs a b rate)) X (t (%warn '|back: cannot undo action| (list act a)))) X (go top) X fin (setq *recording* save) X (setq *refracts* nil) X (return nil))) X X; still-present makes sure that the user has not deleted something X; from wm which occurs in the instantiation about to be restored; it X; makes the check by determining whether each wme still has a time tag. X X(defun still-present (data) X (prog nil X l: (cond ((atom data) (return t)) X ((creation-time (car data)) X (setq data (cdr data)) X (go l:)) X (t (return nil))))) X X X(defun back-print (x) X (prog (port) X (setq port (trace-file)) X (terpri port) X (print x port))) X X X X X;;; Functions to show how close rules are to firing X X(defun matches fexpr (rule-list) X (mapc (function matches2) rule-list) X (terpri)) X X(defun matches2 (p) X (cond ((atom p) X (terpri) X (terpri) X (princ p) X (matches3 (get p 'backpointers) 2. (ncons 1.))))) X X(defun matches3 (nodes ce part) X (cond ((not (null nodes)) X (terpri) X (princ '| ** matches for |) X (princ part) X (princ '| ** |) X (mapc (function write-elms) (find-left-mem (car nodes))) X (terpri) X (princ '| ** matches for |) X (princ (ncons ce)) X (princ '| ** |) X (mapc (function write-elms) (find-right-mem (car nodes))) X (matches3 (cdr nodes) (1+ ce) (cons ce part))))) X X(defun write-elms (wme-or-count) X (cond ((dtpr wme-or-count) X (terpri) X (mapc (function write-elms2) wme-or-count)))) X X(defun write-elms2 (x) X (princ '| |) X (princ (creation-time x))) X X(defun find-left-mem (node) X (cond ((eq (car node) '&and) (memory-part (caddr node))) X (t (car (caddr node))))) X X(defun find-right-mem (node) (memory-part (cadddr node))) X X X;;; Check the RHSs of productions X X X(defun check-rhs (rhs) (mapc (function check-action) rhs)) X X(defun check-action (x) X (prog (a) X (cond ((atom x) X (%warn '|atomic action| x) X (return nil))) X (setq a (setq *action-type* (car x))) X (cond ((eq a 'bind) (check-bind x)) X ((eq a 'cbind) (check-cbind x)) X ((eq a 'make) (check-make x)) X ((eq a 'modify) (check-modify x)) X ((eq a 'remove) (check-remove x)) X ((eq a 'write) (check-write x)) X ((eq a 'call) (check-call x)) X ((eq a 'halt) (check-halt x)) X ((eq a 'openfile) (check-openfile x)) X ((eq a 'closefile) (check-closefile x)) X ((eq a 'default) (check-default x)) X ((eq a 'build) (check-build x)) X (t (%warn '|undefined rhs action| a))))) X X(defun check-build (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-build-collect (cdr z))) X X(defun check-build-collect (args) X (prog (r) X top (and (null args) (return nil)) X (setq r (car args)) X (setq args (cdr args)) X (cond ((dtpr r) (check-build-collect r)) X ((eq r '\\) X (and (null args) (%warn '|nothing to evaluate| r)) X (check-rhs-value (car args)) X (setq args (cdr args)))) X (go top))) X X(defun check-remove (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (mapc (function check-rhs-ce-var) (cdr z))) X X(defun check-make (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-change& (cdr z))) X X(defun check-openfile (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-change& (cdr z))) X X(defun check-closefile (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-change& (cdr z))) X X(defun check-default (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-change& (cdr z))) X X(defun check-modify (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-rhs-ce-var (cadr z)) X (and (null (cddr z)) (%warn '|no changes to make| z)) X (check-change& (cddr z))) X X(defun check-write (z) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (check-change& (cdr z))) X X(defun check-call (z) X (prog (f) X (and (null (cdr z)) (%warn '|needs arguments| z)) X (setq f (cadr z)) X (and (variablep f) X (%warn '|function name must be a constant| z)) X (or (symbolp f) X (%warn '|function name must be a symbolic atom| f)) X (or (externalp f) X (%warn '|function name not declared external| f)) X (check-change& (cddr z)))) X X(defun check-halt (z) X (or (null (cdr z)) (%warn '|does not take arguments| z))) X X(defun check-cbind (z) X (prog (v) X (or (= (length z) 2.) (%warn '|takes only one argument| z)) X (setq v (cadr z)) X (or (variablep v) (%warn '|takes variable as argument| z)) X (note-ce-variable v))) X X(defun check-bind (z) X (prog (v) X (or (> (length z) 1.) (%warn '|needs arguments| z)) X (setq v (cadr z)) X (or (variablep v) (%warn '|takes variable as argument| z)) X (note-variable v) X (check-change& (cddr z)))) X X X(defun check-change& (z) X (prog (r tab-flag) X (setq tab-flag nil) X la (and (atom z) (return nil)) X (setq r (car z)) X (setq z (cdr z)) X (cond ((eq r '^) X (and tab-flag X (%warn '|no value before this tab| (car z))) X (setq tab-flag t) X (check-tab-index (car z)) X (setq z (cdr z))) X ((eq r '//) (setq tab-flag nil) (setq z (cdr z))) X (t (setq tab-flag nil) (check-rhs-value r))) X (go la))) X X(defun check-rhs-ce-var (v) X (cond ((and (not (numberp v)) (not (ce-bound\? v))) X (%warn '|unbound element variable| v)) X ((and (numberp v) (or (< v 1.) (> v *ce-count*))) X (%warn '|numeric element designator out of bounds| v)))) X X(defun check-rhs-value (x) X (cond ((dtpr x) (check-rhs-function x)) X (t (check-rhs-atomic x)))) X X(defun check-rhs-atomic (x) X (and (variablep x) X (not (bound\? x)) X (%warn '|unbound variable| x))) X X(defun check-rhs-function (x) X (prog (a) X (setq a (car x)) X (cond ((eq a 'compute) (check-compute x)) X ((eq a 'arith) (check-compute x)) X ((eq a 'substr) (check-substr x)) X ((eq a 'accept) (check-accept x)) X ((eq a 'acceptline) (check-acceptline x)) X ((eq a 'crlf) (check-crlf x)) X ((eq a 'genatom) (check-genatom x)) X ((eq a 'litval) (check-litval x)) X ((eq a 'tabto) (check-tabto x)) X ((eq a 'rjust) (check-rjust x)) X ((not (externalp a)) X (%warn '"rhs function not declared external" a))))) X X(defun check-litval (x) X (or (= (length x) 2) (%warn '|wrong number of arguments| x)) X (check-rhs-atomic (cadr x))) X X(defun check-accept (x) X (cond ((= (length x) 1) nil) X ((= (length x) 2) (check-rhs-atomic (cadr x))) X (t (%warn '|too many arguments| x)))) X X(defun check-acceptline (x) X (mapc (function check-rhs-atomic) (cdr x))) X X(defun check-crlf (x) X (check-0-args x)) X X(defun check-genatom (x) (check-0-args x)) X X(defun check-tabto (x) X (or (= (length x) 2) (%warn '|wrong number of arguments| x)) X (check-print-control (cadr x))) X X(defun check-rjust (x) X (or (= (length x) 2) (%warn '|wrong number of arguments| x)) X (check-print-control (cadr x))) X X(defun check-0-args (x) X (or (= (length x) 1.) (%warn '|should not have arguments| x))) X X(defun check-substr (x) X (or (= (length x) 4.) (%warn '|wrong number of arguments| x)) X (check-rhs-ce-var (cadr x)) X (check-substr-index (caddr x)) X (check-last-substr-index (cadddr x))) X X(defun check-compute (x) (check-arithmetic (cdr x))) X X(defun check-arithmetic (l) X (cond ((atom l) X (%warn '|syntax error in arithmetic expression| l)) X ((atom (cdr l)) (check-term (car l))) X ((not (memq (cadr l) '(+ - * // \\))) X (%warn '|unknown operator| l)) X (t (check-term (car l)) (check-arithmetic (cddr l))))) X X(defun check-term (x) X (cond ((dtpr x) (check-arithmetic x)) X (t (check-rhs-atomic x)))) X X(defun check-last-substr-index (x) X (or (eq x 'inf) (check-substr-index x))) X X(defun check-substr-index (x) X (prog (v) X (cond ((bound\? x) (return x))) X (setq v ($litbind x)) X (cond ((not (numberp v)) X (%warn '|unbound symbol used as index in substr| x)) X ((or (< v 1.) (> v 127.)) X (%warn '|index out of bounds in tab| x))))) X X(defun check-print-control (x) X (prog () X (cond ((bound\? x) (return x))) X (cond ((or (not (numberp x)) (< x 1.) (> x 127.)) X (%warn '|illegal value for printer control| x))))) X X(defun check-tab-index (x) X (prog (v) X (cond ((bound\? x) (return x))) X (setq v ($litbind x)) X (cond ((not (numberp v)) X (%warn '|unbound symbol occurs after ^| x)) X ((or (< v 1.) (> v 127.)) X (%warn '|index out of bounds after ^| x))))) X X(defun note-variable (var) X (setq *rhs-bound-vars* (cons var *rhs-bound-vars*))) X X(defun bound\? (var) X (or (memq var *rhs-bound-vars*) X (var-dope var))) X X(defun note-ce-variable (ce-var) X (setq *rhs-bound-ce-vars* (cons ce-var *rhs-bound-ce-vars*))) X X(defun ce-bound\? (ce-var) X (or (memq ce-var *rhs-bound-ce-vars*) X (ce-var-dope ce-var))) X X;;; Top level routines X X(defun process-changes (adds dels) X (prog (x) X process-deletes (and (atom dels) (go process-adds)) X (setq x (car dels)) X (setq dels (cdr dels)) X (remove-from-wm x) X (go process-deletes) X process-adds (and (atom adds) (return nil)) X (setq x (car adds)) X (setq adds (cdr adds)) X (add-to-wm x nil) X (go process-adds))) X X(defun main nil X (prog (instance r) X (setq *halt-flag* nil) X (setq *break-flag* nil) X (setq instance nil) X dil (setq *phase* 'conflict-resolution) X (cond (*halt-flag* X (setq r '|end -- explicit halt|) X (go finis)) X ((zerop *remaining-cycles*) X (setq r '***break***) X (setq *break-flag* t) X (go finis)) X (*break-flag* (setq r '***break***) (go finis))) X (setq *remaining-cycles* (1- *remaining-cycles*)) X (setq instance (conflict-resolution)) X (cond ((not instance) X (setq r '|end -- no production true|) X (go finis))) X (setq *phase* (car instance)) X (accum-stats) X (eval-rhs (car instance) (cdr instance)) X (check-limits) X (and (broken (car instance)) (setq *break-flag* t)) X (go dil) X finis (setq *p-name* nil) X (return r))) X X(defun do-continue (wmi) X (cond (*critical* X (terpri) X (princ '|warning: network may be inconsistent|))) X (process-changes wmi nil) X (print-times (main))) X X(defun accum-stats nil X (setq *cycle-count* (1+ *cycle-count*)) X (setq *total-token* (+ *total-token* *current-token*)) X (cond ((> *current-token* *max-token*) X (setq *max-token* *current-token*))) X (setq *total-wm* (+ *total-wm* *current-wm*)) X (cond ((> *current-wm* *max-wm*) (setq *max-wm* *current-wm*)))) X X X(defun print-times (mess) X (prog (cc ac) X (cond (*break-flag* (terpri) (return mess))) X (setq cc (plus (float *cycle-count*) 1.0e-20)) X (setq ac (plus (float *action-count*) 1.0e-20)) X (terpri) X (princ mess) X (pm-size) X (printlinec (list *cycle-count* X 'firings X (list *action-count* 'rhs 'actions))) X (terpri) X (printlinec (list (round (quotient (float *total-wm*) cc)) X 'mean 'working 'memory 'size X (list *max-wm* 'maximum))) X (terpri) X (printlinec (list (round (quotient (float *total-cs*) cc)) X 'mean 'conflict 'set 'size X (list *max-cs* 'maximum))) X (terpri) X (printlinec (list (round (quotient (float *total-token*) cc)) X 'mean 'token 'memory 'size X (list *max-token* 'maximum))) X (terpri))) X X(defun pm-size nil X (terpri) X (printlinec (list *pcount* X 'productions X (list *real-cnt* '// *virtual-cnt* 'nodes))) X (terpri)) X X(defun check-limits nil X (cond ((> (length *conflict-set*) *limit-cs*) X (terpri) X (terpri) X (printlinec (list '|conflict set size exceeded the limit of| X *limit-cs* X '|after| X *p-name*)) X (setq *halt-flag* t))) X (cond ((> *current-token* *limit-token*) X (terpri) X (terpri) X (printlinec (list '|token memory size exceeded the limit of| X *limit-token* X '|after| X *p-name*)) X (setq *halt-flag* t)))) X X X(defun top-level-remove (z) X (cond ((equal z '(*)) (process-changes nil (get-wm nil))) X (t (process-changes nil (get-wm z))))) X X(defun excise fexpr (z) (mapc (function excise-p) z)) X X(defun run fexpr (z) X (cond ((atom z) (setq *remaining-cycles* 1000000.) (do-continue nil)) X ((and (atom (cdr z)) (numberp (car z)) (> (car z) 0.)) X (setq *remaining-cycles* (car z)) X (do-continue nil)) X (t 'what\?))) X X(defun strategy fexpr (z) X (cond ((atom z) *strategy*) X ((equal z '(lex)) (setq *strategy* 'lex)) X ((equal z '(mea)) (setq *strategy* 'mea)) X (t 'what\?))) X X(defun cs fexpr (z) X (cond ((atom z) (conflict-set)) X (t 'what\?))) X X(defun watch fexpr (z) X (cond ((equal z '(0.)) X (setq *wtrace* nil) X (setq *ptrace* nil) X 0.) X ((equal z '(1.)) (setq *wtrace* nil) (setq *ptrace* t) 1.) X ((equal z '(2.)) (setq *wtrace* t) (setq *ptrace* t) 2.) X ((equal z '(3.)) X (setq *wtrace* t) X (setq *ptrace* t) X '(2. -- conflict set trace not supported)) X ((and (atom z) (null *ptrace*)) 0.) X ((and (atom z) (null *wtrace*)) 1.) X ((atom z) 2.) X (t 'what\?))) X X(defun external fexpr (z) (catch (external2 z) \!error\!)) X X(defun external2 (z) (mapc (function external3) z)) X X(defun external3 (x) X (cond ((symbolp x) (putprop x t 'external-routine) X (setq *externals* (enter x *externals*))) X (t (%error '|not a legal function name| x)))) X X(defun externalp (x) X (cond ((symbolp x) (get x 'external-routine)) X (t (%warn '|not a legal function name| x) nil))) X X(defun pbreak fexpr (z) X (cond ((atom z) (terpri) *brkpts*) X (t (mapc (function pbreak2) z) nil))) X X(defun pbreak2 (rule) X (cond ((not (symbolp rule)) (%warn '|illegal name| rule)) X ((not (get rule 'topnode)) (%warn '|not a production| rule)) X ((memq rule *brkpts*) (setq *brkpts* (rematm rule *brkpts*))) X (t (setq *brkpts* (cons rule *brkpts*))))) X X(defun rematm (atm list) X (cond ((atom list) list) X ((eq atm (car list)) (rematm atm (cdr list))) X (t (cons (car list) (rematm atm (cdr list)))))) X X(defun broken (rule) (memq rule *brkpts*)) X X XMONK.OPS X X;;; -*- Mode:Common-Lisp; Package:USER; Base:10 -*- X X;---------------------------------------------------------------------- X;Here's a monkey-and-banana problem in OPS5 (this comes with the OPS5 X;distribution, which you can get for free from Forgy at CMU) X X;To run this demo, load into an OPS5 image, and type X;(make start 1) X;(run) X X X X(i-g-v) X; a monkey is AT some location and may be ON some object and X; may be HOLDing something X; X(literalize start ) X(literalize monkey X at X on X holds) X X; an object has a NAME, is AT somewhere, has a WEIGHT and may X; be ON something X; X(literalize object X name X at X weight X on) X X; a goal is a flag for sequencing actions that may be active, X; describe the state of an object or monkey, the object may be X; speciifed and its future location as well X; X(literalize goal X status X type X object X to) X; X;make everything new again X(defun monkoff() (eval `(excise ,@*pnames* ) )) ;handy function to remove all productions from memory X; X; if the object someone wants to hold is on the ceiling, move X;the ladder to the place under the object. X; X(p mb1 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on ceiling) X --> X (owrite (crlf) Since the <w> are on the ceiling at position <p> \,) X (owrite (crlf) I would like to move the ladder under them.) X (make goal ^status active ^type move ^object ladder ^to <p>)) X X; if the object is on the ceiling and the ladder is under the X; object and you want the object, then get on the ladder X; X(p mb2 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on ceiling) X (object ^name ladder ^at <p>) X --> X (owrite (crlf) With the ladder at <p> \, ) X (owrite (crlf) I climb onto the ladder to get the <w> \.) X (make goal ^status active ^type on ^object ladder)) X; X; if you're on the ladder under the sought-after object (which X; is on the ceiling), make grabbing it your own desire X; X(p mb3 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on ceiling) X (object ^name ladder ^at <p>) X (monkey ^on ladder) X --> X (owrite (crlf) what I want to do now is get the <w> \.) X (make goal ^status active ^type holds ^object nil)) X X; X; so you're under the object and you're on the ladder with empty X; hands, now grab for the gusto !! X; X(p mb4 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on ceiling) X (object ^name ladder ^at <p>) X (monkey ^on ladder ^holds nil) X --> X (owrite (crlf) I have the <w> in hand) X (modify 4 ^holds <w>) X (modify 1 ^status satified)) X X; if you want to hold something, and it's on the floor, X; you must decide to walk over and pick it up X; X(p mb5 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on floor) X --> X (owrite (crlf) I think I will walk over to <p> to get the <w>) X (make goal ^status active ^type walk-to ^object <p>)) X; X; in order to hold something, one needs ones hands free X; X(p mb6 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on floor) X (monkey ^at <p>) X --> X (owrite (crlf) if I am going to hold <w> here at <p>) X (owrite (crlf) I am going to need to have empty hands) X (make goal ^status active ^type holds ^object nil)) X; X; if you where the object is and its on the floor, X; pick it up X; X(p mb7 X (goal ^status active ^type holds ^object <w>) X (object ^name <w> ^at <p> ^on floor) X (monkey ^at <p> ^holds nil) X --> X (owrite (crlf) I picked the <w> off the floor) X (modify 3 ^holds <w>) X (modify 1 ^status satisfied)) X X; X; if the object is light enough, move it where you will X; X(p mb8 X (goal ^status active ^type move ^object <o> ^to <p>) X (object ^name <o> ^weight light ^at <> <p>) X --> X (owrite (crlf) since the <o> is light I can move it ) X (make goal ^status active ^type holds ^object <o>)) X X; X; since i'm holding the object I can and will move it X; X(p mb9 X (goal ^status active ^type move ^object <o> ^to <p>) X (object ^name <o> ^weight light ^at <> <p>) X (monkey ^holds <o>) X --> X (owrite (crlf) since I can move the <o> to <p> \, I will) X (make goal ^status active ^type walk-to ^object <p>)) X X; X; and it is moved ... X; X(p mb10 X (goal ^status active ^type move ^object <o> ^to <p>) X (object ^name <o> ^weight light ^at <p>) X --> X (owrite (crlf) and it is where I want it) X (modify 1 ^status satisfied)) X X(p mb11 X (goal ^status active ^type walk-to ^object <p>) X --> X (owrite (crlf) since I need to be on the floor to walk \,) X (owrite (crlf) I better get to the floor) X (make goal ^status active ^type on ^object floor)) X X; if the monkey is on the floor and not at his goal location X; <p> then walk to <p> X; X(p mb12 X (goal ^status active ^type walk-to ^object <p>) X (monkey ^on floor ^at { <c> <> <p> } ^holds nil) X --> X (owrite (crlf) I will walk over to <p>) X (modify 2 ^at <p>) X (modify 1 ^status satisfied)) X X; if i walk to <p>, then I am at <p> and so is anything i am X; holding X; X(p mb13 X (goal ^status active ^type walk-to ^object <p>) X (monkey ^on floor ^at { <c> <> <p> } ^holds <w> <> nil) X (object ^name <w>) X --> X (owrite (crlf) I will carry <w> to <p>) X (modify 2 ^at <p>) X (modify 3 ^at <p>) X (modify 1 ^status satisfied)) X X; X; if i am not on the floor and what I want is, I had better X; jump down to the floor X; X(p mb14 X (goal ^status active ^type on ^object floor) X (monkey ^on { <x> <> floor }) X --> X (owrite (crlf) I will jump onto the floor) X (modify 2 ^on floor) X (modify 1 ^status satisfied)) X X; X(p mb15 X (goal ^status active ^type on ^object <o>) X (object ^name <o> ^at <p>) X --> X (owrite (crlf) when does mb15 get fired ) X (make goal ^status active ^type walk-to ^object <p>)) X X; X; if i want to get on something and i am at it X; make it so that I have a goal of holding something X; X(p mb16 X (goal ^status active ^type on ^object <o>) X (object ^name <o> ^at <p>) X (monkey ^at <p>) X --> X (owrite (crlf) I will need free hands to climb the <o> ) X (make goal ^status active ^type holds ^object nil)) X X; X; if I have free hands at <p> and my active goal is at <p> X; climb up the object I am at X; X(p mb17 X (goal ^status active ^type on ^object <o>) X (object ^name <o> ^at <p>) X (monkey ^at <p> ^holds nil) X --> X (owrite (crlf) I will now climb onto <o>) X (modify 3 ^on <o>) X (modify 1 ^status satisfied)) X X; X; if I want to hold nothing and I have something in hand, drop X; it X; X(p mb18 X (goal ^status active ^type holds ^object nil) X (monkey ^holds { <x> <> nil }) X --> X (owrite (crlf) since I need my hands free I will put <x> down ) X (modify 2 ^holds nil) X (modify 1 ^status satisfied)) X X(p mb19 X (goal ^status active) X --> X (owrite (crlf) when does mb19 get fired ) X (remove 1) X (make goal ^status not-processed)) X; X;------------------------------------------------------------ X; STARTING CONDITIONS X;------------------------------------------------------------ X; X; in the beginning, the monkey is at loaction [5,7] on the X; couch. The bananas are on the ceiling at location [2,2]. X; There is a light ladder on the floor at [9,5]. The monkey's X; goal is to have those bananas. X; X(p t1 X (start 1) X --> X (make monkey ^at 5-7 ^on couch ^holds nil) X (owrite (crlf) I am a monkey lying on the couch) X (make object ^name couch ^at 5-7 ^weight heavy) X (owrite (crlf) |... a heavy couch|) X (make object ^name bananas ^on ceiling ^at 2-2) X (owrite (crlf) there are some bananas on the ceiling at position 2-2) X (make object ^name ladder ^on floor ^at 9-5 ^weight light) X (owrite (crlf) there is a ladder on the floor at position 9-5) X X (make goal ^status active ^type holds ^object bananas) X (owrite (crlf) I sure would like those bananas ) X (owrite (crlf)(crlf) |The action begins:| (crlf))) X X XTI.OPS X X; VPS2 -- Interpreter for OPS5 X; X; Copyright (C) 1979, 1980, 1981 X; Charles L. Forgy, Pittsburgh, Pennsylvania X X X X; Users of this interpreter are requested to contact X X; X; Charles Forgy X; Computer Science Department X; Carnegie-Mellon University X; Pittsburgh, PA 15213 X; or X; Forgy@CMUA X; X; so that they can be added to the mailing list for OPS5. The mailing list X; is needed when new versions of the interpreter or manual are released. X X X X;;; Definitions X X X -- --------------- C'est la vie, C'est la guerre, C'est la pomme de terre Mail: Imagen Corp. 2650 San Tomas Expressway Santa Clara, CA 95052-8101 UUCP: ...{decvax,ucbvax}!decwrl!imagen!turner AT&T: (408) 986-9400