Skip to content

Commit

Permalink
Merge pull request #1527 from goblint/apron-pretty
Browse files Browse the repository at this point in the history
Refactor Apron `Printable`s
  • Loading branch information
sim642 authored Jul 28, 2024
2 parents 4ca8df9 + eb78ad7 commit bccb230
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/analyses/apron/relationAnalysis.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ struct
(* there should be smarter ways to do this, e.g. by keeping track of which values are written etc. ... *)
(* See, e.g, Beckschulze E, Kowalewski S, Brauer J (2012) Access-based localization for octagons. Electron Notes Theor Comput Sci 287:29–40 *)
(* Also, a local *)
let vname = Apron.Var.to_string var in
let vname = GobApron.Var.show var in
let locals = fundec.sformals @ fundec.slocals in
match List.find_opt (fun v -> VM.var_name (Local v) = vname) locals with (* TODO: optimize *)
| None -> true
Expand Down Expand Up @@ -418,7 +418,7 @@ struct
in
let any_local_reachable = any_local_reachable fundec reachable_from_args in
let arg_vars = f.sformals |> List.filter (RD.Tracked.varinfo_tracked) |> List.map RV.arg in
if M.tracing then M.tracel "combine-rel" "relation remove vars: %a" (docList (fun v -> Pretty.text (Apron.Var.to_string v))) arg_vars;
if M.tracing then M.tracel "combine-rel" "relation remove vars: %a" (docList (GobApron.Var.pretty ())) arg_vars;
RD.remove_vars_with new_fun_rel arg_vars; (* fine to remove arg vars that also exist in caller because unify from new_rel adds them back with proper constraints *)
let tainted = f_ask.f Queries.MayBeTainted in
let tainted_vars = TaintPartialContexts.conv_varset tainted in
Expand Down
15 changes: 7 additions & 8 deletions src/cdomains/apron/affineEqualityDomain.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ struct
else if Z.lt coeff Z.minus_one then Z.to_string coeff
else Format.asprintf "+%s" (Z.to_string coeff)
in
coeff_str ^ Var.to_string var
coeff_str ^ Var.show var
in
let const_to_str vl =
if Z.equal vl Z.zero then
Expand All @@ -203,11 +203,10 @@ struct
| Some m when Matrix.is_empty m -> ""
| Some m ->
let constraint_list = List.init (Matrix.num_rows m) (fun i -> vec_to_constraint (conv_to_ints @@ Matrix.get_row m i) t.env) in
Format.asprintf "%s" ("[|"^ (String.concat "; " constraint_list) ^"|]")
"[|"^ (String.concat "; " constraint_list) ^"|]"

let pretty () (x:t) = text (show x)
let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nmatrix\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%s</value>\n</map>\n</value>\n" (XmlUtil.escape (Format.asprintf "%s" (show x) )) (XmlUtil.escape (Format.asprintf "%a" (Environment.print: Format.formatter -> Environment.t -> unit) (x.env)))

let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nmatrix\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%a</value>\n</map>\n</value>\n" (XmlUtil.escape (show x)) Environment.printXml x.env
let eval_interval ask = Bounds.bound_texpr

let name () = "affeq"
Expand Down Expand Up @@ -430,8 +429,8 @@ struct

let assign_exp ask t var exp no_ov =
let res = assign_exp ask t var exp no_ov in
if M.tracing then M.tracel "ops" "assign_exp t:\n %s \n var: %s \n exp: %a\n no_ov: %b -> \n %s"
(show t) (Var.to_string var) d_exp exp (Lazy.force no_ov) (show res) ;
if M.tracing then M.tracel "ops" "assign_exp t:\n %s \n var: %a \n exp: %a\n no_ov: %b -> \n %s"
(show t) Var.pretty var d_exp exp (Lazy.force no_ov) (show res);
res

let assign_var (t: VarManagement(Vc)(Mx).t) v v' =
Expand All @@ -441,7 +440,7 @@ struct

let assign_var t v v' =
let res = assign_var t v v' in
if M.tracing then M.tracel "ops" "assign_var t:\n %s \n v: %s \n v': %s\n -> %s" (show t) (Var.to_string v) (Var.to_string v') (show res) ;
if M.tracing then M.tracel "ops" "assign_var t:\n %s \n v: %a \n v': %a\n -> %s" (show t) Var.pretty v Var.pretty v' (show res);
res

let assign_var_parallel t vv's =
Expand Down Expand Up @@ -499,7 +498,7 @@ struct

let substitute_exp ask t var exp no_ov =
let res = substitute_exp ask t var exp no_ov in
if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %s \n exp: %a \n -> \n %s" (show t) (Var.to_string var) d_exp exp (show res);
if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res);
res

