summaryrefslogtreecommitdiff
path: root/contrib/dp/dp_why.ml
blob: e24049ad6a8e75f87f677c0635c7601c34b7491b (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

(* 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 (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 rec print_term fmt = function
  | Cst n -> 
      fprintf fmt "%d" 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
  | 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 print_query fmt (decls,concl) =
  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, _, []) ->
	fprintf fmt "@[logic %a : -> prop @]@\n@\n" ident id
    | DeclPred (id, _, l) -> 
	fprintf fmt "@[logic %a : %a -> prop@]@\n@\n" 
	  ident id (print_list comma print_typ) l
    | DeclType _ | Axiom _ ->
	()
  in
  let print_assert = function
    | 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 "@[%a@]@." print_query q;
  close_out c