;is the element a var symbol? i.e ?x ?y.. etc.
(mac varsym? (x)
`(and (is (type ,x) 'sym) (is ((string ,x) 0) #\?)))
;Are both elements varsyms? i.e ?x = ?y (?x . ?y)
(mac tvs? (x y)
`(and (varsym? (car ,x))(varsym? (car ,y))))
;is element x a varsym that hasn't been added to binds?
(mac xvs? (x y binds)
`(and (varsym? (car ,x))(~varsym? (car ,y))(no (assoc (car ,x) ,binds))))
;is element y a varsym that hasn't been added to binds?
(mac yvs? (x y binds)
`(and (varsym? (car ,y)) (~varsym? (car ,x))(no (assoc (car ,y) ,binds))))
;make bind i. e ((?x . a)(?y . b))
(mac mb (a b binds)
`(push (cons (car ,a) (car ,b)) ,binds))
(def match (x y)
(let binds nil
((afn (x y)
(if (or (no x) (no y)) binds ;lists are missing
(if (iso x y) binds ;list are the same
(do
(if (tvs? x y) (mb x y binds))
(if (xvs? x y binds) (mb x y binds))
(if (yvs? x y binds) (mb y x binds))
(self cdr.x cdr.y)))))
x y)))
Tests
(match '(p ?x b ?y a) '(p ?y b c a))
((?y . c) (?x . ?y))
(match '(p ?x b ?y ?z) '(p ?y b c a))
((?z . a) (?y . c) (?x . ?y))
(match '(a b c) '(a a a))
nil ... i.e nil bindings since there are no vars
(match '(a b c) '(a b c))
nil