File: DerivedGen.v

package info (click to toggle)
coq-quickchick 2.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,432 kB
  • sloc: ml: 4,367; ansic: 789; makefile: 388; sh: 27; python: 4; lisp: 2; perl: 2
file content (267 lines) | stat: -rw-r--r-- 8,982 bytes parent folder | download | duplicates (4)
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
From QuickChick Require Import QuickChick.

Require Import ZArith.
Require Import List.
Import ListNotations.
From QuickChick.ifcbasic Require Import Machine Printing Generation.

Set Bullet Behavior "Strict Subproofs".

Local Open Scope nat.

(* Overriding default instance to generate "in-bounds" things *)
(* Definition gen_Z := choose (0,1). *)
Inductive good_Z : Z -> Prop := 
  | GoodZ0 : good_Z 0
  | GoodZ1 : good_Z 1.

Derive ArbitrarySizedSuchThat for (fun z => good_Z z).

(* Definition gen_label := elements L [L; H]. *)
Derive Arbitrary for Label.

(* Definition gen_atom := liftGen2 Atm gen_Z gen_label. *)
Inductive good_atom : Atom -> Prop :=
  | GoodAtom : forall z l, good_Z z -> good_atom (Atm z l).
Derive ArbitrarySizedSuchThat for (fun a => good_atom a).

(* Definition gen_memory := vectorOf 2 gen_atom. *)
Inductive good_mem : Mem -> Prop :=
  | GoodMem : forall a1 a2, good_atom a1 -> good_atom a2 -> good_mem [a1 ; a2].
Derive ArbitrarySizedSuchThat for (fun m => good_mem m).

Definition is_atom_low (a : Atom) :=
  match a with
    | _ @ L => true
    | _     => false
  end.

