Ken%MIT-OZ@MIT-MC@sri-unix.UUCP (08/17/83)
them. My address is: Martin Nilsson UPMAIL Computing Science Department Box 2059 S-750 02 UPPSALA, Sweden ---------- Here is a FOOLOG sample run: (load 'foolog) ; Lower case is user type-in ; Loading DEFMAX 9844442. (progn (defpred member ; Definition of MEMBER predicate ((member ?x (?x . ?l))) ((member ?x (?y . ?l)) (member ?x ?l))) (defpred cannot-prove ; and CANNOT-PROVE predicate ((cannot-prove ?goal) (call ?goal) (cut) (nil)) ((cannot-prove ?goal))) 'ok) OK (prove (member ?elem (1 2 3)) ; Find elements of the list (writeln (?elem is an element)))) (1. IS AN ELEMENT) MORE? t ; Find the next solution (2. IS AN ELEMENT) MORE? nil ; This is enough (TOP) (prove (cannot-prove (= 1 2)) ; The two cannot-prove cases MORE? t NIL (prove (cannot-prove (= 1 1)) NIL ---------- And here is the source code: ; FOOLOG Interpreter (c) Martin Nilsson UPMAIL 1983-06-12 (declare (special *inf* *e* *v* *topfun* *n* *fh* *forward*) (special *bagof-env* *bagof-list*)) (defmacro defknas (fun args &rest body) `(defun ,fun macro (l) (cons 'progn (sublis (mapcar 'cons ',args (cdr l)) ',body)))) ; ---------- Interpreter (setq *e* nil *fh* nil *n* nil *inf* 0 *forward* (munkam (logior 16. (logand (maknum 0) -16.)))) (defknas imm (m x) (cxr x m)) (defknas setimm (m x v) (rplacx x m v)) (defknas makrecord (n) (loop with r = (makhunk n) and c for i from 1 to (- n 2) do (setq c (cons nil nil)) (setimm r i (rplacd c c)) finally (return r))) (defknas transfer (x y) (setq x (prog1 (imm x 0) (setq y (setimm x 0 y))))) (defknas allocate nil (cond (*fh* (transfer *fh* *n*) (setimm *n* 7 nil)) ((setq *n* (setimm (makrecord 8) 0 *n*))))) (defknas deallocate (on) (loop until (eq *n* on) do (transfer *n* *fh*))) (defknas reset (e n) (unbind e) (deallocate n) nil) (defknas ult (m x) (cond ((or (atom x) (null (eq (car x) '/?))) x) ((< (cadr x) 7) (desetq (m . x) (final (imm m (cadr x)))) x) ((loop initially (setq x (cadr x)) until (< x 7) do (setq x (- x 6) m (or (imm m 7) (imm (setimm m 7 (allocate)) 7))) finally (desetq (m . x) (final (imm m x))) (return x))))) (defknas unbind (oe) (loop with x until (eq *e* oe) do (setq x (car *e*)) (rplaca x nil) (rplacd x x) (pop *e*))) (defknas bind (x y n) (cond (n (push x *e*) (rplacd x (cons n y))) (t (push x *e*) (rplacd x y) (rplaca x *forward*)))) (lap-a-list '((lap final subr) (hrrzi 1 @ 0 (1)) (popj p) nil)) ; (defknas final (x) (cdr (memq nil x))) ; equivalent (defknas catch-cut (v e) (and (null (and (eq (car v) 'cut) (eq (cdr v) e))) v))) (defun prove fexpr (gs) (reset nil nil) (seek (list (allocate)) (list (car (convq gs nil))))) (defun seek (e c) (loop while (and c (null (car c))) do (pop e) (pop c)) (cond ((null c) (funcall *topfun*)) ((atom (car c)) (funcall (car c) e (cdr c))) ((loop with rest = (cons (cdar c) (cdr c)) and oe = *e* and on = *n* and e1 = (allocate) for a in (symeval (caaar c)) do (and (unify e1 (cdar a) (car e) (cdaar c)) (setq inf* (1+ *inf*) *v* (seek (cons e1 e) (cons (cdr a) rest))) (return (catch-cut *v* e1))) (unbind oe) finally (deallocate on))))) (defun unify (m x n y) (loop do (cond ((and (eq (ult m x) (ult n y)) (eq m n)) (return t)) ((null m) (return (bind x y n))) ((null n) (return (bind y x m))) ((or (atom x) (atom y)) (return (equal x y))) ((null (unify m (pop x) n (pop y))) (return nil))))) ; ---------- Evaluable Predicates (defun inst (m x) (cond ((let ((y x)) (or (atom (ult m x)) (and (null m) (setq x y)))) x) ((cons (inst m (car x)) (inst m (cdr x)))))) (defun lisp (e c) (let ((n (pop e)) (oe *e*) (on *n*)) (or (and (unify n '(? 2) (allocate) (eval (inst n '(? 1)))) (seek e c)) (reset oe on)))) (defun cut (e c) (let ((on (cadr e))) (or (seek (cdr e) c) (cons 'cut on)))) (defun call (e c) (let ((m (car e)) (x '(? 1))) (seek e (cons (list (cons (ult m x) '(? 2))) c)))) (defun bagof-topfun nil (push (inst *bagof-env* '(? 1)) *bagof-list*) nil) (defun bagof (e c) (let* ((oe *e*) (on *n*) (*bagof-list* nil) (*bagof-env* (car e))) (let ((*topfun* 'bagof-topfun)) (seek e '(((call (? 2)))))) (or (and (unify (pop e) '(? 3) (allocate) *bagof-list*) (seek e c)) (reset oe on)))) ; ---------- Utilities (defun timer fexpr (x) (let* ((*rset nil) (*inf* 0) (x (list (car (convq x nil)))) (t1 (prog2 (gc) (runtime) (reset nil nil) (seek (list (allocate)) x))) (t1 (- (runtime) t1))) (list (// (* *inf* 1000000.) t1) 'LIPS (// t1 1000.) 'MS *inf* 'INF))) (eval-when (compile eval load) (defun convq (t0 l0) (cond ((pairp t0) (let* (((t1 . l1) (convq (car t0) l0)) ((t2 . l2) (convq (cdr t0) l1))) (cons (cons t1 t2) l2))) ((null (and (symbolp t0) (eq (getchar t0 1) '/?))) (cons t0 l0)) ((memq t0 l0) (cons (cons '/? (cons (length (memq t0 l0)) t0)) l0)) ((convq t0 (cons t0 l0)))))) (defmacro defpred (pred &rest body) `(setq ,pred ',(loop for clause in body collect (car (convq clause nil))))) (defpred true ((true))) (defpred = ((= ?x ?x))) (defpred lisp ((lisp ?x ?y) . lisp)) (defpred cut ((cut) . cut)) (defpred call ((call (?x . ?y)) . call)) (defpred bagof ((bagof ?x ?y ?z) . bagof)) (defpred writeln ((writeln ?x) (lisp (progn (princ '?x) (terpri)) ?y))) (setq *topfun* '(lambda nil (princ "MORE? ") (and (null (read)) '(top))))