summaryrefslogtreecommitdiff
path: root/plugins/dp/dp_why.ml
blob: 9a62f39d013ee4f82c01bf8c387496c80ed93923 (plain)
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

(* Pretty-print PFOL (see fol.mli) in Why syntax *)

open Format
open Fol

type proof =
  | Immediate of Term.constr
  | Fun_def of string * (string * typ) list * typ * term

let proofs = Hashtbl.create 97
let proof_name =
  let r = ref 0 in fun () -> incr r; "dp_axiom__" ^ string_of_int !r

let add_proof pr = let n = proof_name () in Hashtbl.add proofs n pr; n

let find_proof = Hashtbl.find proofs

let rec print_list sep print fmt = function
  | [] -> ()
  | [x] -> print fmt x
  | x :: r -> print fmt x; sep fmt (); print_list sep print fmt r

let space fmt () = fprintf fmt "@ "
let comma fmt () = fprintf fmt ",@ "

let is_why_keyword =
  let h = Hashtbl.create 17 in
  List.iter
    (fun s -> Hashtbl.add h s ())
    ["absurd"; "and"; "array"; "as"; "assert"; "axiom"; "begin";
     "bool"; "do"; "done"; "else"; "end"; "exception"; "exists";
     "external"; "false"; "for"; "forall"; "fun"; "function"; "goal";
     "if"; "in"; "int"; "invariant"; "label"; "let"; "logic"; "not";
     "of"; "or"; "parameter"; "predicate"; "prop"; "raise"; "raises";
     "reads"; "real"; "rec"; "ref"; "returns"; "then"; "true"; "try";
     "type"; "unit"; "variant"; "void"; "while"; "with"; "writes" ];
  Hashtbl.mem h

let ident fmt s =
  if is_why_keyword s then fprintf fmt "coq__%s" s else fprintf fmt "%s" s

let rec print_typ fmt = function
  | Tvar x -> fprintf fmt "'%a" ident x
  | Tid ("int", []) -> fprintf fmt "int"
  | Tid ("real", []) -> fprintf fmt "real"
  | Tid (x, []) -> fprintf fmt "%a" ident x
  | Tid (x, [t]) -> fprintf fmt "%a %a" print_typ t ident x
  | Tid (x,tl) -> fprintf fmt "(%a) %a" (print_list comma print_typ) tl ident x

let print_arg fmt (id,typ) = fprintf fmt "%a: %a" ident id print_typ typ

let rec print_term fmt = function
  | Cst n ->
      fprintf fmt "%s" (Big_int.string_of_big_int n)
  | RCst s ->
      fprintf fmt "%s.0" (Big_int.string_of_big_int s)
  | Power2 n ->
      fprintf fmt "0x1p%s" (Big_int.string_of_big_int n)
  | Plus (a, b) ->
      fprintf fmt "@[(%a +@ %a)@]" print_term a print_term b
  | Moins (a, b) ->
      fprintf fmt "@[(%a -@ %a)@]" print_term a print_term b
  | Mult (a, b) ->
      fprintf fmt "@[(%a *@ %a)@]" print_term a print_term b
  | Div (a, b) ->
      fprintf fmt "@[(%a /@ %a)@]" print_term a print_term b
  | Opp (a) ->
      fprintf fmt "@[(-@ %a)@]" print_term a
  | App (id, []) ->
      fprintf fmt "%a" ident id
  | App (id, tl) ->
      fprintf fmt "@[%a(%a)@]" ident id print_terms tl

and print_terms fmt tl =
  print_list comma print_term fmt tl

