3 Copyright (C) 2002,2001 Justin David Smith, Caltech
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 (*** Basic Printers ***)
31 Print out a pragma definition. This will inherit the box of the caller,
32 although line info pragmas will often significantly distort the boxes
34 let pp_print_pragma buf pragma
=
37 fprintf buf
"(* @[<v 0>";
38 pp_print_ocaml_block_text buf text
;
40 | LineInfo
(file_pos
, mark
) ->
41 pp_print_ocaml_line_break buf file_pos mark
44 (* pp_print_delim_space_list
45 Print a list of elements, separated by delim followed by print_space. *)
46 let pp_print_delim_space_list buf delim f ls
=
47 let fold_fun first l
=
49 fprintf buf
"%s@ " delim
;
53 ignore
(List.fold_left
fold_fun true ls
)
56 (* pp_print_space_delim_list
57 Print a list of elements, separated by print_space followed by delim.
58 This prints the delimiter and space in the opposite order of above... *)
59 let pp_print_space_delim_list buf delim f ls
=
60 let fold_fun first l
=
62 fprintf buf
"@ %s" delim
;
66 ignore
(List.fold_left
fold_fun true ls
)
69 (*** Atom Printing ***)
73 Determines the type of an atom expression, which is used to
74 determine if a child atom can be printed without explicit
75 parenthesization inside of a parent atom. *)
89 Returns true if an atom of type self can be printed within an
90 atom of type parent without explicit parenthesization around a. *)
91 let safe_atom parent self
=
92 match parent
, self
with
94 (* Dot expressions bind very tightly *)
95 | (ATDot
| ATBinop _
| ATList
| ATListCons
| ATTuple
| ATConst
| ATFuncall
), ATDot
96 (* Binary operators must consider precedence *)
97 | ATBinop BAndOp
, ATBinop BAndOp
98 | ATBinop BOrOp
, ATBinop BOrOp
99 | ATBinop
(BAndOp
| BOrOp
), ATBinop
(EqOp
| NEqOp
| LtOp
)
100 | ATBinop _
, ATFuncall
101 (* Structures which are permissible inside lists... *)
102 | (ATList
| ATListCons
| ATTuple
), (ATBinop _
| ATList
| ATFuncall
| ATConst
)
103 | ATList
, (ATListCons
| ATTuple
)
104 (* Tuples can contain lists (not vice versa) *)
105 | ATTuple
, ATListCons
106 (* Single-argument constructors are not parenthesized, so if we
107 have a constructor parent, we cannot accept arithmetic ops. *)
109 | ATFuncall
, ATList
->
112 (* Cases which are not safe *)
113 | ATDot
, (ATBinop _
| ATList
| ATListCons
| ATTuple
| ATConst
| ATFuncall
)
114 | ATBinop
(EqOp
| NEqOp
| LtOp
), ATBinop _
115 | ATBinop BAndOp
, ATBinop BOrOp
116 | ATBinop BOrOp
, ATBinop BAndOp
117 | ATBinop _
, (ATList
| ATListCons
| ATTuple
| ATConst
)
118 | ATListCons
, (ATListCons
| ATTuple
)
120 | ATConst
, (ATBinop _
| ATListCons
| ATTuple
| ATConst
| ATFuncall
)
121 | ATFuncall
, (ATBinop _
| ATListCons
| ATTuple
| ATConst
| ATFuncall
)
122 (* Don't know where I need to be strict about as *)
130 Print an infix binary operator. *)
131 let pp_print_binop buf op
=
146 Prints an atom. The parent indicates the type of the parent atom, and is
147 used to determine if this atom expression must be parenthesized. External
148 calls to pp_print_atom should use ATSafe for the parent type. *)
149 let rec pp_print_atom buf parent atom
=
150 let parens_if_unsafe self f
=
151 let not_safe = not
(safe_atom parent self
) in
153 pp_print_string buf
"(";
156 pp_print_string buf
")"
160 fprintf buf
"%s" (string_of_symbol v
)
166 fprintf buf
"%s" (string_of_int32 i
)
168 fprintf buf
"\"%s\"" (String.escaped s
)
169 | AtomDot
(a1
, a2
) ->
170 pp_print_atom buf ATDot a1
;
172 pp_print_atom buf ATDot a2
;
173 | AtomBinop
(op
, a1
, a2
) ->
174 parens_if_unsafe (ATBinop op
) (fun () ->
175 fprintf buf
"@[<hov 0>";
176 pp_print_atom buf
(ATBinop op
) a1
;
178 pp_print_binop buf op
;
180 pp_print_atom buf
(ATBinop op
) a2
;
183 fprintf buf
"[@[<hov 0>";
184 pp_print_delim_space_list buf
";" (fun buf
-> pp_print_atom buf ATList
) atoms
;
186 | AtomListCons
(atoms
, tl
) ->
187 parens_if_unsafe ATListCons
(fun () ->
188 fprintf buf
"@[<hv 0>";
189 pp_print_delim_space_list buf
" ::" (fun buf
-> pp_print_atom buf ATListCons
) (atoms
@ [tl
]);
192 parens_if_unsafe ATTuple
(fun () ->
193 fprintf buf
"@[<hov 0>";
194 pp_print_delim_space_list buf
"," (fun buf
-> pp_print_atom buf ATTuple
) atoms
;
196 | AtomStruct fields
->
197 fprintf buf
"{ @[<v 0>";
198 pp_print_delim_space_list buf
";" (fun buf
(field
, a
) ->
199 fprintf buf
"%s = " (string_of_symbol field
);
200 pp_print_atom buf ATSafe a
) fields
;
202 | AtomConst
(name
, atoms
) ->
206 fprintf buf
"%s" (string_of_symbol name
)
208 parens_if_unsafe ATConst
(fun () ->
209 fprintf buf
"@[<hov 3>%s" (string_of_symbol name
);
211 pp_print_atom buf ATConst atom
;
214 parens_if_unsafe ATConst
(fun () ->
215 fprintf buf
"@[<hov 3>%s" (string_of_symbol name
);
217 pp_print_delim_space_list buf
"," (fun buf
-> pp_print_atom buf ATConst
) atoms
;
220 | AtomAs
(a
, name
) ->
221 parens_if_unsafe ATAs
(fun () ->
222 fprintf buf
"@[<hov 0>";
223 pp_print_atom buf ATAs a
;
224 fprintf buf
"@ as %s@]" (string_of_symbol name
))
226 fprintf buf
"(@[<v -9999>";
227 pp_print_ocaml_block_text buf text
;
229 | AtomFuncall
(f
, atoms
) ->
230 parens_if_unsafe ATFuncall
(fun () ->
231 fprintf buf
"@[<hov 3>";
232 pp_print_atom buf ATFuncall f
;
235 pp_print_atom buf ATFuncall a
) atoms
;
237 | AtomPragma
(p
, a
) ->
238 fprintf buf
"@[<v 0>";
239 pp_print_pragma buf p
;
240 pp_print_atom buf parent a
;
244 (*** Expression/Statement Printers ***)
247 (* pp_print_match_cases
248 Print out the cases in a match statement. *)
249 let rec pp_print_match_cases buf cases
=
250 let pp_print_match_case buf
(pattern
, clause
, e
) =
251 fprintf buf
"@[<v 3>";
254 pp_print_atom buf ATSafe pattern
;
257 fprintf buf
"@[<v 0>";
258 pp_print_atom buf ATSafe pattern
;
259 fprintf buf
"@ @[<hv 3>when@ ";
260 pp_print_expression buf e
;
261 fprintf buf
"@]@ ->@]@ ");
262 pp_print_expression buf e
;
266 pp_print_space_delim_list buf
" | " pp_print_match_case cases
269 (* pp_print_expression
270 Print out an entire expression. This call may recurse. *)
271 and pp_print_expression buf expr
=
272 fprintf buf
"@[<v 0>";
275 pp_print_atom buf ATSafe a
277 fprintf buf
"raise (";
278 pp_print_atom buf ATSafe a
;
280 | LetIn
(v
, args
, e1
, e2
) ->
281 fprintf buf
"@[<hv 3>let@[<h>";
282 List.iter
(fun v
-> fprintf buf
"@ %s" (string_of_symbol v
)) (v
:: args
);
283 fprintf buf
"@] =@ ";
284 pp_print_expression buf e1
;
285 fprintf buf
" in@]@ ";
286 pp_print_expression buf e2
287 | LetRec
(v
, args
, e1
, e2
) ->
288 fprintf buf
"@[<hv 3>let rec@[<h>";
289 List.iter
(fun v
-> fprintf buf
"@ %s" (string_of_symbol v
)) (v
:: args
);
290 fprintf buf
"@] =@ ";
291 pp_print_expression buf e1
;
292 fprintf buf
" in@]@ ";
293 pp_print_expression buf e2
294 | Match
(a
, cases
) ->
295 fprintf buf
"@[<v 0>match ";
296 pp_print_atom buf ATSafe a
;
297 fprintf buf
" with@ ";
298 pp_print_match_cases buf cases
;
301 fprintf buf
"@[<v 0>@[<hov 3>if@ ";
302 pp_print_atom buf ATSafe a
;
303 fprintf buf
"@]@ @[<v 3>then@ ";
304 pp_print_expression buf e1
;
305 fprintf buf
"@]@ @[<v 3>else@ ";
306 pp_print_expression buf e2
;
309 fprintf buf
"@[<v 0>begin@ ";
310 pp_print_expression buf e
;
311 fprintf buf
"@ end@]"
313 pp_print_pragma buf p
;
314 pp_print_expression buf e
);
318 (* pp_print_statement
319 Print out a top-level ML statement. *)
320 let pp_print_statement buf stmt
=
323 fprintf buf
"open %s@ @ " (string_of_symbol name
)
324 | Let
(v
, args
, e
) ->
325 fprintf buf
"@[<hv 3>let@[<h>";
326 List.iter
(fun v
-> fprintf buf
"@ %s" (string_of_symbol v
)) (v
:: args
);
327 fprintf buf
"@] =@ ";
328 pp_print_expression buf e
;
331 pp_print_ocaml_block_text buf text
;
333 pp_print_expression buf e
;
336 pp_print_pragma buf p
339 (*** Interface Statements ***)
343 Print out a type for an MLI file. *)
344 let rec pp_print_itype buf ty
=
347 fprintf buf
"%s" (string_of_symbol name
)
349 fprintf buf
"@[<hov 0>(";
350 pp_print_itype buf t1
;
351 fprintf buf
") ->@ ";
352 pp_print_itype buf t2
;
355 pp_print_itype buf t1
;
357 pp_print_itype buf t2
358 | ITyApply
(t1
, t2
) ->
359 fprintf buf
"@[<hov 0>(";
360 pp_print_itype buf t1
;
362 pp_print_itype buf t2
;
366 (* pp_print_istatement
367 Print out a top-level MLI statement. *)
368 let pp_print_istatement buf stmt
=
371 fprintf buf
"open %s@ @ " (string_of_symbol name
)
373 fprintf buf
"@[<hv 3>val %s :@ " (string_of_symbol v
);
374 pp_print_itype buf ty
;
377 pp_print_pragma buf p
380 (*** External Interface ***)
385 let pp_print_program buf prog
=
386 let prog = Listbuf.to_list
prog in
387 fprintf buf
"@[<v 0>";
388 List.iter
(pp_print_statement buf
) prog;
392 (* pp_print_interface
393 Print an MLI file. *)
394 let pp_print_interface buf
prog =
395 let prog = Listbuf.to_list
prog in
396 fprintf buf
"@[<v 0>";
397 List.iter
(pp_print_istatement buf
) prog;