diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..f27f198
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: thodg
diff --git a/README.md b/README.md
index 02c1743..7abd80e 100644
--- a/README.md
+++ b/README.md
@@ -18,8 +18,8 @@ Requirements
------------
You will need :
-* https://github.com/cl-facts/lessp
-* https://github.com/cl-facts/rollback
+* https://git.kmx.io/facts-db/cl-compare
+* https://git.kmx.io/facts-db/cl-rollback
Usage
@@ -119,18 +119,13 @@ reverted using their respective rollback functions.
Transactions can be nested safely.
-# Licence
+# TODO
-cl-facts
+## Replace cl-lessp with cl-compare
-Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+## Negative facts specifications
-Permission is hereby granted to use this software granted
-the above copyright notice and this permission paragraph
-are included in all copies and substantial portions of this
-software.
-
-THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
-PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
-AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
-THIS SOFTWARE.
+```
+'((not ?subject ?predicate object1
+ ?predicate2 object2))
+```
diff --git a/anon.lisp b/anon.lisp
index b498acd..d4e701a 100644
--- a/anon.lisp
+++ b/anon.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/database.lisp b/database.lisp
index 9a29dc0..efe3875 100644
--- a/database.lisp
+++ b/database.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/fact.lisp b/fact.lisp
index 8756089..8a35de4 100644
--- a/fact.lisp
+++ b/fact.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/facts.asd b/facts.asd
index fb2a5f7..440723f 100644
--- a/facts.asd
+++ b/facts.asd
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/index.lisp b/index.lisp
index f5782a1..f035887 100644
--- a/index.lisp
+++ b/index.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/meta.lisp b/meta.lisp
index ebdc028..af4827a 100644
--- a/meta.lisp
+++ b/meta.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/mop.lisp b/mop.lisp
index 03b0024..f6519be 100644
--- a/mop.lisp
+++ b/mop.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/package.lisp b/package.lisp
index e50db7f..e20481f 100644
--- a/package.lisp
+++ b/package.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/serialize.lisp b/serialize.lisp
index 8353c3f..e13864f 100644
--- a/serialize.lisp
+++ b/serialize.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/skip-list.lisp b/skip-list.lisp
index f328562..ae0d002 100644
--- a/skip-list.lisp
+++ b/skip-list.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/spec.lisp b/spec.lisp
index 60eccb1..4cde73c 100644
--- a/spec.lisp
+++ b/spec.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
@@ -54,7 +54,7 @@
;; Fact specifications
-(defun expand-spec (spec)
+(defun expand-positive-spec (spec)
(destructuring-bind (s p o &rest more-p-o) spec
(labels ((expand/po (p-o-list result)
(if (endp p-o-list)
@@ -66,6 +66,26 @@
(cons `(,s ,p ,o)
nil))))))
+(defun expand-negative-spec (spec)
+ (destructuring-bind (not s p o &rest more-p-o) spec
+ (assert (eq :not not))
+ (labels ((expand/po (p-o-list result)
+ (if (endp p-o-list)
+ result
+ (destructuring-bind (p o &rest list) p-o-list
+ (expand/po list (cons `(:not ,s ,p ,o)
+ result))))))
+ (nreverse (expand/po more-p-o
+ (cons `(:not ,s ,p ,o)
+ nil))))))
+
+(defun expand-spec (spec)
+ (declare (type sequence spec))
+ (let ((len (length spec)))
+ (if (zerop (mod (- len 3) 2))
+ (expand-positive-spec spec)
+ (expand-negative-spec spec))))
+
(defun expand-specs (specs)
"
Facts specification
diff --git a/test.lisp b/test.lisp
index 17c4d8f..86aad9d 100644
--- a/test.lisp
+++ b/test.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/transaction.lisp b/transaction.lisp
index 0a406f6..c5aacc5 100644
--- a/transaction.lisp
+++ b/transaction.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/usl.lisp b/usl.lisp
index 741c3cd..05c1ec2 100644
--- a/usl.lisp
+++ b/usl.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/view.lisp b/view.lisp
index 9b570e7..928a1cd 100644
--- a/view.lisp
+++ b/view.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
diff --git a/with.lisp b/with.lisp
index 930f97c..1bf15a7 100644
--- a/with.lisp
+++ b/with.lisp
@@ -1,5 +1,5 @@
;; cl-facts
-;; Copyright 2011-2022 Thomas de Grivel <thodg@kmx.io>
+;; Copyright 2011, 2023 Thomas de Grivel <thodg@kmx.io>
;;
;; Permission is hereby granted to use this software granted
;; the above copyright notice and this permission paragraph
@@ -72,7 +72,27 @@
(cond ((and (null var-s) var-o) 'db-index-spo)
((null var-p) 'db-index-pos)
(t 'db-index-osp))
- body)))))))
+ body))))))
+
+ (defun without/iter (spec binding-vars body)
+ (destructuring-bind (not s p o) spec
+ (assert (eq :not not))
+ (let ((var-s (when (binding-p s) (cdr (assoc s binding-vars))))
+ (var-p (when (binding-p p) (cdr (assoc p binding-vars))))
+ (var-o (when (binding-p o) (cdr (assoc o binding-vars)))))
+ (unless (cond ((and var-s var-p var-o)
+ (with/0 var-s var-p var-o '(return t)))
+ ((nor var-s var-p var-o)
+ (with/3 s p o '(return t)))
+ (t (with/1-2 s p o var-s var-p var-o
+ (cond ((and (null var-s) var-o)
+ 'db-index-spo)
+ ((null var-p)
+ 'db-index-pos)
+ (t
+ 'db-index-osp))
+ '(return t))))
+ body)))))
(defmacro with/rec ((spec &rest more-specs) &body body)
(let* ((bindings (collect-bindings spec))