(* Locations within the execution tree (used for variable names and other gensyms) *) (* A location is a sequence of `digits', called pigits. Each pigit is the position within the branch of the current expression. The highest-branching expression is the if statement, with three children. Therefore, pigits are one through three. A special pigit PLoc is used for lazy evaluated expressions: the expressions that are evaluated away from the place they occur as children expressions. Such expressions are associated with some fixed location. Another special pigit is PNote, for annotating a particular place in the execution tree (useful in debugging). If an expression has only one child, we can pass it loc as it is, since it won't create any ambiguity (Strictly speaking, we can easily do without PLoc and PNote, but they give a more useful location information to print when things go wrong, I think) *) type pigit = POne | PTwo | PThree | PLoc of loc | PNote of string and loc = pigit list let rec pp_pigit : Format.formatter -> pigit -> unit = fun ppf -> function | POne -> Format.pp_print_int ppf 1 | PTwo -> Format.pp_print_int ppf 2 | PThree -> Format.pp_print_int ppf 3 | PLoc v -> Format.fprintf ppf "(%a)" pp_pigits v | PNote s -> Format.fprintf ppf "%s" s and pp_pigits : Format.formatter -> pigit list -> unit = fun ppf v -> let open Format in pp_print_list ~pp_sep:(fun ppf () -> pp_print_string ppf ".") pp_pigit ppf v; pp_print_string ppf ".0" let string_of_loc : loc -> string = fun v -> let open Format in pp_pigits str_formatter v; flush_str_formatter () let init_loc : loc = []