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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
open Ast
open Ast_util
open PPrint
let doc_op symb a b = infix 2 1 symb a b
let doc_id (Id_aux (id_aux, _)) =
string (match id_aux with
| Id v -> v
| DeIid op -> "operator " ^ op)
let doc_kid kid = string (Ast_util.string_of_kid kid)
let doc_int n = string (string_of_int n)
let doc_ord (Ord_aux(o,_)) = match o with
| Ord_var v -> doc_kid v
| Ord_inc -> string "inc"
| Ord_dec -> string "dec"
let rec doc_nexp =
let rec atomic_nexp (Nexp_aux (n_aux, _) as nexp) =
match n_aux with
| Nexp_constant c -> string (string_of_int c)
| Nexp_id id -> doc_id id
| Nexp_var kid -> doc_kid kid
| _ -> parens (nexp0 nexp)
and nexp0 (Nexp_aux (n_aux, _) as nexp) =
match n_aux with
| Nexp_sum (n1, Nexp_aux (Nexp_neg n2, _)) | Nexp_minus (n1, n2) ->
separate space [nexp0 n1; string "-"; nexp1 n2]
| Nexp_sum (n1, Nexp_aux (Nexp_constant c, _)) when c < 0 ->
separate space [nexp0 n1; string "-"; doc_int (abs c)]
| Nexp_sum (n1, n2) -> separate space [nexp0 n1; string "+"; nexp1 n2]
| _ -> nexp1 nexp
and nexp1 (Nexp_aux (n_aux, _) as nexp) =
match n_aux with
| Nexp_times (n1, n2) -> separate space [nexp1 n1; string "*"; nexp2 n2]
| _ -> nexp2 nexp
and nexp2 (Nexp_aux (n_aux, _) as nexp) =
match n_aux with
| Nexp_neg n -> separate space [string "-"; atomic_nexp n]
| Nexp_exp n -> separate space [string "2"; string "^"; atomic_nexp n]
| _ -> atomic_nexp nexp
in
nexp0
let doc_nc =
let nc_op op n1 n2 = separate space [doc_nexp n1; string op; doc_nexp n2] in
let rec atomic_nc (NC_aux (nc_aux, _) as nc) =
match nc_aux with
| NC_true -> string "true"
| NC_false -> string "false"
| NC_equal (n1, n2) -> nc_op "=" n1 n2
| NC_not_equal (n1, n2) -> nc_op "!=" n1 n2
| NC_bounded_ge (n1, n2) -> nc_op ">=" n1 n2
| NC_bounded_le (n1, n2) -> nc_op "<=" n1 n2
| NC_set (kid, ints) ->
separate space [doc_kid kid; string "in"; braces (separate_map (comma ^^ space) doc_int ints)]
| _ -> parens (nc0 nc)
and nc0 (NC_aux (nc_aux, _) as nc) =
match nc_aux with
| NC_or (c1, c2) -> separate space [nc0 c1; string "|"; nc1 c2]
| _ -> nc1 nc
and nc1 (NC_aux (nc_aux, _) as nc) =
match nc_aux with
| NC_and (c1, c2) -> separate space [nc1 c1; string "&"; atomic_nc c2]
| _ -> atomic_nc nc
in
nc0
let rec doc_typ (Typ_aux (typ_aux, _)) =
match typ_aux with
| Typ_id id -> doc_id id
| Typ_app (id, []) -> doc_id id
| Typ_app (Id_aux (DeIid str, _), [x; y]) ->
separate space [doc_typ_arg x; doc_typ_arg y]
(*
| Typ_app (id, [_; len; _; Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id tid, _)), _)]) when Id.compare (mk_id "vector") id == 0 && Id.compare (mk_id "bit") tid == 0->
string "bits" ^^ parens (doc_typ_arg len)
*)
| Typ_app (id, typs) -> doc_id id ^^ parens (separate_map (string ", ") doc_typ_arg typs)
| Typ_tup typs -> parens (separate_map (string ", ") doc_typ typs)
| Typ_var kid -> doc_kid kid
| Typ_wild -> assert false
(* Resugar set types like {|1, 2, 3|} *)
| Typ_exist ([kid1], NC_aux (NC_set (kid2, ints), _), Typ_aux (Typ_app (id, [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid3, _)), _)]), _))
when Kid.compare kid1 kid2 == 0 && Kid.compare kid2 kid3 == 0 && Id.compare (mk_id "atom") id == 0 ->
enclose (string "{|") (string "|}") (separate_map (string ", ") doc_int ints)
| Typ_exist (kids, nc, typ) ->
braces (separate_map space doc_kid kids ^^ comma ^^ space ^^ doc_nc nc ^^ dot ^^ space ^^ doc_typ typ)
| Typ_fn (typ1, typ2, Effect_aux (Effect_set [], _)) ->
separate space [doc_typ typ1; string "->"; doc_typ typ2]
| Typ_fn (typ1, typ2, Effect_aux (Effect_set effs, _)) ->
let ocaml_eff = braces (separate (comma ^^ space) (List.map (fun be -> string (string_of_base_effect be)) effs)) in
separate space [doc_typ typ1; string "->"; doc_typ typ2; string "effect"; ocaml_eff]
and doc_typ_arg (Typ_arg_aux (ta_aux, _)) =
match ta_aux with
| Typ_arg_typ typ -> doc_typ typ
| Typ_arg_nexp nexp -> doc_nexp nexp
| Typ_arg_order o -> doc_ord o
let doc_quants quants =
let doc_qi_kopt (QI_aux (qi_aux, _)) =
match qi_aux with
| QI_id (KOpt_aux (KOpt_none kid, _)) -> [doc_kid kid]
| QI_id kopt when is_nat_kopt kopt -> [parens (separate space [doc_kid (kopt_kid kopt); colon; string "Int"])]
| QI_id kopt when is_typ_kopt kopt -> [parens (separate space [doc_kid (kopt_kid kopt); colon; string "Type"])]
| QI_id kopt when is_order_kopt kopt -> [parens (separate space [doc_kid (kopt_kid kopt); colon; string "Order"])]
| QI_const nc -> []
in
let qi_nc (QI_aux (qi_aux, _)) =
match qi_aux with
| QI_const nc -> [nc]
| _ -> []
in
let kdoc = separate space (List.concat (List.map doc_qi_kopt quants)) in
let ncs = List.concat (List.map qi_nc quants) in
match ncs with
| [] -> kdoc
| [nc] -> kdoc ^^ comma ^^ space ^^ doc_nc nc
| nc :: ncs -> kdoc ^^ comma ^^ space ^^ doc_nc (List.fold_left nc_and nc ncs)
let doc_typschm (TypSchm_aux (TypSchm_ts (TypQ_aux (tq_aux, _), typ), _)) =
match tq_aux with
| TypQ_no_forall -> doc_typ typ
| TypQ_tq [] -> doc_typ typ
| TypQ_tq qs ->
string "forall" ^^ space ^^ doc_quants qs ^^ dot ^//^ doc_typ typ
let doc_typschm_typ (TypSchm_aux (TypSchm_ts (TypQ_aux (tq_aux, _), typ), _)) = doc_typ typ
let doc_typschm_quants (TypSchm_aux (TypSchm_ts (TypQ_aux (tq_aux, _), typ), _)) =
match tq_aux with
| TypQ_no_forall -> None
| TypQ_tq [] -> None
| TypQ_tq qs -> Some (doc_quants qs)
let doc_lit (L_aux(l,_)) =
utf8string (match l with
| L_unit -> "()"
| L_zero -> "bitzero"
| L_one -> "bitone"
| L_true -> "true"
| L_false -> "false"
| L_num i -> string_of_int i
| L_hex n -> "0x" ^ n
| L_bin n -> "0b" ^ n
| L_real r -> r
| L_undef -> "undefined"
| L_string s -> "\"" ^ String.escaped s ^ "\"")
let rec doc_pat (P_aux (p_aux, _) as pat) =
match p_aux with
| P_id id -> doc_id id
| P_tup pats -> lparen ^^ separate_map (comma ^^ space) doc_pat pats ^^ rparen
| P_app (id, pats) -> doc_id id ^^ lparen ^^ separate_map (comma ^^ space) doc_pat pats ^^ rparen
| P_typ (typ, pat) -> separate space [doc_pat pat; colon; doc_typ typ]
| P_lit lit -> doc_lit lit
(* P_var short form sugar *)
| P_var (P_aux (P_id id, _), kid) when Id.compare (id_of_kid kid) id == 0 ->
doc_kid kid
| P_var (pat, kid) -> separate space [doc_pat pat; string "as"; doc_kid kid]
| P_vector pats -> brackets (separate_map (comma ^^ space) doc_pat pats)
| P_vector_concat pats -> separate_map (space ^^ string "@" ^^ space) doc_pat pats
| P_wild -> string "_"
| P_as (pat, id) -> separate space [doc_pat pat; string "as"; doc_id id]
| P_app (id, pats) -> doc_id id ^^ parens (separate_map (comma ^^ space) doc_pat pats)
| _ -> string (string_of_pat pat)
let rec doc_exp (E_aux (e_aux, _) as exp) =
match e_aux with
| E_block [exp] -> doc_exp exp
| E_block exps -> surround 2 0 lbrace (doc_block exps) rbrace
| E_nondet exps -> assert false
(* This is mostly for the -convert option *)
| E_app_infix (x, id, y) when Id.compare (mk_id "quot") id == 0 ->
separate space [doc_atomic_exp x; string "/"; doc_atomic_exp y]
| E_app_infix (x, id, y) -> separate space [doc_atomic_exp x; doc_id id; doc_atomic_exp y]
| E_tuple exps -> parens (separate_map (comma ^^ space) doc_exp exps)
| E_if (if_exp, then_exp, else_exp) ->
group (separate space [string "if"; doc_exp if_exp; string "then"; doc_exp then_exp; string "else"; doc_exp else_exp])
| E_list exps -> string "E_list"
| E_cons (exp1, exp2) -> string "E_cons"
| E_record fexps -> string "E_record"
| E_loop (While, cond, exp) ->
separate space [string "while"; doc_exp cond; string "do"; doc_exp exp]
| E_loop (Until, cond, exp) ->
separate space [string "repeat"; doc_exp exp; string "until"; doc_exp cond]
| E_record_update (exp, fexps) -> string "E_record_update"
| E_vector_append (exp1, exp2) -> separate space [doc_atomic_exp exp1; string "@"; doc_atomic_exp exp2]
| E_case (exp, pexps) ->
separate space [string "match"; doc_exp exp; doc_pexps pexps]
| E_let (LB_aux (LB_val (pat, binding), _), exp) ->
separate space [string "let"; doc_pat pat; equals; doc_exp binding; string "in"; doc_exp exp]
| E_assign (lexp, exp) ->
separate space [doc_lexp lexp; equals; doc_exp exp]
| E_for (id, exp1, exp2, exp3, order, exp4) ->
begin
let header =
string "foreach" ^^ space ^^
group (parens (separate (break 1)
[ doc_id id;
string "from " ^^ doc_atomic_exp exp1;
string "to " ^^ doc_atomic_exp exp2;
string "by " ^^ doc_atomic_exp exp3;
string "in " ^^ doc_ord order ]))
in
match exp4 with
| E_aux (E_block [_], _) -> header ^//^ doc_exp exp4
| E_aux (E_block _, _) -> header ^^ space ^^ doc_exp exp4
| _ -> header ^//^ doc_exp exp4
end
(* Resugar an assert with an empty message *)
| E_throw exp -> assert false
| E_try (exp, pexps) -> assert false
| E_return exp -> string "return" ^^ parens (doc_exp exp)
| E_app (id, [exp]) when Id.compare (mk_id "pow2") id == 0 ->
separate space [doc_int 2; string "^"; doc_atomic_exp exp]
| _ -> doc_atomic_exp exp
and doc_atomic_exp (E_aux (e_aux, _) as exp) =
match e_aux with
| E_cast (typ, exp) ->
separate space [doc_atomic_exp exp; colon; doc_typ typ]
| E_lit lit -> doc_lit lit
| E_id id -> doc_id id
| E_field (exp, id) -> doc_atomic_exp exp ^^ dot ^^ doc_id id
| E_sizeof (Nexp_aux (Nexp_var kid, _)) -> doc_kid kid
| E_sizeof nexp -> string "sizeof" ^^ parens (doc_nexp nexp)
(* Format a function with a unit argument as f() rather than f(()) *)
| E_app (id, [E_aux (E_lit (L_aux (L_unit, _)), _)]) -> doc_id id ^^ string "()"
| E_app (id, exps) -> doc_id id ^^ parens (separate_map (comma ^^ space) doc_exp exps)
| E_constraint nc -> string "constraint" ^^ parens (doc_nc nc)
| E_assert (exp1, E_aux (E_lit (L_aux (L_string "", _)), _)) -> string "assert" ^^ parens (doc_exp exp1)
| E_assert (exp1, exp2) -> string "assert" ^^ parens (doc_exp exp1 ^^ comma ^^ space ^^ doc_exp exp2)
| E_exit exp -> string "exit" ^^ parens (doc_exp exp)
| E_vector_access (exp1, exp2) -> doc_atomic_exp exp1 ^^ brackets (doc_exp exp2)
| E_vector_subrange (exp1, exp2, exp3) -> doc_atomic_exp exp1 ^^ brackets (separate space [doc_exp exp2; string ".."; doc_exp exp3])
| E_vector exps -> brackets (separate_map (comma ^^ space) doc_exp exps)
| E_vector_update (exp1, exp2, exp3) ->
brackets (separate space [doc_exp exp1; string "with"; doc_atomic_exp exp2; equals; doc_exp exp3])
| E_vector_update_subrange (exp1, exp2, exp3, exp4) ->
brackets (separate space [doc_exp exp1; string "with"; doc_atomic_exp exp2; string ".."; doc_atomic_exp exp3; equals; doc_exp exp4])
| _ -> parens (doc_exp exp)
and doc_block = function
| [] -> string "()"
| [E_aux (E_let (LB_aux (LB_val (pat, binding), _), E_aux (E_block exps, _)), _)] ->
separate space [string "let"; doc_pat pat; equals; doc_exp binding] ^^ semi ^^ hardline ^^ doc_block exps
| [exp] -> doc_exp exp
| exp :: exps -> doc_exp exp ^^ semi ^^ hardline ^^ doc_block exps
and doc_lexp (LEXP_aux (l_aux, _) as lexp) =
match l_aux with
| LEXP_cast (typ, id) -> separate space [doc_id id; colon; doc_typ typ]
| _ -> doc_atomic_lexp lexp
and doc_atomic_lexp (LEXP_aux (l_aux, _) as lexp) =
match l_aux with
| LEXP_id id -> doc_id id
| LEXP_tup lexps -> lparen ^^ separate_map (comma ^^ space) doc_lexp lexps ^^ rparen
| LEXP_field (lexp, id) -> doc_atomic_lexp lexp ^^ dot ^^ doc_id id
| LEXP_vector (lexp, exp) -> doc_atomic_lexp lexp ^^ brackets (doc_exp exp)
| LEXP_vector_range (lexp, exp1, exp2) -> doc_atomic_lexp lexp ^^ brackets (separate space [doc_exp exp1; string ".."; doc_exp exp2])
| LEXP_memory (id, exps) -> doc_id id ^^ parens (separate_map (comma ^^ space) doc_exp exps)
| _ -> parens (doc_lexp lexp)
and doc_pexps pexps = surround 2 0 lbrace (separate_map (comma ^^ hardline) doc_pexp pexps) rbrace
and doc_pexp (Pat_aux (pat_aux, _)) =
match pat_aux with
| Pat_exp (pat, exp) -> separate space [doc_pat pat; string "=>"; doc_exp exp]
| Pat_when (pat, wh, exp) ->
separate space [doc_pat pat; string "if"; doc_exp wh; string "=>"; doc_exp exp]
and doc_letbind (LB_aux (lb_aux, _)) =
match lb_aux with
| LB_val (pat, exp) ->
separate space [doc_pat pat; equals; doc_exp exp]
let doc_funcl funcl = string "FUNCL"
let doc_funcl (FCL_aux (FCL_Funcl (id, pat, exp), _)) =
group (separate space [doc_id id; doc_pat pat; equals; doc_exp exp])
let doc_default (DT_aux(df,_)) = match df with
| DT_kind(bk,v) -> string "DT_kind" (* separate space [string "default"; doc_bkind bk; doc_var v] *)
| DT_typ(ts,id) -> separate space [string "default"; doc_typschm ts; doc_id id]
| DT_order(ord) -> separate space [string "default"; string "Order"; doc_ord ord]
let doc_fundef (FD_aux (FD_function (r, typa, efa, funcls), _)) =
match funcls with
| [] -> failwith "Empty function list"
| _ ->
let sep = hardline ^^ string "and" ^^ space in
let clauses = separate_map sep doc_funcl funcls in
string "function" ^^ space ^^ clauses
let doc_dec (DEC_aux (reg,_)) =
match reg with
| DEC_reg (typ, id) -> separate space [string "register"; doc_id id; colon; doc_typ typ]
| DEC_alias(id,alspec) -> string "ALIAS"
| DEC_typ_alias(typ,id,alspec) -> string "ALIAS"
let doc_field (typ, id) =
separate space [doc_id id; colon; doc_typ typ]
let doc_typdef (TD_aux(td,_)) = match td with
| TD_abbrev (id, _, typschm) ->
begin
match doc_typschm_quants typschm with
| Some qdoc ->
doc_op equals (concat [string "type"; space; doc_id id; space; qdoc]) (doc_typschm_typ typschm)
| None ->
doc_op equals (concat [string "type"; space; doc_id id]) (doc_typschm_typ typschm)
end
| TD_enum (id, _, ids, _) ->
separate space [string "enum"; doc_id id; equals; surround 2 0 lbrace (separate_map (comma ^^ break 1) doc_id ids) rbrace]
| TD_record (id, _, TypQ_aux (TypQ_no_forall, _), fields, _) | TD_record (id, _, TypQ_aux (TypQ_tq [], _), fields, _) ->
separate space [string "struct"; doc_id id; equals; surround 2 0 lbrace (separate_map (comma ^^ break 1) doc_field fields) rbrace]
| TD_record (id, _, TypQ_aux (TypQ_tq qs, _), fields, _) ->
separate space [string "struct"; doc_id id; doc_quants qs; equals;
surround 2 0 lbrace (separate_map (comma ^^ break 1) doc_field fields) rbrace]
| _ -> string "TYPEDEF"
let doc_spec (VS_aux(v,_)) =
let doc_extern = function
| Some s -> equals ^^ space ^^ utf8string ("\"" ^ String.escaped s ^ "\"") ^^ space
| None -> empty
in
match v with
| VS_val_spec(ts,id,ext,is_cast) ->
string "val" ^^ space
^^ (if is_cast then (string "cast" ^^ space) else empty)
^^ doc_id id ^^ space
^^ doc_extern ext
^^ colon ^^ space
^^ doc_typschm ts
let doc_prec = function
| Infix -> string "infix"
| InfixL -> string "infixl"
| InfixR -> string "infixr"
let doc_kind_def (KD_aux (KD_nabbrev (_, id, _, nexp), _)) =
separate space [string "integer"; doc_id id; equals; doc_nexp nexp]
let rec doc_scattered (SD_aux (sd_aux, _)) =
match sd_aux with
| SD_scattered_function (_, _, _, id) ->
string "scattered" ^^ space ^^ string "function" ^^ space ^^ doc_id id
| SD_scattered_funcl funcl ->
string "function" ^^ space ^^ string "clause" ^^ space ^^ doc_funcl funcl
| SD_scattered_end id ->
string "end" ^^ space ^^ doc_id id
| _ -> string "SCATTERED"
let rec doc_def def = group (match def with
| DEF_default df -> doc_default df
| DEF_spec v_spec -> doc_spec v_spec
| DEF_type t_def -> doc_typdef t_def
| DEF_kind k_def -> doc_kind_def k_def
| DEF_fundef f_def -> doc_fundef f_def
| DEF_val lbind -> string "let" ^^ space ^^ doc_letbind lbind
| DEF_reg_dec dec -> doc_dec dec
| DEF_scattered sdef -> doc_scattered sdef
| DEF_fixity (prec, n, id) ->
separate space [doc_prec prec; doc_int n; doc_id id]
| DEF_overload (id, ids) ->
separate space [string "overload"; doc_id id; equals; surround 2 0 lbrace (separate_map (comma ^^ break 1) doc_id ids) rbrace]
| DEF_comm (DC_comm s) -> string "TOPLEVEL"
| DEF_comm (DC_comm_struct d) -> string "TOPLEVEL"
) ^^ hardline
let doc_defs (Defs(defs)) =
separate_map hardline doc_def defs
let pp_defs f d = ToChannel.pretty 1. 80 f (doc_defs d)
|