File: coma_syntax.ml

package info (click to toggle)
why3 1.8.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,028 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (256 lines) | stat: -rw-r--r-- 9,835 bytes parent folder | download
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
(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2025 --  Inria - CNRS - Paris-Saclay University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(********************************************************************)

open Why3
open Ptree

type pvar = ident * term * pty * bool

type pparam =
  | PPt of ident        (* <'a> *)
  | PPv of ident * pty  (* x *)
  | PPr of ident * pty  (* &r *)
  | PPc of ident * ident list * pparam list (* x [x...] p... *)
  | PPa of term * bool  (* {f} or <{f}> -- precondition (assumed) *)
  | PPo                 (* {..} -- open spec (no barrier) *)
  | PPb                 (* {} -- empty precondition (barrier) *)
  | PPl of pvar list    (* [v = t | u = s] -- spec-local let *)

type pexpr = {
  pexpr_desc : pexpr_desc;
  pexpr_loc  : Loc.position;
}

and pexpr_desc =
  | PEsym of qualid (* x *)
  | PEapp of pexpr * pargument (* e <ty>... t... | e... *)
  | PElam of pparam list * pexpr (* fun pl -> e *)
  | PEdef of pexpr * bool * pdefn list (* e / rec? h p = e and ... *)
  | PEset of pexpr * (ident * term) list
  | PElet of pexpr * pvar list
  | PEcut of (term * bool) list * pexpr (* { t } e *)
  | PEbox of pexpr (* ! e *)
  | PEwox of pexpr (* ? e *)
  | PEany (* any *)

and pargument =
  | PAt of pty (* < ty > *)
  | PAv of term (* t *)
  | PAr of ident (* &r *)
  | PAc of pexpr (* (e) *)

and pdefn = {
  pdefn_desc   : pdefn_desc;
  pdefn_loc    : Loc.position;
}

and pdefn_desc = {
  pdefn_name   : ident;
  pdefn_writes : ident list;
  pdefn_params : pparam list;
  pdefn_body   : pexpr;
}

type use =
  | Puseexport of qualid
  | Puseimport of bool * qualid * ident option

type pdecl =
  | Blo of pdefn list
  | Mlw of Ptree.decl
  | Use of use

type pfile = (ident * pdecl list) list

(* typed ast printer *)
module PP = struct
  open Format
  open Coma_logic

  let pr = Ident.create_ident_printer []

  let pp_osp    fmt c      = if c then fprintf fmt " "
  let pp_sp_nl2 fmt ()     = pp_print_break fmt 1 2

  let pp_tv   fmt t = fprintf fmt "<%a>"        Pretty.print_tv t
  let pp_ty   fmt t = fprintf fmt "<%a>"        Pretty.print_ty t
  let pp_hs   fmt h = fprintf fmt "%s"          (Ident.id_unique pr h.hs_name)
  let pp_term fmt t = fprintf fmt "{%a}"        Pretty.print_term t
  let pp_ofty fmt t = fprintf fmt ": @[%a@]" Pretty.print_ty t
  let pp_pval fmt v = fprintf fmt "{%a%a}"      Pretty.print_vs v pp_ofty v.Term.vs_ty
  let pp_var mut fmt v = fprintf fmt "%s%a"     (if mut then "&" else "") Pretty.print_vs v

  let rec pp_hdl fmt (i, w, pl) = fprintf fmt "(%a @[<h>[%a]@]%a%a)" pp_hs i pp_prew w pp_osp (pl <> []) pp_prms pl

  and pp_prew fmt w =
    let pp_sep fmt () = fprintf fmt " " in
    let pp_v fmt s = fprintf fmt "%a" Pretty.print_vs s in
    pp_print_list ~pp_sep pp_v fmt w

  and pp_prms fmt pl =
    let pp_sep fmt () = fprintf fmt " " in
    pp_print_list ~pp_sep pp_param fmt pl

  and pp_param fmt = function
    | Pt t -> fprintf fmt "%a"  pp_tv        t
    | Pv v -> fprintf fmt "%a"  pp_pval      v
    | Pr r -> fprintf fmt "%a" (pp_var true) r
    | Pc (h,l,p) -> fprintf fmt "%a"  pp_hdl (h,l,p)

  let pp_set fmt sl =
    let pp_sep fmt () = fprintf fmt "@ |" in
    let pp_v fmt (s, t) = fprintf fmt "@ %a <-@ %a" (pp_var true) s pp_term t in
    pp_print_list ~pp_sep pp_v fmt sl

  let pp_let fmt sl =
    let pp_sep fmt () = fprintf fmt "@ |" in
    let pp_v fmt (s, t, mut) = fprintf fmt "@ %a =@ %a" (pp_var mut) s pp_term t in
    pp_print_list ~pp_sep pp_v fmt sl

  let pp_annot b fmt f =
    if b then pp_term fmt f else fprintf fmt "-%a-" pp_term f

(*
  let rec pp_fmla fmt = function
    | Fsym i         -> fprintf fmt "%a"             pp_hs i
    | Fneu (e, _)    -> fprintf fmt "(↑@ @[%a@])"    pp_fmla e
    | Fagt (e, _)    -> fprintf fmt "@[%a%a@[<_>@]@]" pp_fmla e pp_sp_nl2 ()
    | Fagv (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_fmla e pp_sp_nl2 () pp_term arg
    | Fagr (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_fmla e pp_sp_nl2 () (pp_var true) arg
    | Fagc (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_fmla e pp_sp_nl2 () pp_fmla arg
    | Fand (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_fmla e pp_sp_nl2 () pp_fmla arg
    | Fcut (t, b, e) -> fprintf fmt "%a@ %a"         (pp_annot b) t pp_fmla e
    | Flam (p, _, e) -> fprintf fmt "(fu@[n %a%a→@ @[%a@]@])" pp_prms p pp_osp (p <> []) pp_fmla e
    | Fall (p, e)    -> fprintf fmt "(al@[l %a%a→@ @[%a@]@])" pp_prms p pp_osp (p <> []) pp_fmla e
*)

  let rec pp_expr fmt = function
    | Eany           -> fprintf fmt "any"
    | Esym i         -> fprintf fmt "%a"             pp_hs i
    | Ebox e         -> fprintf fmt "(↑@ @[%a@])"    pp_expr e
    | Ewox e         -> fprintf fmt "(↓@ @[%a@])"    pp_expr e
    | Eset (e, l)    -> fprintf fmt "%a@\n[%a]"      pp_expr e pp_set l
    | Elet (e, l)    -> fprintf fmt "%a@\n[%a]"      pp_expr e pp_let l
    | Eapp (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_expr e pp_sp_nl2 () pp_arg arg
    | Ecut (t, b, e) -> fprintf fmt "%a@ %a"         (pp_annot b) t pp_expr e
    | Edef (e, b, l) -> fprintf fmt "%a@\n[%a]"      pp_expr e (pp_local_defs_block b)  l
    | Elam (p, e)    -> fprintf fmt "(fu@[n %a%a→@ @[%a@]@])"  pp_prms p pp_osp (p <> []) pp_expr e

  and pp_arg fmt = function
    | At t        -> fprintf fmt "%a"   pp_ty  t
    | Av v        -> fprintf fmt "%a"   pp_term v
    | Ar r        -> fprintf fmt "%a"   (pp_var true) r
    | Ac (Esym i) -> fprintf fmt "%a"   pp_hs i
    | Ac e        -> fprintf fmt "(%a)" pp_expr e

  and pp_def direct fmt (h, w, pl, e) =
    fprintf fmt "%a [%a] %a%a%s%a@[%a@]"
      pp_hs h
      pp_prew w
      pp_prms pl
      pp_osp (pl <> [])
      (if direct then "→" else "=")
      pp_sp_nl2 ()
      pp_expr e

  and pp_local_defs_block direct fmt l =
    let pp_sep fmt () = fprintf fmt "@\n|" in
    let pp_v fmt d = fprintf fmt " %a" (pp_def direct) d in
    pp_print_list ~pp_sep pp_v fmt l

  and pp_def_block fmt = function
    | [d] -> fprintf fmt "let %a" (pp_def false) d
    | l   ->
        let pp_sep fmt () = fprintf fmt "@\nwith " in
        let pp_v fmt d = fprintf fmt "%a" (pp_def false) d in
        pp_print_string fmt "let rec ";
        pp_print_list ~pp_sep pp_v fmt l
end

(* parsed ast printer *)
module PPp = struct
  open Format

  let pr = Ident.create_ident_printer []

  let pp_osp    fmt c      = if c then fprintf fmt " "
  let pp_sp_nl2 fmt ()     = pp_print_break fmt 1 2
  let pp_var mut fmt i = fprintf fmt "%s%s"     (if mut then "&" else "") i.id_str

  let pp_prew fmt w =
    let pp_sep fmt () = fprintf fmt " " in
    pp_print_list ~pp_sep pp_print_string fmt (List.map (fun e -> e.id_str) w)

  let rec pp_param fmt = function
    | PPt i
    | PPr (i,_)
    | PPv (i,_) -> fprintf fmt "%s" i.id_str
    | PPc (i, idl, pl) -> fprintf fmt "(%s [%a] %a)" i.id_str pp_prew idl (pp_print_list pp_param) pl
    | PPl _ -> pp_print_string fmt "[??]"
    | PPa (_,true) -> pp_print_string fmt "{??}"
    | PPa (_,false) -> pp_print_string fmt "-{??}-"
    | PPo -> pp_print_string fmt "{..}"
    | PPb -> pp_print_string fmt "{}"

  let pp_set fmt sl =
    let pp_sep fmt () = fprintf fmt "@ |" in
    let pp_v fmt (s, _t) = fprintf fmt "@ %a <-@ {}" (pp_var true) s in
    pp_print_list ~pp_sep pp_v fmt sl

  let pp_let fmt sl =
    let pp_sep fmt () = fprintf fmt "@ |" in
    let pp_v fmt (s, _, _, mut) = fprintf fmt "@ %a =@ {}" (pp_var mut) s in
    pp_print_list ~pp_sep pp_v fmt sl

  let pp_annot b fmt _f =
    pp_print_string fmt (if b then "assert {}" else "assume {}")

  let rec pp_expr fmt e = match e.pexpr_desc with
    | PEany           -> fprintf fmt "any"
    | PEsym q         -> fprintf fmt "%a"             Typing.print_qualid q
    | PEbox e         -> fprintf fmt "(↑@ @[%a@])"    pp_expr e
    | PEwox e         -> fprintf fmt "(↓@ @[%a@])"    pp_expr e
    | PEset (e, l)    -> fprintf fmt "%a@\n[%a]"      pp_expr e pp_set l
    | PElet (e, l)    -> fprintf fmt "%a@\n[%a]"      pp_expr e pp_let l
    | PEapp (e, arg)  -> fprintf fmt "@[%a%a@[%a@]@]" pp_expr e pp_sp_nl2 () pp_arg arg
    | PEcut (_, e)    -> fprintf fmt "assert/@ %a"    pp_expr e
    | PEdef (e, b, l) -> fprintf fmt "%a@\n[%a]"      pp_expr e (pp_local_defs_block b)  l
    | PElam (p, e)    -> fprintf fmt "(fu@[n %a%a→@ @[%a@]@])"  (pp_print_list pp_param) p pp_osp (p <> []) pp_expr e

  and pp_arg fmt = function
    | PAt _        -> fprintf fmt "<pty>"
    | PAv _        -> fprintf fmt "{}"
    | PAr r        -> fprintf fmt "%a"  (pp_var true) r
    | PAc e        -> fprintf fmt "(%a)" pp_expr e

  and pp_def direct fmt d =
    let { pdefn_name; pdefn_writes ; pdefn_params ; pdefn_body  } = d.pdefn_desc in
    fprintf fmt "%s [%a] %a%a%s%a@[%a@]"
      pdefn_name.id_str
      pp_prew pdefn_writes
      (pp_print_list pp_param) pdefn_params
      pp_osp (pdefn_params <> [])
      (if direct then "→" else "=")
      pp_sp_nl2 ()
      pp_expr pdefn_body

  and pp_local_defs_block direct fmt l =
    let pp_sep fmt () = fprintf fmt "@\n|" in
    let pp_v fmt d = fprintf fmt " %a" (pp_def direct) d in
    pp_print_list ~pp_sep pp_v fmt l

  and pp_def_block fmt = function
    | [d] -> fprintf fmt "let %a" (pp_def false) d
    | l   ->
        let pp_sep fmt () = fprintf fmt "@\nwith " in
        let pp_v fmt d = fprintf fmt "%a" (pp_def false) d in
        pp_print_string fmt "let rec ";
        pp_print_list ~pp_sep pp_v fmt l
end