-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathprintpat.ml
169 lines (152 loc) · 5.91 KB
/
printpat.ml
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
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(* Values as patterns pretty printer *)
open Asttypes
open Typedtree
open Types
open Format
let is_cons = function
| {cstr_name = "::"} -> true
| _ -> false
let pretty_const c = match c with
| Const_int i -> Printf.sprintf "%d" i
| Const_char c -> Printf.sprintf "%C" c
| Const_string (s, _, _) -> Printf.sprintf "%S" s
| Const_float f -> Printf.sprintf "%s" f
| Const_int32 i -> Printf.sprintf "%ldl" i
| Const_int64 i -> Printf.sprintf "%LdL" i
| Const_nativeint i -> Printf.sprintf "%ndn" i
let pretty_extra ppf (cstr, _loc, _attrs) pretty_rest rest =
match cstr with
| Tpat_unpack ->
fprintf ppf "@[(module %a)@]" pretty_rest rest
| Tpat_constraint _ ->
fprintf ppf "@[(%a : _)@]" pretty_rest rest
| Tpat_type _ ->
fprintf ppf "@[(# %a)@]" pretty_rest rest
| Tpat_open _ ->
fprintf ppf "@[(# %a)@]" pretty_rest rest
let rec pretty_val : type k . _ -> k general_pattern -> _ = fun ppf v ->
match v.pat_extra with
| extra :: rem ->
pretty_extra ppf extra
pretty_val { v with pat_extra = rem }
| [] ->
match v.pat_desc with
| Tpat_any -> fprintf ppf "_"
| Tpat_var (x,_) -> fprintf ppf "%s" (Ident.name x)
| Tpat_constant c -> fprintf ppf "%s" (pretty_const c)
| Tpat_tuple vs ->
fprintf ppf "@[(%a)@]" (pretty_vals ",") vs
| Tpat_construct (_, cstr, [], _) ->
fprintf ppf "%s" cstr.cstr_name
| Tpat_construct (_, cstr, [w], None) ->
fprintf ppf "@[<2>%s@ %a@]" cstr.cstr_name pretty_arg w
| Tpat_construct (_, cstr, vs, vto) ->
let name = cstr.cstr_name in
begin match (name, vs, vto) with
("::", [v1;v2], None) ->
fprintf ppf "@[%a::@,%a@]" pretty_car v1 pretty_cdr v2
| (_, _, None) ->
fprintf ppf "@[<2>%s@ @[(%a)@]@]" name (pretty_vals ",") vs
| (_, _, Some ([], _t)) ->
fprintf ppf "@[<2>%s@ @[(%a : _)@]@]" name (pretty_vals ",") vs
| (_, _, Some (vl, _t)) ->
let vars = List.map (fun x -> Ident.name x.txt) vl in
fprintf ppf "@[<2>%s@ (type %s)@ @[(%a : _)@]@]"
name (String.concat " " vars) (pretty_vals ",") vs
end
| Tpat_variant (l, None, _) ->
fprintf ppf "`%s" l
| Tpat_variant (l, Some w, _) ->
fprintf ppf "@[<2>`%s@ %a@]" l pretty_arg w
| Tpat_record (lvs,_) ->
let filtered_lvs = List.filter
(function
| (_,_,{pat_desc=Tpat_any}) -> false (* do not show lbl=_ *)
| _ -> true) lvs in
begin match filtered_lvs with
| [] -> fprintf ppf "_"
| (_, lbl, _) :: q ->
let elision_mark ppf =
(* we assume that there is no label repetitions here *)
if Array.length lbl.lbl_all > 1 + List.length q then
fprintf ppf ";@ _@ "
else () in
fprintf ppf "@[{%a%t}@]"
pretty_lvals filtered_lvs elision_mark
end
| Tpat_array vs ->
fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs
| Tpat_lazy v ->
fprintf ppf "@[<2>lazy@ %a@]" pretty_arg v
| Tpat_alias (v, x,_) ->
fprintf ppf "@[(%a@ as %a)@]" pretty_val v Ident.print x
| Tpat_value v ->
fprintf ppf "%a" pretty_val (v :> pattern)
| Tpat_exception v ->
fprintf ppf "@[<2>exception@ %a@]" pretty_arg v
| Tpat_or _ ->
fprintf ppf "@[(%a)@]" pretty_or v
and pretty_car ppf v = match v.pat_desc with
| Tpat_construct (_,cstr, [_ ; _], None)
when is_cons cstr ->
fprintf ppf "(%a)" pretty_val v
| _ -> pretty_val ppf v
and pretty_cdr ppf v = match v.pat_desc with
| Tpat_construct (_,cstr, [v1 ; v2], None)
when is_cons cstr ->
fprintf ppf "%a::@,%a" pretty_car v1 pretty_cdr v2
| _ -> pretty_val ppf v
and pretty_arg ppf v = match v.pat_desc with
| Tpat_construct (_,_,_::_,None)
| Tpat_variant (_, Some _, _) -> fprintf ppf "(%a)" pretty_val v
| _ -> pretty_val ppf v
and pretty_or : type k . _ -> k general_pattern -> _ = fun ppf v ->
match v.pat_desc with
| Tpat_or (v,w,_) ->
fprintf ppf "%a|@,%a" pretty_or v pretty_or w
| _ -> pretty_val ppf v
and pretty_vals sep ppf = function
| [] -> ()
| [v] -> pretty_val ppf v
| v::vs ->
fprintf ppf "%a%s@ %a" pretty_val v sep (pretty_vals sep) vs
and pretty_lvals ppf = function
| [] -> ()
| [_,lbl,v] ->
fprintf ppf "%s=%a" lbl.lbl_name pretty_val v
| (_, lbl,v)::rest ->
fprintf ppf "%s=%a;@ %a"
lbl.lbl_name pretty_val v pretty_lvals rest
let top_pretty ppf v =
fprintf ppf "@[%a@]@?" pretty_val v
let pretty_pat p =
top_pretty Format.str_formatter p ;
prerr_string (Format.flush_str_formatter ())
type 'k matrix = 'k general_pattern list list
let pretty_line fmt =
List.iter (fun p ->
Format.fprintf fmt " <";
top_pretty fmt p;
Format.fprintf fmt ">";
)
let pretty_matrix fmt (pss : 'k matrix) =
Format.fprintf fmt "begin matrix\n" ;
List.iter (fun ps ->
pretty_line fmt ps ;
Format.fprintf fmt "\n"
) pss;
Format.fprintf fmt "end matrix\n%!"