Skip to content

Commit 57c9ba7

Browse files
authored
Merge pull request #195 from vch9/fix188
Deriver: share fuel between mutual generators
2 parents 3999873 + e0d544a commit 57c9ba7

File tree

7 files changed

+717
-535
lines changed

7 files changed

+717
-535
lines changed

ppx_deriving_qcheck.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ depends: [
1212
"ocaml" {>= "4.08.0"}
1313
"qcheck" {>= "0.17"}
1414
"ppxlib" {>= "0.22.0"}
15+
"ppx_deriving" {>= "5.2.1"}
1516
"odoc" {with-doc}
1617
"alcotest" {with-test & >= "1.4.0" }
1718
]
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
open Ppxlib
2+
3+
(** This module contains all generators from QCheck used to
4+
derive a type declaration *)
5+
6+
(** {2. Type} *)
7+
8+
let ty = "QCheck.Gen.t"
9+
10+
(** {2. Primitive generators} *)
11+
12+
let unit loc = [%expr QCheck.Gen.unit]
13+
14+
let int loc = [%expr QCheck.Gen.int]
15+
16+
let string loc = [%expr QCheck.Gen.string]
17+
18+
let char loc = [%expr QCheck.Gen.char]
19+
20+
let bool loc = [%expr QCheck.Gen.bool]
21+
22+
let float loc = [%expr QCheck.Gen.float]
23+
24+
let int32 loc = [%expr QCheck.Gen.int32]
25+
26+
let int64 loc = [%expr QCheck.Gen.int64]
27+
28+
let option ~loc e = [%expr QCheck.Gen.option [%e e]]
29+
30+
let list ~loc e = [%expr QCheck.Gen.list [%e e]]
31+
32+
let array ~loc e = [%expr QCheck.Gen.array [%e e]]
33+
34+
(** {2. Generator combinators} *)
35+
36+
let pure ~loc x = [%expr QCheck.Gen.pure [%e x]]
37+
38+
let frequency ~loc l =
39+
match l with
40+
| [%expr [([%e? _], [%e? x])]] -> x
41+
| _ ->
42+
[%expr QCheck.Gen.frequency [%e l]]
43+
44+
let map ~loc pat expr gen =
45+
[%expr QCheck.Gen.map (fun [%p pat] -> [%e expr]) [%e gen]]
46+
47+
let pair ~loc a b =
48+
[%expr QCheck.Gen.pair [%e a] [%e b]]
49+
50+
let triple ~loc a b c =
51+
[%expr QCheck.Gen.triple [%e a] [%e b] [%e c]]
52+
53+
let quad ~loc a b c d=
54+
[%expr QCheck.Gen.quad [%e a] [%e b] [%e c] [%e d]]
55+
56+
let sized ~loc e =
57+
[%expr QCheck.Gen.sized @@ [%e e]]
58+
59+
let fix ~loc e =
60+
[%expr QCheck.Gen.fix [%e e]]
61+
62+
(** Observable generators *)
63+
module Observable = struct
64+
(** {2. Primitive generators} *)
65+
let unit loc = [%expr QCheck.Observable.unit]
66+
67+
let int loc = [%expr QCheck.Observable.int]
68+
69+
let string loc = [%expr QCheck.Observable.string]
70+
71+
let char loc = [%expr QCheck.Observable.char]
72+
73+
let bool loc = [%expr QCheck.Observable.bool]
74+
75+
let float loc = [%expr QCheck.Observable.float]
76+
77+
let int32 loc = [%expr QCheck.Observable.int32]
78+
79+
let int64 loc = [%expr QCheck.Observable.int64]
80+
81+
let option ~loc e = [%expr QCheck.Observable.option [%e e]]
82+
83+
let list ~loc e = [%expr QCheck.Observable.list [%e e]]
84+
85+
let array ~loc e = [%expr QCheck.Observable.array [%e e]]
86+
87+
(** {2. Observable combinators} *)
88+
let pair ~loc a b =
89+
[%expr QCheck.Observable.pair [%e a] [%e b]]
90+
91+
let triple ~loc a b c =
92+
[%expr QCheck.Observable.triple [%e a] [%e b] [%e c]]
93+
94+
let quad ~loc a b c d=
95+
[%expr QCheck.Observable.quad [%e a] [%e b] [%e c] [%e d]]
96+
end

src/ppx_deriving_qcheck/README.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ let test =
1818
(fun tree -> rev (rev tree) = tree)
1919
```
2020

21+
For `type tree` we derive two generators:
22+
- `val gen_tree : tree Gen.t` and
23+
- `val gen_tree_sized : int -> tree Gen.t`
24+
25+
For non-recursive types the latter is however not derived.
26+
27+
For types with the name `t` (i.e. `type t = ...`) which is a common idiom in OCaml code,
28+
the deriver omits the name from the derived generators,
29+
thus producing `val gen : t Gen.t` and optionally `val gen_sized : int -> t Gen.t`.
30+
2131
### Overwrite generator
2232
If you wan't to specify your own `generator` for any type you can
2333
add an attribute to the type:
@@ -238,20 +248,19 @@ let gen_color =
238248
type tree = Leaf of int | Node of tree * tree
239249
[@@deriving qcheck]
240250
241-
let gen_tree =
242-
QCheck.Gen.sized @@
243-
(QCheck.Gen.fix
244-
(fun self -> function
245-
| 0 ->
246-
QCheck.Gen.frequency
247-
[(1, (QCheck.Gen.map (fun gen0 -> Leaf gen0) QCheck.Gen.int))]
248-
| n ->
249-
QCheck.Gen.frequency
250-
[(1,
251-
(QCheck.Gen.map (fun gen0 -> Leaf gen0) QCheck.Gen.int));
252-
(1,
253-
(QCheck.Gen.map (fun (gen0, gen1) -> Node (gen0, gen1))
254-
(QCheck.Gen.pair (self (n / 2)) (self (n / 2)))))]))
251+
(* ==> *)
252+
253+
let rec gen_tree_sized n =
254+
match n with
255+
| 0 -> QCheck.Gen.map (fun gen0 -> Leaf gen0) QCheck.Gen.int
256+
| n ->
257+
QCheck.Gen.frequency
258+
[(1, (QCheck.Gen.map (fun gen0 -> Leaf gen0) QCheck.Gen.int));
259+
(1,
260+
(QCheck.Gen.map (fun (gen0, gen1) -> Node (gen0, gen1))
261+
(QCheck.Gen.pair (self (n / 2)) (self (n / 2)))))]))
262+
263+
let gen_tree = QCheck.Gen.sized @@ gen_tree_sized
255264
```
256265

257266
* Recursive polymorphic variants

src/ppx_deriving_qcheck/args.ml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
open Ppxlib
2+
3+
(** [curry_args args body] adds parameter to [body]
4+
5+
e.g.:
6+
curry_args [gen_a; gen_b] () => fun gen_a -> fun gen_b -> ()
7+
*)
8+
let rec curry_args ~loc args body =
9+
match args with
10+
| [] -> body
11+
| x :: xs -> [%expr fun [%p x] -> [%e curry_args ~loc xs body]]
12+
13+
(** [apply_args args body] applies parameters to [body]
14+
15+
e.g.:
16+
apply_args [gen_a; gen_b] f => f gen_a gen_b
17+
*)
18+
let apply_args ~loc args body =
19+
let rec aux acc = function
20+
| [] -> acc
21+
| [arg] -> [%expr [%e acc] [%e arg]]
22+
| arg :: args -> aux [%expr [%e acc] [%e arg]] args
23+
in
24+
aux body args

0 commit comments

Comments
 (0)