let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov
Expand Down
18 changes: 8 additions & 10 deletions src/cdomains/apron/apronDomain.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ struct
let assign_exp_with ask nd v e no_ov =
match Convert.texpr1_of_cil_exp ask nd (A.env nd) e no_ov with
| texpr1 ->
if M.tracing then M.trace "apron" "assign_exp converted: %s" (Format.asprintf "%a" Texpr1.print texpr1);
if M.tracing then M.trace "apron" "assign_exp converted: %a" Texpr1.pretty texpr1;
A.assign_texpr_with Man.mgr nd v texpr1 None
| exception Convert.Unsupported_CilExp _ ->
if M.tracing then M.trace "apron" "assign_exp unsupported";
Expand Down Expand Up @@ -442,7 +442,7 @@ struct
let invariant _ = []

let show (x:t) =
Format.asprintf "%a (env: %a)" A.print x (Environment.print: Format.formatter -> Environment.t -> unit) (A.env x)
GobFormat.asprintf "%a (env: %a)" A.print x Environment.pp (A.env x)
let pretty () (x:t) = text (show x)

let equal x y =
Expand All @@ -454,7 +454,7 @@ struct
let compare (x: t) (y: t): int =
failwith "Apron.Abstract1 doesn't have total order" (* https://github.com/antoinemine/apron/issues/99 *)

let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nconstraints\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%s</value>\n</map>\n</value>\n" (XmlUtil.escape (Format.asprintf "%a" A.print x)) (XmlUtil.escape (Format.asprintf "%a" (Environment.print: Format.formatter -> Environment.t -> unit) (A.env x)))
let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nconstraints\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%a</value>\n</map>\n</value>\n" (XmlUtil.escape (GobFormat.asprint A.print x)) Environment.printXml (A.env x)

let to_yojson (x: t) =
let constraints =
Expand All @@ -463,11 +463,9 @@ struct
|> Lincons1Set.elements
|> List.map (fun lincons1 -> `String (Lincons1.show lincons1))
in
let env = `String (Format.asprintf "%a" (Environment.print: Format.formatter -> Environment.t -> unit) (A.env x))
in
`Assoc [
("constraints", `List constraints);
("env", env);
("env", Environment.to_yojson (A.env x));
]

let unify x y =
Expand Down Expand Up @@ -533,9 +531,9 @@ struct
| _ ->
begin match Convert.tcons1_of_cil_exp ask d (A.env d) e negate no_ov with
| tcons1 ->
if M.tracing then M.trace "apron" "assert_constraint %a %s" d_exp e (Format.asprintf "%a" Tcons1.print tcons1);
if M.tracing then M.trace "apron" "assert_constraint %a %a" d_exp e Tcons1.pretty tcons1;
if M.tracing then M.trace "apron" "assert_constraint st: %a" D.pretty d;
if M.tracing then M.trace "apron" "assert_constraint tcons1: %s" (Format.asprintf "%a" Tcons1.print tcons1);
if M.tracing then M.trace "apron" "assert_constraint tcons1: %a" Tcons1.pretty tcons1;
let r = meet_tcons ask d tcons1 e in
if M.tracing then M.trace "apron" "assert_constraint r: %a" D.pretty r;
r
Expand Down Expand Up @@ -598,7 +596,7 @@ struct
let x_cons = A.to_lincons_array Man.mgr x_j in
let y_cons = A.to_lincons_array Man.mgr y_j in
let try_add_con j con1 =
if M.tracing then M.tracei "apron" "try_add_con %s" (Format.asprintf "%a" (Lincons1.print: Format.formatter -> Lincons1.t -> unit) con1);
if M.tracing then M.tracei "apron" "try_add_con %a" Lincons1.pretty con1;
let t = meet_lincons j con1 in
let t_x = A.change_environment Man.mgr t x_env false in
let t_y = A.change_environment Man.mgr t y_env false in
Expand Down Expand Up @@ -637,7 +635,7 @@ struct
in
let env_exists_mem_con1 env con1 =
let r = env_exists_mem_con1 env con1 in
if M.tracing then M.trace "apron" "env_exists_mem_con1 %s %s -> %B" (Format.asprintf "%a" (Environment.print: Format.formatter -> Environment.t -> unit) env) (Lincons1.show con1) r;
if M.tracing then M.trace "apron" "env_exists_mem_con1 %a %a -> %B" Environment.pretty env Lincons1.pretty con1 r;
r
in
(* Heuristically reorder constraints to pass 36/12 with singlethreaded->multithreaded mode switching. *)
Expand Down
78 changes: 77 additions & 1 deletion src/cdomains/apron/gobApron.apron.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
open Batteries
include Apron

module Scalar =
struct
include Scalar

let pp = print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)
end

module Coeff =
struct
include Coeff
Expand All @@ -11,14 +24,30 @@ end
module Var =
struct
include Var

