   [or-op cat-op star-op plus-op opt-op not-op])
 
 (def operation
-  (gen/sized
-   (fn [size]
-     (let [op-generators (map #(gen/resize size %) all-op-generators)]
-       (gen/one-of op-generators)))))
+  (fn [alias-gen]
+    (gen/sized
+     (fn [size]
+       (let [op-generators (map #(gen/resize size (% alias-gen))
+                                all-op-generators)]
+         (gen/one-of op-generators))))))
+
+(defn expression
+  [alias-gen]
+  (gen/frequency [[8 (operation alias-gen)]
+                  [4 (gen/one-of collection-generators)]
+                  [1 alias-gen]]))
 
 (defn ppm [obj]
   (let [orig-dispatch pprint/*print-pprint-dispatch*]

(ns smallex.test.generators
  (:require [simple-check.generators :as gen]
            [clojure.test :refer :all]
            [clojure.pprint :as pprint :refer [pprint]]))

        (orig-dispatch o))
      (pprint obj))))

(defn alias
  [prev-aliases]
  (let [alias-gen (if (seq prev-aliases)
                    (gen/elements prev-aliases)
                    string) ;; avoid throwing when empty
        alias-name (gen/such-that #(and (seq %)
                                        (Character/isLetter (first %))
                                        (not-any? (fn [e] (= % (:value e)))
                                                  prev-aliases))
                                  (gen/resize 20 gen/string-alpha-numeric))
        expr (expression alias-gen)]
    (->> (gen/tuple alias-name expr)
         (gen/fmap (fn [[alias-name expr]]
                     {(with-meta {:type :symbol :value alias-name}
                        {:result (-> expr meta :result)})
                      expr})))))

(defn aliases
  [size]
  (if (zero? size)
    (alias nil)
    (gen/bind (gen/resize (dec size)
                          (gen/sized aliases))
              (fn [alias-map]
                (gen/fmap
                 (fn [generated-alias]
                   (merge alias-map generated-alias))
                 (alias (-> alias-map keys)))))))
