Wed Apr 15 10:14:24 UTC 2009 mantoniotti
* Major API change to 'unify'. It now accepts keywords. Old code
Major API change to 'unify'. It now accepts keywords. Old code
shouls not be affected, but new code is now more flexible. Look the
the STRING and (new) CHARACTER methods to see how this change is
affecting the code.
diff -rN -u old-cl-unification-1/unifier.lisp new-cl-unification-1/unifier.lisp
--- old-cl-unification-1/unifier.lisp 2013-07-21 20:05:12.000000000 +0000
+++ new-cl-unification-1/unifier.lisp 2013-07-21 20:05:12.000000000 +0000
@@ -5,7 +5,7 @@
(in-package "CL.EXT.DACF.UNIFICATION") ; DACF = Data And Control Flow.
-(defgeneric unify (a b &optional env)
+(defgeneric unify (a b &optional env &key &allow-other-keys)
(:documentation
"Unifies two objects A and B given a substitution ENV.
A is a Common Lisp object and B is either a Common Lisp object or a
@@ -22,7 +22,9 @@
;;;===========================================================================
;;; Simple, non template methods.
-(defmethod unify ((a symbol) (b list) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b list)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
"Unifies a symbol A and a list B in an environment ENV.
If A is not a variable then an error of type UNIFICATION-FAILURE is
signaled. If A is a unification variable, then the environment ENV is
@@ -35,7 +37,9 @@
:format-arguments (list a b)))))
-(defmethod unify ((b list) (a symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((b list) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
"Unifies a symbol B and a list A in an environment ENV.
If A is not a variable then an error of type UNIFICATION-FAILURE is
signaled. If A is a unification variable, then the environment ENV is
@@ -48,7 +52,9 @@
:format-arguments (list b a)))))
-(defmethod unify ((a list) (b list) &optional (env (make-empty-environment)))
+(defmethod unify ((a list) (b list)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
"Unifies a list A and a list B in an environment ENV.
The unification procedure proceedes recursively on each element of
both lists. If two elements cannot be unified then an error of type
@@ -58,7 +64,9 @@
-(defmethod unify ((a number) (b number) &optional (env (make-empty-environment)))
+(defmethod unify ((a number) (b number)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
"Unifies two numbers A and B.
Two numbers unify only if and only if they are equal as per the function #'=, in
which case an unmodified envirironment ENV is returned.
@@ -72,9 +80,35 @@
:format-arguments (list a b))))
-(defparameter *unify-string-case-insensitive-p* nil)
+(defparameter *unify-string-case-sensitive-p* t)
-(defmethod unify ((a string) (b string) &optional (env (make-empty-environment)))
+(defmethod unify ((a character) (b character)
+ &optional (env (make-empty-environment))
+ &key
+ (case-sensitive *unify-string-case-sensitive-p*)
+ &allow-other-keys)
+ "Unifies two strings A and B.
+Two CHARACTERs A and B unify if and only if they satisfy either #'CHAR= or
+#'CHAR-EQUAL. The choice of which of test to perform (#'CHAR= or #'CHAR-EQUAL)
+is made according to the value of the variable
+*UNIFY-STRING-CASE-INSENSITIVE-P*, which defaults to NIL.
+If A and B unify then an unmodified environment ENV is returned,
+otherwise an error of type UNIFICATION-FAILURE is signaled."
+ (cond ((and case-sensitive (char= a b))
+ env)
+ ((char-equal a b)
+ env)
+ (t
+ (error 'unification-failure
+ :format-control "Connot unify two different characters: ~S ~S."
+ :format-arguments (list a b)))))
+
+
+(defmethod unify ((a string) (b string)
+ &optional (env (make-empty-environment))
+ &key
+ (case-sensitive *unify-string-case-sensitive-p*)
+ &allow-other-keys)
"Unifies two strings A and B.
Two strings A and B unify if and only if they satisfy either #'STRING= or
#'STRING-EQUAL. The choice of which of test to perform (#'STRING= or #'STRING-EQUAL)
@@ -82,9 +116,9 @@
*UNIFY-STRING-CASE-INSENSITIVE-P*, which defaults to NIL.
If A and B unify then an unmodified environment ENV is returned,
otherwise an error of type UNIFICATION-FAILURE is signaled."
- (cond ((and *unify-string-case-insensitive-p* (string-equal a b))
+ (cond ((and case-sensitive (string= a b))
env)
- ((string= a b)
+ ((string-equal a b)
env)
(t
(error 'unification-failure
@@ -92,7 +126,9 @@
:format-arguments (list a b)))))
-(defmethod unify ((a symbol) (b string) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b string)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (error 'unification-failure
@@ -100,7 +136,9 @@
:format-arguments (list a b)))))
-(defmethod unify ((b string) (a symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((b string) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (error 'unification-failure
@@ -108,7 +146,9 @@
:format-arguments (list b a)))))
-(defmethod unify ((a symbol) (b symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
((variable-any-p b) env)
@@ -119,27 +159,36 @@
:format-arguments (list a b)))))
-(defmethod unify ((a symbol) (b t) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b t)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (call-next-method))))
-(defmethod unify ((b t) (a symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((b t) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (call-next-method))))
-(defmethod unify ((a symbol) (b array) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b array)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (error 'unification-failure
- :format-control "Cannot unify a symbol with an array or vector: ~S and ~S."
+ :format-control "Cannot unify a symbol with ~
+ an array or vector: ~S and ~S."
:format-arguments (list a b)))))
-(defmethod unify ((b array) (a symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((b array) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (error 'unification-failure
@@ -147,7 +196,9 @@
:format-arguments (list a b)))))
-(defmethod unify ((as vector) (bs vector) &optional (env (make-empty-environment)))
+(defmethod unify ((as vector) (bs vector)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unless (= (length as) (length bs))
(error 'unification-failure
:format-control "Cannot unify two vectors of different length: ~D and ~D."
@@ -158,7 +209,9 @@
finally (return mgu)))
-(defmethod unify ((s1 sequence) (s2 sequence) &optional (env (make-empty-environment)))
+(defmethod unify ((s1 sequence) (s2 sequence)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unless (= (length s1) (length s2))
(error 'unification-failure
:format-control "Cannot unify two sequences of different length: ~D and ~D."
@@ -186,7 +239,9 @@
(unify a b env))
-(defmethod unify ((as array) (bs array) &optional (env (make-empty-environment)))
+(defmethod unify ((as array) (bs array)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unless (= (array-total-size as) (array-total-size bs))
(error 'unification-failure
:format-control "Cannot unify two arrays of different total size: ~D and ~D."
@@ -200,7 +255,9 @@
;;; Catch all method.
-(defmethod unify ((a t) (b t) &optional (env (make-empty-environment)))
+(defmethod unify ((a t) (b t)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(if (equalp a b)
env
(error 'unification-failure
@@ -229,10 +286,13 @@
;;; Special catch all method.
-(defmethod unify ((x template) (y template) &optional (env (make-empty-environment)))
+(defmethod unify ((x template) (y template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
- :format-control "Unification of two templates of type ~A and ~A has not been yet implemented."
+ :format-control "Unification of two templates of type ~A and ~A ~
+ has not been yet implemented."
:format-arguments (list (class-name (class-of x))
(class-name (class-of y)))))
@@ -241,45 +301,58 @@
;;; NIL special unification methods.
(defmethod unify ((x null) (y null)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
env)
(defmethod unify ((x null) (nt nil-template)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
env)
(defmethod unify ((nt nil-template) (x null)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
env)
(defmethod unify ((nt1 nil-template) (nt2 nil-template)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
env)
;;;---------------------------------------------------------------------------
;;; Symbol methods.
-(defmethod unify ((a symbol) (b symbol-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b symbol-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(cond ((variable-any-p a) env)
((variablep a) (var-unify a b env))
(t (unify a (symbol-template-symbol b) env))))
-(defmethod unify ((b symbol-template) (a symbol) &optional (env (make-empty-environment)))
+(defmethod unify ((b symbol-template) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
-(defmethod unify ((a symbol) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a symbol) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
:format-control "Cannot unify symbol ~S with template ~S."
:format-arguments (list a b)))
-(defmethod unify ((b template) (a symbol) &optional (env (make-empty-environment)))
+
+(defmethod unify ((b template) (a symbol)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
@@ -287,47 +360,74 @@
;;;---------------------------------------------------------------------------
;;; Number template methods.
-(defmethod unify ((a number) (b number-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a number) (b number-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a (number-template-number b) env))
-(defmethod unify ((b number-template) (a number) &optional (env (make-empty-environment)))
+(defmethod unify ((b number-template) (a number)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
-(defmethod unify ((a number) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a number) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
:format-control "Cannot unify the number ~S with template ~S."
:format-arguments (list a b)))
-(defmethod unify ((b template) (a number) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a number)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
;;;---------------------------------------------------------------------------
;;; Sequence (List) template methods
-(defmethod unify ((a sequence) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a sequence) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
- :format-control "Cannot unify a sequence with a non sequence or non sequence access template: ~S ~S."
+ :format-control "Cannot unify a sequence with a non sequence ~
+ or non sequence access template: ~S and ~S."
:format-arguments (list a b)))
-(defmethod unify ((b template) (a sequence) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a sequence)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
+#| Needs to be fixed.
+(defmethod unify ((a list) (b lambda-template) &optional (env (make-empty-environment)))
+ (unify a (template-spec b) env))
+
+
+(defmethod unify ((b lambda-template) (a list) &optional (env (make-empty-environment)))
+ (unify (template-spec b) a env))
+|#
+
+
;;; The next is incomplete and does not signal appropriate errors.
-(defmethod unify ((a list) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a list) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
:format-control "Cannot unify a list with a non-list template: ~S ~S."
:format-arguments (list a b)))
-(defmethod unify ((a list) (b sequence-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a list) (b sequence-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(let ((template-lambda-list (sequence-template-lambda-list b))
(ll (list-length a))
)
@@ -355,7 +455,9 @@
-(defmethod unify ((b template) (a list) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a list)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
@@ -363,14 +465,18 @@
;;;---------------------------------------------------------------------------
;;; Vector template methods.
-(defmethod unify ((a vector) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a vector) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
:format-control "Cannot unify a vector with a non-vector template: ~S ~S."
:format-arguments (list a b)))
-(defmethod unify ((a vector) (b vector-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a vector) (b vector-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(let ((template-lambda-list (sequence-template-lambda-list b))
(vl (length a))
)
@@ -401,20 +507,27 @@
))))
-(defmethod unify ((b template) (a vector) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a vector)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
;;;---------------------------------------------------------------------------
;;; Array template methods.
-(defmethod unify ((a array) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a array) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
- :format-control "Cannot unify an array with a non array or non array access template: ~S ~S."
+ :format-control "Cannot unify an array with a non array ~
+ or non array access template: ~S and ~S."
:format-arguments (list a b)))
-(defmethod unify ((b template) (a array) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a array)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
@@ -425,7 +538,9 @@
(let ((row (make-array (first dims)
:displaced-to array
:displaced-index-offset
- (apply #'array-row-major-index array (append indexes (list 0))))))
+ (apply #'array-row-major-index
+ array
+ (append indexes (list 0))))))
(declare (dynamic-extent row)
(type array row))
(untyped-unify row shape-template env)))
@@ -445,7 +560,9 @@
(unify-array-row array (array-dimensions array) shape-template () env))
-(defmethod unify ((a array) (b array-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a array) (b array-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(let ((template-spec (template-spec b)))
(if (= 2 (length template-spec))
@@ -469,10 +586,13 @@
;;;---------------------------------------------------------------------------
;;; Standard object template methods.
-(defmethod unify ((a standard-object) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a standard-object) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
- :format-control "Cannot unify a standard object with a non standard object template: ~S ~S."
+ :format-control "Cannot unify a standard object with a ~
+ non standard object template: ~S and ~S."
:format-arguments (list a b)))
#|| Old version with heavy syntax
@@ -501,7 +621,8 @@
(defmethod unify ((a standard-object) (b standard-object-template)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(destructuring-bind (class &rest template-slot-specs)
(template-spec b)
(unless (typep a class)
@@ -524,27 +645,34 @@
env))))
-(defmethod unify ((b template) (a standard-object) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a standard-object)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
;;;---------------------------------------------------------------------------
;;; Structure object template methods.
-(defmethod unify ((a structure-object) (b template) &optional (env (make-empty-environment)))
+(defmethod unify ((a structure-object) (b template)
+ &optional (env)
+ &key &allow-other-keys)
(declare (ignore env))
(error 'unification-failure
- :format-control "Cannot unify a structure object with a non structure object template: ~S ~S."
+ :format-control "Cannot unify a structure object with ~
+ a non structure object template: ~S and ~S."
:format-arguments (list a b)))
(defmethod unify ((a structure-object) (b structure-object-template)
- &optional (env (make-empty-environment)))
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(destructuring-bind (class &rest template-slot-specs)
(template-spec b)
(unless (typep a class)
(error 'unification-failure
- :format-control "Cannot unify an instance of ~S with a template for structure ~S."
+ :format-control "Cannot unify an instance of ~S with a ~
+ template for structure ~S."
:format-arguments (list (class-of a) class)))
(if template-slot-specs
(loop for (reader value-template) on template-slot-specs by #'cddr
@@ -554,41 +682,195 @@
env)))
-(defmethod unify ((b template) (a structure-object) &optional (env (make-empty-environment)))
+(defmethod unify ((b template) (a structure-object)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
;;;---------------------------------------------------------------------------
;;; Expression template SUBSEQ methods.
-(defmethod unify ((a sequence) (b subseq-template) &optional (env (make-empty-environment)))
+;;; SEQUENCE
+;;; For non LIST and non VECTOR possible SEQUENCE types.
+
+(defmethod unify ((a sequence) (b subseq-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(destructuring-bind (subseq-kwd from to &rest spec)
(template-spec b)
+ (declare (ignore subseq-kwd))
(let* ((seq-type (type-of a))
- (seq-template-kind (if (symbolp seq-type) seq-type (first seq-type))) ; Stupid FTTB.
+ (seq-template-kind (if (symbolp seq-type)
+ seq-type
+ (first seq-type))) ; Stupid FTTB.
)
+ (unify (subseq a from to)
+ (make-template seq-template-kind `(,seq-template-kind ,@spec))
+ env))))
+
+
+;;; LIST
+
+(defmethod unify ((a list) (b subseq-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (subseq-kwd from to &rest spec)
+ (template-spec b)
+ (declare (ignore subseq-kwd))
(unify (subseq a from to)
- (make-template seq-template-kind `(,seq-template-kind ,@spec))
- env))))
+ (make-template 'list `(list ,@spec))
+ env)))
+
+
+;;; VECTOR
+(defmethod unify ((a vector) (b subseq-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (subseq-kwd from to &rest spec)
+ (template-spec b)
+ (declare (ignore subseq-kwd))
+ (let ((seq-type (type-of a)))
+ (unify (subseq a from to)
+ (make-template seq-type `(,seq-type ,@spec))
+ env))))
-(defmethod unify ((b subseq-template) (a sequence) &optional (env (make-empty-environment)))
+
+(defmethod unify ((b subseq-template) (a sequence)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(unify a b env))
;;;---------------------------------------------------------------------------
-;;; Expression template AREF methods.
+;;; Expression templates
+
+;;; AREF methods.
+
+(defmethod unify ((a array) (b aref-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (aref-kwd indexes value-template)
+ (template-spec b)
+ (declare (ignore aref-kwd))
+ ;; Missing check on index spec.
+ (unless (consp indexes)
+ (setf indexes (list indexes)))
+ (unify (apply #'aref a indexes) value-template env)))
+
+
+;;; Necessary due to standard method sorting.
-(defmethod unify ((a array) (b aref-template) &optional (env (make-empty-environment)))
+(defmethod unify ((a vector) (b aref-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
(destructuring-bind (aref-kwd indexes value-template)
(template-spec b)
(declare (ignore aref-kwd))
;; Missing check on index spec.
+ (when (and (consp indexes) (> (length indexes) 1))
+ (error 'unification-failure
+ :format-control "Cannot unify a vector with an element ~
+ too many dimensions down~@
+ (AREF #(...)~{ ~S~})."
+ :format-arguments (list indexes)
+ ))
(unless (consp indexes)
(setf indexes (list indexes)))
(unify (apply #'aref a indexes) value-template env)))
+(defmethod unify ((b aref-template) (a array)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (unify a b env))
+
+
+;;; ELT methods.
+;;; LIST and VECTOR methods must be specified separatedly because of
+;;; the UNIFY (VECTOR TEMPLATE) methods above. It is a snag, but a
+;;; relatively small one. Besides, they are more efficient.
+;;; The (SEQUENCE ELT-TEMPLATE) ELT-TEMPLATE method is left for those
+;;; sequences which, according to the ANSI spec may exist and not be
+;;; either VECTOR or LIST.
+
+(defmethod unify ((a sequence) (b elt-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (elt-kwd index value-template)
+ (template-spec b)
+ (declare (ignore elt-kwd)
+ (type fixnum index))
+ ;; Missing index check.
+ (unify (elt a index) value-template env)))
+
+
+(defmethod unify ((a vector) (b elt-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (elt-kwd index value-template)
+ (template-spec b)
+ (declare (ignore elt-kwd)
+ (type fixnum index))
+ ;; Missing index check.
+ (unify (aref a index) value-template env)))
+
+
+(defmethod unify ((a list) (b elt-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (elt-kwd index value-template)
+ (template-spec b)
+ (declare (ignore elt-kwd)
+ (type fixnum index))
+ ;; Missing index check.
+ (unify (nth index a) value-template env)))
+
+
+(defmethod unify ((b elt-template) (a sequence)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (unify a b env))
+
+
+;;; NTH methods.
+
+(defmethod unify ((a list) (b nth-template)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (destructuring-bind (nth-kwd index value-template)
+ (template-spec b)
+ (declare (ignore nth-kwd))
+ ;; Missing index check.
+ (unify (nth index a) value-template env)))
+
+(defmethod unify ((b nth-template) (a list)
+ &optional (env (make-empty-environment))
+ &key &allow-other-keys)
+ (unify a b env))
+
+
+;;;---------------------------------------------------------------------------
+;;; Utilities.
+
+(defun unify* (a b &optional (env (make-empty-environment)))
+ (ignore-errors (unify a b env)))
+
+
+(defun unify-equations (eqns &optional (env (make-empty-environment)))
+ (loop for (a b) in eqns
+ for result-env = (unify a b env) then (unify a b result-env)
+ finally (return result-env)))
+
+
+(defun unify-equations* (lhss rhss &optional (env (make-empty-environment)))
+ (loop for a in lhss
+ for b in rhss
+ for result-env = (unify a b env) then (unify a b result-env)
+ finally (return result-env)))
+
+
;;;---------------------------------------------------------------------------
;;; VAR-UNIFY
@@ -674,11 +956,18 @@
nil)
+(defmethod occurs-in-p ((var symbol) (pat character) env)
+ (declare (ignore env))
+ nil)
+
+
(defmethod occurs-in-p ((var symbol) (pat t) env)
(declare (ignore env))
- (warn "Occurrence test unimplemented for pattern ~S of type ~S; returning false."
+ (warn "Occurrence test unimplemented for pattern ~S of type ~S in variable ~S;~@
+ returning false."
pat
- (type-of pat))
+ (type-of pat)
+ var)
nil)