let rec print_expression e =
(match e with
| EPrimApp (_, PCharConstant c, _) ->
pp_print_string !ppf ("'"^ String.make 1 c ^"'")
| EPrimApp (_, PIntegerConstant i, _) ->
pp_print_string !ppf (string_of_int i)
| EPrimApp (_, PUnit, _) ->
pp_print_string !ppf "()"
| EAssertFalse _ -> pp_print_string !ppf "assert false"
| EVar (_, SName name) -> pp_print_string !ppf name
| EDCon (_, DName "_Unit", es) ->
pp_print_string !ppf "()"
| EDCon (_, DName "_Tuple", es) ->
pp_print_string !ppf "(";
print_separated_list "," print_expression es;
pp_print_string !ppf ")"
| EDCon (_, DName dname, []) ->
pp_print_string !ppf "(";
pp_print_string !ppf dname;
pp_print_string !ppf ")"
| EDCon (_, DName dname, es) ->
pp_print_string !ppf "(";
pp_print_string !ppf dname;
pp_print_string !ppf " ";
print_separated_list " " print_expression es;
pp_print_string !ppf ")"
| ELambda (_, pat, exp) ->
pp_print_string !ppf "\\";
print_pattern pat;
pp_print_string !ppf ".";
pp_print_cut !ppf ();
print_expression exp;
| EApp (_, t1, t2) ->
pp_print_string !ppf "(";
print_expression t1;
pp_print_string !ppf " ";
print_expression t2;
pp_print_string !ppf ")"
| EMatch (_, e, cs) ->
pp_open_hvbox !ppf 0;
pp_print_string !ppf "match ";
print_expression e;
pp_print_string !ppf " with ";
pp_print_cut !ppf ();
print_separated_list "| " print_clause cs;
pp_print_string !ppf "end ";
pp_close_box !ppf ();
| EBinding (_, bd, exp) ->
pp_open_box !ppf 0;
print_binding bd;
pp_print_string !ppf " in ";
print_expression exp;
pp_close_box !ppf ();
| ETypeConstraint (_, exp, ty) ->
pp_print_string !ppf "(";
print_expression exp;
pp_print_string !ppf " : ";
print_type ty;
pp_print_string !ppf ")"
| EForall (_, vs, e) ->
fprintf !ppf "forall ";
pp_print_string !ppf ".";
print_expression e
| EExists (_, vs, e) ->
fprintf !ppf "exists ";
print_separated_list " "
(fun (TName x) -> pp_print_string !ppf x) vs;
pp_print_string !ppf ".";
print_expression e
| ERecordEmpty _ ->
pp_print_string !ppf "{}"
| ERecordAccess (_, exp, LName name) ->
print_expression exp;
pp_print_string !ppf ".";
pp_print_string !ppf name;
| ERecordExtend (_, bds, ERecordEmpty _) ->
pp_print_string !ppf "{ ";
print_record_binding bds;
pp_print_string !ppf "} ";
| ERecordExtend _ -> assert false
| ERecordUpdate (_, exp, LName label, v) ->
print_expression exp;
pp_print_string !ppf ".";
pp_print_string !ppf label;
pp_print_string !ppf " <- ";
print_expression v);
and print_record_binding bds =
print_separated_list ";"
(fun (LName name, exp) ->
pp_print_string !ppf (name^" = ");
print_expression exp) bds
and print_binding b =
(match b with
| BindValue (pos, vs) ->
pp_print_string !ppf "let ";
print_separated_list " and " print_value_definition vs;
| BindRecValue (pos, vs) ->
pp_print_string !ppf "let rec ";
print_separated_list " and " print_value_definition vs;
| TypeDec (_, tds) ->
pp_print_string !ppf "type ";
print_separated_list " and " print_type_declaration tds)
and print_value_definition (_, tnames, pat, expression) =
let rec chop_args pat expression =
match (pat, expression) with
| ((PTypeConstraint (_, PVar (m, name), _)) as p),
ELambda(_, pat, expression) ->
let q, exp = chop_args pat expression in
p :: q, exp
| (PVar (m, name) as p, ELambda(_, pat, expression)) ->
let q, exp = chop_args pat expression in
p :: q, exp
| (pat, expression) -> [pat], expression
in
let print (pats, expression) = (
pp_open_box !ppf 0;
if tnames <> [] then (
pp_print_string !ppf "forall ";
print_separated_list " " (fun (TName s) -> pp_print_string !ppf s) tnames;
pp_print_string !ppf ".";
pp_print_cut !ppf ()
);
print_separated_list " " print_pattern pats;
pp_print_string !ppf " = ";
pp_close_box !ppf ();
pp_print_cut !ppf ();
print_expression expression;
)
in
print (chop_args pat expression)
and print_pattern p =
(match p with
| PPrimitive _ -> assert false
| PVar (_, SName name) -> pp_print_string !ppf name
| PWildcard _ -> pp_print_string !ppf "_"
| PAlias (_, name, pattern) ->
pp_print_string !ppf "(";
print_pattern pattern;
pp_print_string !ppf " as ";
pp_print_string !ppf ")"
| PTypeConstraint (_, pat, ty) ->
pp_print_string !ppf "(";
print_pattern pat;
pp_print_string !ppf " : ";
print_type ty;
pp_print_string !ppf ")"
| PData (_, DName "_Unit", ps) ->
pp_print_string !ppf "()"
| PData (_, DName "_Tuple", ps) ->
if ps <> [] then (
pp_print_string !ppf "(";
print_separated_list "," print_pattern ps;
pp_print_string !ppf ")")
| PData (_, DName k, ps) ->
pp_print_string !ppf "(";
pp_print_string !ppf k;
pp_print_string !ppf " ";
if ps <> [] then print_separated_list " " print_pattern ps;
pp_print_string !ppf ")"
| POr (_, [ x ]) | PAnd (_, [ x ]) ->
print_pattern x
| PAnd (_, ps) ->
pp_print_string !ppf "(";
print_separated_list "&" print_pattern ps;
pp_print_string !ppf ")";
| POr (_, ps) ->
pp_print_string !ppf "(";
print_separated_list "|" print_pattern ps;
pp_print_string !ppf ")");
and print_type ?paren = function
| TypVar (_, TName name) ->
pp_print_string !ppf name
| TypApp (_, TypVar(_, TName "->"), [t; t']) ->
if paren <> None then
pp_print_string !ppf "(";
print_type ~paren:true t;
pp_print_string !ppf " -> ";
print_type t';
if paren <> None then
pp_print_string !ppf ")"
| TypApp (_, TypVar(_, TName "*"), [a; b]) ->
print_type ~paren:true a;
pp_print_string !ppf " * ";
print_type ~paren:true b
| TypApp (_, t, []) ->
print_type t
| TypApp (_, t, ts) ->
pp_print_string !ppf "(";
print_type t;
pp_print_string !ppf " ";
print_separated_list " " print_type ts;
pp_print_string !ppf ")";
| TypRowCons (_, ls, ty) ->
pp_print_string !ppf "{";
let print_label (LName l, ty) =
pp_print_string !ppf l;
pp_print_string !ppf " : ";
print_type ty
in
print_separated_list "; " print_label ls;
pp_print_string !ppf "; ";
print_type ty;
pp_print_string !ppf "}"
| TypRowUniform (_, ty) ->
pp_print_string !ppf "\\";
print_type ty
and print_kind = function
KStar -> pp_print_string !ppf "*"
| KArrow (KStar, k2) -> pp_print_string !ppf "* ->";
print_kind k2
| KArrow (k1, k2) ->
pp_print_string !ppf "(";
print_kind k1;
pp_print_string !ppf ") -> ";
print_kind k2
| _ -> assert false
and print_type_declaration (_, kind, TName n, typ) =
pp_open_box !ppf 0;
pp_print_string !ppf n;
pp_print_string !ppf ":";
print_kind kind;
pp_print_string !ppf " = ";
pp_close_box !ppf ();
pp_print_cut !ppf ();
pp_open_box !ppf 0;
print_type_definition typ;
pp_print_string !ppf " ";
pp_close_box !ppf ()
and print_type_definition = function
| DAlgebraic ds ->
let first = ref true in
let print_datatype_def (_, DName k, betas, ty) =
if !first then (
first := false)
else (pp_print_cut !ppf (); pp_print_string !ppf "| ");
pp_print_string !ppf k;
pp_print_string !ppf " : ";
if betas <> [] then begin
pp_print_string !ppf "forall ";
print_separated_list " " (fun (TName s) -> pp_print_string !ppf s)
betas;
pp_print_string !ppf "."
end;
print_type ty
in
print_separated_list "" print_datatype_def ds;
and print_clause (_, pat, expression) =
print_pattern pat;
pp_print_string !ppf " => ";
print_expression expression;
pp_print_cut !ppf ()