(*
Fixpoint gen_stack (n : nat) (onlyLow : bool) : G Stack :=
  (* There is no invariant that says this. Why is this here? *)
  (*
  let gen_atom :=
      if onlyLow then liftGen2 Atm gen_Z (returnGen L)
      else gen_atom
  in
   *)
  match n with
    | O => returnGen Mty
    | S n' =>
      frequency (returnGen Mty) [
                  (10, liftGen2 Cons gen_atom (gen_stack n' onlyLow));
                  (4, bindGen gen_atom (fun pc =>
                       liftGen (RetCons pc) (gen_stack n' (is_atom_low pc))))]
  end.
*)
(* I could write this without the nat to exploit the default size! *)
Inductive good_stack : nat -> Stack -> Prop :=
| GoodStackMty  : good_stack 0 Mty
| GoodStackCons : forall n a s , good_atom a  -> good_stack n s -> good_stack (S n) (a  :: s)
| GoodStackRet  : forall n pc s, good_atom pc -> good_stack n s -> good_stack (S n) (RetCons pc s).

QuickChickWeights [(GoodStackCons, 10); (GoodStackRet, 4)].
Derive ArbitrarySizedSuchThat for (fun s => good_stack n s).

(*
Definition ainstr (st : State) : G Instruction :=
  let '(St im m stk pc ) := st in
  let fix stack_length s :=
      match s with
        | _ :: s' => 1 + stack_length s'
        | _ => 0
      end in
  let sl := stack_length stk in
  let fix containsRet s :=
      match s with
        | _ ::: _ => true
        | _ :: s' => containsRet s'
        | _ => false
      end in
  let onLength len x := if leb x len then x else 0 in
  frequency (returnGen Nop) [
              (1, returnGen Nop);
              (10, liftGen Push gen_Z);
              (10, liftGen BCall (if beq_nat sl 0 then returnGen 0
                                  else choose (0, Z.of_nat sl-1))%Z);
              (if containsRet stk then 10 else 0, returnGen BRet);
              (10, returnGen Add);
              (10, returnGen Load);
              (100, returnGen Store)].
*)
Inductive contains_ret : Stack -> Prop := 
  | RetHere  : forall pc s, contains_ret (RetCons pc s)
  | RetLater : forall a  s, contains_ret s -> contains_ret (a :: s).
#[global]
Instance dec_contains_ret (s : Stack) : Dec (contains_ret s).
Proof.
  dec_eq.
  induction s.
  - right => H; inversion H.
  - destruct IHs.
    + left; constructor; auto.
    + right => H; inversion H; eauto.
  - left; constructor; auto.
Defined.

Inductive stack_length : Stack -> nat -> Prop :=
| LenMty  : stack_length Mty 0
| LenRet  : forall pc s, stack_length (pc :: s) 0
| LenCons : forall a s n, stack_length s n -> stack_length (a :: s) (S n).
Derive ArbitrarySizedSuchThat for (fun n => stack_length s n).

Inductive between (x y : Z) (z : nat) : Prop :=
| Bet : (x < y -> y < Z.of_nat z -> between x y z)%Z.
#[global]
Instance genST_bet x z : GenSizedSuchThat Z (fun y => between x y z) := 
{|
  arbitrarySizeST n := liftGen Some (choose (x, Z.of_nat z))
|}.

Inductive good_instr (stk : Stack) : Instruction -> Prop :=
  | GoodNop   : good_instr stk Nop
  | GoodPush  : forall z, good_Z z -> good_instr stk (Push z)
  | GoodCall  : forall z n, 
      stack_length stk n ->
      between 0 z n ->
      good_instr stk (BCall z)
  | GoodRet   : contains_ret stk -> good_instr stk BRet 
  | GoodAdd   : good_instr stk Add 
  | GoodLoad  : good_instr stk Load
  | GoodStore : good_instr stk Store.

QuickChickWeights [ (GoodNop, 1)
                  ; (GoodPush, 10)
                  ; (GoodCall, 10)
                  ; (GoodRet, 10)
                  ; (GoodAdd, 10)
                  ; (GoodLoad, 10)
                  ; (GoodStore, 100) ].
Derive ArbitrarySizedSuchThat for (fun i => good_instr stk i). 

(*
Definition gen_state : G State :=
  let imem0 := [Nop; Nop] in
  bindGen gen_atom (fun pc =>
  bindGen gen_memory (fun mem =>
  bindGen (gen_stack 4 (is_atom_low pc)) (fun stk =>
  bindGen (ainstr (St imem0 mem stk pc)) (fun i =>
  returnGen (St [i;i] mem stk pc))))).
*)
Inductive good_state : State -> Prop :=
  | GoodState : 
      forall i m stk pc, 
        good_atom pc ->
        good_mem m ->
        good_stack 4 stk ->
        good_instr stk i ->
        good_state (St [i;i] m stk pc).
Derive ArbitrarySizedSuchThat for (fun st => good_state st).        

(* Sample (@arbitrarySizeST _ (fun st => good_state st) _ 10).*)

(*
Class Vary (A : Type) := {
  vary : A -> G A
}.
*)

(*
Instance vary_atom : Vary Atom :=
{|
  vary a :=
    let '(x @ l) := a in
    match l with
      | L => returnGen a
      | H => liftGen2 Atm gen_Z (returnGen H)
    end
|}.
*)
Inductive variation_atom : Atom -> Atom -> Prop :=
| VaryAtomL : forall x  , variation_atom (x @ L) (x @ L)
| VaryAtomH : forall x y, good_Z y -> variation_atom (x @ H) (y @ H).
Derive ArbitrarySizedSuchThat for (fun y => variation_atom x y).

(*
Instance vary_mem : Vary Mem :=
{|
  vary m := sequenceGen (map vary m)
|}.
*)
Inductive variation_mem : Mem -> Mem -> Prop :=
| VaryMemNil  : variation_mem [] []
| VaryMemCons : forall a a' m m', variation_atom a a' ->
                                   variation_mem m m'  ->
                                   variation_mem (cons a m) (cons a' m').
Derive ArbitrarySizedSuchThat for (fun m2 => variation_mem m1 m2).    

(*
Fixpoint vary_stack (s : Stack) (isLow : bool) : G Stack :=
  match s with
    | a :: s'  => if isLow then liftGen2 Cons (vary a) (vary_stack s' isLow)
                  else liftGen2 Cons gen_atom (vary_stack s' isLow)
    | (x@l) ::: s' =>
      match l with
        | L => liftGen (RetCons (x@l)) (vary_stack s' true)
        | H => liftGen2 RetCons (vary (x@l)) (vary_stack s' false)
      end
    | Mty => returnGen Mty
  end.
*)
Inductive variation_stack : Stack -> Stack -> Prop :=
  | VaryStkMty  : variation_stack Mty Mty
  | VaryStkCons : forall a a' s s', variation_atom a a' ->
                                    variation_stack s s' ->
                                    variation_stack (a :: s) (a' :: s')
  | VaryStkRet  : forall a a' s s', variation_atom a a' ->
                                    variation_stack s s' ->
                                    variation_stack (RetCons a s) (RetCons a' s').
Derive ArbitrarySizedSuchThat for (fun s2 => variation_stack s1 s2).

(*
Instance vary_state : Vary State :=
{|
  vary st :=
    let '(St imem mem stk pc) := st in
    bindGen (vary mem) (fun mem' =>
    bindGen (vary pc)  (fun pc' =>
    let isLow := match pc with
                   | _ @ L => true
                   | _ @ H => false
                 end in
    if isLow then
      bindGen (vary_stack stk isLow) (fun stk' =>
      returnGen (St imem mem' stk' pc'))
    else
      bindGen (vary_stack stk isLow) (fun stk' =>
      bindGen gen_atom (fun extra_elem =>
      returnGen (St imem mem' (extra_elem :: stk') pc')))))
|}.
*)

Inductive variation_high_stack : Atom -> Stack -> Stack -> Prop :=
| VaryStkAny : forall pc stk stk', variation_stack stk stk' ->
                                  variation_high_stack pc stk stk'
| VarystkHigh : forall pcx stk stk' a,
                       variation_stack stk stk' ->
                       good_atom a ->
                       variation_high_stack (pcx @ H) stk (a :: stk').
Derive ArbitrarySizedSuchThat for (fun stk' => variation_high_stack pc stk stk').

Inductive variation_state : State -> State -> Prop :=
  | VaryState : forall imem mem stk pc mem' stk' pc',
      variation_mem mem mem' ->
      variation_atom pc pc' ->
      variation_high_stack pc stk stk' ->
      variation_state (St imem mem stk pc) (St imem mem' stk' pc').
Derive ArbitrarySizedSuchThat for (fun st' => variation_state st st').

Definition gen_variation_state_derived : G (option (@Variation State)) :=
  bindOpt (genST (fun st => good_state st)) (fun st => 
  bindOpt (genST (fun st' => variation_state st st')) (fun st' =>
  returnGen (Some (V st st')))).                                                            
(*
  bindGen gen_state (fun st =>
  bindGen (vary st) (fun st' =>
  returnGen (V st st'))).
*)