File: genSizedSTMonotonic.ml

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 (188 lines) | stat: -rw-r--r-- 6,206 bytes parent folder | download | duplicates (5)
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
open Pp
open Util
open GenericLib
open SetLib
open CoqLib
open GenLib
open SemLib
open UnifyQC
open ArbitrarySizedST
open Error

(* arguments to handle_branch *)
let fail_exp = returnGenSizeMonotonicOpt (gNone hole)

let ret_exp (c : coq_expr) = returnGenSizeMonotonicOpt (gSome hole c)

let ret_type (s : var) (match_expr : var -> coq_expr -> coq_expr -> coq_expr)  =
  gApp (gInject "SizeMonotonicOpt") [match_expr s hole hole]

(* These should be inferred automatically  *)
let class_method = hole
let class_methodST (n : int) (pred : coq_expr) = hole

let rec_method (ih : var) (n : int) (l : coq_expr list) =
  gApp (gVar ih) l

let bind (opt : bool) (m : coq_expr) (x : string) (f : var -> coq_expr) =
  (if opt then bindOptMonotonicOpt else bindMonotonicOpt) m x f

let stMaybe (opt : bool) (g : coq_expr) (x : string) (checks : ((coq_expr -> coq_expr) * int) list) =
  let rec sumbools_to_bool x lst =
    match lst with
    | [] -> gTrueb
    | (chk, _) :: lst' ->
      matchDec (chk (gVar x)) (fun heq -> gFalseb) (fun hneq -> sumbools_to_bool x lst')
  in
  let bool_pred =
    gFun [x]
      (fun [x] -> sumbools_to_bool x checks)
  in
  (if opt then suchThatMaybeOptMonotonicOpt else suchThatMaybeMonotonicOpt) g bool_pred

let ret_type_dec (s : var) (left : coq_expr) (right : coq_expr) =
      gMatch (gVar s)
      [ (injectCtr "left", ["eq"], fun _ -> left)
      ; (injectCtr "right", ["neq"], fun _ -> right) ]

let check_expr (n : int) (scrut : coq_expr) (left : coq_expr) (right : coq_expr) =
  gMatchReturn scrut
    "s" (* as clause *)
    (fun v -> ret_type v ret_type_dec)
    [ (injectCtr "left", ["eq" ] , fun _ -> left)
    ; (injectCtr "right", ["neq"], fun _ -> right) 
    ]

let match_inp (inp : var) (pat : matcher_pat) (left : coq_expr) (right  : coq_expr) =
  let ret v left right =
    construct_match (gVar v) ~catch_all:(Some right) [(pat, left)]
  in
  construct_match_with_return
    (gVar inp) ~catch_all:(Some right) "s" (fun v -> ret_type v ret)
    [(pat,left)]


let genSizedSTMon_body
      (class_name : string)
      (gen_ctr : ty_ctr)
      (ty_params : ty_param list)
      (ctrs : dep_ctr list)
      (dep_type : dep_type)
      (input_names : string list)
      (inputs : arg list)
      (n : int)
      (register_arbitrary : dep_type -> unit) =

  (* type constructor *)
  let coqTyCtr = gTyCtr gen_ctr in

  (* parameters of the type constructor *)
  let coqTyParams = List.map gTyParam ty_params in

  (* Fully applied type constructor *)
  let full_dt = gApp ~explicit:true coqTyCtr coqTyParams in

  (* The type we are generating for -- not the predicate! *)
  let full_gtyp = (gType ty_params (nthType n dep_type)) in

  (* The type of the dependent generator *)
  let gen_type = gGen (gOption full_gtyp) in

  (* Fully applied predicate (parameters and constructors) *)
  let full_pred inputs =
    gFun ["_forGen"] (fun [fg] -> gApp (full_dt) (list_insert_nth (gVar fg) inputs (n-1)))
  in

  let base_gens (input_names : var list) (rec_name : coq_expr) =
    base_gens (gInt 0) full_gtyp gen_ctr dep_type ctrs input_names n register_arbitrary rec_name
  in

  let ind_gens (input_names : var list) (size : var) (rec_name : coq_expr) =
    ind_gens (gVar size) full_gtyp gen_ctr dep_type ctrs input_names n register_arbitrary rec_name
  in

  let aux_arb (input_names : var list) (rec_name : coq_expr) size vars =
    gMatch (gVar size)
      [ (injectCtr "O", [], fun _ ->
             uniform_backtracking (base_gens input_names rec_name))
      ; (injectCtr "S", ["size'"], fun [size'] ->
            uniform_backtracking (ind_gens input_names size' rec_name))
      ]
  in

  let generator_body (input_names : var list) : coq_expr =
    gRecFunInWithArgs
      ~assumType:(gen_type)
      "aux_arb" (gArg ~assumName:(gVar (fresh_name "size")) () :: inputs) 
      (fun (rec_name, size::vars) -> aux_arb input_names (gVar rec_name) size vars)
      (fun x -> gVar x)
  in

  let add_freq gens =
    List.map gPair (List.combine (List.map (fun _ -> gInt 1) gens) gens) in

  let base_case =
    let handle_branch' (inputs : var list) =
      handle_branch n dep_type inputs
        fail_exp ret_exp class_method class_methodST
        (rec_method (make_up_name ())) bind stMaybe check_expr match_inp gLetIn
        gen_ctr (fun _ -> ())
    in
    gFunWithArgs
      inputs
      (fun inputs ->
         backtrackSizeMonotonicOpt
           (gList (add_freq (base_gens inputs (generator_body inputs))))
           (List.fold_right
              (fun (c : dep_ctr) (exp : coq_expr) ->
                 let (p, b) : coq_expr * bool = handle_branch' inputs c in
                 if b then
                   cons_subset hole hole hole p exp
                 else exp
              )
              ctrs (nil_subset hole)))
  in
  (* gen_ctr dep_type gen_type ctrs input_names inputs n register_arbitrary *)
  (* class_name full_gtyp full_pred inputs base_gen ind_gen = *)

  let ind_case =
    let handle_branch' (ih : var) (size : var) (inputs : var list) =
      handle_branch n dep_type inputs
        fail_exp ret_exp class_method class_methodST
        (rec_method ih) bind stMaybe check_expr match_inp
        (failwith "zoe fix me!")
        gen_ctr (fun _ -> ())
    in
    gFun ["size"; "IHs"]
      (fun [size; ihs] ->
         gFunWithArgs
           inputs
           (fun inputs ->
              backtrackSizeMonotonicOpt
                (gList (add_freq (ind_gens inputs size (generator_body inputs))))
                (List.fold_right
                   (fun c exp ->
                      let (p, b) = handle_branch' ihs size inputs c in
                      cons_subset hole hole hole p exp
                   )
                   ctrs (nil_subset hole))))
  in

  let ret_type =
    gFun ["s"]
      (fun [s] ->
         gProdWithArgs
           inputs
           (fun inputs ->
              gApp (gInject class_name)
                [gApp ~explicit:true (gInject "arbitrarySizeST")
                   [full_gtyp; full_pred (List.map gVar inputs); hole; gVar s]]))
  in 

  let mon_proof =
    gApp (gInject "nat_ind") [ret_type; base_case; ind_case]
  in

  msg_debug (str "mon term");
  debug_coq_expr mon_proof;
  mon_proof