~technomancy/fennel

ref: 83ccb3c3345e84c59303fcd97db257d533905399 fennel/test/generate.fnl -rw-r--r-- 2.6 KiB
83ccb3c3Phil Hagelberg Fix apropos tests for other Lua versions. 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
;; A general-purpose function for generating random values.

(local random-char
       (fn []
         (if (> (math.random) 0.9) ; digits
             (string.char (+ 47 (math.random 10)))
             (> (math.random) 0.5) ; lower case
             (string.char (+ 96 (math.random 26)))
             (> (math.random) 0.5) ; upper case
             (string.char (+ 64 (math.random 26)))
             (> (math.random) 0.5) ; space and punctuation
             (string.char (+ 31 (math.random 16)))
             (> (math.random) 0.5) ; newlines and tabs
             (string.char (+ 9 (math.random 4)))
             :else ; bonus punctuation
             (string.char (+ 58 (math.random 5))))))

(local generators {:number (fn [] ; weighted towards mid-range integers
                             (if (> (math.random) 0.9)
                                 (let [x (math.random 2147483647)]
                                   (math.floor (- x (/ x 2))))
                                 (> (math.random) 0.2)
                                 (math.floor (math.random 2048))
                                 :else (math.random)))
                   :string (fn []
                             (var s "")
                             (for [_ 1 (math.random 16)]
                               (set s (.. s (random-char))))
                             s)
                   :table (fn [generate depth]
                            (let [t {}]
                              (var k nil)
                              (for [_ 1 (math.random 16)]
                                (set k (generate depth))
                                ;; no nans plz
                                (while (not= k k) (set k (generate depth)))
                                (when (not= nil k)
                                  (tset t k (generate depth))))
                              t))
                   :sequence (fn [generate depth]
                               (let [t {}]
                                 (for [_ 1 (math.random 32)]
                                   (tset t (+ (length t) 1) (generate depth)))
                                 t))
                   :boolean (fn [] (> (math.random) 0.5))})

(local order [:number :string :table :sequence :boolean])

(fn generate [depth ?choice]
  "Generate a random piece of data."
  (if (< (+ 0.5 (/ (math.log depth 10) 1.2)) (math.random))
      (match (. generators (or (. order (or ?choice 1)) :boolean))
        generator (generator generate (+ depth 1)))
      (or (= nil ?choice) (<= ?choice (length order)))
      (generate depth (+ (or ?choice 1) 1))))

{: generate : generators : order}