From 6d70176e734ddaa8d7a22bcdeb2a509434e0dc6b Mon Sep 17 00:00:00 2001
From: Nicolas Berger
Date: Fri, 11 Sep 2015 11:42:16 0300
Subject: [PATCH] generators.{[clj cljs] > cljc}

src/main/clojure/clojure/test/check/generators.clj  711 
.../clojure/clojure/test/check/generators.cljc  735 +++++++++++++++++++++
.../clojure/clojure/test/check/generators.cljs  689 
3 files changed, 735 insertions(+), 1400 deletions()
delete mode 100644 src/main/clojure/clojure/test/check/generators.clj
create mode 100644 src/main/clojure/clojure/test/check/generators.cljc
delete mode 100644 src/main/clojure/clojure/test/check/generators.cljs
diff git a/src/main/clojure/clojure/test/check/generators.clj b/src/main/clojure/clojure/test/check/generators.clj
deleted file mode 100644
index 6bb7637..0000000
 a/src/main/clojure/clojure/test/check/generators.clj
+++ /dev/null
@@ 1,711 +0,0 @@
; Copyright (c) Rich Hickey, Reid Draper, and contributors.
; All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse1.0.php)
; which can be found in the file eplv10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.

(ns clojure.test.check.generators
 (:referclojure :exclude [int vector list hashmap map keyword
 char boolean byte bytes sequence
 shuffle notempty symbol namespace])
 (:require [clojure.core :as core]
 [clojure.test.check.random :as random]
 [clojure.test.check.rosetree :as rose]))


;; Gen
;; (internal functions)
;; 

(defrecord Generator [gen])

(defn generator?
 "Test if `x` is a generator. Generators should be treated as opaque values."
 [x]
 (instance? Generator x))

(defn makegen
 [generatorfn]
 (Generator. generatorfn))

(defn callgen
 {:nodoc true}
 [{generatorfn :gen} rnd size]
 (generatorfn rnd size))

(defn genpure
 {:nodoc true}
 [value]
 (makegen
 (fn [rnd size]
 value)))

(defn genfmap
 {:nodoc true}
 [k {h :gen}]
 (makegen
 (fn [rnd size]
 (k (h rnd size)))))

(defn genbind
 {:nodoc true}
 [{h :gen} k]
 (makegen
 (fn [rnd size]
 (let [[r1 r2] (random/split rnd)
 inner (h r1 size)
 {result :gen} (k inner)]
 (result r2 size)))))

(defn lazyrandomstates
 "Given a random number generator, returns an infinite lazy sequence
 of random number generators."
 [rr]
 (lazyseq
 (let [[r1 r2] (random/split rr)]
 (cons r1
 (lazyrandomstates r2)))))

