summaryrefslogtreecommitdiff
path: root/compiler/Print.ml
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/Print.ml')
-rw-r--r--compiler/Print.ml1283
1 files changed, 1283 insertions, 0 deletions
diff --git a/compiler/Print.ml b/compiler/Print.ml
new file mode 100644
index 00000000..8f52b291
--- /dev/null
+++ b/compiler/Print.ml
@@ -0,0 +1,1283 @@
+open Names
+module T = Types
+module TU = TypesUtils
+module V = Values
+module VU = ValuesUtils
+module E = Expressions
+module A = LlbcAst
+module C = Contexts
+
+let option_to_string (to_string : 'a -> string) (x : 'a option) : string =
+ match x with Some x -> "Some (" ^ to_string x ^ ")" | None -> "None"
+
+let name_to_string (name : name) : string = Names.name_to_string name
+let fun_name_to_string (name : fun_name) : string = name_to_string name
+let global_name_to_string (name : global_name) : string = name_to_string name
+
+(** Pretty-printing for types *)
+module Types = struct
+ let type_var_to_string (tv : T.type_var) : string = tv.name
+
+ let region_var_to_string (rv : T.region_var) : string =
+ match rv.name with
+ | Some name -> name
+ | None -> T.RegionVarId.to_string rv.index
+
+ let region_var_id_to_string (rid : T.RegionVarId.id) : string =
+ "rv@" ^ T.RegionVarId.to_string rid
+
+ let region_id_to_string (rid : T.RegionId.id) : string =
+ "r@" ^ T.RegionId.to_string rid
+
+ let region_to_string (rid_to_string : 'rid -> string) (r : 'rid T.region) :
+ string =
+ match r with Static -> "'static" | Var rid -> rid_to_string rid
+
+ let erased_region_to_string (_ : T.erased_region) : string = "'_"
+
+ let ref_kind_to_string (rk : T.ref_kind) : string =
+ match rk with Mut -> "Mut" | Shared -> "Shared"
+
+ let assumed_ty_to_string (_ : T.assumed_ty) : string = "Box"
+
+ type 'r type_formatter = {
+ r_to_string : 'r -> string;
+ type_var_id_to_string : T.TypeVarId.id -> string;
+ type_decl_id_to_string : T.TypeDeclId.id -> string;
+ }
+
+ type stype_formatter = T.RegionVarId.id T.region type_formatter
+ type rtype_formatter = T.RegionId.id T.region type_formatter
+ type etype_formatter = T.erased_region type_formatter
+
+ let integer_type_to_string = function
+ | T.Isize -> "isize"
+ | T.I8 -> "i8"
+ | T.I16 -> "i16"
+ | T.I32 -> "i32"
+ | T.I64 -> "i64"
+ | T.I128 -> "i128"
+ | T.Usize -> "usize"
+ | T.U8 -> "u8"
+ | T.U16 -> "u16"
+ | T.U32 -> "u32"
+ | T.U64 -> "u64"
+ | T.U128 -> "u128"
+
+ let type_id_to_string (fmt : 'r type_formatter) (id : T.type_id) : string =
+ match id with
+ | T.AdtId id -> fmt.type_decl_id_to_string id
+ | T.Tuple -> ""
+ | T.Assumed aty -> (
+ match aty with
+ | Box -> "alloc::boxed::Box"
+ | Vec -> "alloc::vec::Vec"
+ | Option -> "core::option::Option")
+
+ let rec ty_to_string (fmt : 'r type_formatter) (ty : 'r T.ty) : string =
+ match ty with
+ | T.Adt (id, regions, tys) ->
+ let is_tuple = match id with T.Tuple -> true | _ -> false in
+ let params = params_to_string fmt is_tuple regions tys in
+ type_id_to_string fmt id ^ params
+ | T.TypeVar tv -> fmt.type_var_id_to_string tv
+ | T.Bool -> "bool"
+ | T.Char -> "char"
+ | T.Never -> "⊥"
+ | T.Integer int_ty -> integer_type_to_string int_ty
+ | T.Str -> "str"
+ | T.Array aty -> "[" ^ ty_to_string fmt aty ^ "; ?]"
+ | T.Slice sty -> "[" ^ ty_to_string fmt sty ^ "]"
+ | T.Ref (r, rty, ref_kind) -> (
+ match ref_kind with
+ | T.Mut ->
+ "&" ^ fmt.r_to_string r ^ " mut (" ^ ty_to_string fmt rty ^ ")"
+ | T.Shared ->
+ "&" ^ fmt.r_to_string r ^ " (" ^ ty_to_string fmt rty ^ ")")
+
+ and params_to_string (fmt : 'r type_formatter) (is_tuple : bool)
+ (regions : 'r list) (types : 'r T.ty list) : string =
+ let regions = List.map fmt.r_to_string regions in
+ let types = List.map (ty_to_string fmt) types in
+ let params = String.concat ", " (List.append regions types) in
+ if is_tuple then "(" ^ params ^ ")"
+ else if List.length regions + List.length types > 0 then "<" ^ params ^ ">"
+ else ""
+
+ let sty_to_string (fmt : stype_formatter) (ty : T.sty) : string =
+ ty_to_string fmt ty
+
+ let rty_to_string (fmt : rtype_formatter) (ty : T.rty) : string =
+ ty_to_string fmt ty
+
+ let ety_to_string (fmt : etype_formatter) (ty : T.ety) : string =
+ ty_to_string fmt ty
+
+ let field_to_string fmt (f : T.field) : string =
+ match f.field_name with
+ | Some field_name -> field_name ^ " : " ^ ty_to_string fmt f.field_ty
+ | None -> ty_to_string fmt f.field_ty
+
+ let variant_to_string fmt (v : T.variant) : string =
+ v.variant_name ^ "("
+ ^ String.concat ", " (List.map (field_to_string fmt) v.fields)
+ ^ ")"
+
+ let type_decl_to_string (type_decl_id_to_string : T.TypeDeclId.id -> string)
+ (def : T.type_decl) : string =
+ let regions = def.region_params in
+ let types = def.type_params in
+ let rid_to_string rid =
+ match List.find_opt (fun rv -> rv.T.index = rid) regions with
+ | Some rv -> region_var_to_string rv
+ | None -> failwith "Unreachable"
+ in
+ let r_to_string = region_to_string rid_to_string in
+ let type_var_id_to_string id =
+ match List.find_opt (fun tv -> tv.T.index = id) types with
+ | Some tv -> type_var_to_string tv
+ | None -> failwith "Unreachable"
+ in
+ let fmt = { r_to_string; type_var_id_to_string; type_decl_id_to_string } in
+ let name = name_to_string def.name in
+ let params =
+ if List.length regions + List.length types > 0 then
+ let regions = List.map region_var_to_string regions in
+ let types = List.map type_var_to_string types in
+ let params = String.concat ", " (List.append regions types) in
+ "<" ^ params ^ ">"
+ else ""
+ in
+ match def.kind with
+ | T.Struct fields ->
+ if List.length fields > 0 then
+ let fields =
+ String.concat ","
+ (List.map (fun f -> "\n " ^ field_to_string fmt f) fields)
+ in
+ "struct " ^ name ^ params ^ "{" ^ fields ^ "}"
+ else "struct " ^ name ^ params ^ "{}"
+ | T.Enum variants ->
+ let variants =
+ List.map (fun v -> "| " ^ variant_to_string fmt v) variants
+ in
+ let variants = String.concat "\n" variants in
+ "enum " ^ name ^ params ^ " =\n" ^ variants
+ | T.Opaque -> "opaque type " ^ name ^ params
+end
+
+module PT = Types (* local module *)
+
+(** Pretty-printing for values *)
+module Values = struct
+ type value_formatter = {
+ rvar_to_string : T.RegionVarId.id -> string;
+ r_to_string : T.RegionId.id -> string;
+ type_var_id_to_string : T.TypeVarId.id -> string;
+ type_decl_id_to_string : T.TypeDeclId.id -> string;
+ adt_variant_to_string : T.TypeDeclId.id -> T.VariantId.id -> string;
+ var_id_to_string : V.VarId.id -> string;
+ adt_field_names :
+ T.TypeDeclId.id -> T.VariantId.id option -> string list option;
+ }
+
+ let value_to_etype_formatter (fmt : value_formatter) : PT.etype_formatter =
+ {
+ PT.r_to_string = PT.erased_region_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let value_to_rtype_formatter (fmt : value_formatter) : PT.rtype_formatter =
+ {
+ PT.r_to_string = PT.region_to_string fmt.r_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let value_to_stype_formatter (fmt : value_formatter) : PT.stype_formatter =
+ {
+ PT.r_to_string = PT.region_to_string fmt.rvar_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let var_id_to_string (id : V.VarId.id) : string =
+ "var@" ^ V.VarId.to_string id
+
+ let big_int_to_string (bi : V.big_int) : string = Z.to_string bi
+
+ let scalar_value_to_string (sv : V.scalar_value) : string =
+ big_int_to_string sv.value ^ ": " ^ PT.integer_type_to_string sv.int_ty
+
+ let constant_value_to_string (cv : V.constant_value) : string =
+ match cv with
+ | Scalar sv -> scalar_value_to_string sv
+ | Bool b -> Bool.to_string b
+ | Char c -> String.make 1 c
+ | String s -> s
+
+ let symbolic_value_id_to_string (id : V.SymbolicValueId.id) : string =
+ "s@" ^ V.SymbolicValueId.to_string id
+
+ let symbolic_value_to_string (fmt : PT.rtype_formatter)
+ (sv : V.symbolic_value) : string =
+ symbolic_value_id_to_string sv.sv_id ^ " : " ^ PT.rty_to_string fmt sv.sv_ty
+
+ let symbolic_value_proj_to_string (fmt : value_formatter)
+ (sv : V.symbolic_value) (rty : T.rty) : string =
+ symbolic_value_id_to_string sv.sv_id
+ ^ " : "
+ ^ PT.ty_to_string (value_to_rtype_formatter fmt) sv.sv_ty
+ ^ " <: "
+ ^ PT.ty_to_string (value_to_rtype_formatter fmt) rty
+
+ (* TODO: it may be a good idea to try to factorize this function with
+ * typed_avalue_to_string. At some point we had done it, because [typed_value]
+ * and [typed_avalue] were instances of the same general type [g_typed_value],
+ * but then we removed this general type because it proved to be a bad idea. *)
+ let rec typed_value_to_string (fmt : value_formatter) (v : V.typed_value) :
+ string =
+ let ty_fmt : PT.etype_formatter = value_to_etype_formatter fmt in
+ match v.value with
+ | Concrete cv -> constant_value_to_string cv
+ | Adt av -> (
+ let field_values =
+ List.map (typed_value_to_string fmt) av.field_values
+ in
+ match v.ty with
+ | T.Adt (T.Tuple, _, _) ->
+ (* Tuple *)
+ "(" ^ String.concat ", " field_values ^ ")"
+ | T.Adt (T.AdtId def_id, _, _) ->
+ (* "Regular" ADT *)
+ let adt_ident =
+ match av.variant_id with
+ | Some vid -> fmt.adt_variant_to_string def_id vid
+ | None -> fmt.type_decl_id_to_string def_id
+ in
+ if List.length field_values > 0 then
+ match fmt.adt_field_names def_id av.V.variant_id with
+ | None ->
+ let field_values = String.concat ", " field_values in
+ adt_ident ^ " (" ^ field_values ^ ")"
+ | Some field_names ->
+ let field_values = List.combine field_names field_values in
+ let field_values =
+ List.map
+ (fun (field, value) -> field ^ " = " ^ value ^ ";")
+ field_values
+ in
+ let field_values = String.concat " " field_values in
+ adt_ident ^ " { " ^ field_values ^ " }"
+ else adt_ident
+ | T.Adt (T.Assumed aty, _, _) -> (
+ (* Assumed type *)
+ match (aty, field_values) with
+ | Box, [ bv ] -> "@Box(" ^ bv ^ ")"
+ | Option, _ ->
+ if av.variant_id = Some T.option_some_id then
+ "@Option::Some("
+ ^ Collections.List.to_cons_nil field_values
+ ^ ")"
+ else if av.variant_id = Some T.option_none_id then (
+ assert (field_values = []);
+ "@Option::None")
+ else failwith "Unreachable"
+ | Vec, _ -> "@Vec[" ^ String.concat ", " field_values ^ "]"
+ | _ -> failwith "Inconsistent value")
+ | _ -> failwith "Inconsistent typed value")
+ | Bottom -> "⊥ : " ^ PT.ty_to_string ty_fmt v.ty
+ | Borrow bc -> borrow_content_to_string fmt bc
+ | Loan lc -> loan_content_to_string fmt lc
+ | Symbolic s -> symbolic_value_to_string (value_to_rtype_formatter fmt) s
+
+ and borrow_content_to_string (fmt : value_formatter) (bc : V.borrow_content) :
+ string =
+ match bc with
+ | SharedBorrow (_, bid) -> "⌊shared@" ^ V.BorrowId.to_string bid ^ "⌋"
+ | MutBorrow (bid, tv) ->
+ "&mut@" ^ V.BorrowId.to_string bid ^ " ("
+ ^ typed_value_to_string fmt tv
+ ^ ")"
+ | InactivatedMutBorrow (_, bid) ->
+ "⌊inactivated_mut@" ^ V.BorrowId.to_string bid ^ "⌋"
+
+ and loan_content_to_string (fmt : value_formatter) (lc : V.loan_content) :
+ string =
+ match lc with
+ | SharedLoan (loans, v) ->
+ let loans = V.BorrowId.Set.to_string None loans in
+ "@shared_loan(" ^ loans ^ ", " ^ typed_value_to_string fmt v ^ ")"
+ | MutLoan bid -> "⌊mut@" ^ V.BorrowId.to_string bid ^ "⌋"
+
+ let abstract_shared_borrow_to_string (fmt : value_formatter)
+ (abs : V.abstract_shared_borrow) : string =
+ match abs with
+ | AsbBorrow bid -> V.BorrowId.to_string bid
+ | AsbProjReborrows (sv, rty) ->
+ "{" ^ symbolic_value_proj_to_string fmt sv rty ^ "}"
+
+ let abstract_shared_borrows_to_string (fmt : value_formatter)
+ (abs : V.abstract_shared_borrows) : string =
+ "{"
+ ^ String.concat "," (List.map (abstract_shared_borrow_to_string fmt) abs)
+ ^ "}"
+
+ let rec aproj_to_string (fmt : value_formatter) (pv : V.aproj) : string =
+ match pv with
+ | AProjLoans (sv, given_back) ->
+ let given_back =
+ if given_back = [] then ""
+ else
+ let given_back = List.map snd given_back in
+ let given_back = List.map (aproj_to_string fmt) given_back in
+ " (" ^ String.concat "," given_back ^ ") "
+ in
+ "⌊"
+ ^ symbolic_value_to_string (value_to_rtype_formatter fmt) sv
+ ^ given_back ^ "⌋"
+ | AProjBorrows (sv, rty) ->
+ "(" ^ symbolic_value_proj_to_string fmt sv rty ^ ")"
+ | AEndedProjLoans (_, given_back) ->
+ if given_back = [] then "_"
+ else
+ let given_back = List.map snd given_back in
+ let given_back = List.map (aproj_to_string fmt) given_back in
+ "ended_aproj_loans (" ^ String.concat "," given_back ^ ")"
+ | AEndedProjBorrows _mv -> "_"
+ | AIgnoredProjBorrows -> "_"
+
+ let rec typed_avalue_to_string (fmt : value_formatter) (v : V.typed_avalue) :
+ string =
+ let ty_fmt : PT.rtype_formatter = value_to_rtype_formatter fmt in
+ match v.value with
+ | AConcrete cv -> constant_value_to_string cv
+ | AAdt av -> (
+ let field_values =
+ List.map (typed_avalue_to_string fmt) av.field_values
+ in
+ match v.ty with
+ | T.Adt (T.Tuple, _, _) ->
+ (* Tuple *)
+ "(" ^ String.concat ", " field_values ^ ")"
+ | T.Adt (T.AdtId def_id, _, _) ->
+ (* "Regular" ADT *)
+ let adt_ident =
+ match av.variant_id with
+ | Some vid -> fmt.adt_variant_to_string def_id vid
+ | None -> fmt.type_decl_id_to_string def_id
+ in
+ if List.length field_values > 0 then
+ match fmt.adt_field_names def_id av.V.variant_id with
+ | None ->
+ let field_values = String.concat ", " field_values in
+ adt_ident ^ " (" ^ field_values ^ ")"
+ | Some field_names ->
+ let field_values = List.combine field_names field_values in
+ let field_values =
+ List.map
+ (fun (field, value) -> field ^ " = " ^ value ^ ";")
+ field_values
+ in
+ let field_values = String.concat " " field_values in
+ adt_ident ^ " { " ^ field_values ^ " }"
+ else adt_ident
+ | T.Adt (T.Assumed aty, _, _) -> (
+ (* Assumed type *)
+ match (aty, field_values) with
+ | Box, [ bv ] -> "@Box(" ^ bv ^ ")"
+ | _ -> failwith "Inconsistent value")
+ | _ -> failwith "Inconsistent typed value")
+ | ABottom -> "⊥ : " ^ PT.ty_to_string ty_fmt v.ty
+ | ABorrow bc -> aborrow_content_to_string fmt bc
+ | ALoan lc -> aloan_content_to_string fmt lc
+ | ASymbolic s -> aproj_to_string fmt s
+ | AIgnored -> "_"
+
+ and aloan_content_to_string (fmt : value_formatter) (lc : V.aloan_content) :
+ string =
+ match lc with
+ | AMutLoan (bid, av) ->
+ "⌊mut@" ^ V.BorrowId.to_string bid ^ ", "
+ ^ typed_avalue_to_string fmt av
+ ^ "⌋"
+ | ASharedLoan (loans, v, av) ->
+ let loans = V.BorrowId.Set.to_string None loans in
+ "@shared_loan(" ^ loans ^ ", "
+ ^ typed_value_to_string fmt v
+ ^ ", "
+ ^ typed_avalue_to_string fmt av
+ ^ ")"
+ | AEndedMutLoan ml ->
+ "@ended_mut_loan{"
+ ^ typed_avalue_to_string fmt ml.child
+ ^ "; "
+ ^ typed_avalue_to_string fmt ml.given_back
+ ^ " }"
+ | AEndedSharedLoan (v, av) ->
+ "@ended_shared_loan("
+ ^ typed_value_to_string fmt v
+ ^ ", "
+ ^ typed_avalue_to_string fmt av
+ ^ ")"
+ | AIgnoredMutLoan (bid, av) ->
+ "@ignored_mut_loan(" ^ V.BorrowId.to_string bid ^ ", "
+ ^ typed_avalue_to_string fmt av
+ ^ ")"
+ | AEndedIgnoredMutLoan ml ->
+ "@ended_ignored_mut_loan{ "
+ ^ typed_avalue_to_string fmt ml.child
+ ^ "; "
+ ^ typed_avalue_to_string fmt ml.given_back
+ ^ "}"
+ | AIgnoredSharedLoan sl ->
+ "@ignored_shared_loan(" ^ typed_avalue_to_string fmt sl ^ ")"
+
+ and aborrow_content_to_string (fmt : value_formatter) (bc : V.aborrow_content)
+ : string =
+ match bc with
+ | AMutBorrow (_, bid, av) ->
+ "&mut@" ^ V.BorrowId.to_string bid ^ " ("
+ ^ typed_avalue_to_string fmt av
+ ^ ")"
+ | ASharedBorrow bid -> "⌊shared@" ^ V.BorrowId.to_string bid ^ "⌋"
+ | AIgnoredMutBorrow (opt_bid, av) ->
+ "@ignored_mut_borrow("
+ ^ option_to_string V.BorrowId.to_string opt_bid
+ ^ ", "
+ ^ typed_avalue_to_string fmt av
+ ^ ")"
+ | AEndedMutBorrow (_mv, child) ->
+ "@ended_mut_borrow(" ^ typed_avalue_to_string fmt child ^ ")"
+ | AEndedIgnoredMutBorrow
+ { child; given_back_loans_proj; given_back_meta = _ } ->
+ "@ended_ignored_mut_borrow{ "
+ ^ typed_avalue_to_string fmt child
+ ^ "; "
+ ^ typed_avalue_to_string fmt given_back_loans_proj
+ ^ ")"
+ | AEndedSharedBorrow -> "@ended_shared_borrow"
+ | AProjSharedBorrow sb ->
+ "@ignored_shared_borrow("
+ ^ abstract_shared_borrows_to_string fmt sb
+ ^ ")"
+
+ let abs_to_string (fmt : value_formatter) (indent : string)
+ (indent_incr : string) (abs : V.abs) : string =
+ let indent2 = indent ^ indent_incr in
+ let avs =
+ List.map (fun av -> indent2 ^ typed_avalue_to_string fmt av) abs.avalues
+ in
+ let avs = String.concat ",\n" avs in
+ indent ^ "abs@"
+ ^ V.AbstractionId.to_string abs.abs_id
+ ^ "{parents="
+ ^ V.AbstractionId.Set.to_string None abs.parents
+ ^ "}" ^ "{regions="
+ ^ T.RegionId.Set.to_string None abs.regions
+ ^ "}" ^ " {\n" ^ avs ^ "\n" ^ indent ^ "}"
+end
+
+module PV = Values (* local module *)
+
+(** Pretty-printing for contexts *)
+module Contexts = struct
+ let binder_to_string (bv : C.binder) : string =
+ match bv.name with
+ | None -> PV.var_id_to_string bv.index
+ | Some name -> name
+
+ let env_elem_to_string (fmt : PV.value_formatter) (indent : string)
+ (indent_incr : string) (ev : C.env_elem) : string =
+ match ev with
+ | Var (var, tv) ->
+ let bv =
+ match var with Some var -> binder_to_string var | None -> "_"
+ in
+ indent ^ bv ^ " -> " ^ PV.typed_value_to_string fmt tv ^ " ;"
+ | Abs abs -> PV.abs_to_string fmt indent indent_incr abs
+ | Frame -> failwith "Can't print a Frame element"
+
+ let opt_env_elem_to_string (fmt : PV.value_formatter) (indent : string)
+ (indent_incr : string) (ev : C.env_elem option) : string =
+ match ev with
+ | None -> indent ^ "..."
+ | Some ev -> env_elem_to_string fmt indent indent_incr ev
+
+ (** Filters "dummy" bindings from an environment, to gain space and clarity/
+ See [env_to_string]. *)
+ let filter_env (env : C.env) : C.env_elem option list =
+ (* We filter:
+ * - non-dummy bindings which point to ⊥
+ * - dummy bindings which don't contain loans nor borrows
+ * Note that the first case can sometimes be confusing: we may try to improve
+ * it...
+ *)
+ let filter_elem (ev : C.env_elem) : C.env_elem option =
+ match ev with
+ | Var (Some _, tv) ->
+ (* Not a dummy binding: check if the value is ⊥ *)
+ if VU.is_bottom tv.value then None else Some ev
+ | Var (None, tv) ->
+ (* Dummy binding: check if the value contains borrows or loans *)
+ if VU.borrows_in_value tv || VU.loans_in_value tv then Some ev
+ else None
+ | _ -> Some ev
+ in
+ let env = List.map filter_elem env in
+ (* We collapse groups of filtered values - so that we can print one
+ * single "..." for a whole group of filtered values *)
+ let rec group_filtered (env : C.env_elem option list) :
+ C.env_elem option list =
+ match env with
+ | [] -> []
+ | None :: None :: env -> group_filtered (None :: env)
+ | x :: env -> x :: group_filtered env
+ in
+ group_filtered env
+
+ (** Environments can have a lot of dummy or uninitialized values: [filter]
+ allows to filter them when printing, replacing groups of such bindings with
+ "..." to gain space and clarity.
+ *)
+ let env_to_string (filter : bool) (fmt : PV.value_formatter) (env : C.env) :
+ string =
+ let env =
+ if filter then filter_env env else List.map (fun ev -> Some ev) env
+ in
+ "{\n"
+ ^ String.concat "\n"
+ (List.map (fun ev -> opt_env_elem_to_string fmt " " " " ev) env)
+ ^ "\n}"
+
+ type ctx_formatter = PV.value_formatter
+
+ let ctx_to_etype_formatter (fmt : ctx_formatter) : PT.etype_formatter =
+ PV.value_to_etype_formatter fmt
+
+ let ctx_to_rtype_formatter (fmt : ctx_formatter) : PT.rtype_formatter =
+ PV.value_to_rtype_formatter fmt
+
+ let type_ctx_to_adt_variant_to_string_fun
+ (ctx : T.type_decl T.TypeDeclId.Map.t) :
+ T.TypeDeclId.id -> T.VariantId.id -> string =
+ fun def_id variant_id ->
+ let def = T.TypeDeclId.Map.find def_id ctx in
+ match def.kind with
+ | Struct _ | Opaque -> failwith "Unreachable"
+ | Enum variants ->
+ let variant = T.VariantId.nth variants variant_id in
+ name_to_string def.name ^ "::" ^ variant.variant_name
+
+ let type_ctx_to_adt_field_names_fun (ctx : T.type_decl T.TypeDeclId.Map.t) :
+ T.TypeDeclId.id -> T.VariantId.id option -> string list option =
+ fun def_id opt_variant_id ->
+ let def = T.TypeDeclId.Map.find def_id ctx in
+ let fields = TU.type_decl_get_fields def opt_variant_id in
+ (* There are two cases: either all the fields have names, or none of them
+ * has names *)
+ let has_names =
+ List.exists (fun f -> Option.is_some f.T.field_name) fields
+ in
+ if has_names then
+ let fields = List.map (fun f -> Option.get f.T.field_name) fields in
+ Some fields
+ else None
+
+ let eval_ctx_to_ctx_formatter (ctx : C.eval_ctx) : ctx_formatter =
+ (* We shouldn't use rvar_to_string *)
+ let rvar_to_string _r = failwith "Unexpected use of rvar_to_string" in
+ let r_to_string r = PT.region_id_to_string r in
+
+ let type_var_id_to_string vid =
+ let v = C.lookup_type_var ctx vid in
+ v.name
+ in
+ let type_decl_id_to_string def_id =
+ let def = C.ctx_lookup_type_decl ctx def_id in
+ name_to_string def.name
+ in
+ let adt_variant_to_string =
+ type_ctx_to_adt_variant_to_string_fun ctx.type_context.type_decls
+ in
+ let var_id_to_string vid =
+ let bv = C.ctx_lookup_binder ctx vid in
+ binder_to_string bv
+ in
+ let adt_field_names =
+ type_ctx_to_adt_field_names_fun ctx.type_context.type_decls
+ in
+ {
+ rvar_to_string;
+ r_to_string;
+ type_var_id_to_string;
+ type_decl_id_to_string;
+ adt_variant_to_string;
+ var_id_to_string;
+ adt_field_names;
+ }
+
+ (** Split an [env] at every occurrence of [Frame], eliminating those elements.
+ Also reorders the frames and the values in the frames according to the
+ following order:
+ * frames: from the current frame to the first pushed (oldest frame)
+ * values: from the first pushed (oldest) to the last pushed
+ *)
+ let split_env_according_to_frames (env : C.env) : C.env list =
+ let rec split_aux (frames : C.env list) (curr_frame : C.env) (env : C.env) =
+ match env with
+ | [] ->
+ if List.length curr_frame > 0 then curr_frame :: frames else frames
+ | Frame :: env' -> split_aux (curr_frame :: frames) [] env'
+ | ev :: env' -> split_aux frames (ev :: curr_frame) env'
+ in
+ let frames = split_aux [] [] env in
+ frames
+
+ let eval_ctx_to_string (ctx : C.eval_ctx) : string =
+ let fmt = eval_ctx_to_ctx_formatter ctx in
+ let ended_regions = T.RegionId.Set.to_string None ctx.ended_regions in
+ let frames = split_env_according_to_frames ctx.env in
+ let num_frames = List.length frames in
+ let frames =
+ List.mapi
+ (fun i f ->
+ let num_bindings = ref 0 in
+ let num_dummies = ref 0 in
+ let num_abs = ref 0 in
+ List.iter
+ (fun ev ->
+ match ev with
+ | C.Var (None, _) -> num_dummies := !num_abs + 1
+ | C.Var (Some _, _) -> num_bindings := !num_bindings + 1
+ | C.Abs _ -> num_abs := !num_abs + 1
+ | _ -> raise (Failure "Unreachable"))
+ f;
+ "\n# Frame " ^ string_of_int i ^ ":" ^ "\n- locals: "
+ ^ string_of_int !num_bindings
+ ^ "\n- dummy bindings: " ^ string_of_int !num_dummies
+ ^ "\n- abstractions: " ^ string_of_int !num_abs ^ "\n"
+ ^ env_to_string true fmt f ^ "\n")
+ frames
+ in
+ "# Ended regions: " ^ ended_regions ^ "\n" ^ "# " ^ string_of_int num_frames
+ ^ " frame(s)\n" ^ String.concat "" frames
+end
+
+module PC = Contexts (* local module *)
+
+(** Pretty-printing for contexts (generic functions) *)
+module LlbcAst = struct
+ let var_to_string (var : A.var) : string =
+ match var.name with
+ | None -> V.VarId.to_string var.index
+ | Some name -> name
+
+ type ast_formatter = {
+ rvar_to_string : T.RegionVarId.id -> string;
+ r_to_string : T.RegionId.id -> string;
+ type_var_id_to_string : T.TypeVarId.id -> string;
+ type_decl_id_to_string : T.TypeDeclId.id -> string;
+ adt_variant_to_string : T.TypeDeclId.id -> T.VariantId.id -> string;
+ adt_field_to_string :
+ T.TypeDeclId.id -> T.VariantId.id option -> T.FieldId.id -> string option;
+ var_id_to_string : V.VarId.id -> string;
+ adt_field_names :
+ T.TypeDeclId.id -> T.VariantId.id option -> string list option;
+ fun_decl_id_to_string : A.FunDeclId.id -> string;
+ global_decl_id_to_string : A.GlobalDeclId.id -> string;
+ }
+
+ let ast_to_ctx_formatter (fmt : ast_formatter) : PC.ctx_formatter =
+ {
+ PV.rvar_to_string = fmt.rvar_to_string;
+ PV.r_to_string = fmt.r_to_string;
+ PV.type_var_id_to_string = fmt.type_var_id_to_string;
+ PV.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ PV.adt_variant_to_string = fmt.adt_variant_to_string;
+ PV.var_id_to_string = fmt.var_id_to_string;
+ PV.adt_field_names = fmt.adt_field_names;
+ }
+
+ let ast_to_value_formatter (fmt : ast_formatter) : PV.value_formatter =
+ ast_to_ctx_formatter fmt
+
+ let ast_to_etype_formatter (fmt : ast_formatter) : PT.etype_formatter =
+ {
+ PT.r_to_string = PT.erased_region_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let ast_to_rtype_formatter (fmt : ast_formatter) : PT.rtype_formatter =
+ {
+ PT.r_to_string = PT.region_to_string fmt.r_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let ast_to_stype_formatter (fmt : ast_formatter) : PT.stype_formatter =
+ {
+ PT.r_to_string = PT.region_to_string fmt.rvar_to_string;
+ PT.type_var_id_to_string = fmt.type_var_id_to_string;
+ PT.type_decl_id_to_string = fmt.type_decl_id_to_string;
+ }
+
+ let type_ctx_to_adt_field_to_string_fun (ctx : T.type_decl T.TypeDeclId.Map.t)
+ :
+ T.TypeDeclId.id -> T.VariantId.id option -> T.FieldId.id -> string option
+ =
+ fun def_id opt_variant_id field_id ->
+ let def = T.TypeDeclId.Map.find def_id ctx in
+ let fields = TU.type_decl_get_fields def opt_variant_id in
+ let field = T.FieldId.nth fields field_id in
+ field.T.field_name
+
+ let eval_ctx_to_ast_formatter (ctx : C.eval_ctx) : ast_formatter =
+ let ctx_fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ let adt_field_to_string =
+ type_ctx_to_adt_field_to_string_fun ctx.type_context.type_decls
+ in
+ let fun_decl_id_to_string def_id =
+ let def = C.ctx_lookup_fun_decl ctx def_id in
+ fun_name_to_string def.name
+ in
+ let global_decl_id_to_string def_id =
+ let def = C.ctx_lookup_global_decl ctx def_id in
+ global_name_to_string def.name
+ in
+ {
+ rvar_to_string = ctx_fmt.PV.rvar_to_string;
+ r_to_string = ctx_fmt.PV.r_to_string;
+ type_var_id_to_string = ctx_fmt.PV.type_var_id_to_string;
+ type_decl_id_to_string = ctx_fmt.PV.type_decl_id_to_string;
+ adt_variant_to_string = ctx_fmt.PV.adt_variant_to_string;
+ var_id_to_string = ctx_fmt.PV.var_id_to_string;
+ adt_field_names = ctx_fmt.PV.adt_field_names;
+ adt_field_to_string;
+ fun_decl_id_to_string;
+ global_decl_id_to_string;
+ }
+
+ let fun_decl_to_ast_formatter (type_decls : T.type_decl T.TypeDeclId.Map.t)
+ (fun_decls : A.fun_decl A.FunDeclId.Map.t)
+ (global_decls : A.global_decl A.GlobalDeclId.Map.t) (fdef : A.fun_decl) :
+ ast_formatter =
+ let rvar_to_string r =
+ let rvar = T.RegionVarId.nth fdef.signature.region_params r in
+ PT.region_var_to_string rvar
+ in
+ let r_to_string r = PT.region_id_to_string r in
+
+ let type_var_id_to_string vid =
+ let var = T.TypeVarId.nth fdef.signature.type_params vid in
+ PT.type_var_to_string var
+ in
+ let type_decl_id_to_string def_id =
+ let def = T.TypeDeclId.Map.find def_id type_decls in
+ name_to_string def.name
+ in
+ let adt_variant_to_string =
+ PC.type_ctx_to_adt_variant_to_string_fun type_decls
+ in
+ let var_id_to_string vid =
+ let var = V.VarId.nth (Option.get fdef.body).locals vid in
+ var_to_string var
+ in
+ let adt_field_names = PC.type_ctx_to_adt_field_names_fun type_decls in
+ let adt_field_to_string = type_ctx_to_adt_field_to_string_fun type_decls in
+ let fun_decl_id_to_string def_id =
+ let def = A.FunDeclId.Map.find def_id fun_decls in
+ fun_name_to_string def.name
+ in
+ let global_decl_id_to_string def_id =
+ let def = A.GlobalDeclId.Map.find def_id global_decls in
+ global_name_to_string def.name
+ in
+ {
+ rvar_to_string;
+ r_to_string;
+ type_var_id_to_string;
+ type_decl_id_to_string;
+ adt_variant_to_string;
+ var_id_to_string;
+ adt_field_names;
+ adt_field_to_string;
+ fun_decl_id_to_string;
+ global_decl_id_to_string;
+ }
+
+ let rec projection_to_string (fmt : ast_formatter) (inside : string)
+ (p : E.projection) : string =
+ match p with
+ | [] -> inside
+ | pe :: p' -> (
+ let s = projection_to_string fmt inside p' in
+ match pe with
+ | E.Deref -> "*(" ^ s ^ ")"
+ | E.DerefBox -> "deref_box(" ^ s ^ ")"
+ | E.Field (E.ProjOption variant_id, fid) ->
+ assert (variant_id = T.option_some_id);
+ assert (fid = T.FieldId.zero);
+ "(" ^ s ^ " as Option::Some)." ^ T.FieldId.to_string fid
+ | E.Field (E.ProjTuple _, fid) ->
+ "(" ^ s ^ ")." ^ T.FieldId.to_string fid
+ | E.Field (E.ProjAdt (adt_id, opt_variant_id), fid) -> (
+ let field_name =
+ match fmt.adt_field_to_string adt_id opt_variant_id fid with
+ | Some field_name -> field_name
+ | None -> T.FieldId.to_string fid
+ in
+ match opt_variant_id with
+ | None -> "(" ^ s ^ ")." ^ field_name
+ | Some variant_id ->
+ let variant_name =
+ fmt.adt_variant_to_string adt_id variant_id
+ in
+ "(" ^ s ^ " as " ^ variant_name ^ ")." ^ field_name))
+
+ let place_to_string (fmt : ast_formatter) (p : E.place) : string =
+ let var = fmt.var_id_to_string p.E.var_id in
+ projection_to_string fmt var p.E.projection
+
+ let unop_to_string (unop : E.unop) : string =
+ match unop with
+ | E.Not -> "¬"
+ | E.Neg -> "-"
+ | E.Cast (src, tgt) ->
+ "cast<"
+ ^ PT.integer_type_to_string src
+ ^ ","
+ ^ PT.integer_type_to_string tgt
+ ^ ">"
+
+ let binop_to_string (binop : E.binop) : string =
+ match binop with
+ | E.BitXor -> "^"
+ | E.BitAnd -> "&"
+ | E.BitOr -> "|"
+ | E.Eq -> "=="
+ | E.Lt -> "<"
+ | E.Le -> "<="
+ | E.Ne -> "!="
+ | E.Ge -> ">="
+ | E.Gt -> ">"
+ | E.Div -> "/"
+ | E.Rem -> "%"
+ | E.Add -> "+"
+ | E.Sub -> "-"
+ | E.Mul -> "*"
+ | E.Shl -> "<<"
+ | E.Shr -> ">>"
+
+ let operand_to_string (fmt : ast_formatter) (op : E.operand) : string =
+ match op with
+ | E.Copy p -> "copy " ^ place_to_string fmt p
+ | E.Move p -> "move " ^ place_to_string fmt p
+ | E.Constant (ty, cv) ->
+ "("
+ ^ PV.constant_value_to_string cv
+ ^ " : "
+ ^ PT.ety_to_string (ast_to_etype_formatter fmt) ty
+ ^ ")"
+
+ let rvalue_to_string (fmt : ast_formatter) (rv : E.rvalue) : string =
+ match rv with
+ | E.Use op -> operand_to_string fmt op
+ | E.Ref (p, bk) -> (
+ let p = place_to_string fmt p in
+ match bk with
+ | E.Shared -> "&" ^ p
+ | E.Mut -> "&mut " ^ p
+ | E.TwoPhaseMut -> "&two-phase " ^ p)
+ | E.UnaryOp (unop, op) ->
+ unop_to_string unop ^ " " ^ operand_to_string fmt op
+ | E.BinaryOp (binop, op1, op2) ->
+ operand_to_string fmt op1 ^ " " ^ binop_to_string binop ^ " "
+ ^ operand_to_string fmt op2
+ | E.Discriminant p -> "discriminant(" ^ place_to_string fmt p ^ ")"
+ | E.Aggregate (akind, ops) -> (
+ let ops = List.map (operand_to_string fmt) ops in
+ match akind with
+ | E.AggregatedTuple -> "(" ^ String.concat ", " ops ^ ")"
+ | E.AggregatedOption (variant_id, _ty) ->
+ if variant_id == T.option_none_id then (
+ assert (ops == []);
+ "@Option::None")
+ else if variant_id == T.option_some_id then (
+ assert (List.length ops == 1);
+ let op = List.hd ops in
+ "@Option::Some(" ^ op ^ ")")
+ else raise (Failure "Unreachable")
+ | E.AggregatedAdt (def_id, opt_variant_id, _regions, _types) ->
+ let adt_name = fmt.type_decl_id_to_string def_id in
+ let variant_name =
+ match opt_variant_id with
+ | None -> adt_name
+ | Some variant_id ->
+ adt_name ^ "::" ^ fmt.adt_variant_to_string def_id variant_id
+ in
+ let fields =
+ match fmt.adt_field_names def_id opt_variant_id with
+ | None -> "(" ^ String.concat ", " ops ^ ")"
+ | Some field_names ->
+ let fields = List.combine field_names ops in
+ let fields =
+ List.map
+ (fun (field, value) -> field ^ " = " ^ value ^ ";")
+ fields
+ in
+ let fields = String.concat " " fields in
+ "{ " ^ fields ^ " }"
+ in
+ variant_name ^ " " ^ fields)
+
+ let rec statement_to_string (fmt : ast_formatter) (indent : string)
+ (indent_incr : string) (st : A.statement) : string =
+ raw_statement_to_string fmt indent indent_incr st.content
+
+ and raw_statement_to_string (fmt : ast_formatter) (indent : string)
+ (indent_incr : string) (st : A.raw_statement) : string =
+ match st with
+ | A.Assign (p, rv) ->
+ indent ^ place_to_string fmt p ^ " := " ^ rvalue_to_string fmt rv
+ | A.AssignGlobal { dst; global } ->
+ indent ^ fmt.var_id_to_string dst ^ " := global "
+ ^ fmt.global_decl_id_to_string global
+ | A.FakeRead p -> indent ^ "fake_read " ^ place_to_string fmt p
+ | A.SetDiscriminant (p, variant_id) ->
+ (* TODO: improve this to lookup the variant name by using the def id *)
+ indent ^ "set_discriminant(" ^ place_to_string fmt p ^ ", "
+ ^ T.VariantId.to_string variant_id
+ ^ ")"
+ | A.Drop p -> indent ^ "drop " ^ place_to_string fmt p
+ | A.Assert a ->
+ let cond = operand_to_string fmt a.A.cond in
+ if a.A.expected then indent ^ "assert(" ^ cond ^ ")"
+ else indent ^ "assert(¬" ^ cond ^ ")"
+ | A.Call call ->
+ let ty_fmt = ast_to_etype_formatter fmt in
+ let t_params =
+ if List.length call.A.type_args > 0 then
+ "<"
+ ^ String.concat ","
+ (List.map (PT.ty_to_string ty_fmt) call.A.type_args)
+ ^ ">"
+ else ""
+ in
+ let args = List.map (operand_to_string fmt) call.A.args in
+ let args = "(" ^ String.concat ", " args ^ ")" in
+ let name_args =
+ match call.A.func with
+ | A.Regular fid -> fmt.fun_decl_id_to_string fid ^ t_params
+ | A.Assumed fid -> (
+ match fid with
+ | A.Replace -> "core::mem::replace" ^ t_params
+ | A.BoxNew -> "alloc::boxed::Box" ^ t_params ^ "::new"
+ | A.BoxDeref ->
+ "core::ops::deref::Deref<Box" ^ t_params ^ ">::deref"
+ | A.BoxDerefMut ->
+ "core::ops::deref::DerefMut" ^ t_params ^ "::deref_mut"
+ | A.BoxFree -> "alloc::alloc::box_free" ^ t_params
+ | A.VecNew -> "alloc::vec::Vec" ^ t_params ^ "::new"
+ | A.VecPush -> "alloc::vec::Vec" ^ t_params ^ "::push"
+ | A.VecInsert -> "alloc::vec::Vec" ^ t_params ^ "::insert"
+ | A.VecLen -> "alloc::vec::Vec" ^ t_params ^ "::len"
+ | A.VecIndex ->
+ "core::ops::index::Index<alloc::vec::Vec" ^ t_params
+ ^ ">::index"
+ | A.VecIndexMut ->
+ "core::ops::index::IndexMut<alloc::vec::Vec" ^ t_params
+ ^ ">::index_mut")
+ in
+ let dest = place_to_string fmt call.A.dest in
+ indent ^ dest ^ " := move " ^ name_args ^ args
+ | A.Panic -> indent ^ "panic"
+ | A.Return -> indent ^ "return"
+ | A.Break i -> indent ^ "break " ^ string_of_int i
+ | A.Continue i -> indent ^ "continue " ^ string_of_int i
+ | A.Nop -> indent ^ "nop"
+ | A.Sequence (st1, st2) ->
+ statement_to_string fmt indent indent_incr st1
+ ^ ";\n"
+ ^ statement_to_string fmt indent indent_incr st2
+ | A.Switch (op, tgts) -> (
+ let op = operand_to_string fmt op in
+ match tgts with
+ | A.If (true_st, false_st) ->
+ let inner_indent = indent ^ indent_incr in
+ let inner_to_string =
+ statement_to_string fmt inner_indent indent_incr
+ in
+ let true_st = inner_to_string true_st in
+ let false_st = inner_to_string false_st in
+ indent ^ "if (" ^ op ^ ") {\n" ^ true_st ^ "\n" ^ indent ^ "}\n"
+ ^ indent ^ "else {\n" ^ false_st ^ "\n" ^ indent ^ "}"
+ | A.SwitchInt (_ty, branches, otherwise) ->
+ let indent1 = indent ^ indent_incr in
+ let indent2 = indent1 ^ indent_incr in
+ let inner_to_string2 =
+ statement_to_string fmt indent2 indent_incr
+ in
+ let branches =
+ List.map
+ (fun (svl, be) ->
+ let svl =
+ List.map (fun sv -> "| " ^ PV.scalar_value_to_string sv) svl
+ in
+ let svl = String.concat " " svl in
+ indent1 ^ svl ^ " => {\n" ^ inner_to_string2 be ^ "\n"
+ ^ indent1 ^ "}")
+ branches
+ in
+ let branches = String.concat "\n" branches in
+ let branches =
+ branches ^ "\n" ^ indent1 ^ "_ => {\n"
+ ^ inner_to_string2 otherwise ^ "\n" ^ indent1 ^ "}"
+ in
+ indent ^ "switch (" ^ op ^ ") {\n" ^ branches ^ "\n" ^ indent ^ "}")
+ | A.Loop loop_st ->
+ indent ^ "loop {\n"
+ ^ statement_to_string fmt (indent ^ indent_incr) indent_incr loop_st
+ ^ "\n" ^ indent ^ "}"
+
+ let var_to_string (v : A.var) : string =
+ match v.name with None -> PV.var_id_to_string v.index | Some name -> name
+
+ let fun_decl_to_string (fmt : ast_formatter) (indent : string)
+ (indent_incr : string) (def : A.fun_decl) : string =
+ let sty_fmt = ast_to_stype_formatter fmt in
+ let sty_to_string = PT.sty_to_string sty_fmt in
+ let ety_fmt = ast_to_etype_formatter fmt in
+ let ety_to_string = PT.ety_to_string ety_fmt in
+ let sg = def.signature in
+
+ (* Function name *)
+ let name = fun_name_to_string def.A.name in
+
+ (* Region/type parameters *)
+ let regions = sg.region_params in
+ let types = sg.type_params in
+ let params =
+ if List.length regions + List.length types = 0 then ""
+ else
+ let regions = List.map PT.region_var_to_string regions in
+ let types = List.map PT.type_var_to_string types in
+ "<" ^ String.concat "," (List.append regions types) ^ ">"
+ in
+
+ (* Return type *)
+ let ret_ty = sg.output in
+ let ret_ty =
+ if TU.ty_is_unit ret_ty then "" else " -> " ^ sty_to_string ret_ty
+ in
+
+ (* We print the declaration differently if it is opaque (no body) or transparent
+ * (we have access to a body) *)
+ match def.body with
+ | None ->
+ (* Arguments *)
+ let input_tys = sg.inputs in
+ let args = List.map sty_to_string input_tys in
+ let args = String.concat ", " args in
+
+ (* Put everything together *)
+ indent ^ "opaque fn " ^ name ^ params ^ "(" ^ args ^ ")" ^ ret_ty
+ | Some body ->
+ (* Arguments *)
+ let inputs = List.tl body.locals in
+ let inputs, _aux_locals =
+ Collections.List.split_at inputs body.arg_count
+ in
+ let args = List.combine inputs sg.inputs in
+ let args =
+ List.map
+ (fun (var, rty) -> var_to_string var ^ " : " ^ sty_to_string rty)
+ args
+ in
+ let args = String.concat ", " args in
+
+ (* All the locals (with erased regions) *)
+ let locals =
+ List.map
+ (fun var ->
+ indent ^ indent_incr ^ var_to_string var ^ " : "
+ ^ ety_to_string var.var_ty ^ ";")
+ body.locals
+ in
+ let locals = String.concat "\n" locals in
+
+ (* Body *)
+ let body =
+ statement_to_string fmt (indent ^ indent_incr) indent_incr body.body
+ in
+
+ (* Put everything together *)
+ indent ^ "fn " ^ name ^ params ^ "(" ^ args ^ ")" ^ ret_ty ^ " {\n"
+ ^ locals ^ "\n\n" ^ body ^ "\n" ^ indent ^ "}"
+end
+
+module PA = LlbcAst (* local module *)
+
+(** Pretty-printing for ASTs (functions based on a definition context) *)
+module Module = struct
+ (** This function pretty-prints a type definition by using a definition
+ context *)
+ let type_decl_to_string (type_context : T.type_decl T.TypeDeclId.Map.t)
+ (def : T.type_decl) : string =
+ let type_decl_id_to_string (id : T.TypeDeclId.id) : string =
+ let def = T.TypeDeclId.Map.find id type_context in
+ name_to_string def.name
+ in
+ PT.type_decl_to_string type_decl_id_to_string def
+
+ (** Generate an [ast_formatter] by using a definition context in combination
+ with the variables local to a function's definition *)
+ let def_ctx_to_ast_formatter (type_context : T.type_decl T.TypeDeclId.Map.t)
+ (fun_context : A.fun_decl A.FunDeclId.Map.t)
+ (global_context : A.global_decl A.GlobalDeclId.Map.t) (def : A.fun_decl) :
+ PA.ast_formatter =
+ let rvar_to_string vid =
+ let var = T.RegionVarId.nth def.signature.region_params vid in
+ PT.region_var_to_string var
+ in
+ let r_to_string vid =
+ (* TODO: we might want something more informative *)
+ PT.region_id_to_string vid
+ in
+ let type_var_id_to_string vid =
+ let var = T.TypeVarId.nth def.signature.type_params vid in
+ PT.type_var_to_string var
+ in
+ let type_decl_id_to_string def_id =
+ let def = T.TypeDeclId.Map.find def_id type_context in
+ name_to_string def.name
+ in
+ let fun_decl_id_to_string def_id =
+ let def = A.FunDeclId.Map.find def_id fun_context in
+ fun_name_to_string def.name
+ in
+ let global_decl_id_to_string def_id =
+ let def = A.GlobalDeclId.Map.find def_id global_context in
+ global_name_to_string def.name
+ in
+ let var_id_to_string vid =
+ let var = V.VarId.nth (Option.get def.body).locals vid in
+ PA.var_to_string var
+ in
+ let adt_variant_to_string =
+ PC.type_ctx_to_adt_variant_to_string_fun type_context
+ in
+ let adt_field_to_string =
+ PA.type_ctx_to_adt_field_to_string_fun type_context
+ in
+ let adt_field_names = PC.type_ctx_to_adt_field_names_fun type_context in
+ {
+ rvar_to_string;
+ r_to_string;
+ type_var_id_to_string;
+ type_decl_id_to_string;
+ adt_variant_to_string;
+ adt_field_to_string;
+ var_id_to_string;
+ adt_field_names;
+ fun_decl_id_to_string;
+ global_decl_id_to_string;
+ }
+
+ (** This function pretty-prints a function definition by using a definition
+ context *)
+ let fun_decl_to_string (type_context : T.type_decl T.TypeDeclId.Map.t)
+ (fun_context : A.fun_decl A.FunDeclId.Map.t)
+ (global_context : A.global_decl A.GlobalDeclId.Map.t) (def : A.fun_decl) :
+ string =
+ let fmt =
+ def_ctx_to_ast_formatter type_context fun_context global_context def
+ in
+ PA.fun_decl_to_string fmt "" " " def
+
+ let module_to_string (m : Crates.llbc_crate) : string =
+ let types_defs_map, funs_defs_map, globals_defs_map =
+ Crates.compute_defs_maps m
+ in
+
+ (* The types *)
+ let type_decls =
+ List.map (type_decl_to_string types_defs_map) m.Crates.types
+ in
+
+ (* The functions *)
+ let fun_decls =
+ List.map
+ (fun_decl_to_string types_defs_map funs_defs_map globals_defs_map)
+ m.Crates.functions
+ in
+
+ (* Put everything together *)
+ let all_defs = List.append type_decls fun_decls in
+ String.concat "\n\n" all_defs
+end
+
+(** Pretty-printing for LLBC ASTs (functions based on an evaluation context) *)
+module EvalCtxLlbcAst = struct
+ let ety_to_string (ctx : C.eval_ctx) (t : T.ety) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ let fmt = PC.ctx_to_etype_formatter fmt in
+ PT.ety_to_string fmt t
+
+ let rty_to_string (ctx : C.eval_ctx) (t : T.rty) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ let fmt = PC.ctx_to_rtype_formatter fmt in
+ PT.rty_to_string fmt t
+
+ let borrow_content_to_string (ctx : C.eval_ctx) (bc : V.borrow_content) :
+ string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.borrow_content_to_string fmt bc
+
+ let loan_content_to_string (ctx : C.eval_ctx) (lc : V.loan_content) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.loan_content_to_string fmt lc
+
+ let aborrow_content_to_string (ctx : C.eval_ctx) (bc : V.aborrow_content) :
+ string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.aborrow_content_to_string fmt bc
+
+ let aloan_content_to_string (ctx : C.eval_ctx) (lc : V.aloan_content) : string
+ =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.aloan_content_to_string fmt lc
+
+ let aproj_to_string (ctx : C.eval_ctx) (p : V.aproj) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.aproj_to_string fmt p
+
+ let symbolic_value_to_string (ctx : C.eval_ctx) (sv : V.symbolic_value) :
+ string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ let fmt = PC.ctx_to_rtype_formatter fmt in
+ PV.symbolic_value_to_string fmt sv
+
+ let typed_value_to_string (ctx : C.eval_ctx) (v : V.typed_value) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.typed_value_to_string fmt v
+
+ let typed_avalue_to_string (ctx : C.eval_ctx) (v : V.typed_avalue) : string =
+ let fmt = PC.eval_ctx_to_ctx_formatter ctx in
+ PV.typed_avalue_to_string fmt v
+
+ let place_to_string (ctx : C.eval_ctx) (op : E.place) : string =
+ let fmt = PA.eval_ctx_to_ast_formatter ctx in
+ PA.place_to_string fmt op
+
+ let operand_to_string (ctx : C.eval_ctx) (op : E.operand) : string =
+ let fmt = PA.eval_ctx_to_ast_formatter ctx in
+ PA.operand_to_string fmt op
+
+ let statement_to_string (ctx : C.eval_ctx) (indent : string)
+ (indent_incr : string) (e : A.statement) : string =
+ let fmt = PA.eval_ctx_to_ast_formatter ctx in
+ PA.statement_to_string fmt indent indent_incr e
+end