     nil))
 
 ;;    There are four kinds of clauses
-;; 1. Match a key in a map to some specific value.
-;; 2. Match the value at a path in a map to a specific value.
-;; 3. Assert the existence of a value in a map for a key.
-;; 4. Assert the existence of a value in a map for a path.
+;; 1. Assert the existence of a value in a map for a key.
+;;    - without binding - with binding
+;; 2. Assert the existence of a value in a map for a path.
+;;    - without binding - with binding
+;; 3. Match a key in a map to some specific value.
+;;    - without binding - with binding
+;; 4. Match the value at a path in a map to a specific value.
+;;    - without binding - with binding
 ;; 5. An optional clause that contains a regular clause and makes the match optional.
 
-;; 1
+;; 1.
+(define-record-type KeyExistsWithoutBindingClause
+  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`."}
+  (make-key-exists-without-binding-clause key matcher)
+  key-exists-without-binding-clause?
+  [key key-exists-without-binding-clause-key
+   matcher key-exists-without-binding-clause-matcher])
+
+(define-record-type KeyExistsWithBindingClause
+  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`. When evaluated, binds it's result to `binding`."}
+  (make-key-exists-with-binding-clause key matcher binding)
+  key-exists-with-binding-clause?
+  [key key-exists-with-binding-clause-key
+   matcher key-exists-with-binding-clause-matcher
+   binding key-exists-with-binding-clause-binding])
+
+(defn key-exists-without-binding-clause
+  "Returns a clause that asserts the existence of a non-nil value at `key`."
+  [key]
+  (make-key-exists-without-binding-clause key the-existence-matcher))
+
+(defn key-exists-with-binding-clause
+  "Returns a clause that asserts the existence of a non-nil value at `key`."
+  [key bind]
+  (make-key-exists-with-binding-clause key the-existence-matcher bind))
+
+;; 2.
+(define-record-type
+  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`."}
+  PathExistsWithoutBindingClause
+  (make-path-exists-without-binding-clause path matcher)
+  path-exists-without-binding-clause?
+  [path path-exists-without-binding-clause-path
+   matcher path-exists-without-binding-clause-matcher])
+
+(define-record-type
+  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`. When evaluated, binds it's result to `binding`."}
+  PathExistsWithBindingClause
+  (make-path-exists-with-binding-clause path matcher binding)
+  path-exists-with-binding-clause?
+  [path path-exists-with-binding-clause-path
+   matcher path-exists-with-binding-clause-matcher
+   binding path-exists-with-binding-clause-binding])
+
+(defn path-exists-with-binding-clause
+  "Returns a clause that asserts the existence of a non-nil value at `key`."
+  [path bind]
+  (make-path-exists-with-binding-clause path the-existence-matcher bind))
+
+(defn path-exists-without-binding-clause
+  "Returns a clause that asserts the existence of a non-nil value at `key`."
+  [path]
+  (make-path-exists-without-binding-clause path the-existence-matcher))
+
+;; 3.
+(define-record-type
+  ^{:doc "A clause that matches the value of `key` of a map using `matcher`."}
+  KeyMatchesWithoutBindingClause
+  (make-key-matches-without-binding-clause key matcher)
+  key-matches-without-binding-clause?
+  [key key-matches-without-binding-clause-key
+   matcher key-matches-without-binding-clause-matcher])
+
 (define-record-type
   ^{:doc "A clause that matches the value of `key` of a map using `matcher`. When evaluated, binds it's result to `binding`."}
   KeyMatchesWithBindingClause

   matcher path-matches-with-binding-clause-matcher
   binding path-matches-with-binding-clause-binding])

(define-record-type
  ^{:doc "A clause that matches the value of a map at the `path` using a `matcher`."}
  PathMatchesWithoutBindingClause
  (make-path-matches-without-binding-clause path matcher)
  path-matches-without-binding-clause?
  [path path-matches-without-binding-clause-path
   matcher path-matches-without-binding-clause-matcher])

(def path? "Is something a valid path?" (some-fn list? vector?))

(defn path-matches-with-binding-clause
  [path matcher bind]
  {:pre [(and (path? path) (matcher? matcher))]}
  (make-path-matches-with-binding-clause path matcher bind))

(defn path-matches-without-binding-clause
  [path matcher]
  {:pre [(and (path? path) (matcher? matcher))]}
  (make-path-matches-without-binding-clause path matcher))

;; 3.
(define-record-type KeyExistsWithBindingClause
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`. When evaluated, binds it's result to `binding`."}
  (make-key-exists-with-binding-clause key matcher binding)
  key-exists-with-binding-clause?
  [key key-exists-with-binding-clause-key
   matcher key-exists-with-binding-clause-matcher
   binding key-exists-with-binding-clause-binding])

(define-record-type KeyExistsWithoutBindingClause
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`."}
  (make-key-exists-without-binding-clause key matcher)
  key-exists-without-binding-clause?
  [key key-exists-without-binding-clause-key
   matcher key-exists-without-binding-clause-matcher])

(defn key-exists-with-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [key bind]
  (make-key-exists-with-binding-clause key the-existence-matcher bind))

(defn key-exists-without-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [key]
  (make-key-exists-without-binding-clause key the-existence-matcher))

;; 4.
(define-record-type
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`. When evaluated, binds it's result to `binding`."}
  PathExistsWithBindingClause
  (make-path-exists-with-binding-clause path matcher binding)
  path-exists-with-binding-clause?
  [path path-exists-with-binding-clause-path
   matcher path-exists-with-binding-clause-matcher
   binding path-exists-with-binding-clause-binding])

(define-record-type
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`."}
  PathExistsWithoutBindingClause
  (make-path-exists-without-binding-clause path matcher)
  path-exists-without-binding-clause?
  [path path-exists-without-binding-clause-path
   matcher path-exists-without-binding-clause-matcher])

(defn path-exists-with-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [path bind]
  (make-path-exists-with-binding-clause path the-existence-matcher bind))

(defn path-exists-without-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [path]
  (make-path-exists-without-binding-clause path the-existence-matcher))

;; 5.
(define-record-type

(def matcher-lens
  "Returns a function that when applied to a clause, returns a lens focusing on
  the matcher of the clause."
  (clause-lens key-exists-without-binding-clause-matcher
               key-exists-with-binding-clause-matcher
               path-exists-without-binding-clause-matcher
               path-exists-with-binding-clause-matcher
               key-matches-without-binding-clause-matcher
               key-matches-with-binding-clause-matcher
               path-matches-without-binding-clause-matcher
               path-matches-with-binding-clause-matcher))

(def path-lens
  "Returns a function that when applied to a clause, returns a lens focusing on
  the path of the clause."
  (clause-lens key-exists-without-binding-clause-key
               key-exists-with-binding-clause-key
               path-exists-without-binding-clause-path
               path-exists-with-binding-clause-path
               key-matches-without-binding-clause-key
               key-matches-with-binding-clause-key
               path-matches-without-binding-clause-path
               path-matches-with-binding-clause-path))

;;;; Parse
;; Translate pattern expressions for `active.clojure.match` to clauses