(defn genseq>seqgen
 "Takes a sequence of generators and returns a generator of sequences (er, vectors)."
 [gens]
 (makegen
 (fn [rnd size]
 (mapv #(callgen % %2 size) gens (random/splitn rnd (count gens))))))

;; Exported generator functions
;; 

(defn fmap
 [f gen]
 (assert (generator? gen) "Second arg to fmap must be a generator")
 (genfmap (partial rose/fmap f) gen))


(defn return
 "Create a generator that always returns `value`,
 and never shrinks. You can think of this as
 the `constantly` of generators."
 [value]
 (genpure (rose/pure value)))

(defn bindhelper
 [k]
 (fn [rose]
 (genfmap rose/join
 (makegen
 (fn [rnd size]
 (rose/fmap #(callgen % rnd size)
 (rose/fmap k rose)))))))

(defn bind
 "Create a new generator that passes the result of `gen` into function
 `k`. `k` should return a new generator. This allows you to create new
 generators that depend on the value of other generators. For example,
 to create a generator which first generates a vector of integers, and
 then chooses a random element from that vector:

 (gen/bind (gen/suchthat notempty (gen/vector gen/int))
 ;; this function takes a realized vector,
 ;; and then returns a new generator which
 ;; chooses a random element from it
 gen/elements)

 "
 [generator k]
 (assert (generator? generator) "First arg to bind must be a generator")
 (genbind generator (bindhelper k)))

;; Helpers
;; 

(defn makesizerangeseq
 {:nodoc true}
 [maxsize]
 (cycle (range 0 maxsize)))

(defn sampleseq
 "Return a sequence of realized values from `generator`."
 ([generator] (sampleseq generator 100))
 ([generator maxsize]
 (let [r (random/makerandom)
 sizeseq (makesizerangeseq maxsize)]
 (core/map (comp rose/root #(callgen generator %1 %2))
 (lazyrandomstates r)
 sizeseq))))

(defn sample
 "Return a sequence of `numsamples` (default 10)
 realized values from `generator`."
 ([generator]
 (sample generator 10))
 ([generator numsamples]
 (assert (generator? generator) "First arg to sample must be a generator")
 (take numsamples (sampleseq generator))))


(defn generate
 "Returns a single sample value from the generator, using a default
 size of 30."
 ([generator]
 (generate generator 30))
 ([generator size]
 (let [rng (random/makerandom)]
 (rose/root (callgen generator rng size)))))


;; Internal Helpers
;; 

(defn halfs
 [n]
 (takewhile (partial not= 0) (iterate #(quot % 2) n)))

(defn shrinkint
 [integer]
 (core/map (partial  integer) (halfs integer)))

(defn introsetree
 [value]
 (rose/makerose value (core/map introsetree (shrinkint value))))

;; calclong is factored out to support testing the surprisingly tricky double math. Note:
;; An extreme long value does not have a precisionpreserving representation as a double.
;; Be careful about changing this code unless you understand what's happening in these
;; examples:
;;
;; (= (long ( Integer/MAX_VALUE (double ( Integer/MAX_VALUE 10)))) 10)
;; (= (long ( Long/MAX_VALUE (double ( Long/MAX_VALUE 10)))) 0)

(defn calclong
 [factor lower upper]
 ;; these pre and postconditions are disabled for deployment
 #_ {:pre [(float? factor) (>= factor 0.0) (< factor 1.0)
 (integer? lower) (integer? upper) (<= lower upper)]
 :post [(integer? %)]}
 ;; Use ' on width to maintain accuracy with overflow protection.
 (let [width (' upper lower 1)]
 ;; Preserve long precision if the width is in the long range. Otherwise, we must accept
 ;; less precision because doubles don't have enough bits to preserve long equivalence at
 ;; extreme values.
 (if (< width Long/MAX_VALUE)
 (+ lower (long (Math/floor (* factor width))))
 ;; Clamp down to upper because double math.
 (min upper (long (Math/floor (+ lower (* factor width))))))))

(defn randrange
 [rnd lower upper]
 {:pre [(<= lower upper)]}
 (calclong (random/randdouble rnd) lower upper))

(defn sized
 "Create a generator that depends on the size parameter.
 `sizedgen` is a function that takes an integer and returns
 a generator."
 [sizedgen]
 (makegen
 (fn [rnd size]
 (let [sizedgen (sizedgen size)]
 (callgen sizedgen rnd size)))))

;; Combinators and helpers
;; 

(defn resize
 "Create a new generator with `size` always bound to `n`."
 [n generator]
 (assert (generator? generator) "Second arg to resize must be a generator")
 (let [{:keys [gen]} generator]
 (makegen
 (fn [rnd _size]
 (gen rnd n)))))

(defn scale
 "Create a new generator that modifies the size parameter by the given function. Intended to
 support generators with sizes that need to grow at different rates compared to the normal
 linear scaling."
 ([f generator]
 (sized (fn [n] (resize (f n) generator)))))

(defn choose
 "Create a generator that returns long integers in the range `lower` to `upper`, inclusive."
 [lower upper]
 ;; cast to long to support doubles as arguments per TCHECK73
 (let [lower (long lower)
 upper (long upper)]
 (makegen
 (fn [rnd _size]
 (let [value (randrange rnd lower upper)]
 (rose/filter
 #(and (>= % lower) (<= % upper))
 (introsetree value)))))))

(defn oneof
 "Create a generator that randomly chooses a value from the list of
 provided generators. Shrinks toward choosing an earlier generator,
 as well as shrinking the value generated by the chosen generator.

 Examples:

 (oneof [gen/int gen/boolean (gen/vector gen/int)])

 "
 [generators]
 (assert (every? generator? generators)
 "Arg to oneof must be a collection of generators")
 (bind (choose 0 (dec (count generators)))
 (partial nth generators)))

(defn pick
 [[h & tail] n]
 (let [[chance gen] h]
 (if (<= n chance)
 gen
 (recur tail ( n chance)))))

(defn frequency
 "Create a generator that chooses a generator from `pairs` based on the
 provided likelihoods. The likelihood of a given generator being chosen is
 its likelihood divided by the sum of all likelihoods

 Examples:

 (gen/frequency [[5 gen/int] [3 (gen/vector gen/int)] [2 gen/boolean]])
 "
 [pairs]
 (assert (every? (fn [[x g]] (and (number? x) (generator? g)))
 pairs)
 "Arg to frequency must be a list of [num generator] pairs")
 (let [total (apply + (core/map first pairs))]
 (genbind (choose 1 total)
 #(pick pairs (rose/root %)))))

(defn elements
 "Create a generator that randomly chooses an element from `coll`.

 Examples:

 (gen/elements [:foo :bar :baz])
 "
 [coll]
 (assert (seq coll) "elements cannot be called with an empty collection")
 (let [v (vec coll)]
 (genbind (choose 0 (dec (count v)))
 #(genpure (rose/fmap v %)))))

(defn suchthathelper
 [maxtries pred gen triesleft randseed size]
 (if (zero? triesleft)
 (throw (exinfo (str "Couldn't satisfy suchthat predicate after "
 maxtries " tries.") {}))
 (let [[r1 r2] (random/split randseed)
 value (callgen gen r1 size)]
 (if (pred (rose/root value))
 (rose/filter pred value)
 (recur maxtries pred gen (dec triesleft) r2 (inc size))))))

(defn suchthat
 "Create a generator that generates values from `gen` that satisfy predicate
 `pred`. Care is needed to ensure there is a high chance `gen` will satisfy
 `pred`. By default, `suchthat` will try 10 times to generate a value that
 satisfies the predicate. If no value passes this predicate after this number
 of iterations, a runtime exception will be throw. You can pass an optional
 third argument to change the number of times tried. Note also that each
 time suchthat retries, it will increase the size parameter.

 Examples:

 ;; generate nonempty vectors of integers
 ;; (note, gen/notempty does exactly this)
 (gen/suchthat notempty (gen/vector gen/int))
 "
 ([pred gen]
 (suchthat pred gen 10))
 ([pred gen maxtries]
 (assert (generator? gen) "Second arg to suchthat must be a generator")
 (makegen
 (fn [randseed size]
 (suchthathelper maxtries pred gen maxtries randseed size)))))

(defn notempty
 "Modifies a generator so that it doesn't generate empty collections.

 Examples:

 ;; generate a vector of booleans, but never the empty vector
 (gen/notempty (gen/vector gen/boolean))
 "
 [gen]
 (assert (generator? gen) "Arg to notempty must be a generator")
 (suchthat core/notempty gen))

(defn noshrink
 "Create a new generator that is just like `gen`, except does not shrink
 at all. This can be useful when shrinking is taking a long time or is not
 applicable to the domain."
 [gen]
 (assert (generator? gen) "Arg to noshrink must be a generator")
 (genbind gen
 (fn [[root _children]]
 (genpure
 [root []]))))

(defn shrink2
 "Create a new generator like `gen`, but will consider nodes for shrinking
 even if their parent passes the test (up to one additional level)."
 [gen]
 (assert (generator? gen) "Arg to shrink2 must be a generator")
 (genbind gen (comp genpure rose/collapse)))

(def boolean
 "Generates one of `true` or `false`. Shrinks to `false`."
 (elements [false true]))

(defn tuple
 "Create a generator that returns a vector, whose elements are chosen
 from the generators in the same position. The individual elements shrink
 according to their generator, but the value will never shrink in count.

 Examples:

 (def t (tuple gen/int gen/boolean))
 (sample t)
 ;; => ([1 true] [2 true] [2 false] [1 false] [0 true] [2 false] [6 false]
 ;; => [3 true] [4 false] [9 true]))
 "
 [& generators]
 (assert (every? generator? generators)
 "Args to tuple must be generators")
 (genbind (genseq>seqgen generators)
 (fn [roses]
 (genpure (rose/zip core/vector roses)))))

(def int
 "Generates a positive or negative integer bounded by the generator's
 `size` parameter.
 (Really returns a long)"
 (sized (fn [size] (choose ( size) size))))

(def nat
 "Generates natural numbers, starting at zero. Shrinks to zero."
 (fmap #(Math/abs (long %)) int))

(def posint
 "Generate positive integers bounded by the generator's `size` parameter."
 nat)

(def negint
 "Generate negative integers bounded by the generator's `size` parameter."
 (fmap (partial * 1) nat))

(def sposint
 "Generate strictly positive integers bounded by the generator's `size`
 parameter."
 (fmap inc nat))

(def snegint
 "Generate strictly negative integers bounded by the generator's `size`
 parameter."
 (fmap dec negint))

(defn vector
 "Create a generator whose elements are chosen from `gen`. The count of the
 vector will be bounded by the `size` generator parameter."
 ([generator]
 (assert (generator? generator) "Arg to vector must be a generator")
 (genbind
 (sized #(choose 0 %))
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genpure (rose/shrink core/vector
 roses)))))))
 ([generator numelements]
 (assert (generator? generator) "First arg to vector must be a generator")
 (apply tuple (repeat numelements generator)))
 ([generator minelements maxelements]
 (assert (generator? generator) "First arg to vector must be a generator")
 (genbind
 (choose minelements maxelements)
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genbind
 (genpure (rose/shrink core/vector
 roses))
 (fn [rose]
 (genpure (rose/filter
 (fn [v] (and (>= (count v) minelements)
 (<= (count v) maxelements))) rose))))))))))

(defn list
 "Like `vector`, but generates lists."
 [generator]
 (assert (generator? generator) "First arg to list must be a generator")
 (genbind (sized #(choose 0 %))
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genpure (rose/shrink core/list
 roses)))))))

(defn swap
 [coll [i1 i2]]
 (assoc coll i2 (coll i1) i1 (coll i2)))

(defn
 ^{:added "0.6.0"}
 shuffle
 "Create a generator that generates random permutations of `coll`. Shrinks
 toward the original collection: `coll`. `coll` will be turned into a vector,
 if it's not already."
 [coll]
 (let [indexgen (choose 0 (dec (count coll)))]
 (fmap (partial reduce swap (vec coll))
 ;; a vector of swap instructions, with count between
 ;; zero and 2 * count. This means that the average number
 ;; of instructions is count, which should provide sufficient
 ;; (though perhaps not 'perfect') shuffling. This still gives us
 ;; nice, relatively quick shrinks.
 (vector (tuple indexgen indexgen) 0 (* 2 (count coll))))))

(def byte
 "Generates `java.lang.Byte`s, using the full byterange."
 (fmap core/byte (choose Byte/MIN_VALUE Byte/MAX_VALUE)))

(def bytes
 "Generates bytearrays."
 (fmap core/bytearray (vector byte)))

(defn map
 "Create a generator that generates maps, with keys chosen from
 `keygen` and values chosen from `valgen`."
 [keygen valgen]
 (let [input (vector (tuple keygen valgen))]
 (fmap (partial into {}) input)))

(defn hashmap
 "Like clojure.core/hashmap, except the values are generators.
 Returns a generator that makes maps with the supplied keys and
 values generated using the supplied generators.

 Examples:

 (gen/hashmap :a gen/boolean :b gen/nat)
 "
 [& kvs]
 (assert (even? (count kvs)))
 (let [ks (takenth 2 kvs)
 vs (takenth 2 (rest kvs))]
 (assert (every? generator? vs)
 "Value args to hashmap must be generators")
 (fmap (partial zipmap ks)
 (apply tuple vs))))

(def char
 "Generates character from 0255."
 (fmap core/char (choose 0 255)))

(def charascii
 "Generate only ascii character."
 (fmap core/char (choose 32 126)))

(def charalphanumeric
 "Generate alphanumeric characters."
 (fmap core/char
 (oneof [(choose 48 57)
 (choose 65 90)
 (choose 97 122)])))

(def ^{:deprecated "0.6.0"}
 charalphanumeric
 "Deprecated  use charalphanumeric instead.

 Generate alphanumeric characters."
 charalphanumeric)

(def charalpha
 "Generate alpha characters."
 (fmap core/char
 (oneof [(choose 65 90)
 (choose 97 122)])))

(def ^{:private true} charsymbolspecial
 "Generate nonalphanumeric characters that can be in a symbol."
 (elements [\* \+ \! \ \_ \?]))

(def ^{:private true} charkeywordrest
 "Generate characters that can be the char following first of a keyword."
 (frequency [[2 charalphanumeric]
 [1 charsymbolspecial]]))

(def ^{:private true} charkeywordfirst
 "Generate characters that can be the first char of a keyword."
 (frequency [[2 charalpha]
 [1 charsymbolspecial]]))

(def string
 "Generate strings. May generate unprintable characters."
 (fmap clojure.string/join (vector char)))

(def stringascii
 "Generate ascii strings."
 (fmap clojure.string/join (vector charascii)))

(def stringalphanumeric
 "Generate alphanumeric strings."
 (fmap clojure.string/join (vector charalphanumeric)))

(def ^{:deprecated "0.6.0"}
 stringalphanumeric
 "Deprecated  use stringalphanumeric instead.

 Generate alphanumeric strings."
 stringalphanumeric)

(defn +ordigit?
 "Returns true if c is \\+ or \\ and d is nonnil and a digit.

 Symbols that start with +3 or 2 are not readable because they look
 like numbers."
 [c ^Character d]
 (core/boolean (and d
 (or (= \+ c)
 (= \ c))
 (Character/isDigit d))))

(def ^{:private true} namespacesegment
 "Generate the segment of a namespace."
 (>> (tuple charkeywordfirst (vector charkeywordrest))
 (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def ^{:private true} namespace
 "Generate a namespace (or nil for no namespace)."
 (>> (vector namespacesegment)
 (fmap (fn [v] (when (seq v)
 (clojure.string/join "." v))))))

(def ^{:private true} keywordsegmentrest
 "Generate segments of a keyword (between \\:)"
 (>> (tuple charkeywordrest (vector charkeywordrest))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def ^{:private true} keywordsegmentfirst
 "Generate segments of a keyword that can be first (between \\:)"
 (>> (tuple charkeywordfirst (vector charkeywordrest))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def keyword
 "Generate keywords without namespaces."
 (>> (tuple keywordsegmentfirst (vector keywordsegmentrest))
 (fmap (fn [[c cs]]
 (core/keyword (clojure.string/join ":" (cons c cs)))))))

(def
 ^{:added "0.5.9"}
 keywordns
 "Generate keywords with optional namespaces."
 (>> (tuple namespace charkeywordfirst (vector charkeywordrest))
 (fmap (fn [[ns c cs]]
 (core/keyword ns (clojure.string/join (cons c cs)))))))

(def ^{:private true} charsymbolfirst
 (frequency [[10 charalpha]
 [5 charsymbolspecial]
 [1 (return \.)]]))

(def ^{:private true} charsymbolrest
 (frequency [[10 charalphanumeric]
 [5 charsymbolspecial]
 [1 (return \.)]]))

(def symbol
 "Generate symbols without namespaces."
 (frequency [[100 (>> (tuple charsymbolfirst (vector charsymbolrest))
 (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[c cs]] (core/symbol (clojure.string/join (cons c cs))))))]
 [1 (return '/)]]))

(def
 ^{:added "0.5.9"}
 symbolns
 "Generate symbols with optional namespaces."
 (frequency [[100 (>> (tuple namespace charsymbolfirst (vector charsymbolrest))
 (suchthat (fn [[_ c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[ns c cs]] (core/symbol ns (clojure.string/join (cons c cs))))))]
 [1 (return '/)]]))

(def ratio
 "Generates a `clojure.lang.Ratio`. Shrinks toward 0. Not all values generated
 will be ratios, as many values returned by `/` are not ratios."
 (fmap
 (fn [[a b]] (/ a b))
 (tuple int
 (suchthat (complement zero?) int))))

(def simpletype
 (oneof [int char string ratio boolean keyword keywordns symbol symbolns]))

(def simpletypeprintable
 (oneof [int charascii stringascii ratio boolean keyword keywordns symbol symbolns]))

(defn containertype
 [innertype]
 (oneof [(vector innertype)
 (list innertype)
 (map innertype innertype)]))

(defn recursivehelper
 [containergenfn scalargen scalarsize childrensize height]
 (if (zero? height)
 (resize scalarsize scalargen)
 (resize childrensize
 (containergenfn
 (recursivehelper
 containergenfn scalargen
 scalarsize childrensize (dec height))))))

(defn
 ^{:added "0.5.9"}
 recursivegen
 "This is a helper for writing recursive (treeshaped) generators. The first
 argument should be a function that takes a generator as an argument, and
 produces another generator that 'contains' that generator. The vector function
 in this namespace is a simple example. The second argument is a scalar
 generator, like boolean. For example, to produce a tree of booleans:

 (gen/recursivegen gen/vector gen/boolean)

 Vectors or maps either recurring or containing booleans or integers:

 (gen/recursivegen (fn [inner] (gen/oneof [(gen/vector inner)
 (gen/map inner inner)]))
 (gen/oneof [gen/boolean gen/int]))
 "
 [containergenfn scalargen]
 (assert (generator? scalargen)
 "Second arg to recursivegen must be a generator")
 (sized (fn [size]
 (bind (choose 1 5)
 (fn [height] (let [childrensize (Math/pow size (/ 1 height))]
 (recursivehelper containergenfn scalargen size
 childrensize height)))))))

(def any
 "A recursive generator that will generate many different, often nested, values"
 (recursivegen containertype simpletype))

(def anyprintable
 "Like any, but avoids characters that the shell will interpret as actions,
 like 7 and 14 (bell and alternate character set command)"
 (recursivegen containertype simpletypeprintable))
diff git a/src/main/clojure/clojure/test/check/generators.cljc b/src/main/clojure/clojure/test/check/generators.cljc
new file mode 100644
index 0000000..0d6b94c
 /dev/null
+++ b/src/main/clojure/clojure/test/check/generators.cljc
@@ 0,0 +1,735 @@
+; Copyright (c) Rich Hickey, Reid Draper, and contributors.
+; All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse1.0.php)
+; which can be found in the file eplv10.html at the root of this distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(ns clojure.test.check.generators
+ (:referclojure :exclude [int vector list hashmap map keyword
+ char boolean byte bytes sequence
+ shuffle notempty symbol namespace])
+ (:require [#?(:clj clojure.core :cljs cljs.core) :as core]
+ [clojure.test.check.random :as random]
+ [clojure.test.check.rosetree :as rose]
+ #?@(:cljs [[goog.string :as gstring]
+ [clojure.string]])))
+
+
+;; Gen
+;; (internal functions)
+;; 
+
+(defrecord Generator [gen])
+
+(defn generator?
+ "Test if `x` is a generator. Generators should be treated as opaque values."
+ [x]
+ (instance? Generator x))
+
+(defn makegen
+ [generatorfn]
+ (Generator. generatorfn))
+
+(defn callgen
+ {:nodoc true}
+ [{generatorfn :gen} rnd size]
+ (generatorfn rnd size))
+
+(defn genpure
+ {:nodoc true}
+ [value]
+ (makegen
+ (fn [rnd size]
+ value)))
+
+(defn genfmap
+ {:nodoc true}
+ [k {h :gen}]
+ (makegen
+ (fn [rnd size]
+ (k (h rnd size)))))
+
+(defn genbind
+ {:nodoc true}
+ [{h :gen} k]
+ (makegen
+ (fn [rnd size]
+ (let [[r1 r2] (random/split rnd)
+ inner (h r1 size)
+ {result :gen} (k inner)]
+ (result r2 size)))))
+
+(defn lazyrandomstates
+ "Given a random number generator, returns an infinite lazy sequence
+ of random number generators."
+ [rr]
+ (lazyseq
+ (let [[r1 r2] (random/split rr)]
+ (cons r1
+ (lazyrandomstates r2)))))
+
+(defn genseq>seqgen
+ "Takes a sequence of generators and returns a generator of sequences (er, vectors)."
+ [gens]
+ (makegen
+ (fn [rnd size]
+ (mapv #(callgen % %2 size) gens (random/splitn rnd (count gens))))))
+
+;; Exported generator functions
+;; 
+
+(defn fmap
+ [f gen]
+ (assert (generator? gen) "Second arg to fmap must be a generator")
+ (genfmap (partial rose/fmap f) gen))
+
+
+(defn return
+ "Create a generator that always returns `value`,
+ and never shrinks. You can think of this as
+ the `constantly` of generators."
+ [value]
+ (genpure (rose/pure value)))
+
+(defn bindhelper
+ [k]
+ (fn [rose]
+ (genfmap rose/join
+ (makegen
+ (fn [rnd size]
+ (rose/fmap #(callgen % rnd size)
+ (rose/fmap k rose)))))))
+
+(defn bind
+ "Create a new generator that passes the result of `gen` into function
+ `k`. `k` should return a new generator. This allows you to create new
+ generators that depend on the value of other generators. For example,
+ to create a generator which first generates a vector of integers, and
+ then chooses a random element from that vector:
+
+ (gen/bind (gen/suchthat notempty (gen/vector gen/int))
+ ;; this function takes a realized vector,
+ ;; and then returns a new generator which
+ ;; chooses a random element from it
+ gen/elements)
+
+ "
+ [generator k]
+ (assert (generator? generator) "First arg to bind must be a generator")
+ (genbind generator (bindhelper k)))
+
+;; Helpers
+;; 
+
+(defn makesizerangeseq
+ {:nodoc true}
+ [maxsize]
+ (cycle (range 0 maxsize)))
+
+(defn sampleseq
+ "Return a sequence of realized values from `generator`."
+ ([generator] (sampleseq generator 100))
+ ([generator maxsize]
+ (let [r (random/makerandom)
+ sizeseq (makesizerangeseq maxsize)]
+ (core/map (comp rose/root #(callgen generator %1 %2))
+ (lazyrandomstates r)
+ sizeseq))))
+
+(defn sample
+ "Return a sequence of `numsamples` (default 10)
+ realized values from `generator`."
+ ([generator]
+ (sample generator 10))
+ ([generator numsamples]
+ (assert (generator? generator) "First arg to sample must be a generator")
+ (take numsamples (sampleseq generator))))
+
+
+(defn generate
+ "Returns a single sample value from the generator, using a default
+ size of 30."
+ ([generator]
+ (generate generator 30))
+ ([generator size]
+ (let [rng (random/makerandom)]
+ (rose/root (callgen generator rng size)))))
+
+
+;; Internal Helpers
+;; 
+
+(defn halfs
+ [n]
+ (takewhile (partial not= 0) (iterate #(quot % 2) n)))
+
+(defn shrinkint
+ [integer]
+ (core/map (partial  integer) (halfs integer)))
+
+(defn introsetree
+ [value]
+ (rose/makerose value (core/map introsetree (shrinkint value))))
+
+;; calclong is factored out to support testing the surprisingly tricky double math. Note:
+;; An extreme long value does not have a precisionpreserving representation as a double.
+;; Be careful about changing this code unless you understand what's happening in these
+;; examples:
+;;
+;; (= (long ( Integer/MAX_VALUE (double ( Integer/MAX_VALUE 10)))) 10)
+;; (= (long ( Long/MAX_VALUE (double ( Long/MAX_VALUE 10)))) 0)
+
+(defn calclong
+ [factor lower upper]
+ ;; these pre and postconditions are disabled for deployment
+ #_ {:pre [(float? factor) (>= factor 0.0) (< factor 1.0)
+ (integer? lower) (integer? upper) (<= lower upper)]
+ :post [(integer? %)]}
+ ;; Use ' on width to maintain accuracy with overflow protection.
+ #?(:clj
+ (let [width (' upper lower 1)]
+ ;; Preserve long precision if the width is in the long range. Otherwise, we must accept
+ ;; less precision because doubles don't have enough bits to preserve long equivalence at
+ ;; extreme values.
+ (if (< width Long/MAX_VALUE)
+ (+ lower (long (Math/floor (* factor width))))
+ ;; Clamp down to upper because double math.
+ (min upper (long (Math/floor (+ lower (* factor width)))))))
+
+ :cljs
+ (long (Math/floor (+ lower ( (* factor (+ 1.0 upper))
+ (* factor lower)))))))
+
+(defn randrange
+ [rnd lower upper]
+ {:pre [(<= lower upper)]}
+ (calclong (random/randdouble rnd) lower upper))
+
+(defn sized
+ "Create a generator that depends on the size parameter.
+ `sizedgen` is a function that takes an integer and returns
+ a generator."
+ [sizedgen]
+ (makegen
+ (fn [rnd size]
+ (let [sizedgen (sizedgen size)]
+ (callgen sizedgen rnd size)))))
+
+;; Combinators and helpers
+;; 
+
+(defn resize
+ "Create a new generator with `size` always bound to `n`."
+ [n generator]
+ (assert (generator? generator) "Second arg to resize must be a generator")
+ (let [{:keys [gen]} generator]
+ (makegen
+ (fn [rnd _size]
+ (gen rnd n)))))
+
+(defn scale
+ "Create a new generator that modifies the size parameter by the given function. Intended to
+ support generators with sizes that need to grow at different rates compared to the normal
+ linear scaling."
+ ([f generator]
+ (sized (fn [n] (resize (f n) generator)))))
+
+(defn choose
+ #?(:clj
+ "Create a generator that returns long integers in the range `lower` to `upper`, inclusive."
+
+ :cljs
+ "Create a generator that returns numbers in the range
+ `lower` to `upper`, inclusive.")
+ [lower upper]
+ ;; cast to long to support doubles as arguments per TCHECK73
+ (let #?(:clj
+ [lower (long lower)
+ upper (long upper)]
+
+ :cljs ;; does nothing, no long in cljs
+ [])
+ (makegen
+ (fn [rnd _size]
+ (let [value (randrange rnd lower upper)]
+ (rose/filter
+ #(and (>= % lower) (<= % upper))
+ (introsetree value)))))))
+
+(defn oneof
+ "Create a generator that randomly chooses a value from the list of
+ provided generators. Shrinks toward choosing an earlier generator,
+ as well as shrinking the value generated by the chosen generator.
+
+ Examples:
+
+ (oneof [gen/int gen/boolean (gen/vector gen/int)])
+
+ "
+ [generators]
+ (assert (every? generator? generators)
+ "Arg to oneof must be a collection of generators")
+ (bind (choose 0 (dec (count generators)))
+ (partial nth generators)))
+
+(defn pick
+ [[h & tail] n]
+ (let [[chance gen] h]
+ (if (<= n chance)
+ gen
+ (recur tail ( n chance)))))
+
+(defn frequency
+ "Create a generator that chooses a generator from `pairs` based on the
+ provided likelihoods. The likelihood of a given generator being chosen is
+ its likelihood divided by the sum of all likelihoods
+
+ Examples:
+
+ (gen/frequency [[5 gen/int] [3 (gen/vector gen/int)] [2 gen/boolean]])
+ "
+ [pairs]
+ (assert (every? (fn [[x g]] (and (number? x) (generator? g)))
+ pairs)
+ "Arg to frequency must be a list of [num generator] pairs")
+ (let [total (apply + (core/map first pairs))]
+ (genbind (choose 1 total)
+ #(pick pairs (rose/root %)))))
+
+(defn elements
+ "Create a generator that randomly chooses an element from `coll`.
+
+ Examples:
+
+ (gen/elements [:foo :bar :baz])
+ "
+ [coll]
+ (assert (seq coll) "elements cannot be called with an empty collection")
+ (let [v (vec coll)]
+ (genbind (choose 0 (dec (count v)))
+ #(genpure (rose/fmap v %)))))
+
+(defn suchthathelper
+ [maxtries pred gen triesleft randseed size]
+ (if (zero? triesleft)
+ (throw (exinfo (str "Couldn't satisfy suchthat predicate after "
+ maxtries " tries.") {}))
+ (let [[r1 r2] (random/split randseed)
+ value (callgen gen r1 size)]
+ (if (pred (rose/root value))
+ (rose/filter pred value)
+ (recur maxtries pred gen (dec triesleft) r2 (inc size))))))
+
+(defn suchthat
+ "Create a generator that generates values from `gen` that satisfy predicate
+ `pred`. Care is needed to ensure there is a high chance `gen` will satisfy
+ `pred`. By default, `suchthat` will try 10 times to generate a value that
+ satisfies the predicate. If no value passes this predicate after this number
+ of iterations, a runtime exception will be throw. You can pass an optional
+ third argument to change the number of times tried. Note also that each
+ time suchthat retries, it will increase the size parameter.
+
+ Examples:
+
+ ;; generate nonempty vectors of integers
+ ;; (note, gen/notempty does exactly this)
+ (gen/suchthat notempty (gen/vector gen/int))
+ "
+ ([pred gen]
+ (suchthat pred gen 10))
+ ([pred gen maxtries]
+ (assert (generator? gen) "Second arg to suchthat must be a generator")
+ (makegen
+ (fn [randseed size]
+ (suchthathelper maxtries pred gen maxtries randseed size)))))
+
+(defn notempty
+ "Modifies a generator so that it doesn't generate empty collections.
+
+ Examples:
+
+ ;; generate a vector of booleans, but never the empty vector
+ (gen/notempty (gen/vector gen/boolean))
+ "
+ [gen]
+ (assert (generator? gen) "Arg to notempty must be a generator")
+ (suchthat core/notempty gen))
+
+(defn noshrink
+ "Create a new generator that is just like `gen`, except does not shrink
+ at all. This can be useful when shrinking is taking a long time or is not
+ applicable to the domain."
+ [gen]
+ (assert (generator? gen) "Arg to noshrink must be a generator")
+ (genbind gen
+ (fn [rose]
+ (genpure (rose/makerose (rose/root rose) [])))))
+
+(defn shrink2
+ "Create a new generator like `gen`, but will consider nodes for shrinking
+ even if their parent passes the test (up to one additional level)."
+ [gen]
+ (assert (generator? gen) "Arg to shrink2 must be a generator")
+ (genbind gen (comp genpure rose/collapse)))
+
+(def boolean
+ "Generates one of `true` or `false`. Shrinks to `false`."
+ (elements [false true]))
+
+(defn tuple
+ "Create a generator that returns a vector, whose elements are chosen
+ from the generators in the same position. The individual elements shrink
+ according to their generator, but the value will never shrink in count.
+
+ Examples:
+
+ (def t (tuple gen/int gen/boolean))
+ (sample t)
+ ;; => ([1 true] [2 true] [2 false] [1 false] [0 true] [2 false] [6 false]
+ ;; => [3 true] [4 false] [9 true]))
+ "
+ [& generators]
+ (assert (every? generator? generators)
+ "Args to tuple must be generators")
+ (genbind (genseq>seqgen generators)
+ (fn [roses]
+ (genpure (rose/zip core/vector roses)))))
+
+(def int
+ "Generates a positive or negative integer bounded by the generator's
+ `size` parameter.
+ (Really returns a long)"
+ (sized (fn [size] (choose ( size) size))))
+
+(def nat
+ "Generates natural numbers, starting at zero. Shrinks to zero."
+ (fmap #(Math/abs (long %)) int))
+
+(def posint
+ "Generate positive integers bounded by the generator's `size` parameter."
+ nat)
+
+(def negint
+ "Generate negative integers bounded by the generator's `size` parameter."
+ (fmap (partial * 1) nat))
+
+(def sposint
+ "Generate strictly positive integers bounded by the generator's `size`
+ parameter."
+ (fmap inc nat))
+
+(def snegint
+ "Generate strictly negative integers bounded by the generator's `size`
+ parameter."
+ (fmap dec negint))
+
+(defn vector
+ "Create a generator whose elements are chosen from `gen`. The count of the
+ vector will be bounded by the `size` generator parameter."
+ ([generator]
+ (assert (generator? generator) "Arg to vector must be a generator")
+ (genbind
+ (sized #(choose 0 %))
+ (fn [numelementsrose]
+ (genbind (genseq>seqgen
+ (repeat (rose/root numelementsrose)
+ generator))
+ (fn [roses]
+ (genpure (rose/shrink core/vector
+ roses)))))))
+ ([generator numelements]
+ (assert (generator? generator) "First arg to vector must be a generator")
+ (apply tuple (repeat numelements generator)))
+ ([generator minelements maxelements]
+ (assert (generator? generator) "First arg to vector must be a generator")
+ (genbind
+ (choose minelements maxelements)
+ (fn [numelementsrose]
+ (genbind (genseq>seqgen
+ (repeat (rose/root numelementsrose)
+ generator))
+ (fn [roses]
+ (genbind
+ (genpure (rose/shrink core/vector
+ roses))
+ (fn [rose]
+ (genpure (rose/filter
+ (fn [v] (and (>= (count v) minelements)
+ (<= (count v) maxelements))) rose))))))))))
+
+(defn list
+ "Like `vector`, but generates lists."
+ [generator]
+ (assert (generator? generator) "First arg to list must be a generator")
+ (genbind (sized #(choose 0 %))
+ (fn [numelementsrose]
+ (genbind (genseq>seqgen
+ (repeat (rose/root numelementsrose)
+ generator))
+ (fn [roses]
+ (genpure (rose/shrink core/list
+ roses)))))))
+
+(defn swap
+ [coll [i1 i2]]
+ (assoc coll i2 (coll i1) i1 (coll i2)))
+
+(defn
+ ^{:added "0.6.0"}
+ shuffle
+ "Create a generator that generates random permutations of `coll`. Shrinks
+ toward the original collection: `coll`. `coll` will be turned into a vector,
+ if it's not already."
+ [coll]
+ (let [indexgen (choose 0 (dec (count coll)))]
+ (fmap (partial reduce swap (vec coll))
+ ;; a vector of swap instructions, with count between
+ ;; zero and 2 * count. This means that the average number
+ ;; of instructions is count, which should provide sufficient
+ ;; (though perhaps not 'perfect') shuffling. This still gives us
+ ;; nice, relatively quick shrinks.
+ (vector (tuple indexgen indexgen) 0 (* 2 (count coll))))))
+
+;; NOTE cljs: Comment out for now  David
+
+#?(:clj
+ (def byte
+ "Generates `java.lang.Byte`s, using the full byterange."
+ (fmap core/byte (choose Byte/MIN_VALUE Byte/MAX_VALUE))))
+
+#?(:clj
+ (def bytes
+ "Generates bytearrays."
+ (fmap core/bytearray (vector byte))))
+
+(defn map
+ "Create a generator that generates maps, with keys chosen from
+ `keygen` and values chosen from `valgen`."
+ [keygen valgen]
+ (let [input (vector (tuple keygen valgen))]
+ (fmap (partial into {}) input)))
+
+(defn hashmap
+ "Like clojure.core/hashmap, except the values are generators.
+ Returns a generator that makes maps with the supplied keys and
+ values generated using the supplied generators.
+
+ Examples:
+
+ (gen/hashmap :a gen/boolean :b gen/nat)
+ "
+ [& kvs]
+ (assert (even? (count kvs)))
+ (let [ks (takenth 2 kvs)
+ vs (takenth 2 (rest kvs))]
+ (assert (every? generator? vs)
+ "Value args to hashmap must be generators")
+ (fmap (partial zipmap ks)
+ (apply tuple vs))))
+
+(def char
+ "Generates character from 0255."
+ (fmap core/char (choose 0 255)))
+
+(def charascii
+ "Generate only ascii character."
+ (fmap core/char (choose 32 126)))
+
+(def charalphanumeric
+ "Generate alphanumeric characters."
+ (fmap core/char
+ (oneof [(choose 48 57)
+ (choose 65 90)
+ (choose 97 122)])))
+
+(def ^{:deprecated "0.6.0"}
+ charalphanumeric
+ "Deprecated  use charalphanumeric instead.
+
+ Generate alphanumeric characters."
+ charalphanumeric)
+
+(def charalpha
+ "Generate alpha characters."
+ (fmap core/char
+ (oneof [(choose 65 90)
+ (choose 97 122)])))
+
+(def ^{:private true} charsymbolspecial
+ "Generate nonalphanumeric characters that can be in a symbol."
+ (elements [\* \+ \! \ \_ \?]))
+
+(def ^{:private true} charkeywordrest
+ "Generate characters that can be the char following first of a keyword."
+ (frequency [[2 charalphanumeric]
+ [1 charsymbolspecial]]))
+
+(def ^{:private true} charkeywordfirst
+ "Generate characters that can be the first char of a keyword."
+ (frequency [[2 charalpha]
+ [1 charsymbolspecial]]))
+
+(def string
+ "Generate strings. May generate unprintable characters."
+ (fmap clojure.string/join (vector char)))
+
+(def stringascii
+ "Generate ascii strings."
+ (fmap clojure.string/join (vector charascii)))
+
+(def stringalphanumeric
+ "Generate alphanumeric strings."
+ (fmap clojure.string/join (vector charalphanumeric)))
+
+(def ^{:deprecated "0.6.0"}
+ stringalphanumeric
+ "Deprecated  use stringalphanumeric instead.
+
+ Generate alphanumeric strings."
+ stringalphanumeric)
+
+(defn digit?
+ [d]
+ #?(:clj (Character/isDigit ^Character d)
+ :cljs (gstring/isNumeric d)))
+
+(defn +ordigit?
+ "Returns true if c is \\+ or \\ and d is nonnil and a digit.
+
+ Symbols that start with +3 or 2 are not readable because they look
+ like numbers."
+ [c d]
+ (core/boolean (and d
+ (or (#?(:clj = :cljs identical?) \+ c)
+ (#?(:clj = :cljs identical?) \ c))
+ (digit? d))))
+
+(def ^{:private true} namespacesegment
+ "Generate the segment of a namespace."
+ (>> (tuple charkeywordfirst (vector charkeywordrest))
+ (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
+ (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))
+
+(def ^{:private true} namespace
+ "Generate a namespace (or nil for no namespace)."
+ (>> (vector namespacesegment)
+ (fmap (fn [v] (when (seq v)
+ (clojure.string/join "." v))))))
+
+(def ^{:private true} keywordsegmentrest
+ "Generate segments of a keyword (between \\:)"
+ (>> (tuple charkeywordrest (vector charkeywordrest))
+ (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))
+
+(def ^{:private true} keywordsegmentfirst
+ "Generate segments of a keyword that can be first (between \\:)"
+ (>> (tuple charkeywordfirst (vector charkeywordrest))
+ (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))
+
+(def keyword
+ "Generate keywords without namespaces."
+ (>> (tuple keywordsegmentfirst (vector keywordsegmentrest))
+ (fmap (fn [[c cs]]
+ (core/keyword (clojure.string/join ":" (cons c cs)))))))
+
+(def
+ ^{:added "0.5.9"}
+ keywordns
+ "Generate keywords with optional namespaces."
+ (>> (tuple namespace charkeywordfirst (vector charkeywordrest))
+ (fmap (fn [[ns c cs]]
+ (core/keyword ns (clojure.string/join (cons c cs)))))))
+
+(def ^{:private true} charsymbolfirst
+ (frequency [[10 charalpha]
+ [5 charsymbolspecial]
+ [1 (return \.)]]))
+
+(def ^{:private true} charsymbolrest
+ (frequency [[10 charalphanumeric]
+ [5 charsymbolspecial]
+ [1 (return \.)]]))
+
+(def symbol
+ "Generate symbols without namespaces."
+ (frequency [[100 (>> (tuple charsymbolfirst (vector charsymbolrest))
+ (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
+ (fmap (fn [[c cs]] (core/symbol (clojure.string/join (cons c cs))))))]
+ [1 (return '/)]]))
+
+(def
+ ^{:added "0.5.9"}
+ symbolns
+ "Generate symbols with optional namespaces."
+ (frequency [[100 (>> (tuple namespace charsymbolfirst (vector charsymbolrest))
+ (suchthat (fn [[_ c [d]]] (not (+ordigit? c d))))
+ (fmap (fn [[ns c cs]] (core/symbol ns (clojure.string/join (cons c cs))))))]
+ [1 (return '/)]]))
+
+(def ratio
+ "Generates a `clojure.lang.Ratio`. Shrinks toward 0. Not all values generated
+ will be ratios, as many values returned by `/` are not ratios."
+ (fmap
+ (fn [[a b]] (/ a b))
+ (tuple int
+ (suchthat (complement zero?) int))))
+
+(def simpletype
+ (oneof [int char string ratio boolean keyword keywordns symbol symbolns]))
+
+(def simpletypeprintable
+ (oneof [int charascii stringascii ratio boolean keyword keywordns symbol symbolns]))
+
+(defn containertype
+ [innertype]
+ (oneof [(vector innertype)
+ (list innertype)
+ (map innertype innertype)]))
+
+(defn recursivehelper
+ [containergenfn scalargen scalarsize childrensize height]
+ (if (zero? height)
+ (resize scalarsize scalargen)
+ (resize childrensize
+ (containergenfn
+ (recursivehelper
+ containergenfn scalargen
+ scalarsize childrensize (dec height))))))
+
+(defn
+ ^{:added "0.5.9"}
+ recursivegen
+ "This is a helper for writing recursive (treeshaped) generators. The first
+ argument should be a function that takes a generator as an argument, and
+ produces another generator that 'contains' that generator. The vector function
+ in this namespace is a simple example. The second argument is a scalar
+ generator, like boolean. For example, to produce a tree of booleans:
+
+ (gen/recursivegen gen/vector gen/boolean)
+
+ Vectors or maps either recurring or containing booleans or integers:
+
+ (gen/recursivegen (fn [inner] (gen/oneof [(gen/vector inner)
+ (gen/map inner inner)]))
+ (gen/oneof [gen/boolean gen/int]))
+ "
+ [containergenfn scalargen]
+ (assert (generator? scalargen)
+ "Second arg to recursivegen must be a generator")
+ (sized (fn [size]
+ (bind (choose 1 5)
+ (fn [height] (let [childrensize (Math/pow size (/ 1 height))]
+ (recursivehelper containergenfn scalargen size
+ childrensize height)))))))
+
+(def any
+ "A recursive generator that will generate many different, often nested, values"
+ (recursivegen containertype simpletype))
+
+(def anyprintable
+ "Like any, but avoids characters that the shell will interpret as actions,
+ like 7 and 14 (bell and alternate character set command)"
+ (recursivegen containertype simpletypeprintable))
diff git a/src/main/clojure/clojure/test/check/generators.cljs b/src/main/clojure/clojure/test/check/generators.cljs
deleted file mode 100644
index f6b7a0b..0000000
 a/src/main/clojure/clojure/test/check/generators.cljs
+++ /dev/null
@@ 1,689 +0,0 @@
; Copyright (c) Rich Hickey, Reid Draper, and contributors.
; All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse1.0.php)
; which can be found in the file eplv10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.

(ns clojure.test.check.generators
 (:referclojure :exclude [int vector list hashmap map keyword
 char boolean byte bytes sequence
 shuffle notempty symbol namespace])
 (:require [cljs.core :as core]
 [clojure.test.check.random :as random]
 [clojure.test.check.rosetree :as rose]
 [goog.string :as gstring]
 [clojure.string]))


;; Gen
;; (internal functions)
;; 

(defrecord Generator [gen])

(defn generator?
 "Test if `x` is a generator. Generators should be treated as opaque values."
 [x]
 (instance? Generator x))

(defn makegen
 [generatorfn]
 (Generator. generatorfn))

(defn callgen
 {:nodoc true}
 [{generatorfn :gen} rnd size]
 (generatorfn rnd size))

(defn genpure
 {:nodoc true}
 [value]
 (makegen
 (fn [rnd size]
 value)))

(defn genfmap
 {:nodoc true}
 [k {h :gen}]
 (makegen
 (fn [rnd size]
 (k (h rnd size)))))

(defn genbind
 {:nodoc true}
 [{h :gen} k]
 (makegen
 (fn [rnd size]
 (let [[r1 r2] (random/split rnd)
 inner (h r1 size)
 {result :gen} (k inner)]
 (result r2 size)))))

(defn lazyrandomstates
 "Given a random number generator, returns an infinite lazy sequence
 of random number generators."
 [rr]
 (lazyseq
 (let [[r1 r2] (random/split rr)]
 (cons r1
 (lazyrandomstates r2)))))

(defn genseq>seqgen
 "Takes a sequence of generators and returns a generator of sequences (er, vectors)."
 [gens]
 (makegen
 (fn [rnd size]
 (mapv #(callgen % %2 size) gens (random/splitn rnd (count gens))))))

;; Exported generator functions
;; 

(defn fmap
 [f gen]
 (assert (generator? gen) "Second arg to fmap must be a generator")
 (genfmap #(rose/fmap f %) gen))


(defn return
 "Create a generator that always returns `value`,
 and never shrinks. You can think of this as
 the `constantly` of generators."
 [value]
 (genpure (rose/pure value)))

(defn bindhelper
 [k]
 (fn [rose]
 (genfmap rose/join
 (makegen
 (fn [rnd size]
 (rose/fmap #(callgen % rnd size)
 (rose/fmap k rose)))))))

(defn bind
 "Create a new generator that passes the result of `gen` into function
 `k`. `k` should return a new generator. This allows you to create new
 generators that depend on the value of other generators. For example,
 to create a generator which first generates a vector of integers, and
 then chooses a random element from that vector:

 (gen/bind (gen/suchthat notempty (gen/vector gen/int))
 ;; this function takes a realized vector,
 ;; and then returns a new generator which
 ;; chooses a random element from it
 gen/elements)

 "
 [generator k]
 (assert (generator? generator) "First arg to bind must be a generator")
 (genbind generator (bindhelper k)))

;; Helpers
;; 

(defn makesizerangeseq
 {:nodoc true}
 [maxsize]
 (cycle (range 0 maxsize)))

(defn sampleseq
 "Return a sequence of realized values from `generator`."
 ([generator] (sampleseq generator 100))
 ([generator maxsize]
 (let [r (random/makerandom)
 sizeseq (makesizerangeseq maxsize)]
 (core/map #(rose/root (callgen generator %1 %2))
 (lazyrandomstates r)
 sizeseq))))

(defn sample
 "Return a sequence of `numsamples` (default 10)
 realized values from `generator`."
 ([generator]
 (sample generator 10))
 ([generator numsamples]
 (assert (generator? generator) "First arg to sample must be a generator")
 (take numsamples (sampleseq generator))))


(defn generate
 "Returns a single sample value from the generator, using a default
 size of 30."
 ([generator]
 (generate generator 30))
 ([generator size]
 (let [rng (random/makerandom)]
 (rose/root (callgen generator rng size)))))

;; Internal Helpers
;; 

(defn halfs
 [n]
 (takewhile #(not= 0 %) (iterate #(quot % 2) n)))

(defn shrinkint
 [integer]
 (core/map #( integer %) (halfs integer)))

(defn introsetree
 [value]
 (rose/makerose value (core/map introsetree (shrinkint value))))

(defn randrange
 [rnd lower upper]
 {:pre [(<= lower upper)]}
 (let [factor (random/randdouble rnd)]
 (long (Math/floor (+ lower ( (* factor (+ 1.0 upper))
 (* factor lower)))))))

(defn sized
 "Create a generator that depends on the size parameter.
 `sizedgen` is a function that takes an integer and returns
 a generator."
 [sizedgen]
 (makegen
 (fn [rnd size]
 (let [sizedgen (sizedgen size)]
 (callgen sizedgen rnd size)))))

;; Combinators and helpers
;; 

(defn resize
 "Create a new generator with `size` always bound to `n`."
 [n generator]
 (assert (generator? generator) "Second arg to resize must be a generator")
 (let [{:keys [gen]} generator]
 (makegen
 (fn [rnd _size]
 (gen rnd n)))))

(defn scale
 "Create a new generator that modifies the size parameter by the given function. Intended to
 support generators with sizes that need to grow at different rates compared to the normal
 linear scaling."
 ([f generator]
 (sized (fn [n] (resize (f n) generator)))))

(defn choose
 "Create a generator that returns numbers in the range
 `minrange` to `maxrange`, inclusive."
 [lower upper]
 (makegen
 (fn [rnd _size]
 (let [value (randrange rnd lower upper)]
 (rose/filter
 #(and (>= % lower) (<= % upper))
 (introsetree value))))))

(defn oneof
 "Create a generator that randomly chooses a value from the list of
 provided generators. Shrinks toward choosing an earlier generator,
 as well as shrinking the value generated by the chosen generator.

 Examples:

 (oneof [gen/int gen/boolean (gen/vector gen/int)])

 "
 [generators]
 (assert (every? generator? generators)
 "Arg to oneof must be a collection of generators")
 (bind (choose 0 (dec (count generators)))
 #(nth generators %)))

(defn pick
 [[h & tail] n]
 (let [[chance gen] h]
 (if (<= n chance)
 gen
 (recur tail ( n chance)))))

(defn frequency
 "Create a generator that chooses a generator from `pairs` based on the
 provided likelihoods. The likelihood of a given generator being chosen is
 its likelihood divided by the sum of all likelihoods

 Examples:

 (gen/frequency [[5 gen/int] [3 (gen/vector gen/int)] [2 gen/boolean]])
 "
 [pairs]
 (assert (every? (fn [[x g]] (and (number? x) (generator? g)))
 pairs)
 "Arg to frequency must be a list of [num generator] pairs")
 (let [total (apply + (core/map first pairs))]
 (genbind (choose 1 total)
 #(pick pairs (rose/root %)))))

(defn elements
 "Create a generator that randomly chooses an element from `coll`.

 Examples:

 (gen/elements [:foo :bar :baz])
 "
 [coll]
 (assert (seq coll) "elements cannot be called with an empty collection")
 (let [v (vec coll)]
 (genbind (choose 0 (dec (count v)))
 #(genpure (rose/fmap v %)))))

(defn suchthathelper
 [maxtries pred gen triesleft rng size]
 (if (zero? triesleft)
 (throw (exinfo (str "Couldn't satisfy suchthat predicate after "
 maxtries " tries.") {}))
 (let [[r1 r2] (random/split rng)
 value (callgen gen r1 size)]
 (if (pred (rose/root value))
 (rose/filter pred value)
 (recur maxtries pred gen (dec triesleft) r2 (inc size))))))

(defn suchthat
 "Create a generator that generates values from `gen` that satisfy predicate
 `pred`. Care is needed to ensure there is a high chance `gen` will satisfy
 `pred`. By default, `suchthat` will try 10 times to generate a value that
 satisfies the predicate. If no value passes this predicate after this number
 of iterations, a runtime exception will be throw. You can pass an optional
 third argument to change the number of times tried. Note also that each
 time suchthat retries, it will increase the size parameter.

 Examples:

 ;; generate nonempty vectors of integers
 ;; (note, gen/notempty does exactly this)
 (gen/suchthat notempty (gen/vector gen/int))
 "
 ([pred gen]
 (suchthat pred gen 10))
 ([pred gen maxtries]
 (assert (generator? gen) "Second arg to suchthat must be a generator")
 (makegen
 (fn [randseed size]
 (suchthathelper maxtries pred gen maxtries randseed size)))))

(defn notempty
 "Modifies a generator so that it doesn't generate empty collections.

 Examples:

 ;; generate a vector of booleans, but never the empty vector
 (gen/notempty (gen/vector gen/boolean))
 "
 [gen]
 (assert (generator? gen) "Arg to notempty must be a generator")
 (suchthat core/notempty gen))

(defn noshrink
 "Create a new generator that is just like `gen`, except does not shrink
 at all. This can be useful when shrinking is taking a long time or is not
 applicable to the domain."
 [gen]
 (assert (generator? gen) "Arg to noshrink must be a generator")
 (genbind gen
 (fn [rose]
 (genpure (rose/makerose (rose/root rose) [])))))

(defn shrink2
 "Create a new generator like `gen`, but will consider nodes for shrinking
 even if their parent passes the test (up to one additional level)."
 [gen]
 (assert (generator? gen) "Arg to shrink2 must be a generator")
 (genbind gen (comp genpure rose/collapse)))

(def boolean
 "Generates one of `true` or `false`. Shrinks to `false`."
 (elements [false true]))

(defn tuple
 "Create a generator that returns a vector, whose elements are chosen
 from the generators in the same position. The individual elements shrink
 according to their generator, but the value will never shrink in count.

 Examples:

 (def t (tuple gen/int gen/boolean))
 (sample t)
 ;; => ([1 true] [2 true] [2 false] [1 false] [0 true] [2 false] [6 false]
 ;; => [3 true] [4 false] [9 true]))
 "
 [& generators]
 (assert (every? generator? generators)
 "Args to tuple must be generators")
 (genbind (genseq>seqgen generators)
 (fn [roses]
 (genpure (rose/zip core/vector roses)))))

(def int
 "Generates a positive or negative integer bounded by the generator's
 `size` parameter.
 (Really returns a long)"
 (sized (fn [size] (choose ( size) size))))

(def nat
 "Generates natural numbers, starting at zero. Shrinks to zero."
 (fmap #(Math/abs (long %)) int))

(def posint
 "Generate positive integers bounded by the generator's `size` parameter."
 nat)

(def negint
 "Generate negative integers bounded by the generator's `size` parameter."
 (fmap #(* 1 %) nat))

(def sposint
 "Generate strictly positive integers bounded by the generator's `size`
 parameter."
 (fmap inc nat))

(def snegint
 "Generate strictly negative integers bounded by the generator's `size`
 parameter."
 (fmap dec negint))

(defn vector
 "Create a generator whose elements are chosen from `gen`. The count of the
 vector will be bounded by the `size` generator parameter."
 ([generator]
 (assert (generator? generator) "Arg to vector must be a generator")
 (genbind
 (sized #(choose 0 %))
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genpure (rose/shrink core/vector
 roses)))))))
 ([generator numelements]
 (assert (generator? generator) "First arg to vector must be a generator")
 (apply tuple (repeat numelements generator)))
 ([generator minelements maxelements]
 (assert (generator? generator) "First arg to vector must be a generator")
 (genbind
 (choose minelements maxelements)
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genbind
 (genpure (rose/shrink core/vector
 roses))
 (fn [rose]
 (genpure (rose/filter
 (fn [v] (and (>= (count v) minelements)
 (<= (count v) maxelements))) rose))))))))))

(defn list
 "Like `vector`, but generates lists."
 [generator]
 (assert (generator? generator) "First arg to list must be a generator")
 (genbind (sized #(choose 0 %))
 (fn [numelementsrose]
 (genbind (genseq>seqgen
 (repeat (rose/root numelementsrose)
 generator))
 (fn [roses]
 (genpure (rose/shrink core/list
 roses)))))))

(defn swap
 [coll [i1 i2]]
 (assoc coll i2 (coll i1) i1 (coll i2)))

(defn
 ^{:added "0.6.0"}
 shuffle
 "Create a generator that generates random permutations of `coll`. Shrinks
 toward the original collection: `coll`. `coll` will be turned into a vector,
 if it's not already."
 [coll]
 (let [indexgen (choose 0 (dec (count coll)))]
 (fmap #(reduce swap (vec coll) %)
 ;; a vector of swap instructions, with count between
 ;; zero and 2 * count. This means that the average number
 ;; of instructions is count, which should provide sufficient
 ;; (though perhaps not 'perfect') shuffling. This still gives us
 ;; nice, relatively quick shrinks.
 (vector (tuple indexgen indexgen) 0 (* 2 (count coll))))))

;; NOTE: Comment out for now  David
;;
;; (def byte
;; "Generates `java.lang.Byte`s, using the full byterange."
;; (fmap core/byte (choose Byte/MIN_VALUE Byte/MAX_VALUE)))

;; (def bytes
;; "Generates bytearrays."
;; (fmap core/bytearray (vector byte)))

(defn map
 "Create a generator that generates maps, with keys chosen from
 `keygen` and values chosen from `valgen`."
 [keygen valgen]
 (let [input (vector (tuple keygen valgen))]
 (fmap #(into {} %) input)))

(defn hashmap
 "Like clojure.core/hashmap, except the values are generators.
 Returns a generator that makes maps with the supplied keys and
 values generated using the supplied generators.

 Examples:

 (gen/hashmap :a gen/boolean :b gen/nat)
 "
 [& kvs]
 (assert (even? (count kvs)))
 (let [ks (takenth 2 kvs)
 vs (takenth 2 (rest kvs))]
 (assert (every? generator? vs)
 "Value args to hashmap must be generators")
 (fmap #(zipmap ks %)
 (apply tuple vs))))

(def char
 "Generates character from 0255."
 (fmap core/char (choose 0 255)))

(def charascii
 "Generate only ascii character."
 (fmap core/char (choose 32 126)))

(def charalphanumeric
 "Generate alphanumeric characters."
 (fmap core/char
 (oneof [(choose 48 57)
 (choose 65 90)
 (choose 97 122)])))

(def ^{:deprecated "0.6.0"}
 charalphanumeric
 "Deprecated  use charalphanumeric instead.

 Generate alphanumeric characters."
 charalphanumeric)

(def charalpha
 "Generate alpha characters."
 (fmap core/char
 (oneof [(choose 65 90)
 (choose 97 122)])))

(def ^{:private true} charsymbolspecial
 "Generate nonalphanumeric characters that can be in a symbol."
 (elements [\* \+ \! \ \_ \?]))

(def ^{:private true} charkeywordrest
 "Generate characters that can be the char following first of a keyword."
 (frequency [[2 charalphanumeric]
 [1 charsymbolspecial]]))

(def ^{:private true} charkeywordfirst
 "Generate characters that can be the first char of a keyword."
 (frequency [[2 charalpha]
 [1 charsymbolspecial]]))

(def string
 "Generate strings. May generate unprintable characters."
 (fmap clojure.string/join (vector char)))

(def stringascii
 "Generate ascii strings."
 (fmap clojure.string/join (vector charascii)))

(def stringalphanumeric
 "Generate alphanumeric strings."
 (fmap clojure.string/join (vector charalphanumeric)))

(def ^{:deprecated "0.6.0"}
 stringalphanumeric
 "Deprecated  use stringalphanumeric instead.

 Generate alphanumeric strings."
 stringalphanumeric)

(defn +ordigit?
 "Returns true if c is \\+ or \\ and d is nonnil and a digit.

 Symbols that start with +3 or 2 are not readable because they look
 like numbers."
 [c d]
 (core/boolean (and d
 (or (identical? \+ c)
 (identical? \ c))
 (gstring/isNumeric d))))

(def ^{:private true} namespacesegment
 "Generate the segment of a namespace."
 (>> (tuple charkeywordfirst (vector charkeywordrest))
 (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def ^{:private true} namespace
 "Generate a namespace (or nil for no namespace)."
 (>> (vector namespacesegment)
 (fmap (fn [v] (when (seq v)
 (clojure.string/join "." v))))))

(def ^{:private true} keywordsegmentrest
 "Generate segments of a keyword (between \\:)"
 (>> (tuple charkeywordrest (vector charkeywordrest))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def ^{:private true} keywordsegmentfirst
 "Generate segments of a keyword that can be first (between \\:)"
 (>> (tuple charkeywordfirst (vector charkeywordrest))
 (fmap (fn [[c cs]] (clojure.string/join (cons c cs))))))

(def keyword
 "Generate keywords without namespaces."
 (>> (tuple keywordsegmentfirst (vector keywordsegmentrest))
 (fmap (fn [[c cs]]
 (core/keyword (clojure.string/join ":" (cons c cs)))))))

(def
 ^{:added "0.5.9"}
 keywordns
 "Generate keywords with optional namespaces."
 (>> (tuple namespace charkeywordfirst (vector charkeywordrest))
 (fmap (fn [[ns c cs]]
 (core/keyword ns (clojure.string/join (cons c cs)))))))

(def ^{:private true} charsymbolfirst
 (frequency [[10 charalpha]
 [5 charsymbolspecial]
 [1 (return \.)]]))

(def ^{:private true} charsymbolrest
 (frequency [[10 charalphanumeric]
 [5 charsymbolspecial]
 [1 (return \.)]]))

(def symbol
 "Generate symbols without namespaces."
 (frequency [[100 (>> (tuple charsymbolfirst (vector charsymbolrest))
 (suchthat (fn [[c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[c cs]] (core/symbol (clojure.string/join (cons c cs))))))]
 [1 (return '/)]]))

(def
 ^{:added "0.5.9"}
 symbolns
 "Generate symbols with optional namespaces."
 (frequency [[100 (>> (tuple namespace charsymbolfirst (vector charsymbolrest))
 (suchthat (fn [[_ c [d]]] (not (+ordigit? c d))))
 (fmap (fn [[ns c cs]] (core/symbol ns (clojure.string/join (cons c cs))))))]
 [1 (return '/)]]))

(def ratio
 "Generates a `clojure.lang.Ratio`. Shrinks toward 0. Not all values generated
 will be ratios, as many values returned by `/` are not ratios."
 (fmap
 (fn [[a b]] (/ a b))
 (tuple int
 (suchthat (complement zero?) int))))

(def simpletype
 (oneof [int char string ratio boolean keyword keywordns symbol symbolns]))

(def simpletypeprintable
 (oneof [int charascii stringascii ratio boolean keyword keywordns symbol symbolns]))

(defn containertype
 [innertype]
 (oneof [(vector innertype)
 (list innertype)
 (map innertype innertype)]))

(defn recursivehelper
 [containergenfn scalargen scalarsize childrensize height]
 (if (zero? height)
 (resize scalarsize scalargen)
 (resize childrensize
 (containergenfn
 (recursivehelper
 containergenfn scalargen
 scalarsize childrensize (dec height))))))

(defn
 ^{:added "0.5.9"}
 recursivegen
 "This is a helper for writing recursive (treeshaped) generators. The first
 argument should be a function that takes a generator as an argument, and
 produces another generator that 'contains' that generator. The vector function
 in this namespace is a simple example. The second argument is a scalar
 generator, like boolean. For example, to produce a tree of booleans:

 (gen/recursivegen gen/vector gen/boolean)

 Vectors or maps either recurring or containing booleans or integers:

 (gen/recursivegen (fn [inner] (gen/oneof [(gen/vector inner)
 (gen/map inner inner)]))
 (gen/oneof [gen/boolean gen/int]))
 "
 [containergenfn scalargen]
 (assert (generator? scalargen)
 "Second arg to recursivegen must be a generator")
 (sized (fn [size]
 (bind (choose 1 5)
 (fn [height] (let [childrensize (Math/pow size (/ 1 height))]
 (recursivehelper containergenfn scalargen size
 childrensize height)))))))

(def any
 "A recursive generator that will generate many different, often nested, values"
 (recursivegen containertype simpletype))

(def anyprintable
 "Like any, but avoids characters that the shell will interpret as actions,
 like 7 and 14 (bell and alternate character set command)"
 (recursivegen containertype simpletypeprintable))

1.8.3.2