repos
/
cl-unification
/ annotate_shade
summary
|
shortlog
|
log
|
tree
|
commit
|
commitdiff
|
headdiff
|
annotate
|
headblob
|
headfilediff
|
filehistory
normal
|
plain
|
shade
|
zebra
Use *unify-string-case-sensitive-p* consistently.
Annotate for file /unifier.lisp
2004-11-17 mantoniotti
1
;;; -*- Mode: Lisp -*-
22:19:54 '
2
'
3
;;; unifier.lisp
'
4
;;; General CL structures unifier.
'
5
2011-04-02 mantoniotti
6
;;;; See file COPYING for copyright licensing information.
04:05:18 '
7
2004-11-17 mantoniotti
8
(in-package "CL.EXT.DACF.UNIFICATION") ; DACF = Data And Control Flow.
22:19:54 '
9
2009-04-15 mantoniotti
10
(defgeneric unify (a b &optional env &key &allow-other-keys)
2004-11-17 mantoniotti
11
(:documentation
22:19:54 '
12
"Unifies two objects A and B given a substitution ENV.
'
13
A is a Common Lisp object and B is either a Common Lisp object or a
'
14
\"template\", A and B can be commuted.
'
15
'
16
The unification rules are rather complex. Each method of the generic
'
17
function implements a specific rule of unification.
'
18
'
19
The generic function returns a `substitution' upon success or it
'
20
signals a UNIFICATION-FAILURE condition upon failure."))
'
21
'
22
'
23
'
24
;;;===========================================================================
'
25
;;; Simple, non template methods.
'
26
2009-04-15 mantoniotti
27
(defmethod unify ((a symbol) (b list)
10:14:24 '
28
&optional (env (make-empty-environment))
'
29
&key &allow-other-keys)
2004-11-17 mantoniotti
30
"Unifies a symbol A and a list B in an environment ENV.
22:19:54 '
31
If A is not a variable then an error of type UNIFICATION-FAILURE is
'
32
signaled. If A is a unification variable, then the environment ENV is
'
33
extended with a binding for A to B, unless the occurrence check is
'
34
called and fails, in which case an error is signaled."
'
35
(cond ((variable-any-p a) env)
'
36
((variablep a) (var-unify a b env))
'
37
(t (error 'unification-failure
'
38
:format-control "Cannot unify a symbol with a list: ~S ~S."
'
39
:format-arguments (list a b)))))
'
40
'
41
2009-04-15 mantoniotti
42
(defmethod unify ((b list) (a symbol)
10:14:24 '
43
&optional (env (make-empty-environment))
'
44
&key &allow-other-keys)
2004-11-17 mantoniotti
45
"Unifies a symbol B and a list A in an environment ENV.
22:19:54 '
46
If A is not a variable then an error of type UNIFICATION-FAILURE is
'
47
signaled. If A is a unification variable, then the environment ENV is
'
48
extended with a binding for A to B, unless the occurrence check is
'
49
called and fails, in which case an error is signaled."
'
50
(cond ((variable-any-p a) env)
'
51
((variablep a) (var-unify a b env))
'
52
(t (error 'unification-failure
'
53
:format-control "Cannot unify a list with a symbol: ~S ~S."
'
54
:format-arguments (list b a)))))
'
55
'
56
2009-04-15 mantoniotti
57
(defmethod unify ((a list) (b list)
10:14:24 '
58
&optional (env (make-empty-environment))
'
59
&key &allow-other-keys)
2004-11-17 mantoniotti
60
"Unifies a list A and a list B in an environment ENV.
22:19:54 '
61
The unification procedure proceedes recursively on each element of
'
62
both lists. If two elements cannot be unified then an error of type
'
63
UNIFICATION-FAILURE is signaled. Otherwise a possibly extended
'
64
environment is returned."
'
65
(unify (rest a) (rest b) (unify (first a) (first b) env)))
'
66
'
67
'
68
2009-04-15 mantoniotti
69
(defmethod unify ((a number) (b number)
10:14:24 '
70
&optional (env (make-empty-environment))
'
71
&key &allow-other-keys)
2004-11-17 mantoniotti
72
"Unifies two numbers A and B.
22:19:54 '
73
Two numbers unify only if and only if they are equal as per the function #'=, in
'
74
which case an unmodified envirironment ENV is returned.
'
75
Otherwise an error of type UNIFICATION-FAILURE is signalled.
'
76
Of course, asking for unification of two floating point numbers may
'
77
not yield the expected result."
'
78
(if (= a b)
'
79
env
'
80
(error 'unification-failure
'
81
:format-control "Cannot unify two different numbers: ~S ~S."
'
82
:format-arguments (list a b))))
'
83
'
84
2009-04-15 mantoniotti
85
(defparameter *unify-string-case-sensitive-p* t)
2004-11-17 mantoniotti
86
2009-04-15 mantoniotti
87
(defmethod unify ((a character) (b character)
10:14:24 '
88
&optional (env (make-empty-environment))
'
89
&key
'
90
(case-sensitive *unify-string-case-sensitive-p*)
'
91
&allow-other-keys)
'
92
"Unifies two strings A and B.
'
93
Two CHARACTERs A and B unify if and only if they satisfy either #'CHAR= or
'
94
#'CHAR-EQUAL. The choice of which of test to perform (#'CHAR= or #'CHAR-EQUAL)
'
95
is made according to the value of the variable
2011-04-02 rbrown
96
*UNIFY-STRING-CASE-SENSITIVE-P*, which defaults to T.
2009-04-15 mantoniotti
97
If A and B unify then an unmodified environment ENV is returned,
10:14:24 '
98
otherwise an error of type UNIFICATION-FAILURE is signaled."
'
99
(cond ((and case-sensitive (char= a b))
'
100
env)
2010-01-20 pix
101
((and (not case-sensitive) (char-equal a b))
2009-04-15 mantoniotti
102
env)
10:14:24 '
103
(t
'
104
(error 'unification-failure
2010-01-20 pix
105
:format-control "Cannot unify two different characters: ~S ~S."
2009-04-15 mantoniotti
106
:format-arguments (list a b)))))
10:14:24 '
107
'
108
'
109
(defmethod unify ((a string) (b string)
'
110
&optional (env (make-empty-environment))
'
111
&key
'
112
(case-sensitive *unify-string-case-sensitive-p*)
'
113
&allow-other-keys)
2004-11-17 mantoniotti
114
"Unifies two strings A and B.
22:19:54 '
115
Two strings A and B unify if and only if they satisfy either #'STRING= or
'
116
#'STRING-EQUAL. The choice of which of test to perform (#'STRING= or #'STRING-EQUAL)
'
117
is made according to the value of the variable
2011-04-02 rbrown
118
*UNIFY-STRING-CASE-SENSITIVE-P*, which defaults to T.
2004-11-17 mantoniotti
119
If A and B unify then an unmodified environment ENV is returned,
22:19:54 '
120
otherwise an error of type UNIFICATION-FAILURE is signaled."
2009-04-15 mantoniotti
121
(cond ((and case-sensitive (string= a b))
2004-11-17 mantoniotti
122
env)
2010-01-20 pix
123
((and (not case-sensitive) (string-equal a b))
2004-11-17 mantoniotti
124
env)
22:19:54 '
125
(t
'
126
(error 'unification-failure
2010-01-20 pix
127
:format-control "Cannot unify two different strings: ~S ~S."
2004-11-17 mantoniotti
128
:format-arguments (list a b)))))
22:19:54 '
129
'
130
2009-04-15 mantoniotti
131
(defmethod unify ((a symbol) (b string)
10:14:24 '
132
&optional (env (make-empty-environment))
'
133
&key &allow-other-keys)
2004-11-17 mantoniotti
134
(cond ((variable-any-p a) env)
2005-05-20 mantoniotti
135
((variablep a) (var-unify a b env))
2004-11-17 mantoniotti
136
(t (error 'unification-failure
2005-05-20 mantoniotti
137
:format-control "Cannot unify a symbol with a string: ~S ~S."
15:19:53 '
138
:format-arguments (list a b)))))
2004-11-17 mantoniotti
139
22:19:54 '
140
2009-04-15 mantoniotti
141
(defmethod unify ((b string) (a symbol)
10:14:24 '
142
&optional (env (make-empty-environment))
'
143
&key &allow-other-keys)
2004-11-17 mantoniotti
144
(cond ((variable-any-p a) env)
2005-05-20 mantoniotti
145
((variablep a) (var-unify a b env))
2004-11-17 mantoniotti
146
(t (error 'unification-failure
22:19:54 '
147
:format-control "Cannot unify a string with a symbol: ~S ~S."
'
148
:format-arguments (list b a)))))
'
149
'
150
2009-04-15 mantoniotti
151
(defmethod unify ((a symbol) (b symbol)
10:14:24 '
152
&optional (env (make-empty-environment))
'
153
&key &allow-other-keys)
2004-11-17 mantoniotti
154
(cond ((variable-any-p a) env)
22:19:54 '
155
((variablep a) (var-unify a b env))
'
156
((variable-any-p b) env)
'
157
((variablep b) (var-unify b a env))
'
158
((eq a b) env)
'
159
(t (error 'unification-failure
'
160
:format-control "Cannot unify two different symbols: ~S ~S."
'
161
:format-arguments (list a b)))))
'
162
'
163
2009-04-15 mantoniotti
164
(defmethod unify ((a symbol) (b t)
10:14:24 '
165
&optional (env (make-empty-environment))
'
166
&key &allow-other-keys)
2004-11-17 mantoniotti
167
(cond ((variable-any-p a) env)
2005-05-20 mantoniotti
168
((variablep a) (var-unify a b env))
2004-11-17 mantoniotti
169
(t (call-next-method))))
22:19:54 '
170
'
171
2009-04-15 mantoniotti
172
(defmethod unify ((b t) (a symbol)
10:14:24 '
173
&optional (env (make-empty-environment))
'
174
&key &allow-other-keys)
2004-11-17 mantoniotti
175
(cond ((variable-any-p a) env)
2005-05-20 mantoniotti
176
((variablep a) (var-unify a b env))
2004-11-17 mantoniotti
177
(t (call-next-method))))
22:19:54 '
178
'
179
2009-04-15 mantoniotti
180
(defmethod unify ((a symbol) (b array)
10:14:24 '
181
&optional (env (make-empty-environment))
'
182
&key &allow-other-keys)
2004-11-17 mantoniotti
183
(cond ((variable-any-p a) env)
22:19:54 '
184
((variablep a) (var-unify a b env))
'
185
(t (error 'unification-failure
2009-04-15 mantoniotti
186
:format-control "Cannot unify a symbol with ~
10:14:24 '
187
an array or vector: ~S and ~S."
2004-11-17 mantoniotti
188
:format-arguments (list a b)))))
22:19:54 '
189
'
190
2009-04-15 mantoniotti
191
(defmethod unify ((b array) (a symbol)
10:14:24 '
192
&optional (env (make-empty-environment))
'
193
&key &allow-other-keys)
2004-11-17 mantoniotti
194
(cond ((variable-any-p a) env)
22:19:54 '
195
((variablep a) (var-unify a b env))
'
196
(t (error 'unification-failure
'
197
:format-control "Cannot unify an array or vector with a symbol: ~S and ~S."
'
198
:format-arguments (list a b)))))
'
199
'
200
2009-04-15 mantoniotti
201
(defmethod unify ((as vector) (bs vector)
10:14:24 '
202
&optional (env (make-empty-environment))
'
203
&key &allow-other-keys)
2004-11-17 mantoniotti
204
(unless (= (length as) (length bs))
22:19:54 '
205
(error 'unification-failure
'
206
:format-control "Cannot unify two vectors of different length: ~D and ~D."
'
207
:format-arguments (list (length as) (length bs))))
'
208
(loop for a across as
'
209
for b across bs
'
210
for mgu = (unify a b env) then (unify a b mgu)
'
211
finally (return mgu)))
'
212
'
213
2009-04-15 mantoniotti
214
(defmethod unify ((s1 sequence) (s2 sequence)
10:14:24 '
215
&optional (env (make-empty-environment))
'
216
&key &allow-other-keys)
2004-11-17 mantoniotti
217
(unless (= (length s1) (length s2))
22:19:54 '
218
(error 'unification-failure
'
219
:format-control "Cannot unify two sequences of different length: ~D and ~D."
'
220
:format-arguments (list (length s1) (length s2))))
'
221
(loop for i from 0 below (length s1)
'
222
for j from 0 below (length s2)
'
223
for mgu = (unify (elt s1 i) (elt s2 j) env) then (unify (elt s1 i) (elt s2 j) mgu)
'
224
finally (return mgu)))
'
225
'
226
'
227
'
228
(defgeneric untyped-unify (a b &optional env))
'
229
2009-12-17 mantoniotti
230
(defmethod untyped-unify ((as list) (bs vector)
16:44:46 '
231
&optional (env (make-empty-environment)))
2004-11-17 mantoniotti
232
(loop for a in as
22:19:54 '
233
for b across bs
'
234
for mgu = (unify a b env) then (unify a b mgu)
'
235
finally (return mgu)))
'
236
'
237
2009-12-17 mantoniotti
238
(defmethod untyped-unify ((as vector) (bs list)
16:44:46 '
239
&optional (env (make-empty-environment)))
2004-11-17 mantoniotti
240
(untyped-unify bs as env))
22:19:54 '
241
'
242
(defmethod untyped-unify ((a t) (b t) &optional (env (make-empty-environment)))
'
243
(unify a b env))
'
244
'
245
2009-04-15 mantoniotti
246
(defmethod unify ((as array) (bs array)
10:14:24 '
247
&optional (env (make-empty-environment))
'
248
&key &allow-other-keys)
2004-11-17 mantoniotti
249
(unless (= (array-total-size as) (array-total-size bs))
22:19:54 '
250
(error 'unification-failure
'
251
:format-control "Cannot unify two arrays of different total size: ~D and ~D."
'
252
:format-arguments (list (array-total-size as) (array-total-size bs))))
'
253
(loop for ai from 0 below (array-total-size as)
'
254
for bi from 0 below (array-total-size bs)
'
255
for mgu = (unify (row-major-aref as ai) (row-major-aref bs bi) env)
'
256
then (unify (row-major-aref as ai) (row-major-aref bs bi) mgu)
'
257
finally (return mgu)))
'
258
'
259
'
260
;;; Catch all method.
'
261
2009-04-15 mantoniotti
262
(defmethod unify ((a t) (b t)
10:14:24 '
263
&optional (env (make-empty-environment))
'
264
&key &allow-other-keys)
2004-11-17 mantoniotti
265
(if (equalp a b)
22:19:54 '
266
env
'
267
(error 'unification-failure
'
268
:format-control "Cannot unify a ~S and a ~S: ~S ~S."
'
269
:format-arguments (list (type-of a) (type-of b) a b))))
'
270
'
271
'
272
;;;===========================================================================
'
273
;;; Templates methods.
'
274
'
275
'
276
;;; valid-template-p --
'
277
;;; Useful later. Tests whether the object X can be considered a template.
2005-01-28 mantoniotti
278
;;; This should probably become a generic function.
2004-11-17 mantoniotti
279
22:19:54 '
280
(defun valid-template-p (x)
'
281
(or (symbolp x)
'
282
(consp x)
'
283
(numberp x)
2005-01-28 mantoniotti
284
(arrayp x)
19:30:35 '
285
(typep (class-of x) 'structure-class)
'
286
(typep (class-of x) 'standard-class)
'
287
(typep (class-of x) 'built-in-class)
2004-11-17 mantoniotti
288
(template-p x)))
22:19:54 '
289
'
290
'
291
;;; Special catch all method.
'
292
2009-04-15 mantoniotti
293
(defmethod unify ((x template) (y template)
10:14:24 '
294
&optional (env)
'
295
&key &allow-other-keys)
2006-07-19 mantoniotti
296
(declare (ignore env))
2004-11-17 mantoniotti
297
(error 'unification-failure
2009-04-15 mantoniotti
298
:format-control "Unification of two templates of type ~A and ~A ~
10:14:24 '
299
has not been yet implemented."
2004-11-17 mantoniotti
300
:format-arguments (list (class-name (class-of x))
22:19:54 '
301
(class-name (class-of y)))))
'
302
'
303
'
304
;;;---------------------------------------------------------------------------
'
305
;;; NIL special unification methods.
'
306
2006-07-19 mantoniotti
307
(defmethod unify ((x null) (y null)
2009-04-15 mantoniotti
308
&optional (env (make-empty-environment))
10:14:24 '
309
&key &allow-other-keys)
2006-07-19 mantoniotti
310
env)
21:52:34 '
311
'
312
'
313
(defmethod unify ((x null) (nt nil-template)
2009-04-15 mantoniotti
314
&optional (env (make-empty-environment))
10:14:24 '
315
&key &allow-other-keys)
2004-11-17 mantoniotti
316
env)
22:19:54 '
317
'
318
2006-07-19 mantoniotti
319
(defmethod unify ((nt nil-template) (x null)
2009-04-15 mantoniotti
320
&optional (env (make-empty-environment))
10:14:24 '
321
&key &allow-other-keys)
2004-11-17 mantoniotti
322
env)
22:19:54 '
323
'
324
2006-07-19 mantoniotti
325
(defmethod unify ((nt1 nil-template) (nt2 nil-template)
2009-04-15 mantoniotti
326
&optional (env (make-empty-environment))
10:14:24 '
327
&key &allow-other-keys)
2004-11-17 mantoniotti
328
env)
22:19:54 '
329
'
330
'
331
;;;---------------------------------------------------------------------------
'
332
;;; Symbol methods.
'
333
2009-04-15 mantoniotti
334
(defmethod unify ((a symbol) (b symbol-template)
10:14:24 '
335
&optional (env (make-empty-environment))
'
336
&key &allow-other-keys)
2004-11-17 mantoniotti
337
(cond ((variable-any-p a) env)
22:19:54 '
338
((variablep a) (var-unify a b env))
'
339
(t (unify a (symbol-template-symbol b) env))))
'
340
'
341
2009-04-15 mantoniotti
342
(defmethod unify ((b symbol-template) (a symbol)
10:14:24 '
343
&optional (env (make-empty-environment))
'
344
&key &allow-other-keys)
2004-11-17 mantoniotti
345
(unify a b env))
22:19:54 '
346
'
347
2009-04-15 mantoniotti
348
(defmethod unify ((a symbol) (b template)
10:14:24 '
349
&optional (env)
'
350
&key &allow-other-keys)
2004-11-17 mantoniotti
351
(declare (ignore env))
22:19:54 '
352
(error 'unification-failure
'
353
:format-control "Cannot unify symbol ~S with template ~S."
'
354
:format-arguments (list a b)))
'
355
2009-04-15 mantoniotti
356
10:14:24 '
357
(defmethod unify ((b template) (a symbol)
'
358
&optional (env (make-empty-environment))
'
359
&key &allow-other-keys)
2004-11-17 mantoniotti
360
(unify a b env))
22:19:54 '
361
'
362
'
363
'
364
;;;---------------------------------------------------------------------------
'
365
;;; Number template methods.
'
366
2009-04-15 mantoniotti
367
(defmethod unify ((a number) (b number-template)
10:14:24 '
368
&optional (env (make-empty-environment))
'
369
&key &allow-other-keys)
2004-11-17 mantoniotti
370
(unify a (number-template-number b) env))
22:19:54 '
371
'
372
2009-04-15 mantoniotti
373
(defmethod unify ((b number-template) (a number)
10:14:24 '
374
&optional (env (make-empty-environment))
'
375
&key &allow-other-keys)
2004-11-17 mantoniotti
376
(unify a b env))
22:19:54 '
377
2009-04-15 mantoniotti
378
(defmethod unify ((a number) (b template)
10:14:24 '
379
&optional (env)
'
380
&key &allow-other-keys)
2004-11-17 mantoniotti
381
(declare (ignore env))
22:19:54 '
382
(error 'unification-failure
'
383
:format-control "Cannot unify the number ~S with template ~S."
'
384
:format-arguments (list a b)))
'
385
2009-04-15 mantoniotti
386
(defmethod unify ((b template) (a number)
10:14:24 '
387
&optional (env (make-empty-environment))
'
388
&key &allow-other-keys)
2004-11-17 mantoniotti
389
(unify a b env))
22:19:54 '
390
'
391
'
392
;;;---------------------------------------------------------------------------
'
393
;;; Sequence (List) template methods
'
394
2009-04-15 mantoniotti
395
(defmethod unify ((a sequence) (b template)
10:14:24 '
396
&optional (env)
'
397
&key &allow-other-keys)
2006-07-19 mantoniotti
398
(declare (ignore env))
2004-11-17 mantoniotti
399
(error 'unification-failure
2009-04-15 mantoniotti
400
:format-control "Cannot unify a sequence with a non sequence ~
10:14:24 '
401
or non sequence access template: ~S and ~S."
2004-11-17 mantoniotti
402
:format-arguments (list a b)))
22:19:54 '
403
'
404
2009-04-15 mantoniotti
405
(defmethod unify ((b template) (a sequence)
10:14:24 '
406
&optional (env (make-empty-environment))
'
407
&key &allow-other-keys)
2004-11-17 mantoniotti
408
(unify a b env))
22:19:54 '
409
'
410
2009-04-15 mantoniotti
411
#| Needs to be fixed.
10:14:24 '
412
(defmethod unify ((a list) (b lambda-template) &optional (env (make-empty-environment)))
'
413
(unify a (template-spec b) env))
'
414
'
415
'
416
(defmethod unify ((b lambda-template) (a list) &optional (env (make-empty-environment)))
'
417
(unify (template-spec b) a env))
'
418
|#
'
419
'
420
2004-11-17 mantoniotti
421
;;; The next is incomplete and does not signal appropriate errors.
22:19:54 '
422
2009-04-15 mantoniotti
423
(defmethod unify ((a list) (b template)
10:14:24 '
424
&optional (env)
'
425
&key &allow-other-keys)
2004-11-17 mantoniotti
426
(declare (ignore env))
22:19:54 '
427
(error 'unification-failure
'
428
:format-control "Cannot unify a list with a non-list template: ~S ~S."
'
429
:format-arguments (list a b)))
'
430
'
431
2009-04-15 mantoniotti
432
(defmethod unify ((a list) (b sequence-template)
10:14:24 '
433
&optional (env (make-empty-environment))
'
434
&key &allow-other-keys)
2004-11-17 mantoniotti
435
(let ((template-lambda-list (sequence-template-lambda-list b))
22:19:54 '
436
(ll (list-length a))
'
437
)
'
438
(multiple-value-bind (vars optionals keys rest)
'
439
(parse-extended-ordinary-lambda-list template-lambda-list
'
440
:ordinary-variable-test #'valid-template-p
'
441
:optional-variable-test #'valid-template-p
'
442
:key-variable-test #'valid-template-p
'
443
:rest-variable-test #'valid-template-p
'
444
)
2011-04-02 rbrown
445
2004-11-17 mantoniotti
446
(let* ((n-vars (list-length vars))
22:19:54 '
447
(n-optionals (list-length optionals))
2005-10-25 mantoniotti
448
(env (unify (subseq a 0 (min ll (list-length vars)))
19:17:33 '
449
vars
'
450
env))
2004-11-17 mantoniotti
451
)
22:19:54 '
452
(when (and optionals (>= ll (+ n-vars n-optionals)))
'
453
(setf env (unify (subseq a n-vars (+ n-vars n-optionals)) optionals env)))
'
454
(when (and rest (>= ll (+ n-vars n-optionals)))
'
455
(setf env (unify (subseq a (+ n-vars n-optionals)) (first rest) env)))
2009-12-17 mantoniotti
456
(when keys (warn "Sorry matching of keywords ~S not yet implemented." keys))
2004-11-17 mantoniotti
457
env
22:19:54 '
458
))))
'
459
'
460
'
461
2009-04-15 mantoniotti
462
(defmethod unify ((b template) (a list)
10:14:24 '
463
&optional (env (make-empty-environment))
'
464
&key &allow-other-keys)
2004-11-17 mantoniotti
465
(unify a b env))
22:19:54 '
466
'
467
'
468
'
469
;;;---------------------------------------------------------------------------
'
470
;;; Vector template methods.
'
471
2009-04-15 mantoniotti
472
(defmethod unify ((a vector) (b template)
10:14:24 '
473
&optional (env)
'
474
&key &allow-other-keys)
2006-07-19 mantoniotti
475
(declare (ignore env))
2004-11-17 mantoniotti
476
(error 'unification-failure
22:19:54 '
477
:format-control "Cannot unify a vector with a non-vector template: ~S ~S."
'
478
:format-arguments (list a b)))
'
479
'
480
2011-04-02 rbrown
481
(defmethod unify ((a vector) (b sequence-template)
2009-04-15 mantoniotti
482
&optional (env (make-empty-environment))
10:14:24 '
483
&key &allow-other-keys)
2004-11-17 mantoniotti
484
(let ((template-lambda-list (sequence-template-lambda-list b))
22:19:54 '
485
(vl (length a))
'
486
)
'
487
(multiple-value-bind (vars optionals keys rest)
'
488
(parse-extended-ordinary-lambda-list template-lambda-list
'
489
:ordinary-variable-test #'valid-template-p
'
490
:optional-variable-test #'valid-template-p
'
491
:key-variable-test #'valid-template-p
'
492
:rest-variable-test #'valid-template-p
'
493
)
2011-04-02 rbrown
494
2004-11-17 mantoniotti
495
(let ((n-vars (list-length vars))
22:19:54 '
496
(n-optionals (list-length optionals))
'
497
)
'
498
(loop for v in vars
'
499
for e across (subseq a 0 (list-length vars))
'
500
for mgu = (unify v e env) then (unify v e mgu)
'
501
finally (setf env mgu))
'
502
(when (and optionals (>= vl (+ n-vars n-optionals)))
'
503
(loop for v in optionals
'
504
for e across (subseq a n-vars (+ n-vars n-optionals))
'
505
for mgu = (unify v e env) then (unify v e mgu)
'
506
finally (setf env mgu)))
'
507
(when (and rest (>= vl (+ n-vars n-optionals)))
'
508
(setf env (unify (subseq a (+ n-vars n-optionals)) (first rest) env)))
'
509
(when keys (warn "Sorry matching of keywords ~S not yet implemented." keys))
'
510
env
'
511
))))
'
512
'
513
2009-04-15 mantoniotti
514
(defmethod unify ((b template) (a vector)
10:14:24 '
515
&optional (env (make-empty-environment))
'
516
&key &allow-other-keys)
2004-11-17 mantoniotti
517
(unify a b env))
22:19:54 '
518
'
519
'
520
;;;---------------------------------------------------------------------------
'
521
;;; Array template methods.
'
522
2009-04-15 mantoniotti
523
(defmethod unify ((a array) (b template)
10:14:24 '
524
&optional (env)
'
525
&key &allow-other-keys)
2006-07-19 mantoniotti
526
(declare (ignore env))
2004-11-17 mantoniotti
527
(error 'unification-failure
2009-04-15 mantoniotti
528
:format-control "Cannot unify an array with a non array ~
10:14:24 '
529
or non array access template: ~S and ~S."
2004-11-17 mantoniotti
530
:format-arguments (list a b)))
22:19:54 '
531
2009-04-15 mantoniotti
532
(defmethod unify ((b template) (a array)
10:14:24 '
533
&optional (env (make-empty-environment))
'
534
&key &allow-other-keys)
2004-11-17 mantoniotti
535
(unify a b env))
22:19:54 '
536
'
537
'
538
(defun unify-array-row (array dims shape-template indexes env)
'
539
(cond ((null dims) env)
'
540
((= (list-length dims) 1)
'
541
;; Unify the row with the shape-template.
'
542
(let ((row (make-array (first dims)
'
543
:displaced-to array
'
544
:displaced-index-offset
2009-04-15 mantoniotti
545
(apply #'array-row-major-index
10:14:24 '
546
array
'
547
(append indexes (list 0))))))
2004-11-17 mantoniotti
548
(declare (dynamic-extent row)
22:19:54 '
549
(type array row))
'
550
(untyped-unify row shape-template env)))
'
551
(t
'
552
(loop for i from 0 below (first dims)
'
553
for row-template in shape-template
'
554
do (unify-array-row array
'
555
(rest dims)
'
556
row-template
'
557
(append indexes (list i))
'
558
env)
'
559
finally (return env)))
'
560
))
'
561
'
562
'
563
(defun unify-array-rows (array shape-template env)
'
564
(unify-array-row array (array-dimensions array) shape-template () env))
'
565
'
566
2009-04-15 mantoniotti
567
(defmethod unify ((a array) (b array-template)
10:14:24 '
568
&optional (env (make-empty-environment))
'
569
&key &allow-other-keys)
2004-11-17 mantoniotti
570
(let ((template-spec (template-spec b)))
22:19:54 '
571
(if (= 2 (length template-spec))
'
572
'
573
;; Template is (<array type specifier> <shape-template>)
'
574
(destructuring-bind (array-type-spec shape-template)
'
575
template-spec
'
576
(declare (ignore array-type-spec))
'
577
;; Missing check for type-spec.
'
578
(unify-array-rows a shape-template env))
'
579
'
580
;; Template is (array (['*' | <element type>] [<dimension spec>]) <shape template>)
'
581
(destructuring-bind (array-kwd type-spec shape-template)
'
582
template-spec
2006-07-19 mantoniotti
583
(declare (ignore array-kwd type-spec))
2004-11-17 mantoniotti
584
;; Missing check for type-spec.
22:19:54 '
585
(unify-array-rows a shape-template env))
'
586
)))
'
587
'
588
'
589
'
590
;;;---------------------------------------------------------------------------
'
591
;;; Standard object template methods.
'
592
2009-04-15 mantoniotti
593
(defmethod unify ((a standard-object) (b template)
10:14:24 '
594
&optional (env)
'
595
&key &allow-other-keys)
2006-07-19 mantoniotti
596
(declare (ignore env))
2004-11-17 mantoniotti
597
(error 'unification-failure
2009-04-15 mantoniotti
598
:format-control "Cannot unify a standard object with a ~
10:14:24 '
599
non standard object template: ~S and ~S."
2004-11-17 mantoniotti
600
:format-arguments (list a b)))
22:19:54 '
601
2006-07-19 mantoniotti
602
#|| Old version with heavy syntax
2004-11-17 mantoniotti
603
(defmethod unify ((a standard-object) (b standard-object-template)
22:19:54 '
604
&optional (env (make-empty-environment)))
'
605
(destructuring-bind (class &rest template-slot-specs)
'
606
(template-spec b)
'
607
(unless (typep a class)
'
608
(error 'unification-failure
'
609
:format-control "Cannot unify an instance of ~S with a template for class ~S."
'
610
:format-arguments (list (class-of a) class)))
'
611
(flet ((slot-spec-unify (accessor-spec reader value-template mgu)
'
612
(ecase accessor-spec
'
613
(slot-value
'
614
(unify (slot-value a reader) value-template mgu))
'
615
(slot-accessor
'
616
(unify (funcall reader a) value-template mgu))))
'
617
)
'
618
(if template-slot-specs
'
619
(loop for (accessor-spec reader value-template) in template-slot-specs
'
620
for mgu = (slot-spec-unify accessor-spec reader value-template env)
'
621
then (slot-spec-unify accessor-spec reader value-template mgu)
'
622
finally (return mgu))
'
623
env))))
2006-07-19 mantoniotti
624
||#
2004-11-17 mantoniotti
625
22:19:54 '
626
'
627
(defmethod unify ((a standard-object) (b standard-object-template)
2009-04-15 mantoniotti
628
&optional (env (make-empty-environment))
10:14:24 '
629
&key &allow-other-keys)
2004-11-17 mantoniotti
630
(destructuring-bind (class &rest template-slot-specs)
22:19:54 '
631
(template-spec b)
'
632
(unless (typep a class)
'
633
(error 'unification-failure
'
634
:format-control "Cannot unify an instance of ~S with a template for class ~S."
'
635
:format-arguments (list (class-of a) class)))
'
636
(flet ((slot-spec-unify (reader value-template mgu)
'
637
(etypecase reader
'
638
(list
'
639
(assert (eq (first reader) 'slot-value))
'
640
(unify (slot-value a (second reader)) value-template mgu))
'
641
((or function symbol)
'
642
(unify (funcall reader a) value-template mgu))))
'
643
)
'
644
(if template-slot-specs
'
645
(loop for (reader value-template) on template-slot-specs by #'cddr
'
646
for mgu = (slot-spec-unify reader value-template env)
'
647
then (slot-spec-unify reader value-template mgu)
'
648
finally (return mgu))
'
649
env))))
'
650
'
651
2009-04-15 mantoniotti
652
(defmethod unify ((b template) (a standard-object)
10:14:24 '
653
&optional (env (make-empty-environment))
'
654
&key &allow-other-keys)
2004-11-17 mantoniotti
655
(unify a b env))
22:19:54 '
656
'
657
'
658
;;;---------------------------------------------------------------------------
'
659
;;; Structure object template methods.
'
660
2009-04-15 mantoniotti
661
(defmethod unify ((a structure-object) (b template)
10:14:24 '
662
&optional (env)
'
663
&key &allow-other-keys)
2006-07-19 mantoniotti
664
(declare (ignore env))
2004-11-17 mantoniotti
665
(error 'unification-failure
2009-04-15 mantoniotti
666
:format-control "Cannot unify a structure object with ~
10:14:24 '
667
a non structure object template: ~S and ~S."
2004-11-17 mantoniotti
668
:format-arguments (list a b)))
22:19:54 '
669
'
670
'
671
(defmethod unify ((a structure-object) (b structure-object-template)
2009-04-15 mantoniotti
672
&optional (env (make-empty-environment))
10:14:24 '
673
&key &allow-other-keys)
2004-11-17 mantoniotti
674
(destructuring-bind (class &rest template-slot-specs)
22:19:54 '
675
(template-spec b)
'
676
(unless (typep a class)
'
677
(error 'unification-failure
2009-04-15 mantoniotti
678
:format-control "Cannot unify an instance of ~S with a ~
10:14:24 '
679
template for structure ~S."
2004-11-17 mantoniotti
680
:format-arguments (list (class-of a) class)))
22:19:54 '
681
(if template-slot-specs
'
682
(loop for (reader value-template) on template-slot-specs by #'cddr
'
683
for mgu = (unify (funcall reader a) value-template env)
'
684
then (unify (funcall reader a) value-template mgu)
'
685
finally (return mgu))
'
686
env)))
'
687
'
688
2009-04-15 mantoniotti
689
(defmethod unify ((b template) (a structure-object)
10:14:24 '
690
&optional (env (make-empty-environment))
'
691
&key &allow-other-keys)
2004-11-17 mantoniotti
692
(unify a b env))
22:19:54 '
693
'
694
'
695
;;;---------------------------------------------------------------------------
'
696
;;; Expression template SUBSEQ methods.
'
697
2009-04-15 mantoniotti
698
;;; SEQUENCE
10:14:24 '
699
;;; For non LIST and non VECTOR possible SEQUENCE types.
'
700
'
701
(defmethod unify ((a sequence) (b subseq-template)
'
702
&optional (env (make-empty-environment))
'
703
&key &allow-other-keys)
2004-11-17 mantoniotti
704
(destructuring-bind (subseq-kwd from to &rest spec)
22:19:54 '
705
(template-spec b)
2009-04-15 mantoniotti
706
(declare (ignore subseq-kwd))
2004-11-17 mantoniotti
707
(let* ((seq-type (type-of a))
2009-04-15 mantoniotti
708
(seq-template-kind (if (symbolp seq-type)
10:14:24 '
709
seq-type
'
710
(first seq-type))) ; Stupid FTTB.
2004-11-17 mantoniotti
711
)
2009-04-15 mantoniotti
712
(unify (subseq a from to)
10:14:24 '
713
(make-template seq-template-kind `(,seq-template-kind ,@spec))
'
714
env))))
'
715
'
716
'
717
;;; LIST
'
718
'
719
(defmethod unify ((a list) (b subseq-template)
'
720
&optional (env (make-empty-environment))
'
721
&key &allow-other-keys)
'
722
(destructuring-bind (subseq-kwd from to &rest spec)
'
723
(template-spec b)
'
724
(declare (ignore subseq-kwd))
2006-07-19 mantoniotti
725
(unify (subseq a from to)
2009-04-15 mantoniotti
726
(make-template 'list `(list ,@spec))
10:14:24 '
727
env)))
'
728
'
729
'
730
;;; VECTOR
'
731
'
732
(defmethod unify ((a vector) (b subseq-template)
'
733
&optional (env (make-empty-environment))
'
734
&key &allow-other-keys)
'
735
(destructuring-bind (subseq-kwd from to &rest spec)
'
736
(template-spec b)
'
737
(declare (ignore subseq-kwd))
'
738
(let ((seq-type (type-of a)))
'
739
(unify (subseq a from to)
'
740
(make-template seq-type `(,seq-type ,@spec))
'
741
env))))
2004-11-17 mantoniotti
742
22:19:54 '
743
2009-04-15 mantoniotti
744
(defmethod unify ((b subseq-template) (a sequence)
10:14:24 '
745
&optional (env (make-empty-environment))
'
746
&key &allow-other-keys)
2004-11-17 mantoniotti
747
(unify a b env))
22:19:54 '
748
'
749
'
750
;;;---------------------------------------------------------------------------
2009-04-15 mantoniotti
751
;;; Expression templates
2004-11-17 mantoniotti
752
2009-04-15 mantoniotti
753
;;; AREF methods.
10:14:24 '
754
'
755
(defmethod unify ((a array) (b aref-template)
'
756
&optional (env (make-empty-environment))
'
757
&key &allow-other-keys)
2004-11-17 mantoniotti
758
(destructuring-bind (aref-kwd indexes value-template)
22:19:54 '
759
(template-spec b)
'
760
(declare (ignore aref-kwd))
'
761
;; Missing check on index spec.
'
762
(unless (consp indexes)
'
763
(setf indexes (list indexes)))
'
764
(unify (apply #'aref a indexes) value-template env)))
'
765
'
766
2009-04-15 mantoniotti
767
;;; Necessary due to standard method sorting.
10:14:24 '
768
'
769
(defmethod unify ((a vector) (b aref-template)
'
770
&optional (env (make-empty-environment))
'
771
&key &allow-other-keys)
'
772
(destructuring-bind (aref-kwd indexes value-template)
'
773
(template-spec b)
'
774
(declare (ignore aref-kwd))
'
775
;; Missing check on index spec.
'
776
(when (and (consp indexes) (> (length indexes) 1))
'
777
(error 'unification-failure
'
778
:format-control "Cannot unify a vector with an element ~
'
779
too many dimensions down~@
'
780
(AREF #(...)~{ ~S~})."
'
781
:format-arguments (list indexes)
'
782
))
'
783
(unless (consp indexes)
'
784
(setf indexes (list indexes)))
'
785
(unify (apply #'aref a indexes) value-template env)))
'
786
'
787
'
788
(defmethod unify ((b aref-template) (a array)
'
789
&optional (env (make-empty-environment))
'
790
&key &allow-other-keys)
'
791
(unify a b env))
'
792
'
793
'
794
;;; ELT methods.
'
795
;;; LIST and VECTOR methods must be specified separatedly because of
'
796
;;; the UNIFY (VECTOR TEMPLATE) methods above. It is a snag, but a
'
797
;;; relatively small one. Besides, they are more efficient.
'
798
;;; The (SEQUENCE ELT-TEMPLATE) ELT-TEMPLATE method is left for those
'
799
;;; sequences which, according to the ANSI spec may exist and not be
'
800
;;; either VECTOR or LIST.
'
801
'
802
(defmethod unify ((a sequence) (b elt-template)
'
803
&optional (env (make-empty-environment))
'
804
&key &allow-other-keys)
'
805
(destructuring-bind (elt-kwd index value-template)
'
806
(template-spec b)
'
807
(declare (ignore elt-kwd)
'
808
(type fixnum index))
'
809
;; Missing index check.
'
810
(unify (elt a index) value-template env)))
'
811
'
812
'
813
(defmethod unify ((a vector) (b elt-template)
'
814
&optional (env (make-empty-environment))
'
815
&key &allow-other-keys)
'
816
(destructuring-bind (elt-kwd index value-template)
'
817
(template-spec b)
'
818
(declare (ignore elt-kwd)
'
819
(type fixnum index))
'
820
;; Missing index check.
'
821
(unify (aref a index) value-template env)))
'
822
'
823
'
824
(defmethod unify ((a list) (b elt-template)
'
825
&optional (env (make-empty-environment))
'
826
&key &allow-other-keys)
'
827
(destructuring-bind (elt-kwd index value-template)
'
828
(template-spec b)
'
829
(declare (ignore elt-kwd)
'
830
(type fixnum index))
'
831
;; Missing index check.
'
832
(unify (nth index a) value-template env)))
'
833
'
834
'
835
(defmethod unify ((b elt-template) (a sequence)
'
836
&optional (env (make-empty-environment))
'
837
&key &allow-other-keys)
'
838
(unify a b env))
'
839
'
840
'
841
;;; NTH methods.
'
842
'
843
(defmethod unify ((a list) (b nth-template)
'
844
&optional (env (make-empty-environment))
'
845
&key &allow-other-keys)
'
846
(destructuring-bind (nth-kwd index value-template)
'
847
(template-spec b)
'
848
(declare (ignore nth-kwd))
'
849
;; Missing index check.
'
850
(unify (nth index a) value-template env)))
'
851
'
852
(defmethod unify ((b nth-template) (a list)
'
853
&optional (env (make-empty-environment))
'
854
&key &allow-other-keys)
'
855
(unify a b env))
'
856
'
857
'
858
;;;---------------------------------------------------------------------------
'
859
;;; Utilities.
'
860
'
861
(defun unify* (a b &optional (env (make-empty-environment)))
2010-01-15 pix
862
(handler-case
07:59:02 '
863
(unify a b env)
'
864
(unification-failure (c) (values nil c))))
'
865
2009-04-15 mantoniotti
866
10:14:24 '
867
(defun unify-equations (eqns &optional (env (make-empty-environment)))
'
868
(loop for (a b) in eqns
'
869
for result-env = (unify a b env) then (unify a b result-env)
'
870
finally (return result-env)))
'
871
'
872
'
873
(defun unify-equations* (lhss rhss &optional (env (make-empty-environment)))
'
874
(loop for a in lhss
'
875
for b in rhss
'
876
for result-env = (unify a b env) then (unify a b result-env)
'
877
finally (return result-env)))
'
878
'
879
2004-11-17 mantoniotti
880
;;;---------------------------------------------------------------------------
22:19:54 '
881
;;; VAR-UNIFY
'
882
'
883
(defparameter *occurrence-check-p* t)
'
884
'
885
(defgeneric occurs-in-p (var pat env))
'
886
'
887
(defun var-unify (var pat env)
'
888
(if (eq var pat)
'
889
env
'
890
(multiple-value-bind (value foundp)
'
891
(find-variable-value var env)
'
892
(cond (foundp
'
893
(unify value pat env))
'
894
((and *occurrence-check-p*
'
895
(occurs-in-p var pat env))
'
896
(error 'unification-failure
'
897
:format-control "Variable ~S occurs in ~S."
'
898
:format-arguments (list var pat)))
'
899
(t
'
900
(extend-environment var pat env))))))
'
901
'
902
'
903
2006-07-19 mantoniotti
904
#||
2004-11-17 mantoniotti
905
(defmethod occurs-in-p ((var symbol) pat env)
22:19:54 '
906
(cond ((variablep pat)
'
907
(or (eq var pat)
'
908
(multiple-value-bind (value foundp)
'
909
(find-variable-value pat env)
'
910
(when foundp
'
911
(occurs-in-p var value env)))
'
912
))
'
913
((atom pat) nil)
'
914
((consp pat)
'
915
(or (occurs-in-p var (first pat) env)
'
916
(occurs-in-p var (rest pat) env)))
'
917
(t
'
918
(error "unimplemented"))))
2006-07-19 mantoniotti
919
||#
21:52:34 '
920
2004-11-17 mantoniotti
921
22:19:54 '
922
(defmethod occurs-in-p ((var symbol) (pat symbol) env)
'
923
(when (variablep pat)
'
924
(or (eq var pat)
'
925
(multiple-value-bind (value foundp)
'
926
(find-variable-value pat env)
'
927
(when foundp
'
928
(occurs-in-p var value env)))
'
929
)))
'
930
2006-07-19 mantoniotti
931
2004-11-17 mantoniotti
932
(defmethod occurs-in-p ((var symbol) (pat list) env)
22:19:54 '
933
(or (occurs-in-p var (first pat) env)
'
934
(occurs-in-p var (rest pat) env)))
'
935
2006-07-19 mantoniotti
936
21:52:34 '
937
(defmethod occurs-in-p ((var symbol) (pat null) env)
'
938
;; This is needed because of different precedence rules among lisps
'
939
;; in COMPUTE-APPLICABLE-METHODS when NIL has to matched against
'
940
;; SYMBOL and LIST.
2011-04-02 rbrown
941
2006-07-19 mantoniotti
942
;; We know (assume) that VAR is not NIL.
21:52:34 '
943
nil)
'
944
'
945
2004-11-17 mantoniotti
946
(defmethod occurs-in-p ((var symbol) (pat array) env)
22:19:54 '
947
(loop for i from 0 below (array-total-size pat)
'
948
thereis (occurs-in-p var (row-major-aref pat i) env)))
'
949
'
950
'
951
(defmethod occurs-in-p ((var symbol) (pat vector) env) ; This may be faster than the above.
'
952
(some #'(lambda (x) (occurs-in-p var x env)) pat))
'
953
'
954
'
955
(defmethod occurs-in-p ((var symbol) (pat string) env) ; This is useless, but it's here for completeness.
'
956
(declare (ignore env))
'
957
nil)
'
958
'
959
'
960
(defmethod occurs-in-p ((var symbol) (pat number) env)
'
961
(declare (ignore env))
'
962
nil)
'
963
'
964
2009-04-15 mantoniotti
965
(defmethod occurs-in-p ((var symbol) (pat character) env)
10:14:24 '
966
(declare (ignore env))
'
967
nil)
'
968
'
969
2004-11-17 mantoniotti
970
(defmethod occurs-in-p ((var symbol) (pat t) env)
22:19:54 '
971
(declare (ignore env))
2009-04-15 mantoniotti
972
(warn "Occurrence test unimplemented for pattern ~S of type ~S in variable ~S;~@
10:14:24 '
973
returning false."
2004-11-17 mantoniotti
974
pat
2009-04-15 mantoniotti
975
(type-of pat)
10:14:24 '
976
var)
2004-11-17 mantoniotti
977
nil)
22:19:54 '
978
'
979
'
980
(defmethod occurs-in-p ((var t) (pat t) env)
'
981
(declare (ignore env))
'
982
(error "Occurrence test called on a non symbol ~S. Major problem."
'
983
var))
'
984
'
985
;;; end of file -- unifier.lisp --