We write a single function that enables to print a context alone, an expression alone, or a context and an expression to put in the hole. Actually, we print all of them as expressions but use a special constant as a hook to recognize when we reached the context.

     
let hole = Const {name = Name "[]"; arity = 0; constr = true};; let rec expr_with expr_in_hole k out = let expr = expr_with expr_in_hole in let string x = Format.fprintf out x in let paren p f = if k > p then string "("; f(); if k > p then string ")" in function | Var x -> string "%s" x | Const _ as c when c = hole -> string "[%a]" (expr_with hole 0) expr_in_hole | Const {name = Int n} -> string "%d" n | Const {name = Name c} -> string "%s" c | Fun (x,a) -> paren 0 (fun()-> string "fun %s -> %a" x (expr 0) a) | App (App (Const {name = Name ("+" | "*" as n)}, a1), a2) -> paren 1 (fun()-> string "%a %s %a" (expr 2) a1 n (expr 2) a2) | App (a1, a2) -> paren 1 (fun()-> string "%a %a" (expr 1) a1 (expr 2) a2) | Let (x, a1, a2) -> paren 0 (fun()-> string "let x = %a in %a" (expr 0) a1 (expr 0) a2);; let print_context_expr (c, e) = expr_with e 0 Format.std_formatter (fill_context (c, hole)) let print_expr e = expr_with hole 0 Format.std_formatter e let print_context c = print_expr (fill_context (c, hole));; #install_printer print_context_expr;;