 
 (s/def ::qmark #{'?})
 
+;; FIXME: represent optionals as full-fledged terminal symbols in this grammar
 (s/def ::key-exists-without-binding
   (s/or :required (s/or :flat ::key
                         :list (s/cat :key ::key))

  `(and (not= ~ocr ::match/not-found) (re-matches ~(:regex pat) ~ocr)))

(define-record-type Pattern
  (make-pattern name clauses) pattern?
  [name pattern-name
   clauses pattern-clauses])

(defn pattern
  "Takes a name and some `clauses` and returns a [[Pattern]]."
  [& clauses]
  (make-pattern (str (gensym "pattern-")) clauses))

(defn named-pattern
  [pattern the-name]
  (lens/shove pattern pattern-name the-name))

;;    We differentiate between three kinds of matchers:
;; 1. Constant: Match on exactly one value. The value must be equatable.
;; 2. Regex: Match on a regex. The value must be a String.
;; 3. Existence: Match on the existence. That is, not nil.

        ~rhs)]))

(defmacro parse-pattern
  "Parse the argument to `defpattern` as a [[Pattern]]."
  [pattern]
  (if (vector? pattern)
    `(make-pattern (parse-clauses ~pattern))
    pattern))

;; Match
