diff options
author | Son Ho | 2021-11-29 17:00:46 +0100 |
---|---|---|
committer | Son Ho | 2021-11-29 17:00:46 +0100 |
commit | 30628d4bbc3ea8a4b2e716d5c83323599ed98cce (patch) | |
tree | 64bbd82258afb1353f33b48abf1a4b6b528f5af4 /src/Print.ml | |
parent | 18298def3e1bda9c5db907d4b0432557a76df337 (diff) |
Start working logging and make progress on printing ASTs
Diffstat (limited to 'src/Print.ml')
-rw-r--r-- | src/Print.ml | 179 |
1 files changed, 176 insertions, 3 deletions
diff --git a/src/Print.ml b/src/Print.ml index 8d3e8745..9c9a7a5b 100644 --- a/src/Print.ml +++ b/src/Print.ml @@ -1,5 +1,8 @@ -open Errors +(* TODO: use one letter abbreviations for modules *) + open Identifiers +module T = Types +module V = Values open Types (** Pretty-printing for types *) @@ -73,7 +76,8 @@ module Types = struct let params = params_to_string fmt regions tys in match aty with Box -> "std::boxed::Box" ^ params) - and params_to_string fmt (regions : 'r list) (types : 'r ty list) : string = + and params_to_string (fmt : 'r type_formatter) (regions : 'r list) + (types : 'r ty list) : string = if List.length regions + List.length types > 0 then let regions = List.map fmt.r_to_string regions in let types = List.map (ty_to_string fmt) types in @@ -145,6 +149,7 @@ end (** Pretty-printing for values *) open Values +module PT = Types (* local module *) module Values = struct open Types (* local module *) @@ -159,7 +164,7 @@ module Values = struct let value_to_etype_formatter (fmt : value_formatter) : etype_formatter = { - Types.r_to_string = erased_region_to_string; + Types.r_to_string = PT.erased_region_to_string; Types.type_var_id_to_string = fmt.type_var_id_to_string; Types.type_def_id_to_string = fmt.type_def_id_to_string; } @@ -465,3 +470,171 @@ module Contexts = struct in "# " ^ string_of_int num_frames ^ " frame(s)\n" ^ String.concat "" frames end + +module E = Expressions +module A = CfimAst + +module CfimAst = struct + module PV = Values + module PC = Contexts + module PT = Types + + type ast_formatter = { + r_to_string : RegionVarId.id -> string; + type_var_id_to_string : TypeVarId.id -> string; + type_def_id_to_string : TypeDefId.id -> string; + (* TODO: rename to something like adt_variant_to_string *) + type_def_id_variant_id_to_string : TypeDefId.id -> VariantId.id -> string; + adt_field_to_string : + TypeDefId.id -> VariantId.id option -> FieldId.id -> string; + var_id_to_string : VarId.id -> string; + fun_def_id_to_string : A.FunDefId.id -> string; + } + + let ast_to_ctx_formatter (fmt : ast_formatter) : PC.ctx_formatter = + { + PV.r_to_string = fmt.r_to_string; + PV.type_var_id_to_string = fmt.type_var_id_to_string; + PV.type_def_id_to_string = fmt.type_def_id_to_string; + PV.type_def_id_variant_id_to_string = fmt.type_def_id_variant_id_to_string; + PV.var_id_to_string = fmt.var_id_to_string; + } + + 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_def_id_to_string = fmt.type_def_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.ProjTuple _, fid) -> "(" ^ s ^ ")." ^ FieldId.to_string fid + | E.Field (E.ProjAdt (adt_id, opt_variant_id), fid) -> ( + let field_name = + fmt.adt_field_to_string adt_id opt_variant_id fid + in + match opt_variant_id with + | None -> "(" ^ s ^ ")." ^ field_name + | Some variant_id -> + let variant_name = + fmt.type_def_id_variant_id_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 -> "-" + + 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_constant_value_to_string (fmt : ast_formatter) + (cv : E.operand_constant_value) : string = + match cv with + | E.ConstantValue cv -> PV.constant_value_to_string cv + | E.ConstantAdt def_id -> fmt.type_def_id_to_string def_id + | E.Unit -> "()" + + 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) -> operand_constant_value_to_string fmt cv + + 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.AggregatedAdt (def_id, opt_variant_id, _regions, _types) -> ( + let adt_name = fmt.type_def_id_to_string def_id in + match opt_variant_id with + | None -> adt_name ^ "{ " ^ String.concat ", " ops ^ " }" + | Some variant_id -> + let variant_name = + fmt.type_def_id_variant_id_to_string def_id variant_id + in + adt_name ^ "::" ^ variant_name ^ "(" ^ String.concat ", " ops + ^ ")")) + + let statement_to_string (fmt : ast_formatter) (st : A.statement) : string = + match st with + | A.Assign (p, rv) -> + place_to_string fmt p ^ " := " ^ rvalue_to_string fmt rv + | A.FakeRead p -> "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 *) + "set_discriminant(" ^ place_to_string fmt p ^ ", " + ^ T.VariantId.to_string variant_id + ^ ")" + | A.Drop p -> "drop(" ^ place_to_string fmt p ^ ")" + | A.Assert a -> + let cond = operand_to_string fmt a.A.cond in + if a.A.expected then "assert(" ^ cond ^ ")" + else "assert(¬" ^ cond ^ ")" + | A.Call call -> ( + let ty_fmt = ast_to_etype_formatter fmt in + let params = + if List.length call.A.type_params > 0 then + "<" + ^ String.concat "," + (List.map (PT.ty_to_string ty_fmt) call.A.type_params) + ^ ">" + else "" + in + match call.A.func with + | A.Local fid -> fmt.fun_def_id_to_string fid ^ params + | A.Assumed fid -> ( + match fid with + | A.BoxNew -> "alloc::boxed::Box" ^ params ^ "::new" + | A.BoxDeref -> "core::ops::deref::Deref<Box" ^ params ^ ">::deref" + | A.BoxDerefMut -> + "core::ops::deref::DerefMut<Box" ^ params ^ ">::deref_mut" + | A.BoxFree -> "alloc::alloc::box_free<" ^ params ^ ">")) + | A.Panic -> "panic" + | A.Return -> "return" + | A.Break i -> "break " ^ string_of_int i + | A.Continue i -> "continue " ^ string_of_int i + | A.Nop -> "nop" +end |