let rec print_predicate fmt p =
  let pp = print_predicate in
  match p with
  | True ->
      fprintf fmt "true"
  | False ->
      fprintf fmt "false"
  | Fatom (Eq (a, b)) ->
      fprintf fmt "@[(%a =@ %a)@]" print_term a print_term b
  | Fatom (Le (a, b)) ->
      fprintf fmt "@[(%a <=@ %a)@]" print_term a print_term b
  | Fatom (Lt (a, b))->
      fprintf fmt "@[(%a <@ %a)@]" print_term a print_term b
  | Fatom (Ge (a, b)) ->
      fprintf fmt "@[(%a >=@ %a)@]" print_term a print_term b
  | Fatom (Gt (a, b)) ->
      fprintf fmt "@[(%a >@ %a)@]" print_term a print_term b
  | Fatom (Pred (id, [])) ->
      fprintf fmt "%a" ident id
  | Fatom (Pred (id, tl)) ->
      fprintf fmt "@[%a(%a)@]" ident id print_terms tl
  | Imp (a, b) ->
      fprintf fmt "@[(%a ->@ %a)@]" pp a pp b
  | Iff (a, b) ->
      fprintf fmt "@[(%a <->@ %a)@]" pp a pp b
  | And (a, b) ->
      fprintf fmt "@[(%a and@ %a)@]" pp a pp b
  | Or (a, b) ->
      fprintf fmt "@[(%a or@ %a)@]" pp a pp b
  | Not a ->
      fprintf fmt "@[(not@ %a)@]" pp a
  | Forall (id, t, p) ->
      fprintf fmt "@[(forall %a:%a.@ %a)@]" ident id print_typ t pp p
  | Exists (id, t, p) ->
      fprintf fmt "@[(exists %a:%a.@ %a)@]" ident id print_typ t pp p

let rec remove_iff args = function
    Forall (id,t,p) -> remove_iff ((id,t)::args) p
  | Iff(_,b) -> List.rev args, b
  | _ -> raise Not_found

let print_query fmt (decls,concl) =
  let find_declared_preds l =
    function
        DeclPred (id,_,args) -> (id,args) :: l
      | _ -> l
  in
  let find_defined_preds declared l = function
      Axiom(id,f) ->
        (try
           let _decl = List.assoc id declared in
           (id,remove_iff [] f)::l
         with Not_found -> l)
    | _ -> l
  in
  let declared_preds =
    List.fold_left find_declared_preds [] decls in
  let defined_preds =
    List.fold_left (find_defined_preds declared_preds) [] decls
  in
  let print_dtype = function
    | DeclType (id, 0) ->
	fprintf fmt "@[type %a@]@\n@\n" ident id
    | DeclType (id, 1) ->
	fprintf fmt "@[type 'a %a@]@\n@\n" ident id
    | DeclType (id, n) ->
	fprintf fmt "@[type (";
	for i = 1 to n do
	  fprintf fmt "'a%d" i; if i < n then fprintf fmt ", "
	done;
	fprintf fmt ") %a@]@\n@\n" ident id
    | DeclFun _ | DeclPred _ | Axiom _ ->
	()
  in
  let print_dvar_dpred = function
    | DeclFun (id, _, [], t) ->
	fprintf fmt "@[logic %a : -> %a@]@\n@\n" ident id print_typ t
    | DeclFun (id, _, l, t) ->
	fprintf fmt "@[logic %a : %a -> %a@]@\n@\n"
	  ident id (print_list comma print_typ) l print_typ t
    | DeclPred (id, _, []) when not (List.mem_assoc id defined_preds) ->
	fprintf fmt "@[logic %a : -> prop @]@\n@\n" ident id
    | DeclPred (id, _, l) when not (List.mem_assoc id defined_preds) ->
	fprintf fmt "@[logic %a : %a -> prop@]@\n@\n"
	  ident id (print_list comma print_typ) l
    | DeclType _ | Axiom _ | DeclPred _ ->
	()
  in
  let print_assert = function
    | Axiom(id,_) when List.mem_assoc id defined_preds ->
        let args, def = List.assoc id defined_preds in
        fprintf fmt "@[predicate %a(%a) =@\n%a@]@\n" ident id
          (print_list comma print_arg) args print_predicate def  
    | Axiom (id, f)  ->
	fprintf fmt "@[<hov 2>axiom %a:@ %a@]@\n@\n" ident id print_predicate f
    | DeclType _ | DeclFun _ | DeclPred _ ->
	()
  in
  List.iter print_dtype decls;
  List.iter print_dvar_dpred decls;
  List.iter print_assert decls;
  fprintf fmt "@[<hov 2>goal coq___goal: %a@]" print_predicate concl

let output_file f q =
  let c = open_out f in
  let fmt = formatter_of_out_channel c in
  fprintf fmt "include \"real.why\"@.";
  fprintf fmt "@[%a@]@." print_query q;
  close_out c