ocaml/camlp4/top/oprint.ml

586 lines
19 KiB
OCaml

(* camlp4r *)
(***********************************************************************)
(* *)
(* Camlp4 *)
(* *)
(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 2002 Institut National de Recherche en Informatique et *)
(* Automatique. Distributed only by permission. *)
(* *)
(***********************************************************************)
(* $Id$ *)
open Format;
open Outcometree;
exception Ellipsis;
value cautious f ppf arg =
try f ppf arg with [ Ellipsis -> fprintf ppf "..." ]
;
value rec print_ident ppf =
fun
[ Oide_ident s -> fprintf ppf "%s" s
| Oide_dot id s -> fprintf ppf "%a.%s" print_ident id s
| Oide_apply id1 id2 ->
fprintf ppf "%a(%a)" print_ident id1 print_ident id2 ]
;
value value_ident ppf name =
if List.mem name ["or"; "mod"; "land"; "lor"; "lxor"; "lsl"; "lsr"; "asr"]
then
fprintf ppf "( %s )" name
else
match name.[0] with
[ 'a'..'z' | '\223'..'\246' | '\248'..'\255' | '_' ->
fprintf ppf "%s" name
| _ -> fprintf ppf "( %s )" name ]
;
(* Values *)
value print_out_value ppf tree =
let rec print_tree ppf =
fun
[ Oval_tuple tree_list ->
fprintf ppf "@[%a@]" (print_tree_list print_tree_1 ",") tree_list
| tree -> print_tree_1 ppf tree ]
and print_tree_1 ppf =
fun
[ Oval_constr name [param] ->
fprintf ppf "@[<1>%a@ %a@]" print_ident name print_simple_tree param
| Oval_constr name ([_ :: _] as params) ->
fprintf ppf "@[<1>%a@ (%a)@]" print_ident name
(print_tree_list print_tree_1 ",") params
| Oval_variant name (Some param) ->
fprintf ppf "@[<2>`%s@ %a@]" name print_simple_tree param
| tree -> print_simple_tree ppf tree ]
and print_simple_tree ppf =
fun
[ Oval_int i -> fprintf ppf "%i" i
| Oval_float f -> fprintf ppf "%s" (string_of_float f)
| Oval_char c -> fprintf ppf "'%s'" (Char.escaped c)
| Oval_string s ->
try fprintf ppf "\"%s\"" (String.escaped s) with
[ Invalid_argument "String.create" -> fprintf ppf "<huge string>" ]
| Oval_list tl ->
fprintf ppf "@[<1>[%a]@]" (print_tree_list print_tree_1 ";") tl
| Oval_array tl ->
fprintf ppf "@[<2>[|%a|]@]" (print_tree_list print_tree_1 ";") tl
| Oval_constr name [] -> print_ident ppf name
| Oval_variant name None -> fprintf ppf "`%s" name
| Oval_stuff s -> fprintf ppf "%s" s
| Oval_record fel ->
fprintf ppf "@[<1>{%a}@]" (cautious (print_fields True)) fel
| Oval_ellipsis -> raise Ellipsis
| Oval_printer f -> f ppf
| tree -> fprintf ppf "@[<1>(%a)@]" (cautious print_tree) tree ]
and print_fields first ppf =
fun
[ [] -> ()
| [(name, tree) :: fields] ->
do {
if not first then fprintf ppf ";@ " else ();
fprintf ppf "@[<1>%a@ =@ %a@]" print_ident name
(cautious print_tree) tree;
print_fields False ppf fields
} ]
and print_tree_list print_item sep ppf tree_list =
let rec print_list first ppf =
fun
[ [] -> ()
| [tree :: tree_list] ->
do {
if not first then fprintf ppf "%s@ " sep else ();
print_item ppf tree;
print_list False ppf tree_list
} ]
in
cautious (print_list True) ppf tree_list
in
cautious print_tree ppf tree
;
(* Types *)
value rec print_list_init pr sep ppf =
fun
[ [] -> ()
| [a :: l] -> do { sep ppf; pr ppf a; print_list_init pr sep ppf l } ]
;
value rec print_list pr sep ppf =
fun
[ [] -> ()
| [a] -> pr ppf a
| [a :: l] -> do { pr ppf a; sep ppf; print_list pr sep ppf l } ]
;
value pr_present =
print_list (fun ppf s -> fprintf ppf "`%s" s) (fun ppf -> fprintf ppf "@ ")
;
value rec print_out_type ppf =
fun
[ Otyp_alias ty s -> fprintf ppf "@[%a as '%s@]" print_out_type ty s
| ty -> print_out_type_1 ppf ty ]
and print_out_type_1 ppf =
fun
[ Otyp_arrow lab ty1 ty2 ->
fprintf ppf "@[%s%a ->@ %a@]" (if lab <> "" then lab ^ ":" else "")
print_out_type_2 ty1 print_out_type_1 ty2
| ty -> print_out_type_2 ppf ty ]
and print_out_type_2 ppf =
fun
[ Otyp_tuple tyl ->
fprintf ppf "@[<0>%a@]" (print_typlist print_simple_out_type " *") tyl
| ty -> print_simple_out_type ppf ty ]
and print_simple_out_type ppf =
fun
[ Otyp_class ng id tyl ->
fprintf ppf "@[%a%s#%a@]" print_typargs tyl (if ng then "_" else "")
print_ident id
| Otyp_constr id tyl ->
fprintf ppf "@[%a%a@]" print_typargs tyl print_ident id
| Otyp_object fields rest ->
fprintf ppf "@[<2>< %a >@]" (print_fields rest) fields
| Otyp_stuff s -> fprintf ppf "%s" s
| Otyp_var ng s -> fprintf ppf "'%s%s" (if ng then "_" else "") s
| Otyp_variant non_gen row_fields closed tags ->
let print_present ppf =
fun
[ None | Some [] -> ()
| Some l -> fprintf ppf "@;<1 -2>> @[<hov>%a@]" pr_present l ]
in
let print_fields ppf =
fun
[ Ovar_fields fields ->
print_list print_row_field (fun ppf -> fprintf ppf "@;<1 -2>| ")
ppf fields
| Ovar_name id tyl ->
fprintf ppf "@[%a%a@]" print_typargs tyl print_ident id ]
in
fprintf ppf "%s[%s@[<hv>@[<hv>%a@]%a]@]" (if non_gen then "_" else "")
(if closed then if tags = None then " " else "< "
else if tags = None then "> "
else "? ")
print_fields row_fields print_present tags
| Otyp_alias _ _ | Otyp_arrow _ _ _ | Otyp_tuple _ as ty ->
fprintf ppf "@[<1>(%a)@]" print_out_type ty
| Otyp_abstract | Otyp_sum _ | Otyp_record _ | Otyp_manifest _ _ -> () ]
and print_fields rest ppf =
fun
[ [] ->
match rest with
[ Some non_gen -> fprintf ppf "%s.." (if non_gen then "_" else "")
| None -> () ]
| [(s, t)] ->
do {
fprintf ppf "%s : %a" s print_out_type t;
match rest with
[ Some _ -> fprintf ppf ";@ "
| None -> () ];
print_fields rest ppf []
}
| [(s, t) :: l] ->
fprintf ppf "%s : %a;@ %a" s print_out_type t (print_fields rest) l ]
and print_row_field ppf (l, opt_amp, tyl) =
let pr_of ppf =
if opt_amp then fprintf ppf " of@ &@ "
else if tyl <> [] then fprintf ppf " of@ "
else fprintf ppf ""
in
fprintf ppf "@[<hv 2>`%s%t%a@]" l pr_of (print_typlist print_out_type " &")
tyl
and print_typlist print_elem sep ppf =
fun
[ [] -> ()
| [ty] -> print_elem ppf ty
| [ty :: tyl] ->
fprintf ppf "%a%s@ %a" print_elem ty sep (print_typlist print_elem sep)
tyl ]
and print_typargs ppf =
fun
[ [] -> ()
| [ty1] -> fprintf ppf "%a@ " print_simple_out_type ty1
| tyl ->
fprintf ppf "@[<1>(%a)@]@ " (print_typlist print_out_type ",") tyl ]
;
(* Signature items *)
value print_out_class_params ppf =
fun
[ [] -> ()
| tyl ->
fprintf ppf "@[<1>[%a]@]@ "
(print_list (fun ppf x -> fprintf ppf "'%s" x)
(fun ppf -> fprintf ppf ", "))
tyl ]
;
value rec print_out_class_type ppf =
fun
[ Octy_constr id tyl ->
let pr_tyl ppf =
fun
[ [] -> ()
| tyl ->
fprintf ppf "@[<1>[%a]@]@ " (print_typlist print_out_type ",")
tyl ]
in
fprintf ppf "@[%a%a@]" pr_tyl tyl print_ident id
| Octy_fun lab ty cty ->
fprintf ppf "@[%s%a ->@ %a@]" (if lab <> "" then lab ^ ":" else "")
print_out_type_2 ty print_out_class_type cty
| Octy_signature self_ty csil ->
let pr_param ppf =
fun
[ Some ty -> fprintf ppf "@ @[(%a)@]" print_out_type ty
| None -> () ]
in
fprintf ppf "@[<hv 2>@[<2>object%a@]@ %a@;<1 -2>end@]" pr_param self_ty
(print_list print_out_class_sig_item (fun ppf -> fprintf ppf "@ "))
csil ]
and print_out_class_sig_item ppf =
fun
[ Ocsg_constraint ty1 ty2 ->
fprintf ppf "@[<2>constraint %a =@ %a@]" print_out_type ty1
print_out_type ty2
| Ocsg_method name priv virt ty ->
fprintf ppf "@[<2>method %s%s%s :@ %a@]"
(if priv then "private " else "") (if virt then "virtual " else "")
name print_out_type ty
| Ocsg_value name mut ty ->
fprintf ppf "@[<2>val %s%s :@ %a@]" (if mut then "mutable " else "")
name print_out_type ty ]
;
value rec print_out_module_type ppf =
fun
[ Omty_abstract -> ()
| Omty_functor name mty_arg mty_res ->
fprintf ppf "@[<2>functor@ (%s : %a) ->@ %a@]" name
print_out_module_type mty_arg print_out_module_type mty_res
| Omty_ident id -> fprintf ppf "%a" print_ident id
| Omty_signature sg ->
fprintf ppf "@[<hv 2>sig@ %a@;<1 -2>end@]" print_signature_body sg ]
and print_signature_body ppf =
fun
[ [] -> ()
| [item] -> print_out_sig_item ppf item
| [item :: items] ->
fprintf ppf "%a@ %a" print_out_sig_item item
print_signature_body items ]
and print_out_sig_item ppf =
fun
[ Osig_class vir_flag name params clt ->
fprintf ppf "@[<2>class%s@ %a%s@ :@ %a@]"
(if vir_flag then " virtual" else "") print_out_class_params params
name print_out_class_type clt
| Osig_class_type vir_flag name params clt ->
fprintf ppf "@[<2>class type%s@ %a%s@ =@ %a@]"
(if vir_flag then " virtual" else "") print_out_class_params params
name print_out_class_type clt
| Osig_exception id tyl ->
fprintf ppf "@[<2>exception %a@]" print_out_constr (id, tyl)
| Osig_modtype name Omty_abstract ->
fprintf ppf "@[<2>module type %s@]" name
| Osig_modtype name mty ->
fprintf ppf "@[<2>module type %s =@ %a@]" name print_out_module_type mty
| Osig_module name mty ->
fprintf ppf "@[<2>module %s :@ %a@]" name print_out_module_type mty
| Osig_type tdl -> print_out_type_decl_list ppf tdl
| Osig_value name ty prims ->
let kwd = if prims = [] then "val" else "external" in
let pr_prims ppf =
fun
[ [] -> ()
| [s :: sl] ->
do {
fprintf ppf "@ = \"%s\"" s;
List.iter (fun s -> fprintf ppf "@ \"%s\"" s) sl
} ]
in
fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name
print_out_type ty pr_prims prims ]
and print_out_type_decl_list ppf =
fun
[ [] -> ()
| [x] -> print_out_type_decl "type" ppf x
| [x :: l] ->
do {
print_out_type_decl "type" ppf x;
List.iter (fun x -> fprintf ppf "@ %a" (print_out_type_decl "and") x)
l
} ]
and print_out_type_decl kwd ppf (name, args, ty, constraints) =
let print_constraints ppf params =
List.iter
(fun (ty1, ty2) ->
fprintf ppf "@ @[<2>constraint %a =@ %a@]" print_out_type
ty1 print_out_type ty2)
params
in
let type_parameter ppf (ty, (co, cn)) =
fprintf ppf "%s'%s" (if not cn then "+" else if not co then "-" else "")
ty
in
let type_defined ppf =
match args with
[ [] -> fprintf ppf "%s" name
| [arg] -> fprintf ppf "@[%a@ %s@]" type_parameter arg name
| _ ->
fprintf ppf "@[(@[%a)@]@ %s@]"
(print_list type_parameter (fun ppf -> fprintf ppf ",@ ")) args
name ]
in
let print_manifest ppf =
fun
[ Otyp_manifest ty _ -> fprintf ppf " =@ %a" print_out_type ty
| _ -> () ]
in
let print_name_args ppf =
fprintf ppf "%s %t%a" kwd type_defined print_manifest ty
in
let ty =
match ty with
[ Otyp_manifest _ ty -> ty
| _ -> ty ]
in
match ty with
[ Otyp_abstract ->
fprintf ppf "@[<2>@[<hv 2>%t@]%a@]" print_name_args print_constraints
constraints
| Otyp_record lbls ->
fprintf ppf "@[<2>@[<hv 2>%t = {%a@;<1 -2>}@]@ %a@]" print_name_args
(print_list_init print_out_label (fun ppf -> fprintf ppf "@ ")) lbls
print_constraints constraints
| Otyp_sum constrs ->
fprintf ppf "@[<2>@[<hv 2>%t =@;<1 2>%a@]%a@]" print_name_args
(print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs
print_constraints constraints
| ty ->
fprintf ppf "@[<2>@[<hv 2>%t =@ %a@]%a@]" print_name_args
print_out_type ty print_constraints constraints ]
and print_out_constr ppf (name, tyl) =
match tyl with
[ [] -> fprintf ppf "%s" name
| _ ->
fprintf ppf "@[<2>%s of@ %a@]" name
(print_typlist print_simple_out_type " *") tyl ]
and print_out_label ppf (name, mut, arg) =
fprintf ppf "@[<2>%s%s :@ %a@];" (if mut then "mutable " else "") name
print_out_type arg
;
(* Signature items *)
value print_out_class_params ppf =
fun
[ [] -> ()
| tyl ->
fprintf ppf "@[<1>[%a]@]@ "
(print_list (fun ppf x -> fprintf ppf "'%s" x)
(fun ppf -> fprintf ppf ", "))
tyl ]
;
value rec print_out_class_type ppf =
fun
[ Octy_constr id tyl ->
let pr_tyl ppf =
fun
[ [] -> ()
| tyl ->
fprintf ppf "@[<1>[%a]@]@ "
(print_typlist print_out_type ",") tyl ]
in
fprintf ppf "@[%a%a@]" pr_tyl tyl print_ident id
| Octy_fun lab ty cty ->
fprintf ppf "@[%s%a ->@ %a@]" (if lab <> "" then lab ^ ":" else "")
print_out_type_2 ty print_out_class_type cty
| Octy_signature self_ty csil ->
let pr_param ppf =
fun
[ Some ty -> fprintf ppf "@ @[(%a)@]" print_out_type ty
| None -> () ]
in
fprintf ppf "@[<hv 2>@[<2>object%a@]@ %a@;<1 -2>end@]" pr_param self_ty
(print_list print_out_class_sig_item (fun ppf -> fprintf ppf "@ "))
csil ]
and print_out_class_sig_item ppf =
fun
[ Ocsg_constraint ty1 ty2 ->
fprintf ppf "@[<2>constraint %a =@ %a@]" print_out_type ty1
print_out_type ty2
| Ocsg_method name priv virt ty ->
fprintf ppf "@[<2>method %s%s%s :@ %a@]"
(if priv then "private " else "") (if virt then "virtual " else "")
name print_out_type ty
| Ocsg_value name mut ty ->
fprintf ppf "@[<2>val %s%s :@ %a@]" (if mut then "mutable " else "")
name print_out_type ty ]
;
value rec print_out_module_type ppf =
fun
[ Omty_abstract -> ()
| Omty_functor name mty_arg mty_res ->
fprintf ppf "@[<2>functor@ (%s : %a) ->@ %a@]" name
print_out_module_type mty_arg print_out_module_type mty_res
| Omty_ident id -> fprintf ppf "%a" print_ident id
| Omty_signature sg ->
fprintf ppf "@[<hv 2>sig@ %a@;<1 -2>end@]" print_signature_body sg ]
and print_signature_body ppf =
fun
[ [] -> ()
| [item] -> print_out_sig_item ppf item
| [item :: items] ->
fprintf ppf "%a@ %a" print_out_sig_item item print_signature_body
items ]
and print_out_sig_item ppf =
fun
[ Osig_class vir_flag name params clt ->
fprintf ppf "@[<2>class%s@ %a%s@ :@ %a@]"
(if vir_flag then " virtual" else "") print_out_class_params params
name print_out_class_type clt
| Osig_class_type vir_flag name params clt ->
fprintf ppf "@[<2>class type%s@ %a%s@ =@ %a@]"
(if vir_flag then " virtual" else "") print_out_class_params params
name print_out_class_type clt
| Osig_exception id tyl ->
fprintf ppf "@[<2>exception %a@]" print_out_constr (id, tyl)
| Osig_modtype name Omty_abstract ->
fprintf ppf "@[<2>module type %s@]" name
| Osig_modtype name mty ->
fprintf ppf "@[<2>module type %s =@ %a@]" name print_out_module_type mty
| Osig_module name mty ->
fprintf ppf "@[<2>module %s :@ %a@]" name print_out_module_type mty
| Osig_type tdl -> print_out_type_decl_list ppf tdl
| Osig_value name ty prims ->
let kwd = if prims = [] then "val" else "external" in
let pr_prims ppf =
fun
[ [] -> ()
| [s :: sl] ->
do {
fprintf ppf "@ = \"%s\"" s;
List.iter (fun s -> fprintf ppf "@ \"%s\"" s) sl
} ]
in
fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name print_out_type
ty pr_prims prims ]
and print_out_type_decl_list ppf =
fun
[ [] -> ()
| [x] -> print_out_type_decl "type" ppf x
| [x :: l] ->
do {
print_out_type_decl "type" ppf x;
List.iter (fun x -> fprintf ppf "@ %a" (print_out_type_decl "and") x)
l
} ]
and print_out_type_decl kwd ppf (name, args, ty, constraints) =
let print_constraints ppf params =
List.iter
(fun (ty1, ty2) ->
fprintf ppf "@ @[<2>constraint %a =@ %a@]" print_out_type ty1
print_out_type ty2)
params
in
let type_parameter ppf (ty, (co, cn)) =
fprintf ppf "%s'%s" (if not cn then "+" else if not co then "-" else "")
ty
in
let type_defined ppf =
match args with
[ [] -> fprintf ppf "%s" name
| [arg] -> fprintf ppf "@[%a@ %s@]" type_parameter arg name
| _ ->
fprintf ppf "@[(@[%a)@]@ %s@]"
(print_list type_parameter (fun ppf -> fprintf ppf ",@ ")) args
name ]
in
let print_manifest ppf =
fun
[ Otyp_manifest ty _ -> fprintf ppf " =@ %a" print_out_type ty
| _ -> () ]
in
let print_name_args ppf =
fprintf ppf "%s %t%a" kwd type_defined print_manifest ty
in
let ty =
match ty with
[ Otyp_manifest _ ty -> ty
| _ -> ty ]
in
match ty with
[ Otyp_abstract ->
fprintf ppf "@[<2>@[<hv 2>%t@]%a@]" print_name_args print_constraints
constraints
| Otyp_record lbls ->
fprintf ppf "@[<2>@[<hv 2>%t = {%a@;<1 -2>}@]@ %a@]" print_name_args
(print_list_init print_out_label (fun ppf -> fprintf ppf "@ ")) lbls
print_constraints constraints
| Otyp_sum constrs ->
fprintf ppf "@[<2>@[<hv 2>%t =@;<1 2>%a@]%a@]" print_name_args
(print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs
print_constraints constraints
| ty ->
fprintf ppf "@[<2>@[<hv 2>%t =@ %a@]%a@]" print_name_args
print_out_type ty print_constraints constraints ]
and print_out_constr ppf (name, tyl) =
match tyl with
[ [] -> fprintf ppf "%s" name
| _ ->
fprintf ppf "@[<2>%s of@ %a@]" name
(print_typlist print_simple_out_type " *") tyl ]
and print_out_label ppf (name, mut, arg) =
fprintf ppf "@[<2>%s%s :@ %a@];" (if mut then "mutable " else "") name
print_out_type arg
;
(* Phrases *)
value print_out_exception ppf exn outv =
match exn with
[ Sys.Break -> fprintf ppf "Interrupted.@."
| Out_of_memory -> fprintf ppf "Out of memory during evaluation.@."
| Stack_overflow ->
fprintf ppf "Stack overflow during evaluation (looping recursion?).@."
| _ ->
fprintf ppf "@[Exception:@ %a.@]@." Toploop.print_out_value.val outv ]
;
value rec print_items ppf =
fun
[ [] -> ()
| [(tree, valopt) :: items] ->
do {
match valopt with
[ Some v ->
fprintf ppf "@[<2>%a =@ %a@]" Toploop.print_out_sig_item.val tree
Toploop.print_out_value.val v
| None -> fprintf ppf "@[%a@]" Toploop.print_out_sig_item.val tree ];
if items <> [] then fprintf ppf "@ %a" print_items items else ()
} ]
;
value print_out_phrase ppf =
fun
[ Ophr_eval outv ty ->
fprintf ppf "@[- : %a@ =@ %a@]@." Toploop.print_out_type.val ty
Toploop.print_out_value.val outv
| Ophr_signature [] -> ()
| Ophr_signature items -> fprintf ppf "@[<v>%a@]@." print_items items
| Ophr_exception (exn, outv) -> print_out_exception ppf exn outv ]
;
Toploop.print_out_value.val := print_out_value;
Toploop.print_out_type.val := print_out_type;
Toploop.print_out_sig_item.val := print_out_sig_item;
Toploop.print_out_phrase.val := print_out_phrase;