layer@franz.UUCP (Kevin Layer) (05/19/89)
I assume that the following is what you're after (from chapters 21 and 22). I got it directly from Robert Wilensky... Kevin ---------------------------------------- : chapter 22 (set-macro-character #\? #'(lambda (stream char) (list '*var* (read stream t nil t)))) (defun match (pattern1 pattern2) (match-with-bindings pattern1 pattern2 nil)) (defun match-with-bindings (pattern1 pattern2 bindings) (cond ((pattern-var-p pattern1) (variable-match pattern1 pattern2 bindings)) ((pattern-var-p pattern2) (variable-match pattern2 pattern1 bindings)) ((atom pattern1) (if (eq pattern1 pattern2) (values t bindings))) ((atom pattern2) nil) (t (multiple-value-bind (flag carbindings) (match-with-bindings (car pattern1) (car pattern2) bindings) (and flag (match-with-bindings (cdr pattern1) (cdr pattern2) carbindings)))))) (defun variable-match (pattern-var item bindings) (if (equal pattern-var item) (values t bindings) (let ((var-binding (get-binding pattern-var bindings))) (cond (var-binding (match-with-bindings var-binding item bindings)) ((not (contained-in pattern-var item bindings)) (values t (add-binding pattern-var item bindings))))))) (defun contained-in (pattern-var item bindings) (cond ((atom item) nil) ((pattern-var-p item) (or (equal pattern-var item) (contained-in pattern-var (get-binding item bindings) bindings))) (t (or (contained-in pattern-var (car item) bindings) (contained-in pattern-var (cdr item) bindings))))) (defun add-binding (pattern-var item bindings) (cons (list pattern-var item) bindings)) (defun pattern-var-p (item) (and (listp item) (eq '*var* (car item)))) (defun get-binding (pattern-var bindings) (cadr (assoc pattern-var bindings :test #'equal))) ; chapter 22 (defmacro add-to-data-base (item d-b-name) `(setq ,d-b-name (cons (replace-variables (quote ,item)) ,d-b-name))) (defun replace-variables (item) (values (replace-variables-with-bindings item nil))) (defun replace-variables-with-bindings (item bindings) (cond ((atom item) (values item bindings)) ((pattern-var-p item) (let ((var-binding (get-binding item bindings))) (if var-binding (values var-binding bindings) (let ((newvar (makevar (gensym "VAR")))) (values newvar (add-binding item newvar bindings)))))) (t (multiple-value-bind (newlhs lhsbindings) (replace-variables-with-bindings (car item) bindings) (multiple-value-bind (newrhs finalbindings) (replace-variables-with-bindings (cdr item) lhsbindings) (values (cons newlhs newrhs) finalbindings)))))) (defun makevar (sym) (list '*var* sym)) (defun query (request data-base) (mapcan #'(lambda (item) (multiple-value-bind (flag bindings) (match item request) (if flag (list bindings)))) data-base)) (defun index (item data-base) (let ((place (cond ((atom (car item)) (car item)) ((pattern-var-p (car item)) '*var*) (t '*list*)))) (setf (get place data-base) (cons (replace-variables item) (get place data-base))) (setf (get data-base '*keys*) (adjoin place (get data-base '*keys*))))) (defun fast-query (request data-base) (if (pattern-var-p (car request)) (mapcan #'(lambda (key) (query request (get key data-base))) (get data-base '*keys*)) (nconc (query request (get (if (atom (car request)) (car request) '*list*) data-base)) (query request (get '*var* data-base))))) (defun retrieve (request data-base) (nconc (fast-query request data-base) (mapcan #'(lambda (bindings) (retrieve (substitute-vars (get-binding '?antecedent bindings) bindings) data-base)) (fast-query `(<- ,request ?antecedent) data-base)))) (defun substitute-vars (item bindings) (cond ((atom item) item) ((pattern-var-p item) (let ((binding (get-binding item bindings))) (cond (binding (substitute-vars binding bindings)) (t item)))) (t (cons (substitute-vars (car item) bindings) (substitute-vars (cdr item) bindings)))))