let pp = print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)

let equal x y = Var.compare x y = 0
end

module Lincons1 =
struct
include Lincons1

let show = Format.asprintf "%a" print
let pp = print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)

let compare x y =
(* TODO: implement proper total Lincons1 order *)
String.compare (show x) (show y) (* HACK *)
Expand All @@ -45,12 +74,59 @@ struct
|> of_enum
end

module Texpr1 =
struct
include Texpr1

let pp = print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)

module Expr =
struct
type t = expr

let pp = print_expr
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)
end
end

module Tcons1 =
struct
include Tcons1

let pp = print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)
end

(** A few code elements for environment changes from functions as remove_vars etc. have been moved to sharedFunctions as they are needed in a similar way inside affineEqualityDomain.
A module that includes various methods used by variable handling operations such as add_vars, remove_vars etc. in apronDomain and affineEqualityDomain. *)
module Environment =
struct
include Environment

let pp: Format.formatter -> Environment.t -> unit = Environment.print
include Printable.SimpleFormat (
struct
type nonrec t = t
let pp = pp
end
)

let compare (x: t) (y: t): int =
(* TODO: implement total Environment order in OCaml *)
failwith "Apron.Environment doesn't have total order" (* https://github.com/antoinemine/apron/issues/99 *)
Expand Down
16 changes: 8 additions & 8 deletions src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ open Batteries
open GoblintCil
open Pretty
module M = Messages
open Apron
open GobApron
open VectorMatrix

module Mpqf = SharedFunctions.Mpqf
Expand Down Expand Up @@ -331,7 +331,7 @@ struct

let simplified_monomials_from_texp (t: t) texp =
let res = simplified_monomials_from_texp t texp in
if M.tracing then M.tracel "from_texp" "%s %s -> %s" (EConj.show @@ snd @@ BatOption.get t.d) (Format.asprintf "%a" Texpr1.print_expr texp)
if M.tracing then M.tracel "from_texp" "%s %a -> %s" (EConj.show @@ snd @@ BatOption.get t.d) Texpr1.Expr.pretty texp
(BatOption.map_default (fun (l,(o,d)) -> List.fold_right (fun (a,x,b) acc -> Printf.sprintf "%s*var_%d/%s + %s" (Z.to_string a) x (Z.to_string b) acc) l ((Z.to_string o)^"/"^(Z.to_string d))) "" res);
res

Expand Down Expand Up @@ -361,7 +361,7 @@ struct
else
match simplify_to_ref_and_offset t (Texpr1.to_expr texpr) with
| Some (None, offset, divisor) when Z.equal (Z.rem offset divisor) Z.zero -> let res = Z.div offset divisor in
(if M.tracing then M.tracel "bounds" "min: %s max: %s" (IntOps.BigIntOps.to_string res) (IntOps.BigIntOps.to_string res);
(if M.tracing then M.tracel "bounds" "min: %a max: %a" GobZ.pretty res GobZ.pretty res;
Some res, Some res)
| _ -> None, None

Expand Down Expand Up @@ -424,7 +424,7 @@ struct
EConj.show_formatted (show_var varM.env) (snd arr) ^ (to_subscript @@ fst arr)

let pretty () (x:t) = text (show x)
let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nequalities\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%s</value>\n</map>\n</value>\n" (XmlUtil.escape (Format.asprintf "%s" (show x) )) (XmlUtil.escape (Format.asprintf "%a" (Environment.print: Format.formatter -> Environment.t -> unit) (x.env)))
let printXml f x = BatPrintf.fprintf f "<value>\n<map>\n<key>\nequalities\n</key>\n<value>\n%s</value>\n<key>\nenv\n</key>\n<value>\n%a</value>\n</map>\n</value>\n" (XmlUtil.escape (show x)) Environment.printXml x.env
let eval_interval ask = Bounds.bound_texpr

let meet_with_one_conj t i (var, o, divi) =
Expand Down Expand Up @@ -630,8 +630,8 @@ struct

let assign_exp ask t var exp no_ov =
let res = assign_exp ask t var exp no_ov in
if M.tracing then M.tracel "ops" "assign_exp t:\n %s \n var: %s \n exp: %a\n no_ov: %b -> \n %s"
(show t) (Var.to_string var) d_exp exp (Lazy.force no_ov) (show res) ;
if M.tracing then M.tracel "ops" "assign_exp t:\n %s \n var: %a \n exp: %a\n no_ov: %b -> \n %s"
(show t) Var.pretty var d_exp exp (Lazy.force no_ov) (show res);
res

let assign_var (t: VarManagement.t) v v' =
Expand All @@ -640,7 +640,7 @@ struct

let assign_var t v v' =
let res = assign_var t v v' in
if M.tracing then M.tracel "ops" "assign_var t:\n %s \n v: %s \n v': %s\n -> %s" (show t) (Var.to_string v) (Var.to_string v') (show res) ;
if M.tracing then M.tracel "ops" "assign_var t:\n %s \n v: %a \n v': %a\n -> %s" (show t) Var.pretty v Var.pretty v' (show res);
res

(** Parallel assignment of variables.
Expand Down Expand Up @@ -693,7 +693,7 @@ struct

let substitute_exp ask t var exp no_ov =
let res = substitute_exp ask t var exp no_ov in
if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %s \n exp: %a \n -> \n %s" (show t) (Var.to_string var) d_exp exp (show res);
if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res);
res

let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov
Expand Down
10 changes: 5 additions & 5 deletions src/cdomains/apron/sharedFunctions.apron.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ let int_of_scalar ?(scalewith=Z.one) ?round (scalar: Scalar.t) =
in
Z_mlgmpidl.z_of_mpzf z
| _ ->
failwith ("int_of_scalar: unsupported: " ^ Scalar.to_string scalar)
failwith ("int_of_scalar: unsupported: " ^ Scalar.show scalar)


module type ConvertArg =
Expand Down Expand Up @@ -200,7 +200,7 @@ struct
in
let exp = Cil.constFold false exp in
let res = conv exp in
if M.tracing then M.trace "relation" "texpr1_expr_of_cil_exp: %a -> %s (%b)" d_plainexp exp (Format.asprintf "%a" Texpr1.print_expr res) (Lazy.force no_ov);
if M.tracing then M.trace "relation" "texpr1_expr_of_cil_exp: %a -> %a (%b)" d_plainexp exp Texpr1.Expr.pretty res (Lazy.force no_ov);
res

let texpr1_of_cil_exp ask d env e no_ov =
Expand Down Expand Up @@ -267,7 +267,7 @@ struct
else
Const (CInt(i,ILongLong,None)), false
else
(M.warn ~category:Analyzer "Invariant Apron: coefficient is not int: %s" (Scalar.to_string c); raise Unsupported_Linexpr1)
(M.warn ~category:Analyzer "Invariant Apron: coefficient is not int: %a" Scalar.pretty c; raise Unsupported_Linexpr1)
| None -> raise Unsupported_Linexpr1)
| _ -> raise Unsupported_Linexpr1
in
Expand All @@ -282,8 +282,8 @@ struct
expr := BinOp(MinusA,!expr,prod,longlong)
else
expr := BinOp(PlusA,!expr,prod,longlong)
| None -> M.warn ~category:Analyzer "Invariant Apron: cannot convert to cil var: %s" (Var.to_string v); raise Unsupported_Linexpr1
| _ -> M.warn ~category:Analyzer "Invariant Apron: cannot convert to cil var in overflow preserving manner: %s" (Var.to_string v); raise Unsupported_Linexpr1
| None -> M.warn ~category:Analyzer "Invariant Apron: cannot convert to cil var: %a" Var.pretty v; raise Unsupported_Linexpr1
| _ -> M.warn ~category:Analyzer "Invariant Apron: cannot convert to cil var in overflow preserving manner: %a" Var.pretty v; raise Unsupported_Linexpr1
in
Linexpr1.iter append_summand linexpr1;
!expr
Expand Down
14 changes: 14 additions & 0 deletions src/common/domains/printable.ml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ struct
let to_yojson x = `String (show x)
end

module type Formatable =
sig
type t
val pp: Format.formatter -> t -> unit
end

module SimpleFormat (P: Formatable) =
struct
let show x = GobFormat.asprint P.pp x
let pretty () x = text (show x)
let printXml f x = BatPrintf.fprintf f "<value>\n<data>\n%s\n</data>\n</value>\n" (XmlUtil.escape (show x))
let to_yojson x = `String (show x)
end


module type Name = sig val name: string end
module UnitConf (N: Name) =
Expand Down
9 changes: 9 additions & 0 deletions src/common/util/gobFormat.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@ let pp_set_ansi_color_tags ppf =
Format.pp_set_mark_tags ppf true

let pp_print_nothing (ppf: Format.formatter) () = ()

let pp_infinity = 1000000001 (* Exact value not exposed before OCaml 5.2, but use the smallest value permitted by documentation. *)

let pp_set_infinite_geometry = Format.pp_set_geometry ~max_indent:(pp_infinity - 2) ~margin:(pp_infinity - 1)

let asprintf (fmt: ('a, Format.formatter, unit, string) format4): 'a =
Format.asprintf ("%t" ^^ fmt) pp_set_infinite_geometry

let asprint pp x = asprintf "%a" pp x (* eta-expanded to bypass value restriction *)

0 comments on commit bccb230

Please sign in to comment.