diff --git a/Gillian-C/lib/External.ml b/Gillian-C/lib/External.ml index a47d02389..f8e299375 100644 --- a/Gillian-C/lib/External.ml +++ b/Gillian-C/lib/External.ml @@ -39,7 +39,7 @@ struct (state : State.t) (cs : Call_stack.t) (i : int) - (x : string) + (x : Var.t) (pid : string) (v_args : Val.t list) (j : int option) = diff --git a/Gillian-C/lib/LocMap.ml b/Gillian-C/lib/LocMap.ml new file mode 100644 index 000000000..c6eb4b606 --- /dev/null +++ b/Gillian-C/lib/LocMap.ml @@ -0,0 +1 @@ +include Map.Make (Gil_syntax.Id.Loc) diff --git a/Gillian-C/lib/MonadicSMemory.ml b/Gillian-C/lib/MonadicSMemory.ml index 1a0928d45..951e00644 100644 --- a/Gillian-C/lib/MonadicSMemory.ml +++ b/Gillian-C/lib/MonadicSMemory.ml @@ -18,7 +18,7 @@ module Recovery_tactic = Gillian.General.Recovery_tactic type init_data = Global_env.t -let resolve_or_create_loc_name (lvar_loc : Expr.t) : string Delayed.t = +let resolve_or_create_loc_name (lvar_loc : Expr.t) : Id.any_loc Id.t Delayed.t = let open Delayed.Syntax in let* loc_name = Delayed.resolve_loc lvar_loc in match loc_name with @@ -26,15 +26,21 @@ let resolve_or_create_loc_name (lvar_loc : Expr.t) : string Delayed.t = let new_loc_name = ALoc.alloc () in let learned = [ Expr.BinOp (ALoc new_loc_name, Equal, lvar_loc) ] in Logging.verbose (fun fmt -> - fmt "Couldn't resolve loc %a, created %s" Expr.pp lvar_loc + fmt "Couldn't resolve loc %a, created %a" Expr.pp lvar_loc Id.pp new_loc_name); - Delayed.return ~learned new_loc_name + Delayed.return ~learned (new_loc_name :> Id.any_loc Id.t) | Some l -> - Logging.verbose (fun fmt -> fmt "Resolved %a as %s" Expr.pp lvar_loc l); + Logging.verbose (fun fmt -> + fmt "Resolved %a as %a" Expr.pp lvar_loc Id.pp l); Delayed.return l type vt = Values.t type st = Subst.t +type loc_t = Id.any_loc Id.t + +let pp_loc_t = Id.pp +let loc_t_to_yojson = Id.to_yojson' +let loc_t_of_yojson = Id.of_yojson' (* let ga = LActions.ga *) @@ -43,14 +49,11 @@ type err_t = | MissingLocResource of { is_store : bool; action : LActions.ga; - loc_name : string; + loc_name : loc_t; ofs_opt : Expr.t option; chunk_opt : Chunk.t option; } - | SHeapTreeErr of { - at_locations : string list; - sheaptree_err : SHeapTree.err; - } + | SHeapTreeErr of { at_locations : loc_t list; sheaptree_err : SHeapTree.err } [@@deriving show, yojson] let lift_sheaptree_err loc err = @@ -66,13 +69,12 @@ module Mem = struct open Delayed.Syntax module SMap = GUtils.Prelude.Map.Make (struct - include String + include Gil_syntax.Id - let of_yojson = function - | `String s -> Ok s - | _ -> Error "string_of_yojson: expected string" + type t = any_loc Id.t - let to_yojson s = `String s + let of_yojson = of_yojson' + let to_yojson = to_yojson' end) type t = SHeapTree.t SMap.t @@ -96,10 +98,10 @@ module Mem = struct (***** Implementation of local actions *****) - let alloc (map : t) low high : t * string = + let alloc (map : t) low high : t * ALoc.t = let loc = ALoc.alloc () in let tree = SHeapTree.alloc low high in - (SMap.add loc tree map, loc) + (SMap.add (loc :> loc_t) tree map, loc) let weak_valid_pointer map loc ofs = let open DR.Syntax in @@ -284,16 +286,14 @@ module Mem = struct SMap.add dst_loc_name new_dst_tree map let lvars map = - let open Utils.Containers in SMap.fold - (fun _ tree acc -> SS.union (SHeapTree.lvars tree) acc) - map SS.empty + (fun _ tree acc -> LVar.Set.union (SHeapTree.lvars tree) acc) + map LVar.Set.empty let alocs map = - let open Utils.Containers in SMap.fold - (fun _ tree acc -> SS.union (SHeapTree.alocs tree) acc) - map SS.empty + (fun _ tree acc -> ALoc.Set.union (SHeapTree.alocs tree) acc) + map ALoc.Set.empty let assertions ~exclude map = SMap.fold @@ -303,17 +303,17 @@ module Mem = struct let pp_full ft mem = let open Fmt in - (Dump.iter_bindings SMap.iter nop string SHeapTree.pp_full) ft mem + (Dump.iter_bindings SMap.iter nop Id.pp SHeapTree.pp_full) ft mem let substitution subst map : (t, SHeapTree.err) DR.t = let open DR.Syntax in - if Subst.domain subst None = Expr.Set.empty then DR.ok map + if Expr.Set.is_empty @@ Subst.domain subst then DR.ok map else let aloc_subst = Subst.fold subst (fun l r acc -> match l with - | ALoc aloc -> (aloc, r) :: acc + | ALoc aloc -> ((aloc :> loc_t), r) :: acc | _ -> acc) [] in @@ -328,11 +328,12 @@ module Mem = struct (fun acc (old_loc, new_loc) -> let** acc = acc in Logging.verbose (fun fmt -> - fmt "SHOULD Merge locs: %s --> %a" old_loc Expr.pp new_loc); + fmt "SHOULD Merge locs: %a --> %a" Id.pp old_loc Expr.pp new_loc); Logging.tmi (fun fmt -> fmt "IN MEMORY: %a" pp_full acc); let new_loc = match new_loc with - | Lit (Loc loc) | ALoc loc -> loc + | Lit (Loc loc) -> (loc :> loc_t) + | ALoc loc -> (loc :> loc_t) | _ -> Fmt.failwith "Heap substitution failed for loc : %a" Expr.pp new_loc @@ -360,7 +361,7 @@ module Mem = struct (fun loc tree -> if not (exclude loc) then ( if !is_first then is_first := false else Fmt.pf ft "@\n"; - Fmt.pf ft "%s -> @[%a@]" loc SHeapTree.pp tree)) + Fmt.pf ft "%a -> @[%a@]" Id.pp loc SHeapTree.pp tree)) mem let pp ~exclude fmt map = @@ -384,10 +385,10 @@ let make_branch ~heap ?(rets = []) () = (heap, rets) let just_functions genv = if !Config.allocated_functions then - String_map.fold + LocMap.fold (fun loc def acc -> match def with - | Global_env.FunDef _ -> Mem.allocate_function acc loc + | Global_env.FunDef _ -> Mem.allocate_function acc (loc :> loc_t) | GlobVar _ -> acc) genv Mem.empty else Mem.empty @@ -395,7 +396,9 @@ let just_functions genv = let init genv = { genv; mem = just_functions genv } let sure_is_nonempty state = - let is_genv loc = String_map.find_opt loc state.genv |> Option.is_some in + let is_genv loc = + LocMap.find_opt (Loc.of_string @@ Id.str loc) state.genv |> Option.is_some + in let is_empty = Mem.SMap.for_all (fun loc tree -> is_genv loc || SHeapTree.is_empty_or_freed tree) @@ -640,7 +643,9 @@ let execute_prod_bounds heap params = let execute_genvgetdef heap params = match params with - | [ (Expr.Lit (Loc loc) | Expr.ALoc loc | Expr.LVar loc) ] -> ( + (* Are the other two cases even relevant, as GEnv only has concrete locs?? + | [ (Expr.Lit (Loc loc) | Expr.ALoc loc | Expr.LVar loc) ] -> ( *) + | [ Expr.Lit (Loc loc) ] -> ( match Global_env.find_def_opt heap.genv loc with | Some def -> let v = Global_env.serialize_def def in @@ -650,8 +655,8 @@ let execute_genvgetdef heap params = signal. *) if !Gillian.Utils.Config.under_approximation then Delayed.vanish () else - Fmt.failwith "execute_genvgetdef: couldn't find %s\nGENV:\n%a" loc - Global_env.pp heap.genv) + Fmt.failwith "execute_genvgetdef: couldn't find %a\nGENV:\n%a" Id.pp + loc Global_env.pp heap.genv) | _ -> fail_ungracefully "genv_getdef" params (* Complete fixes *) @@ -665,21 +670,21 @@ let pp_err fmt (e : err_t) = Expr.pp loc | MissingLocResource { is_store; action; loc_name; ofs_opt; chunk_opt } -> Fmt.pf fmt - "[MissingLocResource] No block associated with location '%s'. \ + "[MissingLocResource] No block associated with location '%a'. \ Associated data: \n\ \ * is_store: '%B'\n\ - \ * location: '%s'\n\ + \ * location: '%a'\n\ \ * core_pred: %s\n\ \ * value: %a \n\ \ * chunk: %a \n" - loc_name is_store loc_name (LActions.str_ga action) + Id.pp loc_name is_store Id.pp loc_name (LActions.str_ga action) (Fmt.Dump.option Expr.pp) ofs_opt (Fmt.Dump.option Chunk.pp) chunk_opt | SHeapTreeErr { at_locations; sheaptree_err } -> Fmt.pf fmt "[SHeapTreeErr] Tree at location%a raised: <%a>" (fun fmt l -> match l with - | [ s ] -> Fmt.pf fmt " '%s'" s - | l -> Fmt.pf fmt "s %a" (Fmt.Dump.list Fmt.string) l) + | [ s ] -> Fmt.pf fmt " '%a'" Id.pp s + | l -> Fmt.pf fmt "s %a" (Fmt.Dump.list Id.pp) l) at_locations SHeapTree.pp_err sheaptree_err (* let str_of_err e = Format.asprintf "%a" pp_err e *) @@ -687,15 +692,15 @@ let pp_err fmt (e : err_t) = let pp fmt h = let exclude loc = try - match String_map.find loc h.genv with + match LocMap.find (Loc.of_string @@ Id.str loc) h.genv with | Global_env.FunDef _ -> true | _ -> false with Not_found -> false in Format.fprintf fmt "@[%a@]" (Mem.pp ~exclude) h.mem -let pp_by_need (_ : SS.t) fmt h = pp fmt h -let get_print_info _ _ = (SS.empty, SS.empty) +let pp_by_need _ fmt h = pp fmt h +let get_print_info _ _ = (LVar.Set.empty, Id.Sets.LocSet.empty) (* let str_noheap _ = "NO HEAP PRINTED" *) @@ -795,7 +800,7 @@ let alocs heap = Mem.alocs heap.mem let assertions ?to_keep:_ heap = let exclude loc = try - match String_map.find loc heap.genv with + match LocMap.find (Loc.of_string @@ Id.str loc) heap.genv with | Global_env.FunDef _ -> true | _ -> false with Not_found -> false @@ -813,7 +818,7 @@ module Lift = struct store |> List.map (fun (var, value) : Variable.t -> let value = Fmt.to_to_string (Fmt.hbox Expr.pp) value in - Variable.create_leaf var value ()) + Variable.create_leaf (Var.str var) value ()) |> List.sort (fun (v : Variable.t) w -> Stdlib.compare v.name w.name) let make_node ~get_new_scope_id ~variables ~name ~value ?(children = []) () : @@ -866,7 +871,7 @@ let get_recovery_tactic _ err = let values = match err with | InvalidLocation e -> - List.map (fun x -> Expr.LVar x) (SS.elements (Expr.lvars e)) + List.map (fun x -> Expr.LVar x) (LVar.Set.elements (Expr.lvars e)) | MissingLocResource { is_store = _; action = _; loc_name; ofs_opt = _; chunk_opt = _ } -> [ Expr.loc_from_loc_name loc_name ] diff --git a/Gillian-C/lib/MonadicSMemory.mli b/Gillian-C/lib/MonadicSMemory.mli index 873754db5..8254b28b4 100644 --- a/Gillian-C/lib/MonadicSMemory.mli +++ b/Gillian-C/lib/MonadicSMemory.mli @@ -4,7 +4,7 @@ module Lift : sig open Gillian.Debugger.Utils val add_variables : - store:(string * vt) list -> + store:(Gil_syntax.Var.t * vt) list -> memory:t -> is_gil_file:'a -> get_new_scope_id:(unit -> int) -> diff --git a/Gillian-C/lib/MonadicSVal.ml b/Gillian-C/lib/MonadicSVal.ml index 5add89ff1..82580c710 100644 --- a/Gillian-C/lib/MonadicSVal.ml +++ b/Gillian-C/lib/MonadicSVal.ml @@ -55,7 +55,7 @@ let of_chunk_and_expr chunk e = | integer -> return (SVlong e) | obj -> ( match e with - | EList [ ALoc l; o ] -> return (Sptr (l, o)) + | EList [ ALoc l; o ] -> return (Sptr ((l :> Id.any_loc Id.t), o)) | _ -> Fmt.failwith "of_chunk_and_expr: Not a location, but should be: %a" @@ -65,7 +65,7 @@ let of_chunk_and_expr chunk e = | integer -> return (SVint e) | obj -> ( match e with - | EList [ ALoc l; o ] -> return (Sptr (l, o)) + | EList [ ALoc l; o ] -> return (Sptr ((l :> Id.any_loc Id.t), o)) | _ -> Fmt.failwith "of_chunk_and_expr: Not a location, but should be: %a" @@ -102,7 +102,7 @@ let of_gil_expr sval_e = | None -> let aloc = ALoc.alloc () in let learned = [ loc_expr == ALoc aloc ] in - (aloc, learned) + ((aloc :> Id.any_loc Id.t), learned) in DO.some ~learned (Sptr (loc, ofs)) | int_typ -> DO.some (SVint (Expr.list_nth sval_e 1)) diff --git a/Gillian-C/lib/SHeapTree.ml b/Gillian-C/lib/SHeapTree.ml index 76657b09e..f60b6ee83 100644 --- a/Gillian-C/lib/SHeapTree.ml +++ b/Gillian-C/lib/SHeapTree.ml @@ -101,8 +101,8 @@ module Range = struct l < x && x < h let split_at (l, h) x = ((l, x), (x, h)) - let lvars (a, b) = SS.union (Expr.lvars a) (Expr.lvars b) - let alocs (a, b) = SS.union (Expr.alocs a) (Expr.alocs b) + let lvars (a, b) = LVar.Set.union (Expr.lvars a) (Expr.lvars b) + let alocs (a, b) = ALoc.Set.union (Expr.alocs a) (Expr.alocs b) let substitution ~le_subst (a, b) = (le_subst a, le_subst b) end @@ -510,12 +510,12 @@ module Node = struct let lvars = function | MemVal { mem_val = Single { value = e; _ }; _ } -> SVal.lvars e - | _ -> SS.empty + | _ -> LVar.Set.empty let alocs = function | MemVal { mem_val = Single { value = e; _ }; _ } -> SVal.alocs e | MemVal { mem_val = Array { values = Arr e; _ }; _ } -> Expr.alocs e - | _ -> SS.empty + | _ -> ALoc.Set.empty let substitution ~sval_subst ~svarr_subst n = let smv = function @@ -1030,20 +1030,20 @@ module Tree = struct let span_lvars = Range.lvars span in let children_lvars = match children with - | Some (a, b) -> SS.union (lvars a) (lvars b) - | None -> SS.empty + | Some (a, b) -> LVar.Set.union (lvars a) (lvars b) + | None -> LVar.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + LVar.Set.union (LVar.Set.union node_lvars span_lvars) children_lvars let rec alocs { node; span; children; _ } = - let node_lvars = Node.alocs node in - let span_lvars = Range.alocs span in + let node_alocs = Node.alocs node in + let span_alocs = Range.alocs span in let children_lvars = match children with - | Some (a, b) -> SS.union (alocs a) (alocs b) - | None -> SS.empty + | Some (a, b) -> ALoc.Set.union (alocs a) (alocs b) + | None -> ALoc.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + ALoc.Set.union (ALoc.Set.union node_alocs span_alocs) children_lvars let rec assertions ~loc { node; span; children; _ } = let low, high = span in @@ -1152,18 +1152,18 @@ let is_empty t = let freed = Freed let lvars = function - | Freed -> SS.empty + | Freed -> LVar.Set.empty | Tree { bounds; root } -> - SS.union - (Option.fold ~none:SS.empty ~some:Range.lvars bounds) - (Option.fold ~none:SS.empty ~some:Tree.lvars root) + LVar.Set.union + (Option.fold ~none:LVar.Set.empty ~some:Range.lvars bounds) + (Option.fold ~none:LVar.Set.empty ~some:Tree.lvars root) let alocs = function - | Freed -> SS.empty + | Freed -> ALoc.Set.empty | Tree { bounds; root } -> - SS.union - (Option.fold ~none:SS.empty ~some:Range.alocs bounds) - (Option.fold ~none:SS.empty ~some:Tree.alocs root) + ALoc.Set.union + (Option.fold ~none:ALoc.Set.empty ~some:Range.alocs bounds) + (Option.fold ~none:ALoc.Set.empty ~some:Tree.alocs root) let is_in_bounds range bounds = match bounds with @@ -1586,7 +1586,7 @@ module Lift = struct ~loc t : Variable.t = match t with - | Freed -> make_node ~name:loc ~value:"Freed" () + | Freed -> make_node ~name:(Id.str loc) ~value:"Freed" () | Tree { bounds; root } -> let bounds = match bounds with @@ -1601,5 +1601,6 @@ module Lift = struct | None -> make_node ~name:"Tree" ~value:"Not owned" () | Some root -> Tree.Lift.as_variable ~make_node root in - make_node ~name:loc ~value:"Allocated" ~children:[ bounds; root ] () + make_node ~name:(Id.str loc) ~value:"Allocated" + ~children:[ bounds; root ] () end diff --git a/Gillian-C/lib/SHeapTree.mli b/Gillian-C/lib/SHeapTree.mli index 230f1a5a6..7c261b911 100644 --- a/Gillian-C/lib/SHeapTree.mli +++ b/Gillian-C/lib/SHeapTree.mli @@ -1,5 +1,4 @@ open Gil_syntax -open Utils.Containers open Monadic type missingResourceType = @@ -38,8 +37,8 @@ val empty : t val freed : t val is_empty : t -> bool val is_empty_or_freed : t -> bool -val lvars : t -> SS.t -val alocs : t -> SS.t +val lvars : t -> LVar.Set.t +val alocs : t -> ALoc.Set.t val cons_bounds : t -> (Range.t option * t) or_error val prod_bounds : t -> Range.t option -> t or_error @@ -85,7 +84,7 @@ val allocated_function : t [dst_tree] after modification *) val move : t -> Expr.t -> t -> Expr.t -> Expr.t -> t d_or_error -val assertions : loc:string -> t -> Asrt.t +val assertions : loc:Id.any_loc Id.t -> t -> Asrt.t val substitution : le_subst:(Expr.t -> Expr.t) -> @@ -106,7 +105,7 @@ module Lift : sig ?children:Variable.t list -> unit -> Variable.t) -> - loc:string -> + loc:Id.any_loc Id.t -> t -> Variable.t end diff --git a/Gillian-C/lib/SVal.ml b/Gillian-C/lib/SVal.ml index b70db48ee..8678a3aad 100644 --- a/Gillian-C/lib/SVal.ml +++ b/Gillian-C/lib/SVal.ml @@ -6,7 +6,7 @@ let ( let+ ) o f = Option.map f o type t = | SUndefined - | Sptr of string * Expr.t + | Sptr of Id.any_loc Id.t * Expr.t | SVint of Expr.t | SVlong of Expr.t | SVsingle of Expr.t @@ -16,8 +16,7 @@ type t = let equal a b = match (a, b) with | SUndefined, SUndefined -> true - | Sptr (la, oa), Sptr (lb, ob) when String.equal la lb && Expr.equal oa ob -> - true + | Sptr (la, oa), Sptr (lb, ob) when Id.equal la lb && Expr.equal oa ob -> true | SVint a, SVint b when Expr.equal a b -> true | SVlong a, SVlong b when Expr.equal a b -> true | SVsingle a, SVsingle b when Expr.equal a b -> true @@ -71,16 +70,18 @@ let of_gil_expr_almost_concrete ?(gamma = Type_env.init ()) gexpr = let open CConstants.VTypes in match gexpr with | Lit Undefined -> Some (SUndefined, []) - | EList [ ALoc loc; offset ] | EList [ Lit (Loc loc); offset ] -> - Some (Sptr (loc, offset), []) + | EList [ ALoc loc; offset ] -> + Some (Sptr ((loc :> Id.any_loc Id.t), offset), []) + | EList [ Lit (Loc loc); offset ] -> + Some (Sptr ((loc :> Id.any_loc Id.t), offset), []) | EList [ LVar loc; Lit (Int k) ] -> let aloc = ALoc.alloc () in let new_pf = Expr.BinOp (LVar loc, Equal, Expr.ALoc aloc) in - Some (Sptr (aloc, Lit (Int k)), [ new_pf ]) + Some (Sptr ((aloc :> Id.any_loc Id.t), Lit (Int k)), [ new_pf ]) | EList [ LVar loc; LVar ofs ] when is_loc_ofs gamma loc ofs -> let aloc = ALoc.alloc () in let new_pf = Expr.BinOp (LVar loc, Equal, Expr.ALoc aloc) in - Some (Sptr (aloc, LVar ofs), [ new_pf ]) + Some (Sptr ((aloc :> Id.any_loc Id.t), LVar ofs), [ new_pf ]) | EList [ Lit (String typ); value ] when String.equal typ int_type -> Some (SVint value, []) | EList [ Lit (String typ); value ] when String.equal typ float_type -> @@ -132,20 +133,17 @@ let to_gil_expr gexpr = | SVsingle n -> (EList [ Lit (String single_type); n ], [ (n, Type.NumberType) ]) -let lvars = - let open Utils.Containers in - function - | SUndefined -> SS.empty - | Sptr (_, e) -> Expr.lvars e - | SVint e | SVfloat e | SVsingle e | SVlong e -> Expr.lvars e - -let alocs = - let open Utils.Containers in - function - | SUndefined -> SS.empty - | Sptr (l, e) -> - let alocs_e = Expr.alocs e in - if Utils.Names.is_aloc_name l then SS.add l alocs_e else alocs_e +let lvars = function + | SUndefined -> LVar.Set.empty + | Sptr (_, e) | SVint e | SVfloat e | SVsingle e | SVlong e -> Expr.lvars e + +let alocs = function + | SUndefined -> ALoc.Set.empty + | Sptr (l, e) -> ( + let e_alocs = Expr.alocs e in + match Id.as_aloc l with + | Some l -> ALoc.Set.add l e_alocs + | None -> e_alocs) | SVint e | SVfloat e | SVsingle e | SVlong e -> Expr.alocs e let pp fmt v = @@ -153,7 +151,7 @@ let pp fmt v = let f = Format.fprintf in match v with | SUndefined -> f fmt "undefined" - | Sptr (l, ofs) -> f fmt "Ptr(%s, %a)" l se ofs + | Sptr (l, ofs) -> f fmt "Ptr(%a, %a)" Id.pp l se ofs | SVint i -> f fmt "Int(%a)" se i | SVlong i -> f fmt "Long(%a)" se i | SVfloat i -> f fmt "Float(%a)" se i @@ -169,7 +167,6 @@ let substitution ~le_subst sv = | Sptr (loc, offs) -> ( let loc_e = Expr.loc_from_loc_name loc in match le_subst loc_e with - | Expr.ALoc nloc | Lit (Loc nloc) -> Sptr (nloc, le_subst offs) - | e -> - failwith - (Format.asprintf "Heap substitution fail for loc: %a" Expr.pp e)) + | Expr.ALoc nloc -> Sptr ((nloc :> Id.any_loc Id.t), le_subst offs) + | Lit (Loc nloc) -> Sptr ((nloc :> Id.any_loc Id.t), le_subst offs) + | e -> Fmt.failwith "Heap substitution fail for loc: %a" Expr.pp e) diff --git a/Gillian-C/lib/cParserAndCompiler.ml b/Gillian-C/lib/cParserAndCompiler.ml index 269bce012..5d62b9afe 100644 --- a/Gillian-C/lib/cParserAndCompiler.ml +++ b/Gillian-C/lib/cParserAndCompiler.ml @@ -252,11 +252,18 @@ let mangle_proc proc mangled_syms = inherit [_] Gillian.Gil_syntax.Visitors.endo as super method! visit_proc env proc = - let proc_params = List.map mangle_var proc.proc_params in + let proc_params = + List.map + (fun x -> + Gil_syntax.Var.of_string @@ mangle_var @@ Gil_syntax.Var.str x) + proc.proc_params + in let proc = super#visit_proc env proc in { proc with proc_params } - method! visit_PVar _ _ var = Gillian.Gil_syntax.Expr.PVar (mangle_var var) + method! visit_PVar _ _ var = + Gillian.Gil_syntax.Expr.PVar + Gil_syntax.Id.Var.(of_string @@ mangle_var @@ str var) method! visit_Loc _ _ str = Gillian.Gil_syntax.Literal.Loc (mangle_symbol str) @@ -457,7 +464,7 @@ let parse_and_compile_files paths = (fun a b -> match (a, b) with | ( Cmd.Call (_, _, Lit (Loc a) :: _, _, _), - Cmd.Call (_, _, Lit (Loc b) :: _, _, _) ) -> String.compare a b + Cmd.Call (_, _, Lit (Loc b) :: _, _, _) ) -> Loc.compare a b | _ -> failwith "Wrong init cmd") (init_cmds @ genv_init_cmds) in diff --git a/Gillian-C/lib/gil_logic_gen.ml b/Gillian-C/lib/gil_logic_gen.ml index 03b8a6825..47fd5666f 100644 --- a/Gillian-C/lib/gil_logic_gen.ml +++ b/Gillian-C/lib/gil_logic_gen.ml @@ -10,8 +10,8 @@ open Expr.Infix let id_of_string = Camlcoq.intern_string let true_name = Camlcoq.extern_atom -let loc_param_name = "loc" -let ofs_param_name = "ofs" +let loc_param_name = Var.of_string "loc" +let ofs_param_name = Var.of_string "ofs" let pred_name_of_struct struct_name = Prefix.generated_preds ^ "struct_" ^ struct_name @@ -24,7 +24,7 @@ let opt_rec_pred_name_of_struct struct_name = let fresh_lvar ?(fname = "") () = let pre = "_lvar_i_" in - Generators.gen_str ~fname pre + LVar.of_string @@ Generators.gen_str ~fname pre let rec split3_expr_comp = function | [] -> ([], [], []) @@ -121,7 +121,7 @@ let assert_of_member cenv members id typ = let field_name = true_name id in let pvloc = Expr.PVar loc_param_name in let pvofs = Expr.PVar ofs_param_name in - let pvmember = Expr.PVar field_name in + let pvmember = Expr.PVar (Var.of_string field_name) in let fo = match field_offset cenv id members with | Errors.OK (f, Full) -> Expr.int_z (ValueTranslation.int_of_z f) @@ -139,7 +139,8 @@ let assert_of_member cenv members id typ = in let args_without_ins = List.init arg_number (fun k -> - Expr.LVar ("i__" ^ field_name ^ "_" ^ string_of_int k)) + Expr.LVar + (LVar.of_string ("i__" ^ field_name ^ "_" ^ string_of_int k))) in let list_is_components = pvmember #== (Expr.list args_without_ins) in let ofs = Expr.Infix.(pvofs + fo) in @@ -160,7 +161,7 @@ let assert_of_member cenv members id typ = ] | _ -> let mk t v = Expr.list [ Expr.string t; v ] in - let field_val_name = "i__" ^ field_name ^ "_v" in + let field_val_name = LVar.of_string ("i__" ^ field_name ^ "_v") in let lvval = Expr.LVar field_val_name in let e_to_use, getter_or_type_pred = let open Internal_Predicates in @@ -173,9 +174,8 @@ let assert_of_member cenv members id typ = (mk float_type lvval, Asrt.Pred (float_get, [ pvmember; lvval ])) | Tpointer _ -> (pvmember, Asrt.Pred (is_ptr_opt, [ pvmember ])) | _ -> - failwith - (Printf.sprintf "unhandled struct field type for now : %s" - (PrintCsyntax.name_cdecl field_name typ)) + Fmt.failwith "unhandled struct field type for now : %s" + (PrintCsyntax.name_cdecl field_name typ) in let chunk = match access_mode_by_value typ with @@ -221,7 +221,8 @@ let gen_pred_of_struct cenv ann struct_name = let struct_params = comp.co_members |> List.map @@ function - | Member_plain (i, _) -> (true_name i, Some Type.ListType) + | Member_plain (i, _) -> + (Var.of_string @@ true_name i, Some Type.ListType) | Member_bitfield _ -> failwith "Unsupported bitfield members" in let pred_params = first_params @ struct_params in @@ -302,9 +303,9 @@ let trans_nop : CNOp.t -> NOp.t = function | SetUnion -> SetUnion let trans_simpl_expr : CSimplExpr.t -> Expr.t = function - | PVar s -> PVar s - | LVar s -> LVar s - | Loc s -> Lit (Loc s) + | PVar s -> PVar (Var.of_string s) + | LVar s -> LVar (LVar.of_string s) + | Loc s -> Lit (Loc (Loc.of_string s)) | Int i -> Lit (Int i) | Bool b -> Lit (Bool b) | String s -> Lit (String s) @@ -312,7 +313,7 @@ let trans_simpl_expr : CSimplExpr.t -> Expr.t = function (* The first element of the result should be a pure assertion : either a formula, or overlapping assertions, The second element is the list of created variables, the third is the expression to be used *) -let trans_sval (sv : CSVal.t) : Asrt.t * Var.t list * Expr.t = +let trans_sval (sv : CSVal.t) : Asrt.t * [< Id.any_var ] Id.t list * Expr.t = let open CConstants.VTypes in let mk str v = Expr.EList [ Expr.Lit (String str); v ] in let tnum = types Type.NumberType in @@ -342,7 +343,7 @@ let trans_sval (sv : CSVal.t) : Asrt.t * Var.t list * Expr.t = (** Returns assertions that are necessary to define the expression, the created variable for binding when necessary, and the used expression *) -let rec trans_expr (e : CExpr.t) : Asrt.t * Var.t list * Expr.t = +let rec trans_expr (e : CExpr.t) : Asrt.t * [< Id.any_var ] Id.t list * Expr.t = match e with | CExpr.SExpr se -> ([], [], trans_simpl_expr se) | SVal sv -> trans_sval sv @@ -389,7 +390,8 @@ let rec trans_expr (e : CExpr.t) : Asrt.t * Var.t list * Expr.t = let a3, v3, len = trans_expr len in (a1 @ a2 @ a3, v1 @ v2 @ v3, Expr.list_sub ~lst ~start ~size:len) -let rec trans_form : CFormula.t -> Asrt.t * Var.t list * Expr.t = function +let rec trans_form : CFormula.t -> Asrt.t * [< Id.any_var ] Id.t list * Expr.t = + function | True -> ([], [], Expr.true_) | False -> ([], [], Expr.false_) | Eq (ce1, ce2) -> @@ -425,6 +427,7 @@ let rec trans_form : CFormula.t -> Asrt.t * Var.t list * Expr.t = function (a1 @ a2, v1 @ v2, fp1 ==> fp2) | ForAll (lvts, f) -> let a, v, fp = trans_form f in + let lvts = List.map (fun (x, t) -> (LVar.of_string x, t)) lvts in (a, v, ForAll (lvts, fp)) let malloc_chunk_asrt loc beg_ofs struct_sz = @@ -597,7 +600,7 @@ let rec trans_lcmd ~fname ~ann lcmd = let trans_asrt = trans_asrt ~fname ~ann in let make_assert ~bindings = function | [] | [ Asrt.Emp ] -> [] - | a -> [ LCmd.SL (SepAssert (a, bindings)) ] + | a -> [ LCmd.SL (SepAssert (a, (bindings :> Id.any_var Id.t list))) ] in match lcmd with | CLCmd.Apply (pn, el) -> @@ -607,12 +610,19 @@ let rec trans_lcmd ~fname ~ann lcmd = let aps, bindings, gel = split3_expr_comp (List.map trans_expr el) in `Normal (make_assert ~bindings aps @ [ SL (Fold (pn, gel, None)) ]) | Unfold { pred; params; bindings; recursive } -> + let bindings = + Option.map + (List.map (fun (l, r) -> (LVar.of_string l, LVar.of_string r))) + bindings + in let ap, vs, gel = split3_expr_comp (List.map trans_expr params) in `Normal (make_assert ~bindings:vs ap @ [ SL (Unfold (pred, gel, bindings, recursive)) ]) | Unfold_all pred_name -> `Normal [ SL (GUnfold pred_name) ] - | Assert (a, ex) -> `Normal [ SL (SepAssert (trans_asrt a, ex)) ] + | Assert (a, ex) -> + let ex = List.map LVar.of_string ex in + `Normal [ SL (SepAssert (trans_asrt a, (ex :> Id.any_var Id.t list))) ] | Branch f -> let to_assert, bindings, f_gil = trans_form f in `Normal (make_assert ~bindings to_assert @ [ Branch f_gil ]) @@ -628,8 +638,9 @@ let rec trans_lcmd ~fname ~ann lcmd = let gcl2 = List.concat_map trans_normal_lcmd cl2 in `Normal (make_assert ~bindings:vs f @ [ If (ge, gcl1, gcl2) ]) | Invariant { bindings; assertion } -> + let bindings = List.map LVar.of_string bindings in let asrt = trans_asrt assertion in - `Invariant (SLCmd.Invariant (asrt, bindings)) + `Invariant (SLCmd.Invariant (asrt, (bindings :> Id.any_var Id.t list))) | SymbExec -> `Normal [ SL SymbExec ] let trans_asrt_annot da = @@ -637,6 +648,7 @@ let trans_asrt_annot da = let exs, typsb = existentials |> ( List.map @@ fun (ex, topt) -> + let ex = LVar.of_string ex in match topt with | None -> (ex, Asrt.Emp) | Some t -> (ex, types t (Expr.LVar ex)) ) @@ -654,6 +666,7 @@ let trans_abs_pred ~filepath cl_pred = } = cl_pred in + let pred_params = List.map (fun (x, t) -> (Var.of_string x, t)) pred_params in let pred_num_params = List.length pred_params in Pred. { @@ -684,6 +697,7 @@ let trans_pred ~ann ~filepath cl_pred = } = cl_pred in + let pred_params = List.map (fun (x, t) -> (Var.of_string x, t)) pred_params in let pred_num_params = List.length pred_params in let pred_definitions = List.map @@ -765,7 +779,7 @@ let trans_lemma ~ann ~filepath lemma = Lemma. { lemma_name = name; - lemma_params = params; + lemma_params = List.map Var.of_string params; lemma_source_path = Some filepath; lemma_existentials = []; lemma_internal = false; @@ -780,7 +794,7 @@ let trans_spec ~ann ?(only_spec = false) cl_spec = Spec. { spec_name = fname; - spec_params = params; + spec_params = List.map Var.of_string params; spec_sspecs = List.map (trans_sspec ~ann fname) sspecs; spec_normalised = false; spec_incomplete = false; @@ -886,14 +900,10 @@ let predicate_from_triple (e, csmt, ct) = | AST.Tsingle, _ -> pred is_single | AST.Tfloat, _ -> pred is_float | _ -> - failwith - (Printf.sprintf - "Don't know how to handle the following type as a bispec function \ - parameter %s" - (PrintAST.name_of_type csmt)) - -let simple_predicate_from_triple (pn, _, _) = - Asrt.Pure (BinOp (Expr.PVar pn, Equal, Expr.LVar ("" ^ pn))) + Fmt.failwith + "Don't know how to handle the following type as a bispec function \ + parameter %s" + (PrintAST.name_of_type csmt) let generate_bispec clight_prog fname ident f = let rec combine a b c = @@ -907,11 +917,12 @@ let generate_bispec clight_prog fname ident f = let true_params = List.map true_name params in let clight_fun = get_clight_fun clight_prog ident in let cligh_params = clight_fun.Clight.fn_params in - let mk_lvar x = Expr.LVar ("" ^ x) in + let mk_lvar x = Expr.LVar (LVar.of_string x) in let lvars = List.map mk_lvar true_params in let equalities = List.map - (fun x -> Asrt.Pure (Expr.BinOp (Expr.PVar x, Equal, mk_lvar x))) + (fun x -> + Asrt.Pure (Expr.BinOp (Expr.PVar (Var.of_string x), Equal, mk_lvar x))) true_params in (* Right now, triples are : (param_name, csharpminor type, c type) @@ -922,7 +933,7 @@ let generate_bispec clight_prog fname ident f = BiSpec. { bispec_name = fname; - bispec_params = true_params; + bispec_params = List.map Var.of_string true_params; bispec_pres = [ pre ]; bispec_normalised = false; } diff --git a/Gillian-C/lib/gilgen.ml b/Gillian-C/lib/gilgen.ml index 0fd2c4cd4..80bc88109 100644 --- a/Gillian-C/lib/gilgen.ml +++ b/Gillian-C/lib/gilgen.ml @@ -12,7 +12,7 @@ let true_name = ValueTranslation.true_name type context = { block_stack : string list; - local_env : string list; + local_env : Var.t list; gil_annot : Gil_logic_gen.gil_annots; exec_mode : Exec_mode.t; loop_stack : string list; @@ -62,7 +62,7 @@ let internal_proc_of_unop uop = let trans_binop_expr ~fname binop te1 te2 = let call func = - let gvar = Generators.gen_str ~fname Prefix.gvar in + let gvar = Var.of_string @@ Generators.gen_str ~fname Prefix.gvar in ( [ Cmd.Call (gvar, Expr.Lit (Literal.String func), [ te1; te2 ], None, None); ], @@ -264,11 +264,11 @@ let rec trans_expr ~clight_prog ~fname ~fid ~local_env expr = let gen_str = Generators.gen_str ~fname in let open Expr in match expr with - | Evar id -> ([], PVar (true_name id)) + | Evar id -> ([], PVar (Var.of_string @@ true_name id)) | Econst const -> ([], Lit (trans_const const)) | Eload (compcert_chunk, expp) -> let cl, e = trans_expr expp in - let gvar = gen_str Prefix.gvar in + let gvar = Var.of_string @@ gen_str Prefix.gvar in let loadv = Expr.Lit (Literal.String Internal_Functions.loadv) in let chunk = to_gil_chunk clight_prog fname fid compcert_chunk expp in @@ -279,7 +279,7 @@ let rec trans_expr ~clight_prog ~fname ~fid ~local_env expr = (cl @ [ cmd ], Expr.PVar gvar) | Eunop (uop, e) -> let cl, e = trans_expr e in - let gvar = gen_str Prefix.gvar in + let gvar = Var.of_string @@ gen_str Prefix.gvar in let ip = internal_proc_of_unop uop in let call = Cmd.Call (gvar, Lit (Literal.String ip), [ e ], None, None) in (cl @ [ call ], PVar gvar) @@ -294,8 +294,11 @@ let rec trans_expr ~clight_prog ~fname ~fid ~local_env expr = ^ PrintCminor.name_of_binop binop) in (leading_e1 @ leading_e2 @ leading_binop, te) - | Eaddrof id when List.mem (true_name id) local_env -> - let res = EList [ nth (true_name id) 0; Lit (Literal.Int Z.zero) ] in + | Eaddrof id when List.mem (Var.of_string @@ true_name id) local_env -> + let res = + EList + [ nth (Var.of_string @@ true_name id) 0; Lit (Literal.Int Z.zero) ] + in ([], res) | Eaddrof id -> let name = true_name id in @@ -331,7 +334,7 @@ let make_free_cmd fname var_list = | x :: r -> Expr.EList [ nth x 0; zero; nth x 1 ] :: make_blocks r in let freelist = Expr.Lit (Literal.String Internal_Functions.free_list) in - let gvar = Generators.gen_str ~fname Prefix.gvar in + let gvar = Var.of_string @@ Generators.gen_str ~fname Prefix.gvar in (* If there's nothing to free, we just don't create the command *) match make_blocks var_list with | [] -> None @@ -339,8 +342,8 @@ let make_free_cmd fname var_list = Some (Cmd.Call (gvar, freelist, [ Expr.EList blocks ], None, None)) let make_symb_gen ~fname ~ctx assigned_id type_string = - let gen_str = Generators.gen_str ~fname Prefix.gvar in - let assigned = true_name assigned_id in + let gen_str = Var.of_string @@ Generators.gen_str ~fname Prefix.gvar in + let assigned = Var.of_string @@ true_name assigned_id in let fresh_svar = Cmd.Logic (FreshSVar gen_str) in let gvar_val = Expr.PVar gen_str in let assume_val_t = Cmd.Logic (LCmd.AssumeType (gvar_val, Type.IntType)) in @@ -393,7 +396,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : | Sskip -> ([ (annot_ctx context, None, Cmd.Skip) ], []) | Sset (id, exp) -> let cmds, te = trans_expr exp in - let var_name = true_name id in + let var_name = Var.of_string @@ true_name id in let ncmd = Cmd.Assignment (var_name, te) in let lab_ncmd = (annot_ctx context, None, ncmd) in let cmds = add_annots ~ctx:context cmds @ [ lab_ncmd ] in @@ -424,7 +427,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : let bool_of_val = Expr.Lit (Literal.String Internal_Functions.bool_of_val) in - let texb = gen_str Prefix.gvar in + let texb = Var.of_string @@ gen_str Prefix.gvar in let bov = Cmd.Call (texb, bool_of_val, [ texp ], None, None) in let a_bov = (annot_ctx context, None, bov) in let guard = Cmd.GuardedGoto (PVar texb, then_lab, else_lab) in @@ -475,7 +478,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : let ret_assign = ( annot_ctx context, None, - Cmd.Assignment (Gillian.Utils.Names.return_variable, rexpr) ) + Cmd.Assignment (Gil_syntax.Id.return_variable, rexpr) ) in let freecmd_opt = make_free_cmd fname context.local_env in let return = (annot_ctx context, None, Cmd.ReturnNormal) in @@ -514,7 +517,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : let annot_addr_eval = add_annots ~ctx:context addr_eval_cmds in let annot_v_eval = add_annots ~ctx:context v_eval_cmds in let storev = Expr.Lit (Literal.String Internal_Functions.storev) in - let gvar = gen_str Prefix.gvar in + let gvar = Var.of_string @@ gen_str Prefix.gvar in let cmd = Cmd.Call (gvar, storev, [ chunk_expr; eaddr; ev ], None, None) in @@ -538,7 +541,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : (make_symb_gen ~ctx:context id CConstants.VTypes.int_type, []) | Scall (None, _, ex, args) when is_printf_call ex -> let cmds, egil = List.split (List.map trans_expr args) in - let leftvar = gen_str Prefix.gvar in + let leftvar = Var.of_string @@ gen_str Prefix.gvar in let cmd = Cmd.ECall ( leftvar, @@ -559,15 +562,15 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : in let leftvar = match optid with - | None -> gen_str Prefix.gvar - | Some id -> true_name id + | None -> Var.of_string @@ gen_str Prefix.gvar + | Some id -> Var.of_string @@ true_name id in let leading_fn, fn_expr = trans_expr ex in let leadings_params, trans_params = List.split (List.map trans_expr lexp) in let leading_params = List.concat leadings_params in - let fname_var = gen_str Prefix.gvar in + let fname_var = Var.of_string @@ gen_str Prefix.gvar in let s_get_function_name = Expr.Lit (Literal.String Internal_Functions.get_function_name) in @@ -737,7 +740,7 @@ let rec trans_stmt ~clight_prog ~fname ~fid ~context stmt : let al = ValueTranslation.int_of_z al in let cmds_dst, dst = trans_expr dst in let cmds_src, src = trans_expr src in - let temp = gen_str Prefix.gvar in + let temp = Var.of_string @@ gen_str Prefix.gvar in let call = Cmd.Call ( temp, @@ -757,7 +760,7 @@ let empty_annot = Annot.make_basic () let add_empty_annots l = List.map (fun a -> (empty_annot, None, a)) l let alloc_var fname (name, sz) = - let gvar = Generators.gen_str ~fname Prefix.gvar in + let gvar = Var.of_string @@ Generators.gen_str ~fname Prefix.gvar in let ocaml_size = ValueTranslation.gil_size_of_compcert sz in let expr_size = Expr.Lit (Int ocaml_size) in let alloc = LActions.(str_ac (AMem Alloc)) in @@ -778,11 +781,13 @@ let trans_function fid = let { fn_sig = _; fn_params; fn_vars; fn_temps; fn_body } = fdef in (* Getting rid of the ids immediately *) - let fn_vars = List.map (fun (id, sz) -> (true_name id, sz)) fn_vars in + let fn_vars = + List.map (fun (id, sz) -> (Var.of_string @@ true_name id, sz)) fn_vars + in let context = { block_stack = []; - local_env = fst (List.split fn_vars); + local_env = List.map fst fn_vars; gil_annot; exec_mode; loop_stack = []; @@ -793,13 +798,14 @@ let trans_function (fun temp -> ( empty_annot, None, - Cmd.Assignment (true_name temp, Expr.Lit Literal.Undefined) )) + Cmd.Assignment + (Var.of_string @@ true_name temp, Expr.Lit Literal.Undefined) )) fn_temps in let register_vars = List.concat (List.map (alloc_var fname) fn_vars) in let init_genv = if String.equal fname !Utils.Config.entry_point then - let gvar = Generators.gen_str ~fname Prefix.gvar in + let gvar = Var.of_string @@ Generators.gen_str ~fname Prefix.gvar in let expr_fn = Expr.Lit (Literal.String CConstants.Internal_Functions.initialize_genv) in @@ -816,13 +822,15 @@ let trans_function | [ (a, b, c) ] -> [ (a, b, c); - (Annot.make_basic (), None, Assignment ("ret", Expr.zero_i)); + ( Annot.make_basic (), + None, + Assignment (Id.return_variable, Expr.zero_i) ); (Annot.make_basic (), None, ReturnNormal); ] | a :: b -> a :: add_return b in let body_with_reg_and_ret = add_return body_with_registrations in - let params = List.map true_name fn_params in + let params = List.map (fun x -> Var.of_string @@ true_name x) fn_params in Proc. { proc_name = fname; @@ -852,7 +860,7 @@ let set_global_var symbol v = let id_list_expr = Expr.Lit (Literal.LList init_data_list) in let setvar = CConstants.Internal_Functions.glob_set_var in Cmd.Call - ( "u", + ( Var.of_string "u", Lit (String setvar), [ loc; sz; id_list_expr; perm_string ], None, @@ -1016,8 +1024,7 @@ let make_init_proc init_cmds = [ ( empty_annot, None, - Cmd.Assignment - (Gillian.Utils.Names.return_variable, Expr.Lit Literal.Undefined) ); + Cmd.Assignment (Id.return_variable, Expr.Lit Literal.Undefined) ); (empty_annot, None, Cmd.ReturnNormal); ] in diff --git a/Gillian-C/lib/gilgen.mli b/Gillian-C/lib/gilgen.mli index ee02207ff..1f943238f 100644 --- a/Gillian-C/lib/gilgen.mli +++ b/Gillian-C/lib/gilgen.mli @@ -21,7 +21,7 @@ val trans_program : ?gil_annot:Gil_logic_gen.gil_annots -> clight_prog:Clight.program -> filepath:string -> - mangled_syms:(string, string) Hashtbl.t -> + mangled_syms:(Loc.t, Loc.t) Hashtbl.t -> Csharpminor.program -> (Annot.Basic.t, string) Prog.t * compilation_data @@ -29,7 +29,7 @@ val trans_program_with_annots : exec_mode:Exec_mode.t -> clight_prog:Clight.program -> filepath:string -> - mangled_syms:(string, string) Hashtbl.t -> + mangled_syms:(Loc.t, Loc.t) Hashtbl.t -> Csharpminor.program -> CLogic.CProg.t -> (Annot.Basic.t, string) Prog.t * compilation_data diff --git a/Gillian-C/lib/global_env.ml b/Gillian-C/lib/global_env.ml index c839c4675..06f4ca7a6 100644 --- a/Gillian-C/lib/global_env.ml +++ b/Gillian-C/lib/global_env.ml @@ -1,15 +1,18 @@ +open Gil_syntax.Id + type err_t = Symbol_not_found of string type def = FunDef of string | GlobVar of string -let location_of_symbol str = "$l_" ^ str +let location_of_symbol str = Gil_syntax.Id.Loc.of_string ("$l_" ^ str) (** maps location to definition *) -type t = def String_map.t -let empty = String_map.empty -let add_fundef genv loc fdef = String_map.add loc (FunDef fdef) genv -let add_globvar genv loc gvar = String_map.add loc (GlobVar gvar) genv -let add_def genv loc def = String_map.add loc def genv +type t = def LocMap.t + +let empty = LocMap.empty +let add_fundef genv loc fdef = LocMap.add loc (FunDef fdef) genv +let add_globvar genv loc gvar = LocMap.add loc (GlobVar gvar) genv +let add_def genv loc def = LocMap.add loc def genv let of_definition_list defs = List.fold_left @@ -18,7 +21,7 @@ let of_definition_list defs = add_def genv loc def) empty defs -let find_def genv loc = String_map.find loc genv +let find_def genv loc = LocMap.find loc genv let find_def_opt genv loc = try Some (find_def genv loc) with Not_found -> None @@ -30,29 +33,13 @@ let find_function_opt genv loc = failwith "Gillian-C.Global_env.find_function: Not a function!" | None -> None -let serialize_def def = +let serialize_def = let open Gil_syntax in - let lit = - match def with - | FunDef fname -> Literal.LList [ String "function"; String fname ] - | GlobVar vname -> Literal.LList [ String "variable"; String vname ] - in - lit + function + | FunDef fname -> Literal.LList [ String "function"; String fname ] + | GlobVar vname -> Literal.LList [ String "variable"; String vname ] module Serialization = struct - module Loc = struct - open Gillian.Utils - - type t = string - - let of_yojson yjs = - match yjs with - | `String str when Names.is_lloc_name str -> Ok str - | _ -> Error ("invalid symbol location: " ^ Yojson.Safe.to_string yjs) - - let to_yojson loc = `String loc - end - type kind = Function [@name "fun"] | Variable [@name "var"] let kind_to_yojson kind = @@ -77,7 +64,7 @@ module Serialization = struct List.fold_left add_entry empty entries let to_definition_list genv = - String_map.fold + LocMap.fold (fun loc def acc -> let entry = match def with @@ -108,6 +95,6 @@ let pp ft genv = | FunDef fdef -> pf ft "%s (Function)" fdef | GlobVar gvar -> pf ft "%s (Variable)" gvar in - pf ft "%s -> %a" loc pp_def def + pf ft "%a -> %a" Loc.pp loc pp_def def in - (Fmt.iter_bindings ~sep:(any "@\n") String_map.iter pp_binding) ft genv + (Fmt.iter_bindings ~sep:(any "@\n") LocMap.iter pp_binding) ft genv diff --git a/Gillian-C/lib/string_map.ml b/Gillian-C/lib/string_map.ml deleted file mode 100644 index 99d658088..000000000 --- a/Gillian-C/lib/string_map.ml +++ /dev/null @@ -1 +0,0 @@ -include Map.Make (String) diff --git a/Gillian-C/lib/valueTranslation.ml b/Gillian-C/lib/valueTranslation.ml index b2d209c7b..8dfc4ae99 100644 --- a/Gillian-C/lib/valueTranslation.ml +++ b/Gillian-C/lib/valueTranslation.ml @@ -15,9 +15,12 @@ let chunk_of_string = Chunk.of_string let loc_name_of_block block = let int_block = Camlcoq.P.to_int block in let string_block = string_of_int int_block in - Prefix.loc ^ string_block + Gil_syntax.Loc.of_string @@ Prefix.loc ^ string_block let block_of_loc_name loc_name = + let loc_name = + Gil_syntax.Id.str (loc_name :> Gil_syntax.Id.any_loc Gil_syntax.Id.t) + in let size_int = String.length loc_name - 2 in let string_block = String.sub loc_name 2 size_int in let int_block = int_of_string string_block in diff --git a/Gillian-C/lib/valueTranslation.mli b/Gillian-C/lib/valueTranslation.mli index bb5ed5612..315540611 100644 --- a/Gillian-C/lib/valueTranslation.mli +++ b/Gillian-C/lib/valueTranslation.mli @@ -24,8 +24,11 @@ val gil_size_of_compcert : Compcert.Camlcoq.Z.t -> Z.t (** {3 Block serialization} *) -val loc_name_of_block : Compcert.Camlcoq.P.t -> string -val block_of_loc_name : string -> Compcert.Camlcoq.P.t +val loc_name_of_block : + Compcert.Camlcoq.P.t -> Gil_syntax.Id.loc Gil_syntax.Id.t + +val block_of_loc_name : + [< Gil_syntax.Id.any_loc ] Gil_syntax.Id.t -> Compcert.Camlcoq.P.t (** {3 Permission serialization} *) diff --git a/Gillian-C2/lib/common/constants.ml b/Gillian-C2/lib/common/constants.ml index 8a3c0e276..d53290564 100644 --- a/Gillian-C2/lib/common/constants.ml +++ b/Gillian-C2/lib/common/constants.ml @@ -63,7 +63,7 @@ module CBMC_names = struct end module Gillian_C2_names = struct - let return_by_copy_name = "i___ret" + let return_by_copy_name = Gil_syntax.Var.of_string "i___ret" let ret_label = "ret" end diff --git a/Gillian-C2/lib/common/dune b/Gillian-C2/lib/common/dune index 76fb94930..95e9a2acd 100644 --- a/Gillian-C2/lib/common/dune +++ b/Gillian-C2/lib/common/dune @@ -1,5 +1,10 @@ (library (name kcommons) - (libraries zarith ppx_deriving.runtime ppx_deriving_yojson.runtime fmt) + (libraries + gillian + zarith + ppx_deriving.runtime + ppx_deriving_yojson.runtime + fmt) (preprocess (pps ppx_deriving.std ppx_deriving_yojson))) diff --git a/Gillian-C2/lib/compiler/compile.ml b/Gillian-C2/lib/compiler/compile.ml index e5f0afad1..9bf61dc65 100644 --- a/Gillian-C2/lib/compiler/compile.ml +++ b/Gillian-C2/lib/compiler/compile.ml @@ -41,7 +41,8 @@ let set_global_function (fn : Program.Func.t) : Body_item.t Seq.t = let target = Expr.string target in let glob_set_fun = Expr.string Constants.Internal_functions.glob_set_fun in let call = - b @@ Cmd.Call ("u", glob_set_fun, [ symbol; target ], None, None) + b + @@ Cmd.Call (Var.of_string "u", glob_set_fun, [ symbol; target ], None, None) in Seq.return call @@ -58,15 +59,23 @@ let set_global_var ~ctx (gv : Program.Global_var.t) : Body_item.t Seq.t = else (* We start by allocating the variable *) let size = Ctx.size_of ctx gv.type_ in - let loc_expr, alloc_cmd = Memory.alloc ~loc_var:"ll" ~size in + let loc_expr, alloc_cmd = + Memory.alloc ~loc_var:(Var.of_string "ll") ~size + in let alloc_cmd = b alloc_cmd in let size = Expr.int size in - let loc = "loc" in + let loc = Var.of_string "loc" in let assign_cmd = b @@ Cmd.Assignment (loc, loc_expr) in let loc = Expr.PVar loc in let store_zeros_cmd = let store_zeros = Constants.Internal_functions.store_zeros in - b @@ Cmd.Call ("u", Lit (String store_zeros), [ loc; size ], None, None) + b + @@ Cmd.Call + ( Var.of_string "u", + Lit (String store_zeros), + [ loc; size ], + None, + None ) in let store_value_cmds = @@ -78,7 +87,11 @@ let set_global_var ~ctx (gv : Program.Global_var.t) : Body_item.t Seq.t = let store_value = match v with | ByValue v -> - [ b (Memory.store_scalar ~ctx ~var:"u" dst v gv.type_) ] + [ + b + (Memory.store_scalar ~ctx ~var:(Var.of_string "u") dst v + gv.type_); + ] | ByCompositValue { writes; _ } -> Memory.write_composit ~ctx ~annot:b ~dst writes | _ -> Error.unexpected "compile_global_var: not by value" @@ -88,18 +101,24 @@ let set_global_var ~ctx (gv : Program.Global_var.t) : Body_item.t Seq.t = let drom_perm_cmd = let drom_perm = Mem_interface.(str_ac (AMem DropPerm)) in let perm_string = Expr.Lit (String (Perm.to_string Writable)) in - b @@ Cmd.LAction ("u", drom_perm, [ loc; Expr.zero_i; size; perm_string ]) + b + @@ Cmd.LAction + ( Var.of_string "u", + drom_perm, + [ loc; Expr.zero_i; size; perm_string ] ) in let symexpr = Expr.Lit (String gv.symbol) in let set_symbol_cmd = let set_symbol = Mem_interface.(str_ac (AGEnv SetSymbol)) in - b @@ Cmd.LAction ("u", set_symbol, [ symexpr; loc ]) + b @@ Cmd.LAction (Var.of_string "u", set_symbol, [ symexpr; loc ]) in let set_def_cmd = let set_def = Mem_interface.(str_ac (AGEnv SetDef)) in b @@ Cmd.LAction - ("u", set_def, [ loc; EList [ Lit (String "variable"); symexpr ] ]) + ( Var.of_string "u", + set_def, + [ loc; EList [ Lit (String "variable"); symexpr ] ] ) in [ alloc_cmd; assign_cmd; store_zeros_cmd ] @ store_value_cmds @@ -115,13 +134,13 @@ let set_global_env_proc (ctx : Ctx.t) = let constructor_calls = Seq.map (fun c -> - let cmd = Cmd.Call ("u", Expr.string c, [], None, None) in + let cmd = Cmd.Call (Var.of_string "u", Expr.string c, [], None, None) in Body_item.make cmd) (Hashset.to_seq ctx.prog.constrs) in let ret = let b = Body_item.make in - let assign = b @@ Cmd.Assignment (Kutils.Names.return_variable, Lit Null) in + let assign = b @@ Cmd.Assignment (Id.return_variable, Lit Null) in let ret = b Cmd.ReturnNormal in Seq.cons assign (Seq.return ret) in @@ -163,13 +182,17 @@ let compile_alloc_params ~ctx params = List.concat_map (fun (param, type_) -> if Ctx.is_zst_access ctx type_ then [] - else if Ctx.representable_in_store ctx type_ && Ctx.in_memory ctx param + else if + Ctx.representable_in_store ctx type_ + && Ctx.in_memory ctx (Var.str param) then + let param = param in let ptr, cmda = Memory.alloc_ptr ~ctx type_ in let cmdb = Memory.store_scalar ~ctx ptr (PVar param) type_ in let cmdc = Cmd.Assignment (param, ptr) in [ cmda; cmdb; cmdc ] else if not (Ctx.representable_in_store ctx type_) then + let param = param in (* Passing a structure to the function. In that case, we copy it. *) let dst, cmda = Memory.alloc_ptr ~ctx type_ in let cmdb = Memory.memcpy ~ctx ~dst ~src:(PVar param) ~type_ in @@ -222,7 +245,7 @@ let compile_function ?map_body ~ctx (func : Program.Func.t) : (fun x -> match x.Param.identifier with | None -> (Ctx.fresh_v ctx, x.type_) - | Some s -> (s, x.type_)) + | Some s -> (Var.of_string s, x.type_)) func.params in let proc_spec = None in @@ -231,9 +254,7 @@ let compile_function ?map_body ~ctx (func : Program.Func.t) : let b ?(cmd_kind = C2_annot.Hidden) = Body_item.make_hloc ~loc:func.location ~cmd_kind in - let return_undef = - b (Assignment (Kutils.Names.return_variable, Lit Undefined)) - in + let return_undef = b (Assignment (Id.return_variable, Lit Undefined)) in let return_block = set_first_label ~annot:(b ~loop:[] ?display:None ?cmd_kind:None) @@ -288,7 +309,7 @@ module Start_for_harness = struct (fun (p : Param.t) -> let ident = match p.identifier with - | None -> Ctx.fresh_v ctx + | None -> Var.str @@ Ctx.fresh_v ctx | Some ident -> ident in let lhs = expr p.type_ (Symbol ident) in diff --git a/Gillian-C2/lib/compiler/compile_expr.ml b/Gillian-C2/lib/compiler/compile_expr.ml index 7345cb781..40983d7b4 100644 --- a/Gillian-C2/lib/compiler/compile_expr.ml +++ b/Gillian-C2/lib/compiler/compile_expr.ml @@ -149,13 +149,13 @@ type access = [@@deriving show { with_path = false }] let write_list_member ~list ~index ~total_size e = - let list_e = Expr.PVar list in + let list_e = Expr.PVar (Var.of_string list) in let values = List.init total_size (fun i -> if index == i then e else Expr.list_nth list_e i) in let new_list = Expr.EList values in - Cmd.Assignment (list, new_list) + Cmd.Assignment (Var.of_string list, new_list) let dummy_access ~ctx type_ = if Ctx.is_zst_access ctx type_ then ZST @@ -692,9 +692,12 @@ let rec lvalue_as_access ~ctx ~read (lvalue : GExpr.t) : access Cs.with_body = | Symbol x -> if Ctx.is_local ctx x then if not (Ctx.representable_in_store ctx lvalue.type_) then - Cs.return (InMemoryComposit { ptr = PVar x; type_ = lvalue.type_ }) + Cs.return + (InMemoryComposit + { ptr = PVar (Var.of_string x); type_ = lvalue.type_ }) else if Ctx.in_memory ctx x then - Cs.return (InMemoryScalar { ptr = PVar x; loaded = None }) + Cs.return + (InMemoryScalar { ptr = PVar (Var.of_string x); loaded = None }) else (Direct x, []) else if Ctx.is_function_symbol ctx x then Cs.return (DirectFunction x) else @@ -718,7 +721,8 @@ let rec lvalue_as_access ~ctx ~read (lvalue : GExpr.t) : access Cs.with_body = Cs.return (InMemoryComposit { ptr = ge; type_ = lvalue.type_ }) else if read then let+ v = Memory.load_scalar ~ctx ge lvalue.type_ |> Cs.map_l b in - InMemoryScalar { ptr = ge; loaded = Some (PVar v) } + InMemoryScalar + { ptr = ge; loaded = Some (PVar (Var.of_string v)) } else Cs.return (InMemoryScalar { ptr = ge; loaded = None }) | ByCopy _ | ByCompositValue _ -> Error.unexpected "Pointers should be scalars passed by value" @@ -966,7 +970,7 @@ and poison ~ctx ~annot (lhs : GExpr.t) = let write = match access with | ZST -> Cmd.Skip - | Direct x -> Assignment (x, Lit Undefined) + | Direct x -> Assignment (Var.of_string x, Lit Undefined) | InMemoryScalar { ptr; _ } | InMemoryComposit { ptr; _ } -> Memory.poison ~ctx ~dst:ptr (Ctx.size_of ctx type_) | ListMember { list; index; total_size } -> @@ -984,7 +988,7 @@ and compile_assign_val ~ctx ~annot ~lhs ~(rhs : Val_repr.t) = | ZST, _ -> Ok [ annot Cmd.Skip ] (* We need a command in case we try want to add a label *) - | Direct x, ByValue v -> Ok [ annot (Assignment (x, v)) ] + | Direct x, ByValue v -> Ok [ annot (Assignment (Var.of_string x, v)) ] | InMemoryScalar { ptr; _ }, ByValue v -> Ok [ annot (Memory.store_scalar ~ctx ptr v lhs.type_) ] | ( InMemoryComposit { ptr = ptr_access; type_ = type_access }, @@ -1090,13 +1094,13 @@ and compile_symbol ~ctx ~b expr = let* access = lvalue_as_access ~ctx ~read:true expr in match access with | ZST -> by_value (Lit Null) - | Direct x -> by_value (Expr.PVar x) + | Direct x -> by_value (Expr.PVar (Var.of_string x)) | ListMember { list; index; _ } -> - by_value (Expr.list_nth (PVar list) index) + by_value (Expr.list_nth (PVar (Var.of_string list)) index) | InMemoryScalar { loaded = Some e; _ } -> by_value e | InMemoryScalar { loaded = None; ptr } -> let* var = Memory.load_scalar ~ctx ptr expr.type_ |> Cs.map_l b in - by_value (PVar var) + by_value (PVar (Var.of_string var)) | InMemoryComposit { ptr; type_ } -> by_copy ptr type_ | InMemoryFunction { symbol = Some sym; _ } -> Cs.return (Val_repr.Procedure (Expr.string sym)) @@ -1309,7 +1313,7 @@ and compile_expr ~(ctx : Ctx.t) (expr : GExpr.t) : Val_repr.t Cs.with_body = let new_ptr = Memory.ptr_add ptr_to_read offset in if Ctx.representable_in_store ctx expr.type_ then let* var = Memory.load_scalar ~ctx new_ptr expr.type_ |> Cs.map_l b in - by_value (PVar var) + by_value (PVar (Var.of_string var)) else by_copy new_ptr expr.type_ | Struct elems -> ( let () = log_type "Struct" in @@ -1513,7 +1517,7 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = | Procedure _ -> Error.code_error "Return value is a procedure") | None -> Cs.return ~app:[] (Expr.Lit Undefined) in - let variable = Utils.Names.return_variable in + let variable = Id.return_variable in s @ add_annot [ @@ -1530,11 +1534,11 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = let lhs = GExpr.as_symbol glhs in (* ZSTs are just (GIL) Null values *) if Ctx.is_zst_access ctx ty then - let cmd = Cmd.Assignment (lhs, Lit Null) in + let cmd = Cmd.Assignment (Var.of_string @@ lhs, Lit Null) in [ b ~cmd_kind:(Normal true) cmd ] |> void else if not (Ctx.representable_in_store ctx ty) then let ptr, alloc_cmd = Memory.alloc_ptr ~ctx ty in - let assign = Cmd.Assignment (lhs, ptr) in + let assign = Cmd.Assignment (Var.of_string @@ lhs, ptr) in let write = match value with | None -> [] @@ -1553,7 +1557,7 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = |> void else if Ctx.in_memory ctx lhs then let ptr, action_cmd = Memory.alloc_ptr ~ctx ty in - let assign = Cmd.Assignment (lhs, ptr) in + let assign = Cmd.Assignment (Var.of_string @@ lhs, ptr) in let pre, write = match value with | None -> ([], []) @@ -1563,7 +1567,9 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = Val_repr.as_value ~error:Error.code_error ~msg:"declaration initial value for in-memory scalar access" v in - let write = Memory.store_scalar ~ctx (Expr.PVar lhs) v ty in + let write = + Memory.store_scalar ~ctx (Expr.PVar (Var.of_string @@ lhs)) v ty + in (pre, [ b write ]) in pre @@ -1583,7 +1589,8 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = (e, s) | None -> (Lit Undefined, []) in - s @ [ b ~cmd_kind:(Normal true) (Assignment (lhs, v)) ] |> void + s @ [ b ~cmd_kind:(Normal true) (Assignment (Var.of_string @@ lhs, v)) ] + |> void | SAssign { lhs; rhs } -> let () = log_kind "SAssign" in (* Special case: my patched Kani will comment "deinit" if this assignment @@ -1612,7 +1619,8 @@ and compile_statement ~ctx (stmt : Stmt.t) : Val_repr.t Cs.with_body = let write = match (access, v) with | ZST, _ -> [] - | Direct x, ByValue v -> [ b (Cmd.Assignment (x, v)) ] + | Direct x, ByValue v -> + [ b (Cmd.Assignment (Var.of_string @@ x, v)) ] | InMemoryScalar { ptr; _ }, ByValue v -> [ b (Memory.store_scalar ~ctx ptr v lvalue.type_) ] | InMemoryComposit { ptr = dst; type_ }, ByCopy { ptr = src; _ } -> diff --git a/Gillian-C2/lib/compiler/ctx.ml b/Gillian-C2/lib/compiler/ctx.ml index fe880f74e..bd87e1a91 100644 --- a/Gillian-C2/lib/compiler/ctx.ml +++ b/Gillian-C2/lib/compiler/ctx.ml @@ -110,7 +110,7 @@ type t = { exec_mode : Kutils.Exec_mode.t; machine : Machine_model.t; prog : Program.t; - fresh_v : unit -> string; + fresh_v : unit -> Gil_syntax.Var.t; in_memory : string Hashset.t; locals : (string, Local.t) Hashtbl.t; allocated_temps : Local.t Hashset.t; @@ -136,7 +136,11 @@ let make ~exec_mode ~machine ~prog ~harness () = } let with_new_generators t = - { t with fresh_v = Generators.temp_var (); fresh_lab = Generators.label () } + { + t with + fresh_v = (fun () -> Gil_syntax.Var.of_string @@ Generators.temp_var () ()); + fresh_lab = Generators.label (); + } let fresh_v t = t.fresh_v () let fresh_lab t = t.fresh_lab () @@ -200,7 +204,7 @@ let with_entering_body ctx ~body ~params ~location = p.identifier) params; let allocated_temps = Hashset.empty ~size:32 () in - let fresh_v = Generators.temp_var () in + let fresh_v () = Gil_syntax.Var.of_string @@ Generators.temp_var () () in { ctx with in_memory; locals; fresh_v; allocated_temps } let archi ctx : Archi.t = diff --git a/Gillian-C2/lib/compiler/memory.ml b/Gillian-C2/lib/compiler/memory.ml index 60877d99f..b0df1d023 100644 --- a/Gillian-C2/lib/compiler/memory.ml +++ b/Gillian-C2/lib/compiler/memory.ml @@ -68,7 +68,9 @@ let alloc_temp ~ctx ~location ty : Expr.t Cs.with_cmds = let ptr, alloc_cmd = alloc_ptr ~ctx ty in let temp = Ctx.fresh_v ctx in let assign = Cmd.Assignment (temp, ptr) in - let () = Ctx.register_allocated_temp ctx ~name:temp ~type_:ty ~location in + let () = + Ctx.register_allocated_temp ctx ~name:(Var.str temp) ~type_:ty ~location + in Cs.return ~app:[ alloc_cmd; assign ] (Expr.PVar temp) (** Should only be called for a local that is in memory*) @@ -80,7 +82,13 @@ let dealloc_local ~ctx ~cmd_kind (l : Ctx.Local.t) : Body_item.t = let var = Ctx.fresh_v ctx in let cmd = Cmd.LAction - (var, free, [ Expr.list_nth (Expr.PVar l.symbol) 0; Expr.zero_i; size ]) + ( var, + free, + [ + Expr.list_nth (Expr.PVar (Var.of_string l.symbol)) 0; + Expr.zero_i; + size; + ] ) in let loc = Body_item.compile_location l.location in Body_item.make ~loc ~cmd_kind cmd @@ -106,7 +114,7 @@ let load_scalar ~ctx ?var (e : Expr.t) (t : GType.t) : string Cs.with_cmds = let load_cmd = Cmd.Call (var, Lit (String loadv), [ chunk; e ], None, None) in - (var, [ load_cmd ]) + (Var.str var, [ load_cmd ]) let store_scalar ~ctx ?var (p : Expr.t) (v : Expr.t) (t : GType.t) : string Cmd.t = diff --git a/Gillian-C2/lib/compiler/val_repr.ml b/Gillian-C2/lib/compiler/val_repr.ml index e28e73f6b..0bafd5eb5 100644 --- a/Gillian-C2/lib/compiler/val_repr.ml +++ b/Gillian-C2/lib/compiler/val_repr.ml @@ -51,7 +51,7 @@ let same_kind a b = GType.equal typea typeb | _ -> false -let copy_into (v : t) (x : string) : t Cs.with_cmds = +let copy_into (v : t) (x : Var.t) : t Cs.with_cmds = match v with | Procedure e -> let cmd = Cmd.Assignment (x, e) in diff --git a/Gillian-C2/lib/lifter/c2_lifter.ml b/Gillian-C2/lib/lifter/c2_lifter.ml index a7a257e8a..f5b676a6b 100644 --- a/Gillian-C2/lib/lifter/c2_lifter.ml +++ b/Gillian-C2/lib/lifter/c2_lifter.ml @@ -370,7 +370,8 @@ struct let> pid = match CmdReport.(cmd_report.cmd) with | Call (_, Lit (String pid), _, _, _) - | ECall (_, (Lit (String pid) | PVar pid), _, _) -> Some pid + | ECall (_, Lit (String pid), _, _) -> Some pid + | ECall (_, PVar pid, _, _) -> Some (Var.str pid) | _ -> None in let kind = diff --git a/Gillian-C2/lib/memory_model/External.ml b/Gillian-C2/lib/memory_model/External.ml index f39d9018b..c354b077c 100644 --- a/Gillian-C2/lib/memory_model/External.ml +++ b/Gillian-C2/lib/memory_model/External.ml @@ -39,7 +39,7 @@ struct (state : State.t) (cs : Call_stack.t) (i : int) - (x : string) + (x : Var.t) (pid : string) (v_args : Val.t list) (j : int option) = diff --git a/Gillian-C2/lib/memory_model/GEnv.ml b/Gillian-C2/lib/memory_model/GEnv.ml index 8b0fef6b8..949d185a8 100644 --- a/Gillian-C2/lib/memory_model/GEnv.ml +++ b/Gillian-C2/lib/memory_model/GEnv.ml @@ -1,7 +1,17 @@ type err_t = Symbol_not_found of string [@@deriving show, yojson] +module Id = Gil_syntax.Id module StringMap = Map.Make (String) +module LocMap = Map.Make (struct + include Id + + type nonrec t = any_loc Id.t + + let of_yojson = of_yojson' + let to_yojson = to_yojson' +end) + module Make (Def_value : sig type t type vt @@ -20,11 +30,11 @@ end) (Delayed_hack : sig val return : ?learned:Gil_syntax.Expr.t list -> - ?learned_types:(string * Gil_syntax.Type.t) list -> + ?learned_types:(Id.any_var Id.t * Gil_syntax.Type.t) list -> 'a -> 'a t - val resolve_or_create_lt : Def_value.lt -> string t + val resolve_or_create_lt : Def_value.lt -> Id.any_loc Id.t t val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t end) = struct @@ -40,12 +50,10 @@ struct type def = FunDef of Def_value.t | GlobVar of Def_value.t type t = { - symb : string StringMap.t; (** maps symbols to loc names *) - defs : def StringMap.t; (** maps loc names to definitions *) + symb : Id.any_loc Id.t StringMap.t; (** maps symbols to loc names *) + defs : def LocMap.t; (** maps loc names to definitions *) } - let find_opt x s = try Some (StringMap.find x s) with Not_found -> None - let find_symbol genv sym = try Ok (StringMap.find sym genv.symb) with Not_found -> Error (Symbol_not_found sym) @@ -64,11 +72,11 @@ struct let symb = StringMap.add sym block genv.symb in { genv with symb } - let find_def genv block = StringMap.find block genv.defs + let find_def genv block = LocMap.find block genv.defs let set_def genv block def = try - let cur_def = StringMap.find block genv.defs in + let cur_def = LocMap.find block genv.defs in match (def, cur_def) with | GlobVar a, GlobVar b | FunDef a, FunDef b -> let open Delayed_hack in @@ -77,10 +85,10 @@ struct failwith "Equality between a global variable and a function definition" with Not_found -> - let defs = StringMap.add block def genv.defs in + let defs = LocMap.add block def genv.defs in Delayed_hack.return { genv with defs } - let empty = { symb = StringMap.empty; defs = StringMap.empty } + let empty = { symb = StringMap.empty; defs = LocMap.empty } (** Serialization of definitions *) let serialize_def def = @@ -119,8 +127,8 @@ struct let pp_one ft s l = try let d = find_def genv l in - Format.fprintf ft "'%s' -> %s -> %a@\n" s l pp_def d - with Not_found -> Format.fprintf ft "'%s' -> %s -> UNKNOWN@\n" s l + Format.fprintf ft "'%s' -> %a -> %a@\n" s Id.pp l pp_def d + with Not_found -> Format.fprintf ft "'%s' -> %a -> UNKNOWN@\n" s Id.pp l in if !Kconfig.hide_genv then Format.fprintf fmt "{@[@\nHIDDEN@]@\n}" else @@ -147,43 +155,33 @@ struct GlobVar substituted in let with_substituted_defs = - { genv with defs = StringMap.map substitute_in_def genv.defs } - in - let aloc_subst = - Subst.filter subst (fun var _ -> - match var with - | ALoc _ -> true - | _ -> false) + { genv with defs = LocMap.map substitute_in_def genv.defs } in let rename_val old_loc new_loc map = - StringMap.map (fun k -> if String.equal old_loc k then new_loc else k) map + StringMap.map (fun k -> if Id.equal old_loc k then new_loc else k) map in let rename_key old_loc new_loc map = - match find_opt old_loc map with + match LocMap.find_opt old_loc map with | None -> map - | Some d -> StringMap.add new_loc d (StringMap.remove old_loc map) + | Some d -> LocMap.add new_loc d (LocMap.remove old_loc map) in (* Then we substitute the locations *) - Subst.fold aloc_subst - (fun old_loc new_loc cgenv -> - let old_loc = - match old_loc with - | ALoc loc -> loc - | _ -> raise (Failure "Impossible by construction") - in - let new_loc = - match new_loc with - | Lit (Loc loc) | ALoc loc -> loc - | _ -> - failwith - (Format.asprintf "Heap substitution failed for loc : %a" Expr.pp - new_loc) - in - { - symb = rename_val old_loc new_loc cgenv.symb; - defs = rename_key old_loc new_loc cgenv.defs; - }) - with_substituted_defs + Subst.to_list subst + |> List.filter_map (function + | Expr.ALoc aloc, Expr.Lit (Loc after) -> + Some ((aloc :> Id.any_loc Id.t), (after :> Id.any_loc Id.t)) + | Expr.ALoc aloc, Expr.ALoc after -> + Some ((aloc :> Id.any_loc Id.t), (after :> Id.any_loc Id.t)) + | Expr.ALoc aloc, after -> + Fmt.failwith "Heap substitution failed for loc : %a" Expr.pp after + | _ -> None) + |> List.fold_left + (fun cgenv (old_loc, new_loc) -> + { + symb = rename_val old_loc new_loc cgenv.symb; + defs = rename_key old_loc new_loc cgenv.defs; + }) + with_substituted_defs (** This function returns the assertions as well as a list of locations corresponding to functions declaration, so that memory knows not @@ -220,7 +218,7 @@ module Concrete = type t = string type vt = Literal.t - type lt = string + type lt = Id.any_loc Id.t let pp = Fmt.string let to_expr s = Expr.Lit (String s) @@ -238,7 +236,7 @@ module Concrete = | Literal.LList ll -> Expr.EList (List.map vt_to_expr ll) | l -> Lit l - let of_lt x = x + let of_lt x = Id.str x end) (struct type 'a t = 'a @@ -283,7 +281,7 @@ module Symbolic = let open Gil_syntax.Expr.Infix in [ a == b ] - let resolve_or_create_lt lvar_loc : string t = + let resolve_or_create_lt lvar_loc : Id.any_loc Id.t t = let open Syntax in let* loc_name = resolve_loc lvar_loc in match loc_name with @@ -291,11 +289,11 @@ module Symbolic = let new_loc_name = Gil_syntax.ALoc.alloc () in let learned = lvar_loc #== (ALoc new_loc_name) in Logging.verbose (fun fmt -> - fmt "Couldn't resolve loc %a, created %s" Gil_syntax.Expr.pp - lvar_loc new_loc_name); - return ~learned new_loc_name + fmt "Couldn't resolve loc %a, created %a" Gil_syntax.Expr.pp + lvar_loc Id.pp new_loc_name); + return ~learned (new_loc_name :> Id.any_loc Id.t) | Some l -> Logging.verbose (fun fmt -> - fmt "Resolved %a as %s" Gil_syntax.Expr.pp lvar_loc l); + fmt "Resolved %a as %a" Gil_syntax.Expr.pp lvar_loc Id.pp l); return l end) diff --git a/Gillian-C2/lib/memory_model/GEnv.mli b/Gillian-C2/lib/memory_model/GEnv.mli index 5e4affdc3..9fdfd5c23 100644 --- a/Gillian-C2/lib/memory_model/GEnv.mli +++ b/Gillian-C2/lib/memory_model/GEnv.mli @@ -1,6 +1,8 @@ type err_t = Symbol_not_found of string [@@deriving show, yojson] +module Id := Gil_syntax.Id module StringMap : Map.S with type key = string +module LocMap : Map.S with type key = Id.any_loc Id.t module Concrete : sig open Gil_syntax @@ -12,23 +14,23 @@ module Concrete : sig val deserialize_def : Literal.t -> def type t = { - symb : string StringMap.t; (** maps symbols to loc names *) - defs : def StringMap.t; (** maps loc names to definitions *) + symb : Id.any_loc Id.t StringMap.t; (** maps symbols to loc names *) + defs : def LocMap.t; (** maps loc names to definitions *) } (** Finds a location name given symbol in the global environment *) - val find_symbol : t -> string -> (string, err_t) result + val find_symbol : t -> string -> (Id.any_loc Id.t, err_t) result (** Finds a definition given its location name in the global environment *) - val find_def : t -> string -> def + val find_def : t -> Id.any_loc Id.t -> def (** [set_symbol genv symbol locname ] Returns a new global environment where the symbol [symbol] is associated with the location [locname] *) - val set_symbol : t -> string -> string -> t + val set_symbol : t -> string -> Id.any_loc Id.t -> t (** [set_def genv locname def ] Returns a new global environment where the block [locname] is associated with the global definition [def] *) - val set_def : t -> string -> def -> t + val set_def : t -> Id.any_loc Id.t -> def -> t (** Empty global environment *) val empty : t @@ -39,7 +41,7 @@ module Concrete : sig (** {3 Symbolic things} *) val substitution : Gillian.Symbolic.Subst.t -> t -> t - val assertions : t -> string list * Gillian.Gil_syntax.Asrt.t + val assertions : t -> Id.any_loc Id.t list * Gillian.Gil_syntax.Asrt.t end module Symbolic : sig @@ -52,15 +54,15 @@ module Symbolic : sig val deserialize_def : Expr.t -> def type t = { - symb : string StringMap.t; (** maps symbols to loc names *) - defs : def StringMap.t; (** maps loc names to definitions *) + symb : Id.any_loc Id.t StringMap.t; (** maps symbols to loc names *) + defs : def LocMap.t; (** maps loc names to definitions *) } (** Finds a location name given symbol in the global environment *) - val find_symbol : t -> string -> (string, err_t) result + val find_symbol : t -> string -> (Id.any_loc Id.t, err_t) result (** Finds a definition given its location name in the global environment *) - val find_def : t -> string -> def + val find_def : t -> Id.any_loc Id.t -> def (** [set_symbol genv symbol locname ] Returns a new global environment where the symbol [symbol] is associated with the location [locname] *) @@ -68,7 +70,7 @@ module Symbolic : sig (** [set_def genv locname def ] Returns a new global environment where the block [locname] is associated with the global definition [def] *) - val set_def : t -> string -> def -> t Monadic.Delayed.t + val set_def : t -> Id.any_loc Id.t -> def -> t Monadic.Delayed.t (** Empty global environment *) val empty : t @@ -79,5 +81,5 @@ module Symbolic : sig (** {3 Symbolic things} *) val substitution : Gillian.Symbolic.Subst.t -> t -> t - val assertions : t -> string list * Gillian.Gil_syntax.Asrt.t + val assertions : t -> Id.any_loc Id.t list * Gillian.Gil_syntax.Asrt.t end diff --git a/Gillian-C2/lib/memory_model/MonadicSMemory.ml b/Gillian-C2/lib/memory_model/MonadicSMemory.ml index 9122e480e..5bb76fa89 100644 --- a/Gillian-C2/lib/memory_model/MonadicSMemory.ml +++ b/Gillian-C2/lib/memory_model/MonadicSMemory.ml @@ -13,7 +13,13 @@ module GEnv = GEnv.Symbolic (* Some utils first *) -let resolve_or_create_loc_name (lvar_loc : Expr.t) : string Delayed.t = +type loc_t = Id.any_loc Id.t + +let pp_loc_t = Id.pp +let loc_t_to_yojson = Id.to_yojson' +let loc_t_of_yojson = Id.of_yojson' + +let resolve_or_create_loc_name (lvar_loc : Expr.t) : loc_t Delayed.t = let open Delayed.Syntax in let* loc_name = Delayed.resolve_loc lvar_loc in match loc_name with @@ -21,17 +27,14 @@ let resolve_or_create_loc_name (lvar_loc : Expr.t) : string Delayed.t = let new_loc_name = ALoc.alloc () in let learned = [ Expr.BinOp (ALoc new_loc_name, Equal, lvar_loc) ] in Logging.verbose (fun fmt -> - fmt "Couldn't resolve loc %a, created %s" Expr.pp lvar_loc + fmt "Couldn't resolve loc %a, created %a" Expr.pp lvar_loc Id.pp new_loc_name); - Delayed.return ~learned new_loc_name + Delayed.return ~learned (new_loc_name :> Id.any_loc Id.t) | Some l -> - Logging.verbose (fun fmt -> fmt "Resolved %a as %s" Expr.pp lvar_loc l); + Logging.verbose (fun fmt -> + fmt "Resolved %a as %a" Expr.pp lvar_loc Id.pp l); Delayed.return l -let expr_of_loc_name loc_name = - if GUtils.Names.is_aloc_name loc_name then Expr.ALoc loc_name - else Lit (Loc loc_name) - type init_data = unit let get_init_data _ = () @@ -42,11 +45,8 @@ type st = Subst.t type err_t = | InvalidLocation of Expr.t | NonPositiveArraySize of Expr.t - | MissingLocResource of string - | SHeapTreeErr of { - at_locations : string list; - sheaptree_err : SHeapTree.err; - } + | MissingLocResource of loc_t + | SHeapTreeErr of { at_locations : loc_t list; sheaptree_err : SHeapTree.err } | GEnvErr of GEnv.err_t [@@deriving show, yojson] @@ -64,37 +64,36 @@ let resolve_loc_result loc = module Mem = struct open Delayed.Syntax - module SMap = GUtils.Prelude.Map.Make (struct - include String + module LocMap = GUtils.Prelude.Map.Make (struct + include Id - let of_yojson = function - | `String s -> Ok s - | _ -> Error "string_of_yojson: expected string" + type nonrec t = any_loc t - let to_yojson s = `String s + let of_yojson = of_yojson' + let to_yojson = to_yojson' end) - type t = SHeapTree.t SMap.t + type t = SHeapTree.t LocMap.t - let of_yojson json = SMap.of_yojson SHeapTree.of_yojson json - let to_yojson map = SMap.to_yojson SHeapTree.to_yojson map + let of_yojson json = LocMap.of_yojson SHeapTree.of_yojson json + let to_yojson map = LocMap.to_yojson SHeapTree.to_yojson map let map_lift_err loc res = DR.map_error res (lift_sheaptree_err loc) - let empty = SMap.empty + let empty = LocMap.empty let copy x = x let get_tree_res map loc_name = DR.of_option ~none:(MissingLocResource loc_name) - (SMap.find_opt loc_name map) + (LocMap.find_opt loc_name map) let get_or_create_tree map loc_name = - match SMap.find_opt loc_name map with + match LocMap.find_opt loc_name map with | Some t -> Delayed.return t | None -> Delayed.return SHeapTree.empty - let alloc (map : t) low high : t * string = + let alloc (map : t) low high : t * ALoc.t = let loc = ALoc.alloc () in let tree = SHeapTree.alloc low high in - (SMap.add loc tree map, loc) + (LocMap.add (loc :> loc_t) tree map, loc) let weak_valid_pointer map loc ofs = let open DR.Syntax in @@ -115,7 +114,7 @@ module Mem = struct let++ new_tree = map_lift_err loc_name (SHeapTree.drop_perm tree low high new_perm) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let store map loc chunk ofs value = let open DR.Syntax in @@ -124,7 +123,7 @@ module Mem = struct let++ new_tree = map_lift_err loc_name (SHeapTree.store tree chunk ofs value) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let load map loc chunk ofs = let open DR.Syntax in @@ -133,14 +132,14 @@ module Mem = struct let++ value, new_tree = map_lift_err loc_name (SHeapTree.load tree chunk ofs) in - (value, SMap.add loc_name new_tree map) + (value, LocMap.add loc_name new_tree map) let free map loc low high = let open DR.Syntax in let** loc_name = resolve_loc_result loc in let** tree = get_tree_res map loc_name in let++ new_tree = map_lift_err loc_name (SHeapTree.free tree low high) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let zero_init map loc ofs size = let open DR.Syntax in @@ -149,14 +148,14 @@ module Mem = struct let++ new_tree = map_lift_err loc_name (SHeapTree.zero_init tree ofs size) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let poison map loc ofs size = let open DR.Syntax in let** loc_name = resolve_loc_result loc in let** tree = get_tree_res map loc_name in let++ new_tree = map_lift_err loc_name (SHeapTree.poison tree ofs size) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let cons_single map loc ofs chunk = let open DR.Syntax in @@ -165,7 +164,7 @@ module Mem = struct let++ sval, perm, new_tree = map_lift_err loc_name (SHeapTree.cons_single tree ofs chunk) in - (SMap.add loc_name new_tree map, sval, perm) + (LocMap.add loc_name new_tree map, sval, perm) let prod_single map loc ofs chunk sval perm = let open DR.Syntax in @@ -174,7 +173,7 @@ module Mem = struct let++ new_tree = map_lift_err loc_name (SHeapTree.prod_single tree ofs chunk sval perm) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let get_array map loc ofs size chunk = let open DR.Syntax in @@ -187,7 +186,7 @@ module Mem = struct let++ sarr, perm, new_tree = map_lift_err loc_name (SHeapTree.get_array tree ofs size chunk) in - (SMap.add loc_name new_tree map, loc_name, sarr, perm) + (LocMap.add loc_name new_tree map, loc_name, sarr, perm) let cons_array map loc ofs size chunk = let open DR.Syntax in @@ -200,7 +199,7 @@ module Mem = struct let++ sarr, perm, new_tree = map_lift_err loc_name (SHeapTree.cons_array tree ofs size chunk) in - (SMap.add loc_name new_tree map, loc_name, sarr, perm) + (LocMap.add loc_name new_tree map, loc_name, sarr, perm) let prod_array map loc ofs size chunk array perm = let open DR.Syntax in @@ -214,7 +213,7 @@ module Mem = struct (SHeapTree.prod_array tree ofs size chunk array perm) in Logging.tmi (fun m -> m "created tree: %a" SHeapTree.pp new_tree); - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let cons_freed map loc = let open DR.Syntax in @@ -223,11 +222,11 @@ module Mem = struct let++ () = DR.of_result (SHeapTree.get_freed tree) |> map_lift_err loc_name in - SMap.remove loc_name map + LocMap.remove loc_name map let prod_freed map loc = let+ loc_name = resolve_or_create_loc_name loc in - SMap.add loc_name SHeapTree.freed map + LocMap.add loc_name SHeapTree.freed map let cons_simple ~sheap_consumer map loc low high = let open DR.Syntax in @@ -239,7 +238,7 @@ module Mem = struct let++ new_tree, perm = map_lift_err loc_name (sheap_consumer tree low high) in - (SMap.add loc_name new_tree map, perm) + (LocMap.add loc_name new_tree map, perm) let prod_simple ~sheap_producer map loc low high perm = let open DR.Syntax in @@ -251,7 +250,7 @@ module Mem = struct let++ new_tree = map_lift_err loc_name (sheap_producer tree low high perm) in - SMap.add loc_name new_tree map + LocMap.add loc_name new_tree map let cons_hole = cons_simple ~sheap_consumer:SHeapTree.cons_hole let prod_hole = prod_simple ~sheap_producer:SHeapTree.prod_hole @@ -274,7 +273,7 @@ module Mem = struct let++ bounds, new_tree = map_lift_err loc_name (DR.of_result (SHeapTree.cons_bounds tree)) in - (bounds, SMap.add loc_name new_tree map) + (bounds, LocMap.add loc_name new_tree map) let prod_bounds map loc bounds = let open DR.Syntax in @@ -283,7 +282,7 @@ module Mem = struct let++ tree_set = map_lift_err loc_name (DR.of_result (SHeapTree.prod_bounds tree bounds)) in - SMap.add loc_name tree_set map + LocMap.add loc_name tree_set map let move map dst_loc dst_ofs src_loc src_ofs sz = let open DR.Syntax in @@ -303,22 +302,20 @@ module Mem = struct sheaptree_err = err; }) in - SMap.add dst_loc_name new_dst_tree map + LocMap.add dst_loc_name new_dst_tree map let lvars map = - let open Utils.Containers in - SMap.fold - (fun _ tree acc -> SS.union (SHeapTree.lvars tree) acc) - map SS.empty + LocMap.fold + (fun _ tree acc -> LVar.Set.union (SHeapTree.lvars tree) acc) + map LVar.Set.empty let alocs map = - let open Utils.Containers in - SMap.fold - (fun _ tree acc -> SS.union (SHeapTree.alocs tree) acc) - map SS.empty + LocMap.fold + (fun _ tree acc -> ALoc.Set.union (SHeapTree.alocs tree) acc) + map ALoc.Set.empty let assertions ~exclude map = - SMap.fold + LocMap.fold (fun loc tree acc -> if not (List.mem loc exclude) then SHeapTree.assertions ~loc tree @ acc else acc) @@ -333,22 +330,20 @@ module Mem = struct with Not_found -> false in let iter_exclude f map = - SMap.iter (fun loc x -> if not (is_fun loc) then f loc x) map + LocMap.iter (fun loc x -> if not (is_fun loc) then f loc x) map in let open Fmt in - pf ft "%a" - (Dump.iter_bindings iter_exclude nop string SHeapTree.pp_full) - mem + pf ft "%a" (Dump.iter_bindings iter_exclude nop Id.pp SHeapTree.pp_full) mem let substitution ?(genv = GEnv.empty) subst mem : (t, SHeapTree.err) DR.t = let open DR.Syntax in - if Subst.domain subst None = Expr.Set.empty then DR.ok mem + if Subst.domain subst = Expr.Set.empty then DR.ok mem else let aloc_subst = Subst.fold subst (fun l r acc -> match l with - | ALoc aloc -> (aloc, r) :: acc + | ALoc aloc -> ((aloc :> loc_t), r) :: acc | _ -> acc) [] in @@ -358,35 +353,36 @@ module Mem = struct let subst_tree = SHeapTree.substitution ~le_subst ~sval_subst ~svarr_subst in - let substituted = SMap.map subst_tree mem in + let substituted = LocMap.map subst_tree mem in List.fold_left (fun acc (old_loc, new_loc) -> let** acc = acc in Logging.verbose (fun fmt -> - fmt "SHOULD Merge locs: %s --> %a" old_loc Expr.pp new_loc); + fmt "SHOULD Merge locs: %a --> %a" Id.pp old_loc Expr.pp new_loc); Logging.tmi (fun fmt -> fmt "IN MEMORY: %a" (pp_full ~genv) acc); let new_loc = match new_loc with - | Lit (Loc loc) | ALoc loc -> loc + | Lit (Loc loc) -> (loc :> loc_t) + | ALoc loc -> (loc :> loc_t) | _ -> Fmt.failwith "Heap substitution failed for loc : %a" Expr.pp new_loc in - match SMap.find_opt new_loc acc with + match LocMap.find_opt new_loc acc with | Some new_tree -> ( try - let old_tree = SMap.find old_loc acc in - let without_old = SMap.remove old_loc acc in + let old_tree = LocMap.find old_loc acc in + let without_old = LocMap.remove old_loc acc in Logging.verbose (fun fmt -> fmt "Merging now."); let++ merged = SHeapTree.merge ~new_tree ~old_tree in Logging.verbose (fun fmt -> fmt "Done merging."); - SMap.add new_loc merged without_old + LocMap.add new_loc merged without_old with Not_found -> DR.ok acc) | None -> ( try - let tree = SMap.find old_loc acc in - DR.ok (SMap.add new_loc tree (SMap.remove old_loc acc)) + let tree = LocMap.find old_loc acc in + DR.ok (LocMap.add new_loc tree (LocMap.remove old_loc acc)) with Not_found -> DR.ok acc)) (DR.ok substituted) aloc_subst @@ -399,11 +395,11 @@ module Mem = struct with Not_found -> false in let is_first = ref true in - SMap.iter + LocMap.iter (fun loc tree -> if not (is_fun loc) then ( if !is_first then is_first := false else Fmt.pf ft "@\n"; - Fmt.pf ft "%s -> @[%a@]" loc SHeapTree.pp tree)) + Fmt.pf ft "%a -> @[%a@]" Id.pp loc SHeapTree.pp tree)) mem let pp ?(genv = GEnv.empty) fmt map = pp_normal ~genv fmt map @@ -600,7 +596,7 @@ let execute_get_array heap params = let** mem, loc_name, array, perm = Mem.get_array heap.mem loc ofs size chunk in - let loc_e = expr_of_loc_name loc_name in + let loc_e = Expr.loc_from_loc_name loc_name in let array_e = SVArray.to_gil_expr ~chunk ~size array in let perm_string = Perm.opt_to_string perm in DR.ok @@ -795,13 +791,13 @@ let pp_err fmt (e : err_t) = | InvalidLocation loc -> Fmt.pf fmt "'%a' cannot be resolved as a location" Expr.pp loc | MissingLocResource l -> - Fmt.pf fmt "No block associated with location '%s'" l + Fmt.pf fmt "No block associated with location '%a'" Id.pp l | SHeapTreeErr { at_locations; sheaptree_err } -> Fmt.pf fmt "Tree at location%a raised: <%a>" (fun fmt l -> match l with - | [ s ] -> Fmt.pf fmt " '%s'" s - | l -> Fmt.pf fmt "s %a" (Fmt.Dump.list Fmt.string) l) + | [ s ] -> Fmt.pf fmt " '%a'" Id.pp s + | l -> Fmt.pf fmt "s %a" (Fmt.Dump.list Id.pp) l) at_locations SHeapTree.pp_err sheaptree_err | GEnvErr (Symbol_not_found s) -> Fmt.pf fmt "Symbol not found: %s" s | NonPositiveArraySize vt -> @@ -816,8 +812,8 @@ let pp fmt h = (Mem.pp ~genv:h.genv) h.mem -let pp_by_need (_ : SS.t) fmt h = pp fmt h -let get_print_info _ _ = (SS.empty, SS.empty) +let pp_by_need _ fmt h = pp fmt h +let get_print_info _ _ = (LVar.Set.empty, Id.Sets.LocSet.empty) (* let str_noheap _ = "NO HEAP PRINTED" *) @@ -949,7 +945,7 @@ module Lift = struct store |> List.map (fun (var, value) : Variable.t -> let value = Fmt.to_to_string (Fmt.hbox Expr.pp) value in - Variable.create_leaf var value ()) + Variable.create_leaf (Var.str var) value ()) |> List.sort (fun (v : Variable.t) w -> Stdlib.compare v.name w.name) let make_node ~get_new_scope_id ~variables ~name ~value ?(children = []) () : @@ -982,7 +978,7 @@ module Lift = struct let make_node = make_node ~get_new_scope_id ~variables in let heap_id = get_new_scope_id () in let heap_vars = - Mem.SMap.to_seq mem + Mem.LocMap.to_seq mem |> Seq.map (fun (loc, tree) -> SHeapTree.Lift.get_variable ~make_node ~loc tree) |> List.of_seq @@ -1002,7 +998,7 @@ end let get_recovery_vals _ = function | InvalidLocation e -> - List.map (fun x -> Expr.LVar x) (SS.elements (Expr.lvars e)) + List.map (fun x -> Expr.LVar x) (LVar.Set.elements (Expr.lvars e)) | MissingLocResource l -> [ Expr.loc_from_loc_name l ] | SHeapTreeErr { at_locations; _ } -> List.map Expr.loc_from_loc_name at_locations diff --git a/Gillian-C2/lib/memory_model/MonadicSMemory.mli b/Gillian-C2/lib/memory_model/MonadicSMemory.mli index 4b268777b..19143f87b 100644 --- a/Gillian-C2/lib/memory_model/MonadicSMemory.mli +++ b/Gillian-C2/lib/memory_model/MonadicSMemory.mli @@ -4,7 +4,7 @@ module Lift : sig open Gillian.Debugger.Utils val add_variables : - store:(string * vt) list -> + store:(Gil_syntax.Var.t * vt) list -> memory:t -> is_gil_file:'a -> get_new_scope_id:(unit -> int) -> diff --git a/Gillian-C2/lib/memory_model/SHeapTree.ml b/Gillian-C2/lib/memory_model/SHeapTree.ml index 16560cbce..4c0372fdd 100644 --- a/Gillian-C2/lib/memory_model/SHeapTree.ml +++ b/Gillian-C2/lib/memory_model/SHeapTree.ml @@ -112,8 +112,8 @@ module Range = struct l < x && x < h let split_at (l, h) x = ((l, x), (x, h)) - let lvars (a, b) = SS.union (Expr.lvars a) (Expr.lvars b) - let alocs (a, b) = SS.union (Expr.alocs a) (Expr.alocs b) + let lvars (a, b) = LVar.Set.union (Expr.lvars a) (Expr.lvars b) + let alocs (a, b) = ALoc.Set.union (Expr.alocs a) (Expr.alocs b) let substitution ~le_subst (a, b) = (le_subst a, le_subst b) end @@ -417,12 +417,12 @@ module Node = struct let lvars = function | MemVal { mem_val = Single sval; _ } -> SVal.lvars sval | MemVal { mem_val = Array sarr; _ } -> SVArr.lvars sarr - | _ -> SS.empty + | _ -> LVar.Set.empty let alocs = function | MemVal { mem_val = Single sval; _ } -> SVal.alocs sval | MemVal { mem_val = Array svarr; _ } -> SVArr.alocs svarr - | _ -> SS.empty + | _ -> ALoc.Set.empty let substitution ~sval_subst ~svarr_subst n = let smv = function @@ -987,20 +987,20 @@ module Tree = struct let span_lvars = Range.lvars span in let children_lvars = match children with - | Some (a, b) -> SS.union (lvars a) (lvars b) - | None -> SS.empty + | Some (a, b) -> LVar.Set.union (lvars a) (lvars b) + | None -> LVar.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + LVar.Set.union (LVar.Set.union node_lvars span_lvars) children_lvars let rec alocs { node; span; children; _ } = let node_lvars = Node.alocs node in let span_lvars = Range.alocs span in let children_lvars = match children with - | Some (a, b) -> SS.union (alocs a) (alocs b) - | None -> SS.empty + | Some (a, b) -> ALoc.Set.union (alocs a) (alocs b) + | None -> ALoc.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + ALoc.Set.union (ALoc.Set.union node_lvars span_lvars) children_lvars let rec assertions ~loc { node; span; children; _ } = let low, high = span in @@ -1098,18 +1098,18 @@ let is_empty t = let freed = Freed let lvars = function - | Freed -> SS.empty + | Freed -> LVar.Set.empty | Tree { bounds; root } -> - SS.union - (Option.fold ~none:SS.empty ~some:Range.lvars bounds) - (Option.fold ~none:SS.empty ~some:Tree.lvars root) + LVar.Set.union + (Option.fold ~none:LVar.Set.empty ~some:Range.lvars bounds) + (Option.fold ~none:LVar.Set.empty ~some:Tree.lvars root) let alocs = function - | Freed -> SS.empty + | Freed -> ALoc.Set.empty | Tree { bounds; root } -> - SS.union - (Option.fold ~none:SS.empty ~some:Range.alocs bounds) - (Option.fold ~none:SS.empty ~some:Tree.alocs root) + ALoc.Set.union + (Option.fold ~none:ALoc.Set.empty ~some:Range.alocs bounds) + (Option.fold ~none:ALoc.Set.empty ~some:Tree.alocs root) let get_root = function | Freed -> Error UseAfterFree @@ -1557,7 +1557,7 @@ module Lift = struct ~loc t : Variable.t = match t with - | Freed -> make_node ~name:loc ~value:"Freed" () + | Freed -> make_node ~name:(Id.str loc) ~value:"Freed" () | Tree { bounds; root } -> let bounds = match bounds with @@ -1572,5 +1572,6 @@ module Lift = struct | None -> make_node ~name:"Tree" ~value:"Not owned" () | Some root -> Tree.Lift.as_variable ~make_node root in - make_node ~name:loc ~value:"Allocated" ~children:[ bounds; root ] () + make_node ~name:(Id.str loc) ~value:"Allocated" + ~children:[ bounds; root ] () end diff --git a/Gillian-C2/lib/memory_model/SHeapTree.mli b/Gillian-C2/lib/memory_model/SHeapTree.mli index 40a91970c..60df9c1d9 100644 --- a/Gillian-C2/lib/memory_model/SHeapTree.mli +++ b/Gillian-C2/lib/memory_model/SHeapTree.mli @@ -34,8 +34,8 @@ val pp_full : t Fmt.t val empty : t val freed : t val is_empty : t -> bool -val lvars : t -> SS.t -val alocs : t -> SS.t +val lvars : t -> LVar.Set.t +val alocs : t -> ALoc.Set.t val load_bounds : t -> Range.t or_error val cons_bounds : t -> (Range.t * t) or_error val prod_bounds : t -> Range.t -> t or_error @@ -74,7 +74,7 @@ val weak_valid_pointer : t -> Expr.t -> bool d_or_error [dst_tree] after modification *) val move : t -> Expr.t -> t -> Expr.t -> Expr.t -> t d_or_error -val assertions : loc:string -> t -> Asrt.t +val assertions : loc:Id.any_loc Id.t -> t -> Asrt.t val substitution : le_subst:(Expr.t -> Expr.t) -> @@ -95,7 +95,7 @@ module Lift : sig ?children:Variable.t list -> unit -> Variable.t) -> - loc:string -> + loc:Id.any_loc Id.t -> t -> Variable.t end diff --git a/Gillian-C2/lib/memory_model/SVal.mli b/Gillian-C2/lib/memory_model/SVal.mli index ee85c6e64..0ca19e00b 100644 --- a/Gillian-C2/lib/memory_model/SVal.mli +++ b/Gillian-C2/lib/memory_model/SVal.mli @@ -6,8 +6,8 @@ module SVal : sig val make : chunk:Chunk.t -> value:Gil_syntax.Expr.t -> t val pp : Format.formatter -> t -> unit - val alocs : t -> SS.t - val lvars : t -> SS.t + val alocs : t -> ALoc.Set.t + val lvars : t -> LVar.Set.t val sure_is_zero : t -> bool val substitution : le_subst:(Expr.t -> Expr.t) -> t -> t val syntactic_equal : t -> t -> bool @@ -24,8 +24,8 @@ module SVArray : sig type t [@@deriving yojson] val make : chunk:Chunk.t -> values:Expr.t -> t - val alocs : t -> SS.t - val lvars : t -> SS.t + val alocs : t -> ALoc.Set.t + val lvars : t -> LVar.Set.t val reduce : t -> t Monadic.Delayed.t val pp : Format.formatter -> t -> unit val sure_is_all_zeros : t -> bool diff --git a/Gillian-JS/lib/Compiler/JS2JSIL_Compiler.ml b/Gillian-JS/lib/Compiler/JS2JSIL_Compiler.ml index 2e2714cfd..774f82a43 100644 --- a/Gillian-JS/lib/Compiler/JS2JSIL_Compiler.ml +++ b/Gillian-JS/lib/Compiler/JS2JSIL_Compiler.ml @@ -47,7 +47,7 @@ let fresh_switch_labels () = let default_lab = fresh_default_label () in let end_switch = fresh_end_switch_label () in let fresh_end_case_label, _ = - fresh_sth ("end_case_" ^ string_of_int !number_of_switches ^ "_") + fresh_sth_str ("end_case_" ^ string_of_int !number_of_switches ^ "_") in number_of_switches := !number_of_switches + 1; (b_cases_lab, default_lab, end_switch, fresh_end_case_label) @@ -139,10 +139,7 @@ let rec get_continue_lab loop_list lab = | Some lab_c -> lab_c else get_continue_lab rest lab)) -let filter_cur_jumps - (jumps : (string option * string * string) list) - loop_lab - include_no_lab = +let filter_cur_jumps jumps loop_lab include_no_lab = let rec filter_cur_jumps_iter jumps inner_jumps outer_jumps = match jumps with | [] -> (List.rev inner_jumps, List.rev outer_jumps) @@ -764,7 +761,7 @@ let annotate_cmds_top_level metadata cmds = x_is - the list of variables that may hold error values *) let rec translate_expr tr_ctx e : - (Annot.Basic.t * string option * LabCmd.t) list * Expr.t * string list = + (Annot.Basic.t * string option * LabCmd.t) list * Expr.t * Var.t list = let f = translate_expr tr_ctx in let find_var_er_index v : int option = @@ -830,7 +827,7 @@ let rec translate_expr tr_ctx e : LCall ( x_sf, lit_str dynamicScoper, - [ PVar tr_ctx.tr_sc_var; lit_str x ], + [ PVar tr_ctx.tr_sc_var; lit_str_v x ], None, None ) in @@ -843,7 +840,10 @@ let rec translate_expr tr_ctx e : ( x_ref, EList [ - lit_refv; PVar x_sf; lit_str x; Lit (Bool tr_ctx.tr_strictness); + lit_refv; + PVar x_sf; + lit_str_v x; + Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -922,7 +922,7 @@ let rec translate_expr tr_ctx e : LCall ( x_sf, lit_str dynamicScoper, - [ PVar tr_ctx.tr_sc_var; lit_str x ], + [ PVar tr_ctx.tr_sc_var; lit_str_v x ], None, None ) in @@ -935,7 +935,10 @@ let rec translate_expr tr_ctx e : ( x_ref, EList [ - lit_refv; PVar x_sf; lit_str x; Lit (Bool tr_ctx.tr_strictness); + lit_refv; + PVar x_sf; + lit_str_v x; + Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -1100,6 +1103,7 @@ let rec translate_expr tr_ctx e : ] in let cmds = annotate_cmds cmds in cmds, PVar x_r, [] in *) + let v = Var.of_string v in let index = find_var_er_index v in match index with | (Some _ | None) @@ -1121,7 +1125,7 @@ let rec translate_expr tr_ctx e : LCall ( x_1, lit_str dynamicScoper, - [ PVar tr_ctx.tr_sc_var; lit_str v ], + [ PVar tr_ctx.tr_sc_var; lit_str_v v ], None, None ) in @@ -1135,7 +1139,7 @@ let rec translate_expr tr_ctx e : [ lit_refv; PVar x_1; - lit_str v; + lit_str_v v; Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -1156,7 +1160,7 @@ let rec translate_expr tr_ctx e : LCall ( x_1, Lit (String hasPropertyName), - [ Lit (Loc locGlobName); Lit (String v) ], + [ Lit (Loc locGlobName); lit_str_v v ], Some tr_ctx.tr_err_lab, None ) in @@ -1179,7 +1183,7 @@ let rec translate_expr tr_ctx e : [ lit_refv; lit_loc locGlobName; - lit_str v; + lit_str_v v; Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -1194,7 +1198,7 @@ let rec translate_expr tr_ctx e : [ lit_refv; Lit Undefined; - lit_str v; + lit_str_v v; Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -2061,7 +2065,12 @@ let rec translate_expr tr_ctx e : List.fold_left (fun (cmds, errs) x -> let new_cmds, x_expr, new_errs = - f { e with JS_Parser.Syntax.exp_stx = JS_Parser.Syntax.Var x } + f + { + e with + JS_Parser.Syntax.exp_stx = + JS_Parser.Syntax.Var (Var.str x); + } in let x_v, cmd_gv_x, errs_x_v = @@ -2070,7 +2079,7 @@ let rec translate_expr tr_ctx e : SSubst.put subst (PVar x) (PVar x_v); ( cmds @ new_cmds @ [ annotate_cmd cmd_gv_x None ], errs @ new_errs @ errs_x_v )) - ([], []) (SS.elements xs) + ([], []) (Var.Set.elements xs) in let le = SSubst.subst_in_expr subst ~partial:true e' in @@ -2099,7 +2108,12 @@ let rec translate_expr tr_ctx e : List.fold_left (fun (cmds, errs) x -> let new_cmds, x_expr, new_errs = - f { e with JS_Parser.Syntax.exp_stx = JS_Parser.Syntax.Var x } + f + { + e with + JS_Parser.Syntax.exp_stx = + JS_Parser.Syntax.Var (Var.str x); + } in let x_v, cmd_gv_x, errs_x_v = make_get_value_call x_expr tr_ctx.tr_err_lab @@ -2107,7 +2121,7 @@ let rec translate_expr tr_ctx e : SSubst.put subst (PVar x) (PVar x_v); ( cmds @ new_cmds @ [ annotate_cmd cmd_gv_x None ], errs @ new_errs @ errs_x_v )) - ([], []) (SS.elements xs) + ([], []) (Var.Set.elements xs) in let le = SSubst.subst_in_expr subst ~partial:true e' in @@ -2125,8 +2139,8 @@ let rec translate_expr tr_ctx e : | [] -> () | _ -> raise (Failure "Invalid symbolic") in - let x_v = fresh_var () ^ "_v" in - let cmd1 = (metadata, None, LLogic (LCmd.FreshSVar x_v)) in + let x_v = Var.of_string @@ (Var.str @@ fresh_var ()) ^ "_v" in + let cmd1 = (metadata, None, LLogic (LCmd.FreshSVar (Var.str x_v))) in let x_v = PVar x_v in let cmd2 = ( metadata, @@ -2156,8 +2170,8 @@ let rec translate_expr tr_ctx e : | [] -> () | _ -> raise (Failure "Invalid symb_number") in - let x_v = fresh_var () ^ "_v" in - let cmd1 = (metadata, None, LLogic (FreshSVar x_v)) in + let x_v = Var.of_string @@ (Var.str @@ fresh_var ()) ^ "_v" in + let cmd1 = (metadata, None, LLogic (FreshSVar (Var.str x_v))) in let x_v = PVar x_v in let cmd2 = (metadata, None, LLogic (LCmd.AssumeType (x_v, Type.NumberType))) @@ -2171,8 +2185,8 @@ let rec translate_expr tr_ctx e : | [] -> () | _ -> raise (Failure "Invalid symb_string") in - let x_v = fresh_var () ^ "_v" in - let cmd1 = (metadata, None, LLogic (FreshSVar x_v)) in + let x_v = Var.of_string @@ (Var.str @@ fresh_var ()) ^ "_v" in + let cmd1 = (metadata, None, LLogic (FreshSVar (Var.str x_v))) in let x_v = PVar x_v in let cmd2 = (metadata, None, LLogic (LCmd.AssumeType (x_v, Type.StringType))) @@ -2186,8 +2200,8 @@ let rec translate_expr tr_ctx e : | [] -> () | _ -> raise (Failure "Invalid symb_bool") in - let x_v = fresh_var () ^ "_v" in - let cmd1 = (metadata, None, LLogic (FreshSVar x_v)) in + let x_v = Var.of_string @@ (Var.str @@ fresh_var ()) ^ "_v" in + let cmd1 = (metadata, None, LLogic (FreshSVar (Var.str x_v))) in let x_v = PVar x_v in let cmd2 = (metadata, None, LLogic (LCmd.AssumeType (x_v, Type.BooleanType))) @@ -2372,7 +2386,11 @@ let rec translate_expr tr_ctx e : :: Lit (Bool tr_ctx.tr_strictness) :: x_args_gv in let cmd_execute_eval = - LECall (x_ecall, PVar "ExecuteEval", proc_args, Some tr_ctx.tr_err_lab) + LECall + ( x_ecall, + PVar (Var.of_string "ExecuteEval"), + proc_args, + Some tr_ctx.tr_err_lab ) in (* x_fscope := [x_f_val, "@scope"]; *) @@ -4060,6 +4078,7 @@ let rec translate_expr tr_ctx e : (Failure "no empty variable declaration lists in expression contexts") | [ (v, eo) ] -> ( + let v = Var.of_string v in match eo with | None -> let x, new_cmds, new_errs = compile_var_dec_without_exp v in @@ -4068,6 +4087,7 @@ let rec translate_expr tr_ctx e : let new_cmds, x, new_errs = compile_var_dec v e in (x, cmds @ new_cmds, errs @ new_errs)) | (v, eo) :: rest_decs -> ( + let v = Var.of_string v in match eo with | None -> loop rest_decs cmds errs | Some e -> @@ -4150,7 +4170,7 @@ and translate_statement tr_ctx e = LCall ( x_sf, lit_str dynamicScoper, - [ PVar tr_ctx.tr_sc_var; lit_str x ], + [ PVar tr_ctx.tr_sc_var; lit_str_v x ], Some tr_ctx.tr_err_lab, None ) in @@ -4163,7 +4183,10 @@ and translate_statement tr_ctx e = ( x_ref, EList [ - lit_refv; PVar x_sf; lit_str x; Lit (Bool tr_ctx.tr_strictness); + lit_refv; + PVar x_sf; + lit_str_v x; + Lit (Bool tr_ctx.tr_strictness); ] )) in @@ -5092,6 +5115,7 @@ and translate_statement tr_ctx e = match eo with | None -> loop rest_decs cmds errs | Some e -> + let v = Var.of_string v in let new_cmds, _, new_errs = compile_var_dec v e in loop rest_decs (cmds @ new_cmds) (errs @ new_errs)) in @@ -6426,7 +6450,7 @@ and translate_statement tr_ctx e = (* x_r := PHI(breaks_ab, x_ab, breaks_def, breaks_b, x_b) *) let x_r = fresh_var () in - let phi_args : string list = + let phi_args = cur_breaks_ab @ [ x_old_b ] @ cur_breaks_def @ cur_breaks_b @ [ x_b ] in let phi_args = List.map (fun x -> PVar x) phi_args in @@ -6648,7 +6672,7 @@ let make_final_cmd vars final_lab final_var origin_loc = in (Annot.Basic.make_basic ~origin_loc (), Some final_lab, cmd_final) -let translate_fun_decls (top_level : bool) (sc_var : string) (cur_index : int) e +let translate_fun_decls (top_level : bool) (sc_var : Var.t) (cur_index : int) e = let f_decls = func_decls_in_exp e in let hoisted_fdecls = @@ -6713,7 +6737,7 @@ let generate_main e strictness spec : EProc.t = (LBasic (Mutation ( Lit (Loc locGlobName), - Lit (String global_v), + lit_str_v global_v, Lit (LList [ @@ -6750,7 +6774,7 @@ let generate_main e strictness spec : EProc.t = (* x_ret := x_e *) let ret_ass = - annotate_cmd (LBasic (Assignment (Names.return_variable, x_e))) None + annotate_cmd (LBasic (Assignment (Id.return_variable, x_e))) None in let x_ignore = fresh_var () in @@ -6789,7 +6813,7 @@ let generate_main e strictness spec : EProc.t = let lab_ret_cmd = annotate_cmd LReturnNormal (Some ctx.tr_ret_lab) in let cmd_err_phi_node = - make_final_cmd errs ctx.tr_err_lab Names.return_variable origin_loc + make_final_cmd errs ctx.tr_err_lab Id.return_variable origin_loc in let lab_err_cmd = annotate_cmd LReturnError None in let global_err_asrt = annotate_cmd (LLogic (LCmd.Assert Expr.false_)) None in @@ -6848,7 +6872,7 @@ let generate_proc_eval new_fid ?use_cc e strictness vis_fid : EProc.t = List.map (fun decl_var -> let cmd = - LBasic (Mutation (PVar x_er, Lit (String decl_var), Lit Undefined)) + LBasic (Mutation (PVar x_er, lit_str_v decl_var, Lit Undefined)) in annotate_cmd cmd None) new_fid_vars @@ -6911,9 +6935,7 @@ let generate_proc_eval new_fid ?use_cc e strictness vis_fid : EProc.t = (* x_ret := x_e *) let ret_ass = - annotate_cmd - (LBasic (Assignment (Names.return_variable, PVar x_final))) - None + annotate_cmd (LBasic (Assignment (Id.return_variable, PVar x_final))) None in (* lab_ret: skip *) @@ -6921,7 +6943,7 @@ let generate_proc_eval new_fid ?use_cc e strictness vis_fid : EProc.t = (* lab_err: x_error := PHI(errs, x_fake_ret) *) let cmd_error_phi = - make_final_cmd (errs @ errs_xe_v) ctx.tr_err_lab Names.return_variable + make_final_cmd (errs @ errs_xe_v) ctx.tr_err_lab Id.return_variable origin_loc in let lab_err_cmd = annotate_cmd LReturnError None in @@ -6999,7 +7021,8 @@ let generate_proc ?use_cc e fid params strictness vis_fid spec : EProc.t = List.map (fun param -> let cmd = - LBasic (Mutation (PVar var_er, Lit (String param), PVar param)) + LBasic + (Mutation (PVar var_er, Lit (String (Var.str param)), PVar param)) in annotate_cmd cmd None) params @@ -7010,7 +7033,7 @@ let generate_proc ?use_cc e fid params strictness vis_fid spec : EProc.t = List.map (fun decl_var -> let cmd = - LBasic (Mutation (PVar var_er, Lit (String decl_var), Lit Undefined)) + LBasic (Mutation (PVar var_er, lit_str_v decl_var, Lit Undefined)) in annotate_cmd cmd None) (var_decls e) @@ -7089,7 +7112,7 @@ let generate_proc ?use_cc e fid params strictness vis_fid spec : EProc.t = (* pre_lab_ret: x_return := PHI(...) *) let cmd_return_phi = - make_final_cmd rets new_ctx.tr_ret_lab Names.return_variable origin_loc + make_final_cmd rets new_ctx.tr_ret_lab Id.return_variable origin_loc in let x_ignore = fresh_var () in @@ -7129,7 +7152,7 @@ let generate_proc ?use_cc e fid params strictness vis_fid spec : EProc.t = (LCall ( x_ignore, Lit (String JS2JSIL_Helpers.deleteErrorObjects), - [ PVar Names.return_variable; PVar var_te; PVar var_se; PVar var_re ], + [ PVar Id.return_variable; PVar var_te; PVar var_se; PVar var_re ], None, None )) None @@ -7141,7 +7164,7 @@ let generate_proc ?use_cc e fid params strictness vis_fid spec : EProc.t = let cmds_restore_er_ret = annotate_cmds cmds_restore_er_ret in *) let errs = errs in let cmd_error_phi = - make_final_cmd errs new_ctx.tr_err_lab Names.return_variable origin_loc + make_final_cmd errs new_ctx.tr_err_lab Id.return_variable origin_loc in let cmd_err_final = annotate_cmd LReturnError None in @@ -7196,9 +7219,9 @@ let js2jsil_eval raise (Failure msg) in let f_params = - match f_params with - | "x__scope" :: "x__this" :: rest -> rest - | "x__scope" :: rest -> rest + match List.map Var.str f_params with + | "x__scope" :: "x__this" :: rest -> List.map Var.of_string rest + | "x__scope" :: rest -> List.map Var.of_string rest | _ -> f_params in generate_proc f_body f_id f_params f_strictness vislist None @@ -7248,9 +7271,9 @@ let js2jsil_function_constructor_prop raise (Failure msg) in let f_params = - match f_params with - | "x__scope" :: "x__this" :: rest -> rest - | "x__scope" :: rest -> rest + match List.map Var.str f_params with + | "x__scope" :: "x__this" :: _ -> List.tl @@ List.tl f_params + | "x__scope" :: _ -> List.tl f_params | _ -> f_params in generate_proc f_body f_id f_params f_strictness vis_fid None diff --git a/Gillian-JS/lib/Compiler/JS2JSIL_Helpers.ml b/Gillian-JS/lib/Compiler/JS2JSIL_Helpers.ml index b864190be..d39a765b3 100644 --- a/Gillian-JS/lib/Compiler/JS2JSIL_Helpers.ml +++ b/Gillian-JS/lib/Compiler/JS2JSIL_Helpers.ml @@ -106,13 +106,13 @@ let _extensiblePropName = "@extensible" let _internalProtoFieldName = "@proto" let _erFlagPropName = "@er" let locGlobName = Jslogic.JSLogicCommon.locGlobName -let locObjPrototype = "$lobj_proto" -let locFunObjPrototype = "$lfun_proto" -let locArrPrototype = "$larr_proto" -let locTErrPrototype = "$lterr_proto" -let locSErrPrototype = "$lserr_proto" -let locRErrPrototype = "$lrerr_proto" -let locErrPrototype = "$lerr_proto" +let locObjPrototype = Loc.of_string "$lobj_proto" +let locFunObjPrototype = Loc.of_string "$lfun_proto" +let locArrPrototype = Loc.of_string "$larr_proto" +let locTErrPrototype = Loc.of_string "$lterr_proto" +let locSErrPrototype = Loc.of_string "$lserr_proto" +let locRErrPrototype = Loc.of_string "$lrerr_proto" +let locErrPrototype = Loc.of_string "$lerr_proto" let toBooleanName = "i__toBoolean" (* 9.2 *) @@ -190,14 +190,14 @@ let deleteErrorObjects = "i__deleteErrors" let var_this = Jslogic.JSLogicCommon.var_this let var_scope = Jslogic.JSLogicCommon.var_scope -let var_scope_final = "x__scope_f" +let var_scope_final = Var.of_string "x__scope_f" let var_se = Jslogic.JSLogicCommon.var_se let var_te = Jslogic.JSLogicCommon.var_te -let var_re = "x__re" -let var_args = "x__args" -let var_er = "x__er" -let var_er_metadata = "x__er_m" -let var_sc_first = "x__sc_fst" +let var_re = Var.of_string "x__re" +let var_args = Var.of_string "x__args" +let var_er = Var.of_string "x__er" +let var_er_metadata = Var.of_string "x__er_m" +let var_sc_first = Var.of_string "x__sc_fst" let js2jsil_spec_vars = [ var_this; var_scope; var_scope_final; var_se; var_te; var_er ] @@ -212,7 +212,7 @@ let reserved_vars = var_er; var_er_metadata; var_sc_first; - Names.return_variable; + Id.return_variable; ] let main_fid = !Config.entry_point @@ -224,6 +224,7 @@ let pi_predicate_name = "Pi" let lit_num n = Expr.Lit (Num n) let lit_str s = Expr.Lit (String s) +let lit_str_v s = Expr.Lit (String (Var.str s)) let lit_loc l = Expr.Lit (Loc l) let lit_typ t = Expr.Lit (Type t) let lit_refv = lit_str "v" @@ -233,9 +234,22 @@ let base r = Expr.BinOp (r, LstNth, lit_num 1.) let field r = Expr.BinOp (r, LstNth, lit_num 2.) (** - * Fresh identifiers + * Fresh identifiers (Var.t) *) -let fresh_sth (name : string) : (unit -> string) * (unit -> unit) = +let fresh_sth (name : string) : (unit -> Var.t) * (unit -> unit) = + let counter = ref 0 in + let f () = + let v = name ^ string_of_int !counter in + counter := !counter + 1; + Var.of_string v + in + let r () = counter := 0 in + (f, r) + +(** + * Fresh identifiers (string) + *) +let fresh_sth_str (name : string) : (unit -> string) * (unit -> unit) = let counter = ref 0 in let f () = let v = name ^ string_of_int !counter in @@ -258,30 +272,32 @@ let fresh_desc_var, reset_desc_var = fresh_sth "x_desc_" let fresh_body_var, reset_body_var = fresh_sth "x_body_" let fresh_fscope_var, reset_fscope_var = fresh_sth "x_fscope_" let fresh_xfoundb_var, reset_xfoundb_var = fresh_sth "x_found_b_" -let fresh_label, reset_label = fresh_sth "lab_" -let fresh_next_label, reset_next_label = fresh_sth "next_" -let fresh_then_label, reset_then_label = fresh_sth "then_" -let fresh_else_label, reset_else_label = fresh_sth "else_" -let fresh_endif_label, reset_endif_label = fresh_sth "fi_" -let fresh_end_label, reset_end_label = fresh_sth "end_" -let fresh_end_switch_label, reset_end_switch_label = fresh_sth "end_switch_" -let fresh_end_case_label, reset_end_case_label = fresh_sth "end_case_" -let fresh_default_label, reset_default_label = fresh_sth "default_" -let fresh_b_cases_label, reset_b_cases_label = fresh_sth "b_cases_" -let fresh_logical_variable, reset_logical_variable = fresh_sth "#x" -let fresh_break_label, reset_break_label = fresh_sth "break_" -let fresh_loop_head_label, reset_loop_head_label = fresh_sth "loop_h_" -let fresh_loop_cont_label, reset_loop_cont_label = fresh_sth "loop_c_" -let fresh_loop_guard_label, reset_loop_guard_label = fresh_sth "loop_g_" -let fresh_loop_body_label, reset_loop_body_label = fresh_sth "loop_b_" -let fresh_loop_end_label, reset_loop_end_label = fresh_sth "loop_e_" -let fresh_loop_identifier, reset_loop_identifier = fresh_sth "loop_id_" -let fresh_tcf_finally_label, reset_tcf_finally_label = fresh_sth "finally_" -let fresh_tcf_end_label, reset_tcf_end_label = fresh_sth "end_tcf_" -let fresh_tcf_err_try_label, reset_tcf_err_try_label = fresh_sth "err_tcf_t_" +let fresh_label, reset_label = fresh_sth_str "lab_" +let fresh_next_label, reset_next_label = fresh_sth_str "next_" +let fresh_then_label, reset_then_label = fresh_sth_str "then_" +let fresh_else_label, reset_else_label = fresh_sth_str "else_" +let fresh_endif_label, reset_endif_label = fresh_sth_str "fi_" +let fresh_end_label, reset_end_label = fresh_sth_str "end_" +let fresh_end_switch_label, reset_end_switch_label = fresh_sth_str "end_switch_" +let fresh_end_case_label, reset_end_case_label = fresh_sth_str "end_case_" +let fresh_default_label, reset_default_label = fresh_sth_str "default_" +let fresh_b_cases_label, reset_b_cases_label = fresh_sth_str "b_cases_" +let fresh_logical_variable, reset_logical_variable = fresh_sth_str "#x" +let fresh_break_label, reset_break_label = fresh_sth_str "break_" +let fresh_loop_head_label, reset_loop_head_label = fresh_sth_str "loop_h_" +let fresh_loop_cont_label, reset_loop_cont_label = fresh_sth_str "loop_c_" +let fresh_loop_guard_label, reset_loop_guard_label = fresh_sth_str "loop_g_" +let fresh_loop_body_label, reset_loop_body_label = fresh_sth_str "loop_b_" +let fresh_loop_end_label, reset_loop_end_label = fresh_sth_str "loop_e_" +let fresh_loop_identifier, reset_loop_identifier = fresh_sth_str "loop_id_" +let fresh_tcf_finally_label, reset_tcf_finally_label = fresh_sth_str "finally_" +let fresh_tcf_end_label, reset_tcf_end_label = fresh_sth_str "end_tcf_" + +let fresh_tcf_err_try_label, reset_tcf_err_try_label = + fresh_sth_str "err_tcf_t_" let fresh_tcf_err_catch_label, reset_tcf_err_catch_label = - fresh_sth "err_tcf_c_" + fresh_sth_str "err_tcf_c_" let fresh_tcf_ret, reset_tcf_ret = fresh_sth "ret_tcf_" @@ -301,10 +317,10 @@ let fresh_tcf_vars () = let end_l = fresh_tcf_end_label () in let finally = fresh_tcf_finally_label () in let fresh_abnormal_finally, _ = - fresh_sth ("abnormal_finally_" ^ string_of_int !number_of_tcfs ^ "_") + fresh_sth_str ("abnormal_finally_" ^ string_of_int !number_of_tcfs ^ "_") in number_of_tcfs := !number_of_tcfs + 1; - let ret = fresh_tcf_ret () in + let ret = Var.str @@ fresh_tcf_ret () in (err1, err2, finally, end_l, fresh_abnormal_finally, ret) let fresh_name = @@ -329,48 +345,24 @@ let fresh_named_eval n : string = fresh_name ("___$eval___" ^ n ^ "_") let is_get_value_var x = match (x : Expr.t) with | PVar x_name -> - let x_name_len = String.length x_name in - if x_name_len > 2 && String.sub x_name (x_name_len - 2) 2 = "_v" then + let x_name_s = Var.str x_name in + let x_name_len = String.length x_name_s in + if x_name_len > 2 && String.sub x_name_s (x_name_len - 2) 2 = "_v" then Some x_name else None | _ -> None -let val_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_v" - | Lit _ -> fresh_var () ^ "_v" - | _ -> raise (Failure "val_var_of_var expects a variable or a literal") - -let number_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_n" - | Lit _ -> fresh_var () ^ "_n" - | _ -> raise (Failure "number_var_of_var expects a variable") - -let boolean_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_b" - | Lit _ -> fresh_var () ^ "_b" - | _ -> raise (Failure "boolean_var_of_var expects a variable") - -let primitive_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_p" - | Lit _ -> fresh_var () ^ "_p" - | _ -> raise (Failure "primitive_var_of_var expects a variable") - -let string_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_s" - | Lit _ -> fresh_var () ^ "_s" - | _ -> raise (Failure "string_var_of_var expects a variable") - -let i32_var_of_var x = - match (x : Expr.t) with - | PVar x_name -> x_name ^ "_i32" - | Lit _ -> fresh_var () ^ "_i32" - | _ -> raise (Failure "string_var_of_var expects a variable") - +let add_suffix suffix fn_name : Expr.t -> Var.t = function + | PVar x -> Var.of_string (Var.str x ^ suffix) + | Lit _ -> Var.of_string ((Var.str @@ fresh_var ()) ^ suffix) + | _ -> Fmt.failwith "%s expects a variable or a literal" fn_name + +let val_var_of_var = add_suffix "_v" "val_var_of_var" +let number_var_of_var = add_suffix "_n" "number_var_of_var" +let boolean_var_of_var = add_suffix "_b" "boolean_var_of_var" +let primitive_var_of_var = add_suffix "_p" "primitive_var_of_var" +let string_var_of_var = add_suffix "_s" "string_var_of_var" +let i32_var_of_var = add_suffix "_i32" "string_var_of_var" let fresh_err_label, reset_err_label = fresh_sth "err_" let fresh_ret_label, reset_ret_label = fresh_sth "ret_" @@ -379,7 +371,7 @@ type loop_list_type = (string option * string * string option * bool) list type translation_context = { tr_fid : string; tr_er_fid : string; - tr_sc_var : string; + tr_sc_var : Var.t; tr_vis_list : string list; tr_loop_list : loop_list_type; tr_loops : string list; diff --git a/Gillian-JS/lib/Compiler/JS2JSIL_Preprocessing.ml b/Gillian-JS/lib/Compiler/JS2JSIL_Preprocessing.ml index 1f0a3e844..f746e9b96 100644 --- a/Gillian-JS/lib/Compiler/JS2JSIL_Preprocessing.ml +++ b/Gillian-JS/lib/Compiler/JS2JSIL_Preprocessing.ml @@ -6,6 +6,7 @@ open JS2JSIL_Helpers open JS_Utils open Parsing module Flag = Gillian.Gil_syntax.Flag +module Var = Gillian.Gil_syntax.Var exception CannotHappen exception No_Codename @@ -21,7 +22,7 @@ let string_of_vtf_tbl (var_tbl : var_to_fid_tbl_type) = let var_tbl_str = Hashtbl.fold (fun v fid ac -> - let v_fid_pair_str = v ^ ": " ^ fid in + let v_fid_pair_str = Var.str v ^ ": " ^ fid in if ac = "" then v_fid_pair_str else ac ^ ", " ^ v_fid_pair_str) var_tbl "" in @@ -38,7 +39,7 @@ let string_of_cc_tbl (cc_tbl : cc_tbl_type) = let update_fun_tbl (fun_tbl : pre_fun_tbl_type) (f_id : string) - (f_args : string list) + (f_args : Var.t list) (f_body : JS_Parser.Syntax.exp option) (f_strictness : bool) (annotations : JS_Parser.Syntax.annotation list) @@ -52,7 +53,7 @@ let update_cc_tbl (cc_tbl : cc_tbl_type) (f_parent_id : string) (f_id : string) - (f_vars : string list) = + (f_vars : Var.t list) = let f_parent_var_table = get_scope_table cc_tbl f_parent_id in let new_f_tbl = Hashtbl.create 1 in Hashtbl.iter @@ -66,7 +67,7 @@ let update_cc_tbl_single_var_er (cc_tbl : cc_tbl_type) (f_parent_id : string) (f_id : string) - (x : string) = + (x : Var.t) = let f_parent_var_table = try Hashtbl.find cc_tbl f_parent_id with _ -> @@ -205,6 +206,7 @@ let closure_clarification let cur_annot = e.JS_Parser.Syntax.exp_annot in match e.exp_stx with | FunctionExp (strictness, f_name, args, fb) -> ( + let args = List.map Var.of_string args in match f_name with | None -> let new_f_id = get_codename e in @@ -220,7 +222,8 @@ let closure_clarification let new_f_id = get_codename e in let new_f_id_outer = new_f_id ^ "_outer" in let _ = - update_cc_tbl_single_var_er cc_tbl f_id new_f_id_outer f_name + update_cc_tbl_single_var_er cc_tbl f_id new_f_id_outer + (Var.of_string f_name) in let new_f_tbl = update_cc_tbl cc_tbl new_f_id_outer new_f_id @@ -233,6 +236,7 @@ let closure_clarification (visited_funs @ [ new_f_id_outer; new_f_id ]); Some (new_f_id, visited_funs @ [ new_f_id_outer; new_f_id ])) | Function (strictness, _, args, fb) -> + let args = List.map Var.of_string args in let new_f_id = get_codename e in let new_f_tbl = update_cc_tbl cc_tbl f_id new_f_id (get_all_vars_f fb args) @@ -256,7 +260,9 @@ let closure_clarification let _ = f prev_state e1 in let _ = Option.map (f prev_state) e3 in let new_f_id = get_codename e in - let _ = update_cc_tbl_single_var_er cc_tbl f_id new_f_id x in + let _ = + update_cc_tbl_single_var_er cc_tbl f_id new_f_id (Var.of_string x) + in f (Some (new_f_id, visited_funs @ [ new_f_id ])) e2 | _ -> []) in @@ -394,7 +400,7 @@ let translate_lannots_in_exp (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (scope_var : string) + (scope_var : Var.t) (inside_stmt_compilation : bool) e = let is_e_expr = not (is_stmt e) in @@ -451,7 +457,7 @@ let translate_invariant_in_exp (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (sc_var : string) + (sc_var : Var.t) (e : JS_Parser.Syntax.exp) : (Asrt.t * string list) option = let invariant = List.filter @@ -481,7 +487,7 @@ let translate_single_func_specs (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (fun_args : string list) + (fun_args : Var.t list) (annotations : JS_Parser.Syntax.annotation list) (requires_flag : JS_Parser.Syntax.annotation_type) (ensures_normal_flag : JS_Parser.Syntax.annotation_type) @@ -731,6 +737,7 @@ let get_them_functions let cur_annot = e.JS_Parser.Syntax.exp_annot in match e.exp_stx with | FunctionExp (strictness, f_name, args, fb) -> ( + let args = List.map Var.of_string args in match f_name with | None -> let new_f_id = get_codename e in @@ -746,7 +753,8 @@ let get_them_functions let new_f_id = get_codename e in let new_f_id_outer = new_f_id ^ "_outer" in let _ = - update_cc_tbl_single_var_er cc_tbl f_id new_f_id_outer f_name + update_cc_tbl_single_var_er cc_tbl f_id new_f_id_outer + (Var.of_string f_name) in let new_f_tbl = update_cc_tbl cc_tbl new_f_id_outer new_f_id @@ -759,6 +767,7 @@ let get_them_functions (visited_funs @ [ new_f_id_outer; new_f_id ]); Some (new_f_id, visited_funs @ [ new_f_id_outer; new_f_id ])) | Function (strictness, _, args, fb) -> + let args = List.map Var.of_string args in let new_f_id = get_codename e in let new_f_tbl = update_cc_tbl cc_tbl f_id new_f_id (get_all_vars_f fb args) @@ -782,7 +791,9 @@ let get_them_functions let _ = f prev_state e1 in let _ = Option.map (f prev_state) e3 in let new_f_id = get_codename e in - let _ = update_cc_tbl_single_var_er cc_tbl f_id new_f_id x in + let _ = + update_cc_tbl_single_var_er cc_tbl f_id new_f_id (Var.of_string x) + in f (Some (new_f_id, visited_funs @ [ new_f_id ])) e2 | _ -> []) in @@ -794,7 +805,7 @@ let preprocess_eval (strictness : bool) (e : JS_Parser.Syntax.exp) (fid_parent : string) - (params : string list) = + (params : Var.t list) = (* let offset_converter x = 0 in *) let fid = if List.length params > 0 then fresh_anonymous () diff --git a/Gillian-JS/lib/Compiler/JSIL2GIL.ml b/Gillian-JS/lib/Compiler/JSIL2GIL.ml index 31ccae3ce..772e44911 100644 --- a/Gillian-JS/lib/Compiler/JSIL2GIL.ml +++ b/Gillian-JS/lib/Compiler/JSIL2GIL.ml @@ -14,6 +14,9 @@ module GBiSpec = Gil.BiSpec module GCmd = Gil.Cmd module Expr = Gil.Expr module Annot = Gil.Annot +module Var = Gil.Var +module LVar = Gil.LVar +module Id = Gil.Id (** * Fresh identifiers @@ -31,6 +34,11 @@ let fresh_sth (name : string) : (unit -> string) * (unit -> unit) = let fresh_then, reset_then = fresh_sth "glab_then_" let fresh_else, reset_else = fresh_sth "glab_else_" let fresh_var, reset_var = fresh_sth "gvar_aux_" +let fresh_var () = Var.of_string @@ fresh_var () + +let map_bindings = + Option.map (fun (info_l, info_r) -> + (info_l, List.map (fun (x, t) -> (LVar.of_string x, t)) info_r)) let resource_error args = if Utils.Exec_mode.is_biabduction_exec !Config.current_exec_mode then @@ -91,12 +99,28 @@ let rec jsil2gil_asrt (a : Asrt.t) : GAsrt.t = let jsil2gil_slcmd (slcmd : SLCmd.t) : GSLCmd.t = match slcmd with - | Fold (pn, es, info) -> Fold (pn, List.map jsil2gil_expr es, info) - | Unfold (pn, es, info, b) -> Unfold (pn, List.map jsil2gil_expr es, info, b) + | Fold (pn, es, info) -> + Fold (pn, List.map jsil2gil_expr es, map_bindings info) + | Unfold (pn, es, info, b) -> + Unfold + ( pn, + List.map jsil2gil_expr es, + Option.map + (List.map (fun (l, r) -> (LVar.of_string l, LVar.of_string r))) + info, + b ) | GUnfold pn -> GUnfold pn - | ApplyLem (x, es, xs) -> ApplyLem (x, List.map jsil2gil_expr es, xs) - | SepAssert (a, xs) -> SepAssert (jsil2gil_asrt a, xs) - | Invariant (a, xs) -> Invariant (jsil2gil_asrt a, xs) + | ApplyLem (x, es, xs) -> + ApplyLem + ( x, + List.map jsil2gil_expr es, + (List.map Var.of_string xs :> Id.any_var Id.t list) ) + | SepAssert (a, xs) -> + SepAssert + (jsil2gil_asrt a, (List.map Var.of_string xs :> Id.any_var Id.t list)) + | Invariant (a, xs) -> + Invariant + (jsil2gil_asrt a, (List.map Var.of_string xs :> Id.any_var Id.t list)) let rec jsil2gil_lcmd (lcmd : LCmd.t) : GLCmd.t = let f = jsil2gil_lcmd in @@ -109,12 +133,14 @@ let rec jsil2gil_lcmd (lcmd : LCmd.t) : GLCmd.t = | Assert f -> Assert (fe f) | Assume f -> Assume (fe f) | AssumeType (x, t) -> AssumeType (fe x, t) - | FreshSVar x -> FreshSVar x + | FreshSVar x -> FreshSVar (Var.of_string x) | SL slcmd -> SL (jsil2gil_slcmd slcmd) let jsil2gil_sspec (sspec : Spec.st) : GSpec.st = let ss_label = - Option.map (fun (l, vl) -> (l, Containers.SS.elements vl)) sspec.label + Option.map + (fun (l, vl) -> (l, Containers.SS.elements vl |> List.map LVar.of_string)) + sspec.label in { ss_pre = jsil2gil_asrt sspec.pre; @@ -143,7 +169,7 @@ let jsil2gil_lemma (lemma : Lemma.t) : GLemma.t = lemma_source_path = None; lemma_internal = false; (* TODO (Alexis): Set depending on module of lemma *) - lemma_params = lemma.params; + lemma_params = List.map Var.of_string lemma.params; lemma_specs = [ { @@ -154,7 +180,7 @@ let jsil2gil_lemma (lemma : Lemma.t) : GLemma.t = ]; lemma_proof = Option.map (List.map jsil2gil_lcmd) lemma.proof; lemma_variant = Option.map jsil2gil_expr lemma.variant; - lemma_existentials = lemma.existentials; + lemma_existentials = List.map LVar.of_string lemma.existentials; } let jsil2gil_pred (pred : Pred.t) : GPred.t = @@ -167,7 +193,11 @@ let jsil2gil_pred (pred : Pred.t) : GPred.t = pred_params = pred.params; pred_ins = pred.ins; pred_definitions = - List.map (fun (info, asrt) -> (info, jsil2gil_asrt asrt)) pred.definitions; + List.map + (fun (info, asrt) -> + ( Option.map (fun (l, r) -> (l, List.map LVar.of_string r)) info, + jsil2gil_asrt asrt )) + pred.definitions; pred_facts = List.map jsil2gil_expr pred.facts; pred_guard = None; (* TODO: Support for predicates with tokens *) @@ -180,7 +210,7 @@ let jsil2gil_pred (pred : Pred.t) : GPred.t = let jsil2gil_macro (macro : Macro.t) : GMacro.t = { macro_name = macro.name; - macro_params = macro.params; + macro_params = List.map Var.of_string macro.params; macro_definition = List.map jsil2gil_lcmd macro.definition; } @@ -440,7 +470,7 @@ let jsil2core (lab : string option) (cmd : LabCmd.t) : | LGoto j -> [ (lab, GCmd.Goto j) ] | LGuardedGoto (e, j, k) -> [ (lab, GCmd.GuardedGoto (fe e, j, k)) ] | LCall (x, e, es, j, subst) -> - [ (lab, GCmd.Call (x, fe e, List.map fe es, j, subst)) ] + [ (lab, GCmd.Call (x, fe e, List.map fe es, j, map_bindings subst)) ] | LECall (x, e, es, j) -> [ (lab, GCmd.ECall (x, fe e, List.map fe es, j)) ] | LApply (x, e, j) -> [ (lab, GCmd.Apply (x, fe e, j)) ] | LArguments x -> [ (lab, GCmd.Arguments x) ] diff --git a/Gillian-JS/lib/Compiler/JSIL_PostParser.ml b/Gillian-JS/lib/Compiler/JSIL_PostParser.ml index f253e3f8a..2266f7385 100644 --- a/Gillian-JS/lib/Compiler/JSIL_PostParser.ml +++ b/Gillian-JS/lib/Compiler/JSIL_PostParser.ml @@ -1,6 +1,6 @@ -open Containers open Gillian.Gil_syntax open Jsil_syntax +open Jslogic.JSLogicCommon let heap_asrt_name = "initialHeapPostWeak" let pre_scope_prefix = "PreScope_" @@ -13,7 +13,7 @@ let pvar_counter = ref 0 let fresh_bi_lvar () = let v = "#bi_var_" ^ string_of_int !counter in counter := !counter + 1; - v + LVar.of_string v let populate () : unit = Hashtbl.replace reserved_methods "hasOwnProperty" "$lobj_proto"; @@ -75,7 +75,7 @@ let post_parse_eprog (eprog : EProg.t) : EProg.t = let expr_from_fid (fid : string) : Expr.t = if fid = JS2JSIL_Helpers.main_fid then Expr.Lit (Loc JS2JSIL_Helpers.locGlobName) - else Expr.LVar (Names.make_lvar_name fid) + else Expr.LVar (LVar.of_string @@ Names.make_lvar_name fid) let make_sc (vis_list : string list) : Expr.t list = let chopped_vis_list = @@ -117,20 +117,22 @@ let var_assertion (fid : string) (x : string) (x_val : Expr.t) : Asrt.t = let make_this_assertion () : Asrt.t = let var_this = JS2JSIL_Helpers.var_this in let f1 : Expr.t = - UnOp (Not, BinOp (UnOp (TypeOf, LVar "#this"), Equal, Lit (Type ListType))) + UnOp (Not, BinOp (UnOp (TypeOf, LVar this_lvar), Equal, Lit (Type ListType))) in let f2 : Expr.t = - UnOp (Not, BinOp (UnOp (TypeOf, LVar "#this"), Equal, Lit (Type NumberType))) + UnOp + (Not, BinOp (UnOp (TypeOf, LVar this_lvar), Equal, Lit (Type NumberType))) in let f3 : Expr.t = - UnOp (Not, BinOp (UnOp (TypeOf, LVar "#this"), Equal, Lit (Type StringType))) + UnOp + (Not, BinOp (UnOp (TypeOf, LVar this_lvar), Equal, Lit (Type StringType))) in let f4 : Expr.t = UnOp - (Not, BinOp (UnOp (TypeOf, LVar "#this"), Equal, Lit (Type BooleanType))) + (Not, BinOp (UnOp (TypeOf, LVar this_lvar), Equal, Lit (Type BooleanType))) in - let f5 : Expr.t = UnOp (Not, BinOp (LVar "#this", Equal, Lit Empty)) in - let f6 : Expr.t = BinOp (LVar "#this", Equal, PVar var_this) in + let f5 : Expr.t = UnOp (Not, BinOp (LVar this_lvar, Equal, Lit Empty)) in + let f6 : Expr.t = BinOp (LVar this_lvar, Equal, PVar var_this) in Asrt.Pure (Expr.conjunct [ f1; f2; f3; f4; f5; f6 ]) let scope_info_to_assertion @@ -138,7 +140,7 @@ let scope_info_to_assertion (cc_tbl : Jslogic.JSLogicCommon.cc_tbl_type) (vis_tbl : Jslogic.JSLogicCommon.vis_tbl_type) (fid : string) - (args : SS.t) : Asrt.t = + (args : Var.Set.t) : Asrt.t = let vis_list = Jslogic.JSLogicCommon.get_vis_list vis_tbl fid in let sc_bindings = match List.rev (List.map expr_from_fid vis_list) with @@ -166,11 +168,12 @@ let scope_info_to_assertion let a_vars = Hashtbl.fold (fun x fid' asrts -> + let x_s = Var.str x in let new_asrts = if fid' <> fid then let x_val = Expr.LVar (fresh_bi_lvar ()) in - let a_xval = var_assertion fid' x x_val in - let proc_x = EProg.get_proc eprog x in + let a_xval = var_assertion fid' x_s x_val in + let proc_x = EProg.get_proc eprog x_s in match proc_x with | None -> [ a_xval ] | Some proc_x -> @@ -192,8 +195,10 @@ let scope_info_to_assertion in let proto_asrt = Asrt.Pred ("JSObject", [ proc_x_prototype ]) in [ fun_obj_asrt; proto_asrt; a_xval ] - else if SS.mem x args then - let x_val : Expr.t = LVar (Names.make_svar_name x) in + else if Var.Set.mem x args then + let x_val : Expr.t = + LVar (LVar.of_string @@ Names.make_svar_name @@ Var.str x) + in let asrts_x = asrts_js_val x_val in Pure (BinOp (PVar x, Equal, x_val)) :: asrts_x else [] @@ -215,7 +220,7 @@ let create_pre_scope_pred (cc_tbl : Jslogic.JSLogicCommon.cc_tbl_type) (vis_tbl : Jslogic.JSLogicCommon.vis_tbl_type) (fid : string) - (_ : SS.t) : Pred.t = + (_ : Var.Set.t) : Pred.t = let vis_list = Jslogic.JSLogicCommon.get_vis_list vis_tbl fid in let sc_bindings = match List.rev (List.map expr_from_fid vis_list) with @@ -232,9 +237,10 @@ let create_pre_scope_pred Hashtbl.fold (fun x fid' (p_args, asrts) -> let x, new_asrts = + let x_s = Var.str x in if fid' <> fid then - let a_x = var_assertion fid' x (PVar x) in - let proc_x = EProg.get_proc eprog x in + let a_x = var_assertion fid' x_s (PVar x) in + let proc_x = EProg.get_proc eprog x_s in match proc_x with | None -> ([ x ], [ a_x ]) | Some proc_x -> @@ -285,13 +291,13 @@ let create_function_predicate (_ : Jslogic.JSLogicCommon.cc_tbl_type) (vis_tbl : Jslogic.JSLogicCommon.vis_tbl_type) (fid : string) - (fparams : string list) : Pred.t = + (fparams : Var.t list) : Pred.t = let pred_name = fid ^ "_FO_BI" in - let x = "x" in + let x = Var.of_string "x" in let fid_vis_list = Jslogic.JSLogicCommon.get_vis_list vis_tbl fid in let fid_x_sc = Expr.EList (make_sc fid_vis_list) in - let fid_prototype = Expr.LVar ("#" ^ fid ^ "_prototype") in + let fid_prototype = Expr.LVar (LVar.of_string @@ "#" ^ fid ^ "_prototype") in let fo_asrt = Asrt.Pred @@ -309,7 +315,7 @@ let create_function_predicate { name = pred_name; num_params = 1; - params = [ ("x", None) ]; + params = [ (Var.of_string "x", None) ]; ins = [ 0 ]; definitions = [ (None, Asrt.star [ fo_asrt; proto_asrt ]) ]; facts = []; @@ -336,7 +342,7 @@ let create_post_scope_pred (cc_tbl : Jslogic.JSLogicCommon.cc_tbl_type) (_ : Jslogic.JSLogicCommon.vis_tbl_type) (fid : string) - (_ : SS.t) : Pred.t = + (_ : Var.Set.t) : Pred.t = (* let args = SS.diff args (SS.of_list [ JS2JSIL_Helpers.var_this; JS2JSIL_Helpers.var_scope ]) in *) let vis_tbl = Jslogic.JSLogicCommon.get_scope_table cc_tbl fid in let all_params, out_params, in_params = @@ -354,7 +360,8 @@ let create_post_scope_pred let args_asrts = List.map (fun x -> - Asrt.PointsTo (PVar JS2JSIL_Helpers.var_er, Lit (String x), PVar x)) + Asrt.PointsTo + (PVar JS2JSIL_Helpers.var_er, Lit (String (Var.str x)), PVar x)) in_params in @@ -364,7 +371,7 @@ let create_post_scope_pred let mtdt_er_a : Asrt.t = MetaData (arg_er, lv_er_md) in (* empty_fields(er : -{ "arguments", in_params }-) *) let args_strs : Expr.t list = - List.map (fun x -> Expr.Lit (String x)) in_params + List.map (fun x -> Expr.Lit (String (Var.str x))) in_params in let ef_er_a : Asrt.t = EmptyFields (arg_er, ESet args_strs) in (* ((er, "arguments") -> arguments) *) @@ -425,7 +432,7 @@ let bi_post_parse_cmd (cmd : Annot.Basic.t * string option * LabCmd.t) : LabCmd.LCall ( x_r, Lit (String JS2JSIL_Helpers.isNativeErrorName), - [ PVar "ret" ], + [ PVar Id.return_variable ], None, None ) in @@ -470,7 +477,7 @@ let create_new_bispec else let pre = scope_info_to_assertion eprog cc_tbl vis_tbl eproc.name - (SS.of_list eproc.params) + (Var.Set.of_list eproc.params) in let bispec : BiSpec.t = { name = eproc.name; params = eproc.params; pre; normalised = false } @@ -488,11 +495,11 @@ let bi_post_parse_eprog let proc' = bi_post_parse_eproc eprog cc_tbl vis_tbl proc in let pre_scope_pred = create_pre_scope_pred eprog cc_tbl vis_tbl proc.name - (SS.of_list proc.params) + (Var.Set.of_list proc.params) in let post_scope_pred = create_post_scope_pred eprog cc_tbl vis_tbl proc.name - (SS.of_list proc.params) + (Var.Set.of_list proc.params) in let fun_pred = create_function_predicate cc_tbl vis_tbl proc.name proc.params diff --git a/Gillian-JS/lib/Compiler/JS_Utils.ml b/Gillian-JS/lib/Compiler/JS_Utils.ml index ea72b4608..60f473b7f 100644 --- a/Gillian-JS/lib/Compiler/JS_Utils.ml +++ b/Gillian-JS/lib/Compiler/JS_Utils.ml @@ -1,4 +1,5 @@ open JS_Parser.Syntax +module Var = Gil_syntax.Var (********************************************) (********************************************) @@ -470,7 +471,7 @@ let var_decls_inner exp = if not state then ac else match exp.exp_stx with - | VarDec vars -> List.map (fun (v, _) -> v) vars @ ac + | VarDec vars -> List.map (fun (v, _) -> Var.of_string v) vars @ ac | _ -> ac in let f_state exp state = @@ -481,7 +482,8 @@ let var_decls_inner exp = js_fold f_ac f_state true exp let var_decls exp = - List.sort_uniq Stdlib.compare (var_decls_inner exp) @ [ "arguments" ] + List.sort_uniq Stdlib.compare (var_decls_inner exp) + @ [ Var.of_string "arguments" ] let get_fun_decls exp = let f_ac exp _ _ ac = @@ -519,7 +521,7 @@ let get_all_vars_f f_body f_args = List.map (fun f -> match f.exp_stx with - | Function (_, Some name, _, _) -> name + | Function (_, Some name, _, _) -> Var.of_string name | _ -> raise (Failure diff --git a/Gillian-JS/lib/Debugging/JSLifter.ml b/Gillian-JS/lib/Debugging/JSLifter.ml index 81d704ebd..4a4f4cee4 100644 --- a/Gillian-JS/lib/Debugging/JSLifter.ml +++ b/Gillian-JS/lib/Debugging/JSLifter.ml @@ -24,7 +24,7 @@ struct store |> List.map (fun (var, value) : Variable.t -> let value = Fmt.to_to_string (Fmt.hbox Expr.pp) value in - Variable.create_leaf var value ()) + Variable.create_leaf (Var.str var) value ()) |> List.sort (fun (v : Variable.t) (w : Variable.t) -> Stdlib.compare v.name w.name) @@ -66,7 +66,10 @@ struct in node - let add_memory_vars smemory get_new_scope_id (variables : Variable.ts) = + let add_memory_vars + (smemory : memory) + get_new_scope_id + (variables : Variable.ts) = let sorted_locs_with_vals = Legacy_symbolic.sorted_locs_with_vals smemory in let value_nodes (loc, ((properties, domain), metadata)) : Variable.t = let () = ignore properties in @@ -85,23 +88,25 @@ struct let () = Hashtbl.replace variables loc_id [ properties; domain; metadata ] in - Variable.create_node loc loc_id () + Variable.create_node (Id.str loc) loc_id () in List.map value_nodes sorted_locs_with_vals let rec add_loc_vars - (loc : string) + (loc : Id.any_loc Id.t) smemory get_new_scope_id (variables : Variable.ts) - (loc_to_scope_id : (string, int) Hashtbl.t) : unit = + (loc_to_scope_id : (Id.any_loc Id.t, int) Hashtbl.t) : unit = let rec add_lit_vars name lit : Variable.t = match lit with | Literal.Loc loc -> let () = - add_loc_vars loc smemory get_new_scope_id variables loc_to_scope_id + add_loc_vars + (loc :> Id.any_loc Id.t) + smemory get_new_scope_id variables loc_to_scope_id in - let id = Hashtbl.find loc_to_scope_id loc in + let id = Hashtbl.find loc_to_scope_id (loc :> Id.any_loc Id.t) in Variable.create_node name id () | LList lst -> let nodes = @@ -119,9 +124,11 @@ struct match expr with | Expr.ALoc loc -> let () = - add_loc_vars loc smemory get_new_scope_id variables loc_to_scope_id + add_loc_vars + (loc :> Id.any_loc Id.t) + smemory get_new_scope_id variables loc_to_scope_id in - let id = Hashtbl.find loc_to_scope_id loc in + let id = Hashtbl.find loc_to_scope_id (loc :> Id.any_loc Id.t) in Variable.create_node name id () (* TODO: The below causes a stack overflow error in large pieces of code, so they is probably a more efficient way to write this algorithm @@ -213,10 +220,14 @@ struct match metadata with | Expr.ALoc child_loc -> let () = - add_loc_vars child_loc smemory get_new_scope_id - variables loc_to_scope_id + add_loc_vars + (child_loc :> Id.any_loc Id.t) + smemory get_new_scope_id variables loc_to_scope_id + in + let id = + Hashtbl.find loc_to_scope_id + (child_loc :> Id.any_loc Id.t) in - let id = Hashtbl.find loc_to_scope_id child_loc in Variable.create_node name id () | _ -> Variable.create_leaf name (to_str Expr.pp metadata) ()) @@ -239,7 +250,7 @@ struct let add_variables ~store - ~memory + ~(memory : memory) ~is_gil_file ~get_new_scope_id (variables : Variable.ts) = @@ -281,23 +292,26 @@ struct else None) store in - let local_scope_loc = - if List.length local_scope == 0 then "" - else - match List.hd local_scope with - | _, Expr.EList [ _; ALoc loc ] -> loc - | _ -> "" - in + let local_id : int = - match Hashtbl.find_opt loc_to_scope_id local_scope_loc with - | None -> + match local_scope with + | (_, Expr.EList [ _; ALoc loc ]) :: _ -> ( + match Hashtbl.find_opt loc_to_scope_id (loc :> Id.any_loc Id.t) with + | Some local_id -> local_id + | None -> + let local_id = get_new_scope_id () in + let () = Hashtbl.replace variables local_id [] in + local_id) + | _ -> let local_id = get_new_scope_id () in let () = Hashtbl.replace variables local_id [] in local_id - | Some local_id -> local_id in let global_id : int = - match Hashtbl.find_opt loc_to_scope_id "$lg" with + match + Hashtbl.find_opt loc_to_scope_id + (Jslogic.JSLogicCommon.locGlobName :> Id.any_loc Id.t) + with | None -> let global_id = get_new_scope_id () in let () = Hashtbl.replace variables global_id [] in diff --git a/Gillian-JS/lib/JSIL/BCmd.ml b/Gillian-JS/lib/JSIL/BCmd.ml index 184507196..70295dbd1 100644 --- a/Gillian-JS/lib/JSIL/BCmd.ml +++ b/Gillian-JS/lib/JSIL/BCmd.ml @@ -3,31 +3,31 @@ open Gillian.Gil_syntax type t = | Skip (** Empty command *) - | Assignment of string * Expr.t (** Assignment *) - | New of string * Expr.t option * Expr.t option (** Object creation *) - | Lookup of string * Expr.t * Expr.t (** Field lookup *) + | Assignment of Var.t * Expr.t (** Assignment *) + | New of Var.t * Expr.t option * Expr.t option (** Object creation *) + | Lookup of Var.t * Expr.t * Expr.t (** Field lookup *) | Mutation of Expr.t * Expr.t * Expr.t (** Field mutation *) | Delete of Expr.t * Expr.t (** Field deletion *) | DeleteObj of Expr.t (** Object deletion *) - | HasField of string * Expr.t * Expr.t (** Field check *) - | GetFields of string * Expr.t (** All fields of an object *) - | MetaData of string * Expr.t (** Object metadata *) + | HasField of Var.t * Expr.t * Expr.t (** Field check *) + | GetFields of Var.t * Expr.t (** All fields of an object *) + | MetaData of Var.t * Expr.t (** Object metadata *) let pp fmt bcmd = match bcmd with | Skip -> Fmt.pf fmt "skip" - | Assignment (var, e) -> Fmt.pf fmt "%s := %a" var Expr.pp e + | Assignment (var, e) -> Fmt.pf fmt "%a := %a" Var.pp var Expr.pp e | New (var, loc, metadata) -> - Fmt.pf fmt "%s := new(%a%a%a)" var (Fmt.option Expr.pp) loc + Fmt.pf fmt "%a := new(%a%a%a)" Var.pp var (Fmt.option Expr.pp) loc (fun f a -> if Option.is_some a then Fmt.string f ", ") loc (Fmt.option Expr.pp) metadata | Lookup (var, e1, e2) -> - Fmt.pf fmt "%s := [%a, %a]" var Expr.pp e1 Expr.pp e2 + Fmt.pf fmt "%a := [%a, %a]" Var.pp var Expr.pp e1 Expr.pp e2 | Mutation (e1, e2, e3) -> Fmt.pf fmt "[%a, %a] := %a" Expr.pp e1 Expr.pp e2 Expr.pp e3 | Delete (e1, e2) -> Fmt.pf fmt "delete (%a, %a)" Expr.pp e1 Expr.pp e2 | DeleteObj e1 -> Fmt.pf fmt "deleteObject (%a)" Expr.pp e1 | HasField (x, e1, e2) -> - Fmt.pf fmt "%s := hasField(%a, %a)" x Expr.pp e1 Expr.pp e2 - | GetFields (x, e) -> Fmt.pf fmt "%s := getFields (%a)" x Expr.pp e - | MetaData (x, e) -> Fmt.pf fmt "%s := metadata (%a)" x Expr.pp e + Fmt.pf fmt "%a := hasField(%a, %a)" Var.pp x Expr.pp e1 Expr.pp e2 + | GetFields (x, e) -> Fmt.pf fmt "%a := getFields (%a)" Var.pp x Expr.pp e + | MetaData (x, e) -> Fmt.pf fmt "%a := metadata (%a)" Var.pp x Expr.pp e diff --git a/Gillian-JS/lib/JSIL/BiSpec.ml b/Gillian-JS/lib/JSIL/BiSpec.ml index 8da78befd..aebb3cae9 100644 --- a/Gillian-JS/lib/JSIL/BiSpec.ml +++ b/Gillian-JS/lib/JSIL/BiSpec.ml @@ -1,7 +1,7 @@ (** {b Single JSIL specifications}. *) type t = { name : string; (** Procedure/spec name *) - params : string list; (** Procedure/spec parameters *) + params : Gil_syntax.Var.t list; (** Procedure/spec parameters *) pre : Asrt.t; (** Precondition *) normalised : bool; (** If the spec is already normalised *) } @@ -10,7 +10,7 @@ type t_tbl = (string, t) Hashtbl.t let init (name : string) - (params : string list) + (params : Gil_syntax.Var.t list) (pre : Asrt.t) (normalised : bool) : t = { name; params; pre; normalised } @@ -19,5 +19,5 @@ let init_tbl () : t_tbl = Hashtbl.create Config.medium_tbl_size let pp fmt bi_spec = Fmt.pf fmt "@[bispec %s (%a) :@\n[[ @[%a@] ]]@]" bi_spec.name - (Fmt.list ~sep:(Fmt.any ", ") Fmt.string) + (Fmt.list ~sep:(Fmt.any ", ") Gil_syntax.Var.pp) bi_spec.params Asrt.pp bi_spec.pre diff --git a/Gillian-JS/lib/JSIL/EProc.ml b/Gillian-JS/lib/JSIL/EProc.ml index 4451f1878..c6a2653c2 100644 --- a/Gillian-JS/lib/JSIL/EProc.ml +++ b/Gillian-JS/lib/JSIL/EProc.ml @@ -5,7 +5,7 @@ module Flag = Gillian.Gil_syntax.Flag type t = { name : string; body : (Annot.t * string option * LabCmd.t) array; - params : string list; + params : Gil_syntax.Var.t list; spec : Spec.t option; } @@ -34,7 +34,7 @@ let pp fmt labproc = Fmt.pf fmt "@[%a@\n@[proc %s(%a) {@\n%a@\n@]@\n};@\n@]" Fmt.(option Spec.pp) spec name - Fmt.(list ~sep:(Fmt.any ", ") Fmt.string) + Fmt.(list ~sep:(Fmt.any ", ") Gil_syntax.Var.pp) params Fmt.(array ~sep:(any ";@\n") pp_cmd_triple) body diff --git a/Gillian-JS/lib/JSIL/LabCmd.ml b/Gillian-JS/lib/JSIL/LabCmd.ml index 78560519f..122a560bc 100644 --- a/Gillian-JS/lib/JSIL/LabCmd.ml +++ b/Gillian-JS/lib/JSIL/LabCmd.ml @@ -1,4 +1,5 @@ module Expr = Gillian.Gil_syntax.Expr +module Var = Gillian.Gil_syntax.Var (***************************************************************) (***************************************************************) @@ -13,15 +14,15 @@ type t = | LGoto of string | LGuardedGoto of Expr.t * string * string | LCall of - string + Var.t * Expr.t * Expr.t list * string option * (string * (string * Expr.t) list) option - | LECall of string * Expr.t * Expr.t list * string option - | LApply of string * Expr.t * string option - | LArguments of string - | LPhiAssignment of (string * Expr.t list) list + | LECall of Var.t * Expr.t * Expr.t list * string option + | LApply of Var.t * Expr.t * string option + | LArguments of Var.t + | LPhiAssignment of (Var.t * Expr.t list) list | LReturnNormal | LReturnError @@ -42,18 +43,19 @@ let pp fmt lcmd = | LGuardedGoto (e, j, k) -> Fmt.pf fmt "goto [%a] %s %s" Expr.pp e j k | LCall (var, name, args, error, subst) -> let pp_subst f lbs = Fmt.pf f " use_subst %a" pp_logic_bindings lbs in - Fmt.pf fmt "%s := %a(%a)%a%a" var Expr.pp name pp_params args + Fmt.pf fmt "%a := %a(%a)%a%a" Var.pp var Expr.pp name pp_params args (Fmt.option pp_error) error (Fmt.option pp_subst) subst | LECall (var, name, args, error) -> - Fmt.pf fmt "%s := extern %a(%a)%a" var Expr.pp name pp_params args + Fmt.pf fmt "%a := extern %a(%a)%a" Var.pp var Expr.pp name pp_params args (Fmt.option pp_error) error | LApply (var, arg, error) -> - Fmt.pf fmt "%s := apply(%a)%a" var Expr.pp arg (Fmt.option pp_error) error - | LArguments var -> Fmt.pf fmt "%s := args" var + Fmt.pf fmt "%a := apply(%a)%a" Var.pp var Expr.pp arg + (Fmt.option pp_error) error + | LArguments var -> Fmt.pf fmt "%a := args" Var.pp var | LPhiAssignment lva -> let vars, var_args = List.split lva in Fmt.pf fmt "PHI(%a: %a)" - Fmt.(list ~sep:comma string) + Fmt.(list ~sep:comma Var.pp) vars Fmt.(list ~sep:semi pp_params) var_args diff --git a/Gillian-JS/lib/JSIL/Pred.ml b/Gillian-JS/lib/JSIL/Pred.ml index 148d08d90..51c7edfa0 100644 --- a/Gillian-JS/lib/JSIL/Pred.ml +++ b/Gillian-JS/lib/JSIL/Pred.ml @@ -7,7 +7,8 @@ module Expr = Gillian.Gil_syntax.Expr type t = { name : string; (** Name of the predicate *) num_params : int; (** Number of parameters *) - params : (string * Type.t option) list; (** Actual parameters *) + params : (Gil_syntax.Var.t * Type.t option) list; + (** Actual parameters *) ins : int list; (** Ins *) definitions : ((string * string list) option * Asrt.t) list; (** Predicate definitions *) @@ -32,9 +33,10 @@ let pp fmt pred = let params_with_info = if exist_ins then List.mapi - (fun i (v, t) -> ((if List.mem i ins then "+" else "") ^ v, t)) + (fun i (v, t) -> + ((if List.mem i ins then "+" else "") ^ Gil_syntax.Var.str v, t)) params - else params + else List.map (fun (v, t) -> (Gil_syntax.Var.str v, t)) params in let pp_param fmt (v, t) = match t with diff --git a/Gillian-JS/lib/JSIL/Spec.ml b/Gillian-JS/lib/JSIL/Spec.ml index 34a8aa34e..1aeab41ca 100644 --- a/Gillian-JS/lib/JSIL/Spec.ml +++ b/Gillian-JS/lib/JSIL/Spec.ml @@ -2,6 +2,7 @@ module SSubst = Gillian.Symbolic.Subst module SVal = Gillian.Symbolic.Values module Flag = Gillian.Gil_syntax.Flag module Expr = Gillian.Gil_syntax.Expr +module Var = Gillian.Gil_syntax.Var module SS = Containers.SS (** {b Single JSIL specifications}. *) @@ -16,7 +17,7 @@ type st = { (** {b Full JSIL specifications}. *) type t = { name : string; (** Procedure/spec name *) - params : string list; (** Procedure/spec parameters *) + params : Var.t list; (** Procedure/spec parameters *) sspecs : st list; (** List of single specifications *) normalised : bool; (** If the spec is already normalised *) incomplete : bool; (** If the spec is incomplete *) @@ -34,7 +35,7 @@ let s_init let init (name : string) - (params : string list) + (params : Var.t list) (sspecs : st list) (normalised : bool) (incomplete : bool) @@ -44,7 +45,7 @@ let init let extend (spec : t) (sspecs : st list) : t = { spec with sspecs = sspecs @ spec.sspecs } -let get_params (spec : t) : string list = spec.params +let get_params (spec : t) : Var.t list = spec.params let pp_sspec fmt sspec = let pp_lab fmt' (lab, exs) = @@ -66,7 +67,7 @@ let pp fmt spec = in Fmt.pf fmt "@[@[%a spec %s(%a)@]@\n%a@]" pp_incomplete spec.incomplete spec.name - (Fmt.list ~sep:Fmt.comma Fmt.string) + (Fmt.list ~sep:Fmt.comma Var.pp) spec.params (Fmt.list ~sep:(Fmt.any "@\n@\n") pp_sspec) spec.sspecs diff --git a/Gillian-JS/lib/JSLogic/JSAsrt.ml b/Gillian-JS/lib/JSLogic/JSAsrt.ml index d94721435..b20da4fd6 100644 --- a/Gillian-JS/lib/JSLogic/JSAsrt.ml +++ b/Gillian-JS/lib/JSLogic/JSAsrt.ml @@ -54,7 +54,7 @@ let rec js2jsil_pure (scope_le : Expr.t option) (a : pt) : Expr.t = | LessEq (le1, le2) -> BinOp (fe le1, FLessThanEqual, fe le2) | StrLess (le1, le2) -> BinOp (fe le1, StrLess, fe le2) | ForAll (s, a) -> - let new_binders = List.map (fun (x, t) -> (x, Some t)) s in + let new_binders = List.map (fun (x, t) -> (LVar.of_string x, Some t)) s in ForAll (new_binders, f a) | SetMem (le1, le2) -> BinOp (fe le1, SetMem, fe le2) | SetSub (le1, le2) -> BinOp (fe le1, SetSub, fe le2) @@ -89,7 +89,8 @@ let rec js2jsil | MetaData (le1, le2) -> Asrt.MetaData (fe le1, fe le2) | Emp -> Asrt.Emp | Types vts -> - Asrt.Types (List.map (fun (v, t) -> (Expr.from_var_name v, t)) vts) + Asrt.Types + (List.map (fun (v, t) -> (Expr.var_to_expr @@ Var.of_string v, t)) vts) | EmptyFields (e, domain) -> Asrt.EmptyFields (fe e, fe domain) | Pred (name, [ loc; Lit (String fid); sch; args_len; fproto ]) when name = "JSFunctionObject" || name = "JSFunctionObjectStrong" -> @@ -118,7 +119,7 @@ let rec js2jsil ((l-nth(le_sc', i), "x") -> le_x') if Phi(fid, x) != 0 ((lg, "x") -> {{"d", le_x', true, true, false}}) if Phi(fid, x) = 0 or bot *) | VarSChain (fid, x, le_x, le_sc) -> - let i = psi cc_tbl vis_tbl fid x in + let i = psi cc_tbl vis_tbl fid (Var.of_string x) in (* let a_len = Asrt.Pure (Eq (Lit (Num (float_of_int len)), UnOp (LstLen, fe le_sc))) in *) let a' = match i with @@ -267,7 +268,7 @@ let js2jsil_tactic (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (scope_var : string) + (scope_var : Var.t) (a : t) : Asrt.t = let vis_list = get_vis_list vis_tbl fid in let scope_chain_list = vislist_2_les vis_list (List.length vis_list) in @@ -282,7 +283,7 @@ let js2jsil_tactic (* x__this == #this *) let a_this = - Asrt.Pure (BinOp (Expr.PVar var_this, Equal, Expr.LVar this_logic_var_name)) + Asrt.Pure (BinOp (Expr.PVar var_this, Equal, Expr.LVar this_lvar)) in Asrt.star [ a'; a''; a_this ] diff --git a/Gillian-JS/lib/JSLogic/JSExpr.ml b/Gillian-JS/lib/JSLogic/JSExpr.ml index 6bcd4f5e4..9a2aaaf35 100644 --- a/Gillian-JS/lib/JSLogic/JSExpr.ml +++ b/Gillian-JS/lib/JSLogic/JSExpr.ml @@ -18,16 +18,16 @@ let rec js2jsil (scope_le : Expr.t option) (le : t) : Expr.t = let fe = js2jsil scope_le in match le with | Lit lit -> Expr.Lit lit - | LVar x -> Expr.LVar x - | ALoc l -> Expr.ALoc l - | PVar x -> Expr.PVar x + | LVar x -> Expr.LVar (LVar.of_string x) + | ALoc l -> Expr.ALoc (ALoc.of_string l) + | PVar x -> Expr.PVar (Var.of_string x) | UnOp (op, le) -> Expr.UnOp (op, fe le) | BinOp (le1, op, le2) -> Expr.BinOp (fe le1, op, fe le2) | LstSub (le1, le2, le3) -> Expr.LstSub (fe le1, fe le2, fe le3) | NOp (op, les) -> Expr.NOp (op, List.map fe les) | EList les -> Expr.EList (List.map fe les) | ESet les -> Expr.ESet (List.map fe les) - | This -> Expr.LVar JSLogicCommon.this_logic_var_name + | This -> Expr.LVar JSLogicCommon.this_lvar | Scope -> ( match scope_le with | None -> raise (Failure "DEATH: js2jsil_lexpr") diff --git a/Gillian-JS/lib/JSLogic/JSLCmd.ml b/Gillian-JS/lib/JSLogic/JSLCmd.ml index 4ec5aa598..02904b495 100644 --- a/Gillian-JS/lib/JSLogic/JSLCmd.ml +++ b/Gillian-JS/lib/JSLogic/JSLCmd.ml @@ -21,7 +21,7 @@ let rec js2jsil (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (scope_var : string) + (scope_var : Gil_syntax.Var.t) (logic_cmd : t) : LCmd.t list = let f = js2jsil cc_tbl vis_tbl fun_tbl fid scope_var in let fe = JSExpr.js2jsil None in diff --git a/Gillian-JS/lib/JSLogic/JSLogicCommon.ml b/Gillian-JS/lib/JSLogic/JSLogicCommon.ml index 75366ee27..0db65cf26 100644 --- a/Gillian-JS/lib/JSLogic/JSLogicCommon.ml +++ b/Gillian-JS/lib/JSLogic/JSLogicCommon.ml @@ -1,6 +1,7 @@ module L = Logging module Expr = Gillian.Gil_syntax.Expr open Jsil_syntax +open Gil_syntax.Id (** Tables *) module SS = Containers.SS @@ -8,24 +9,23 @@ module SS = Containers.SS let small_tbl_size = 1 let medium_tbl_size = 1 -type var_to_fid_tbl_type = (string, string) Hashtbl.t +type var_to_fid_tbl_type = (Var.t, string) Hashtbl.t type cc_tbl_type = (string, var_to_fid_tbl_type) Hashtbl.t type fun_tbl_type = ( string, - string * string list * JS_Parser.Syntax.exp option * bool * Spec.t option - ) + string * Var.t list * JS_Parser.Syntax.exp option * bool * Spec.t option ) Hashtbl.t type pre_fun_tbl_type = ( string, string - * string list + * Var.t list * JS_Parser.Syntax.exp option * bool * (JS_Parser.Syntax.annotation list * string list - * (string, string) Hashtbl.t) ) + * (Var.t, string) Hashtbl.t) ) Hashtbl.t type vis_tbl_type = (string, string list) Hashtbl.t @@ -53,15 +53,15 @@ let initial_heap_pre_pred_name = "initialHeapPre" let initial_heap_post_pred_name = "initialHeapPost" let function_object_pred_name = "function_object" let standard_object_pred_name = "standardObject" -let this_logic_var_name = "#this" -let locGlobName = "$lg" -let var_te = "x__te" -let var_se = "x__se" -let var_er = "x__er" -let var_this = "x__this" -let var_scope = "x__scope" -let logic_var_scope = "#x__scope" -let var_scope_final = "x__scope_f" +let this_lvar = LVar.of_string "#this" +let locGlobName = Loc.of_string "$lg" +let var_te = Var.of_string "x__te" +let var_se = Var.of_string "x__se" +let var_er = Var.of_string "x__er" +let var_this = Var.of_string "x__this" +let var_scope = Var.of_string "x__scope" +let logic_var_scope = LVar.of_string "#x__scope" +let var_scope_final = Var.of_string "x__scope_f" let funobj_pred_name = "JSFunctionObject" let js_obj_internal_fields = [ "@proto"; "@class"; "@extensible" ] @@ -110,7 +110,7 @@ let psi (cc_tbl : cc_tbl_type) (vis_tbl : vis_tbl_type) (fid : string) - (x : string) = + (x : Var.t) = let var_to_fid_tbl = get_scope_table cc_tbl fid in try let fid' = Hashtbl.find var_to_fid_tbl x in diff --git a/Gillian-JS/lib/JSLogic/JSPred.ml b/Gillian-JS/lib/JSLogic/JSPred.ml index 297779071..abd2cbcb0 100644 --- a/Gillian-JS/lib/JSLogic/JSPred.ml +++ b/Gillian-JS/lib/JSLogic/JSPred.ml @@ -1,12 +1,13 @@ open JSLogicCommon module Type = Gillian.Gil_syntax.Type module Expr = Gillian.Gil_syntax.Expr +module Var = Gillian.Gil_syntax.Var module Pred = Jsil_syntax.Pred type t = { name : string; num_params : int; - params : (string * Type.t option) list; + params : (Var.t * Type.t option) list; ins : int list; definitions : ((string * string list) option * JSAsrt.t) list; facts : Expr.t list; diff --git a/Gillian-JS/lib/JSLogic/JSSpec.ml b/Gillian-JS/lib/JSLogic/JSSpec.ml index e7ecfa47c..883d005af 100644 --- a/Gillian-JS/lib/JSLogic/JSSpec.ml +++ b/Gillian-JS/lib/JSLogic/JSSpec.ml @@ -9,7 +9,7 @@ type st = { label : (string * SS.t) option; } -type t = { name : string; params : string list; sspecs : st list } +type t = { name : string; params : Var.t list; sspecs : st list } let js2jsil_st (pre : JSAsrt.t) @@ -18,7 +18,7 @@ let js2jsil_st (vis_tbl : vis_tbl_type) (fun_tbl : pre_fun_tbl_type) (fid : string) - (params : string list) : Asrt.t * Asrt.t list = + (params : Gil_syntax.Var.t list) : Asrt.t * Asrt.t list = let vis_list = get_vis_list vis_tbl fid in let scope_chain_list = vislist_2_les vis_list (List.length vis_list - 1) in @@ -64,7 +64,7 @@ let js2jsil_st (* x__this == #this *) let a_this = - Asrt.Pure (BinOp (Expr.PVar var_this, Equal, Expr.LVar this_logic_var_name)) + Asrt.Pure (BinOp (Expr.PVar var_this, Equal, Expr.LVar this_lvar)) in (* x__scope == {{ #x1, ..., #xn }} *) let a_scope = diff --git a/Gillian-JS/lib/Parsing/Javert_Parser.mly b/Gillian-JS/lib/Parsing/Javert_Parser.mly index 72fa5282f..10d2081ad 100644 --- a/Gillian-JS/lib/Parsing/Javert_Parser.mly +++ b/Gillian-JS/lib/Parsing/Javert_Parser.mly @@ -330,7 +330,7 @@ lit_target: | NAN { Literal.Num nan } | INFINITY { Literal.Num infinity } | STRING { Literal.String $1 } - | LOC { Literal.Loc $1 } + | LOC { Literal.Loc (Loc.of_string $1) } | type_target { Literal.Type $1 } | LSTNIL { Literal.LList [] } | LSTOPEN LSTCLOSE { Literal.LList [] } @@ -406,10 +406,10 @@ expr_target: | lit=lit_target { Expr.Lit lit } | v = LVAR { let v_imported = Str.replace_first normalised_lvar_r "_lvar_n" v in - Expr.LVar v_imported + Expr.LVar (LVar.of_string v_imported) } - | ALOC { Expr.ALoc $1 } - | v = VAR { Expr.PVar v } + | ALOC { Expr.ALoc (ALoc.of_string $1) } + | v = program_variable_target { v } | e1=expr_target; bop=binop_target; e2=expr_target { Expr.BinOp (e1, bop, e2) } %prec binop_prec | e1=expr_target; LSTCONS; e2=expr_target { Expr.NOp (LstCat, [ EList [ e1 ]; e2 ]) } | e1=expr_target; GREATERTHAN; e2=expr_target { Expr.BinOp (e2, FLessThan, e1) } @@ -441,9 +441,9 @@ expr_target: lvar_type_target: | lvar = LVAR; COLON; the_type = type_target - { (lvar, Some the_type) } + { (LVar.of_string lvar, Some the_type) } | lvar = LVAR; - { (lvar, None) } + { (LVar.of_string lvar, None) } pure_assertion_target: @@ -472,15 +472,18 @@ pure_assertion_target: | delimited(LBRACE, pure_assertion_target, RBRACE) { $1 } +program_variable_name_target: + | v = VAR { Var.of_string v } + program_variable_target: - | v = VAR { Expr.PVar v } + | v = program_variable_name_target { Expr.PVar v } logic_variable_target: v = LVAR { let v_imported = Str.replace_first normalised_lvar_r "_lvar_n" v in (* Prefixed with _n_ to avoid clashes *) - Expr.LVar v_imported } + Expr.LVar (LVar.of_string v_imported) } type_env_pair_target: | lvar = logic_variable_target; COLON; the_type=type_target @@ -579,7 +582,7 @@ logic_cmd_target: { LCmd.Branch fo } phi_target: - v = VAR; COLON; args = separated_list(COMMA, expr_target) + v = program_variable_name_target; COLON; args = separated_list(COMMA, expr_target) { (v, args) } call_with_target: @@ -603,9 +606,9 @@ new_target: cmd_target: | SKIP { LabCmd.LBasic (Skip) } - | v=VAR; DEFEQ; e=expr_target + | v=program_variable_name_target; DEFEQ; e=expr_target { LabCmd.LBasic (Assignment (v, e)) } - | VAR; DEFEQ; NEW; LBRACE; option(new_target); RBRACE + | program_variable_name_target; DEFEQ; NEW; LBRACE; option(new_target); RBRACE { let loc, metadata = (match $5 with | Some (Some arg_a, Some arg_b) -> Some arg_a, Some arg_b @@ -614,7 +617,7 @@ cmd_target: | _ -> None, None ) in LabCmd.LBasic (New ($1, loc, metadata)) } - | v=VAR; DEFEQ; LBRACKET; e1=expr_target; COMMA; e2=expr_target; RBRACKET + | v=program_variable_name_target; DEFEQ; LBRACKET; e1=expr_target; COMMA; e2=expr_target; RBRACKET { LabCmd.LBasic (Lookup (v, e1, e2)) } | LBRACKET; e1=expr_target; COMMA; e2=expr_target; RBRACKET; DEFEQ; e3=expr_target { LabCmd.LBasic (Mutation (e1, e2, e3)) } @@ -622,26 +625,26 @@ cmd_target: { LabCmd.LBasic (Delete (e1, e2)) } | DELETEOBJ; LBRACE; e1=expr_target; RBRACE { LabCmd.LBasic (DeleteObj (e1)) } - | v=VAR; DEFEQ; HASFIELD; LBRACE; e1=expr_target; COMMA; e2=expr_target; RBRACE + | v=program_variable_name_target; DEFEQ; HASFIELD; LBRACE; e1=expr_target; COMMA; e2=expr_target; RBRACE { LabCmd.LBasic (HasField (v, e1, e2)) } - | v = VAR; DEFEQ; GETFIELDS; LBRACE; e=expr_target; RBRACE + | v = program_variable_name_target; DEFEQ; GETFIELDS; LBRACE; e=expr_target; RBRACE { LabCmd.LBasic (GetFields (v, e)) } - | v = VAR; DEFEQ; METADATA; LBRACE; e=expr_target; RBRACE + | v = program_variable_name_target; DEFEQ; METADATA; LBRACE; e=expr_target; RBRACE { LabCmd.LBasic (MetaData (v, e)) } | GOTO; i=VAR { LabCmd.LGoto i } | GOTO LBRACKET; e=expr_target; RBRACKET; i=VAR; j=VAR { LabCmd.LGuardedGoto (e, i, j) } - | v=VAR; DEFEQ; e=expr_target; + | v=program_variable_name_target; DEFEQ; e=expr_target; LBRACE; es=separated_list(COMMA, expr_target); RBRACE; oi = option(call_with_target); subst = option(use_subst_target) { LabCmd.LCall (v, e, es, oi, subst) } - | v=VAR; DEFEQ; EXTERN; pname=VAR; + | v=program_variable_name_target; DEFEQ; EXTERN; pname=program_variable_target; LBRACE; es=separated_list(COMMA, expr_target); RBRACE; oi = option(call_with_target) - { LabCmd.LECall (v, PVar pname, es, oi) } - | v=VAR; DEFEQ; APPLY; + { LabCmd.LECall (v, pname, es, oi) } + | v=program_variable_name_target; DEFEQ; APPLY; LBRACE; es=expr_target; RBRACE; oi = option(call_with_target) { LabCmd.LApply (v, es, oi) } - | v = VAR; DEFEQ; ARGUMENTS + | v = program_variable_name_target; DEFEQ; ARGUMENTS { (LabCmd.LArguments v) } | PHI; LBRACE; phi_args =separated_list(SCOLON, phi_target); RBRACE { match phi_args with @@ -710,7 +713,7 @@ pre_post_target: { Spec.{ pre; posts; flag = Error; to_verify = true; label = lab_spec} } spec_head_target: - spec_name = VAR; LBRACE; spec_params = separated_list(COMMA, VAR); RBRACE + spec_name = VAR; LBRACE; spec_params = separated_list(COMMA, program_variable_name_target); RBRACE { (spec_name, spec_params) } spec_target: @@ -732,7 +735,7 @@ spec_target: /* PROCEDURES */ proc_head_target: - PROC; proc_name = VAR; LBRACE; param_list = separated_list(COMMA, VAR); RBRACE + PROC; proc_name = VAR; LBRACE; param_list = separated_list(COMMA, program_variable_name_target); RBRACE { (proc_name, param_list) } proc_target: @@ -783,7 +786,7 @@ named_assertion_target: pred_param_target: (* Program variable with in-parameter status and optional type *) - | in_param = option(PLUS); v = VAR; t = option(preceded(COLON, type_target)) + | in_param = option(PLUS); v = program_variable_name_target; t = option(preceded(COLON, type_target)) { let in_param = Option.fold ~some:(fun _ -> true) ~none:false in_param in (v, t), in_param } @@ -989,7 +992,7 @@ js_lexpr_target: { e } (* _ *) | UNDERSCORE - { JSExpr.LVar (Javert_utils.Js_generators.fresh_lvar ()) } + { JSExpr.LVar (LVar.str @@ Javert_utils.Js_generators.fresh_lvar ()) } (* $$scope *) | SCOPELEXPR { JSExpr.Scope } diff --git a/Gillian-JS/lib/Semantics/CHeap.ml b/Gillian-JS/lib/Semantics/CHeap.ml index 3cdea024b..c25ab1a3c 100644 --- a/Gillian-JS/lib/Semantics/CHeap.ml +++ b/Gillian-JS/lib/Semantics/CHeap.ml @@ -1,16 +1,17 @@ open Gillian.Concrete +module Loc = Gil_syntax.Loc -type t = (string, CObject.t * Values.t) Hashtbl.t +type t = (Loc.t, CObject.t * Values.t) Hashtbl.t let pp fmt heap = let pp_obj fmt (loc, (obj, metadata)) = CObject.pp fmt (loc, obj, metadata) in (Fmt.hashtbl ~sep:(Fmt.any "@\n") pp_obj) fmt heap let init () : t = Hashtbl.create Config.medium_tbl_size -let get (heap : t) (loc : string) = Hashtbl.find_opt heap loc +let get (heap : t) (loc : Loc.t) = Hashtbl.find_opt heap loc -let set (heap : t) (loc : string) (obj_with_mv : CObject.t * Values.t) = +let set (heap : t) (loc : Loc.t) (obj_with_mv : CObject.t * Values.t) = Hashtbl.replace heap loc obj_with_mv -let remove (heap : t) (loc : string) = Hashtbl.remove heap loc +let remove (heap : t) (loc : Loc.t) = Hashtbl.remove heap loc let copy (heap : t) = Hashtbl.copy heap diff --git a/Gillian-JS/lib/Semantics/CHeap.mli b/Gillian-JS/lib/Semantics/CHeap.mli index 44c7541c2..6e306ad7e 100644 --- a/Gillian-JS/lib/Semantics/CHeap.mli +++ b/Gillian-JS/lib/Semantics/CHeap.mli @@ -1,10 +1,11 @@ open Gillian.Concrete +module Loc := Gil_syntax.Loc type t val pp : Format.formatter -> t -> unit val init : unit -> t -val get : t -> string -> (CObject.t * Values.t) option -val set : t -> string -> CObject.t * Values.t -> unit -val remove : t -> string -> unit +val get : t -> Loc.t -> (CObject.t * Values.t) option +val set : t -> Loc.t -> CObject.t * Values.t -> unit +val remove : t -> Loc.t -> unit val copy : t -> t diff --git a/Gillian-JS/lib/Semantics/CObject.ml b/Gillian-JS/lib/Semantics/CObject.ml index bc7f962c1..35a385994 100644 --- a/Gillian-JS/lib/Semantics/CObject.ml +++ b/Gillian-JS/lib/Semantics/CObject.ml @@ -1,5 +1,5 @@ open Gillian.Concrete -module Var = Gillian.Gil_syntax.Var +module SS = Gillian.Utils.Containers.SS type t = (string, Values.t) Hashtbl.t @@ -7,7 +7,7 @@ let pp fmt (loc, obj, metadata) = let pp_kv fmt (prop, prop_val) = Fmt.pf fmt "%s: %a" prop Values.pp prop_val in - Fmt.pf fmt "@[%s|-> [ %a ], %a@]" loc + Fmt.pf fmt "@[%a|-> [ %a ], %a@]" Gil_syntax.Loc.pp loc (Fmt.hashtbl ~sep:Fmt.comma pp_kv) obj Values.pp metadata @@ -20,7 +20,4 @@ let set (obj : t) (prop : string) (value : Values.t) = let remove (obj : t) (prop : string) = Hashtbl.remove obj prop let properties (obj : t) : string list = - Var.Set.elements - (Hashtbl.fold - (fun prop _ props -> Var.Set.add prop props) - obj Var.Set.empty) + SS.elements @@ Hashtbl.fold (fun prop _ -> SS.add prop) obj SS.empty diff --git a/Gillian-JS/lib/Semantics/CObject.mli b/Gillian-JS/lib/Semantics/CObject.mli index 5dd98a82b..519fee38a 100644 --- a/Gillian-JS/lib/Semantics/CObject.mli +++ b/Gillian-JS/lib/Semantics/CObject.mli @@ -2,7 +2,7 @@ open Gillian.Concrete type t -val pp : Format.formatter -> string * t * Values.t -> unit +val pp : Format.formatter -> Gil_syntax.Loc.t * t * Values.t -> unit val init : unit -> t val get : t -> string -> Values.t option val set : t -> string -> Values.t -> unit diff --git a/Gillian-JS/lib/Semantics/External.ml b/Gillian-JS/lib/Semantics/External.ml index d19975eaa..2360ae0dc 100644 --- a/Gillian-JS/lib/Semantics/External.ml +++ b/Gillian-JS/lib/Semantics/External.ml @@ -173,9 +173,10 @@ struct | JS_Parser.Syntax.Function (strictness, Some "THISISANELABORATENAME", params, body) -> let cur_proc_id = Call_stack.get_cur_proc_id cs in + let params_var = List.map Gil_syntax.Var.of_string params in let new_proc = JS2JSIL_Compiler.js2jsil_function_constructor_prop prog - cur_proc_id params strictness body + cur_proc_id params_var strictness body in let fun_name = String new_proc.proc_name in let params = LList (List.map (fun x -> String x) params) in @@ -206,7 +207,7 @@ struct (state : State.t) (cs : Call_stack.t) (i : int) - (x : string) + (x : Gil_syntax.Var.t) (pid : string) (v_args : Val.t list) (j : int option) = diff --git a/Gillian-JS/lib/Semantics/JSILCMemory.ml b/Gillian-JS/lib/Semantics/JSILCMemory.ml index 5321f1dd8..5f94a3198 100644 --- a/Gillian-JS/lib/Semantics/JSILCMemory.ml +++ b/Gillian-JS/lib/Semantics/JSILCMemory.ml @@ -109,7 +109,7 @@ module M : Memory_S with type init_data = unit = struct let alloc (heap : t) (loc : vt option) (mv : vt) : action_ret = let new_loc = match loc with - | None -> Generators.fresh_loc () + | None -> Loc.alloc () | Some (Loc loc) -> loc | _ -> raise (Failure "C Allocation: non-loc loc argument") in diff --git a/Gillian-JS/lib/Semantics/JSILSMemory.ml b/Gillian-JS/lib/Semantics/JSILSMemory.ml index 746b33cfb..032e745f9 100644 --- a/Gillian-JS/lib/Semantics/JSILSMemory.ml +++ b/Gillian-JS/lib/Semantics/JSILSMemory.ml @@ -11,6 +11,8 @@ module Type_env = Gillian.Symbolic.Type_env module Recovery_tactic = Gillian.General.Recovery_tactic open Gillian.Logic +type loc_t = Id.any_loc Id.t + module M = struct type init_data = unit type vt = SVal.t [@@deriving yojson, show] @@ -34,7 +36,7 @@ module M = struct type err_t = vt list * i_fix_t list list * Expr.t [@@deriving yojson, show] type action_ret = - ( (t * vt list * Expr.t list * (string * Type.t) list) list, + ( (t * vt list * Expr.t list * (Id.any_var Id.t * Type.t) list) list, err_t list ) result @@ -91,8 +93,8 @@ module M = struct Recovery_tactic.try_unfold values let assertions ?to_keep:_ (heap : t) : GAsrt.t = SHeap.assertions heap - let lvars (heap : t) : Containers.SS.t = SHeap.lvars heap - let alocs (heap : t) : Containers.SS.t = SHeap.alocs heap + let lvars (heap : t) : LVar.Set.t = SHeap.lvars heap + let alocs (heap : t) : ALoc.Set.t = SHeap.alocs heap let clean_up ?(keep = Expr.Set.empty) (heap : t) : Expr.Set.t * Expr.Set.t = SHeap.clean_up heap; @@ -114,21 +116,18 @@ module M = struct Gillian.Logic.FOSolver.resolve_loc_name ~pfs ~gamma let fresh_loc ?(loc : vt option) (pfs : PFS.t) (gamma : Type_env.t) : - string * vt * Expr.t list = + loc_t * vt * Expr.t list = match loc with | Some loc -> ( let loc_name = get_loc_name pfs gamma loc in match loc_name with - | Some loc_name -> - if Names.is_aloc_name loc_name then - (loc_name, Expr.ALoc loc_name, []) - else (loc_name, Expr.Lit (Loc loc_name), []) + | Some loc_name -> (loc_name, Expr.loc_from_loc_name loc_name, []) | None -> let al = ALoc.alloc () in - (al, ALoc al, [ Expr.BinOp (ALoc al, Equal, loc) ])) + ((al :> loc_t), ALoc al, [ Expr.BinOp (ALoc al, Equal, loc) ])) | None -> let al = ALoc.alloc () in - (al, ALoc al, []) + ((al :> loc_t), ALoc al, []) let alloc (heap : t) @@ -136,22 +135,19 @@ module M = struct (loc : vt option) ?is_empty:(ie = false) (mv : vt option) : action_ret = - let (loc_name : string), (loc : Expr.t) = + let (loc_name : loc_t), (loc : Expr.t) = match (loc : Expr.t option) with | None -> let loc_name = ALoc.alloc () in - (loc_name, ALoc loc_name) - | Some (Lit (Loc loc)) -> (loc, Lit (Loc loc)) - | Some (ALoc loc) -> (loc, ALoc loc) + ((loc_name :> loc_t), ALoc loc_name) + | Some (Lit (Loc loc)) -> ((loc :> loc_t), Lit (Loc loc)) + | Some (ALoc loc) -> ((loc :> loc_t), ALoc loc) | Some (LVar v) -> let loc_name = ALoc.alloc () in PFS.extend pfs (BinOp (LVar v, Equal, ALoc loc_name)); - (loc_name, ALoc loc_name) + ((loc_name :> loc_t), ALoc loc_name) | Some le -> - raise - (Failure - (Printf.sprintf "Alloc with a non-loc loc argument: %s" - ((Fmt.to_to_string Expr.pp) le))) + Fmt.failwith "Alloc with a non-loc loc argument: %a" Expr.pp le in SHeap.init_object heap loc_name ~is_empty:ie mv; Ok [ (heap, [ loc ], [], []) ] @@ -177,11 +173,11 @@ module M = struct L.tmi (fun m -> m "@[GetCell: resolved location: %a -> %a@]" SVal.pp loc - Fmt.(option ~none:(any "None") string) + Fmt.(option ~none:(any "None") Id.pp) loc_name); let make_gc_error - (loc_name : string) + (loc_name : loc_t) (prop : vt) (props : vt list) (dom : vt option) : err_t = @@ -241,7 +237,7 @@ module M = struct UnOp (Not, BinOp (prop, SetMem, dom)) in if - FOSolver.check_entailment Containers.SS.empty pfs + FOSolver.check_entailment LVar.Set.empty pfs [ a_set_inclusion ] gamma then ( let new_domain : Expr.t = @@ -260,7 +256,7 @@ module M = struct BinOp (dom, Equal, ESet f_names) in if - FOSolver.check_entailment Containers.SS.empty pfs + FOSolver.check_entailment LVar.Set.empty pfs [ full_knowledge ] gamma then ( L.verbose (fun m -> m "GET CELL will branch\n"); @@ -330,7 +326,7 @@ module M = struct (loc : vt) (prop : vt) : action_ret = let heap = SHeap.copy heap in - let f (loc_name : string) : unit = + let f (loc_name : loc_t) : unit = Option.fold ~some:(fun ((fv_list, dom), mtdt) -> SHeap.set heap loc_name (SFVL.remove prop fv_list) dom mtdt; @@ -359,16 +355,13 @@ module M = struct action_ret = let loc_name = get_loc_name pfs gamma loc in - let make_gm_error (loc_name : string) : err_t = + let make_gm_error (loc_name : loc_t) : err_t = let loc = Expr.loc_from_loc_name loc_name in ([ loc ], [ [ FMetadata loc ] ], Expr.false_) in let f loc_name = - let loc = - if Names.is_aloc_name loc_name then Expr.ALoc loc_name - else Expr.Lit (Loc loc_name) - in + let loc = Expr.loc_from_loc_name loc_name in match SHeap.get heap loc_name with | None -> Error [ make_gm_error loc_name ] | Some ((_, _), mtdt) -> @@ -487,7 +480,7 @@ module M = struct let props = SFVL.field_names fv_list in let a_set_equality : Expr.t = BinOp (dom, Equal, ESet props) in let solver_ret = - FOSolver.check_entailment Containers.SS.empty pfs [ a_set_equality ] + FOSolver.check_entailment LVar.Set.empty pfs [ a_set_equality ] gamma in if solver_ret then @@ -505,7 +498,7 @@ module M = struct let remove_domain (heap : t) (pfs : PFS.t) (gamma : Type_env.t) (loc : vt) : action_ret = - let f (loc_name : string) : unit = + let f (loc_name : loc_t) : unit = Option.fold ~some:(fun ((fv_list, _), mtdt) -> SHeap.set heap loc_name fv_list None mtdt; @@ -742,6 +735,6 @@ module M = struct let can_fix _ = true let sorted_locs_with_vals (smemory : t) = - let sorted_locs = Containers.SS.elements (SHeap.domain smemory) in - List.map (fun loc -> (loc, Option.get (SHeap.get smemory loc))) sorted_locs + Id.Sets.LocSet.elements (SHeap.domain smemory) + |> List.map (fun loc -> (loc, Option.get @@ SHeap.get smemory loc)) end diff --git a/Gillian-JS/lib/Semantics/SFVL.ml b/Gillian-JS/lib/Semantics/SFVL.ml index ae5aa6ef3..ae22980b0 100644 --- a/Gillian-JS/lib/Semantics/SFVL.ml +++ b/Gillian-JS/lib/Semantics/SFVL.ml @@ -1,6 +1,5 @@ (** JSIL symbolic field-value list *) -open Containers module Expr = Gillian.Gil_syntax.Expr module SSubst = Gillian.Symbolic.Subst open Gillian.Gil_syntax @@ -62,18 +61,18 @@ let get_first (f : field_name -> bool) (sfvl : t) : Expr.Map.find_first_opt f sfvl (** Returns the logical variables occuring in --sfvl-- *) -let lvars (sfvl : t) : SS.t = - let gllv = Expr.lvars in +let lvars (sfvl : t) : LVar.Set.t = Expr.Map.fold - (fun e_field e_val ac -> SS.union ac (SS.union (gllv e_field) (gllv e_val))) - sfvl SS.empty + (fun e_field e_val -> + LVar.Set.union @@ LVar.Set.union (Expr.lvars e_field) (Expr.lvars e_val)) + sfvl LVar.Set.empty (** Returns the abstract locations occuring in --sfvl-- *) -let alocs (sfvl : t) : SS.t = +let alocs (sfvl : t) : ALoc.Set.t = Expr.Map.fold - (fun e_field e_val ac -> - SS.union ac (SS.union (Expr.alocs e_field) (Expr.alocs e_val))) - sfvl SS.empty + (fun e_field e_val -> + ALoc.Set.union @@ ALoc.Set.union (Expr.alocs e_field) (Expr.alocs e_val)) + sfvl ALoc.Set.empty let assertions (loc : Expr.t) (sfvl : t) : Asrt.t = List.rev diff --git a/Gillian-JS/lib/Semantics/SFVL.mli b/Gillian-JS/lib/Semantics/SFVL.mli index 023415218..a461fdafc 100644 --- a/Gillian-JS/lib/Semantics/SFVL.mli +++ b/Gillian-JS/lib/Semantics/SFVL.mli @@ -21,8 +21,8 @@ val partition : (field_name -> field_value -> bool) -> t -> t * t val remove : field_name -> t -> t val pp : Format.formatter -> t -> unit val union : t -> t -> t -val lvars : t -> Containers.SS.t -val alocs : t -> Containers.SS.t +val lvars : t -> LVar.Set.t +val alocs : t -> ALoc.Set.t val assertions : Expr.t -> t -> Asrt.t val substitution : Subst.t -> bool -> t -> t val selective_substitution : Subst.t -> bool -> t -> t diff --git a/Gillian-JS/lib/Semantics/SHeap.ml b/Gillian-JS/lib/Semantics/SHeap.ml index a160b3104..08dd8c971 100644 --- a/Gillian-JS/lib/Semantics/SHeap.ml +++ b/Gillian-JS/lib/Semantics/SHeap.ml @@ -4,18 +4,24 @@ open Gillian.Gil_syntax open Javert_utils module SSubst = Gillian.Symbolic.Subst module L = Logging +module LocSet = Id.Sets.LocSet + +type loc_t = Id.any_loc Id.t + +let loc_t_of_yojson = Id.of_yojson' +let loc_t_to_yojson = Id.to_yojson' type s_object = (SFVL.t * Expr.t option) * Expr.t option type t = { - cfvl : (string, SFVL.t) Hashtbl.t; - cdom : (string, Expr.t option) Hashtbl.t; - cmet : (string, Expr.t option) Hashtbl.t; - sfvl : (string, SFVL.t) Hashtbl.t; - sdom : (string, Expr.t option) Hashtbl.t; - smet : (string, Expr.t option) Hashtbl.t; - cdmn : SS.t ref; - sdmn : SS.t ref; + cfvl : (loc_t, SFVL.t) Hashtbl.t; + cdom : (loc_t, Expr.t option) Hashtbl.t; + cmet : (loc_t, Expr.t option) Hashtbl.t; + sfvl : (loc_t, SFVL.t) Hashtbl.t; + sdom : (loc_t, Expr.t option) Hashtbl.t; + smet : (loc_t, Expr.t option) Hashtbl.t; + cdmn : LocSet.t ref; + sdmn : LocSet.t ref; } [@@deriving yojson] @@ -31,30 +37,30 @@ let merge (a : 't option) (b : 't option) (f : 't -> 't -> 't) : 't option = | None, b -> b | Some a, Some b -> Some (f a b) -let get_fvl (heap : t) (loc : string) : SFVL.t option = +let get_fvl (heap : t) (loc : loc_t) : SFVL.t option = let cfvl = Hashtbl.find_opt heap.cfvl loc in let sfvl = Hashtbl.find_opt heap.sfvl loc in merge cfvl sfvl SFVL.union -let get_dom (heap : t) (loc : string) : Expr.t option = +let get_dom (heap : t) (loc : loc_t) : Expr.t option = let cdom = Option.value ~default:None (Hashtbl.find_opt heap.cdom loc) in let sdom = Option.value ~default:None (Hashtbl.find_opt heap.sdom loc) in merge cdom sdom (fun _ _ -> raise (Failure "Domain in both the concrete and symbolic part of the heap.")) -let get_met (heap : t) (loc : string) : Expr.t option = +let get_met (heap : t) (loc : loc_t) : Expr.t option = let cmet = Option.value ~default:None (Hashtbl.find_opt heap.cmet loc) in let smet = Option.value ~default:None (Hashtbl.find_opt heap.smet loc) in merge cmet smet (fun _ _ -> raise (Failure "MetaData in both the concrete and symbolic part of the heap.")) -let set_fvl (heap : t) (loc : string) (fvl : SFVL.t) : unit = +let set_fvl (heap : t) (loc : loc_t) (fvl : SFVL.t) : unit = Hashtbl.remove heap.cfvl loc; Hashtbl.remove heap.sfvl loc; - heap.cdmn := Var.Set.remove loc !(heap.cdmn); - heap.sdmn := Var.Set.remove loc !(heap.sdmn); + heap.cdmn := LocSet.remove loc !(heap.cdmn); + heap.sdmn := LocSet.remove loc !(heap.sdmn); let cfvl, sfvl = SFVL.partition (fun prop value -> is_c value && is_c prop) fvl @@ -63,22 +69,22 @@ let set_fvl (heap : t) (loc : string) (fvl : SFVL.t) : unit = | true, true -> Hashtbl.replace heap.cfvl loc SFVL.empty; Hashtbl.remove heap.sfvl loc; - heap.cdmn := Var.Set.add loc !(heap.cdmn) + heap.cdmn := LocSet.add loc !(heap.cdmn) | true, false -> Hashtbl.remove heap.cfvl loc; Hashtbl.replace heap.sfvl loc sfvl; - heap.cdmn := Var.Set.add loc !(heap.cdmn) + heap.cdmn := LocSet.add loc !(heap.cdmn) | false, true -> Hashtbl.replace heap.cfvl loc cfvl; Hashtbl.remove heap.sfvl loc; - heap.sdmn := Var.Set.add loc !(heap.sdmn) + heap.sdmn := LocSet.add loc !(heap.sdmn) | false, false -> Hashtbl.replace heap.cfvl loc cfvl; Hashtbl.replace heap.sfvl loc sfvl; - heap.cdmn := Var.Set.add loc !(heap.cdmn); - heap.sdmn := Var.Set.add loc !(heap.sdmn) + heap.cdmn := LocSet.add loc !(heap.cdmn); + heap.sdmn := LocSet.add loc !(heap.sdmn) -let set_dom (heap : t) (loc : string) (dom : Expr.t option) : unit = +let set_dom (heap : t) (loc : loc_t) (dom : Expr.t option) : unit = Hashtbl.remove heap.cdom loc; Hashtbl.remove heap.sdom loc; let add, rem = @@ -89,7 +95,7 @@ let set_dom (heap : t) (loc : string) (dom : Expr.t option) : unit = Hashtbl.replace add loc dom; Hashtbl.remove rem loc -let set_met (heap : t) (loc : string) (met : Expr.t option) : unit = +let set_met (heap : t) (loc : loc_t) (met : Expr.t option) : unit = Hashtbl.remove heap.cmet loc; Hashtbl.remove heap.smet loc; let add, rem = @@ -115,24 +121,24 @@ let init () : t = sdom = Hashtbl.create big_tbl_size; cmet = Hashtbl.create big_tbl_size; smet = Hashtbl.create big_tbl_size; - cdmn = ref SS.empty; - sdmn = ref SS.empty; + cdmn = ref LocSet.empty; + sdmn = ref LocSet.empty; } (** Symbolic heap read heap(loc) *) -let get (heap : t) (loc : string) : s_object option = +let get (heap : t) (loc : loc_t) : s_object option = Option.map (fun sfvl -> ((sfvl, get_dom heap loc), get_met heap loc)) (get_fvl heap loc) (** Symbolic heap read heap(loc) with the normal new obj default *) -let get_with_default (heap : t) (loc : string) : s_object = +let get_with_default (heap : t) (loc : loc_t) : s_object = Option.value ~default:((SFVL.empty, None), None) (get heap loc) (** Symbolic heap set heap(loc) is assigned to fv_list *) let set (heap : t) - (loc : string) + (loc : loc_t) (fv_list : SFVL.t) (dom : Expr.t option) (metadata : Expr.t option) : unit = @@ -141,10 +147,10 @@ let set set_met heap loc metadata (** Symbolic heap put heap (loc, (perm, field)) is assigned to value *) -let set_fv_pair (heap : t) (loc : string) (field : Expr.t) (value : Expr.t) : +let set_fv_pair (heap : t) (loc : loc_t) (field : Expr.t) (value : Expr.t) : unit = - heap.cdmn := Var.Set.remove loc !(heap.cdmn); - heap.sdmn := Var.Set.remove loc !(heap.sdmn); + heap.cdmn := LocSet.remove loc !(heap.cdmn); + heap.sdmn := LocSet.remove loc !(heap.sdmn); let add, sadd, rem = if is_c field && is_c value then (heap.cfvl, heap.cdmn, heap.sfvl) else (heap.sfvl, heap.sdmn, heap.cfvl) @@ -157,14 +163,14 @@ let set_fv_pair (heap : t) (loc : string) (field : Expr.t) (value : Expr.t) : SFVL.remove field (Option.value ~default:SFVL.empty (Hashtbl.find_opt rem loc)) in - sadd := Var.Set.add loc !sadd; + sadd := LocSet.add loc !sadd; Hashtbl.replace add loc fvadd; if fvrem = SFVL.empty then Hashtbl.remove rem loc else Hashtbl.replace rem loc fvrem let init_object (heap : t) - (loc : string) + (loc : loc_t) ?is_empty:(ie = false) (mtdt : Expr.t option) : unit = if Hashtbl.mem heap.cfvl loc || Hashtbl.mem heap.sfvl loc then @@ -173,24 +179,24 @@ let init_object let dom : Expr.t option = if ie then None else Some (ESet []) in set heap loc SFVL.empty dom mtdt -let has_loc (heap : t) (loc : string) : bool = +let has_loc (heap : t) (loc : loc_t) : bool = Hashtbl.mem heap.cfvl loc || Hashtbl.mem heap.sfvl loc (** Removes the fv-list associated with --loc-- in --heap-- *) -let remove (heap : t) (loc : string) : unit = +let remove (heap : t) (loc : loc_t) : unit = Hashtbl.remove heap.cfvl loc; Hashtbl.remove heap.sfvl loc; Hashtbl.remove heap.cdom loc; Hashtbl.remove heap.sdom loc; Hashtbl.remove heap.cmet loc; Hashtbl.remove heap.smet loc; - heap.cdmn := Var.Set.remove loc !(heap.cdmn); - heap.sdmn := Var.Set.remove loc !(heap.sdmn) + heap.cdmn := LocSet.remove loc !(heap.cdmn); + heap.sdmn := LocSet.remove loc !(heap.sdmn) (** Retrieves the domain of --heap-- *) -let domain (heap : t) : SS.t = SS.union !(heap.cdmn) !(heap.sdmn) +let domain (heap : t) : LocSet.t = LocSet.union !(heap.cdmn) !(heap.sdmn) -let cdomain (heap : t) : SS.t = !(heap.cdmn) +let cdomain (heap : t) : LocSet.t = !(heap.cdmn) (** Returns a copy of --heap-- *) let copy (heap : t) : t = @@ -205,10 +211,10 @@ let copy (heap : t) : t = sdmn = ref !(heap.sdmn); } -let merge_loc (heap : t) (new_loc : string) (old_loc : string) : unit = +let merge_loc (heap : t) (new_loc : loc_t) (old_loc : loc_t) : unit = let domain = domain heap in let cfvl, sfvl, dom, met = - match SS.mem new_loc domain with + match LocSet.mem new_loc domain with | true -> (* Merge field-value lists *) let ocvfl, osfvl = @@ -258,7 +264,7 @@ let merge_loc (heap : t) (new_loc : string) (old_loc : string) : unit = (** Modifies --heap-- in place updating it to subst(heap) *) let substitution_in_place (subst : SSubst.t) (heap : t) : unit = (* If the substitution is empty, there is nothing to be done *) - if not (SSubst.domain subst None = Expr.Set.empty) then ( + if not (SSubst.domain subst = Expr.Set.empty) then ( (* The substitution is not empty *) let le_subst = SSubst.subst_in_expr subst ~partial:true in @@ -317,34 +323,27 @@ let substitution_in_place (subst : SSubst.t) (heap : t) : unit = SSubst.iter aloc_subst (fun aloc new_loc -> let aloc = match aloc with - | ALoc loc -> loc + | ALoc loc -> (loc :> loc_t) | _ -> raise (Failure "Impossible by construction") in let new_loc = match (new_loc : Expr.t) with - | Lit (Loc loc) -> loc - | ALoc loc -> loc + | Lit (Loc loc) -> (loc :> loc_t) + | ALoc loc -> (loc :> loc_t) | _ -> - raise - (Failure - (Printf.sprintf "Heap substitution fail for loc: %s" - ((Fmt.to_to_string Expr.pp) new_loc))) + Fmt.failwith "Heap substitution fail for loc: %a" Expr.pp new_loc in merge_loc heap new_loc aloc)) (** Returns the serialization of --heap-- as a list *) -let to_list (heap : t) : (string * s_object) list = +let to_list (heap : t) : (loc_t * s_object) list = let domain = domain heap in - SS.fold (fun loc ac -> (loc, Option.get (get heap loc)) :: ac) domain [] + LocSet.fold (fun loc ac -> (loc, Option.get (get heap loc)) :: ac) domain [] (** converts a symbolic heap to a list of assertions *) let assertions (heap : t) : Asrt.t = - let make_loc_lexpr loc = - if Names.is_aloc_name loc then Expr.ALoc loc else Expr.Lit (Loc loc) - in - let assertions_of_object (loc, ((fv_list, domain), metadata)) = - let le_loc = make_loc_lexpr loc in + let le_loc = Expr.loc_from_loc_name loc in let fv_assertions = SFVL.assertions le_loc fv_list in let domain = Option.fold @@ -361,7 +360,7 @@ let assertions (heap : t) : Asrt.t = to_list heap |> List.concat_map assertions_of_object |> List.sort Asrt.compare -let wf_assertions_of_obj (heap : t) (loc : string) : Expr.t list = +let wf_assertions_of_obj (heap : t) (loc : loc_t) : Expr.t list = let cfvl = Option.value ~default:SFVL.empty (Hashtbl.find_opt heap.cfvl loc) in @@ -376,7 +375,7 @@ let wf_assertions_of_obj (heap : t) (loc : string) : Expr.t list = let wf_assertions (heap : t) : Expr.t list = let domain = domain heap in - SS.fold (fun loc ac -> wf_assertions_of_obj heap loc @ ac) domain [] + LocSet.fold (fun loc ac -> wf_assertions_of_obj heap loc @ ac) domain [] let is_well_formed (heap : t) : unit = let cfvl = @@ -397,39 +396,34 @@ let is_well_formed (heap : t) : unit = if not sfvl then raise (Failure "Concreteness in the symbolic part of the heap"); let dom_kept = domain heap in - let dom_calc_1 = - SS.union - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.cfvl SS.empty) - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.sfvl SS.empty) + let fold cset sset = + LocSet.union + (Hashtbl.fold (fun v _ ac -> LocSet.add v ac) cset LocSet.empty) + (Hashtbl.fold (fun v _ ac -> LocSet.add v ac) sset LocSet.empty) in - let dom_calc_2 = - SS.union - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.cdom SS.empty) - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.sdom SS.empty) - in - let dom_calc_3 = - SS.union - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.cmet SS.empty) - (Hashtbl.fold (fun v _ ac -> SS.add v ac) heap.smet SS.empty) - in - let dom_calc = SS.union dom_calc_1 (SS.union dom_calc_2 dom_calc_3) in - if SS.elements dom_kept <> SS.elements dom_calc then + let dom_calc_1 = fold heap.cfvl heap.sfvl in + let dom_calc_2 = fold heap.cdom heap.sdom in + let dom_calc_3 = fold heap.cmet heap.smet in + let dom_calc = LocSet.union dom_calc_1 (LocSet.union dom_calc_2 dom_calc_3) in + if LocSet.elements dom_kept <> LocSet.elements dom_calc then let msg = - Printf.sprintf "Domain mismatch:\n%s\n%s" - (String.concat ", " (SS.elements dom_kept)) - (String.concat ", " (SS.elements dom_calc)) + Fmt.str "Domain mismatch:\n%a\n%a" + Fmt.(iter ~sep:comma LocSet.iter Id.pp) + dom_kept + Fmt.(iter ~sep:comma LocSet.iter Id.pp) + dom_calc in L.fail msg let pp ft heap = let open Fmt in - let sorted_locs = SS.elements (domain heap) in + let sorted_locs = LocSet.elements (domain heap) in let sorted_locs_with_vals = List.map (fun loc -> (loc, Option.get (get heap loc))) sorted_locs in let pp_one ft (loc, ((fv_pairs, domain), metadata)) = - pf ft "@[%s |-> [ @[%a@] | @[%a@] ] with metadata %a@]" loc SFVL.pp fv_pairs - (option Expr.pp) domain + pf ft "@[%a |-> [ @[%a@] | @[%a@] ] with metadata %a@]" Id.pp loc SFVL.pp + fv_pairs (option Expr.pp) domain (option ~none:(any "unknown") Expr.pp) metadata in @@ -438,29 +432,31 @@ let pp ft heap = let get_print_info locs heap = let domain = domain heap in let metadata_locs = - SS.fold + LocSet.fold (fun loc locs -> match get_met heap loc with - | (Some (Lit (Loc x)) | Some (ALoc x)) when SS.mem x domain -> - SS.add x locs + | Some (Lit (Loc x)) when LocSet.mem (x :> loc_t) domain -> + LocSet.add (x :> loc_t) locs + | Some (ALoc x) when LocSet.mem (x :> loc_t) domain -> + LocSet.add (x :> loc_t) locs | _ -> locs) - locs SS.empty + locs LocSet.empty in (* TODO: Traverse locations and collect info about other locations and lvars *) - (SS.empty, metadata_locs) + (LVar.Set.empty, metadata_locs) let pp_by_need locs ft heap = let domain = domain heap in - let existent_locs = SS.inter locs domain in + let existent_locs = LocSet.inter locs domain in let sorted_locs_with_vals = List.map (fun loc -> (loc, Option.get (get heap loc))) - (SS.elements existent_locs) + (LocSet.elements existent_locs) in let open Fmt in let pp_one ft (loc, ((fv_pairs, domain), metadata)) = - pf ft "@[%s |-> [ @[%a@] | @[%a@] ] with metadata %a@]" loc SFVL.pp fv_pairs - (option Expr.pp) domain + pf ft "@[%a |-> [ @[%a@] | @[%a@] ] with metadata %a@]" Id.pp loc SFVL.pp + fv_pairs (option Expr.pp) domain (option ~none:(any "unknown") Expr.pp) metadata in @@ -474,9 +470,7 @@ let get_inv_metadata (heap : t) : (Expr.t, Expr.t) Hashtbl.t = match e_metadata with | None -> () | Some e_metadata -> - let loc_e = - if Names.is_lloc_name loc then Expr.Lit (Loc loc) else ALoc loc - in + let loc_e = Expr.loc_from_loc_name loc in Hashtbl.add inv_metadata e_metadata loc_e) mt in @@ -485,7 +479,7 @@ let get_inv_metadata (heap : t) : (Expr.t, Expr.t) Hashtbl.t = inv_metadata let clean_up (heap : t) : unit = - SS.iter + LocSet.iter (fun loc -> match has_loc heap loc with | false -> () @@ -495,42 +489,32 @@ let clean_up (heap : t) : unit = | true, None -> ( remove heap loc; match met with - | Some (ALoc loc) | Some (Lit (Loc loc)) -> remove heap loc + | Some (ALoc loc) -> remove heap (loc :> loc_t) + | Some (Lit (Loc loc)) -> remove heap (loc :> loc_t) | _ -> ()) | _, _ -> ())) (domain heap) -let lvars (heap : t) : Var.Set.t = - let lvars_fvl = - Hashtbl.fold - (fun _ fvl ac -> Var.Set.union (SFVL.lvars fvl) ac) - heap.sfvl Var.Set.empty - in - let lvars_dom = - Hashtbl.fold - (fun _ oe ac -> - let voe = Option.fold ~some:Expr.lvars ~none:Var.Set.empty oe in - Var.Set.union voe ac) - heap.sdom Var.Set.empty - in - let lvars_met = - Hashtbl.fold - (fun _ oe ac -> - let voe = Option.fold ~some:Expr.lvars ~none:Var.Set.empty oe in - Var.Set.union voe ac) - heap.smet Var.Set.empty - in - List.fold_left SS.union Var.Set.empty [ lvars_fvl; lvars_met; lvars_dom ] +let lvars (heap : t) : LVar.Set.t = + LVar.Set.empty + |> Hashtbl.fold (fun _ fvl ac -> LVar.Set.union (SFVL.lvars fvl) ac) heap.sfvl + |> Hashtbl.fold + (fun _ oe -> + LVar.Set.union @@ Option.fold ~some:Expr.lvars ~none:LVar.Set.empty oe) + heap.sdom + |> Hashtbl.fold + (fun _ oe -> + LVar.Set.union @@ Option.fold ~some:Expr.lvars ~none:LVar.Set.empty oe) + heap.smet -let alocs (heap : t) : Var.Set.t = - let union = Var.Set.union in - Var.Set.empty - |> Hashtbl.fold (fun _ fvl ac -> Var.Set.union (SFVL.alocs fvl) ac) heap.sfvl +let alocs (heap : t) : ALoc.Set.t = + ALoc.Set.empty + |> Hashtbl.fold (fun _ fvl ac -> ALoc.Set.union (SFVL.alocs fvl) ac) heap.sfvl |> Hashtbl.fold - (fun _ oe ac -> - Option.fold ~some:(fun oe -> union (Expr.alocs oe) ac) ~none:ac oe) + (fun _ oe -> + ALoc.Set.union @@ Option.fold ~some:Expr.alocs ~none:ALoc.Set.empty oe) heap.sdom |> Hashtbl.fold - (fun _ oe ac -> - Option.fold ~some:(fun oe -> union (Expr.alocs oe) ac) ~none:ac oe) + (fun _ oe -> + ALoc.Set.union @@ Option.fold ~some:Expr.alocs ~none:ALoc.Set.empty oe) heap.smet diff --git a/Gillian-JS/lib/Test262/Test262_expectations_helper.ml b/Gillian-JS/lib/Test262/Test262_expectations_helper.ml index 2ff09bace..0b0d7de6f 100644 --- a/Gillian-JS/lib/Test262/Test262_expectations_helper.ml +++ b/Gillian-JS/lib/Test262/Test262_expectations_helper.ml @@ -54,7 +54,7 @@ let error_has_proto str ret_val ret_state = get_cell ret_state md proto_name in match final_proto with - | Some (Loc s) when String.equal s str -> true + | Some (Loc s) when String.equal (Gil_syntax.Loc.str s) str -> true | _ -> false let is_syntax_error = error_has_proto "$lserr_proto" diff --git a/Gillian-JS/lib/utils/js_generators.ml b/Gillian-JS/lib/utils/js_generators.ml index 5d9d868ee..1f0ec5f9f 100644 --- a/Gillian-JS/lib/utils/js_generators.ml +++ b/Gillian-JS/lib/utils/js_generators.ml @@ -10,6 +10,8 @@ let fresh_sth (name : string) : (unit -> string) * (unit -> unit) = let fresh_lvar, reset_lvar = fresh_sth "_lvar_js_" let fresh_pvar, reset_pvar = fresh_sth "pvar_js_" +let fresh_lvar () = Gil_syntax.LVar.of_string (fresh_lvar ()) +let fresh_pvar () = Gil_syntax.Var.of_string (fresh_pvar ()) let reset () = reset_lvar (); diff --git a/GillianCore/GIL_Syntax/ALoc.ml b/GillianCore/GIL_Syntax/ALoc.ml deleted file mode 100644 index 7bedc5948..000000000 --- a/GillianCore/GIL_Syntax/ALoc.ml +++ /dev/null @@ -1,8 +0,0 @@ -open Allocators - -include - Make_with_prefix - (Basic ()) - (struct - let prefix = Names.aloc_prefix - end) diff --git a/GillianCore/GIL_Syntax/ALoc.mli b/GillianCore/GIL_Syntax/ALoc.mli deleted file mode 100644 index cc065732b..000000000 --- a/GillianCore/GIL_Syntax/ALoc.mli +++ /dev/null @@ -1 +0,0 @@ -include Allocators.S with type t = string diff --git a/GillianCore/GIL_Syntax/Asrt.ml b/GillianCore/GIL_Syntax/Asrt.ml index 2450fa3d5..e0fffe66a 100644 --- a/GillianCore/GIL_Syntax/Asrt.ml +++ b/GillianCore/GIL_Syntax/Asrt.ml @@ -1,3 +1,5 @@ +open Id + (** {b GIL logic assertions}. *) type atom = TypeDef__.assertion_atom = | Emp (** Empty heap *) @@ -44,7 +46,7 @@ let prioritise (a1 : atom) (a2 : atom) = | PVar _, _ -> -1 | _, PVar _ -> 1 | LVar v, LVar v' -> ( - match (Names.is_spec_var_name v, Names.is_spec_var_name v') with + match (Id.LVar.is_spec_var_name v, Id.LVar.is_spec_var_name v') with | true, true -> 0 | true, false -> -1 | false, true -> 1 @@ -84,20 +86,24 @@ let map (f_e : Expr.t -> Expr.t) : t -> t = }) (* Get all the logical variables in --a-- *) -let lvars : t -> SS.t = - Visitors.Collectors.lvar_collector#visit_assertion SS.empty +let lvars : t -> LVar.Set.t = + Visitors.Collectors.lvar_collector#visit_assertion LVar.Set.empty (* Get all the program variables in --a-- *) -let pvars : t -> SS.t = Visitors.Collectors.pvar_collector#visit_assertion () +let pvars : t -> Var.Set.t = + Visitors.Collectors.pvar_collector#visit_assertion () (* Get all the abstract locations in --a-- *) -let alocs : t -> SS.t = Visitors.Collectors.aloc_collector#visit_assertion () +let alocs : t -> ALoc.Set.t = + Visitors.Collectors.aloc_collector#visit_assertion () (* Get all the concrete locations in [a] *) -let clocs : t -> SS.t = Visitors.Collectors.cloc_collector#visit_assertion () +let clocs : t -> Loc.Set.t = + Visitors.Collectors.cloc_collector#visit_assertion () -(* Get all the concrete locations in [a] *) -let locs : t -> SS.t = Visitors.Collectors.loc_collector#visit_assertion () +(* Get all the abstract and concrete locations in [a] *) +let locs : t -> Sets.LocSet.t = + Visitors.Collectors.loc_collector#visit_assertion () (* Returns a list with the names of the predicates that occur in --a-- *) let pred_names : t -> string list = @@ -169,7 +175,7 @@ let pp_atom_full = _pp_atom ~e_pp:Expr.full_pp let pp = _pp ~e_pp:Expr.pp let full_pp = _pp ~e_pp:Expr.full_pp -let subst_clocs (subst : string -> Expr.t) : t -> t = +let subst_clocs (subst : Id.Loc.t -> Expr.t) : t -> t = map (Expr.subst_clocs subst) let subst_expr_for_expr ~(to_subst : Expr.t) ~(subst_with : Expr.t) : t -> t = diff --git a/GillianCore/GIL_Syntax/Cmd.ml b/GillianCore/GIL_Syntax/Cmd.ml index 7c91a41ab..c630ae7af 100644 --- a/GillianCore/GIL_Syntax/Cmd.ml +++ b/GillianCore/GIL_Syntax/Cmd.ml @@ -5,83 +5,87 @@ (**************************************************************) (**************************************************************) -module SS = Containers.SS +open Id -type logic_bindings_t = string * (string * Expr.t) list [@@deriving yojson] +type logic_bindings_t = string * (Id.LVar.t * Expr.t) list [@@deriving yojson] type 'label t = 'label TypeDef__.cmd = | Skip (** Skip *) - | Assignment of string * Expr.t (** Assignment *) - | LAction of string * string * Expr.t list (** Local Actions *) + | Assignment of Var.t * Expr.t (** Assignment *) + | LAction of Var.t * string * Expr.t list (** Local Actions *) | Logic of LCmd.t (** GIL Logic commands *) | Goto of 'label (** Unconditional goto *) | GuardedGoto of Expr.t * 'label * 'label (** Conditional goto *) | Call of - string * Expr.t * Expr.t list * 'label option * logic_bindings_t option + Var.t * Expr.t * Expr.t list * 'label option * logic_bindings_t option (** Procedure call *) - | ECall of string * Expr.t * Expr.t list * 'label option + | ECall of Var.t * Expr.t * Expr.t list * 'label option (** External Procedure call *) - | Apply of string * Expr.t * 'label option + | Apply of Var.t * Expr.t * 'label option (** Application-style procedure call *) - | Arguments of string (** Arguments of the current function *) - | PhiAssignment of (string * Expr.t list) list (** PHI assignment *) + | Arguments of Var.t (** Arguments of the current function *) + | PhiAssignment of (Var.t * Expr.t list) list (** PHI assignment *) | ReturnNormal (** Normal return *) | ReturnError (** Error return *) | Fail of string * Expr.t list (** Failure *) [@@deriving yojson] let equal = TypeDef__.equal_cmd -let fold = List.fold_left SS.union SS.empty -let pvars (cmd : 'label t) : SS.t = +let pvars (cmd : 'label t) : Var.Set.t = + let fold = List.fold_left Var.Set.union Var.Set.empty in let pvars_es es = fold (List.map Expr.pvars es) in match cmd with - | Skip -> SS.empty - | Assignment (x, e) -> SS.add x (Expr.pvars e) - | LAction (x, _, es) -> SS.add x (pvars_es es) + | Skip -> Var.Set.empty + | Assignment (x, e) -> Var.Set.add x (Expr.pvars e) + | LAction (x, _, es) -> Var.Set.add x (pvars_es es) | Logic lcmd -> LCmd.pvars lcmd - | Goto _ -> SS.empty + | Goto _ -> Var.Set.empty | GuardedGoto (e, _, _) -> Expr.pvars e - | Call (x, e, es, _, _) -> SS.union (SS.add x (Expr.pvars e)) (pvars_es es) - | ECall (x, e, es, _) -> SS.union (SS.add x (Expr.pvars e)) (pvars_es es) - | Apply (x, e, _) -> SS.add x (Expr.pvars e) - | Arguments x -> SS.singleton x + | Call (x, e, es, _, _) -> + Var.Set.union (Var.Set.add x (Expr.pvars e)) (pvars_es es) + | ECall (x, e, es, _) -> + Var.Set.union (Var.Set.add x (Expr.pvars e)) (pvars_es es) + | Apply (x, e, _) -> Var.Set.add x (Expr.pvars e) + | Arguments x -> Var.Set.singleton x | PhiAssignment phis -> fold (List.map (fun (_, es) -> pvars_es es) phis) - | ReturnNormal | ReturnError -> SS.singleton "ret" + | ReturnNormal | ReturnError -> Var.Set.singleton "ret" | Fail (_, es) -> pvars_es es -let lvars (cmd : 'label t) : SS.t = +let lvars (cmd : 'label t) : LVar.Set.t = + let fold = List.fold_left LVar.Set.union LVar.Set.empty in let lvars_es es = fold (List.map Expr.lvars es) in match cmd with - | Skip -> SS.empty + | Skip -> LVar.Set.empty | Assignment (_, e) -> Expr.lvars e | LAction (_, _, es) -> lvars_es es | Logic lcmd -> LCmd.lvars lcmd - | Goto _ -> SS.empty + | Goto _ -> LVar.Set.empty | GuardedGoto (e, _, _) -> Expr.lvars e - | Call (_, e, es, _, _) -> SS.union (Expr.lvars e) (lvars_es es) - | ECall (_, e, es, _) -> SS.union (Expr.lvars e) (lvars_es es) + | Call (_, e, es, _, _) -> LVar.Set.union (Expr.lvars e) (lvars_es es) + | ECall (_, e, es, _) -> LVar.Set.union (Expr.lvars e) (lvars_es es) | Apply (_, e, _) -> Expr.lvars e - | Arguments _ -> SS.empty + | Arguments _ -> LVar.Set.empty | PhiAssignment phis -> fold (List.map (fun (_, es) -> lvars_es es) phis) - | ReturnNormal | ReturnError -> SS.empty + | ReturnNormal | ReturnError -> LVar.Set.empty | Fail (_, es) -> lvars_es es -let locs (cmd : 'label t) : SS.t = +let locs (cmd : 'label t) : Sets.LocSet.t = + let fold = List.fold_left Sets.LocSet.union Sets.LocSet.empty in let locs_es es = fold (List.map Expr.locs es) in match cmd with - | Skip -> SS.empty + | Skip -> Sets.LocSet.empty | Assignment (_, e) -> Expr.locs e | LAction (_, _, es) -> locs_es es - | Logic lcmd -> LCmd.lvars lcmd - | Goto _ -> SS.empty + | Logic lcmd -> LCmd.locs lcmd + | Goto _ -> Sets.LocSet.empty | GuardedGoto (e, _, _) -> Expr.locs e - | Call (_, e, es, _, _) -> SS.union (Expr.lvars e) (locs_es es) - | ECall (_, e, es, _) -> SS.union (Expr.lvars e) (locs_es es) + | Call (_, e, es, _, _) -> Sets.LocSet.union (Expr.locs e) (locs_es es) + | ECall (_, e, es, _) -> Sets.LocSet.union (Expr.locs e) (locs_es es) | Apply (_, e, _) -> Expr.locs e - | Arguments _ -> SS.empty + | Arguments _ -> Sets.LocSet.empty | PhiAssignment phis -> fold (List.map (fun (_, es) -> locs_es es) phis) - | ReturnNormal | ReturnError -> SS.empty + | ReturnNormal | ReturnError -> Sets.LocSet.empty | Fail (_, es) -> locs_es es let successors (cmd : int t) (i : int) : int list = diff --git a/GillianCore/GIL_Syntax/Expr.ml b/GillianCore/GIL_Syntax/Expr.ml index 650e2b70e..6674c6498 100644 --- a/GillianCore/GIL_Syntax/Expr.ml +++ b/GillianCore/GIL_Syntax/Expr.ml @@ -1,9 +1,10 @@ open Names +open Id (** GIL Expressions *) type t = TypeDef__.expr = | Lit of Literal.t (** GIL literals *) - | PVar of string (** GIL program variables *) + | PVar of Var.t (** GIL program variables *) | LVar of LVar.t (** GIL logical variables *) | ALoc of string (** GIL abstract locations *) | UnOp of UnOp.t * t (** Unary operators *) @@ -12,9 +13,9 @@ type t = TypeDef__.expr = | NOp of NOp.t * t list (** n-ary operators *) | EList of t list (** Lists of expressions *) | ESet of t list (** Sets of expressions *) - | Exists of (string * Type.t option) list * t + | Exists of (LVar.t * Type.t option) list * t (** Existential quantification. *) - | ForAll of (string * Type.t option) list * t + | ForAll of (LVar.t * Type.t option) list * t (** Universal quantification. *) [@@deriving eq, ord] @@ -447,19 +448,17 @@ let to_literal = function | _ -> None (** Get all the logical variables in --e-- *) -let lvars : t -> SS.t = Visitors.Collectors.lvar_collector#visit_expr SS.empty +let lvars : t -> LVar.Set.t = + Visitors.Collectors.lvar_collector#visit_expr LVar.Set.empty (** Get all the abstract locations in --e-- *) -let alocs : t -> SS.t = Visitors.Collectors.aloc_collector#visit_expr () +let alocs : t -> ALoc.Set.t = Visitors.Collectors.aloc_collector#visit_expr () (** Get all the concrete locations in --e-- *) -let clocs : t -> SS.t = Visitors.Collectors.cloc_collector#visit_expr () +let clocs : t -> Loc.Set.t = Visitors.Collectors.cloc_collector#visit_expr () -let locs : t -> SS.t = Visitors.Collectors.loc_collector#visit_expr () - -(** Get all substitutables in --e-- *) -let substitutables : t -> SS.t = - Visitors.Collectors.substitutable_collector#visit_expr () +(** Get all the concrete and abstract locations in --e-- *) +let locs : t -> Sets.LocSet.t = Visitors.Collectors.loc_collector#visit_expr () let rec is_concrete (le : t) : bool = let f = is_concrete in @@ -481,9 +480,6 @@ let is_concrete_zero_i : t -> bool = function | Lit (Int z) -> Z.equal Z.zero z | _ -> false -(** Get all the variables in --e-- *) -let vars : t -> SS.t = Visitors.Collectors.var_collector#visit_expr () - (** Are all expressions in the list literals? *) let all_literals = List.for_all (function @@ -501,14 +497,14 @@ let rec from_lit_list (lit : Literal.t) : t = let lists (le : t) : t list = Visitors.Collectors.list_collector#visit_expr () le -let subst_clocs (subst : string -> t) (e : t) : t = - (new Visitors.Substs.subst_clocs subst)#visit_expr () e +let subst_clocs (subst : Id.Loc.t -> t) : t -> t = + (new Visitors.Substs.subst_clocs subst)#visit_expr () -let from_var_name (var_name : string) : t = - if is_aloc_name var_name then ALoc var_name - else if is_lvar_name var_name then LVar var_name - else if is_pvar_name var_name then PVar var_name - else Fmt.failwith "Invalid var name : %s" var_name +let var_to_expr (x : [< Id.substable ] Id.t) : t = + if Names.is_lvar_name x then LVar x + else if is_aloc_name x then ALoc x + else if is_pvar_name x then PVar x + else raise (Failure ("var_to_expr: Impossible matchable: " ^ x)) let loc_from_loc_name (loc_name : string) : t = if is_aloc_name loc_name then ALoc loc_name else Lit (Loc loc_name) @@ -585,13 +581,7 @@ let base_elements (expr : t) : t list = in v#visit_expr () expr -let pvars : t -> SS.t = Visitors.Collectors.pvar_collector#visit_expr () - -let var_to_expr (x : string) : t = - if Names.is_lvar_name x then LVar x - else if is_aloc_name x then ALoc x - else if is_pvar_name x then PVar x - else raise (Failure ("var_to_expr: Impossible matchable: " ^ x)) +let pvars : t -> Var.Set.t = Visitors.Collectors.pvar_collector#visit_expr () let is_matchable = function | PVar _ | LVar _ | ALoc _ | UnOp (LstLen, PVar _) | UnOp (LstLen, LVar _) -> diff --git a/GillianCore/GIL_Syntax/Gil_syntax.ml b/GillianCore/GIL_Syntax/Gil_syntax.ml index 656d59030..15a0eef43 100644 --- a/GillianCore/GIL_Syntax/Gil_syntax.ml +++ b/GillianCore/GIL_Syntax/Gil_syntax.ml @@ -1,4 +1,4 @@ -module ALoc = ALoc +module ALoc = Id.ALoc module Annot = Annot module Asrt = Asrt module BinOp = BinOp @@ -8,11 +8,13 @@ module Cmd = Cmd module Constant = Constant module Expr = Expr module Flag = Flag +module Id = Id module LCmd = LCmd module Lemma = Lemma module Literal = Literal +module Loc = Id.Loc module Location = Location -module LVar = LVar +module LVar = Id.LVar module Macro = Macro module NOp = NOp module Pred = Pred @@ -22,5 +24,5 @@ module SLCmd = SLCmd module Spec = Spec module Type = Type module UnOp = UnOp -module Var = Var +module Var = Id.Var module Visitors = Visitors diff --git a/GillianCore/GIL_Syntax/Gil_syntax.mli b/GillianCore/GIL_Syntax/Gil_syntax.mli index 9227ab7af..133b9067b 100644 --- a/GillianCore/GIL_Syntax/Gil_syntax.mli +++ b/GillianCore/GIL_Syntax/Gil_syntax.mli @@ -1,42 +1,105 @@ -(** @canonical Gillian.Gil_syntax.Location *) -module Location : sig - (** Representation of a location in a source file *) +module Id : sig + type +'a t + and loc = [ `Loc ] + and aloc = [ `ALoc ] + and var = [ `Var ] + and lvar = [ `LVar ] [@@deriving yojson] + + type any_var = [ var | lvar ] + and any_loc = [ loc | aloc ] + and any = [ loc | aloc | var | lvar ] + and substable = [ aloc | var | lvar ] [@@deriving yojson] + + val return_variable : var t + val str : 'a t -> string + val equal : 'a t -> 'b t -> bool + val compare : 'a t -> 'a t -> int + val pp : 'a t Fmt.t + val of_yojson' : Yojson.Safe.t -> ('a t, string) result + val to_yojson' : 'a t -> Yojson.Safe.t + val as_lvars : any_var t list -> lvar t list option + val as_aloc : any_loc t -> aloc t option + + module type SetYoJson := sig + include Set.S + + val to_yojson : t -> Yojson.Safe.t + val of_yojson : Yojson.Safe.t -> (t, string) result + end - type position = { pos_line : int; pos_column : int } [@@deriving yojson] + module type Id := sig + (** @inline *) + include Allocators.S_with_stringify - type t = { loc_start : position; loc_end : position; loc_source : string } - [@@deriving yojson, eq] + module Set : SetYoJson with type elt = t + end - val none : t - val pp : t Fmt.t - val pp_log_opt : Format.formatter -> t option -> unit -end + (** @canonical Gillian.Gil_syntax.Id.Loc + Allocator for GIL concrete locations *) + module Loc : Id with type t = loc t -(** @canonical Gillian.Gil_syntax.LVar *) -module LVar : sig - (** Allocator for logical variable names *) + (** @canonical Gillian.Gil_syntax.Id.ALoc + Allocator for GIL abstract locations *) + module ALoc : Id with type t = aloc t - (** @inline *) - include Allocators.S with type t = string -end + (** @canonical Gillian.Gil_syntax.Id.Var + Allocator for GIL concrete variables *) + module Var : Id with type t = var t -(** @canonical Gillian.Gil_syntax.ALoc *) -module ALoc : sig - (** Allocator for (sybolic) memory locations *) + (** @canonical Gillian.Gil_syntax.Id.LVar + Allocator for GIL logical variables *) + module LVar : sig + include Id with type t = lvar t + + val is_spec_var_name : t -> bool + end - (** @inline *) - include Allocators.S with type t = string + module Sets : sig + (** Set of substitutable identifiers *) + module SubstSet : SetYoJson with type elt = substable t + + (** Set of concrete and abstract locations *) + module LocSet : SetYoJson with type elt = any_loc t + + (** Set of program and logical variables *) + module VarSet : SetYoJson with type elt = any_var t + + val pvar_to_varset : Var.Set.t -> VarSet.t + val lvar_to_varset : LVar.Set.t -> VarSet.t + val pvar_to_subst : Var.Set.t -> SubstSet.t + val lvar_to_subst : LVar.Set.t -> SubstSet.t + val aloc_to_subst : ALoc.Set.t -> SubstSet.t + val aloc_to_loc : ALoc.Set.t -> LocSet.t + + (** @deprecated *) + val substset_to_lvar : SubstSet.t -> LVar.Set.t + end end +(** @canonical Gillian.Gil_syntax.Loc *) +module Loc = Id.Loc + +(** @canonical Gillian.Gil_syntax.ALoc *) +module ALoc = Id.ALoc + (** @canonical Gillian.Gil_syntax.Var *) -module Var : sig - (** GIL Variables *) +module Var = Id.Var - type t = string [@@deriving yojson, show] +(** @canonical Gillian.Gil_syntax.LVar *) +module LVar = Id.LVar + +(** @canonical Gillian.Gil_syntax.Location *) +module Location : sig + (** Representation of a location in a source file *) - module Set : module type of Containers.SS + type position = { pos_line : int; pos_column : int } [@@deriving yojson] - val str : t -> string + type t = { loc_start : position; loc_end : position; loc_source : string } + [@@deriving yojson, eq] + + val none : t + val pp : t Fmt.t + val pp_log_opt : Format.formatter -> t option -> unit end (** @canonical Gillian.Gil_syntax.Constant *) @@ -97,7 +160,7 @@ module Literal : sig | Int of Z.t (** GIL integers: TODO: understand size *) | Num of float (** GIL floats - double-precision 64-bit IEEE 754 *) | String of string (** GIL strings *) - | Loc of string (** GIL locations (uninterpreted symbols) *) + | Loc of Loc.t (** GIL locations (uninterpreted symbols) *) | Type of Type.t (** GIL types ({!type:Type.t}) *) | LList of t list (** Lists of GIL literals *) | Nono (** Negative information *) @@ -252,18 +315,18 @@ module Expr : sig type t = | Lit of Literal.t (** GIL literals *) - | PVar of string (** GIL program variables *) - | LVar of string (** GIL logical variables (interpreted symbols) *) - | ALoc of string (** GIL abstract locations (uninterpreted symbols) *) + | PVar of Var.t (** GIL program variables *) + | LVar of LVar.t (** GIL logical variables (interpreted symbols) *) + | ALoc of ALoc.t (** GIL abstract locations (uninterpreted symbols) *) | UnOp of UnOp.t * t (** Unary operators ({!type:UnOp.t}) *) | BinOp of t * BinOp.t * t (** Binary operators ({!type:BinOp.t}) *) | LstSub of t * t * t (** Sublist *) | NOp of NOp.t * t list (** n-ary operators ({!type:NOp.t}) *) | EList of t list (** Lists of expressions *) | ESet of t list (** Sets of expressions *) - | Exists of (string * Type.t option) list * t + | Exists of (LVar.t * Type.t option) list * t (** Existential quantification. *) - | ForAll of (string * Type.t option) list * t + | ForAll of (LVar.t * Type.t option) list * t [@@deriving yojson] (** {2: Helpers for building expressions} @@ -336,7 +399,7 @@ module Expr : sig (** Booleans *) val not : t -> t - val forall : (string * Type.t option) list -> t -> t + val forall : (LVar.t * Type.t option) list -> t -> t val ( == ) : t -> t -> t val ( && ) : t -> t -> t val ( || ) : t -> t -> t @@ -377,22 +440,19 @@ module Expr : sig val from_list : t list -> t (** [lvars e] returns all logical variables in [e] *) - val lvars : t -> SS.t + val lvars : t -> LVar.Set.t (** [pvars e] returns all program variables in [e] *) - val pvars : t -> SS.t + val pvars : t -> Var.Set.t (** [alocs e] returns all abstract locations in [e] *) - val alocs : t -> SS.t + val alocs : t -> ALoc.Set.t (** [clocs e] returns all concrete locations in [e] *) - val clocs : t -> SS.t + val clocs : t -> Loc.Set.t (** [locs e] returns all concrete and abstract locations in [e] *) - val locs : t -> SS.t - - (** [vars e] returns all variables in [e] (includes lvars, pvars, alocs and clocs) *) - val vars : t -> SS.t + val locs : t -> Id.Sets.LocSet.t (** [push_in_negations e] pushes all negations in e "downwards", recursively *) val push_in_negations : t -> t @@ -403,9 +463,6 @@ module Expr : sig (** Returns if this expression is a boolean expression, recursively. *) val is_boolean_expr : t -> bool - (** [substitutables e] returns all lvars and alocs *) - val substitutables : t -> SS.t - (** [is_concrete e] returns [true] iff the expression contains no lvar or aloc *) val is_concrete : t -> bool @@ -419,14 +476,10 @@ module Expr : sig val lists : t -> t list (** [subst_clocs subst e] substitutes expressions of the form [Lit (Loc l)] with [subst l] in [e] *) - val subst_clocs : (string -> t) -> t -> t - - (** [from_var_name var] returns either an aloc, an lvar or a pvar if [var] name matches one of these types - (see {!Utils.Names.is_aloc_name}, {!Utils.Names.is_lvar_name} and {!Utils.Names.is_pvar_name}) *) - val from_var_name : string -> t + val subst_clocs : (Id.loc Id.t -> t) -> t -> t - (** [loc_from_loc_name loc] Has the same behaviour as [from_var_name] except that it returns either an [ALoc loc] or a [Lit (Loc loc)] *) - val loc_from_loc_name : string -> t + (** [loc_from_loc_name loc] Has the same behaviour as [var_to_expr] except that it returns either an [ALoc loc] or a [Lit (Loc loc)] *) + val loc_from_loc_name : [< Id.any_loc ] Id.t -> t (** [subst_expr_for_expr ~to_subst ~subst_with expr] substitutes every occurence of the expression [to_subst] with the expression [subst_with] in [expr] *) val subst_expr_for_expr : to_subst:t -> subst_with:t -> t -> t @@ -435,8 +488,9 @@ module Expr : sig abstract locations, and non-list literals in [e] *) val base_elements : t -> t list - (** [var_to_expr x] returns the expression representing the program/logical variable or abstract location [x] *) - val var_to_expr : string -> t + (** [var_to_expr x] returns the expression representing the program/logical variable or abstract location [x] + (see {!Utils.Names.is_aloc_name}, {!Utils.Names.is_lvar_name} and {!Utils.Names.is_pvar_name}) *) + val var_to_expr : [< Id.substable ] Id.t -> t (** [is_matchable x] returns whether or not the expression [e] is matchable *) val is_matchable : t -> bool @@ -471,19 +525,19 @@ module Asrt : sig val map : (Expr.t -> Expr.t) -> t -> t (** Get all the logical variables in [a] *) - val lvars : t -> SS.t + val lvars : t -> LVar.Set.t (** Get all the program variables in [a] *) - val pvars : t -> SS.t + val pvars : t -> Var.Set.t (** Get all the abstract locations in [a] *) - val alocs : t -> SS.t + val alocs : t -> ALoc.Set.t (** Get all the concrete locations in [a] *) - val clocs : t -> SS.t + val clocs : t -> Loc.Set.t (** Get all locations in [a] *) - val locs : t -> SS.t + val locs : t -> Id.Sets.LocSet.t (** Returns a list with the names of the predicates that occur in [a] *) val pred_names : t -> string list @@ -510,7 +564,7 @@ module Asrt : sig val pp_atom_full : Format.formatter -> atom -> unit (** [subst_clocs subst a] Substitutes expressions of the form [Lit (Loc l)] with [subst l] in [a] *) - val subst_clocs : (string -> Expr.t) -> t -> t + val subst_clocs : (Id.Loc.t -> Expr.t) -> t -> t (** [subst_expr_for_expr ~to_subst ~subst_with a] substitutes every occurence of the expression [to_subst] with the expression [subst_with] in [a] *) val subst_expr_for_expr : to_subst:Expr.t -> subst_with:Expr.t -> t -> t @@ -523,18 +577,21 @@ end module SLCmd : sig (** GIL Separation-Logic Commands *) + type logic_bindings_t := string * (LVar.t * Expr.t) list + type t = - | Fold of string * Expr.t list * (string * (string * Expr.t) list) option + | Fold of string * Expr.t list * logic_bindings_t option (** Fold predicate *) - | Unfold of string * Expr.t list * (string * string) list option * bool + | Unfold of string * Expr.t list * (LVar.t * LVar.t) list option * bool (** Unfold predicate *) | Package of { lhs : string * Expr.t list; rhs : string * Expr.t list } (** Magic wand packaging *) | GUnfold of string (** Global Unfold *) - | ApplyLem of string * Expr.t list * string list (** Apply lemma *) - | SepAssert of Asrt.t * string list (** Assert *) - | Invariant of Asrt.t * string list (** Invariant *) - | Consume of Asrt.t * string list + | ApplyLem of string * Expr.t list * Id.any_var Id.t list + (** Apply lemma *) + | SepAssert of Asrt.t * Id.any_var Id.t list (** Assert *) + | Invariant of Asrt.t * Id.any_var Id.t list (** Invariant *) + | Consume of Asrt.t * Id.any_var Id.t list | Produce of Asrt.t | SymbExec @@ -542,9 +599,9 @@ module SLCmd : sig val map : (Asrt.t -> Asrt.t) -> (Expr.t -> Expr.t) -> t -> t (** Pretty-printer of folding info *) - val pp_folding_info : (string * (string * Expr.t) list) option Fmt.t + val pp_folding_info : Cmd.logic_bindings_t option Fmt.t - val pp_unfold_info : (string * string) list option Fmt.t + val pp_unfold_info : (LVar.t * LVar.t) list option Fmt.t (** Pretty-printer *) val pp : Format.formatter -> t -> unit @@ -561,7 +618,7 @@ module LCmd : sig | Assert of Expr.t (** Assert *) | Assume of Expr.t (** Assume *) | AssumeType of Expr.t * Type.t (** Assume Type *) - | FreshSVar of string (** x := fresh_svar() *) + | FreshSVar of Var.t (** x := fresh_svar() *) | SL of SLCmd.t (** Separation-logic command *) (** @deprecated Use {!Visitors.endo} instead *) @@ -576,24 +633,24 @@ module Cmd : sig (** GIL Commands *) (** Optional bindings for procedure calls *) - type logic_bindings_t = string * (string * Expr.t) list + type logic_bindings_t = string * (LVar.t * Expr.t) list type 'label t = | Skip (** Skip *) - | Assignment of string * Expr.t (** Variable Assignment *) - | LAction of string * string * Expr.t list (** Action *) + | Assignment of Var.t * Expr.t (** Variable Assignment *) + | LAction of Var.t * string * Expr.t list (** Action *) | Logic of LCmd.t (** Logic commands *) | Goto of 'label (** Unconditional goto *) | GuardedGoto of Expr.t * 'label * 'label (** Conditional goto *) | Call of - string * Expr.t * Expr.t list * 'label option * logic_bindings_t option + Var.t * Expr.t * Expr.t list * 'label option * logic_bindings_t option (** Procedure call *) - | ECall of string * Expr.t * Expr.t list * 'label option + | ECall of Var.t * Expr.t * Expr.t list * 'label option (** External Procedure call *) - | Apply of string * Expr.t * 'label option + | Apply of Var.t * Expr.t * 'label option (** Application-style procedure call *) - | Arguments of string (** Arguments of the currently executing function *) - | PhiAssignment of (string * Expr.t list) list (** PHI-assignment *) + | Arguments of Var.t (** Arguments of the currently executing function *) + | PhiAssignment of (Var.t * Expr.t list) list (** PHI-assignment *) | ReturnNormal (** Normal return *) | ReturnError (** Error return *) | Fail of string * Expr.t list (** Failure *) @@ -612,13 +669,13 @@ module Cmd : sig val successors : int t -> int -> int list (** Program variable collector *) - val pvars : 'a t -> Containers.SS.t + val pvars : 'a t -> Var.Set.t (** Logical variable collector *) - val lvars : 'a t -> Containers.SS.t + val lvars : 'a t -> LVar.Set.t (** Location collector *) - val locs : 'a t -> Containers.SS.t + val locs : 'a t -> Id.Sets.LocSet.t end (** @canonical Gillian.Gil_syntax.Pred *) @@ -630,10 +687,10 @@ module Pred : sig pred_source_path : string option; pred_internal : bool; pred_num_params : int; (** Number of parameters *) - pred_params : (string * Type.t option) list; + pred_params : (Var.t * Type.t option) list; (** Parameter names and (optional) types *) pred_ins : int list; (** Ins *) - pred_definitions : ((string * string list) option * Asrt.t) list; + pred_definitions : ((string * LVar.t list) option * Asrt.t) list; (** Predicate definitions *) pred_facts : Expr.t list; (** Facts that hold for every definition *) pred_guard : Asrt.t option; (** Cost for unfolding the predicate *) @@ -650,13 +707,13 @@ module Pred : sig val ins_and_outs : t -> Utils.Containers.SI.t * Utils.Containers.SI.t (** Returns the names of in-parameters *) - val in_params : t -> string list + val in_params : t -> Var.t list (** Returns the in-parameters given all parameters *) val in_args : t -> 'a list -> 'a list - (** Returns the names of in-parameters *) - val out_params : t -> string list + (** Returns the names of out-parameters *) + val out_params : t -> Var.t list (** Returns the out-parameters given all parameters *) val out_args : t -> 'a list -> 'a list @@ -718,11 +775,11 @@ module Lemma : sig lemma_name : string; (** Name *) lemma_source_path : string option; lemma_internal : bool; - lemma_params : string list; (** Parameters *) + lemma_params : Var.t list; (** Parameters *) lemma_specs : spec list; (** Specs of the Lemma *) lemma_proof : LCmd.t list option; (** (Optional) Proof *) lemma_variant : Expr.t option; (** Variant *) - lemma_existentials : string list; (* Existentials *) + lemma_existentials : LVar.t list; (* Existentials *) } (** Pretty-printer *) @@ -741,7 +798,7 @@ module Macro : sig type t = { macro_name : string; (** Name of the macro *) - macro_params : string list; (** Actual parameters *) + macro_params : Var.t list; (** Actual parameters *) macro_definition : LCmd.t list; (** Macro definition *) } @@ -782,13 +839,13 @@ module Spec : sig ss_variant : Expr.t option; (** Variant *) ss_flag : Flag.t; (** Return flag *) ss_to_verify : bool; (** Should the spec be verified? *) - ss_label : (string * string list) option; + ss_label : (string * Id.LVar.t list) option; } (** Full specification *) type t = { spec_name : string; (** Procedure/spec name *) - spec_params : string list; (** Procedure/spec parameters *) + spec_params : Var.t list; (** Procedure/spec parameters *) spec_sspecs : st list; (** List of single specifications *) spec_normalised : bool; (** If the spec is already normalised *) spec_incomplete : bool; (** If the spec is incomplete *) @@ -806,13 +863,13 @@ module Spec : sig st (** [init spec_name spec_params spec_sspecs spec_normalised spec_to_verify] creates a full specification with the given values *) - val init : string -> string list -> st list -> bool -> bool -> bool -> t + val init : string -> Var.t list -> st list -> bool -> bool -> bool -> t (** Extends a full specfiication with a single specification *) val extend : t -> st list -> t (** Return the list of parameters of a Spec *) - val get_params : t -> string list + val get_params : t -> Var.t list val pp_sspec : Format.formatter -> st -> unit val pp : Format.formatter -> t -> unit @@ -822,9 +879,7 @@ module Spec : sig (** @deprecated For legacy purposes, some functions use string sets instead of string list existentials. This function allows for a smooth translation *) - val label_vars_to_set : - ('a * Utils.Containers.SS.elt list) option -> - ('a * Utils.Containers.SS.t) option + val label_vars_to_set : ('a * LVar.t list) option -> ('a * LVar.Set.t) option (** {3 Serialization} *) @@ -839,14 +894,14 @@ module BiSpec : sig type t = { bispec_name : string; (** Procedure/spec name *) - bispec_params : string list; (** Procedure/spec parameters *) + bispec_params : Var.t list; (** Procedure/spec parameters *) bispec_pres : Asrt.t list; (** Possible preconditions *) bispec_normalised : bool; (** If the spec is already normalised *) } type t_tbl = (string, t) Hashtbl.t - val init : string -> string list -> Asrt.t list -> bool -> t + val init : string -> Var.t list -> Asrt.t list -> bool -> t val init_tbl : unit -> t_tbl (** Pretty-printer *) @@ -917,7 +972,7 @@ module Proc : sig proc_source_path : string option; proc_internal : bool; proc_body : ('annot * 'label option * 'label Cmd.t) array; - proc_params : string list; + proc_params : Var.t list; proc_spec : Spec.t option; proc_aliases : string list; proc_calls : string list; @@ -925,7 +980,7 @@ module Proc : sig [@@deriving yojson] (** Gets the parameters of the procedure *) - val get_params : ('a, 'b) t -> string list + val get_params : ('a, 'b) t -> Var.t list (** If the [show_labels] flag is true, the labels will be written before the command they correspond to *) val pp : @@ -1120,7 +1175,7 @@ module Visitors : sig constraint 'b = < visit_'annot : 'c -> 'd -> 'd ; visit_'label : 'c -> 'f -> 'f - ; visit_ALoc : 'c -> Expr.t -> string -> Expr.t + ; visit_ALoc : 'c -> Expr.t -> ALoc.t -> Expr.t ; visit_And : 'c -> BinOp.t -> BinOp.t ; visit_Impl : 'c -> BinOp.t -> BinOp.t ; visit_Apply : @@ -1154,7 +1209,7 @@ module Visitors : sig Expr.t -> Expr.t list -> 'f option -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> 'f Cmd.t ; visit_Car : 'c -> UnOp.t -> UnOp.t ; visit_Cdr : 'c -> UnOp.t -> UnOp.t @@ -1170,7 +1225,7 @@ module Visitors : sig ; visit_EList : 'c -> Expr.t -> Expr.t list -> Expr.t ; visit_ESet : 'c -> Expr.t -> Expr.t list -> Expr.t ; visit_Exists : - 'c -> Expr.t -> (string * Type.t option) list -> Expr.t -> Expr.t + 'c -> Expr.t -> (LVar.t * Type.t option) list -> Expr.t -> Expr.t ; visit_Emp : 'c -> Asrt.atom -> Asrt.atom ; visit_Empty : 'c -> Literal.t -> Literal.t ; visit_EmptyType : 'c -> Type.t -> Type.t @@ -1183,7 +1238,7 @@ module Visitors : sig ; visit_FMinus : 'c -> BinOp.t -> BinOp.t ; visit_FMod : 'c -> BinOp.t -> BinOp.t ; visit_ForAll : - 'c -> Expr.t -> (string * Type.t option) list -> Expr.t -> Expr.t + 'c -> Expr.t -> (LVar.t * Type.t option) list -> Expr.t -> Expr.t ; visit_FPlus : 'c -> BinOp.t -> BinOp.t ; visit_FTimes : 'c -> BinOp.t -> BinOp.t ; visit_FUnaryMinus : 'c -> UnOp.t -> UnOp.t @@ -1193,7 +1248,7 @@ module Visitors : sig SLCmd.t -> string -> Expr.t list -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> SLCmd.t ; visit_CorePred : 'c -> @@ -1229,14 +1284,14 @@ module Visitors : sig ; visit_LAction : 'c -> 'f Cmd.t -> string -> string -> Expr.t list -> 'f Cmd.t ; visit_LList : 'c -> Literal.t -> Literal.t list -> Literal.t - ; visit_LVar : 'c -> Expr.t -> string -> Expr.t + ; visit_LVar : 'c -> Expr.t -> LVar.t -> Expr.t ; visit_LeftShift : 'c -> BinOp.t -> BinOp.t ; visit_LeftShiftL : 'c -> BinOp.t -> BinOp.t ; visit_LeftShiftF : 'c -> BinOp.t -> BinOp.t ; visit_IsInt : 'c -> UnOp.t -> UnOp.t ; visit_ListType : 'c -> Type.t -> Type.t ; visit_Lit : 'c -> Expr.t -> Literal.t -> Expr.t - ; visit_Loc : 'c -> Literal.t -> string -> Literal.t + ; visit_Loc : 'c -> Literal.t -> Loc.t -> Literal.t ; visit_LocalTime : 'c -> Constant.t -> Constant.t ; visit_Logic : 'c -> 'f Cmd.t -> LCmd.t -> 'f Cmd.t ; visit_LstCat : 'c -> NOp.t -> NOp.t @@ -1277,9 +1332,9 @@ module Visitors : sig ; visit_NumberType : 'c -> Type.t -> Type.t ; visit_ObjectType : 'c -> Type.t -> Type.t ; visit_Or : 'c -> BinOp.t -> BinOp.t - ; visit_PVar : 'c -> Expr.t -> string -> Expr.t + ; visit_PVar : 'c -> Expr.t -> Var.t -> Expr.t ; visit_PhiAssignment : - 'c -> 'f Cmd.t -> (string * Expr.t list) list -> 'f Cmd.t + 'c -> 'f Cmd.t -> (Var.t * Expr.t list) list -> 'f Cmd.t ; visit_Pi : 'c -> Constant.t -> Constant.t ; visit_Pred : 'c -> Asrt.atom -> string -> Expr.t list -> Asrt.atom ; visit_Pure : 'c -> Asrt.atom -> Expr.t -> Asrt.atom @@ -1299,7 +1354,7 @@ module Visitors : sig ; visit_SignedRightShiftL : 'c -> BinOp.t -> BinOp.t ; visit_SignedRightShiftF : 'c -> BinOp.t -> BinOp.t ; visit_Skip : 'c -> 'f Cmd.t -> 'f Cmd.t - ; visit_FreshSVar : 'c -> LCmd.t -> string -> LCmd.t + ; visit_FreshSVar : 'c -> LCmd.t -> Var.t -> LCmd.t ; visit_StrCat : 'c -> BinOp.t -> BinOp.t ; visit_StrLen : 'c -> UnOp.t -> UnOp.t ; visit_StrLess : 'c -> BinOp.t -> BinOp.t @@ -1343,10 +1398,7 @@ module Visitors : sig ; visit_UnsignedRightShiftF : 'c -> BinOp.t -> BinOp.t ; visit_assertion_atom : 'c -> Asrt.atom -> Asrt.atom ; visit_assertion : 'c -> Asrt.t -> Asrt.t - ; visit_bindings : - 'c -> - string * (string * Expr.t) list -> - string * (string * Expr.t) list + ; visit_bindings : 'c -> Cmd.logic_bindings_t -> Cmd.logic_bindings_t ; visit_binop : 'c -> BinOp.t -> BinOp.t ; visit_bispec : 'c -> BiSpec.t -> BiSpec.t ; visit_cmd : 'c -> 'f Cmd.t -> 'f Cmd.t @@ -1370,7 +1422,7 @@ module Visitors : sig method visit_'annot : 'c -> 'd -> 'd method visit_'label : 'c -> 'f -> 'f - method visit_ALoc : 'c -> Expr.t -> string -> Expr.t + method visit_ALoc : 'c -> Expr.t -> ALoc.t -> Expr.t method visit_And : 'c -> BinOp.t -> BinOp.t method visit_Impl : 'c -> BinOp.t -> BinOp.t @@ -1408,7 +1460,7 @@ module Visitors : sig Expr.t -> Expr.t list -> 'f option -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> 'f Cmd.t method visit_Car : 'c -> UnOp.t -> UnOp.t @@ -1422,7 +1474,7 @@ module Visitors : sig method visit_ESet : 'c -> Expr.t -> Expr.t list -> Expr.t method visit_Exists : - 'c -> Expr.t -> (string * Type.t option) list -> Expr.t -> Expr.t + 'c -> Expr.t -> (LVar.t * Type.t option) list -> Expr.t -> Expr.t method visit_Emp : 'c -> Asrt.atom -> Asrt.atom method visit_Empty : 'c -> Literal.t -> Literal.t @@ -1445,11 +1497,11 @@ module Visitors : sig SLCmd.t -> string -> Expr.t list -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> SLCmd.t method visit_ForAll : - 'c -> Expr.t -> (string * Type.t option) list -> Expr.t -> Expr.t + 'c -> Expr.t -> (LVar.t * Type.t option) list -> Expr.t -> Expr.t method visit_CorePred : 'c -> Asrt.atom -> string -> Expr.t list -> Expr.t list -> Asrt.atom @@ -1486,14 +1538,14 @@ module Visitors : sig 'c -> 'f Cmd.t -> string -> string -> Expr.t list -> 'f Cmd.t method visit_LList : 'c -> Literal.t -> Literal.t list -> Literal.t - method visit_LVar : 'c -> Expr.t -> string -> Expr.t + method visit_LVar : 'c -> Expr.t -> LVar.t -> Expr.t method visit_LeftShift : 'c -> BinOp.t -> BinOp.t method visit_LeftShiftL : 'c -> BinOp.t -> BinOp.t method visit_LeftShiftF : 'c -> BinOp.t -> BinOp.t method visit_IsInt : 'c -> UnOp.t -> UnOp.t method visit_ListType : 'c -> Type.t -> Type.t method visit_Lit : 'c -> Expr.t -> Literal.t -> Expr.t - method visit_Loc : 'c -> Literal.t -> string -> Literal.t + method visit_Loc : 'c -> Literal.t -> Loc.t -> Literal.t method visit_LocalTime : 'c -> Constant.t -> Constant.t method visit_Logic : 'c -> 'f Cmd.t -> LCmd.t -> 'f Cmd.t method visit_LstCat : 'c -> NOp.t -> NOp.t @@ -1534,10 +1586,10 @@ module Visitors : sig method visit_NumberType : 'c -> Type.t -> Type.t method visit_ObjectType : 'c -> Type.t -> Type.t method visit_Or : 'c -> BinOp.t -> BinOp.t - method visit_PVar : 'c -> Expr.t -> string -> Expr.t + method visit_PVar : 'c -> Expr.t -> Var.t -> Expr.t method visit_PhiAssignment : - 'c -> 'f Cmd.t -> (string * Expr.t list) list -> 'f Cmd.t + 'c -> 'f Cmd.t -> (Var.t * Expr.t list) list -> 'f Cmd.t method visit_Pi : 'c -> Constant.t -> Constant.t method visit_Pred : 'c -> Asrt.atom -> string -> Expr.t list -> Asrt.atom @@ -1558,7 +1610,7 @@ module Visitors : sig method visit_SignedRightShiftL : 'c -> BinOp.t -> BinOp.t method visit_SignedRightShiftF : 'c -> BinOp.t -> BinOp.t method visit_Skip : 'c -> 'f Cmd.t -> 'f Cmd.t - method visit_FreshSVar : 'c -> LCmd.t -> string -> LCmd.t + method visit_FreshSVar : 'c -> LCmd.t -> Var.t -> LCmd.t method visit_StrCat : 'c -> BinOp.t -> BinOp.t method visit_StrLen : 'c -> UnOp.t -> UnOp.t method visit_StrLess : 'c -> BinOp.t -> BinOp.t @@ -1605,10 +1657,7 @@ module Visitors : sig method visit_assertion_atom : 'c -> Asrt.atom -> Asrt.atom method visit_assertion : 'c -> Asrt.t -> Asrt.t - - method visit_bindings : - 'c -> string * (string * Expr.t) list -> string * (string * Expr.t) list - + method visit_bindings : 'c -> Cmd.logic_bindings_t -> Cmd.logic_bindings_t method visit_binop : 'c -> BinOp.t -> BinOp.t method visit_bispec : 'c -> BiSpec.t -> BiSpec.t method private visit_bool : 'env. 'env -> bool -> bool @@ -1699,7 +1748,7 @@ module Visitors : sig Expr.t -> Expr.t list -> 'g option -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> 'f ; visit_Car : 'c -> 'f ; visit_Cdr : 'c -> 'f @@ -1710,7 +1759,7 @@ module Visitors : sig 'c -> string -> Expr.t -> Expr.t list -> 'g option -> 'f ; visit_EList : 'c -> Expr.t list -> 'f ; visit_ESet : 'c -> Expr.t list -> 'f - ; visit_Exists : 'c -> (string * Type.t option) list -> Expr.t -> 'f + ; visit_Exists : 'c -> (LVar.t * Type.t option) list -> Expr.t -> 'f ; visit_Emp : 'c -> 'f ; visit_Empty : 'c -> 'f ; visit_EmptyType : 'c -> 'f @@ -1719,12 +1768,8 @@ module Visitors : sig ; visit_Error : 'c -> 'f ; visit_Fail : 'c -> string -> Expr.t list -> 'f ; visit_Fold : - 'c -> - string -> - Expr.t list -> - (string * (string * Expr.t) list) option -> - 'f - ; visit_ForAll : 'c -> (string * Type.t option) list -> Expr.t -> 'f + 'c -> string -> Expr.t list -> Cmd.logic_bindings_t option -> 'f + ; visit_ForAll : 'c -> (LVar.t * Type.t option) list -> Expr.t -> 'f ; visit_CorePred : 'c -> string -> Expr.t list -> Expr.t list -> 'f ; visit_Wand : 'c -> string * Expr.t list -> string * Expr.t list -> 'f ; visit_GUnfold : 'c -> string -> 'f @@ -1747,7 +1792,7 @@ module Visitors : sig ; visit_FLessThanEqual : 'c -> 'f ; visit_ListType : 'c -> 'f ; visit_Lit : 'c -> Literal.t -> 'f - ; visit_Loc : 'c -> string -> 'f + ; visit_Loc : 'c -> Loc.t -> 'f ; visit_LocalTime : 'c -> 'f ; visit_Logic : 'c -> LCmd.t -> 'f ; visit_LstCat : 'c -> 'f @@ -1794,8 +1839,8 @@ module Visitors : sig ; visit_NumberType : 'c -> 'f ; visit_ObjectType : 'c -> 'f ; visit_Or : 'c -> 'f - ; visit_PVar : 'c -> string -> 'f - ; visit_PhiAssignment : 'c -> (string * Expr.t list) list -> 'f + ; visit_PVar : 'c -> Var.t -> 'f + ; visit_PhiAssignment : 'c -> (Var.t * Expr.t list) list -> 'f ; visit_Pi : 'c -> 'f ; visit_IPlus : 'c -> 'f ; visit_FPlus : 'c -> 'f @@ -1817,7 +1862,7 @@ module Visitors : sig ; visit_SignedRightShiftL : 'c -> 'f ; visit_SignedRightShiftF : 'c -> 'f ; visit_Skip : 'c -> 'f - ; visit_FreshSVar : 'c -> string -> 'f + ; visit_FreshSVar : 'c -> Var.t -> 'f ; visit_StrCat : 'c -> 'f ; visit_StrLen : 'c -> 'f ; visit_StrLess : 'c -> 'f @@ -1860,7 +1905,7 @@ module Visitors : sig ; visit_UnsignedRightShiftF : 'c -> 'f ; visit_assertion_atom : 'c -> Asrt.atom -> 'f ; visit_assertion : 'c -> Asrt.t -> 'f - ; visit_bindings : 'c -> string * (string * Expr.t) list -> 'f + ; visit_bindings : 'c -> Cmd.logic_bindings_t -> 'f ; visit_binop : 'c -> BinOp.t -> 'f ; visit_bispec : 'c -> BiSpec.t -> 'f ; visit_cmd : 'c -> 'g Cmd.t -> 'f @@ -1917,7 +1962,7 @@ module Visitors : sig Expr.t -> Expr.t list -> 'g option -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> 'f method visit_Car : 'c -> 'f @@ -1931,7 +1976,7 @@ module Visitors : sig method visit_EList : 'c -> Expr.t list -> 'f method visit_ESet : 'c -> Expr.t list -> 'f - method visit_Exists : 'c -> (string * Type.t option) list -> Expr.t -> 'f + method visit_Exists : 'c -> (LVar.t * Type.t option) list -> Expr.t -> 'f method visit_Emp : 'c -> 'f method visit_Empty : 'c -> 'f method visit_EmptyType : 'c -> 'f @@ -1941,13 +1986,9 @@ module Visitors : sig method visit_Fail : 'c -> string -> Expr.t list -> 'f method visit_Fold : - 'c -> - string -> - Expr.t list -> - (string * (string * Expr.t) list) option -> - 'f + 'c -> string -> Expr.t list -> Cmd.logic_bindings_t option -> 'f - method visit_ForAll : 'c -> (string * Type.t option) list -> Expr.t -> 'f + method visit_ForAll : 'c -> (LVar.t * Type.t option) list -> Expr.t -> 'f method visit_CorePred : 'c -> string -> Expr.t list -> Expr.t list -> 'f method visit_Wand : 'c -> string * Expr.t list -> string * Expr.t list -> 'f method visit_GUnfold : 'c -> string -> 'f @@ -1970,7 +2011,7 @@ module Visitors : sig method visit_FLessThanEqual : 'c -> 'f method visit_ListType : 'c -> 'f method visit_Lit : 'c -> Literal.t -> 'f - method visit_Loc : 'c -> string -> 'f + method visit_Loc : 'c -> Loc.t -> 'f method visit_LocalTime : 'c -> 'f method visit_Logic : 'c -> LCmd.t -> 'f method visit_LstCat : 'c -> 'f @@ -2017,8 +2058,8 @@ module Visitors : sig method visit_NumberType : 'c -> 'f method visit_ObjectType : 'c -> 'f method visit_Or : 'c -> 'f - method visit_PVar : 'c -> string -> 'f - method visit_PhiAssignment : 'c -> (string * Expr.t list) list -> 'f + method visit_PVar : 'c -> Var.t -> 'f + method visit_PhiAssignment : 'c -> (Var.t * Expr.t list) list -> 'f method visit_Pi : 'c -> 'f method visit_IPlus : 'c -> 'f method visit_FPlus : 'c -> 'f @@ -2040,7 +2081,7 @@ module Visitors : sig method visit_SignedRightShiftL : 'c -> 'f method visit_SignedRightShiftF : 'c -> 'f method visit_Skip : 'c -> 'f - method visit_FreshSVar : 'c -> string -> 'f + method visit_FreshSVar : 'c -> Var.t -> 'f method visit_StrCat : 'c -> 'f method visit_StrLen : 'c -> 'f method visit_StrLess : 'c -> 'f @@ -2081,7 +2122,7 @@ module Visitors : sig method visit_UnsignedRightShiftF : 'c -> 'f method visit_assertion_atom : 'c -> Asrt.atom -> 'f method visit_assertion : 'c -> Asrt.t -> 'f - method visit_bindings : 'c -> string * (string * Expr.t) list -> 'f + method visit_bindings : 'c -> Cmd.logic_bindings_t -> 'f method visit_binop : 'c -> BinOp.t -> 'f method visit_bispec : 'c -> BiSpec.t -> 'f method visit_cmd : 'c -> 'g Cmd.t -> 'f @@ -2108,7 +2149,7 @@ module Visitors : sig constraint 'b = < visit_'annot : 'c -> 'd -> unit ; visit_'label : 'c -> 'f -> unit - ; visit_ALoc : 'c -> string -> unit + ; visit_ALoc : 'c -> ALoc.t -> unit ; visit_And : 'c -> unit ; visit_Impl : 'c -> unit ; visit_Apply : 'c -> string -> Expr.t -> 'f option -> unit @@ -2148,7 +2189,7 @@ module Visitors : sig 'c -> string -> Expr.t -> Expr.t list -> 'f option -> unit ; visit_EList : 'c -> Expr.t list -> unit ; visit_ESet : 'c -> Expr.t list -> unit - ; visit_Exists : 'c -> (string * Type.t option) list -> Expr.t -> unit + ; visit_Exists : 'c -> (LVar.t * Type.t option) list -> Expr.t -> unit ; visit_Emp : 'c -> unit ; visit_Empty : 'c -> unit ; visit_EmptyType : 'c -> unit @@ -2165,12 +2206,8 @@ module Visitors : sig ; visit_FUnaryMinus : 'c -> unit ; visit_Fail : 'c -> string -> Expr.t list -> unit ; visit_Fold : - 'c -> - string -> - Expr.t list -> - (string * (string * Expr.t) list) option -> - unit - ; visit_ForAll : 'c -> (string * Type.t option) list -> Expr.t -> unit + 'c -> string -> Expr.t list -> Cmd.logic_bindings_t option -> unit + ; visit_ForAll : 'c -> (LVar.t * Type.t option) list -> Expr.t -> unit ; visit_CorePred : 'c -> string -> Expr.t list -> Expr.t list -> unit ; visit_Wand : 'c -> string * Expr.t list -> string * Expr.t list -> unit @@ -2193,14 +2230,14 @@ module Visitors : sig ; visit_Produce : 'c -> Asrt.t -> unit ; visit_LAction : 'c -> string -> string -> Expr.t list -> unit ; visit_LList : 'c -> Literal.t list -> unit - ; visit_LVar : 'c -> string -> unit + ; visit_LVar : 'c -> LVar.t -> unit ; visit_LeftShift : 'c -> unit ; visit_LeftShiftL : 'c -> unit ; visit_LeftShiftF : 'c -> unit ; visit_IsInt : 'c -> unit ; visit_ListType : 'c -> unit ; visit_Lit : 'c -> Literal.t -> unit - ; visit_Loc : 'c -> string -> unit + ; visit_Loc : 'c -> Loc.t -> unit ; visit_LocalTime : 'c -> unit ; visit_Logic : 'c -> LCmd.t -> unit ; visit_LstCat : 'c -> unit @@ -2241,8 +2278,8 @@ module Visitors : sig ; visit_NumberType : 'c -> unit ; visit_ObjectType : 'c -> unit ; visit_Or : 'c -> unit - ; visit_PVar : 'c -> string -> unit - ; visit_PhiAssignment : 'c -> (string * Expr.t list) list -> unit + ; visit_PVar : 'c -> Var.t -> unit + ; visit_PhiAssignment : 'c -> (Var.t * Expr.t list) list -> unit ; visit_Pi : 'c -> unit ; visit_Pred : 'c -> string -> Expr.t list -> unit ; visit_Pure : 'c -> Expr.t -> unit @@ -2262,7 +2299,7 @@ module Visitors : sig ; visit_SignedRightShiftL : 'c -> unit ; visit_SignedRightShiftF : 'c -> unit ; visit_Skip : 'c -> unit - ; visit_FreshSVar : 'c -> string -> unit + ; visit_FreshSVar : 'c -> Var.t -> unit ; visit_StrCat : 'c -> unit ; visit_StrLen : 'c -> unit ; visit_StrLess : 'c -> unit @@ -2300,7 +2337,7 @@ module Visitors : sig ; visit_UnsignedRightShiftF : 'c -> unit ; visit_assertion_atom : 'c -> Asrt.atom -> unit ; visit_assertion : 'c -> Asrt.t -> unit - ; visit_bindings : 'c -> string * (string * Expr.t) list -> unit + ; visit_bindings : 'c -> Cmd.logic_bindings_t -> unit ; visit_binop : 'c -> BinOp.t -> unit ; visit_bispec : 'c -> BiSpec.t -> unit ; visit_cmd : 'c -> 'f Cmd.t -> unit @@ -2324,7 +2361,7 @@ module Visitors : sig method visit_'annot : 'c -> 'd -> unit method visit_'label : 'c -> 'f -> unit - method visit_ALoc : 'c -> string -> unit + method visit_ALoc : 'c -> ALoc.t -> unit method visit_And : 'c -> unit method visit_Impl : 'c -> unit method visit_Apply : 'c -> string -> Expr.t -> 'f option -> unit @@ -2356,7 +2393,7 @@ module Visitors : sig Expr.t -> Expr.t list -> 'f option -> - (string * (string * Expr.t) list) option -> + Cmd.logic_bindings_t option -> unit method visit_Car : 'c -> unit @@ -2368,7 +2405,7 @@ module Visitors : sig method visit_EList : 'c -> Expr.t list -> unit method visit_ESet : 'c -> Expr.t list -> unit - method visit_Exists : 'c -> (string * Type.t option) list -> Expr.t -> unit + method visit_Exists : 'c -> (LVar.t * Type.t option) list -> Expr.t -> unit method visit_Emp : 'c -> unit method visit_Empty : 'c -> unit method visit_EmptyType : 'c -> unit @@ -2386,13 +2423,9 @@ module Visitors : sig method visit_Fail : 'c -> string -> Expr.t list -> unit method visit_Fold : - 'c -> - string -> - Expr.t list -> - (string * (string * Expr.t) list) option -> - unit + 'c -> string -> Expr.t list -> Cmd.logic_bindings_t option -> unit - method visit_ForAll : 'c -> (string * Type.t option) list -> Expr.t -> unit + method visit_ForAll : 'c -> (LVar.t * Type.t option) list -> Expr.t -> unit method visit_CorePred : 'c -> string -> Expr.t list -> Expr.t list -> unit method visit_Wand : @@ -2417,14 +2450,14 @@ module Visitors : sig method visit_Produce : 'c -> Asrt.t -> unit method visit_LAction : 'c -> string -> string -> Expr.t list -> unit method visit_LList : 'c -> Literal.t list -> unit - method visit_LVar : 'c -> string -> unit + method visit_LVar : 'c -> LVar.t -> unit method visit_LeftShift : 'c -> unit method visit_LeftShiftL : 'c -> unit method visit_LeftShiftF : 'c -> unit method visit_IsInt : 'c -> unit method visit_ListType : 'c -> unit method visit_Lit : 'c -> Literal.t -> unit - method visit_Loc : 'c -> string -> unit + method visit_Loc : 'c -> Loc.t -> unit method visit_LocalTime : 'c -> unit method visit_Logic : 'c -> LCmd.t -> unit method visit_LstCat : 'c -> unit @@ -2465,8 +2498,8 @@ module Visitors : sig method visit_NumberType : 'c -> unit method visit_ObjectType : 'c -> unit method visit_Or : 'c -> unit - method visit_PVar : 'c -> string -> unit - method visit_PhiAssignment : 'c -> (string * Expr.t list) list -> unit + method visit_PVar : 'c -> Var.t -> unit + method visit_PhiAssignment : 'c -> (Var.t * Expr.t list) list -> unit method visit_Pi : 'c -> unit method visit_Pred : 'c -> string -> Expr.t list -> unit method visit_Pure : 'c -> Expr.t -> unit @@ -2486,7 +2519,7 @@ module Visitors : sig method visit_SignedRightShiftL : 'c -> unit method visit_SignedRightShiftF : 'c -> unit method visit_Skip : 'c -> unit - method visit_FreshSVar : 'c -> string -> unit + method visit_FreshSVar : 'c -> Var.t -> unit method visit_StrCat : 'c -> unit method visit_StrLen : 'c -> unit method visit_StrLess : 'c -> unit @@ -2531,7 +2564,7 @@ module Visitors : sig method visit_assertion_atom : 'c -> Asrt.atom -> unit method visit_assertion : 'c -> Asrt.t -> unit - method visit_bindings : 'c -> string * (string * Expr.t) list -> unit + method visit_bindings : 'c -> Cmd.logic_bindings_t -> unit method visit_binop : 'c -> BinOp.t -> unit method visit_bispec : 'c -> BiSpec.t -> unit method private visit_bool : 'env. 'env -> bool -> unit diff --git a/GillianCore/GIL_Syntax/Id.ml b/GillianCore/GIL_Syntax/Id.ml new file mode 100644 index 000000000..6277aea02 --- /dev/null +++ b/GillianCore/GIL_Syntax/Id.ml @@ -0,0 +1,78 @@ +open Allocators + +type +'a t = string +and loc = [ `Loc ] +and aloc = [ `ALoc ] +and var = [ `Var ] +and lvar = [ `LVar ] [@@deriving yojson] + +type any_var = [ var | lvar ] +and any_loc = [ loc | aloc ] +and any = [ loc | aloc | var | lvar ] +and substable = [ aloc | var | lvar ] [@@deriving yojson] + +let return_variable = Names.return_variable +let str : 'a t -> string = Fun.id +let equal : 'a t -> 'b t -> bool = String.equal +let pp fmt (i : 'a t) = Fmt.pf fmt "%s" i +let compare = String.compare + +let of_yojson' = function + | `String s -> Ok s + | _ -> Error "Id.of_yojson: expected string" + +let to_yojson' s = `String s + +let as_lvars (vars : any_var t list) : lvar t list option = + if List.for_all Names.is_lvar_name vars then Some vars else None + +let as_aloc (loc : any_loc t) : aloc t option = + if Names.is_aloc_name loc then Some loc else None + +module type Id = sig + include S_with_stringify + module Set = Containers.SS +end + +module Make (I : sig + val prefix : string +end) : Id with type t = string = struct + include Make_with_prefix (Basic ()) (I) + module Set = Containers.SS +end + +module Loc = Make (struct + let prefix = Names.lloc_prefix +end) + +module ALoc = Make (struct + let prefix = Names.aloc_prefix +end) + +module LVar = struct + include Make (struct + let prefix = Names.lvar_prefix + end) + + let is_spec_var_name = Names.is_spec_var_name +end + +module Var = Make (struct + let prefix = Names.pvar_prefix +end) + +module Sets = struct + module SubstSet = Containers.SS + module LocSet = Containers.SS + module VarSet = Containers.SS + + let pvar_to_varset = Fun.id + let lvar_to_varset = Fun.id + let pvar_to_subst = Fun.id + let lvar_to_subst = Fun.id + let aloc_to_subst = Fun.id + let aloc_to_loc = Fun.id + + (** @deprecated *) + let substset_to_lvar = Fun.id +end diff --git a/GillianCore/GIL_Syntax/LCmd.ml b/GillianCore/GIL_Syntax/LCmd.ml index fd9bff41a..696162700 100644 --- a/GillianCore/GIL_Syntax/LCmd.ml +++ b/GillianCore/GIL_Syntax/LCmd.ml @@ -1,6 +1,6 @@ (** {b GIL logic commands}. *) -module SS = Containers.SS +open Id type t = TypeDef__.lcmd = | If of Expr.t * t list * t list (** If-then-else *) @@ -25,40 +25,44 @@ let rec map (f_e : Expr.t -> Expr.t) (f_sl : SLCmd.t -> SLCmd.t) (lcmd : t) = | FreshSVar _ as lcmd -> lcmd | SL sl_cmd -> SL (f_sl sl_cmd) -let fold = List.fold_left SS.union SS.empty - -let rec pvars (lcmd : t) : SS.t = +let rec pvars (lcmd : t) : Var.Set.t = + let fold = List.fold_left Var.Set.union Var.Set.empty in let pvars_es es = fold (List.map Expr.pvars es) in let pvars_lcmds es = fold (List.map pvars es) in match lcmd with | If (e, lthen, lelse) -> - SS.union (Expr.pvars e) (SS.union (pvars_lcmds lthen) (pvars_lcmds lelse)) + Var.Set.union (Expr.pvars e) + (Var.Set.union (pvars_lcmds lthen) (pvars_lcmds lelse)) | Macro (_, es) -> pvars_es es | Branch e | Assert e | Assume e | AssumeType (e, _) -> Expr.pvars e - | FreshSVar name -> SS.singleton name + | FreshSVar name -> Var.Set.singleton name | SL slcmd -> SLCmd.pvars slcmd -let rec lvars (lcmd : t) : SS.t = +let rec lvars (lcmd : t) : LVar.Set.t = + let fold = List.fold_left LVar.Set.union LVar.Set.empty in let lvars_es es = fold (List.map Expr.lvars es) in let lvars_lcmds es = fold (List.map lvars es) in match lcmd with | If (e, lthen, lelse) -> - SS.union (Expr.lvars e) (SS.union (lvars_lcmds lthen) (lvars_lcmds lelse)) + LVar.Set.union (Expr.lvars e) + (LVar.Set.union (lvars_lcmds lthen) (lvars_lcmds lelse)) | Macro (_, es) -> lvars_es es | Branch e | Assert e | Assume e | AssumeType (e, _) -> Expr.lvars e | SL slcmd -> SLCmd.lvars slcmd - | FreshSVar _ -> SS.empty + | FreshSVar _ -> LVar.Set.empty -let rec locs (lcmd : t) : SS.t = +let rec locs (lcmd : t) : Sets.LocSet.t = + let fold = List.fold_left Sets.LocSet.union Sets.LocSet.empty in let locs_es es = fold (List.map Expr.locs es) in let locs_lcmds es = fold (List.map locs es) in match lcmd with | If (e, lthen, lelse) -> - SS.union (Expr.locs e) (SS.union (locs_lcmds lthen) (locs_lcmds lelse)) + Sets.LocSet.union (Expr.locs e) + (Sets.LocSet.union (locs_lcmds lthen) (locs_lcmds lelse)) | Macro (_, es) -> locs_es es | Branch e | Assert e | Assume e | AssumeType (e, _) -> Expr.locs e | SL slcmd -> SLCmd.locs slcmd - | FreshSVar _ -> SS.empty + | FreshSVar _ -> Sets.LocSet.empty let rec pp fmt lcmd = let pp_list = Fmt.list ~sep:Fmt.semi pp in diff --git a/GillianCore/GIL_Syntax/LVar.ml b/GillianCore/GIL_Syntax/LVar.ml deleted file mode 100644 index 2efa5364b..000000000 --- a/GillianCore/GIL_Syntax/LVar.ml +++ /dev/null @@ -1,8 +0,0 @@ -open Allocators - -include - Make_with_prefix - (Basic ()) - (struct - let prefix = Names.lvar_prefix - end) diff --git a/GillianCore/GIL_Syntax/LVar.mli b/GillianCore/GIL_Syntax/LVar.mli deleted file mode 100644 index cc065732b..000000000 --- a/GillianCore/GIL_Syntax/LVar.mli +++ /dev/null @@ -1 +0,0 @@ -include Allocators.S with type t = string diff --git a/GillianCore/GIL_Syntax/Lemma.ml b/GillianCore/GIL_Syntax/Lemma.ml index 5d88ba38d..420deb26c 100644 --- a/GillianCore/GIL_Syntax/Lemma.ml +++ b/GillianCore/GIL_Syntax/Lemma.ml @@ -9,14 +9,14 @@ type t = TypeDef__.lemma = { (* Name of the lemma *) lemma_source_path : string option; lemma_internal : bool; - lemma_params : string list; + lemma_params : Id.Var.t list; (* Params *) lemma_specs : spec list; lemma_proof : LCmd.t list option; (* (Optional) Proof body *) lemma_variant : Expr.t option; (* The paramater to treat as the variant. Will trigger termination checks *) - lemma_existentials : string list; + lemma_existentials : Id.LVar.t list; } let init_tbl () : (string, t) Hashtbl.t = Hashtbl.create Config.small_tbl_size diff --git a/GillianCore/GIL_Syntax/Literal.ml b/GillianCore/GIL_Syntax/Literal.ml index 84b9a987d..38bb9b56f 100644 --- a/GillianCore/GIL_Syntax/Literal.ml +++ b/GillianCore/GIL_Syntax/Literal.ml @@ -2,6 +2,8 @@ GIL Literals *) +type loc = string [@@deriving ord] + type t = TypeDef__.literal = | Undefined (** The literal [undefined] *) | Null (** The literal [null] *) @@ -11,7 +13,7 @@ type t = TypeDef__.literal = | Int of Z.t (** GIL integers *) | Num of float (** GIL floats - double-precision 64-bit IEEE 754 *) | String of string (** GIL strings *) - | Loc of string (** GIL object locations *) + | Loc of loc (** GIL object locations *) | Type of Type.t (** GIL types ({!type:Type.t}) *) | LList of t list (** Lists of GIL literals *) | Nono diff --git a/GillianCore/GIL_Syntax/Macro.ml b/GillianCore/GIL_Syntax/Macro.ml index 60cf21d91..b971d69eb 100644 --- a/GillianCore/GIL_Syntax/Macro.ml +++ b/GillianCore/GIL_Syntax/Macro.ml @@ -2,7 +2,7 @@ type t = TypeDef__.macro = { macro_name : string; (** Name of the macro *) - macro_params : string list; (** Actual parameters *) + macro_params : Id.Var.t list; (** Actual parameters *) macro_definition : LCmd.t list; (** Macro definition *) } diff --git a/GillianCore/GIL_Syntax/Pred.ml b/GillianCore/GIL_Syntax/Pred.ml index 50fad6ce7..89428fc65 100644 --- a/GillianCore/GIL_Syntax/Pred.ml +++ b/GillianCore/GIL_Syntax/Pred.ml @@ -3,9 +3,9 @@ type t = TypeDef__.pred = { pred_source_path : string option; pred_internal : bool; pred_num_params : int; (** Number of parameters *) - pred_params : (string * Type.t option) list; (** Actual parameters *) + pred_params : (Id.Var.t * Type.t option) list; (** Actual parameters *) pred_ins : int list; (** Ins *) - pred_definitions : ((string * string list) option * Asrt.t) list; + pred_definitions : ((string * Id.LVar.t list) option * Asrt.t) list; (** Predicate definitions *) pred_facts : Expr.t list; (** Facts that hold for every definition *) pred_guard : Asrt.t option; (** Cost for unfolding the predicate *) @@ -34,7 +34,7 @@ let ins_and_outs (pred : t) : SI.t * SI.t = let outs_set = SI.of_list outs in (ins_set, outs_set) -let in_params (pred : t) : string list = +let in_params (pred : t) : Id.Var.t list = let ins_set = SI.of_list pred.pred_ins in let _, ins = List.fold_left @@ -146,7 +146,7 @@ let check_pvars (predicates : (string, t) Hashtbl.t) : unit = let all_pred_pvars : string list = List.concat (List.map - (fun (_, ass) -> SS.elements (Asrt.pvars ass)) + (fun (_, ass) -> Id.Var.Set.elements (Asrt.pvars ass)) predicate.pred_definitions) in diff --git a/GillianCore/GIL_Syntax/Proc.ml b/GillianCore/GIL_Syntax/Proc.ml index eb6152619..a6524c051 100644 --- a/GillianCore/GIL_Syntax/Proc.ml +++ b/GillianCore/GIL_Syntax/Proc.ml @@ -10,7 +10,7 @@ type ('annot, 'label) t = ('annot, 'label) TypeDef__.proc = { proc_source_path : string option; proc_internal : bool; proc_body : ('annot * 'label option * 'label Cmd.t) array; - proc_params : string list; + proc_params : Id.Var.t list; proc_spec : Spec.t option; proc_aliases : string list; proc_calls : string list; diff --git a/GillianCore/GIL_Syntax/SLCmd.ml b/GillianCore/GIL_Syntax/SLCmd.ml index 584e52358..b07b98728 100644 --- a/GillianCore/GIL_Syntax/SLCmd.ml +++ b/GillianCore/GIL_Syntax/SLCmd.ml @@ -1,11 +1,10 @@ (***************************************************************) (** Separation Logic Commmands **) - (***************************************************************) -module SS = Containers.SS +open Id -type folding_info = string * (string * Expr.t) list [@@deriving yojson] +type folding_info = string * (LVar.t * Expr.t) list [@@deriving yojson] type unfold_info = (string * string) list [@@deriving yojson] (** {b GIL Separation Logic commands}. *) @@ -44,61 +43,62 @@ let map (f_a : Asrt.t -> Asrt.t) (f_e : Expr.t -> Expr.t) : t -> t = function Package { lhs = (lname, List.map f_e largs); rhs = (rname, List.map f_e rargs) } -let fold = List.fold_left SS.union SS.empty - -let pvars (slcmd : t) : SS.t = +let pvars (slcmd : t) : Var.Set.t = + let fold = List.fold_left Var.Set.union Var.Set.empty in let pvars_es es = fold (List.map Expr.pvars es) in match slcmd with | Fold (_, es, _) | Unfold (_, es, _, _) | ApplyLem (_, es, _) -> pvars_es es - | GUnfold _ -> SS.empty + | GUnfold _ -> Var.Set.empty | Package { lhs = _, les1; rhs = _, les2 } -> - SS.union (pvars_es les1) (pvars_es les2) + Var.Set.union (pvars_es les1) (pvars_es les2) | SepAssert (a, _) | Invariant (a, _) | Consume (a, _) | Produce a -> Asrt.pvars a - | SymbExec -> SS.empty + | SymbExec -> Var.Set.empty -let lvars (slcmd : t) : SS.t = +let lvars (slcmd : t) : LVar.Set.t = + let fold = List.fold_left LVar.Set.union LVar.Set.empty in let lvars_es es = fold (List.map Expr.lvars es) in match slcmd with | Fold (_, es, finfo) -> let lvars_finfo = match finfo with - | None -> SS.empty + | None -> LVar.Set.empty | Some (_, les) -> let _, es = List.split les in fold (List.map Expr.lvars es) in - SS.union lvars_finfo (lvars_es es) + LVar.Set.union lvars_finfo (lvars_es es) | Unfold (_, es, _, _) -> lvars_es es | Package { lhs = _, les1; rhs = _, les2 } -> - SS.union (lvars_es les1) (lvars_es les2) + LVar.Set.union (lvars_es les1) (lvars_es les2) | ApplyLem (_, es, _) -> lvars_es es - | GUnfold _ -> SS.empty + | GUnfold _ -> LVar.Set.empty | SepAssert (a, binders) | Consume (a, binders) -> - SS.union (Asrt.lvars a) (SS.of_list binders) + LVar.Set.union (Asrt.lvars a) (LVar.Set.of_list binders) | Invariant (a, _) | Produce a -> Asrt.lvars a - | SymbExec -> SS.empty + | SymbExec -> LVar.Set.empty -let locs (slcmd : t) : SS.t = +let locs (slcmd : t) : Sets.LocSet.t = + let fold = List.fold_left Sets.LocSet.union Sets.LocSet.empty in let locs_es es = fold (List.map Expr.locs es) in match slcmd with | Fold (_, es, finfo) -> let lvars_finfo = match finfo with - | None -> SS.empty + | None -> Sets.LocSet.empty | Some (_, les) -> let _, es = List.split les in fold (List.map Expr.locs es) in - SS.union lvars_finfo (locs_es es) + Sets.LocSet.union lvars_finfo (locs_es es) | Unfold (_, es, _, _) -> locs_es es | Package { lhs = _, les1; rhs = _, les2 } -> - SS.union (locs_es les1) (locs_es les2) + Sets.LocSet.union (locs_es les1) (locs_es les2) | ApplyLem (_, es, _) -> locs_es es - | GUnfold _ -> SS.empty + | GUnfold _ -> Sets.LocSet.empty | SepAssert (a, _) | Invariant (a, _) | Consume (a, _) | Produce a -> Asrt.locs a - | SymbExec -> SS.empty + | SymbExec -> Sets.LocSet.empty let pp_folding_info = let pp_ui f (v, le) = Fmt.pf f "(%s := %a)" v Expr.pp le in diff --git a/GillianCore/GIL_Syntax/Spec.ml b/GillianCore/GIL_Syntax/Spec.ml index 5dc961619..290d13758 100644 --- a/GillianCore/GIL_Syntax/Spec.ml +++ b/GillianCore/GIL_Syntax/Spec.ml @@ -1,5 +1,3 @@ -module SS = Containers.SS - (** {b Single GIL specifications}. *) type st = TypeDef__.single_spec = { ss_pre : Asrt.t; (** Precondition *) @@ -7,13 +5,13 @@ type st = TypeDef__.single_spec = { ss_variant : Expr.t option; (** Variant *) ss_flag : Flag.t; (** Return flag *) ss_to_verify : bool; (** Should the spec be verified? *) - ss_label : (string * string list) option; + ss_label : (string * Id.LVar.t list) option; } (** {b Full GIL specifications}. *) type t = TypeDef__.spec = { spec_name : string; (** Procedure/spec name *) - spec_params : string list; (** Procedure/spec parameters *) + spec_params : Id.Var.t list; (** Procedure/spec parameters *) spec_sspecs : st list; (** List of single specifications *) spec_normalised : bool; (** If the spec is already normalised *) spec_incomplete : bool; (** If the spec is incomplete *) @@ -87,7 +85,7 @@ let parameter_types (preds : (string, Pred.t) Hashtbl.t) (spec : t) : t = { spec with spec_sspecs = List.map pt_sspec spec.spec_sspecs } let label_vars_to_set lab = - Option.map (fun (l, vl) -> (l, Containers.SS.of_list vl)) lab + Option.map (fun (l, vl) -> (l, Id.LVar.Set.of_list vl)) lab let to_yojson = TypeDef__.spec_to_yojson let of_yojson = TypeDef__.spec_of_yojson diff --git a/GillianCore/GIL_Syntax/TypeDef__.ml b/GillianCore/GIL_Syntax/TypeDef__.ml index 17ad77768..4f2b540a7 100644 --- a/GillianCore/GIL_Syntax/TypeDef__.ml +++ b/GillianCore/GIL_Syntax/TypeDef__.ml @@ -39,7 +39,7 @@ and literal = | _ -> Error "Invalid yojson for Z"]) | Num of float | String of string - | Loc of string + | Loc of (Id.Loc.t[@opaque]) | Type of typ | LList of literal list | Nono @@ -133,17 +133,17 @@ and nop = LstCat | SetUnion | SetInter and expr = | Lit of literal - | PVar of string - | LVar of string - | ALoc of string + | PVar of (Id.Var.t[@opaque]) + | LVar of (Id.LVar.t[@opaque]) + | ALoc of (Id.ALoc.t[@opaque]) | UnOp of unop * expr | BinOp of expr * binop * expr | LstSub of expr * expr * expr | NOp of nop * expr list | EList of expr list | ESet of expr list - | Exists of (string * typ option) list * expr - | ForAll of (string * typ option) list * expr + | Exists of ((Id.LVar.t[@opaque]) * typ option) list * expr + | ForAll of ((Id.LVar.t[@opaque]) * typ option) list * expr and assertion_atom = | Emp @@ -154,7 +154,7 @@ and assertion_atom = | Wand of { lhs : string * expr list; rhs : string * expr list } and assertion = assertion_atom list -and bindings = string * (string * expr) list +and bindings = string * ((Id.LVar.t[@opaque]) * expr) list and slcmd = | Fold of string * expr list * bindings option @@ -202,7 +202,7 @@ and pred = { pred_source_path : string option; pred_internal : bool; pred_num_params : int; - pred_params : (string * typ option) list; + pred_params : ((Id.Var.t[@opaque]) * typ option) list; pred_ins : int list; pred_definitions : ((string * string list) option * assertion) list; pred_facts : expr list; @@ -223,7 +223,7 @@ and lemma = { lemma_name : string; lemma_source_path : string option; lemma_internal : bool; - lemma_params : string list; + lemma_params : (Id.Var.t[@opaque]) list; lemma_specs : lemma_spec list; lemma_proof : lcmd list option; lemma_variant : expr option; @@ -236,12 +236,12 @@ and single_spec = { ss_variant : expr option; ss_flag : flag; ss_to_verify : bool; - ss_label : (string * string list) option; + ss_label : (string * (Id.LVar.t[@opaque]) list) option; } and spec = { spec_name : string; - spec_params : string list; + spec_params : (Id.Var.t[@opaque]) list; spec_sspecs : single_spec list; spec_normalised : bool; spec_incomplete : bool; diff --git a/GillianCore/GIL_Syntax/Var.ml b/GillianCore/GIL_Syntax/Var.ml deleted file mode 100644 index ec2d0f362..000000000 --- a/GillianCore/GIL_Syntax/Var.ml +++ /dev/null @@ -1,7 +0,0 @@ -(** GIL Variables *) - -type t = string [@@deriving yojson, show] - -module Set = Containers.SS - -let str t = t diff --git a/GillianCore/GIL_Syntax/Visitors.ml b/GillianCore/GIL_Syntax/Visitors.ml index 508df7c0d..32a85ac8d 100644 --- a/GillianCore/GIL_Syntax/Visitors.ml +++ b/GillianCore/GIL_Syntax/Visitors.ml @@ -49,23 +49,14 @@ module Utils = struct end module Collectors = struct - let var_collector = - object (self) - inherit [_] reduce - inherit Utils.ss_monoid - method! visit_PVar () x = Containers.SS.singleton x - method! visit_LVar () x = Containers.SS.singleton x - method! visit_ALoc () x = Containers.SS.singleton x - method! visit_Loc () x = Containers.SS.singleton x - method! visit_'label () (_ : int) = self#zero - method! visit_'annot () () = self#zero - end + open Id let pvar_collector = object (self) inherit [_] reduce - inherit Utils.ss_monoid - method! visit_PVar () x = Containers.SS.singleton x + method private zero = Var.Set.empty + method private plus = Var.Set.union + method! visit_PVar () x = Var.Set.singleton x method! visit_'label () (_ : int) = self#zero method! visit_'annot () () = self#zero end @@ -73,22 +64,23 @@ module Collectors = struct let lvar_collector = object (self) inherit [_] reduce - inherit Utils.ss_monoid + method private zero = LVar.Set.empty + method private plus = LVar.Set.union method! visit_ForAll exclude binders e = (* Quantified variables need to be excluded *) let univ_quant = List.to_seq binders |> Seq.map fst in - let exclude = Containers.SS.add_seq univ_quant exclude in + let exclude = LVar.Set.add_seq univ_quant exclude in self#visit_expr exclude e method! visit_Exists exclude binders e = let exist_quants = List.to_seq binders |> Seq.map fst in - let exclude = Containers.SS.add_seq exist_quants exclude in + let exclude = LVar.Set.add_seq exist_quants exclude in self#visit_expr exclude e method! visit_LVar exclude x = - if not (Containers.SS.mem x exclude) then Containers.SS.singleton x - else Containers.SS.empty + if not (LVar.Set.mem x exclude) then LVar.Set.singleton x + else LVar.Set.empty method! visit_'label _ (_ : int) = self#zero method! visit_'annot _ () = self#zero @@ -97,8 +89,9 @@ module Collectors = struct let cloc_collector = object (self) inherit [_] reduce - inherit Utils.ss_monoid - method! visit_Loc () x = Containers.SS.singleton x + method private zero = Loc.Set.empty + method private plus = Loc.Set.union + method! visit_Loc () x = Loc.Set.singleton x method! visit_'label () (_ : int) = self#zero method! visit_'annot () () = self#zero end @@ -106,8 +99,9 @@ module Collectors = struct let aloc_collector = object (self) inherit [_] reduce - inherit Utils.ss_monoid - method! visit_ALoc () x = Containers.SS.singleton x + method private zero = ALoc.Set.empty + method private plus = ALoc.Set.union + method! visit_ALoc () x = ALoc.Set.singleton x method! visit_'label () (_ : int) = self#zero method! visit_'annot () () = self#zero end @@ -115,23 +109,14 @@ module Collectors = struct let loc_collector = object (self) inherit [_] reduce - inherit Utils.ss_monoid - method! visit_ALoc () x = Containers.SS.singleton x - method! visit_Loc () x = Containers.SS.singleton x + method private zero = Sets.LocSet.empty + method private plus = Sets.LocSet.union + method! visit_ALoc () x = Sets.LocSet.singleton x + method! visit_Loc () x = Sets.LocSet.singleton x method! visit_'label _ (_ : int) = self#zero method! visit_'annot _ () = self#zero end - let substitutable_collector = - object (self) - inherit [_] reduce - inherit Utils.ss_monoid - method! visit_ALoc () x = Containers.SS.singleton x - method! visit_LVar () x = Containers.SS.singleton x - method! visit_'label () (_ : int) = self#zero - method! visit_'annot () () = self#zero - end - let list_collector = object (self) inherit [_] reduce diff --git a/GillianCore/GIL_Syntax/test/Visitors.ml b/GillianCore/GIL_Syntax/test/Visitors.ml index 57342647e..6d698f8b5 100644 --- a/GillianCore/GIL_Syntax/test/Visitors.ml +++ b/GillianCore/GIL_Syntax/test/Visitors.ml @@ -34,6 +34,10 @@ let test_expr_base_elements () = "The base elements of a list of undefined is that list" (base_elements lit_list) (List.map (fun x -> Lit x) inner); + + let pvar = Var.alloc () in + let lvar = LVar.alloc () in + let aloc = ALoc.alloc () in let rec_expr_list = EList [ @@ -41,14 +45,14 @@ let test_expr_base_elements () = EList [ Lit (LList [ Bool false ]); - BinOp (UnOp (Not, Lit (Num 32.)), FPlus, PVar "b"); + BinOp (UnOp (Not, Lit (Num 32.)), FPlus, PVar pvar); ]; - LVar "a"; - ALoc "e"; + LVar lvar; + ALoc aloc; ] in let expected = - [ Lit Undefined; Lit (Bool false); Lit (Num 32.); LVar "a"; ALoc "e" ] + [ Lit Undefined; Lit (Bool false); Lit (Num 32.); LVar lvar; ALoc aloc ] in Alcotest.check list_expr "Get base elements in recursive list" (base_elements rec_expr_list) diff --git a/GillianCore/debugging/debugger/base_debugger.ml b/GillianCore/debugging/debugger/base_debugger.ml index 914632da9..b345bad7d 100644 --- a/GillianCore/debugging/debugger/base_debugger.ml +++ b/GillianCore/debugging/debugger/base_debugger.ml @@ -241,6 +241,7 @@ struct Type_env.to_list typ_env |> List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) |> List.map (fun (name, value) -> + let name = Id.str name in let value = Type.str value in { name; value; type_ = None; var_ref = 0 }) |> List.sort (fun v w -> Stdlib.compare v.name w.name) diff --git a/GillianCore/debugging/lifter/gil_lifter.ml b/GillianCore/debugging/lifter/gil_lifter.ml index b70afca62..163277c9f 100644 --- a/GillianCore/debugging/lifter/gil_lifter.ml +++ b/GillianCore/debugging/lifter/gil_lifter.ml @@ -227,6 +227,7 @@ functor let store_vars = store |> List.map (fun (var, value) : Variable.t -> + let var = Var.str var in let value = Fmt.to_to_string (Fmt.hbox Expr.pp) value in Variable.create_leaf var value ()) |> List.sort (fun (v : Variable.t) w -> Stdlib.compare v.name w.name) diff --git a/GillianCore/debugging/lifter/lifter_intf.ml b/GillianCore/debugging/lifter/lifter_intf.ml index 5e4545f99..7712094e8 100644 --- a/GillianCore/debugging/lifter/lifter_intf.ml +++ b/GillianCore/debugging/lifter/lifter_intf.ml @@ -108,7 +108,7 @@ module type S = sig (memory_error, annot, tl_ast) memory_error_info -> exception_info val add_variables : - store:(string * Expr.t) list -> + store:(Var.t * Expr.t) list -> memory:memory -> is_gil_file:bool -> get_new_scope_id:(unit -> int) -> diff --git a/GillianCore/engine/Abstraction/LogicPreprocessing.ml b/GillianCore/engine/Abstraction/LogicPreprocessing.ml index b325417bd..dcc0770b3 100644 --- a/GillianCore/engine/Abstraction/LogicPreprocessing.ml +++ b/GillianCore/engine/Abstraction/LogicPreprocessing.ml @@ -31,7 +31,7 @@ let rec auto_unfold let pred = Hashtbl.find unfolded_preds name in let params, _ = List.split pred.pred_params in let combined = - try List.combine params args + try (List.combine params args :> (Id.substable Id.t * Expr.t) list) with Invalid_argument _ -> Fmt.failwith "Impossible to auto unfold predicate %s. Used with %i args \ @@ -49,7 +49,10 @@ let rec auto_unfold substituting the formal parameters of the predicate with the corresponding logical expressions in the argument list *) let params, _ = List.split pred.pred_params in - let subst = SVal.SSubst.init (List.combine params args) in + let combined = + (List.combine params args :> (Id.substable Id.t * Expr.t) list) + in + let subst = SVal.SSubst.init combined in L.tmi (fun fmt -> fmt "PREDICATE %s has %d definitions" pred.pred_name (List.length pred.pred_definitions)); @@ -243,7 +246,7 @@ let unfold_preds (preds : (string, Pred.t) Hashtbl.t) : (fun (name, _) -> let pred = Hashtbl.find preds name in L.verbose (fun fmt -> fmt "Unfolding predicate: %s" pred.pred_name); - let definitions' : ((string * string list) option * Asrt.t) list = + let definitions' = List.concat_map (fun (os, a) -> List.map (fun a -> (os, a)) (auto_unfold preds recursion_info a)) @@ -347,11 +350,16 @@ let remove_equalities_between_binders_and_lvars binders assertion = | true, false -> `Greater | false, true -> `Lower in - let equal = String.equal in - let uf = Union_find.init ~priority ~equal in + let equal = Id.equal in + let uf : Id.any_var Id.t Union_find.t = Union_find.init ~priority ~equal in let rec union_expr (e1 : Expr.t) (e2 : Expr.t) = match (e1, e2) with - | (LVar x | PVar x), (LVar y | PVar y) -> Union_find.union uf x y + | LVar x, PVar y | PVar y, LVar x -> + Union_find.union uf (x :> Id.any_var Id.t) (y :> Id.any_var Id.t) + | LVar x, LVar y -> + Union_find.union uf (x :> Id.any_var Id.t) (y :> Id.any_var Id.t) + | PVar x, PVar y -> + Union_find.union uf (x :> Id.any_var Id.t) (y :> Id.any_var Id.t) | EList x, EList y -> ( try List.iter2 union_expr x y with Invalid_argument _ -> @@ -371,9 +379,10 @@ let remove_equalities_between_binders_and_lvars binders assertion = method! visit_expr () e = match e with - | LVar x | PVar x -> + | LVar x -> + let x = (x :> Id.any_var Id.t) in let rep = Union_find.rep uf x in - if String.equal x rep then e else Expr.var_to_expr rep + if Id.equal x rep then e else Expr.var_to_expr rep | _ -> super#visit_expr () e end in diff --git a/GillianCore/engine/Abstraction/MP.ml b/GillianCore/engine/Abstraction/MP.ml index ce7e07c7d..b32bf178d 100644 --- a/GillianCore/engine/Abstraction/MP.ml +++ b/GillianCore/engine/Abstraction/MP.ml @@ -1,26 +1,23 @@ -open Containers module L = Logging (** The [outs] type represents a list of learned outs, together with (optionally) the way of constructing them *) type outs = (Expr.t * Expr.t) list [@@deriving yojson, eq] -let outs_pp = - Fmt.( - list ~sep:(Fmt.any "; ") (parens (pair ~sep:(Fmt.any ", ") Expr.pp Expr.pp))) +let outs_pp = Fmt.(list ~sep:semi (parens (pair ~sep:comma Expr.pp Expr.pp))) (** The [mp_step] type represents a matching plan step, consisting of an assertion together with the possible learned outs *) type step = Asrt.atom * outs [@@deriving yojson, eq] -let pp_step = Fmt.pair ~sep:(Fmt.any ", ") Asrt.pp_atom_full outs_pp +let pp_step = Fmt.(pair ~sep:comma Asrt.pp_atom_full outs_pp) let pp_step_list = Fmt.Dump.list pp_step -type label = string * SS.t [@@deriving eq, yojson] +type label = string * LVar.Set.t [@@deriving eq, yojson] -let pp_label ft (lab, ss) = - Fmt.pf ft "LABEL(%s): %a" lab (Fmt.Dump.iter SS.iter Fmt.nop Fmt.string) ss +let pp_label ft ((lab, ss) : label) = + Fmt.pf ft "LABEL(%s): %a" lab Fmt.(Dump.iter LVar.Set.iter nop Id.pp) ss type post = Flag.t * Asrt.t list [@@deriving eq, yojson] @@ -87,10 +84,7 @@ let minimise_matchables (kb : KB.t) : KB.t = KB.fold (fun u ac -> match u with - | UnOp (LstLen, e) -> ( - match KB.mem e kb with - | true -> ac - | false -> KB.add u ac) + | UnOp (LstLen, e) when KB.mem e kb -> ac | _ -> KB.add u ac) kb KB.empty @@ -321,13 +315,32 @@ let simple_ins_expr_collector = method! visit_expr exclude e = match e with - | (LVar s | PVar s | ALoc s) when not (SS.mem s exclude) -> - (KB.empty, KB.singleton e) - | UnOp (LstLen, ((PVar s | LVar s) as v)) when not (SS.mem s exclude) -> + | ALoc s when not @@ Id.Sets.SubstSet.mem (s :> Id.substable Id.t) exclude + -> (KB.empty, KB.singleton e) + | PVar s when not @@ Id.Sets.SubstSet.mem (s :> Id.substable Id.t) exclude + -> (KB.empty, KB.singleton e) + | LVar s when not @@ Id.Sets.SubstSet.mem (s :> Id.substable Id.t) exclude + -> (KB.empty, KB.singleton e) + | UnOp (LstLen, (PVar s as v)) + when not (Id.Sets.SubstSet.mem (s :> Id.substable Id.t) exclude) -> (KB.singleton v, KB.empty) - | Exists (bt, e) | ForAll (bt, e) -> + | UnOp (LstLen, (LVar s as v)) + when not (Id.Sets.SubstSet.mem (s :> Id.substable Id.t) exclude) -> + (KB.singleton v, KB.empty) + | Exists (bt, e) -> + let exclude = + List.fold_left + (fun acc (x, _) -> + Id.Sets.SubstSet.add (x :> Id.substable Id.t) acc) + exclude bt + in + self#visit_expr exclude e + | ForAll (bt, e) -> let exclude = - List.fold_left (fun acc (x, _) -> SS.add x acc) exclude bt + List.fold_left + (fun acc (x, _) -> + Id.Sets.SubstSet.add (x :> Id.substable Id.t) acc) + exclude bt in self#visit_expr exclude e | _ -> super#visit_expr exclude e @@ -337,7 +350,9 @@ let simple_ins_expr_collector = for a given expression [e] *) let simple_ins_expr (e : Expr.t) : KB.t list = let open Expr in - let llens, others = simple_ins_expr_collector#visit_expr SS.empty e in + let llens, others = + simple_ins_expr_collector#visit_expr Id.Sets.SubstSet.empty e + in (* List lengths whose variables do not appear elsewhere *) let llens = Set.elements (Set.diff llens others) in (* Those we can learn by knowing the variable or the list length *) @@ -390,7 +405,13 @@ let ins_and_outs_from_lists (kb : KB.t) (lei : Expr.t list) (leo : Expr.t list) m "Calculated ins: %a" Fmt.(brackets (list ~sep:semi kb_pp)) ins)); let outs : outs = (* Trick to keep track of parameter order *) - let leo = List.mapi (fun i u -> (u, Expr.PVar (string_of_int i))) leo in + let leo = + List.mapi + (fun i u -> + let var = Var.of_string @@ string_of_int i in + (u, Expr.PVar var)) + leo + in (* Outs that are matchables we learn immediately and add to knowledge base *) let kb' = KB.union kb (KB.of_list (snd (List.split leo))) in learn_expr_list kb' leo @@ -536,10 +557,9 @@ let simplify_asrts ?(sorted = true) a = | Pure (BinOp (f1, And, f2)) -> aux (Pure f1) @ aux (Pure f2) | Pure _ | Pred _ | CorePred _ | Wand _ -> [ a ] | Types _ -> ( - let a = Reduction.reduce_assertion [ a ] in - match a with - | [ Types les ] -> List.map (fun e -> Asrt.Types [ e ]) les - | _ -> List.concat_map aux a) + match Reduction.reduce_assertion [ a ] with + | [ Asrt.Types les ] -> List.map (fun e -> Asrt.Types [ e ]) les + | a -> List.concat_map aux a) in let atoms = List.concat_map aux a in if List.mem (Asrt.Pure (Lit (Bool false))) atoms then @@ -643,8 +663,8 @@ let init (params : KB.t) (preds : (string, int list) Hashtbl.t) (asrts_posts : - (Asrt.t * ((string * SS.t) option * (Flag.t * Asrt.t list) option)) list) - : (t, Asrt.atom list list) result = + (Asrt.t * ((string * LVar.Set.t) option * (Flag.t * Asrt.t list) option)) + list) : (t, Asrt.atom list list) result = let known_matchables = match use_params with | None -> known_matchables @@ -658,7 +678,7 @@ let init Option.fold ~some:(fun (_, existentials) -> let existentials = - List.map (fun x -> Expr.LVar x) (SS.elements existentials) + List.map (fun x -> Expr.LVar x) (LVar.Set.elements existentials) in KB.of_list existentials) ~none:KB.empty lab @@ -723,7 +743,8 @@ let init_specs (preds : (string, int list) Hashtbl.t) (specs : Spec.t list) : KB.of_list (List.map (fun x -> Expr.PVar x) spec.spec_params) in let sspecs : - (Asrt.t * ((string * SS.t) option * (Flag.t * Asrt.t list) option)) + (Asrt.t + * ((string * LVar.Set.t) option * (Flag.t * Asrt.t list) option)) list = List.mapi (fun i (sspec : Spec.st) -> @@ -732,7 +753,7 @@ let init_specs (preds : (string, int list) Hashtbl.t) (specs : Spec.t list) : Fmt.( option (brackets - (pair ~sep:(any ": ") string (list ~sep:comma string)))) + (pair ~sep:(any ": ") string (list ~sep:comma Id.pp)))) sspec.ss_label); ( sspec.ss_pre, ( Spec.label_vars_to_set sspec.ss_label, @@ -767,7 +788,8 @@ let init_lemmas (preds : (string, int list) Hashtbl.t) (lemmas : Lemma.t list) : KB.of_list (List.map (fun x -> Expr.PVar x) lemma.lemma_params) in let sspecs : - (Asrt.t * ((string * SS.t) option * (Flag.t * Asrt.t list) option)) + (Asrt.t + * ((string * LVar.Set.t) option * (Flag.t * Asrt.t list) option)) list = List.map (fun spec -> @@ -818,7 +840,7 @@ let init_preds (preds : (string, Pred.t) Hashtbl.t) : List.map (fun (lab, def) -> let lab' = - Option.map (fun (s, vars) -> (s, SS.of_list vars)) lab + Option.map (fun (s, vars) -> (s, LVar.Set.of_list vars)) lab in (def, (lab', None))) pred.pred_definitions @@ -910,7 +932,7 @@ let pp_asrt let in_args = Pred.in_args pred.pred args in let out_params_args = List.combine out_params out_args in let pp_out_params_args fmt (x, e) = - Fmt.pf fmt "@[%s: %a@]" x Expr.pp e + Fmt.pf fmt "@[%a: %a@]" Id.pp x Expr.pp e in Fmt.pf fmt "%s(@[%a@])" name (Pred.pp_ins_outs pred.pred Expr.pp pp_out_params_args) @@ -942,7 +964,7 @@ let pp_spec in let pp_sspec = pp_sspec ?preds_printer ~preds in Fmt.pf fmt "@[spec %s (@[%a@])@\n%a;@\n%a@]" spec.spec_name - Fmt.(list ~sep:comma string) + Fmt.(list ~sep:comma Id.pp) spec.spec_params Fmt.(list ~sep:(any "@\n") pp_sspec) normal_specs @@ -961,7 +983,7 @@ let pp_normal_spec in let pp_sspec = pp_sspec ?preds_printer ~preds in Fmt.pf fmt "@[spec %s (@[%a@])@\n%a@]" spec.spec_name - Fmt.(list ~sep:comma string) + Fmt.(list ~sep:comma Id.pp) spec.spec_params Fmt.(list ~sep:(any "@\n") pp_sspec) normal_specs diff --git a/GillianCore/engine/Abstraction/MP.mli b/GillianCore/engine/Abstraction/MP.mli index 42b4752dc..8ab0be586 100644 --- a/GillianCore/engine/Abstraction/MP.mli +++ b/GillianCore/engine/Abstraction/MP.mli @@ -1,5 +1,3 @@ -open Containers - type outs = (Expr.t * Expr.t) list val outs_pp : outs Fmt.t @@ -9,7 +7,7 @@ val outs_pp : outs Fmt.t learned outs *) type step = Asrt.atom * outs [@@deriving yojson] -type label = string * SS.t [@@deriving yojson] +type label = string * LVar.Set.t [@@deriving yojson] type post = Flag.t * Asrt.t list [@@deriving yojson] val pp_step : step Fmt.t @@ -68,7 +66,7 @@ val init : KB.t -> KB.t -> (string, int list) Hashtbl.t -> - (Asrt.t * ((string * SS.t) option * (Flag.t * Asrt.t list) option)) list -> + (Asrt.t * ((string * LVar.Set.t) option * (Flag.t * Asrt.t list) option)) list -> (t, Asrt.t list) result val init_prog : diff --git a/GillianCore/engine/Abstraction/Matcher.ml b/GillianCore/engine/Abstraction/Matcher.ml index 8af919b1a..e9159c331 100644 --- a/GillianCore/engine/Abstraction/Matcher.ml +++ b/GillianCore/engine/Abstraction/Matcher.ml @@ -74,7 +74,7 @@ module type S = sig end end - type unfold_info_t = (string * string) list + type unfold_info_t = (LVar.t * LVar.t) list val produce_assertion : t -> SVal.SESubst.t -> Asrt.atom -> (t, err_t) Res_list.t @@ -142,7 +142,6 @@ end module Make (State : SState.S) : S with type state_t = State.t and type err_t = State.err_t = struct open Literal - open Containers module L = Logging type state_t = State.t [@@deriving yojson] @@ -162,7 +161,7 @@ module Make (State : SState.S) : type s_state = t * SVal.SESubst.t * MP.t type search_state = s_state list * err_t list type search_state' = (s_state * L.Report_id.t option) list * err_t list - type unfold_info_t = (string * string) list + type unfold_info_t = (LVar.t * LVar.t) list (* This is mostly to do with Gillian legacy. We have to handle UX and OX separately, or otherwise @@ -180,8 +179,12 @@ module Make (State : SState.S) : (Fmt.hashtbl ~sep:Fmt.semi pp_variants) variants - let pp_astate_by_need (pvars : SS.t) (lvars : SS.t) (locs : SS.t) fmt astate - = + let pp_astate_by_need + (pvars : Var.Set.t) + (lvars : LVar.Set.t) + (locs : Id.Sets.LocSet.t) + fmt + astate = let { state; preds; wands; variants; _ } = astate in Fmt.pf fmt "%a@\n@\nPREDS:@\n%a@\nWANDS:@\n%a@\nVARIANTS:@\n%a@\n" (State.pp_by_need pvars lvars locs) @@ -317,7 +320,7 @@ module Make (State : SState.S) : else if State.assert_a state [ f ] then Success state else Abort f - let update_store (astate : t) (x : string) (v : Expr.t) : t = + let update_store (astate : t) (x : Var.t) (v : Expr.t) : t = let store = State.get_store astate.state in let () = SStore.put store x v in let state' = State.set_store astate.state store in @@ -466,12 +469,10 @@ module Make (State : SState.S) : (* Strategy 4: Predicate has non-literal parameters in pure formulae *) let strategy_4 ~state ((name, args) : string * Expr.t list) : int = print_local_info 4 name args; - let lvars_state = State.get_spec_vars state in - let lvars_args = - List.fold_left SS.union SS.empty (List.map Expr.lvars args) - in - let inter = SS.inter lvars_args lvars_state in - SS.cardinal inter + let lvars_state = Id.Sets.substset_to_lvar @@ State.get_spec_vars state in + List.map Expr.lvars args + |> List.fold_left LVar.Set.union LVar.Set.empty + |> LVar.Set.inter lvars_state |> LVar.Set.cardinal end let consume_pred_with_vs @@ -652,8 +653,8 @@ module Make (State : SState.S) : L.verbose (fun m -> m "UNHAPPY. update_store inside produce assertions with prog \ - variable: %s!!!\n" - x); + variable: %a!!!\n" + Id.pp x); Res_list.return (update_store astate x v)) | Pure f -> ( L.verbose (fun fmt -> fmt "Pure assertion."); @@ -760,9 +761,10 @@ module Make (State : SState.S) : | _ -> ()); Some state) - let complete_subst (subst : SVal.SESubst.t) (lab : string * SS.t) : unit = + let complete_subst (subst : SVal.SESubst.t) (lab : string * LVar.Set.t) : unit + = let _, existentials = lab in - SS.iter + LVar.Set.iter (fun x -> let lvar = Expr.LVar x in if not (SVal.SESubst.mem subst lvar) then @@ -778,7 +780,7 @@ module Make (State : SState.S) : let extend_subst_with_bindings (state : State.t) (subst : SVal.SESubst.t) - (bindings : (string * string) list) : unit = + (bindings : (LVar.t * LVar.t) list) : unit = let bindings = List.map (fun (x, y) -> (Expr.LVar y, State.eval_expr state (Expr.LVar x))) @@ -829,11 +831,13 @@ module Make (State : SState.S) : L.verbose (fun m -> m "unfold with unfold_info with additional bindings@\n%a@\n" - Fmt.(Dump.list (pair string string)) + Fmt.(Dump.list (pair Id.pp Id.pp)) additional_bindings); let new_spec_vars = - List.to_seq additional_bindings |> Seq.map fst |> SS.of_seq + (List.to_seq additional_bindings |> Seq.map fst + :> Id.substable Id.t Seq.t) + |> Id.Sets.SubstSet.of_seq in let () = extend_subst_with_bindings state subst_i additional_bindings in let definitions = @@ -1102,7 +1106,9 @@ module Make (State : SState.S) : fmt "Obtained exprs: %a" Fmt.(brackets (list ~sep:semi Expr.pp)) eos); (* Substitution of the program variables *) let pvar_subst_bindings = - List.mapi (fun i v -> (Expr.PVar (string_of_int i), v)) vos + List.mapi + (fun i v -> (Expr.PVar (Var.of_string (string_of_int i)), v)) + vos in let pvar_subst = SVal.SESubst.init pvar_subst_bindings in L.verbose (fun fmt -> fmt "Parameter subst\n%a" SVal.SESubst.pp pvar_subst); @@ -1164,52 +1170,50 @@ module Make (State : SState.S) : let { state; wands; preds; pred_defs; variants } = astate in let assertion_loggable = + let open Id.Sets in let+ () = if L.Mode.enabled () then Some () else None in let a = fst step in - (* Get pvars, lvars, locs from the assertion *) - let a_pvars, a_lvars, a_locs = - (Asrt.pvars [ a ], Asrt.lvars [ a ], Asrt.locs [ a ]) + (* Get pvars, lvars, alocs from the assertion *) + let a_pvars, a_lvars, a_alocs = + (Asrt.pvars [ a ], Asrt.lvars [ a ], Asrt.alocs [ a ]) in - let filter_vars = SS.union a_pvars (SS.union a_lvars a_locs) in (* From the subst, we take any pair that has any of those and collect the pvars, lvars, and alocs, from their values *) - let s_pvars, s_lvars, s_locs = + let s_pvars, s_lvars, s_alocs = SVal.SESubst.fold subst - (fun e v (s_pvars, s_lvars, s_locs) -> - let pvars, lvars, locs = - (Expr.pvars e, Expr.lvars e, Expr.locs e) - in + (fun e v (s_pvars, s_lvars, s_alocs) -> if - Containers.SS.inter - (List.fold_left SS.union SS.empty [ pvars; lvars; locs ]) - filter_vars - <> SS.empty - then - ( SS.union s_pvars (Expr.pvars v), - SS.union s_lvars (Expr.lvars v), - SS.union s_locs (Expr.locs v) ) - else (s_pvars, s_lvars, s_locs)) - (SS.empty, SS.empty, SS.empty) + (Var.Set.is_empty @@ Var.Set.inter a_pvars @@ Expr.pvars e) + && (LVar.Set.is_empty @@ LVar.Set.inter a_lvars @@ Expr.lvars e) + && (ALoc.Set.is_empty @@ ALoc.Set.inter a_alocs @@ Expr.alocs e) + then (s_pvars, s_lvars, s_alocs) + else + ( Var.Set.union s_pvars @@ Expr.pvars v, + LVar.Set.union s_lvars @@ Expr.lvars v, + ALoc.Set.union s_alocs @@ Expr.alocs v )) + (Var.Set.empty, LVar.Set.empty, ALoc.Set.empty) in let subst_pp = match !Config.pbn with | false -> SVal.SESubst.pp - | true -> - SVal.SESubst.pp_by_need (SS.union a_pvars (SS.union a_lvars a_locs)) + | true -> SVal.SESubst.pp_by_need a_pvars a_lvars a_alocs in - let pp_str_list = Fmt.(brackets (list ~sep:comma string)) in - L.verbose (fun fmt -> - fmt "Substs:\n%a\n%a\n%a" pp_str_list (SS.elements s_pvars) - pp_str_list (SS.elements s_lvars) pp_str_list (SS.elements s_locs)); + fmt "Substs:\n%a\n%a\n%a" + Fmt.(brackets @@ iter ~sep:comma Var.Set.iter Id.pp) + s_pvars + Fmt.(brackets @@ iter ~sep:comma LVar.Set.iter Id.pp) + s_lvars + Fmt.(brackets @@ iter ~sep:comma ALoc.Set.iter Id.pp) + s_alocs); let pp_astate = match !Config.pbn with | false -> pp_astate - | true -> pp_astate_by_need s_pvars s_lvars s_locs + | true -> pp_astate_by_need s_pvars s_lvars (aloc_to_loc s_alocs) in AssertionReport.to_loggable pp_astate subst_pp @@ -1462,7 +1466,7 @@ module Make (State : SState.S) : m "Reached LabelStep, about to complete substitution with \ vars: %a" - Fmt.(Dump.iter SS.iter nop string) + Fmt.(Dump.iter LVar.Set.iter nop Id.pp) (snd label)); complete_subst subst label; let current_state = ((astate, subst, rest_mp), prev_id) in @@ -1872,15 +1876,15 @@ module Make (State : SState.S) : type split_answer = { init_subst : State.st; mp : MP.t; - fold_outs_info : State.st * MP.step * string list * Expr.t list; + fold_outs_info : State.st * MP.step * Var.t list * Expr.t list; } let matchables expr = let lvars = - Expr.lvars expr |> SS.to_seq |> Seq.map (fun x -> Expr.LVar x) + Expr.lvars expr |> LVar.Set.to_seq |> Seq.map (fun x -> Expr.LVar x) in let alocs = - Expr.alocs expr |> SS.to_seq |> Seq.map Expr.loc_from_loc_name + Expr.alocs expr |> ALoc.Set.to_seq |> Seq.map (fun x -> Expr.ALoc x) in Seq.append lvars alocs @@ -1939,7 +1943,9 @@ module Make (State : SState.S) : MP.KB.to_seq kb |> Seq.map (fun x -> (x, x)) |> SVal.SESubst.of_seq in let out_params = - List.mapi (fun i _ -> "out___" ^ string_of_int i) outs + List.mapi + (fun i _ -> Var.of_string @@ "out___" ^ string_of_int i) + outs in (* Now we build our assertion *) let+ new_ins_l, new_outs_learn = @@ -1957,14 +1963,11 @@ module Make (State : SState.S) : Expr.LVar (LVar.alloc ())) in let pvar_subst = - let seq = - Seq.concat - @@ Seq.init cp_amount (fun i -> - Seq.init out_amount (fun j -> - let id = Fmt.str "%d:%d" i j in - (Expr.PVar id, all_new_outs.((i * out_amount) + j)))) - in - SVal.SESubst.of_seq seq + SVal.SESubst.of_seq @@ Seq.concat + @@ Seq.init cp_amount (fun i -> + Seq.init out_amount (fun j -> + let id = Var.of_string @@ Fmt.str "%d:%d" i j in + (Expr.PVar id, all_new_outs.((i * out_amount) + j)))) in let new_cps = List.mapi @@ -2014,7 +2017,9 @@ module Make (State : SState.S) : let open Syntaxes.List in let outs = snd step in let pvar_subst = - List.mapi (fun i v -> (Expr.PVar (string_of_int i), v)) obtained + List.mapi + (fun i v -> (Expr.PVar (Var.of_string @@ string_of_int i), v)) + obtained |> SVal.SESubst.init in let outs = @@ -2087,7 +2092,7 @@ module Make (State : SState.S) : (fun x -> match SVal.SESubst.get state.subst (PVar x) with | Some x -> x - | None -> Fmt.failwith "Did not learn %s ??" x) + | None -> Fmt.failwith "Did not learn %a ??" Id.pp x) out_params in let+ state = diff --git a/GillianCore/engine/Abstraction/Matcher.mli b/GillianCore/engine/Abstraction/Matcher.mli index 3e41c9ffb..497ab1244 100644 --- a/GillianCore/engine/Abstraction/Matcher.mli +++ b/GillianCore/engine/Abstraction/Matcher.mli @@ -74,7 +74,7 @@ module type S = sig end end - type unfold_info_t = (string * string) list + type unfold_info_t = (LVar.t * LVar.t) list val produce_assertion : t -> SVal.SESubst.t -> Asrt.atom -> (t, err_t) Res_list.t diff --git a/GillianCore/engine/Abstraction/Normaliser.ml b/GillianCore/engine/Abstraction/Normaliser.ml index 7182ef4f0..e10f377c6 100644 --- a/GillianCore/engine/Abstraction/Normaliser.ml +++ b/GillianCore/engine/Abstraction/Normaliser.ml @@ -1,9 +1,8 @@ open Names -open Containers module L = Logging module SESubst = SVal.SESubst -let new_lvar_name var = lvar_prefix ^ var +let lvar_of_var var = LVar.of_string (lvar_prefix ^ Var.str var) module Make (SPState : PState.S) = struct (* ------------------------------------------------------------------ @@ -220,7 +219,7 @@ module Make (SPState : PState.S) = struct bt; let ne = normalise_lexpr ~no_types ~store ~subst new_gamma e in let lvars = Expr.lvars ne in - let bt = List.filter (fun (x, _) -> SS.mem x lvars) bt in + let bt = List.filter (fun (x, _) -> LVar.Set.mem x lvars) bt in match (bt, le) with | [], _ -> ne | _, Exists _ -> Exists (bt, ne) @@ -234,21 +233,16 @@ module Make (SPState : PState.S) = struct let extend_typing_env_using_assertion_info (gamma : Type_env.t) (a_list : Expr.t list) : unit = + let fn (x : [< Id.any_var ] Id.t) e = + if not @@ Type_env.mem gamma x then + Typing.type_lexpr gamma e |> fst + |> Option.iter @@ Type_env.update gamma x + in + List.iter - (fun a -> - match (a : Expr.t) with - | BinOp (LVar x, Equal, le) - | BinOp (le, Equal, LVar x) - | BinOp (PVar x, Equal, le) - | BinOp (le, Equal, PVar x) -> ( - let x_type = Type_env.get gamma x in - match x_type with - | None -> - let le_type, _ = Typing.type_lexpr gamma le in - Option.fold - ~some:(fun x_type -> Type_env.update gamma x x_type) - ~none:() le_type - | Some _ -> ()) + (function + | Expr.BinOp (LVar x, Equal, le) | BinOp (le, Equal, LVar x) -> fn x le + | BinOp (PVar x, Equal, le) | BinOp (le, Equal, PVar x) -> fn x le | _ -> ()) a_list @@ -261,7 +255,7 @@ module Make (SPState : PState.S) = struct (store : SStore.t) (gamma : Type_env.t) (subst : SESubst.t) - (args : SS.t option) + (args : Var.Set.t option) (fs : Expr.t list) : PFS.t = let pvar_equalities = Hashtbl.create 1 in let non_store_pure_assertions = Stack.create () in @@ -294,10 +288,16 @@ module Make (SPState : PState.S) = struct * Step 2 - Build a table mapping pvars to integers * ------------------------------------------------ *) - let get_vars_tbl (vars : SS.t) : (string, int) Hashtbl.t = - let len = SS.cardinal vars in + let get_vars_tbl (vars : Var.Set.t) : (Var.t, int) Hashtbl.t = + let len = Var.Set.cardinal vars in let vars_tbl = Hashtbl.create len in - List.iteri (fun i var -> Hashtbl.add vars_tbl var i) (SS.elements vars); + let _ = + Var.Set.fold + (fun var i -> + Hashtbl.add vars_tbl var i; + i + 1) + vars 0 + in vars_tbl in @@ -308,23 +308,22 @@ module Make (SPState : PState.S) = struct * definitions) * ------------------------------------------------------------------------ *) - let pvars_graph (p_vars : SS.t) (p_vars_tbl : (string, int) Hashtbl.t) : + let pvars_graph (p_vars : Var.Set.t) (p_vars_tbl : (Var.t, int) Hashtbl.t) : int list array = - let len = SS.cardinal p_vars in + let len = Var.Set.cardinal p_vars in let graph = Array.make len [] in List.iteri (fun u cur_var -> let cur_le = Hashtbl.find pvar_equalities cur_var in let cur_var_deps = Expr.pvars cur_le in - SS.iter + Var.Set.iter (fun v -> - try - let v_num = Hashtbl.find p_vars_tbl v in - graph.(u) <- v_num :: graph.(u) - with _ -> ()) + match Hashtbl.find_opt p_vars_tbl v with + | Some v_num -> graph.(u) <- v_num :: graph.(u) + | None -> ()) cur_var_deps) - (SS.elements p_vars); + (Var.Set.elements p_vars); graph in @@ -339,14 +338,14 @@ module Make (SPState : PState.S) = struct * (x = y + 1) * (y = #z) ==> (x = #z + 1) * (y = #z) * (x = y + 1) * (y = (3 * x) - 2) ==> (x = #w + 1) * (y = #y) * (#y = (3 * (#y + 1)) - 2) - where #y = new_lvar_name (y) + where #y = lvar_of_var (y) * ------------------------------------------------------------------------ *) let normalise_pvar_equalities (graph : int list array) - (p_vars : SS.t) - (_ : (string, int) Hashtbl.t) = - let p_vars = Array.of_list (SS.elements p_vars) in + (p_vars : Var.Set.t) + (_ : (Var.t, int) Hashtbl.t) = + let p_vars = Array.of_list (Var.Set.elements p_vars) in let len = Array.length p_vars in let visited_tbl = Array.make len false in @@ -360,17 +359,14 @@ module Make (SPState : PState.S) = struct try let e = Hashtbl.find pvar_equalities var in Stack.push - (Expr.BinOp (LVar (new_lvar_name var), Equal, e)) + (Expr.BinOp (LVar (lvar_of_var var), Equal, e)) non_store_pure_assertions; Hashtbl.remove pvar_equalities var with _ -> - let msg = - Printf.sprintf - "DEATH. normalise_pure_assertions -> normalise_pvar_equalities \ - -> remove_assignment. Var: %s." - var - in - raise (Failure msg) + Fmt.failwith + "DEATH. normalise_pure_assertions -> normalise_pvar_equalities -> \ + remove_assignment. Var: %a." + Id.pp var in (* lifting an assignment to the abstract store *) @@ -381,13 +377,10 @@ module Make (SPState : PState.S) = struct SStore.put store var le'; () with _ -> - let msg = - Printf.sprintf - "DEATH. normalise_pure_assertions -> normalise_pvar_equalities \ - -> rewrite_assignment. Var: %s\n" - var - in - raise (Failure msg) + Fmt.failwith + "DEATH. normalise_pure_assertions -> normalise_pvar_equalities -> \ + rewrite_assignment. Var: %a\n" + Id.pp var in (* DFS on pvar dependency graph *) @@ -418,13 +411,13 @@ module Make (SPState : PState.S) = struct *) let fill_store args = let def_pvars = - fs |> List.map Expr.pvars |> List.fold_left SS.union SS.empty + fs |> List.map Expr.pvars |> List.fold_left Var.Set.union Var.Set.empty in let p_vars = Option.value ~default:def_pvars args in - SS.iter + Var.Set.iter (fun var -> if not (SStore.mem store var) then ( - SStore.put store var (LVar (new_lvar_name var)); + SStore.put store var (LVar (lvar_of_var var)); ())) p_vars in @@ -453,7 +446,7 @@ module Make (SPState : PState.S) = struct L.verbose (fun m -> m "About to simplify."); let _ = Simplifications.simplify_pfs_and_gamma pfs gamma ~matching:true - ~save_spec_vars:(SS.empty, true) + ~save_spec_vars:(LVar.Set.empty, true) in L.verbose (fun m -> m "Done simplifying."); pfs @@ -463,12 +456,15 @@ module Make (SPState : PState.S) = struct (* 1 *) init_pvar_equalities fs; let p_vars = - Hashtbl.fold (fun var _ ac -> SS.add var ac) pvar_equalities SS.empty + Hashtbl.fold + (fun var _ ac -> Var.Set.add var ac) + pvar_equalities Var.Set.empty in L.verbose (fun m -> - m "PVars in normalise_pvar_equalities: %s\n" - (String.concat ", " (SS.elements p_vars))); + m "PVars in normalise_pvar_equalities: %a\n" + Fmt.(iter ~sep:comma Var.Set.iter Id.pp) + p_vars); (* 2 *) let p_vars_tbl = get_vars_tbl p_vars in @@ -675,7 +671,7 @@ module Make (SPState : PState.S) = struct (store : SStore.t) (pfs : PFS.t) (gamma : Type_env.t) - (svars : SS.t) + (svars : LVar.Set.t) (subst : SESubst.t) (c_asrts : (string * Expr.t list * Expr.t list) list) : (string * Expr.t list * Expr.t list) list * SESubst.t * SESubst.t = @@ -690,11 +686,12 @@ module Make (SPState : PState.S) = struct List.iter (fun fo -> PFS.extend new_pfs fo) fos; let subst', _ = Simplifications.simplify_pfs_and_gamma new_pfs gamma ~matching:true - ~save_spec_vars:(SS.empty, true) + ~save_spec_vars:(LVar.Set.empty, true) in let subst = compose_substs subst subst' in let lsvars = - Expr.Set.of_list (List.map (fun x -> Expr.LVar x) (SS.elements svars)) + Expr.Set.of_list + (List.map (fun x -> Expr.LVar x) (LVar.Set.elements svars)) in let subst' = SESubst.filter subst' (fun x _ -> not (Expr.Set.mem x lsvars)) @@ -720,14 +717,16 @@ module Make (SPState : PState.S) = struct (astate : SPState.t) (core_asrts : (string * Expr.t list * Expr.t list) list) : SPState.t list = - let f_aux (es : Expr.t list) : SS.t * SS.t = + let f_aux (es : Expr.t list) : LVar.Set.t * ALoc.Set.t = List.fold_left (fun (ret1, ret2) e -> - (SS.union ret1 (Expr.lvars e), SS.union ret2 (Expr.alocs e))) - (SS.empty, SS.empty) es + ( LVar.Set.union ret1 (Expr.lvars e), + ALoc.Set.union ret2 (Expr.alocs e) )) + (LVar.Set.empty, ALoc.Set.empty) + es in - let (lvars : SS.t), (alocs : SS.t) = + let (lvars : LVar.Set.t), (alocs : ALoc.Set.t) = List.fold_left (fun (ret1, ret2) (id, ins, outs) -> L.verbose (fun m -> @@ -735,17 +734,18 @@ module Make (SPState : PState.S) = struct outs); let lv_ins, al_ins = f_aux ins in let lv_outs, al_outs = f_aux outs in - let ret1' = SS.union ret1 (SS.union lv_ins lv_outs) in - let ret2' = SS.union ret2 (SS.union al_ins al_outs) in + let ret1' = LVar.Set.union ret1 (LVar.Set.union lv_ins lv_outs) in + let ret2' = ALoc.Set.union ret2 (ALoc.Set.union al_ins al_outs) in (ret1', ret2')) - (SS.empty, SS.empty) core_asrts + (LVar.Set.empty, ALoc.Set.empty) + core_asrts in let lv_bnds = - List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (SS.elements lvars) + List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (LVar.Set.elements lvars) in let al_bnds = - List.map (fun l -> (Expr.ALoc l, Expr.ALoc l)) (SS.elements alocs) + List.map (fun l -> (Expr.ALoc l, Expr.ALoc l)) (ALoc.Set.elements alocs) in let subst = SESubst.init (lv_bnds @ al_bnds) in @@ -779,26 +779,20 @@ module Make (SPState : PState.S) = struct None)) [ astate ] - let subst_to_pfs ?(svars : SS.t option) (subst : SESubst.t) : Expr.t list = - let subst_lvs = SESubst.to_list subst in - let subst_lvs' = - match svars with - | Some svars -> - List.filter - (fun (e, _) -> - match e with - | Expr.LVar x -> SS.mem x svars - | _ -> false) - subst_lvs - | None -> - List.filter - (fun (e, _) -> - match e with - | Expr.LVar _ -> true - | _ -> false) - subst_lvs - in - List.map (fun (e, le) -> Expr.BinOp (e, Equal, le)) subst_lvs' + let subst_to_pfs ?(svars : LVar.Set.t option) (subst : SESubst.t) : + Expr.t list = + SESubst.to_list subst + |> List.filter + (match svars with + | Some svars -> ( + function + | Expr.LVar x, _ -> LVar.Set.mem x svars + | _ -> false) + | None -> ( + function + | Expr.LVar _, _ -> true + | _ -> false)) + |> List.map (fun (e, le) -> Expr.BinOp (e, Equal, le)) let normalise_a_bit (a : Asrt.t) = let a = Reduction.reduce_assertion a in @@ -807,10 +801,10 @@ module Make (SPState : PState.S) = struct let find_spec_var_eqs (a : Asrt.atom) = match a with | Pure (BinOp (LVar x, Equal, LVar y)) - when is_spec_var_name x && not (is_spec_var_name y) -> + when LVar.is_spec_var_name x && not (LVar.is_spec_var_name y) -> SESubst.put subst (LVar y) (LVar x) | Pure (BinOp (LVar x, Equal, LVar y)) - when is_spec_var_name y && not (is_spec_var_name x) -> + when LVar.is_spec_var_name y && not (LVar.is_spec_var_name x) -> SESubst.put subst (LVar x) (LVar y) | _ -> () in @@ -821,14 +815,14 @@ module Make (SPState : PState.S) = struct let normalise_assertion ~(pred_defs : MP.preds_tbl_t) ~(init_data : SPState.init_data) - ?(pvars : SS.t option) + ?(pvars : Var.Set.t option) (a : Asrt.t) : ((SPState.t * SESubst.t) list, string) result = let falsePFs pfs = PFS.mem pfs Expr.false_ in let a = normalise_a_bit a in - let svars = SS.filter is_spec_var_name (Asrt.lvars a) in + let svars = LVar.Set.filter LVar.is_spec_var_name (Asrt.lvars a) in L.verbose (fun m -> m "@[Normalising assertion:@ %a@]@ svars: @[%a@]" Asrt.pp a - (Fmt.iter ~sep:Fmt.comma SS.iter Fmt.string) + (Fmt.iter ~sep:Fmt.comma LVar.Set.iter Id.pp) svars); (* Step 1 -- Preprocess list expressions - resolve l-nth(E, i) when possible *) @@ -879,8 +873,8 @@ module Make (SPState : PState.S) = struct (* Step 6 -- Extend pfs with info on subst *) L.verbose (fun m -> m "Subst before extenzion:\n%a" SESubst.pp subst'); - List.iter (fun pf -> PFS.extend pfs pf) (subst_to_pfs subst'); - List.iter (fun pf -> PFS.extend pfs pf) (subst_to_pfs subst); + List.iter (PFS.extend pfs) (subst_to_pfs subst'); + List.iter (PFS.extend pfs) (subst_to_pfs subst); L.verbose (fun m -> m "PFS after extenzion:\n%a" PFS.pp pfs); (* Step 7 -- Construct the state *) @@ -888,7 +882,8 @@ module Make (SPState : PState.S) = struct let wands' = normalise_wands wands in let astate : SPState.t = SPState.make_p ~preds:pred_defs ~init_data ~store ~pfs ~gamma - ~spec_vars:svars () + ~spec_vars:(Id.Sets.lvar_to_subst svars) + () in let astate = SPState.set_preds astate preds' in let astate = SPState.set_wands astate wands' in diff --git a/GillianCore/engine/Abstraction/Normaliser.mli b/GillianCore/engine/Abstraction/Normaliser.mli index 116daf424..aeb765216 100644 --- a/GillianCore/engine/Abstraction/Normaliser.mli +++ b/GillianCore/engine/Abstraction/Normaliser.mli @@ -6,7 +6,7 @@ module Make (SPState : PState.S) : sig val normalise_assertion : pred_defs:MP.preds_tbl_t -> init_data:SPState.init_data -> - ?pvars:Utils.Containers.SS.t -> + ?pvars:Var.Set.t -> Asrt.t -> ((SPState.t * SVal.SESubst.t) list, string) result end diff --git a/GillianCore/engine/Abstraction/PState.ml b/GillianCore/engine/Abstraction/PState.ml index bb2a29235..c200949ce 100644 --- a/GillianCore/engine/Abstraction/PState.ml +++ b/GillianCore/engine/Abstraction/PState.ml @@ -14,7 +14,7 @@ module type S = sig store:store_t -> pfs:PFS.t -> gamma:Type_env.t -> - spec_vars:SS.t -> + spec_vars:Id.Sets.SubstSet.t -> unit -> t @@ -43,7 +43,6 @@ module Make (State : SState.S) : and type heap_t = State.heap_t and type m_err_t = State.m_err_t and type init_data = State.init_data = struct - open Containers open Literal module L = Logging module SMatcher = Matcher.Make (State) @@ -119,7 +118,7 @@ module Make (State : SState.S) : ~(store : store_t) ~(pfs : PFS.t) ~(gamma : Type_env.t) - ~(spec_vars : SS.t) + ~(spec_vars : Id.Sets.SubstSet.t) () : t = let state = State.make_s ~init_data ~store ~pfs ~gamma ~spec_vars in let variants = Hashtbl.create 1 in @@ -250,19 +249,20 @@ module Make (State : SState.S) : (State.pp_by_need pvars lvars locs) state Preds.pp preds Wands.pp wands - let add_spec_vars (astate : t) (vs : Var.Set.t) : t = + let add_spec_vars (astate : t) (vs : Id.Sets.SubstSet.t) : t = let state = State.add_spec_vars astate.state vs in { astate with state } - let get_spec_vars (astate : t) : Var.Set.t = State.get_spec_vars astate.state + let get_spec_vars (astate : t) : Id.Sets.SubstSet.t = + State.get_spec_vars astate.state - let get_lvars (astate : t) : Var.Set.t = + let get_lvars (astate : t) : LVar.Set.t = let { state; preds; wands; _ } = astate in State.get_lvars state - |> SS.union (Preds.get_lvars preds) - |> SS.union (Wands.get_lvars wands) + |> LVar.Set.union (Preds.get_lvars preds) + |> LVar.Set.union (Wands.get_lvars wands) - let to_assertions ?(to_keep : SS.t option) (astate : t) : Asrt.t = + let to_assertions ?to_keep (astate : t) : Asrt.t = let { state; preds; wands; _ } = astate in let s_asrts = State.to_assertions ?to_keep state in let p_asrts = Preds.to_assertions preds in @@ -295,7 +295,7 @@ module Make (State : SState.S) : }) (State.substitution_in_place ~subst_all subst state) - let update_store (state : t) (x : string option) (v : Expr.t) : t = + let update_store (state : t) (x : Var.t option) (v : Expr.t) : t = match x with | None -> state | Some x -> @@ -307,12 +307,12 @@ module Make (State : SState.S) : (* FIXME: This needs to change -> we need to return a matching ret type, so we can compose with bi-abduction at the spec level *) let run_spec_aux - ?(existential_bindings : (string * vt) list option) + ?(existential_bindings : (LVar.t * vt) list option) (name : string) - (params : string list) + (params : Var.t list) (mp : MP.t) (astate : t) - (x : string option) + (x : Var.t option) (args : vt list) : (t * Flag.t, SMatcher.err_t) Res_list.t = L.verbose (fun m -> m "INSIDE RUN spec of %s with the following MP:@\n%a@\n" name MP.pp mp); @@ -365,7 +365,7 @@ module Make (State : SState.S) : (* OK FOR DELAY ENTAILMENT *) let* final_state = SMatcher.produce_posts frame_state subst posts in let final_store = get_store final_state in - let v_ret = SStore.get final_store Names.return_variable in + let v_ret = SStore.get final_store Id.return_variable in let final_state = set_store final_state (SStore.copy old_store) in let v_ret = Option.value ~default:(Lit Undefined) v_ret in let final_state = update_store final_state x v_ret in @@ -376,8 +376,8 @@ module Make (State : SState.S) : in Ok (with_unfolded_concrete, fl) - let fresh_subst (xs : SS.t) : SVal.SESubst.t = - let xs = SS.elements xs in + let fresh_subst (xs : LVar.Set.t) : SVal.SESubst.t = + let xs = LVar.Set.elements xs in let bindings = List.map (fun x -> (Expr.LVar x, Expr.LVar (LVar.alloc ()))) xs in @@ -387,10 +387,10 @@ module Make (State : SState.S) : let lvars = Asrt.lvars a in let alocs = Asrt.alocs a in let lvars_subst = - List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (SS.elements lvars) + List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (LVar.Set.elements lvars) in let alocs_subst = - List.map (fun x -> (Expr.ALoc x, Expr.ALoc x)) (SS.elements alocs) + List.map (fun x -> (Expr.ALoc x, Expr.ALoc x)) (ALoc.Set.elements alocs) in let subst_lst = lvars_subst @ alocs_subst in SVal.SESubst.init subst_lst @@ -411,15 +411,16 @@ module Make (State : SState.S) : { state; preds; wands = Wands.init []; pred_defs; variants } let consume ~(prog : 'a MP.prog) astate (a : Asrt.t) binders = - if not (List.for_all Names.is_lvar_name binders) then - failwith "Binding of pure variables in *-assert."; + (* With type-checked variables, this can be removed I think. + if not (List.for_all (fun x -> Names.is_lvar_name @@ LVar.str x) binders) + then failwith "Binding of pure variables in *-assert."; *) let store = State.get_store astate.state in let pvars_store = SStore.domain store in let pvars_a = Asrt.pvars a in - let pvars_diff = SS.diff pvars_a pvars_store in - (if not (SS.is_empty pvars_diff) then + let pvars_diff = Var.Set.diff pvars_a pvars_store in + (if not (Var.Set.is_empty pvars_diff) then let pvars_errs : err_t list = - List.map (fun pvar : err_t -> EVar pvar) (SS.elements pvars_diff) + List.map (fun pvar : err_t -> EVar pvar) (Var.Set.elements pvars_diff) in raise (Internal_State_Error (pvars_errs, astate))); let store_subst = SStore.to_ssubst store in @@ -427,12 +428,12 @@ module Make (State : SState.S) : (* let known_vars = SS.diff (SS.filter is_spec_var_name (Asrt.lvars a)) (SS.of_list binders) in *) let state_lvars = State.get_lvars astate.state in let known_lvars = - SS.elements - (SS.diff (SS.inter state_lvars (Asrt.lvars a)) (SS.of_list binders)) + LVar.Set.( + elements (diff (inter state_lvars (Asrt.lvars a)) (of_list binders))) in let known_lvars = List.map (fun x -> Expr.LVar x) known_lvars in let asrt_alocs = - List.map (fun x -> Expr.ALoc x) (SS.elements (Asrt.alocs a)) + List.map (fun x -> Expr.ALoc x) (ALoc.Set.elements (Asrt.alocs a)) in let known_matchables = Expr.Set.of_list (known_lvars @ asrt_alocs) in @@ -448,12 +449,14 @@ module Make (State : SState.S) : let mp = MP.init known_matchables Expr.Set.empty pred_ins [ (a, (None, None)) ] in - let vars_to_forget = SS.inter state_lvars (SS.of_list binders) in - if not (SS.is_empty vars_to_forget) then ( + let vars_to_forget = + LVar.Set.inter state_lvars (LVar.Set.of_list binders) + in + if not (LVar.Set.is_empty vars_to_forget) then ( let oblivion_subst = fresh_subst vars_to_forget in L.verbose (fun m -> m "Forget @[%a@] with subst: %a" - Fmt.(iter ~sep:comma SS.iter string) + Fmt.(iter ~sep:comma LVar.Set.iter Id.pp) vars_to_forget SVal.SESubst.pp oblivion_subst); (* TODO: THIS SUBST IN PLACE MUST NOT BRANCH *) @@ -513,7 +516,8 @@ module Make (State : SState.S) : let result = let** new_astate = SMatcher.produce new_state full_subst a_produce in let new_state' = - State.add_spec_vars new_astate.state (SS.of_list binders) + State.add_spec_vars new_astate.state + (Id.Sets.SubstSet.of_list (binders :> Id.substable Id.t list)) in let subst, new_states = State.simplify ~kill_new_lvars:true new_state' @@ -555,10 +559,10 @@ module Make (State : SState.S) : let store = State.get_store astate.state in let pvars_store = SStore.domain store in let pvars_a = Asrt.pvars a in - let pvars_diff = SS.diff pvars_a pvars_store in - (if not (SS.is_empty pvars_diff) then + let pvars_diff = Var.Set.diff pvars_a pvars_store in + (if not (Var.Set.is_empty pvars_diff) then let pvars_errs : err_t list = - List.map (fun pvar : err_t -> EVar pvar) (SS.elements pvars_diff) + List.map (fun pvar : err_t -> EVar pvar) (Var.Set.elements pvars_diff) in raise (Internal_State_Error (pvars_errs, astate))); let store_subst = SStore.to_ssubst store in @@ -580,31 +584,36 @@ module Make (State : SState.S) : (revisited : bool) (astate : t) (a : Asrt.t) - (binders : string list) : (t * t, err_t) Res_list.t = + (binders : Id.any_var Id.t list) : (t * t, err_t) Res_list.t = let store = State.get_store astate.state in let pvars_store = SStore.domain store in let pvars_a = Asrt.pvars a in - let pvars_diff = SS.diff pvars_a pvars_store in - L.verbose (fun m -> m "%s" (String.concat ", " (SS.elements pvars_diff))); - (if not (SS.is_empty pvars_diff) then + let pvars_diff = Var.Set.diff pvars_a pvars_store in + L.verbose (fun m -> + m "%a" Fmt.(iter ~sep:comma Var.Set.iter Id.pp) pvars_diff); + (if not (Var.Set.is_empty pvars_diff) then let pvars_errs : err_t list = - List.map (fun pvar : err_t -> EVar pvar) (SS.elements pvars_diff) + List.map (fun pvar : err_t -> EVar pvar) (Var.Set.elements pvars_diff) in raise (Internal_State_Error (pvars_errs, astate))); let lvar_binders, pvar_binders = - List.partition Names.is_lvar_name binders + List.partition_map + (fun x -> + let x = Id.str x in + if Names.is_lvar_name x then Left (LVar.of_string x) + else Right (Var.of_string x)) + binders in - let known_pvars = List.map Expr.from_var_name (SS.elements pvars_a) in + let known_pvars = List.map Expr.var_to_expr (Var.Set.elements pvars_a) in let state_lvars = State.get_lvars astate.state in let known_lvars = - SS.elements - (SS.diff - (SS.inter state_lvars (Asrt.lvars a)) - (SS.of_list lvar_binders)) + LVar.Set.( + elements + (diff (inter state_lvars (Asrt.lvars a)) (of_list lvar_binders))) in let known_lvars = List.map (fun x -> Expr.LVar x) known_lvars in let asrt_alocs = - List.map (fun x -> Expr.ALoc x) (SS.elements (Asrt.alocs a)) + List.map (fun x -> Expr.ALoc x) (ALoc.Set.elements (Asrt.alocs a)) in let known_matchables = Expr.Set.of_list (known_pvars @ known_lvars @ asrt_alocs) @@ -623,12 +632,14 @@ module Make (State : SState.S) : in (* This will not do anything in the original pass, but will do precisely what is needed in the re-establishment *) - let vars_to_forget = SS.inter state_lvars (SS.of_list lvar_binders) in - if vars_to_forget <> SS.empty then ( + let vars_to_forget = + LVar.Set.inter state_lvars (LVar.Set.of_list lvar_binders) + in + if not @@ LVar.Set.is_empty vars_to_forget then ( let oblivion_subst = fresh_subst vars_to_forget in L.verbose (fun m -> m "Forget @[%a@] with subst: %a" - Fmt.(iter ~sep:comma SS.iter string) + Fmt.(iter ~sep:comma LVar.Set.iter Id.pp) vars_to_forget SVal.SESubst.pp oblivion_subst); (* TODO: THIS SUBST IN PLACE MUST NOT BRANCH *) @@ -713,7 +724,7 @@ module Make (State : SState.S) : (list ~sep:semi (parens (pair ~sep:comma Expr.pp Expr.pp)))) bindings); let known_pvars = - SS.elements (SS.diff pvars_a (SS.of_list pvar_binders)) + Var.Set.elements (Var.Set.diff pvars_a (Var.Set.of_list pvar_binders)) in let bindings = (if revisited then new_bindings @ bindings else bindings) @@ -728,8 +739,7 @@ module Make (State : SState.S) : let pvar_subst_list_known = List.map (fun x -> - ( Expr.PVar x, - Option.get (SStore.get (State.get_store astate.state) x) )) + (Expr.PVar x, SStore.get_unsafe (State.get_store astate.state) x)) known_pvars in let pvar_subst_list_bound = @@ -768,7 +778,9 @@ module Make (State : SState.S) : match res with | Ok new_astate -> let new_state' = - State.add_spec_vars new_astate.state (SS.of_list lvar_binders) + State.add_spec_vars new_astate.state + (Id.Sets.SubstSet.of_list + (lvar_binders :> Id.substable Id.t list)) in let invariant_state = { new_astate with state = new_state' } in let _, invariant_states = @@ -907,32 +919,39 @@ module Make (State : SState.S) : let _, astates = simplify ~kill_new_lvars:true astate in Res_list.just_oks astates | SepAssert (a, binders) -> ( - if not (List.for_all Names.is_lvar_name binders) then - failwith "Binding of pure variables in *-assert."; + if + not (List.for_all (fun x -> Names.is_lvar_name @@ Id.str x) binders) + then failwith "Binding of pure variables in *-assert."; let store = State.get_store astate.state in let pvars_store = SStore.domain store in let pvars_a = Asrt.pvars a in - let pvars_diff = SS.diff pvars_a pvars_store in + let pvars_diff = Var.Set.diff pvars_a pvars_store in L.verbose (fun m -> - m "%s" (String.concat ", " (SS.elements pvars_diff))); - (if not (SS.is_empty pvars_diff) then + m "%a" Fmt.(iter ~sep:comma Var.Set.iter Id.pp) pvars_diff); + (if not (Var.Set.is_empty pvars_diff) then let pvars_errs : err_t list = - List.map (fun pvar : err_t -> EVar pvar) (SS.elements pvars_diff) + List.map + (fun pvar : err_t -> EVar pvar) + (Var.Set.elements pvars_diff) in raise (Internal_State_Error (pvars_errs, astate))); let store_subst = SStore.to_ssubst store in let a = SVal.SESubst.substitute_asrt store_subst ~partial:true a in (* let known_vars = SS.diff (SS.filter is_spec_var_name (Asrt.lvars a)) (SS.of_list binders) in *) let state_lvars = State.get_lvars astate.state in + (* TODO: can binders even be PVars? *) + let binders_as_lvars = + binders |> List.map (fun s -> LVar.of_string @@ Id.str s) + in let known_lvars = - SS.elements - (SS.diff - (SS.inter state_lvars (Asrt.lvars a)) - (SS.of_list binders)) + LVar.Set.( + elements + @@ diff (inter state_lvars @@ Asrt.lvars a) + @@ LVar.Set.of_list binders_as_lvars) in let known_lvars = List.map (fun x -> Expr.LVar x) known_lvars in let asrt_alocs = - List.map (fun x -> Expr.ALoc x) (SS.elements (Asrt.alocs a)) + List.map (fun x -> Expr.ALoc x) (ALoc.Set.elements (Asrt.alocs a)) in let known_matchables = Expr.Set.of_list (known_lvars @ asrt_alocs) in @@ -949,12 +968,14 @@ module Make (State : SState.S) : MP.init known_matchables Expr.Set.empty pred_ins [ (a, (None, None)) ] in - let vars_to_forget = SS.inter state_lvars (SS.of_list binders) in - if not (SS.is_empty vars_to_forget) then ( + let vars_to_forget = + LVar.Set.inter state_lvars (LVar.Set.of_list binders_as_lvars) + in + if not (LVar.Set.is_empty vars_to_forget) then ( let oblivion_subst = fresh_subst vars_to_forget in L.verbose (fun m -> m "Forget @[%a@] with subst: %a" - Fmt.(iter ~sep:comma SS.iter string) + Fmt.(iter ~sep:comma LVar.Set.iter Id.pp) vars_to_forget SVal.SESubst.pp oblivion_subst); (* TODO: THIS SUBST IN PLACE MUST NOT BRANCH *) @@ -989,7 +1010,7 @@ module Make (State : SState.S) : match matching_result with | Ok (new_state, subst', _) -> (* Successful matching *) - let lbinders = List.map (fun x -> Expr.LVar x) binders in + let lbinders = List.map (fun x -> Expr.LVar x) binders_as_lvars in let new_bindings = List.map (fun e -> (e, SVal.SESubst.get subst' e)) lbinders in @@ -1026,7 +1047,9 @@ module Make (State : SState.S) : SMatcher.produce new_state full_subst a_produce in let new_state' = - State.add_spec_vars new_astate.state (SS.of_list binders) + State.add_spec_vars new_astate.state + (Id.Sets.SubstSet.of_list + (binders_as_lvars :> Id.substable Id.t list)) in let subst, new_states = State.simplify ~kill_new_lvars:true new_state' @@ -1064,31 +1087,42 @@ module Make (State : SState.S) : in L.print_to_all msg; Res_list.error_with (StateErr.EPure fail_pfs)) - | Consume (asrt, binders) -> consume ~prog astate asrt binders + | Consume (asrt, binders) -> ( + (* TODO: check if type of Consume can be changed to only accept lvars. *) + match Id.as_lvars binders with + | None -> failwith "Binding of pure variables in *-assert." + | Some binders -> + consume ~prog astate asrt + (List.map (fun x -> LVar.of_string @@ Id.str x) binders)) | Produce asrt -> produce astate asrt - | ApplyLem (lname, args, binders) -> - if not (List.for_all Names.is_lvar_name binders) then - failwith "Binding of pure variables in lemma application."; - let lemma = - match MP.get_lemma prog lname with - | Error _ -> Fmt.failwith "Lemma %s does not exist" lname - | Ok lemma -> lemma - in - let v_args : vt list = List.map eval_expr args in - (* Printf.printf "apply lemma. binders: %s. existentials: %s\n\n" - (String.concat ", " binders) (String.concat ", " lemma.lemma.existentials); *) - let existential_bindings = - List.map2 - (fun x y -> (x, Expr.LVar y)) - lemma.data.lemma_existentials binders - in - let** astate, _ = - run_spec_aux ~existential_bindings lname lemma.data.lemma_params - lemma.mp astate None v_args - in - let astate = add_spec_vars astate (Var.Set.of_list binders) in - let _, astates = simplify ~matching:true astate in - Res_list.just_oks astates + | ApplyLem (lname, args, binders) -> ( + (* TODO: check if type of ApplyLem can be changed to only accept lvars. *) + match Id.as_lvars binders with + | None -> failwith "Binding of pure variables in lemma application." + | Some binders -> + let lemma = + match MP.get_lemma prog lname with + | Error _ -> Fmt.failwith "Lemma %s does not exist" lname + | Ok lemma -> lemma + in + let v_args : vt list = List.map eval_expr args in + (* Printf.printf "apply lemma. binders: %s. existentials: %s\n\n" + (String.concat ", " binders) (String.concat ", " lemma.lemma.existentials); *) + let existential_bindings = + List.map2 + (fun x y -> (x, Expr.LVar y)) + lemma.data.lemma_existentials binders + in + let** astate, _ = + run_spec_aux ~existential_bindings lname lemma.data.lemma_params + lemma.mp astate None v_args + in + let astate = + add_spec_vars astate + (Id.Sets.SubstSet.of_list (binders :> Id.substable Id.t list)) + in + let _, astates = simplify ~matching:true astate in + Res_list.just_oks astates) | Invariant _ -> raise (Failure "Invariant must be treated by the match_invariant function") @@ -1099,17 +1133,13 @@ module Make (State : SState.S) : let run_spec (spec : MP.spec) (astate : t) - (x : string) + (x : Var.t) (args : vt list) - (subst : (string * (string * vt) list) option) : + (subst : (string * (LVar.t * vt) list) option) : (t * Flag.t, err_t) Res_list.t = - match subst with - | None -> - run_spec_aux spec.data.spec_name spec.data.spec_params spec.mp astate - (Some x) args - | Some (_, subst_lst) -> - run_spec_aux ~existential_bindings:subst_lst spec.data.spec_name - spec.data.spec_params spec.mp astate (Some x) args + let existential_bindings = Option.map snd subst in + run_spec_aux ?existential_bindings spec.data.spec_name spec.data.spec_params + spec.mp astate (Some x) args let matches (astate : t) diff --git a/GillianCore/engine/Abstraction/PState.mli b/GillianCore/engine/Abstraction/PState.mli index 71695e854..98551a1ad 100644 --- a/GillianCore/engine/Abstraction/PState.mli +++ b/GillianCore/engine/Abstraction/PState.mli @@ -14,7 +14,7 @@ module type S = sig store:store_t -> pfs:PFS.t -> gamma:Type_env.t -> - spec_vars:SS.t -> + spec_vars:Id.Sets.SubstSet.t -> unit -> t diff --git a/GillianCore/engine/Abstraction/Preds.ml b/GillianCore/engine/Abstraction/Preds.ml index 547d6ed45..5db993c7c 100644 --- a/GillianCore/engine/Abstraction/Preds.ml +++ b/GillianCore/engine/Abstraction/Preds.ml @@ -86,17 +86,17 @@ let remove_by_name (preds : t) (pname : string) : abs_t option = let find_pabs_by_name (preds : t) (pname : string) : abs_t list = List.filter (fun (pn, _) -> pn = pname) !preds -let get_lvars (preds : t) : SS.t = +let get_lvars (preds : t) : LVar.Set.t = List.fold_left (fun ac (_, vs) -> - List.fold_left (fun ac e -> SS.union ac (Expr.lvars e)) ac vs) - SS.empty !preds + List.fold_left (fun ac e -> LVar.Set.union ac (Expr.lvars e)) ac vs) + LVar.Set.empty !preds -let get_alocs (preds : t) : SS.t = +let get_alocs (preds : t) : ALoc.Set.t = List.fold_left (fun ac (_, vs) -> - List.fold_left (fun ac e -> SS.union ac (Expr.alocs e)) ac vs) - SS.empty !preds + List.fold_left (fun ac e -> ALoc.Set.union ac (Expr.alocs e)) ac vs) + ALoc.Set.empty !preds (** Printing function *) let pp_pabs fmt pa = diff --git a/GillianCore/engine/Abstraction/Preds.mli b/GillianCore/engine/Abstraction/Preds.mli index ad1e0011e..6db5a4249 100644 --- a/GillianCore/engine/Abstraction/Preds.mli +++ b/GillianCore/engine/Abstraction/Preds.mli @@ -17,8 +17,8 @@ val strategic_choice : consume:bool -> t -> (abs_t -> int) -> abs_t option val remove_by_name : t -> string -> abs_t option val find_pabs_by_name : t -> string -> abs_t list -val get_lvars : t -> SS.t -val get_alocs : t -> SS.t +val get_lvars : t -> LVar.Set.t +val get_alocs : t -> ALoc.Set.t val pp : Format.formatter -> t -> unit val pp_pabs : Format.formatter -> abs_t -> unit diff --git a/GillianCore/engine/Abstraction/Verifier.ml b/GillianCore/engine/Abstraction/Verifier.ml index cb8cb7a81..356622fd5 100644 --- a/GillianCore/engine/Abstraction/Verifier.ml +++ b/GillianCore/engine/Abstraction/Verifier.ml @@ -94,7 +94,7 @@ struct type t = { name : string; id : int * int; - params : string list; + params : Var.t list; pre_state : SPState.t; post_mp : MP.t; flag : Flag.t option; @@ -123,24 +123,24 @@ struct (preds : (string, MP.pred) Hashtbl.t) (pred_ins : (string, int list) Hashtbl.t) (name : string) - (params : string list) + (params : Var.t list) (id : int) (pre : Asrt.t) (posts : Asrt.t list) (variant : Expr.t option) (flag : Flag.t option) - (label : (string * SS.t) option) + (label : (string * LVar.Set.t) option) (to_verify : bool) : (t option * (Asrt.t * Asrt.t list) option) list = let test_of_normalised_state id' (ss_pre, subst) = (* Step 2 - spec_vars = lvars(pre)\dom(subst) -U- alocs(range(subst)) *) let lvars = - SS.fold + LVar.Set.fold (fun x acc -> - if Names.is_spec_var_name x then Expr.Set.add (Expr.LVar x) acc + if LVar.is_spec_var_name x then Expr.Set.add (Expr.LVar x) acc else acc) (Asrt.lvars pre) Expr.Set.empty in - let subst_dom = SSubst.domain subst None in + let subst_dom = SSubst.domain subst in let alocs = SSubst.fold subst (fun _ v_val acc -> @@ -166,7 +166,7 @@ struct name Fmt.( option ~none:(any "None") (fun ft (s, e) -> - Fmt.pf ft "[ %s; %a ]" s (iter ~sep:comma SS.iter string) e)) + pf ft "[ %s; %a ]" s (iter ~sep:comma LVar.Set.iter Id.pp) e)) label Fmt.(iter ~sep:comma Expr.Set.iter Expr.pp) spec_vars Asrt.pp pre SPState.pp ss_pre SSubst.pp subst @@ -202,13 +202,13 @@ struct Expr.Set.empty params in let known_matchables = - Expr.Set.add (PVar Names.return_variable) + Expr.Set.add (PVar Id.return_variable) (Expr.Set.union pvar_params spec_vars) in let existentials = Option.fold ~none:Expr.Set.empty ~some:(fun (_, exs) -> - SS.fold + LVar.Set.fold (fun x acc -> Expr.Set.add (LVar x) acc) exs Expr.Set.empty) label @@ -255,7 +255,7 @@ struct (* Step 1 - normalise the precondition *) match Normaliser.normalise_assertion ~init_data ~pred_defs:preds - ~pvars:(SS.of_list params) pre + ~pvars:(Var.Set.of_list params) pre with | Error _ -> [ (None, None) ] | Ok normalised_assertions -> @@ -287,7 +287,7 @@ struct (preds : MP.preds_tbl_t) (pred_ins : (string, int list) Hashtbl.t) (name : string) - (params : string list) + (params : Var.t list) (id : int) (sspec : Spec.st) : (t option * Spec.st option) list = let ( let+ ) x f = List.map f x in @@ -417,9 +417,9 @@ struct (* Adding spec vars in the post to the subst - these are effectively the existentials of the post *) List.iter (fun x -> - if not (SSubst.mem subst (LVar x)) then - SSubst.add subst (LVar x) (LVar x)) - (SS.elements (SPState.get_spec_vars state)); + let var = Expr.LVar (LVar.of_string (Id.str x)) in + if not (SSubst.mem subst var) then SSubst.add subst var var) + (Id.Sets.SubstSet.elements (SPState.get_spec_vars state)); L.verbose (fun m -> m "Analyse result: About to match one postcondition of %s. post: %a" @@ -491,7 +491,7 @@ struct let store = SPState.get_store final_state in let () = SStore.filter_map_inplace store (fun x v -> - if x = Names.return_variable then Some v else None) + if x = Id.return_variable then Some v else None) in let subst = make_post_subst test final_state in if analyse_result subst test final_state then ( diff --git a/GillianCore/engine/Abstraction/Wands.ml b/GillianCore/engine/Abstraction/Wands.ml index 6c246b4b5..548e4353a 100644 --- a/GillianCore/engine/Abstraction/Wands.ml +++ b/GillianCore/engine/Abstraction/Wands.ml @@ -79,21 +79,29 @@ let extend wands new_wand = wands := new_wand :: !wands let get_lvars t = let lvars_val_list el = - List.fold_left (fun acc expr -> SS.union acc (Expr.lvars expr)) SS.empty el + List.fold_left + (fun acc expr -> LVar.Set.union acc (Expr.lvars expr)) + LVar.Set.empty el in List.fold_left (fun acc { lhs = _, largs; rhs = _, rargs } -> - acc |> SS.union (lvars_val_list largs) |> SS.union (lvars_val_list rargs)) - SS.empty !t + acc + |> LVar.Set.union (lvars_val_list largs) + |> LVar.Set.union (lvars_val_list rargs)) + LVar.Set.empty !t let get_alocs t = let alocs_val_list el = - List.fold_left (fun acc v -> SS.union acc (Expr.alocs v)) SS.empty el + List.fold_left + (fun acc v -> ALoc.Set.union acc (Expr.alocs v)) + ALoc.Set.empty el in List.fold_left (fun acc { lhs = _, largs; rhs = _, rargs } -> - acc |> SS.union (alocs_val_list largs) |> SS.union (alocs_val_list rargs)) - SS.empty !t + acc + |> ALoc.Set.union (alocs_val_list largs) + |> ALoc.Set.union (alocs_val_list rargs)) + ALoc.Set.empty !t let to_assertions (wands : t) = let wand_to_asrt { lhs; rhs } = Asrt.Wand { lhs; rhs } in diff --git a/GillianCore/engine/BiAbduction/Abductor.ml b/GillianCore/engine/BiAbduction/Abductor.ml index 75add5ab1..a7522740b 100644 --- a/GillianCore/engine/BiAbduction/Abductor.ml +++ b/GillianCore/engine/BiAbduction/Abductor.ml @@ -29,7 +29,7 @@ module Make type bi_state_t = SBAState.t type result_t = SBAInterpreter.result_t - type t = { name : string; params : string list; state : bi_state_t } + type t = { name : string; params : Var.t list; state : bi_state_t } type annot = PC.Annot.t type init_data = PC.init_data @@ -37,10 +37,12 @@ module Make let lvars = Asrt.lvars a in let alocs = Asrt.alocs a in let lvar_bindings = - List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (SS.elements lvars) + List.map (fun x -> (Expr.LVar x, Expr.LVar x)) (LVar.Set.elements lvars) in let aloc_bindings = - List.map (fun x -> (Expr.LVar x, Expr.ALoc x)) (SS.elements alocs) + List.map + (fun x -> (Expr.LVar (LVar.of_string @@ ALoc.str x), Expr.ALoc x)) + (ALoc.Set.elements alocs) in let bindings = lvar_bindings @ aloc_bindings in let bindings' = @@ -56,7 +58,7 @@ module Make let make_spec (_ : annot MP.prog) (name : string) - (params : string list) + (params : Var.t list) (bi_state_i : bi_state_t) (bi_state_f : bi_state_t) (fl : Flag.t) : Spec.t option = @@ -68,7 +70,7 @@ module Make (* let _ = SBAState.simplify ~kill_new_lvars:true bi_state_f in *) let state_i, _ = SBAState.get_components bi_state_i in let state_f, state_af = SBAState.get_components bi_state_f in - let pvars = SS.of_list (Names.return_variable :: params) in + let pvars = Var.Set.of_list (Id.return_variable :: params) in L.verbose (fun m -> m @@ -78,12 +80,12 @@ module Make @[Final STATE:@\n\ %a@]" name - Fmt.(list ~sep:comma string) + Fmt.(list ~sep:comma Id.pp) params SPState.pp state_af SPState.pp state_f); (* Drop all pvars except ret/err from the state *) let () = SStore.filter_map_inplace (SPState.get_store state_f) (fun x v -> - if x = Names.return_variable then Some v else None) + if x = Id.return_variable then Some v else None) in let* post = let _, finals_simplified = @@ -112,11 +114,11 @@ module Make in let post_clocs = Asrt.clocs post in let pre_clocs = Asrt.clocs pre in - let new_clocs = SS.diff post_clocs pre_clocs in + let new_clocs = Loc.Set.diff post_clocs pre_clocs in let subst = Hashtbl.create Config.medium_tbl_size in List.iter (fun cloc -> Hashtbl.replace subst cloc (Expr.ALoc (ALoc.alloc ()))) - (SS.elements new_clocs); + (Loc.Set.elements new_clocs); let subst_fun cloc = match Hashtbl.find_opt subst cloc with | Some e -> e @@ -153,14 +155,14 @@ module Make the spec:@\n\ %a@]" name - Fmt.(list ~sep:comma string) + Fmt.(list ~sep:comma Id.pp) params Spec.pp spec); Some spec let testify ~init_data ~(prog : annot MP.prog) (bi_spec : BiSpec.t) : t list = L.verbose (fun m -> m "Bi-testifying: %s" bi_spec.bispec_name); let proc_names = Prog.get_proc_names prog.prog in - let params = SS.of_list bi_spec.bispec_params in + let params = Var.Set.of_list bi_spec.bispec_params in let normalise = Normaliser.normalise_assertion ~init_data ~pred_defs:prog.preds ~pvars:params @@ -187,7 +189,10 @@ module Make (prog : annot MP.prog) (test : t) : (Spec.t * Flag.t) list = let state = SBAState.copy test.state in - let state = SBAState.add_spec_vars state (SBAState.get_lvars state) in + let state = + SBAState.add_spec_vars state + (Id.Sets.lvar_to_subst @@ SBAState.get_lvars state) + in try let opt_results = SBAInterpreter.evaluate_proc ret_fun prog test.name test.params state @@ -214,7 +219,7 @@ module Make let process_sym_exec_result (prog : annot MP.prog) (name : string) - (params : string list) + (params : Var.t list) (state_i : bi_state_t) (result : result_t) : (Spec.t * Flag.t) option = let open Syntaxes.Option in diff --git a/GillianCore/engine/BiAbduction/BiState.ml b/GillianCore/engine/BiAbduction/BiState.ml index beb46afb2..cb27508b8 100644 --- a/GillianCore/engine/BiAbduction/BiState.ml +++ b/GillianCore/engine/BiAbduction/BiState.ml @@ -120,7 +120,10 @@ module Make (State : SState.S) = struct let svars = State.get_spec_vars state in SVal.SESubst.filter_in_place af_subst (fun x x_v -> match x with - | LVar x -> if SS.mem x svars then None else Some x_v + | LVar x -> + if Id.Sets.SubstSet.mem (x :> Id.substable Id.t) svars then + None + else Some x_v | _ -> Some x_v); List.map (fun af_state -> { procs; state; af_state }) @@ -141,16 +144,14 @@ module Make (State : SState.S) = struct (* TODO: By-need formatter *) let pp_by_need _ _ _ fmt state = pp fmt state - let add_spec_vars (bi_state : t) (vs : Var.Set.t) : t = + let add_spec_vars bi_state vs = let { state; _ } = bi_state in let state' = State.add_spec_vars state vs in { bi_state with state = state' } - let get_spec_vars ({ state; _ } : t) : Var.Set.t = State.get_spec_vars state - let get_lvars ({ state; _ } : t) : Var.Set.t = State.get_lvars state - - let to_assertions ?(to_keep : SS.t option) ({ state; _ } : t) : Asrt.t = - State.to_assertions ?to_keep state + let get_spec_vars { state; _ } = State.get_spec_vars state + let get_lvars { state; _ } = State.get_lvars state + let to_assertions ?to_keep { state; _ } = State.to_assertions ?to_keep state let evaluate_slcmd (prog : 'a MP.prog) (lcmd : SLCmd.t) (bi_state : t) : (t, err_t) Res_list.t = @@ -199,7 +200,9 @@ module Make (State : SState.S) = struct (fun acc a -> let* this_state = acc in let lvars = Asrt.lvars [ a ] in - let this_state = State.add_spec_vars this_state lvars in + let this_state = + State.add_spec_vars this_state (Id.Sets.lvar_to_subst lvars) + in match a with | Asrt.Emp -> [ this_state ] | Pure f -> @@ -291,7 +294,9 @@ module Make (State : SState.S) = struct let svars = State.get_spec_vars state' in SVal.SESubst.filter_in_place new_subst (fun x x_v -> match x with - | LVar x -> if SS.mem x svars then None else Some x_v + | LVar x + when Id.Sets.SubstSet.mem (x :> Id.substable Id.t) svars + -> None | _ -> Some x_v); let subst_afs = State.substitution_in_place new_subst af_state' @@ -321,8 +326,7 @@ module Make (State : SState.S) = struct in search (state, af_state, subst, mp) - let update_store (state : State.t) (x : string option) (v : Expr.t) : State.t - = + let update_store (state : State.t) (x : Var.t option) (v : Expr.t) : State.t = match x with | None -> state | Some x -> @@ -334,9 +338,9 @@ module Make (State : SState.S) = struct let run_spec (spec : MP.spec) (bi_state : t) - (x : string) + (x : Var.t) (args : Expr.t list) - (_ : (string * (string * Expr.t) list) option) : (t * Flag.t) list = + _ : (t * Flag.t) list = (* let start_time = time() in *) L.( verbose (fun m -> @@ -404,7 +408,7 @@ module Make (State : SState.S) = struct let+ final_state = State.produce_posts frame_state subst posts in let af_state' : State.t = State.copy af_state in let final_store : SStore.t = State.get_store final_state in - let v_ret : Expr.t option = SStore.get final_store Names.return_variable in + let v_ret : Expr.t option = SStore.get final_store Id.return_variable in let final_state' : State.t = State.set_store final_state (SStore.copy old_store) in @@ -428,9 +432,9 @@ module Make (State : SState.S) = struct let run_spec (spec : MP.spec) (bi_state : t) - (x : string) + (x : Var.t) (args : Expr.t list) - (_ : (string * (string * Expr.t) list) option) = + _ = Res_list.just_oks (run_spec spec bi_state x args None) let produce_posts (_ : t) (_ : SVal.SESubst.t) (_ : Asrt.t list) : t list = diff --git a/GillianCore/engine/FOLogic/FOSolver.ml b/GillianCore/engine/FOLogic/FOSolver.ml index f841f83b6..f2605873a 100644 --- a/GillianCore/engine/FOLogic/FOSolver.ml +++ b/GillianCore/engine/FOLogic/FOSolver.ml @@ -42,23 +42,21 @@ let check_satisfiability_with_model (fs : Expr.t list) (gamma : Type_env.t) : let fs, gamma, subst = simplify_pfs_and_gamma fs gamma in let model = Smt.check_sat fs (Type_env.as_hashtbl gamma) in let lvars = - List.fold_left - (fun ac vs -> - let vs = - Expr.Set.of_list (List.map (fun x -> Expr.LVar x) (SS.elements vs)) - in - Expr.Set.union ac vs) - Expr.Set.empty + List.fold_left LVar.Set.union LVar.Set.empty (List.map Expr.lvars (Expr.Set.elements fs)) in - let smt_vars = Expr.Set.diff lvars (SESubst.domain subst None) in - L.( - verbose (fun m -> - m "OBTAINED VARS: %s\n" - (String.concat ", " - (List.map - (fun e -> Format.asprintf "%a" Expr.pp e) - (Expr.Set.elements smt_vars))))); + let subst_lvars = + SESubst.domain subst |> Expr.Set.to_list + |> List.filter_map (function + | Expr.LVar l -> Some l + | _ -> None) + |> LVar.Set.of_list + in + let smt_vars = LVar.Set.diff lvars subst_lvars in + L.verbose (fun m -> + m "OBTAINED VARS: %a\n" + Fmt.(list ~sep:comma Id.pp) + (LVar.Set.elements smt_vars)); let update x e = SESubst.put subst (LVar x) e in match model with | None -> None @@ -115,7 +113,7 @@ let sat ~matching ~pfs ~gamma formula : bool = let check_entailment ?(matching = false) - (existentials : SS.t) + (existentials : LVar.Set.t) (left_fs : PFS.t) (right_fs : Expr.t list) (gamma : Type_env.t) : bool = @@ -128,7 +126,7 @@ let check_entailment Right:%a@\n\ Gamma:@\n\ %a@\n" - (Fmt.iter ~sep:Fmt.comma SS.iter Fmt.string) + (Fmt.iter ~sep:Fmt.comma LVar.Set.iter Id.pp) existentials PFS.pp left_fs PFS.pp (PFS.of_list right_fs) Type_env.pp gamma); @@ -145,15 +143,11 @@ let check_entailment Simplifications.simplify_implication ~matching existentials left_fs right_fs gamma in - Type_env.filter_vars_in_place gamma (SS.union left_lvars right_lvars); + Type_env.filter_vars_in_place gamma + @@ Id.Sets.lvar_to_varset (LVar.Set.union left_lvars right_lvars); - (* Separate gamma into existentials and non-existentials *) let left_fs = PFS.to_list left_fs in let right_fs = PFS.to_list right_fs in - let gamma_left = - Type_env.filter gamma (fun v -> not (SS.mem v existentials)) - in - let gamma_right = Type_env.filter gamma (fun v -> SS.mem v existentials) in (* If left side is false, return false *) if List.mem Expr.false_ (left_fs @ right_fs) then false @@ -180,16 +174,26 @@ let check_entailment -> Axioms(A) /\ A /\ (ForAll (x1, ..., x2) Axioms(B) /\ !B) is SAT -> ForAll (x1, ..., x2) Axioms(A) /\ Axioms(B) /\ A /\ !B is SAT *) + (* Separate gamma into existentials and non-existentials *) + let gamma_left = Type_env.init () in + let gamma_right = Type_env.init () in + let () = + Type_env.iter gamma (fun v t -> + if Id.Sets.VarSet.mem v @@ Id.Sets.lvar_to_varset existentials then + Type_env.update gamma_right v t + else Type_env.update gamma_left v t) + in + (* Get axioms *) (* let axioms = get_axioms (left_fs @ right_fs) gamma in *) let right_fs = List.map Expr.negate right_fs in let right_f : Expr.t = - if SS.is_empty existentials then Expr.disjunct right_fs + if LVar.Set.is_empty existentials then Expr.disjunct right_fs else let binders = List.map (fun x -> (x, Type_env.get gamma_right x)) - (SS.elements existentials) + (LVar.Set.elements existentials) in ForAll (binders, Expr.disjunct right_fs) in @@ -220,12 +224,9 @@ let is_equal ~pfs ~gamma e1 e2 = match feq with | Lit (Bool b) -> b | BinOp (_, Equal, _) | BinOp (_, And, _) -> - check_entailment SS.empty pfs [ feq ] gamma + check_entailment LVar.Set.empty pfs [ feq ] gamma | _ -> - raise - (Failure - ("Equality reduced to something unexpected: " - ^ (Fmt.to_to_string Expr.pp) feq)) + Fmt.failwith "Equality reduced to something unexpected: %a" Expr.pp feq in (* Utils.Statistics.update_statistics "FOS: is_equal" (Sys.time () -. t); *) result @@ -238,12 +239,10 @@ let is_different ~pfs ~gamma e1 e2 = let result = match feq with | Lit (Bool b) -> b - | Expr.UnOp (Not, _) -> check_entailment SS.empty pfs [ feq ] gamma + | UnOp (Not, _) -> check_entailment LVar.Set.empty pfs [ feq ] gamma | _ -> - raise - (Failure - ("Inequality reduced to something unexpected: " - ^ (Fmt.to_to_string Expr.pp) feq)) + Fmt.failwith "Inequality reduced to something unexpected: %a" Expr.pp + feq in (* Utils.Statistics.update_statistics "FOS: is different" (Sys.time () -. t); *) result @@ -257,17 +256,16 @@ let num_is_less_or_equal ~pfs ~gamma e1 e2 = | Lit (Bool b) -> b | BinOp (ra, Equal, rb) -> is_equal ~pfs ~gamma ra rb | BinOp (_, FLessThanEqual, _) -> - check_entailment SS.empty pfs [ feq ] gamma + check_entailment LVar.Set.empty pfs [ feq ] gamma | _ -> - raise - (Failure - ("Inequality reduced to something unexpected: " - ^ (Fmt.to_to_string Expr.pp) feq)) + Fmt.failwith "Inequality reduced to something unexpected: %a" Expr.pp + feq in result let resolve_loc_name ~pfs ~gamma loc = Logging.tmi (fun fmt -> fmt "get_loc_name: %a" Expr.pp loc); match Reduction.reduce_lexpr ~pfs ~gamma loc with - | Lit (Loc loc) | ALoc loc -> Some loc + | Lit (Loc loc) -> Some (loc :> Id.any_loc Id.t) + | ALoc loc -> Some (loc :> Id.any_loc Id.t) | loc' -> Reduction.resolve_expr_to_location pfs gamma loc' diff --git a/GillianCore/engine/FOLogic/FOSolver.mli b/GillianCore/engine/FOLogic/FOSolver.mli index 7d294813b..76d14d70e 100644 --- a/GillianCore/engine/FOLogic/FOSolver.mli +++ b/GillianCore/engine/FOLogic/FOSolver.mli @@ -12,7 +12,7 @@ val check_satisfiability_with_model : val check_satisfiability : ?matching:bool -> ?time:string -> - ?relevant_info:Containers.SS.t * Containers.SS.t * Containers.SS.t -> + ?relevant_info:Var.Set.t * LVar.Set.t * Id.Sets.LocSet.t -> Gil_syntax.Expr.t list -> Type_env.t -> bool @@ -26,7 +26,7 @@ val sat : under the typing environment [gamma]. *) val check_entailment : ?matching:bool -> - Utils.Containers.SS.t -> + LVar.Set.t -> PFS.t -> Gil_syntax.Expr.t list -> Type_env.t -> @@ -58,4 +58,4 @@ val num_is_less_or_equal : bool val resolve_loc_name : - pfs:PFS.t -> gamma:Type_env.t -> Gil_syntax.Expr.t -> string option + pfs:PFS.t -> gamma:Type_env.t -> Gil_syntax.Expr.t -> Id.any_loc Id.t option diff --git a/GillianCore/engine/FOLogic/PFS.ml b/GillianCore/engine/FOLogic/PFS.ml index f2f7dae6c..de9cff067 100644 --- a/GillianCore/engine/FOLogic/PFS.ml +++ b/GillianCore/engine/FOLogic/PFS.ml @@ -32,14 +32,20 @@ let subst_expr_for_expr (to_subst : Expr.t) (subst_with : Expr.t) (pfs : t) : unit = Ext_list.map_inplace (Expr.subst_expr_for_expr ~to_subst ~subst_with) pfs -let lvars (pfs : t) : SS.t = - Ext_list.fold_left (fun ac a -> SS.union ac (Expr.lvars a)) SS.empty pfs +let lvars (pfs : t) : LVar.Set.t = + Ext_list.fold_left + (fun ac a -> LVar.Set.union ac (Expr.lvars a)) + LVar.Set.empty pfs -let alocs (pfs : t) : SS.t = - Ext_list.fold_left (fun ac a -> SS.union ac (Expr.alocs a)) SS.empty pfs +let alocs (pfs : t) : ALoc.Set.t = + Ext_list.fold_left + (fun ac a -> ALoc.Set.union ac (Expr.alocs a)) + ALoc.Set.empty pfs -let clocs (pfs : t) : SS.t = - Ext_list.fold_left (fun ac a -> SS.union ac (Expr.clocs a)) SS.empty pfs +let clocs (pfs : t) : Loc.Set.t = + Ext_list.fold_left + (fun ac a -> Loc.Set.union ac (Expr.clocs a)) + Loc.Set.empty pfs let pp = Fmt.vbox (Ext_list.pp ~sep:Fmt.cut Expr.pp) @@ -81,41 +87,42 @@ let clean_up pfs = | _ -> true) pfs -let rec get_relevant_info (_ : SS.t) (lvars : SS.t) (locs : SS.t) (pfs : t) : - SS.t * SS.t * SS.t = - let relevant = SS.union lvars locs in +let rec get_relevant_info + (_ : Var.Set.t) + (lvars : LVar.Set.t) + (locs : Id.Sets.LocSet.t) + (pfs : t) : Var.Set.t * LVar.Set.t * Id.Sets.LocSet.t = let new_pvars, new_lvars, new_locs = fold_left (fun (new_pvars, new_lvars, new_locs) pf -> let pf_pvars = Expr.pvars pf in let pf_lvars = Expr.lvars pf in let pf_locs = Expr.locs pf in - let pf_relevant = SS.union pf_pvars (SS.union pf_lvars pf_locs) in - if SS.inter relevant pf_relevant = SS.empty then - (new_pvars, new_lvars, new_locs) + if + (LVar.Set.is_empty @@ LVar.Set.inter lvars pf_lvars) + || (Id.Sets.LocSet.is_empty @@ Id.Sets.LocSet.inter locs pf_locs) + then (new_pvars, new_lvars, new_locs) else - ( SS.union new_pvars pf_pvars, - SS.union new_lvars pf_lvars, - SS.union new_locs pf_locs )) - (SS.empty, SS.empty, SS.empty) + ( Var.Set.union new_pvars pf_pvars, + LVar.Set.union new_lvars pf_lvars, + Id.Sets.LocSet.union new_locs pf_locs )) + (Var.Set.empty, LVar.Set.empty, Id.Sets.LocSet.empty) pfs in if new_lvars = lvars && new_locs = locs then (new_pvars, new_lvars, new_locs) else get_relevant_info new_pvars new_lvars new_locs pfs let filter_with_info relevant_info (pfs : t) : t = - let pvars, lvars, locs = relevant_info in + let pvars, lvars, alocs = relevant_info in - let _, lvars, locs = get_relevant_info pvars lvars locs pfs in + let _, lvars, alocs = get_relevant_info pvars lvars alocs pfs in - let relevant = List.fold_left SS.union SS.empty [ lvars; locs ] in let filtered_pfs = copy pfs in let () = filter (fun pf -> - let pf_info = SS.union (Expr.lvars pf) (Expr.locs pf) in - let overlap = SS.inter relevant pf_info in - not @@ SS.is_empty overlap) + LVar.Set.(not @@ is_empty @@ inter (Expr.lvars pf) lvars) + || Id.Sets.LocSet.(not @@ is_empty @@ inter (Expr.locs pf) alocs)) filtered_pfs in filtered_pfs diff --git a/GillianCore/engine/FOLogic/PFS.mli b/GillianCore/engine/FOLogic/PFS.mli index d7fd46a20..ed465d686 100644 --- a/GillianCore/engine/FOLogic/PFS.mli +++ b/GillianCore/engine/FOLogic/PFS.mli @@ -66,28 +66,24 @@ val substitution : SVal.SESubst.t -> t -> unit val subst_expr_for_expr : Expr.t -> Expr.t -> t -> unit (** [lvars pfs] returns the set containing all the lvars occurring in [pfs] *) -val lvars : t -> Containers.SS.t +val lvars : t -> LVar.Set.t (** Returns the set containing all the alocs occurring in --pfs-- *) -val alocs : t -> Containers.SS.t +val alocs : t -> ALoc.Set.t (** [alocs pfs] returns the set containing all the abstract locations occurring in [pfs] *) (** [clocs pfs] returns the set containing all the concrete locations occurring in [pfs] *) -val clocs : t -> Containers.SS.t +val clocs : t -> Loc.Set.t (** [pp fmt pfs] prints the pure formulae [pfs] *) val pp : Format.formatter -> t -> unit -(** [pp pvars lvars locs fmt pfs] prints the pure formulae [pfs] relevnt to [pvars], [lvars] and [locs] *) +(** [pp pvars lvars locs fmt pfs] prints the pure formulae [pfs] relevnt to [pvars], [lvars] and [alocs] *) val pp_by_need : - Containers.SS.t * Containers.SS.t * Containers.SS.t -> - Format.formatter -> - t -> - unit + Var.Set.t * LVar.Set.t * Id.Sets.LocSet.t -> Format.formatter -> t -> unit (** [filter_with_info pvars lvars locs pfs] returns only the pfs relevant to [pvars], [lvars], and [locs]*) -val filter_with_info : - Containers.SS.t * Containers.SS.t * Containers.SS.t -> t -> t +val filter_with_info : Var.Set.t * LVar.Set.t * Id.Sets.LocSet.t -> t -> t (** [sort pfs] sorts the pure formulae [pfs] *) val sort : t -> unit @@ -96,11 +92,11 @@ val remove_duplicates : t -> unit val clean_up : t -> unit val get_relevant_info : - Containers.SS.t -> - Containers.SS.t -> - Containers.SS.t -> + Var.Set.t -> + LVar.Set.t -> + Id.Sets.LocSet.t -> t -> - Containers.SS.t * Containers.SS.t * Containers.SS.t + Var.Set.t * LVar.Set.t * Id.Sets.LocSet.t val filter_map_stop : (Expr.t -> [ `Stop | `Filter | `Replace of Expr.t ]) -> t -> bool diff --git a/GillianCore/engine/FOLogic/Reduction.ml b/GillianCore/engine/FOLogic/Reduction.ml index e1779fc8e..b0dc12ffb 100644 --- a/GillianCore/engine/FOLogic/Reduction.ml +++ b/GillianCore/engine/FOLogic/Reduction.ml @@ -162,21 +162,21 @@ let resolve_list (le : Expr.t) (pfs : Expr.t list) : Expr.t = let rec search x pfs = match (pfs : Expr.t list) with | [] -> None - | BinOp (LVar x', Equal, le) :: rest when String.equal x' x -> ( + | BinOp (LVar x', Equal, le) :: rest when Id.equal x' x -> ( let le' = normalise_list_expressions le in match le' with (* Weird things can happen where x reduces to e.g. `{{ l-nth(x, 0) }}`. We check absence of cycles *) - | (EList _ | NOp (LstCat, _)) when not (SS.mem x (Expr.lvars le')) -> - Some le' + | (EList _ | NOp (LstCat, _)) when not (LVar.Set.mem x (Expr.lvars le')) + -> Some le' | Expr.BinOp (_, LstRepeat, _) as ret - when not (SS.mem x (Expr.lvars ret)) -> Some ret + when not (LVar.Set.mem x (Expr.lvars ret)) -> Some ret | _ -> search x rest) - | BinOp (le, Equal, LVar x') :: rest when String.equal x' x -> ( + | BinOp (le, Equal, LVar x') :: rest when Id.equal x' x -> ( let le' = normalise_list_expressions le in match le' with - | (EList _ | NOp (LstCat, _)) when not (SS.mem x (Expr.lvars le')) -> - Some le' + | (EList _ | NOp (LstCat, _)) when not (LVar.Set.mem x (Expr.lvars le')) + -> Some le' | _ -> search x rest) | _ :: rest -> search x rest in @@ -546,7 +546,8 @@ let rec list_prefix (pfs : PFS.t) (la : Expr.t) (lb : Expr.t) : bool * Expr.t = in let candidates = List.filter - (fun (_, lvars) -> not (SS.is_empty (SS.inter lvars_lb lvars))) + (fun (_, lvars) -> + not (LVar.Set.is_empty (LVar.Set.inter lvars_lb lvars))) candidates in match candidates with @@ -558,16 +559,14 @@ let rec list_prefix (pfs : PFS.t) (la : Expr.t) (lb : Expr.t) : bool * Expr.t = List.map (fun (x : Expr.t) -> (x, Expr.lvars x)) candidates in let candidates = - List.filter - (fun (_, lvars) -> Containers.SS.mem a lvars) - candidates + List.filter (fun (_, lvars) -> LVar.Set.mem a lvars) candidates in match candidates with | [ (x, _) ] -> f (LVar a) x | _ -> nono)) | _, _ -> nono -let prefix_catch pfs (x : Expr.t) (y : string) = +let prefix_catch pfs (x : Expr.t) (y : LVar.t) = match x with | NOp (LstCat, x) -> PFS.exists @@ -917,8 +916,7 @@ and reduce_lexpr_loop BinOp (Lit (Int len), ILessThanEqual, LVar b) ), Or, BinOp (BinOp (EList c, LstNth, LVar d), Equal, e) ) ) - when Z.equal z Z.zero && String.equal x a && String.equal a b - && String.equal b d + when Z.equal z Z.zero && Id.equal x a && Id.equal a b && Id.equal b d && Int.equal (List.compare_length_with c (Z.to_int len)) 0 -> let rhs = Expr.EList (List_utils.make (Z.to_int len) e) in BinOp (EList c, Equal, rhs) @@ -967,7 +965,7 @@ and reduce_lexpr_loop reduce_lexpr_loop ~matching ~reduce_lvars new_pfs new_gamma e in let vars = Expr.lvars re in - let bt = List.filter (fun (b, _) -> Containers.SS.mem b vars) bt in + let bt = List.filter (fun (b, _) -> LVar.Set.mem b vars) bt in (* We remove all quantifiers that aren't used anymore *) match (le, bt) with | _, [] -> re @@ -1156,7 +1154,7 @@ and reduce_lexpr_loop match le with | LVar x -> List.filter - (fun eq -> not (Containers.SS.mem x (Expr.lvars eq))) + (fun eq -> not (LVar.Set.mem x (Expr.lvars eq))) eqs | _ -> eqs in @@ -1207,7 +1205,7 @@ and reduce_lexpr_loop && List.exists (function | (Expr.LVar lx' | NOp (LstCat, LVar lx' :: _)) - when String.equal lx lx' -> true + when Id.equal lx lx' -> true | _ -> false) (get_equal_expressions pfs fle1) -> L.tmi (fun fmt -> fmt "Case 8"); @@ -1215,8 +1213,8 @@ and reduce_lexpr_loop List.find_map (fun e -> match e with - | Expr.LVar ly when String.equal ly lx -> Some e - | NOp (LstCat, (LVar ly as e) :: _) when String.equal ly lx -> + | Expr.LVar ly when Id.equal ly lx -> Some e + | NOp (LstCat, (LVar ly as e) :: _) when Id.equal ly lx -> Some e | _ -> None) (get_equal_expressions pfs fle1) @@ -1597,7 +1595,7 @@ and reduce_lexpr_loop ( LVar lst, Equal, NOp (LstCat, LstSub (LVar lst', Lit (Int z), split) :: _) ) - when Z.equal z Z.zero && String.equal lst lst' + when Z.equal z Z.zero && Id.equal lst lst' && PFS.mem pfs (BinOp (UnOp (LstLen, LVar lst), ILessThan, split)) -> Expr.false_ (* l U {x} = l' U {x} /\ x ∉ l /\ x ∉ l' <=> l = l' *) @@ -1644,9 +1642,9 @@ and reduce_lexpr_loop (BinOp (LVar x, IPlus, UnOp (IUnaryMinus, LVar y)), Equal, Lit (Int z)) when Z.equal z Z.zero -> BinOp (LVar x, Equal, LVar y) | BinOp (BinOp (Lit (Num x), FPlus, LVar y), Equal, LVar z) - when x <> 0. && String.equal y z -> Expr.false_ + when x <> 0. && Id.equal y z -> Expr.false_ | BinOp (BinOp (Lit (Int x), IPlus, LVar y), Equal, LVar z) - when (not (Z.equal x Z.zero)) && String.equal y z -> Expr.false_ + when (not (Z.equal x Z.zero)) && Id.equal y z -> Expr.false_ (* FIXME: INTEGER BYTE-BY-BYTE BREAKDOWN *) (* 256 * b1 + b0 = n /\ b0,b1 ∈ [0;256[ <==> b1 = n/256 /\ b0 = n-b1 Opale: The b0 = n-b1 bit is weird?? Why not mod? *) @@ -2525,18 +2523,19 @@ and substitute_for_list_length (pfs : PFS.t) (le : Expr.t) : Expr.t = le len_eqs let resolve_expr_to_location (pfs : PFS.t) (gamma : Type_env.t) (e : Expr.t) : - string option = + Id.any_loc Id.t option = let max_fuel = 10 in let loc_name = function - | Expr.ALoc loc | Lit (Loc loc) -> Some loc + | Expr.ALoc loc -> Some (loc :> Id.any_loc Id.t) + | Lit (Loc loc) -> Some (loc :> Id.any_loc Id.t) | _ -> None in let rec resolve_expr_to_location_aux (fuel : int) (tried : Expr.Set.t) - (to_try : Expr.t list) : string option = + (to_try : Expr.t list) : Id.any_loc Id.t option = let open Syntaxes.Option in L.tmi (fun m -> m "to_try: %a" (Fmt.Dump.list Expr.pp) to_try); let* () = if fuel <= 0 then None else Some () in @@ -2553,7 +2552,7 @@ let resolve_expr_to_location (pfs : PFS.t) (gamma : Type_env.t) (e : Expr.t) : (* If we find a loc in there, we return it *) let/ () = List.find_map loc_name equal_e in (* We actually want to try all possible substs! *) - let all_lvars = Containers.SS.elements (Expr.lvars e) in + let all_lvars = LVar.Set.elements (Expr.lvars e) in let subst_for_each_lvar = List.map (fun x -> @@ -2566,7 +2565,7 @@ let resolve_expr_to_location (pfs : PFS.t) (gamma : Type_env.t) (e : Expr.t) : in L.tmi (fun m -> m "subst_for_each_lvar: %a" - (Fmt.Dump.list (Fmt.Dump.list (Fmt.Dump.pair Expr.pp Expr.pp))) + Fmt.Dump.(list (list (pair Expr.pp Expr.pp))) subst_for_each_lvar); let found_substs = List.fold_left @@ -2575,15 +2574,15 @@ let resolve_expr_to_location (pfs : PFS.t) (gamma : Type_env.t) (e : Expr.t) : in L.tmi (fun m -> m "found_substs: %a" - (Fmt.Dump.list (Fmt.Dump.list (Fmt.Dump.pair Expr.pp Expr.pp))) + Fmt.Dump.(list (list (pair Expr.pp Expr.pp))) found_substs); (* lvar and substs is a list [ (ei, esi) ] where for each ei, esi is a list of equal expressions. We are going to build the product of each esi to obtain *) let subst_es = List.map (List.fold_left - (fun (e : Expr.t) (e_to, e_with) -> - Expr.subst_expr_for_expr ~to_subst:e_to ~subst_with:e_with e) + (fun e (to_subst, subst_with) -> + Expr.subst_expr_for_expr ~to_subst ~subst_with e) e) found_substs in @@ -2603,7 +2602,7 @@ let relate_llen (pfs : PFS.t) (gamma : Type_env.t) (e : Expr.t) - (lcat : Expr.t list) : (Expr.t * Containers.SS.t) option = + (lcat : Expr.t list) : (Expr.t * LVar.Set.t) option = (* Loop *) let rec relate_llen_loop (llen : Cint.t) @@ -2632,7 +2631,7 @@ let relate_llen match e with | Expr.Lit (Int _) -> true | e - when Containers.SS.subset (Expr.lvars e) + when LVar.Set.subset (Expr.lvars e) (Expr.lvars (Cint.to_expr llen)) -> true | _ -> false) eqs @@ -2676,13 +2675,13 @@ let relate_llen in let pf = Expr.BinOp (e, Equal, NOp (LstCat, les @ new_lvars)) in L.verbose (fun fmt -> fmt "Constructed equality: %a" Expr.pp pf); - (pf, Containers.SS.of_list new_vars) + (pf, LVar.Set.of_list new_vars) | false, exp -> let rest_var = LVar.alloc () in let rest = Expr.LVar rest_var in let pfeq = Expr.BinOp (e, Equal, NOp (LstCat, les @ [ rest ])) in let pflen = Expr.BinOp (UnOp (LstLen, rest), Equal, exp) in - (Expr.BinOp (pfeq, And, pflen), Containers.SS.singleton rest_var) + (Expr.BinOp (pfeq, And, pflen), LVar.Set.singleton rest_var) | _ -> failwith "Impossible by construction") (relate_llen_loop llen [] lcat) in @@ -2702,7 +2701,7 @@ let understand_lstcat (pfs : PFS.t) (gamma : Type_env.t) (lcat : Expr.t list) - (rcat : Expr.t list) : (Expr.t * Containers.SS.t) option = + (rcat : Expr.t list) : (Expr.t * LVar.Set.t) option = L.tmi (fun fmt -> fmt "Understanding LstCat: %a, %a" Fmt.(brackets (list ~sep:semi Expr.pp)) @@ -2807,10 +2806,11 @@ let reduce_assertion_loop L.(tmi (fun m -> m "Reduce_assertion: %a -> %a" Asrt.pp a Asrt.pp result))); result -let extract_lvar_equalities : Asrt.t -> (string * Expr.t) list = +let extract_lvar_equalities : Asrt.t -> (LVar.t * Expr.t) list = List.filter_map @@ function | Asrt.Pure (BinOp (LVar x, Equal, v) | BinOp (v, Equal, LVar x)) -> - if Names.is_lvar_name x && not (Names.is_spec_var_name x) then Some (x, v) + if Names.is_lvar_name (LVar.str x) && not (LVar.is_spec_var_name x) then + Some (x, v) else None | _ -> None @@ -2833,7 +2833,8 @@ let reduce_assertion match x with | Lit _ -> subst a | LVar w when v <> w -> subst a - | EList lx when not (Var.Set.mem v (Expr.lvars (EList lx))) -> subst a + | EList lx when not (LVar.Set.mem v (Expr.lvars (EList lx))) -> + subst a | _ -> a) a' equalities in diff --git a/GillianCore/engine/FOLogic/Reduction.mli b/GillianCore/engine/FOLogic/Reduction.mli index dfa70eab0..2e0abe05d 100644 --- a/GillianCore/engine/FOLogic/Reduction.mli +++ b/GillianCore/engine/FOLogic/Reduction.mli @@ -7,7 +7,7 @@ exception ReductionException of Gil_syntax.Expr.t * string If successful, it returns that location, together with any bindings learned during the resolution. *) val resolve_expr_to_location : - PFS.t -> Type_env.t -> Gil_syntax.Expr.t -> string option + PFS.t -> Type_env.t -> Gil_syntax.Expr.t -> Id.any_loc Id.t option (** [get_equal_expressions pfs e] returns a list of expressions that equal [e] under the pure formulae [pfs]. *) @@ -18,7 +18,7 @@ val understand_lstcat : Type_env.t -> Expr.t list -> Expr.t list -> - (Expr.t * Containers.SS.t) option + (Expr.t * LVar.Set.t) option (** [reduce_lexpr ?matching ?reduce_lvars ?pfs ?gamma e] reduces the expression [e] given (optional) pure formulae [pfs] and typing environment [gamma]. diff --git a/GillianCore/engine/FOLogic/Simplifications.ml b/GillianCore/engine/FOLogic/Simplifications.ml index a6a856ec9..fbcd5e2ed 100644 --- a/GillianCore/engine/FOLogic/Simplifications.ml +++ b/GillianCore/engine/FOLogic/Simplifications.ml @@ -4,17 +4,17 @@ module SB = Containers.SB type simpl_key_type = { kill_new_lvars : bool option; - gamma_list : (Var.t * Type.t) list; + gamma_list : (Id.any_var Id.t * Type.t) list; pfs_list : Expr.t list; - existentials : SS.t; + existentials : LVar.Set.t; matching : bool; - save_spec_vars : (SS.t * bool) option; (* rpfs_lvars : CCommon.SS.t *) + save_spec_vars : (LVar.Set.t * bool) option; (* rpfs_lvars : CCommon.SS.t *) } type simpl_val_type = { - simpl_gamma : (Var.t * Type.t) list; + simpl_gamma : (Id.any_var Id.t * Type.t) list; simpl_pfs : Expr.t list; - simpl_existentials : SS.t; + simpl_existentials : LVar.Set.t; subst : SVal.SESubst.t; } @@ -85,7 +85,7 @@ let get_num_set_intersections pfs = Or, BinOp (LVar elem, FLessThan, LVar z) ) ) when x = y && x = z -> - L.(verbose (fun m -> m "Got left: %s, %s" elem set)); + L.verbose (fun m -> m "Got left: %a, %a" Id.pp elem Id.pp set); Hashtbl.add lvars elem set | ForAll ( [ (x, Some NumberType) ], @@ -94,15 +94,16 @@ let get_num_set_intersections pfs = Or, BinOp (LVar z, FLessThan, LVar elem) ) ) when x = y && x = z -> - L.(verbose (fun m -> m "Got right: %s, %s" elem set)); + L.verbose (fun m -> m "Got right: %a, %a" Id.pp elem Id.pp set); Hashtbl.add rvars elem set | _ -> ()) pfs; - L.verbose (fun m -> m "v <# set :"); - Hashtbl.iter (fun v s -> L.(verbose (fun m -> m "\t%s, %s" v s))) lvars; - L.verbose (fun m -> m "set <# v :"); - Hashtbl.iter (fun v s -> L.(verbose (fun m -> m "\t%s, %s" v s))) rvars; + L.verbose (fun m -> + let hashtbl_pp : (LVar.t, LVar.t) Hashtbl.t Fmt.t = + Fmt.(hashtbl ~sep:(any "\t") (pair ~sep:comma Id.pp Id.pp)) + in + m "v <# set :@\n%a@\nset <# v :@\n%a" hashtbl_pp lvars hashtbl_pp rvars); (* * 1. forall (v, s) in lvars -> inter { v }, s = 0 @@ -172,21 +173,16 @@ let _resolve_set_existentials let exists = ref exists in let set_exists = - SS.filter (fun x -> Type_env.get gamma x = Some SetType) !exists + LVar.Set.filter (fun x -> Type_env.get gamma x = Some SetType) !exists in - if SS.cardinal set_exists > 0 then ( + if LVar.Set.cardinal set_exists > 0 then ( let intersections = get_num_set_intersections (PFS.to_list lpfs @ PFS.to_list rpfs) in - L.( - verbose (fun m -> - m "Intersections we have:\n%s" - (String.concat "\n" - (List.map - (fun s -> - String.concat ", " - (List.map (fun e -> (Fmt.to_to_string Expr.pp) e) s)) - intersections)))); + L.verbose (fun m -> + m "Intersections we have:\n%a" + Fmt.(list ~sep:(any "\n") @@ list ~sep:comma Expr.pp) + intersections); let filter_map_fun (formula_to_filter : Expr.t) = match formula_to_filter with @@ -276,14 +272,14 @@ let _resolve_set_existentials in (* CAREFULLY substitute *) match lhs with - | LVar v when SS.mem v set_exists -> + | LVar v when LVar.Set.mem v set_exists -> L.( verbose (fun m -> - m "Managed to instantiate a set existential: %s" v)); + m "Managed to instantiate a set existential: %a" Id.pp v)); let temp_subst = SESubst.init [] in SESubst.put temp_subst (LVar v) rhs; PFS.substitution temp_subst rpfs; - exists := SS.remove v !exists; + exists := LVar.Set.remove v !exists; while Type_env.mem gamma v do Type_env.remove gamma v done; @@ -308,15 +304,15 @@ let _resolve_set_existentials let simplify_pfs_and_gamma ?(matching = false) ?(kill_new_lvars : bool option) - ?(save_spec_vars : (SS.t * bool) option) - ?(existentials : SS.t option) + ?(save_spec_vars : (LVar.Set.t * bool) option) + ?(existentials : LVar.Set.t option) (lpfs : PFS.t) ?(rpfs : PFS.t option) - (gamma : Type_env.t) : SESubst.t * SS.t = + (gamma : Type_env.t) : SESubst.t * LVar.Set.t = (* let t = Sys.time () in *) let rpfs : PFS.t = Option.value ~default:(PFS.init ()) rpfs in - let existentials : SS.t ref = - ref (Option.value ~default:SS.empty existentials) + let existentials : LVar.Set.t ref = + ref (Option.value ~default:LVar.Set.empty existentials) in let key : simpl_key_type = @@ -354,16 +350,16 @@ let simplify_pfs_and_gamma let result = SESubst.init [] in let vars_to_save, save_all = - Option.value ~default:(SS.empty, false) save_spec_vars + Option.value ~default:(LVar.Set.empty, false) save_spec_vars in - let vars_to_kill = ref SS.empty in + let vars_to_kill = ref LVar.Set.empty in let kill_new_lvars = Option.value ~default:false kill_new_lvars in (* Unit types *) let simplify_unit_types () = Type_env.iter gamma (fun x t -> - let e = Expr.from_var_name x in + let e = Expr.var_to_expr x in match t with | UndefinedType -> SESubst.put result e (Lit Undefined) | NullType -> SESubst.put result e (Lit Null) @@ -427,8 +423,8 @@ let simplify_pfs_and_gamma let append_lvar = LVar.alloc () in (* Fresh variables can be removed *) vars_to_kill := - SS.add append_lvar - (SS.add_seq (List.to_seq prepend_lvars) !vars_to_kill); + LVar.Set.add append_lvar + (LVar.Set.add_seq (List.to_seq prepend_lvars) !vars_to_kill); let prepend = List.map (fun x -> Expr.LVar x) prepend_lvars in let append = Expr.LVar append_lvar in rec_call @@ -450,7 +446,8 @@ let simplify_pfs_and_gamma let len = Z.to_int len in if len >= 0 then ( let le_vars = List.init len (fun _ -> LVar.alloc ()) in - vars_to_kill := SS.union !vars_to_kill (SS.of_list le_vars); + vars_to_kill := + LVar.Set.union !vars_to_kill (LVar.Set.of_list le_vars); let le' = List.map (fun x -> Expr.LVar x) le_vars in rec_call (BinOp (le, Equal, EList le'))) else stop_explain "List length an unexpected integer." @@ -469,7 +466,7 @@ let simplify_pfs_and_gamma | None -> `Replace whole | Some (pf, new_vars) -> extend_with pf; - vars_to_kill := SS.union !vars_to_kill new_vars; + vars_to_kill := LVar.Set.union !vars_to_kill new_vars; `Replace whole) (* *) | BinOp (UnOp (LstLen, x), Equal, BinOp (Lit (Int n), IPlus, LVar z)) @@ -492,7 +489,7 @@ let simplify_pfs_and_gamma let prefix_lvar = LVar.alloc () in let suffix_lvar = LVar.alloc () in vars_to_kill := - SS.add prefix_lvar (SS.add suffix_lvar !vars_to_kill); + LVar.Set.add prefix_lvar (LVar.Set.add suffix_lvar !vars_to_kill); let suffix_len = let open Expr.Infix in Expr.list_length lst - (start + num) @@ -534,7 +531,7 @@ let simplify_pfs_and_gamma | UnOp (LstLen, LVar x), UnOp (LstLen, LVar y) when x <> y -> let x, y = match - (Names.is_spec_var_name x, Names.is_spec_var_name y) + (LVar.is_spec_var_name x, LVar.is_spec_var_name y) with | true, false -> (x, y) | false, true -> (y, x) @@ -554,7 +551,7 @@ let simplify_pfs_and_gamma PFS.substitution_in_place temp_subst lpfs *) | ALoc alocl, ALoc alocr when matching -> L.verbose (fun fmt -> - fmt "Two equal alocs: %s and %s" alocl alocr); + fmt "Two equal alocs: %a and %a" Id.pp alocl Id.pp alocr); SESubst.put result (ALoc alocr) (ALoc alocl); let temp_subst = SESubst.init [ (ALoc alocr, ALoc alocl) ] @@ -577,23 +574,27 @@ let simplify_pfs_and_gamma let v, (le : Expr.t) = match le with | LVar w -> ( - let save_v = save_all || SS.mem v vars_to_save in - let save_w = save_all || SS.mem w vars_to_save in + let save_v = + save_all || LVar.Set.mem v vars_to_save + in + let save_w = + save_all || LVar.Set.mem w vars_to_save + in match (save_v, save_w) with | true, false -> (w, LVar v) | true, true -> (v, le) | false, true -> (v, le) | false, false -> if - Names.is_spec_var_name v - && not (Names.is_spec_var_name w) + LVar.is_spec_var_name v + && not (LVar.is_spec_var_name w) then (w, LVar v) else (v, le)) | _ -> (v, le) in let lvars_le = Expr.lvars le in - match SS.mem v lvars_le with + match LVar.Set.mem v lvars_le with (* Cannot substitute if variable on both sides or not substitutable *) | true -> `Replace whole | false -> ( @@ -627,7 +628,7 @@ let simplify_pfs_and_gamma SESubst.put result x sle); SESubst.put result (LVar v) le; - existentials := SS.remove v !existentials; + existentials := LVar.Set.remove v !existentials; (* Understand gamma if subst is another LVar *) let* () = @@ -649,7 +650,9 @@ let simplify_pfs_and_gamma (* Remove (or add) from (or to) gamma *) let* () = - match save_all || SS.mem v vars_to_save with + match + save_all || LVar.Set.mem v vars_to_save + with | true -> ( let le_type, _ = Typing.type_lexpr gamma le @@ -711,7 +714,7 @@ let simplify_pfs_and_gamma match pf with (* List length direct equality *) | BinOp (UnOp (LstLen, LVar x), Equal, UnOp (LstLen, LVar y)) - when not (String.equal x y) -> + when not (Id.equal x y) -> let lens = map_add (UnOp (LstLen, LVar y)) (LVar x) lens in (map_add (UnOp (LstLen, LVar x)) (LVar y) lens, cats, xcats) (* List length equals some other expression on the right *) @@ -873,20 +876,28 @@ let simplify_pfs_and_gamma match v with | LVar v -> if - (not (SS.mem v !vars_to_kill)) + (not (LVar.Set.mem v !vars_to_kill)) && (save_all - || (kill_new_lvars && SS.mem v vars_to_save) - || ((not kill_new_lvars) && vars_to_save <> SS.empty)) - && not (Names.is_aloc_name v) + || (kill_new_lvars && LVar.Set.mem v vars_to_save) + || (not kill_new_lvars) + && (not @@ LVar.Set.is_empty vars_to_save)) + && not (Names.is_aloc_name (LVar.str v)) then PFS.extend lpfs (BinOp (LVar v, Equal, le)) | _ -> ()); sanitise_pfs_no_store ~matching gamma lpfs; - let current_lvars = SS.union (PFS.lvars lpfs) (PFS.lvars rpfs) in + let current_lvars = + LVar.Set.union (PFS.lvars lpfs) (PFS.lvars rpfs) + in Type_env.iter gamma (fun v _ -> - if SS.mem v !vars_to_kill && not (SS.mem v current_lvars) then - Type_env.remove gamma v); + (* Need to cast Var|LVar to LVar, unfortunately. + Could Type_env be reduced to only handle LVars? *) + let v_ = LVar.of_string (Id.str v) in + if + LVar.Set.mem v_ !vars_to_kill + && not (LVar.Set.mem v_ current_lvars) + then Type_env.remove gamma v); Type_env.iter gamma (fun v t -> match t with @@ -895,7 +906,7 @@ let simplify_pfs_and_gamma (BinOp ( Expr.zero_i, ILessThanEqual, - UnOp (LstLen, Expr.from_var_name v) )) + UnOp (LstLen, Expr.var_to_expr v) )) | _ -> ()); analyse_list_structure lpfs; @@ -950,7 +961,7 @@ let simplify_pfs_and_gamma let simplify_implication ~matching - (exists : SS.t) + (exists : LVar.Set.t) (lpfs : PFS.t) (rpfs : PFS.t) (gamma : Type_env.t) = @@ -991,7 +1002,7 @@ let simplify_implication @[Right:@ %a@]\n\ Gamma:\n\ %a\n" - (Fmt.iter ~sep:Fmt.comma SS.iter Fmt.string) + (Fmt.iter ~sep:Fmt.comma LVar.Set.iter Id.pp) exists PFS.pp lpfs PFS.pp rpfs Type_env.pp gamma)); (* Utils.Statistics.update_statistics "FOS: SimplifyImplication" (Sys.time () -. t); *) @@ -1012,9 +1023,9 @@ let admissible_assertion (a : Asrt.t) : bool = | Pure f -> PFS.extend pfs f | Types ets -> List.iter - (fun (le, t) -> - match (le : Expr.t) with - | LVar x | PVar x -> Type_env.update gamma x t + (function + | Expr.LVar x, t -> Type_env.update gamma x t + | PVar x, t -> Type_env.update gamma x t | _ -> ()) ets | _ -> () diff --git a/GillianCore/engine/FOLogic/Simplifications.mli b/GillianCore/engine/FOLogic/Simplifications.mli index 355e8b126..637927231 100644 --- a/GillianCore/engine/FOLogic/Simplifications.mli +++ b/GillianCore/engine/FOLogic/Simplifications.mli @@ -12,24 +12,19 @@ val simplify_pfs_and_gamma : ?matching:bool -> ?kill_new_lvars:bool -> - ?save_spec_vars:Utils.Containers.SS.t * bool -> - ?existentials:Utils.Containers.SS.t -> + ?save_spec_vars:LVar.Set.t * bool -> + ?existentials:LVar.Set.t -> PFS.t -> ?rpfs:PFS.t -> Type_env.t -> - SVal.SESubst.t * Utils.Containers.SS.t + SVal.SESubst.t * LVar.Set.t (** [simplify_implication existentials lpfs rpfs gamma] simplifies the entailment << ∃ [existentials]. [lpfs] => [rpfs] >> under the typing environment [gamma], attempting to instantiate the [existentials] and returning a (possibly smaller) new set of existentials *) val simplify_implication : - matching:bool -> - Utils.Containers.SS.t -> - PFS.t -> - PFS.t -> - Type_env.t -> - Utils.Containers.SS.t + matching:bool -> LVar.Set.t -> PFS.t -> PFS.t -> Type_env.t -> LVar.Set.t (** [admissible_assertion a] checks whether or not the assertion [a] is a contradiction only using the reductions/simplifications *) diff --git a/GillianCore/engine/FOLogic/type_env.ml b/GillianCore/engine/FOLogic/type_env.ml index 2cb626594..ed20e069f 100644 --- a/GillianCore/engine/FOLogic/type_env.ml +++ b/GillianCore/engine/FOLogic/type_env.ml @@ -4,7 +4,8 @@ open Names open SVal module L = Logging -type t = (string, Type.t) Hashtbl.t [@@deriving yojson] +type k = Id.any_var Id.t [@@deriving yojson] +type t = (k, Type.t) Hashtbl.t [@@deriving yojson] let as_hashtbl x = x @@ -17,78 +18,75 @@ let as_hashtbl x = x let init () : t = Hashtbl.create Config.medium_tbl_size (* Copy *) -let copy (x : t) : t = Hashtbl.copy x +let copy : t -> t = Hashtbl.copy (* Type of a variable *) -let get (x : t) (var : string) : Type.t option = Hashtbl.find_opt x var +let get (x : t) (k : [< Id.any_var ] Id.t) : Type.t option = + Hashtbl.find_opt x (k :> Id.any_var Id.t) (* Membership *) -let mem (x : t) (v : string) : bool = Hashtbl.mem x v +let mem (x : t) (k : [< Id.any_var ] Id.t) : bool = + Hashtbl.mem x (k :> Id.any_var Id.t) (* Empty *) let empty (x : t) : bool = Hashtbl.length x == 0 (* Type of a variable *) -let get_unsafe (x : t) (var : string) : Type.t = - match Hashtbl.find_opt x var with - | Some t -> t - | None -> - raise (Failure ("Type_env.get_unsafe: variable " ^ var ^ " not found.")) - -(* Get all matchable elements *) -let matchables (x : t) : SS.t = - Hashtbl.fold (fun var _ ac -> SS.add var ac) x SS.empty - -(* Get all variables *) -let vars (x : t) : SS.t = - Hashtbl.fold (fun var _ ac -> SS.add var ac) x SS.empty +let get_unsafe (x : t) (k : [< Id.any_var ] Id.t) : Type.t = + try Hashtbl.find x (k :> Id.any_var Id.t) + with _ -> Fmt.failwith "Type_env.get_unsafe: variable %a not found." Id.pp k (* Get all logical variables *) -let lvars (x : t) : SS.t = +let lvars (x : t) : LVar.Set.t = Hashtbl.fold - (fun var _ ac -> if is_lvar_name var then SS.add var ac else ac) - x SS.empty + (fun var _ ac -> + let var = Id.str var in + if is_lvar_name var then LVar.Set.add (LVar.of_string var) ac else ac) + x LVar.Set.empty (* Get all variables of specific type *) -let get_vars_of_type (x : t) (tt : Type.t) : string list = +let get_vars_of_type (x : t) (tt : Type.t) : k list = Hashtbl.fold (fun var t ac_vars -> if t = tt then var :: ac_vars else ac_vars) x [] (* Get all var-type pairs as a list *) -let get_var_type_pairs (x : t) : (string * Type.t) Seq.t = Hashtbl.to_seq x +let get_var_type_pairs : t -> (k * Type.t) Seq.t = Hashtbl.to_seq (* Iteration *) -let iter (x : t) (f : string -> Type.t -> unit) : unit = Hashtbl.iter f x +let iter (x : t) (f : k -> Type.t -> unit) : unit = Hashtbl.iter f x -let fold (x : t) (f : string -> Type.t -> 'a -> 'a) (init : 'a) : 'a = +let fold (x : t) (f : k -> Type.t -> 'a -> 'a) (init : 'a) : 'a = Hashtbl.fold f x init let pp fmt tenv = - let pp_pair fmt (v, vt) = Fmt.pf fmt "(%s: %s)" v (Type.str vt) in + let pp_pair fmt (v, vt) = Fmt.pf fmt "(%a: %s)" Id.pp v (Type.str vt) in let bindings = fold tenv (fun x t ac -> (x, t) :: ac) [] in let bindings = List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) bindings in (Fmt.list ~sep:(Fmt.any "@\n") pp_pair) fmt bindings let pp_by_need vars fmt tenv = - let pp_pair fmt (v, vt) = Fmt.pf fmt "(%s: %s)" v (Type.str vt) in + let pp_pair fmt (v, vt) = Fmt.pf fmt "(%a: %s)" Id.pp v (Type.str vt) in let bindings = fold tenv (fun x t ac -> (x, t) :: ac) [] in let bindings = List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) bindings in - let bindings = List.filter (fun (v, _) -> SS.mem v vars) bindings in + let bindings = + List.filter (fun (v, _) -> Id.Sets.VarSet.mem v vars) bindings + in (Fmt.list ~sep:(Fmt.any "@\n") pp_pair) fmt bindings (* Update with removal *) -let update (te : t) (x : string) (t : Type.t) : unit = - match get te x with - | None -> Hashtbl.replace te x t +let update (te : t) (k : [< Id.any_var ] Id.t) (t : Type.t) : unit = + match get te (k :> Id.any_var Id.t) with + | None -> Hashtbl.replace te (k :> Id.any_var Id.t) t | Some t' when t' = t -> () | Some t' -> Fmt.failwith - "Type_env update: Conflict: %s has type %s but required extension is %s" - x (Type.str t') (Type.str t) + "Type_env update: Conflict: %a has type %s but required extension is %s" + Id.pp k (Type.str t') (Type.str t) -let remove (te : t) (x : string) : unit = Hashtbl.remove te x +let remove (te : t) (k : [< Id.any_var ] Id.t) : unit = + Hashtbl.remove te (k :> Id.any_var Id.t) (* Extend gamma with more_gamma *) let extend (x : t) (y : t) : unit = @@ -100,65 +98,53 @@ let extend (x : t) (y : t) : unit = raise (Failure "Typing environment cannot be extended.")) (* Filter using function on variables *) -let filter (x : t) (f : string -> bool) : t = +let filter (x : t) (f : k -> bool) : t = let new_gamma = init () in iter x (fun v v_type -> if f v then update new_gamma v v_type); new_gamma (* Filter using function on variables *) -let filter_in_place (x : t) (f : string -> bool) : unit = +let filter_in_place (x : t) (f : k -> bool) : unit = iter x (fun v _ -> if not (f v) then remove x v) (* Filter for specific variables *) -let filter_vars (gamma : t) (vars : SS.t) : t = - filter gamma (fun v -> SS.mem v vars) +let filter_vars (gamma : t) (vars : Id.Sets.VarSet.t) : t = + filter gamma (fun v -> Id.Sets.VarSet.mem v vars) (* Filter for specific variables *) -let filter_vars_in_place (gamma : t) (vars : SS.t) : unit = - filter_in_place gamma (fun v -> SS.mem v vars) +let filter_vars_in_place (gamma : t) (vars : Id.Sets.VarSet.t) : unit = + filter_in_place gamma (fun v -> Id.Sets.VarSet.mem v vars) (* Perform substitution, return new typing environment *) let substitution (x : t) (subst : SESubst.t) (partial : bool) : t = let new_gamma = init () in iter x (fun var v_type -> - let evar = Expr.from_var_name var in + let evar = Expr.var_to_expr var in let new_var = SESubst.get subst evar in match new_var with - | Some (LVar new_var) -> update new_gamma new_var v_type + | Some (LVar new_var) -> update new_gamma (new_var :> k) v_type | Some _ -> if partial then update new_gamma var v_type | None -> if partial then update new_gamma var v_type - else if Names.is_lvar_name var then ( + else if Names.is_lvar_name (Id.str var) then ( let new_lvar = LVar.alloc () in SESubst.put subst evar (LVar new_lvar); - update new_gamma new_lvar v_type)); + update new_gamma (new_lvar :> k) v_type)); new_gamma let to_list_expr (x : t) : (Expr.t * Type.t) list = - let le_type_pairs = - Hashtbl.fold - (fun x t (pairs : (Expr.t * Type.t) list) -> - if Names.is_lvar_name x then (LVar x, t) :: pairs - else (PVar x, t) :: pairs) - x [] - in - le_type_pairs + Hashtbl.fold (fun x t pairs -> (Expr.var_to_expr x, t) :: pairs) x [] -let to_list (x : t) : (Var.t * Type.t) list = - let le_type_pairs = - Hashtbl.fold - (fun x t (pairs : (Var.t * Type.t) list) -> (x, t) :: pairs) - x [] - in - le_type_pairs +let to_list (x : t) : (k * Type.t) list = + Hashtbl.fold (fun x t pairs -> (x, t) :: pairs) x [] -let reset (x : t) (reset : (Var.t * Type.t) list) = +let reset (x : t) (reset : (k * Type.t) list) = Hashtbl.clear x; List.iter (fun (y, t) -> Hashtbl.replace x y t) reset let is_well_formed (_ : t) : bool = true -let filter_with_info relevant_info (x : t) = - let pvars, lvars, locs = relevant_info in - let relevant = List.fold_left SS.union SS.empty [ pvars; lvars; locs ] in - filter x (fun x -> SS.mem x relevant) +let filter_with_info (pvars, lvars, _) (x : t) = + let open Id.Sets in + let relevant = VarSet.union (pvar_to_varset pvars) (lvar_to_varset lvars) in + filter x (fun k -> VarSet.mem k relevant) diff --git a/GillianCore/engine/FOLogic/type_env.mli b/GillianCore/engine/FOLogic/type_env.mli index c2d55c894..774f6c135 100644 --- a/GillianCore/engine/FOLogic/type_env.mli +++ b/GillianCore/engine/FOLogic/type_env.mli @@ -1,5 +1,5 @@ (** @canonical Gillian.Symbolic.Type_env - + Interface for typing environments *) open SVal @@ -7,34 +7,32 @@ open SVal (** @canonical Gillian.Symbolic.Type_env.t *) type t [@@deriving yojson] -val as_hashtbl : t -> (string, Type.t) Hashtbl.t +type k := Id.any_var Id.t + +val as_hashtbl : t -> (k, Type.t) Hashtbl.t val copy : t -> t val extend : t -> t -> unit -val filter : t -> (string -> bool) -> t -val filter_in_place : t -> (string -> bool) -> unit -val filter_vars : t -> Containers.SS.t -> t -val filter_vars_in_place : t -> Containers.SS.t -> unit -val get : t -> string -> Type.t option -val get_unsafe : t -> string -> Type.t -val get_var_type_pairs : t -> (string * Type.t) Seq.t -val get_vars_of_type : t -> Type.t -> string list +val filter : t -> (k -> bool) -> t +val filter_in_place : t -> (k -> bool) -> unit +val filter_vars : t -> Id.Sets.VarSet.t -> t +val filter_vars_in_place : t -> Id.Sets.VarSet.t -> unit +val get : t -> [< Id.any_var ] Id.t -> Type.t option +val get_unsafe : t -> [< Id.any_var ] Id.t -> Type.t +val get_var_type_pairs : t -> (k * Type.t) Seq.t +val get_vars_of_type : t -> Type.t -> k list val init : unit -> t -val mem : t -> string -> bool +val mem : t -> [< Id.any_var ] Id.t -> bool val empty : t -> bool -val pp : Format.formatter -> t -> unit -val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit -val update : t -> string -> Type.t -> unit -val remove : t -> string -> unit -val reset : t -> (Var.t * Type.t) list -> unit -val iter : t -> (string -> Type.t -> unit) -> unit -val fold : t -> (string -> Type.t -> 'a -> 'a) -> 'a -> 'a -val lvars : t -> Containers.SS.t -val vars : t -> Containers.SS.t -val matchables : t -> Containers.SS.t -val to_list : t -> (Var.t * Type.t) list +val pp : t Fmt.t +val pp_by_need : Id.Sets.VarSet.t -> Format.formatter -> t -> unit +val update : t -> [< Id.any_var ] Id.t -> Type.t -> unit +val remove : t -> [< Id.any_var ] Id.t -> unit +val reset : t -> (k * Type.t) list -> unit +val iter : t -> (k -> Type.t -> unit) -> unit +val fold : t -> (k -> Type.t -> 'a -> 'a) -> 'a -> 'a +val lvars : t -> LVar.Set.t +val to_list : t -> (k * Type.t) list val to_list_expr : t -> (Expr.t * Type.t) list val substitution : t -> SESubst.t -> bool -> t val is_well_formed : t -> bool - -val filter_with_info : - Containers.SS.t * Containers.SS.t * Containers.SS.t -> t -> t +val filter_with_info : Var.Set.t * LVar.Set.t * 'a -> t -> t diff --git a/GillianCore/engine/FOLogic/typing.ml b/GillianCore/engine/FOLogic/typing.ml index edb1327e2..d8e32db79 100644 --- a/GillianCore/engine/FOLogic/typing.ml +++ b/GillianCore/engine/FOLogic/typing.ml @@ -131,7 +131,14 @@ module Infer_types_to_gamma = struct | Lit lit -> Literal.type_of lit = tt (* Variables are reverse-typable if they are already typable *) (* with the target type or if they are not typable *) - | LVar var | PVar var -> ( + | LVar var -> ( + match (Type_env.get gamma var, Type_env.get new_gamma var) with + | Some t, None | None, Some t -> t = tt + | None, None -> + Type_env.update new_gamma var tt; + true + | Some t1, Some t2 -> t1 = t2) + | PVar var -> ( match (Type_env.get gamma var, Type_env.get new_gamma var) with | Some t, None | None, Some t -> t = tt | None, None -> @@ -173,7 +180,7 @@ module Infer_types_to_gamma = struct (* We've updated our new_gamma_copy with a bunch of things. We need to import everything except the quantified variables to the new_gamma *) Type_env.iter new_gamma_copy (fun x t -> - if not (List.exists (fun (y, _) -> String.equal x y) bt) then + if not (List.exists (fun (y, _) -> Id.equal x y) bt) then Type_env.update new_gamma x t); ret end @@ -457,7 +464,8 @@ module Type_lexpr = struct (* Literals are always typable *) | Lit lit -> def_pos (Some (Literal.type_of lit)) (* Variables are typable if in gamma, otherwise no, but typing continues *) - | LVar var | PVar var -> def_pos (Type_env.get gamma var) + | LVar var -> def_pos (Type_env.get gamma var) + | PVar var -> def_pos (Type_env.get gamma var) (* Abstract locations are always typable, by construction *) | ALoc _ -> def_pos (Some ObjectType) (* Lists are always typable *) @@ -490,11 +498,14 @@ let te_of_list (vt : (Expr.t * Type.t) list) : Type_env.t option = | Lit l -> let t' = Literal.type_of l in if t <> t' then raise Break - | LVar x | PVar x -> - if Type_env.mem result x then ( - let t' = Type_env.get_unsafe result x in - if t <> t' then raise Break) - else Type_env.update result x t + | LVar x -> ( + match Type_env.get result x with + | Some t' -> if t <> t' then raise Break + | None -> Type_env.update result x t) + | PVar x -> ( + match Type_env.get result x with + | Some t' -> if t <> t' then raise Break + | None -> Type_env.update result x t) | _ -> ( let t', _ = type_lexpr result e in match t' with @@ -511,9 +522,7 @@ let naively_infer_type_information (pfs : PFS.t) (gamma : Type_env.t) : unit = | Expr.BinOp (LVar x, Equal, le) | Expr.BinOp (le, Equal, LVar x) -> if not (Type_env.mem gamma x) then let le_type, _ = type_lexpr gamma le in - Option.fold - ~some:(fun x_type -> Type_env.update gamma x x_type) - ~none:() le_type + Option.fold ~some:(Type_env.update gamma x) ~none:() le_type | Expr.BinOp (UnOp (TypeOf, LVar x), Equal, Lit (Type t)) | Expr.BinOp (Lit (Type t), Equal, UnOp (TypeOf, LVar x)) -> Type_env.update gamma x t @@ -526,7 +535,13 @@ let substitution_in_place (subst : SSubst.t) (gamma : Type_env.t) : unit = List.fold_left (fun ac (x, e) -> match x with - | Expr.LVar x | PVar x -> + | Expr.LVar x -> + Option.fold + ~some:(fun x_type -> + Type_env.remove gamma x; + (e, x_type) :: ac) + ~none:ac (Type_env.get gamma x) + | PVar x -> Option.fold ~some:(fun x_type -> Type_env.remove gamma x; @@ -536,4 +551,4 @@ let substitution_in_place (subst : SSubst.t) (gamma : Type_env.t) : unit = [] ve_pairs in let gamma' = reverse_type_lexpr true gamma et_pairs in - Option.fold ~some:(fun gamma' -> Type_env.extend gamma gamma') ~none:() gamma' + Option.fold ~some:(Type_env.extend gamma) ~none:() gamma' diff --git a/GillianCore/engine/concrete_semantics/CExprEval.ml b/GillianCore/engine/concrete_semantics/CExprEval.ml index 95b0ce28c..a1b349c01 100644 --- a/GillianCore/engine/concrete_semantics/CExprEval.ml +++ b/GillianCore/engine/concrete_semantics/CExprEval.ml @@ -320,10 +320,7 @@ and evaluate_expr (store : CStore.t) (e : Expr.t) : CVal.M.t = | Lit lit -> lit | PVar x -> ( match CStore.get store x with - | None -> - let err_msg = Fmt.str "Variable %s not found in the store" x in - (* if (!verbose) then Fmt.printf "The current store is: \n%s" CStore.pp store; *) - raise (Failure err_msg) + | None -> Fmt.failwith "Variable %a not found in the store" Var.pp x | Some v -> v) | BinOp (e1, bop, e2) -> evaluate_binop store bop e1 e2 | UnOp (unop, e) -> evaluate_unop unop (ee e) diff --git a/GillianCore/engine/concrete_semantics/CState.ml b/GillianCore/engine/concrete_semantics/CState.ml index b305d9d89..0ac3ae3ca 100644 --- a/GillianCore/engine/concrete_semantics/CState.ml +++ b/GillianCore/engine/concrete_semantics/CState.ml @@ -127,22 +127,16 @@ end = struct let get_lvars _ = raise (Failure "ERROR: get_lvars called for concrete executions") - let to_assertions ?to_keep:_ (_ : t) : Asrt.t = + let to_assertions ?to_keep:_ _ = raise (Failure "ERROR: to_assertions called for concrete executions") - let run_spec - (_ : MP.spec) - (_ : t) - (_ : string) - (_ : vt list) - (_ : (string * (string * vt) list) option) = + let run_spec _ _ _ _ _ = raise (Failure "ERROR: run_spec called for non-abstract execution") - let unfolding_vals (_ : t) (_ : Expr.t list) : vt list = + let unfolding_vals _ _ = raise (Failure "ERROR: unfolding_vals called for non-abstract execution") - let evaluate_slcmd (_ : 'a MP.prog) (_ : SLCmd.t) (_ : t) : - (t, err_t) Res_list.t = + let evaluate_slcmd _ _ _ = raise (Failure "ERROR: evaluate_slcmd called for non-abstract execution") let match_invariant _ _ _ _ _ = diff --git a/GillianCore/engine/general_semantics/call_stack.ml b/GillianCore/engine/general_semantics/call_stack.ml index 0ddcb6020..a4ca73f14 100644 --- a/GillianCore/engine/general_semantics/call_stack.ml +++ b/GillianCore/engine/general_semantics/call_stack.ml @@ -1,5 +1,5 @@ (** @canonical Gillian.General.Call_stack - + Implementation of GIL call stacks *) (** @canonical Gillian.General.Call_stack.S *) @@ -51,7 +51,7 @@ module type S = sig Get current procedure identifier @param cs Target call stack - @return Identifier of the procedure currently being executed + @return Id of the procedure currently being executed *) val get_cur_proc_id : t -> string @@ -161,7 +161,7 @@ module Make (Val : Val.S) (Store : Store.S with type vt = Val.t) : Get current procedure identifier @param cs Target call stack - @return Identifier of the procedure currently being executed + @return Id of the procedure currently being executed *) let get_cur_proc_id (cs : t) : string = diff --git a/GillianCore/engine/general_semantics/eSubst.ml b/GillianCore/engine/general_semantics/eSubst.ml index 73db6e83f..2b23f45ac 100644 --- a/GillianCore/engine/general_semantics/eSubst.ml +++ b/GillianCore/engine/general_semantics/eSubst.ml @@ -24,7 +24,7 @@ module type S = sig val clear : t -> unit (** Domain of the e-substitution *) - val domain : t -> (Expr.t -> bool) option -> Expr.Set.t + val domain : t -> Expr.Set.t (** Range of the e-substitution *) val range : t -> vt list @@ -69,7 +69,8 @@ module type S = sig val full_pp : Format.formatter -> t -> unit (** Selective Pretty Printer *) - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit + val pp_by_need : + Var.Set.t -> LVar.Set.t -> ALoc.Set.t -> Format.formatter -> t -> unit val filter_in_place : t -> (Expr.t -> vt -> vt option) -> unit @@ -90,7 +91,6 @@ module type S = sig end module Make (Val : Val.S) : S with type vt = Val.t = struct - open Containers module L = Logging (** Type of GIL values *) @@ -132,15 +132,8 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param filter_out Optional filtering function @return Domain of the (filtered) substitution *) - let domain (subst : t) (filter_out : (Expr.t -> bool) option) : Expr.Set.t = - let filter = - match filter_out with - | Some filter -> filter - | None -> fun _ -> false - in - Hashtbl.fold - (fun e _ ac -> if filter e then ac else Expr.Set.add e ac) - subst Expr.Set.empty + let domain (subst : t) : Expr.Set.t = + Hashtbl.fold (fun e _ ac -> Expr.Set.add e ac) subst Expr.Set.empty (** Substitution range @@ -284,25 +277,19 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct in Fmt.pf fmt "@[[ %a ]@]" (Fmt.list ~sep:Fmt.comma pp_pair) bindings - let pp_by_need (filter_vars : Containers.SS.t) fmt (subst : t) = + let pp_by_need f_pvars f_lvars f_alocs fmt (subst : t) = let pp_pair fmt (e, e_val) = Fmt.pf fmt "@[(%a: %a)@]" Expr.pp e Val.pp e_val in - let bindings = fold subst (fun x t ac -> (x, t) :: ac) [] in - let bindings = - List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) bindings - in let bindings = - List.filter - (fun (v, _) -> - let pvars, lvars, alocs = - (Expr.pvars v, Expr.lvars v, Expr.alocs v) - in - Containers.SS.inter - (SS.union pvars (SS.union lvars alocs)) - filter_vars - <> Containers.SS.empty) - bindings + fold subst (fun x t ac -> (x, t) :: ac) [] + |> List.filter (fun (v, _) -> + not + ((Var.Set.is_empty @@ Var.Set.inter f_pvars @@ Expr.pvars v) + && (LVar.Set.is_empty @@ LVar.Set.inter f_lvars @@ Expr.lvars v) + && (ALoc.Set.is_empty @@ ALoc.Set.inter f_alocs @@ Expr.alocs v) + )) + |> List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) in Fmt.pf fmt "@[[ %a ]@]" (Fmt.list ~sep:Fmt.comma pp_pair) bindings @@ -390,12 +377,11 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct self#find_in_subst ~make_new_x:(fun () -> let lvar = LVar.alloc () in - L.( - verbose (fun m -> - m - "General: Subst in lexpr: PVar %s not in subst, generating \ - fresh: %s" - x lvar)); + L.verbose (fun m -> + m + "General: Subst in lexpr: PVar %a not in subst, generating \ + fresh: %a" + Var.pp x LVar.pp lvar); Expr.LVar lvar) this diff --git a/GillianCore/engine/general_semantics/external.ml b/GillianCore/engine/general_semantics/external.ml index 2eff53bc8..119edfa12 100644 --- a/GillianCore/engine/general_semantics/external.ml +++ b/GillianCore/engine/general_semantics/external.ml @@ -18,7 +18,7 @@ module T (Annot : Annot.S) = struct State.t -> Call_stack.t -> int -> - string -> + Var.t -> string -> Val.t list -> int option -> diff --git a/GillianCore/engine/general_semantics/general/g_interpreter.ml b/GillianCore/engine/general_semantics/general/g_interpreter.ml index ea2c36e1e..858f315ae 100644 --- a/GillianCore/engine/general_semantics/general/g_interpreter.ml +++ b/GillianCore/engine/general_semantics/general/g_interpreter.ml @@ -417,20 +417,16 @@ struct raise (Failure (Printf.sprintf "Undefined predecessor: %s %d %d" pid prev i)) - let update_store (state : State.t) (x : string) (v : Val.t) : State.t = + let update_store (state : State.t) (x : Var.t) (v : Val.t) : State.t = let store = State.get_store state in let () = Store.put store x v in let state' = State.set_store state store in state' - let eval_subst_list - (state : State.t) - (subst_lst : (string * (string * Expr.t) list) option) : - (string * (string * Val.t) list) option = - match subst_lst with + let eval_subst_list (state : State.t) = function | None -> None | Some (lab, subst_lst) -> - let subst_lst' : (string * Val.t) list = + let subst_lst' = List.map (fun (x, e) -> (x, State.eval_expr state e)) subst_lst in Some (lab, subst_lst') @@ -517,8 +513,11 @@ struct | _ -> Res_list.vanish let eval_freshsvar x state = - let new_svar = Generators.fresh_svar () in - let state' = State.add_spec_vars state (SS.singleton new_svar) in + let new_svar = LVar.of_string @@ Generators.fresh_svar () in + let state' = + State.add_spec_vars state @@ Id.Sets.SubstSet.singleton + @@ (new_svar :> Id.substable Id.t) + in let v = Val.from_expr (LVar new_svar) |> Option.get in Res_list.return (update_store state' x v) @@ -571,12 +570,10 @@ struct let params_card = List.length params in let args_card = List.length args in if params_card <> args_card then - raise - (Failure - (Printf.sprintf - "Macro %s called with incorrect number of parameters: %d \ - instead of %d." - macro.macro_name args_card params_card)); + Fmt.failwith + "Macro %s called with incorrect number of parameters: %d instead \ + of %d." + macro.macro_name args_card params_card; let subst = SVal.SSubst.init (List.combine params args) in let lcmds = macro.macro_definition in List.map (SVal.SSubst.substitute_lcmd subst ~partial:true) lcmds @@ -1005,7 +1002,7 @@ struct m ~json: [ - ("x", `String x); + ("x", Var.to_yojson x); ("a", `String a); ("es", `List (List.map Expr.to_yojson es)); ] @@ -1375,7 +1372,7 @@ struct DL.log ~v:true (fun m -> m "ECall"); let pid = match pid with - | PVar pid -> pid + | PVar pid -> Var.str pid | Lit (String pid) -> pid | _ -> raise @@ -1421,7 +1418,7 @@ struct } = eval_state in - let v_ret = Store.get store Names.return_variable in + let v_ret = Store.get store Id.return_variable in let result = match (v_ret, cs) with | None, _ -> raise (Failure "nm_ret_var not in store (normal return)") @@ -1490,7 +1487,7 @@ struct } = eval_state in - let v_ret = Store.get store Names.return_variable in + let v_ret = Store.get store Id.return_variable in match (v_ret, cs) with | None, _ -> raise (Failure "Return variable not in store (error return) ") @@ -1564,7 +1561,8 @@ struct | Assignment (x, e) -> DL.log ~v:true (fun m -> m - ~json:[ ("target", `String x); ("expr", Expr.to_yojson e) ] + ~json: + [ ("target", Var.to_yojson x); ("expr", Expr.to_yojson e) ] "Assignment"); let v = eval_expr e in let state' = update_store state x v in @@ -1788,7 +1786,7 @@ struct @param ret_fun Function to transform the results @param prog GIL program - @param name Identifier of the procedure to be evaluated + @param name Id of the procedure to be evaluated @param params Parameters of the procedure to be evaluated @state state Current state @preds preds Current predicate set @@ -2263,7 +2261,7 @@ struct @param ret_fun Function to transform the results @param prog GIL program - @param name Identifier of the procedure to be evaluated + @param name Id of the procedure to be evaluated @param params Parameters of the procedure to be evaluated @state state Current state @preds preds Current predicate set @@ -2273,7 +2271,7 @@ struct (ret_fun : result_t -> 'a) (prog : annot MP.prog) (name : string) - (params : string list) + (params : Var.t list) (state : State.t) : 'a cont_func = let () = Call_graph.add_proc call_graph name in L.normal (fun m -> @@ -2295,8 +2293,8 @@ struct in let cs : Call_stack.t = Call_stack.push Call_stack.empty ~pid:name ~arguments ~loop_ids:[] - ~ret_var:"out" ~call_index:(-1) ~continue_index:(-1) ~error_index:(-1) - () + ~ret_var:(Var.of_string "out") ~call_index:(-1) ~continue_index:(-1) + ~error_index:(-1) () in let proc_body_index = 0 in let conf : CConf.t = @@ -2328,7 +2326,7 @@ struct Evaluation of procedures @param prog GIL program - @param name Identifier of the procedure to be evaluated + @param name Id of the procedure to be evaluated @param params Parameters of the procedure to be evaluated @state state Current state @preds preds Current predicate set @@ -2338,7 +2336,7 @@ struct (ret_fun : result_t -> 'a) (prog : annot MP.prog) (name : string) - (params : string list) + (params : Var.t list) (state : State.t) : 'a list = let init_func = init_evaluate_proc ret_fun prog name params state in evaluate_cmd_iter init_func diff --git a/GillianCore/engine/general_semantics/general/g_interpreter_intf.ml b/GillianCore/engine/general_semantics/general/g_interpreter_intf.ml index eebee5027..cd4d8bc20 100644 --- a/GillianCore/engine/general_semantics/general/g_interpreter_intf.ml +++ b/GillianCore/engine/general_semantics/general/g_interpreter_intf.ml @@ -82,7 +82,7 @@ module type S = sig type conf_t = BConfErr of err_t list | BConfCont of state_t (** The result of execution - + In the symbolic case, this is the result of {i one branch} of execution *) type result_t = (state_t, state_vt, err_t) Exec_res.t @@ -156,7 +156,7 @@ module type S = sig (result_t -> 'a) -> annot MP.prog -> string -> - string list -> + Var.t list -> state_t -> 'a cont_func @@ -165,7 +165,7 @@ module type S = sig (result_t -> 'a) -> annot MP.prog -> string -> - string list -> + Var.t list -> state_t -> 'a list diff --git a/GillianCore/engine/general_semantics/state.ml b/GillianCore/engine/general_semantics/state.ml index d20e9055d..943a45f53 100644 --- a/GillianCore/engine/general_semantics/state.ml +++ b/GillianCore/engine/general_semantics/state.ml @@ -84,12 +84,7 @@ module type S = sig val pp : Format.formatter -> t -> unit val pp_by_need : - Containers.SS.t -> - Containers.SS.t -> - Containers.SS.t -> - Format.formatter -> - t -> - unit + Var.Set.t -> LVar.Set.t -> Id.Sets.LocSet.t -> Format.formatter -> t -> unit val pp_err : Format.formatter -> err_t -> unit val get_recovery_tactic : t -> err_t list -> vt Recovery_tactic.t @@ -98,16 +93,18 @@ module type S = sig val copy : t -> t (** Add Spec Var *) - val add_spec_vars : t -> Var.Set.t -> t + val add_spec_vars : t -> Id.Sets.SubstSet.t -> t + + (* TODO: Is this right? Or are spec vars LVars? *) (** Get Spec Vars *) - val get_spec_vars : t -> Var.Set.t + val get_spec_vars : t -> Id.Sets.SubstSet.t (** Get all logical variables *) - val get_lvars : t -> Var.Set.t + val get_lvars : t -> LVar.Set.t (** Turns a state into a list of assertions *) - val to_assertions : ?to_keep:Containers.SS.t -> t -> Asrt.t + val to_assertions : ?to_keep:Var.Set.t -> t -> Asrt.t val evaluate_slcmd : 'a MP.prog -> SLCmd.t -> t -> (t, err_t) Res_list.t @@ -119,7 +116,7 @@ module type S = sig bool -> t -> Asrt.t -> - string list -> + Id.any_var Id.t list -> (t * t, err_t) Res_list.t val frame_on : t -> (string * t) list -> string list -> (t, err_t) Res_list.t @@ -127,9 +124,9 @@ module type S = sig val run_spec : MP.spec -> t -> - string -> + Var.t -> vt list -> - (string * (string * vt) list) option -> + (string * (LVar.t * vt) list) option -> (t * Flag.t, err_t) Res_list.t val sure_is_nonempty : t -> bool diff --git a/GillianCore/engine/general_semantics/stateErr.ml b/GillianCore/engine/general_semantics/stateErr.ml index 3e799dd43..98da6e38e 100644 --- a/GillianCore/engine/general_semantics/stateErr.ml +++ b/GillianCore/engine/general_semantics/stateErr.ml @@ -37,7 +37,7 @@ let pp_err (Fmt.option ~none:(Fmt.any "None") (Fmt.of_to_string Type.str)) t1 (Type.str t2) | EPure f -> Fmt.pf fmt "EPure(%a)" Expr.pp f - | EVar x -> Fmt.pf fmt "EVar(%s)" x + | EVar x -> Fmt.pf fmt "EVar(%a)" Id.pp x | EAsrt (vs, f, asrtss) -> let pp_asrts fmt asrts = Fmt.pf fmt "[%a]" Asrt.pp asrts in Fmt.pf fmt "EAsrt(%a; %a; %a)" diff --git a/GillianCore/engine/general_semantics/store.ml b/GillianCore/engine/general_semantics/store.ml index 35dfa02d9..272fbca87 100644 --- a/GillianCore/engine/general_semantics/store.ml +++ b/GillianCore/engine/general_semantics/store.ml @@ -58,13 +58,13 @@ module type S = sig val pp : Format.formatter -> t -> unit (** Store printer by need *) - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit + val pp_by_need : Var.Set.t -> Format.formatter -> t -> unit (** Converts the store into an ssubst *) val to_ssubst : t -> SESubst.t (** Logical variables *) - val lvars : t -> Var.Set.t + val lvars : t -> LVar.Set.t end (** Implementation of GIL Stores *) @@ -114,7 +114,8 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct let get_unsafe (store : t) (v : Var.t) : vt = match get store v with | Some result -> result - | None -> Fmt.failwith "Store.get_unsafe: variable %s not found in store" v + | None -> + Fmt.failwith "Store.get_unsafe: variable %a not found in store" Var.pp v (** Store update (in-place) @@ -225,25 +226,23 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct let pp fmt (store : t) = let sep = Fmt.any "@\n" in let pp_pair = - Fmt.(hbox (parens (pair ~sep:(any ": ") string Val.full_pp))) + Fmt.(hbox (parens (pair ~sep:(any ": ") Var.pp Val.full_pp))) in let bindings = List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) (bindings store) in (Fmt.list ~sep pp_pair) fmt bindings - let pp_by_need (pvars : Containers.SS.t) fmt (store : t) = + let pp_by_need (pvars : Var.Set.t) fmt (store : t) = let sep = Fmt.any "@\n" in let pp_pair = - Fmt.(hbox (parens (pair ~sep:(any ": ") string Val.full_pp))) + Fmt.(hbox (parens (pair ~sep:(any ": ") Var.pp Val.full_pp))) in let bindings = List.sort (fun (v, _) (w, _) -> Stdlib.compare v w) (bindings store) in (* Filter for the ones needed *) - let bindings = - List.filter (fun (v, _) -> Containers.SS.mem v pvars) bindings - in + let bindings = List.filter (fun (v, _) -> Var.Set.mem v pvars) bindings in (Fmt.list ~sep pp_pair) fmt bindings (** @@ -257,8 +256,8 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct iter store (fun x v -> SESubst.put subst (Expr.PVar x) (Val.to_expr v)); subst - let lvars (store : t) : Var.Set.t = + let lvars (store : t) : LVar.Set.t = Hashtbl.fold - (fun _ v ac -> Var.Set.union ac (Expr.lvars (Val.to_expr v))) - store Var.Set.empty + (fun _ v ac -> LVar.Set.union ac (Expr.lvars (Val.to_expr v))) + store LVar.Set.empty end diff --git a/GillianCore/engine/general_semantics/store.mli b/GillianCore/engine/general_semantics/store.mli index 53b8ff752..ca7a3c92b 100644 --- a/GillianCore/engine/general_semantics/store.mli +++ b/GillianCore/engine/general_semantics/store.mli @@ -58,13 +58,13 @@ module type S = sig val pp : Format.formatter -> t -> unit (** Store printer by need *) - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit + val pp_by_need : Var.Set.t -> Format.formatter -> t -> unit (** Converts the store into an ssubst *) val to_ssubst : t -> SVal.SESubst.t (** Logical variables *) - val lvars : t -> Var.Set.t + val lvars : t -> LVar.Set.t end module Make (Val : Val.S) : S with type vt = Val.t diff --git a/GillianCore/engine/general_semantics/subst.ml b/GillianCore/engine/general_semantics/subst.ml index e5f4f79af..9e4da8891 100644 --- a/GillianCore/engine/general_semantics/subst.ml +++ b/GillianCore/engine/general_semantics/subst.ml @@ -6,6 +6,13 @@ (** @canonical Gillian.General.Subst.S *) module type S = sig + type +'a id := 'a Id.t + + (** Type of GIL variable and abstract location names *) + type keys := Id.substable + + type kt := keys id + (** Type of GIL values *) type vt @@ -13,7 +20,7 @@ module type S = sig type t (** Substitution constructor, with a list of bindings of the form (variable, value) *) - val init : (Var.t * vt) list -> t + val init : ([< keys ] id * vt) list -> t (** Is the substitution empty? *) val is_empty : t -> bool @@ -22,43 +29,43 @@ module type S = sig val clear : t -> unit (** Domain of the substitution *) - val domain : t -> (Var.t -> bool) option -> Var.Set.t + val domain : t -> (kt -> bool) option -> Id.Sets.SubstSet.t (** Range of the substitution *) val range : t -> vt list (** Substitution lookup *) - val get : t -> Var.t -> vt option + val get : t -> kt -> vt option (** Substitution incremental update *) - val add : t -> Var.t -> vt -> unit + val add : t -> kt -> vt -> unit (** Substitution update *) - val put : t -> Var.t -> vt -> unit + val put : t -> kt -> vt -> unit (** Substitution membership *) - val mem : t -> Var.t -> bool + val mem : t -> kt -> bool (** Substitution copy *) val copy : t -> t (** Substitution extension with a list of bindings *) - val extend : t -> (Var.t * vt) list -> unit + val extend : t -> (kt * vt) list -> unit (** Substution merge into left *) val merge_left : t -> t -> unit (** Substitution filter *) - val filter : t -> (Var.t -> vt -> bool) -> t + val filter : t -> (kt -> vt -> bool) -> t (** Substitution variable filter *) - val projection : t -> Var.Set.t -> t + val projection : t -> Id.Sets.SubstSet.t -> t (** Substitution iterator *) - val iter : t -> (Var.t -> vt -> unit) -> unit + val iter : t -> (kt -> vt -> unit) -> unit (** Substitution fold *) - val fold : t -> (Var.t -> vt -> 'a -> 'a) -> 'a -> 'a + val fold : t -> (kt -> vt -> 'a -> 'a) -> 'a -> 'a (** Pretty Printer *) val pp : Format.formatter -> t -> unit @@ -66,10 +73,10 @@ module type S = sig (** Full pretty Printer *) val full_pp : Format.formatter -> t -> unit - val filter_in_place : t -> (Var.t -> vt -> vt option) -> unit + val filter_in_place : t -> (kt -> vt -> vt option) -> unit (** Convert substitution to list *) - val to_list : t -> (Var.t * vt) list + val to_list : t -> (kt * vt) list (** Substitution inside a logical expression *) val subst_in_expr : t -> partial:bool -> Expr.t -> Expr.t @@ -85,11 +92,14 @@ end module Make (Val : Val.S) : S with type vt = Val.t = struct module L = Logging + type ktv = Id.substable + type kt = ktv Id.t + (** Type of GIL values *) type vt = Val.t (** Type of GIL substitutions, implemented as hashtables *) - type t = (Var.t, vt) Hashtbl.t + type t = (kt, vt) Hashtbl.t (** Substitution constructor @@ -97,9 +107,9 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param vars_les Bindings of the form (variable, value) @return Substitution with the given bindings *) - let init (vars_les : (Var.t * vt) list) : t = + let init (vars_les : ([< ktv ] Id.t * vt) list) : t = let subst = Hashtbl.create Config.big_tbl_size in - List.iter (fun (v, v_val) -> Hashtbl.replace subst v v_val) vars_les; + List.iter (fun (v, v_val) -> Hashtbl.replace subst (v :> kt) v_val) vars_les; subst let clear (subst : t) : unit = Hashtbl.clear subst @@ -111,15 +121,16 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param filter_out Optional filtering function @return Domain of the (filtered) substitution *) - let domain (subst : t) (filter_out : (Var.t -> bool) option) : Var.Set.t = + let domain (subst : t) (filter_out : (kt -> bool) option) : Id.Sets.SubstSet.t + = let filter = match filter_out with | Some filter -> filter | None -> fun _ -> false in Hashtbl.fold - (fun k _ ac -> if filter k then ac else Var.Set.add k ac) - subst Var.Set.empty + (fun k _ ac -> if filter k then ac else Id.Sets.SubstSet.add k ac) + subst Id.Sets.SubstSet.empty (** Substitution range @@ -137,7 +148,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param x Target variable @return Resulting (optional) value *) - let get (subst : t) (x : Var.t) : vt option = Hashtbl.find_opt subst x + let get (subst : t) (x : kt) : vt option = Hashtbl.find_opt subst x (** Substitution incremental update @@ -146,7 +157,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param x Target variable @param v Target value *) - let add (subst : t) (x : Var.t) (v : vt) : unit = Hashtbl.add subst x v + let add (subst : t) (x : kt) (v : vt) : unit = Hashtbl.add subst x v (** Substitution update @@ -155,7 +166,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param x Target variable @param v Target value *) - let put (subst : t) (x : Var.t) (v : vt) : unit = Hashtbl.replace subst x v + let put (subst : t) (x : kt) (v : vt) : unit = Hashtbl.replace subst x v (** Substitution membership @@ -164,7 +175,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param x Target variable @return Returns true if the variable is in the domain of the substitution, and false otherwise *) - let mem (subst : t) (x : Var.t) : bool = Hashtbl.mem subst x + let mem (subst : t) (x : kt) : bool = Hashtbl.mem subst x (** Substitution copy @@ -180,7 +191,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param store Target substitution @param extend *) - let extend (subst : t) (vars_les : (Var.t * vt) list) : unit = + let extend (subst : t) (vars_les : (kt * vt) list) : unit = List.iter (fun (v, v_val) -> Hashtbl.replace subst v v_val) vars_les (** @@ -189,7 +200,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param subst Target substitution @param f Iterator function *) - let iter (subst : t) (f : Var.t -> vt -> unit) : unit = Hashtbl.iter f subst + let iter (subst : t) (f : kt -> vt -> unit) : unit = Hashtbl.iter f subst (** Substitution fold @@ -216,7 +227,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param filter Filtering function @return The new, filtered substitution *) - let filter (subst : t) (filter : Var.t -> vt -> bool) : t = + let filter (subst : t) (filter : kt -> vt -> bool) : t = let new_subst = copy subst in Hashtbl.filter_map_inplace (fun v v_val -> @@ -233,8 +244,8 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param vars Variables to save @return The new, filtered substitution *) - let projection (subst : t) (vars : Var.Set.t) : t = - filter subst (fun x _ -> Var.Set.mem x vars) + let projection (subst : t) (vars : Id.Sets.SubstSet.t) : t = + filter subst (fun x _ -> Id.Sets.SubstSet.mem x vars) (** Substitution pretty_printer @@ -244,7 +255,9 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @return unit *) let pp fmt (subst : t) = - let pp_pair fmt (v, v_val) = Fmt.pf fmt "@[(%s: %a)@]" v Val.pp v_val in + let pp_pair fmt (v, v_val) = + Fmt.pf fmt "@[(%a: %a)@]" Id.pp v Val.pp v_val + in Fmt.pf fmt "[ @[%a@] ]" (Fmt.hashtbl ~sep:Fmt.comma pp_pair) subst (** @@ -256,7 +269,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct *) let full_pp fmt (subst : t) = let pp_pair fmt (v, v_val) = - Fmt.pf fmt "@[(%s: %a)@]" v Val.full_pp v_val + Fmt.pf fmt "@[(%a: %a)@]" Id.pp v Val.full_pp v_val in Fmt.pf fmt "[ @[%a@] ]" (Fmt.hashtbl ~sep:Fmt.comma pp_pair) subst @@ -267,7 +280,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @param filter Filtering function @return Filtered substitution *) - let filter_in_place (subst : t) (filter : Var.t -> vt -> vt option) : unit = + let filter_in_place (subst : t) (filter : kt -> vt -> vt option) : unit = Hashtbl.filter_map_inplace filter subst (** @@ -276,7 +289,7 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @params subst Target substitution @return List of bindings of the form (variable, value) *) - let to_list (subst : t) : (Var.t * vt) list = + let to_list (subst : t) : (kt * vt) list = Hashtbl.fold (fun v v_val ac -> (v, v_val) :: ac) subst [] (** @@ -287,10 +300,8 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct @return Expression resulting from the substitution, with fresh locations created. *) let subst_in_expr (subst : t) ~(partial : bool) (le : Expr.t) : Expr.t = - let find_in_subst - (x : Var.t) - (le_x_old : Expr.t) - (make_new_x : unit -> Expr.t) : Expr.t = + let find_in_subst (x : kt) (le_x_old : Expr.t) (make_new_x : unit -> Expr.t) + : Expr.t = match get subst x with | Some v -> Val.to_expr v | None -> ( @@ -309,30 +320,33 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct val mutable self_subst = init [] method! visit_LVar () this x = - find_in_subst x this (fun () -> Expr.LVar (LVar.alloc ())) + find_in_subst (x :> kt) this (fun () -> Expr.LVar (LVar.alloc ())) method! visit_ALoc () this x = - find_in_subst x this (fun () -> Expr.ALoc (LVar.alloc ())) + find_in_subst (x :> kt) this (fun () -> Expr.ALoc (ALoc.alloc ())) method! visit_PVar () this x = - find_in_subst x this (fun () -> - let lvar = LVar.alloc () in - L.( - verbose (fun m -> - m - "General: Subst in lexpr: PVar %s not in subst, \ - generating fresh: %s" - x lvar)); - Expr.LVar lvar) + find_in_subst (x :> kt) this @@ fun () -> + let lvar = LVar.alloc () in + L.verbose (fun m -> + m + "General: Subst in lexpr: PVar %a not in subst, generating \ + fresh: %a" + Var.pp x LVar.pp lvar); + Expr.LVar lvar method! visit_Exists () this bt e = let binders = List.to_seq bt |> Seq.map fst in let binder_substs = binders |> Seq.filter_map (fun x -> - Option.map (fun x_v -> (x, x_v)) (get self_subst x)) + Option.map + (fun x_v -> ((x :> kt), x_v)) + (get self_subst (x :> kt))) in - Seq.iter (fun x -> put self_subst x (Val.from_lvar_name x)) binders; + Seq.iter + (fun x -> put self_subst (x :> kt) (Val.from_lvar_name x)) + binders; let new_expr = self#visit_expr () e in Seq.iter (fun (x, le_x) -> put self_subst x le_x) binder_substs; if new_expr == e then this else Exists (bt, new_expr) @@ -342,9 +356,13 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct let binder_substs = binders |> Seq.filter_map (fun x -> - Option.map (fun x_v -> (x, x_v)) (get self_subst x)) + Option.map + (fun x_v -> ((x :> kt), x_v)) + (get self_subst (x :> kt))) in - Seq.iter (fun x -> put self_subst x (Val.from_lvar_name x)) binders; + Seq.iter + (fun x -> put self_subst (x :> kt) (Val.from_lvar_name x)) + binders; let new_expr = self#visit_expr () e in Seq.iter (fun (x, le_x) -> put self_subst x le_x) binder_substs; if new_expr == e then this else ForAll (bt, new_expr) @@ -361,7 +379,9 @@ module Make (Val : Val.S) : S with type vt = Val.t = struct *) let subst_in_expr_opt (subst : t) (le : Expr.t) : Expr.t option = let f_before : Expr.t -> Expr.t option * bool = function - | LVar x | ALoc x | PVar x -> (Option.map Val.to_expr (get subst x), false) + | LVar x -> (Option.map Val.to_expr (get subst (x :> kt)), false) + | ALoc x -> (Option.map Val.to_expr (get subst (x :> kt)), false) + | PVar x -> (Option.map Val.to_expr (get subst (x :> kt)), false) | _ -> (Some le, true) in Expr.map_opt f_before None le diff --git a/GillianCore/engine/general_semantics/val.ml b/GillianCore/engine/general_semantics/val.ml index 3b88bf9d9..84979f265 100644 --- a/GillianCore/engine/general_semantics/val.ml +++ b/GillianCore/engine/general_semantics/val.ml @@ -37,7 +37,7 @@ module type S = sig val from_list : t list -> t (** Converts a logical variable name into a value *) - val from_lvar_name : string -> t + val from_lvar_name : LVar.t -> t (** Convert a value to a list of values, if possible *) val to_list : t -> t list option diff --git a/GillianCore/engine/symbolic_semantics/Legacy_s_memory.ml b/GillianCore/engine/symbolic_semantics/Legacy_s_memory.ml index 43b92eb98..5e97d2d53 100644 --- a/GillianCore/engine/symbolic_semantics/Legacy_s_memory.ml +++ b/GillianCore/engine/symbolic_semantics/Legacy_s_memory.ml @@ -15,7 +15,7 @@ module type S = sig type t [@@deriving yojson] type action_ret := - ( (t * vt list * Expr.t list * (string * Type.t) list) list, + ( (t * vt list * Expr.t list * (Id.any_var Id.t * Type.t) list) list, err_t list ) result @@ -46,19 +46,19 @@ module type S = sig (** Printer *) val pp : Format.formatter -> t -> unit - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit - val get_print_info : Containers.SS.t -> t -> Containers.SS.t * Containers.SS.t + val pp_by_need : Id.Sets.LocSet.t -> Format.formatter -> t -> unit + val get_print_info : Id.Sets.LocSet.t -> t -> LVar.Set.t * Id.Sets.LocSet.t val substitution_in_place : pfs:PFS.t -> gamma:Type_env.t -> st -> t -> - (t * Expr.Set.t * (string * Type.t) list) list + (t * Expr.Set.t * (Id.any_var Id.t * Type.t) list) list val clean_up : ?keep:Expr.Set.t -> t -> Expr.Set.t * Expr.Set.t - val lvars : t -> Containers.SS.t - val alocs : t -> Containers.SS.t + val lvars : t -> LVar.Set.t + val alocs : t -> ALoc.Set.t val assertions : ?to_keep:Containers.SS.t -> t -> Asrt.t val mem_constraints : t -> Expr.t list val get_recovery_tactic : t -> err_t -> vt Recovery_tactic.t @@ -100,7 +100,11 @@ module Dummy : S with type init_data = unit = struct let sure_is_nonempty _ = failwith "Please implement SMemory" end -module Modernize (Old_memory : S) = struct +module Modernize (Old_memory : S) : + SMemory.S + with type t = Old_memory.t + and type init_data = Old_memory.init_data + and type err_t = Old_memory.err_t = struct include Old_memory let execute_action action_name heap (pc : Gpc.t) args = diff --git a/GillianCore/engine/symbolic_semantics/SMemory.ml b/GillianCore/engine/symbolic_semantics/SMemory.ml index 59748e7a1..f4dae17a2 100644 --- a/GillianCore/engine/symbolic_semantics/SMemory.ml +++ b/GillianCore/engine/symbolic_semantics/SMemory.ml @@ -41,19 +41,19 @@ module type S = sig (** Printer *) val pp : Format.formatter -> t -> unit - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit - val get_print_info : Containers.SS.t -> t -> Containers.SS.t * Containers.SS.t + val pp_by_need : Id.Sets.LocSet.t -> Format.formatter -> t -> unit + val get_print_info : Id.Sets.LocSet.t -> t -> LVar.Set.t * Id.Sets.LocSet.t val substitution_in_place : pfs:PFS.t -> gamma:Type_env.t -> st -> t -> - (t * Expr.Set.t * (string * Type.t) list) list + (t * Expr.Set.t * (Id.any_var Id.t * Type.t) list) list val clean_up : ?keep:Expr.Set.t -> t -> Expr.Set.t * Expr.Set.t - val lvars : t -> Containers.SS.t - val alocs : t -> Containers.SS.t + val lvars : t -> LVar.Set.t + val alocs : t -> ALoc.Set.t val assertions : ?to_keep:Containers.SS.t -> t -> Asrt.t val mem_constraints : t -> Expr.t list val get_recovery_tactic : t -> err_t -> vt Recovery_tactic.t diff --git a/GillianCore/engine/symbolic_semantics/SState.ml b/GillianCore/engine/symbolic_semantics/SState.ml index f1bbf84b4..97ceeaa0a 100644 --- a/GillianCore/engine/symbolic_semantics/SState.ml +++ b/GillianCore/engine/symbolic_semantics/SState.ml @@ -1,5 +1,3 @@ -open Literal -open Names module L = Logging module SSubst = SVal.SESubst @@ -15,7 +13,7 @@ module type S = sig store:store_t -> pfs:PFS.t -> gamma:Type_env.t -> - spec_vars:SS.t -> + spec_vars:Id.Sets.SubstSet.t -> t val init : init_data -> t @@ -48,7 +46,7 @@ module Make (SMemory : SMemory.S) : store : store_t; pfs : PFS.t; gamma : Type_env.t; - spec_vars : SS.t; + spec_vars : Id.Sets.SubstSet.t; } [@@deriving yojson] @@ -80,7 +78,7 @@ module Make (SMemory : SMemory.S) : @\n\ @[TYPING ENVIRONMENT:@\n\ %a@]" - (Fmt.iter ~sep:Fmt.comma SS.iter Fmt.string) + (Fmt.iter ~sep:Fmt.comma Id.Sets.SubstSet.iter Id.pp) spec_vars SStore.pp store pp_heap heap PFS.pp pfs Type_env.pp gamma let sure_is_nonempty { heap; _ } = SMemory.sure_is_nonempty heap @@ -88,7 +86,8 @@ module Make (SMemory : SMemory.S) : let pp_by_need pvars cmd_lvars cmd_locs fmt state = let { heap = memory; store; pfs; gamma; spec_vars } = state in - let rec get_print_info (lvars : SS.t) (locs : SS.t) : SS.t * SS.t = + let rec get_print_info (lvars : LVar.Set.t) (locs : Id.Sets.LocSet.t) : + LVar.Set.t * Id.Sets.LocSet.t = (* let pp_str_list = Fmt.(brackets (list ~sep:comma string)) in let () = L.verbose (fun fmt -> @@ -97,49 +96,54 @@ module Make (SMemory : SMemory.S) : in *) (* Get locs from lvars... *) let pfs_locs = - SS.fold + LVar.Set.fold (fun x ac -> match Reduction.resolve_expr_to_location pfs gamma (LVar x) with - | Some loc -> SS.add loc ac + | Some loc -> Id.Sets.LocSet.add loc ac | None -> ac) - lvars SS.empty + lvars Id.Sets.LocSet.empty in (* ...and add them to the current locs *) - let new_locs = SS.union locs pfs_locs in + let new_locs = Id.Sets.LocSet.union locs pfs_locs in (* Get relevant lvars and locs from the memory... *) let mem_lvars, mem_locs = SMemory.get_print_info new_locs memory in (* ...and add them accordingly *) - let new_lvars = SS.union lvars mem_lvars in - let new_locs = SS.union new_locs mem_locs in + let new_lvars = LVar.Set.union lvars mem_lvars in + let new_locs = Id.Sets.LocSet.union new_locs mem_locs in (* Learn more from the pfs... *) let _, more_lvars, more_locs = PFS.get_relevant_info pvars new_lvars new_locs pfs in (* ...and add that accordingly *) - let new_lvars = SS.union new_lvars more_lvars in - let new_locs = SS.union new_locs more_locs in + let new_lvars = LVar.Set.union new_lvars more_lvars in + let new_locs = Id.Sets.LocSet.union new_locs more_locs in (* If nothing has been learned, stop; otherwise, retry *) - if SS.equal lvars new_lvars && SS.equal locs new_locs then (lvars, locs) + if LVar.Set.equal lvars new_lvars && Id.Sets.LocSet.equal locs new_locs + then (lvars, locs) else get_print_info new_lvars new_locs in (* Logical variables and locations from the store *) let store_lvars, store_locs = - SS.fold - (fun pvar ac -> + Var.Set.fold + (fun pvar ((lvars, locs) as ac) -> match SStore.get store pvar with | None -> ac | Some e -> - (SS.union (fst ac) (Expr.lvars e), SS.union (snd ac) (Expr.locs e))) - pvars (SS.empty, SS.empty) + ( LVar.Set.union lvars (Expr.lvars e), + Id.Sets.LocSet.union locs (Expr.locs e) )) + pvars + (LVar.Set.empty, Id.Sets.LocSet.empty) in (* LVars: commands + store *) - let lvars = SS.union cmd_lvars store_lvars in - let locs = SS.union cmd_locs store_locs in + let lvars = LVar.Set.union cmd_lvars store_lvars in + let locs = Id.Sets.LocSet.union cmd_locs store_locs in (* Locations found in the pfs *) let lvars, locs = get_print_info lvars locs in (* Filter spec vars *) - let spec_vars = SS.filter (fun x -> SS.mem x lvars) spec_vars in + let spec_vars = + Id.Sets.SubstSet.inter spec_vars @@ Id.Sets.lvar_to_subst lvars + in (* TODO: Locations for the heap *) (* TODO: Logical variables for the pfs and gamma *) @@ -161,11 +165,14 @@ module Make (SMemory : SMemory.S) : @\n\ @[TYPING ENVIRONMENT:@\n\ %a@]" - (Fmt.iter ~sep:Fmt.comma SS.iter Fmt.string) + (Fmt.iter ~sep:Fmt.comma Id.Sets.SubstSet.iter Id.pp) spec_vars (SStore.pp_by_need pvars) store pp_memory memory (PFS.pp_by_need (pvars, lvars, locs)) pfs - (Type_env.pp_by_need (List.fold_left SS.union SS.empty [ pvars; lvars ])) + (Type_env.pp_by_need + (Id.Sets.VarSet.union + (Id.Sets.pvar_to_varset pvars) + (Id.Sets.lvar_to_varset lvars))) gamma let init init_data = @@ -174,7 +181,7 @@ module Make (SMemory : SMemory.S) : store = SStore.init []; pfs = PFS.init (); gamma = Type_env.init (); - spec_vars = SS.empty; + spec_vars = Id.Sets.SubstSet.empty; } let make_s @@ -182,7 +189,7 @@ module Make (SMemory : SMemory.S) : ~(store : SStore.t) ~(pfs : PFS.t) ~(gamma : Type_env.t) - ~(spec_vars : SS.t) : t = + ~(spec_vars : Id.Sets.SubstSet.t) : t = { heap = SMemory.init init_data; store; pfs; gamma; spec_vars } let execute_action (action : string) (state : t) (args : vt list) : action_ret @@ -341,7 +348,7 @@ module Make (SMemory : SMemory.S) : FOSolver.check_satisfiability_with_model (fs @ PFS.to_list pfs) gamma let assert_a ({ pfs; gamma; _ } : t) (ps : Expr.t list) : bool = - FOSolver.check_entailment SS.empty pfs ps gamma + FOSolver.check_entailment LVar.Set.empty pfs ps gamma let equals ({ pfs; gamma; _ } : t) (le1 : vt) (le2 : vt) : bool = let result = FOSolver.is_equal ~pfs ~gamma le1 le2 in @@ -359,7 +366,13 @@ module Make (SMemory : SMemory.S) : (state : t) : st * t list = let { heap; store; pfs; gamma; spec_vars } = state in let save_spec_vars = - if save then (SS.empty, true) else (spec_vars, false) + if save then (LVar.Set.empty, true) + else ( + assert ( + Id.Sets.SubstSet.for_all + (fun x -> Names.is_lvar_name @@ Id.str x) + spec_vars); + (Id.Sets.substset_to_lvar spec_vars, false)) in L.verbose (fun m -> m @@ -375,7 +388,12 @@ module Make (SMemory : SMemory.S) : let subst = SSubst.filter subst (fun x _ -> match x with - | LVar x | PVar x | ALoc x -> not (SS.mem x spec_vars) + | LVar x -> + not (Id.Sets.SubstSet.mem (x :> Id.substable Id.t) spec_vars) + | PVar x -> + not (Id.Sets.SubstSet.mem (x :> Id.substable Id.t) spec_vars) + | ALoc x -> + not (Id.Sets.SubstSet.mem (x :> Id.substable Id.t) spec_vars) | _ -> true) in (* Sometimes, [simplify_pfs_and_gamma] leaves abstract locations on the @@ -474,25 +492,30 @@ module Make (SMemory : SMemory.S) : in result - let add_spec_vars (state : t) (xs : Var.Set.t) : t = - let spec_vars = SS.union xs state.spec_vars in + let add_spec_vars (state : t) (xs : Id.Sets.SubstSet.t) : t = + let spec_vars = Id.Sets.SubstSet.union xs state.spec_vars in { state with spec_vars } - let get_spec_vars ({ spec_vars; _ } : t) : SS.t = spec_vars + let get_spec_vars ({ spec_vars; _ } : t) : Id.Sets.SubstSet.t = spec_vars - let get_lvars (state : t) : Var.Set.t = + let get_lvars (state : t) : LVar.Set.t = let { heap; store; pfs; gamma; spec_vars } = state in SMemory.lvars heap - |> SS.union (SStore.lvars store) - |> SS.union (PFS.lvars pfs) - |> SS.union (Type_env.lvars gamma) - |> SS.union spec_vars - - let to_assertions ?(to_keep : SS.t option) (state : t) : Asrt.t = + |> LVar.Set.union (SStore.lvars store) + |> LVar.Set.union (PFS.lvars pfs) + |> LVar.Set.union (Type_env.lvars gamma) + |> LVar.Set.union + (* TODO: ???? should spec_vars be an lvar.set rather than substset ?? otherwise why is this here *) + @@ LVar.Set.of_list + @@ List.map (fun x -> LVar.of_string @@ Id.str x) + @@ Id.Sets.SubstSet.to_list spec_vars + + let to_assertions ?(to_keep : Var.Set.t option) (state : t) : Asrt.t = let { heap; store; pfs; gamma; _ } = state in let store' = Option.fold - ~some:(fun store_dom -> SStore.projection store (SS.elements store_dom)) + ~some:(fun store_dom -> + SStore.projection store (Var.Set.elements store_dom)) ~none:store to_keep in let asrts_pfs = @@ -524,24 +547,19 @@ module Make (SMemory : SMemory.S) : let frame_on _ _ _ = raise (Failure "ERROR: framing called for symbolic execution") - let run_spec - (_ : MP.spec) - (_ : t) - (_ : string) - (_ : vt list) - (_ : (string * (string * vt) list) option) = + let run_spec _ _ _ _ _ = raise (Failure "ERROR: run_spec called for non-abstract execution") let unfolding_vals (_ : t) (fs : Expr.t list) : vt list = - let map to_str to_expr = - List.map to_str fs - |> List.fold_left SS.union SS.empty - |> SS.elements |> List.map to_expr + let map_e to_set union empty elements to_expr = + List.map to_set fs |> List.fold_left union empty |> elements + |> List.map to_expr in - let lvars = map Expr.lvars (fun x -> Expr.LVar x) in - let alocs = map Expr.alocs (fun x -> Expr.ALoc x) in - let clocs = map Expr.clocs (fun x -> Expr.Lit (Loc x)) in - clocs @ alocs @ lvars + + LVar.Set.(map_e Expr.lvars union empty elements (fun x -> Expr.LVar x)) + @ ALoc.Set.(map_e Expr.alocs union empty elements (fun x -> Expr.ALoc x)) + @ Loc.Set.( + map_e Expr.clocs union empty elements (fun x -> Expr.Lit (Loc x))) let substitution_in_place ?(subst_all = false) (subst : st) (state : t) : t list = @@ -589,8 +607,8 @@ module Make (SMemory : SMemory.S) : let { heap; store; _ } = state in let keep = keep - |> SS.fold (fun x ac -> ES.add (Expr.ALoc x) ac) (SStore.alocs store) - |> SS.fold (fun x ac -> ES.add (Expr.LVar x) ac) (SStore.lvars store) + |> ALoc.Set.fold (fun x -> ES.add (Expr.ALoc x)) (SStore.alocs store) + |> LVar.Set.fold (fun x -> ES.add (Expr.LVar x)) (SStore.lvars store) in let forgettables, keep = SMemory.clean_up ~keep heap in L.verbose (fun fmt -> @@ -612,10 +630,10 @@ module Make (SMemory : SMemory.S) : match Reduction.resolve_expr_to_location pfs gamma (LVar y) with - | Some loc_name -> - if is_aloc_name loc_name then - (x, Expr.ALoc loc_name) :: ac - else ac + | Some loc_name -> ( + match Id.as_aloc loc_name with + | Some loc_name -> (x, Expr.ALoc loc_name) :: ac + | None -> ac) | _ -> ac) | _ -> ac) | _ -> ac) @@ -624,11 +642,12 @@ module Make (SMemory : SMemory.S) : List.iter (fun (x, e) -> SSubst.put subst x e) new_bindings (* Auxiliary Functions *) - let get_loc_name (loc : Expr.t) state : string option = + let get_loc_name (loc : Expr.t) state : Id.any_loc Id.t option = L.(tmi (fun m -> m "get_loc_name: %s" ((Fmt.to_to_string Expr.pp) loc))); let { pfs; gamma; _ } = state in match loc with - | Lit (Loc loc) | ALoc loc -> Some loc + | Lit (Loc loc) -> Some (loc :> Id.any_loc Id.t) + | ALoc loc -> Some (loc :> Id.any_loc Id.t) | LVar x -> Reduction.resolve_expr_to_location pfs gamma (LVar x) | _ -> L.verbose (fun m -> m "Unsupported location MAKESState: %a" Expr.pp loc); @@ -638,11 +657,8 @@ module Make (SMemory : SMemory.S) : let fresh_loc ?(loc : vt option) (state : t) : vt = match loc with | Some loc -> ( - let loc_name = get_loc_name loc state in - match loc_name with - | Some loc_name -> - if is_aloc_name loc_name then Expr.ALoc loc_name - else Expr.Lit (Loc loc_name) + match get_loc_name loc state with + | Some loc_name -> Expr.loc_from_loc_name loc_name | None -> ALoc (ALoc.alloc ())) | None -> ALoc (ALoc.alloc ()) @@ -660,20 +676,19 @@ module Make (SMemory : SMemory.S) : PFS.fold_left (fun (acc : vt Recovery_tactic.t) -> function | BinOp ((ALoc _ as loc), Equal, LVar x) - | BinOp (LVar x, Equal, (ALoc _ as loc)) -> - if Names.is_spec_var_name x then - let try_fold = - Option.map - (fun l -> if List.mem loc l then Expr.LVar x :: l else l) - acc.try_fold - in - let try_unfold = - Option.map - (fun l -> if List.mem loc l then Expr.LVar x :: l else l) - acc.try_unfold - in - { try_fold; try_unfold } - else acc + | BinOp (LVar x, Equal, (ALoc _ as loc)) + when LVar.is_spec_var_name x -> + let try_fold = + Option.map + (fun l -> if List.mem loc l then Expr.LVar x :: l else l) + acc.try_fold + in + let try_unfold = + Option.map + (fun l -> if List.mem loc l then Expr.LVar x :: l else l) + acc.try_unfold + in + { try_fold; try_unfold } | _ -> acc) memory_tactic pfs diff --git a/GillianCore/engine/symbolic_semantics/SState.mli b/GillianCore/engine/symbolic_semantics/SState.mli index bbfbc6e82..92629045c 100644 --- a/GillianCore/engine/symbolic_semantics/SState.mli +++ b/GillianCore/engine/symbolic_semantics/SState.mli @@ -10,7 +10,7 @@ module type S = sig store:store_t -> pfs:PFS.t -> gamma:Type_env.t -> - spec_vars:SS.t -> + spec_vars:Id.Sets.SubstSet.t -> t val init : init_data -> t diff --git a/GillianCore/engine/symbolic_semantics/SStore.ml b/GillianCore/engine/symbolic_semantics/SStore.ml index 5c56ddcec..e356b01f8 100644 --- a/GillianCore/engine/symbolic_semantics/SStore.ml +++ b/GillianCore/engine/symbolic_semantics/SStore.ml @@ -9,27 +9,23 @@ let substitution_in_place ?(subst_all = false) (subst : SESubst.t) (x : t) : if not (SESubst.is_empty subst) then ( (* Do not substitute spec vars for spec vars *) let store_subst = SESubst.copy subst in - SESubst.filter_in_place store_subst (fun u le -> - match (u, le) with - | LVar x, LVar _ when (not subst_all) && Names.is_spec_var_name x -> - Some (LVar x) - | _ -> Some le); + if not subst_all then + SESubst.filter_in_place store_subst (fun u le -> + match (u, le) with + | LVar x, LVar _ when LVar.is_spec_var_name x -> Some (LVar x) + | _ -> Some le); filter_map_inplace x (fun _ value -> let substed = SESubst.subst_in_expr store_subst ~partial:true value in Some (Reduction.reduce_lexpr substed))) -(** Returns the set containing all the vars occurring in --x-- *) -let vars (x : t) : SS.t = - fold x (fun x le ac -> SS.union ac (SS.add x (Expr.vars le))) SS.empty - (** Returns the set containing all the alocs occurring in --x-- *) -let alocs (x : t) : SS.t = - fold x (fun _ le ac -> SS.union ac (Expr.alocs le)) SS.empty +let alocs (x : t) : ALoc.Set.t = + fold x (fun _ le ac -> ALoc.Set.union ac (Expr.alocs le)) ALoc.Set.empty (** Returns the set containing all the alocs occurring in --x-- *) -let clocs (x : t) : SS.t = - fold x (fun _ le ac -> SS.union ac (Expr.clocs le)) SS.empty +let clocs (x : t) : Loc.Set.t = + fold x (fun _ le ac -> Loc.Set.union ac (Expr.clocs le)) Loc.Set.empty (** conversts a symbolic store to a list of assertions *) let assertions (x : t) : Expr.t list = diff --git a/GillianCore/engine/symbolic_semantics/SStore.mli b/GillianCore/engine/symbolic_semantics/SStore.mli index 089b75c4e..204b543f2 100644 --- a/GillianCore/engine/symbolic_semantics/SStore.mli +++ b/GillianCore/engine/symbolic_semantics/SStore.mli @@ -6,7 +6,7 @@ type vt = Expr.t type t [@@deriving yojson] val copy : t -> t -val domain : t -> Containers.SS.t +val domain : t -> Var.Set.t val get : t -> Var.t -> Expr.t option val get_unsafe : t -> Var.t -> Expr.t val init : (Var.t * Expr.t) list -> t @@ -16,14 +16,13 @@ val projection : t -> Var.t list -> t val put : t -> Var.t -> Expr.t -> unit val remove : t -> Var.t -> unit val pp : Format.formatter -> t -> unit -val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit +val pp_by_need : Var.Set.t -> Format.formatter -> t -> unit val iter : t -> (Var.t -> Expr.t -> unit) -> unit val fold : t -> (Var.t -> Expr.t -> 'a -> 'a) -> 'a -> 'a val filter_map_inplace : t -> (Var.t -> Expr.t -> Expr.t option) -> unit -val vars : t -> Var.Set.t -val lvars : t -> Var.Set.t -val clocs : t -> Var.Set.t -val alocs : t -> Var.Set.t +val lvars : t -> LVar.Set.t +val clocs : t -> Loc.Set.t +val alocs : t -> ALoc.Set.t val assertions : t -> Expr.t list val substitution_in_place : ?subst_all:bool -> SVal.SESubst.t -> t -> unit val is_well_formed : t -> bool diff --git a/GillianCore/gil_parser/GIL_Parser.mly b/GillianCore/gil_parser/GIL_Parser.mly index a59c1572f..df46ab958 100644 --- a/GillianCore/gil_parser/GIL_Parser.mly +++ b/GillianCore/gil_parser/GIL_Parser.mly @@ -262,9 +262,11 @@ let normalised_lvar_r = Str.regexp "##NORMALISED_LVAR" %type <(Annot.t, string) Prog.t * Yojson.Safe.t> gmain_target %type top_level_expr_target +%type just_logic_variable_target + %type g_sspec_target %type top_level_g_assertion_target -%type lab_spec_target +%type lab_spec_target %start gmain_target %start top_level_expr_target @@ -289,7 +291,7 @@ proc_name: | proc_name = STRING { proc_name } proc_head_target: - PROC; proc_name = proc_name; LBRACE; param_list = separated_list(COMMA, VAR); RBRACE + PROC; proc_name = proc_name; LBRACE; param_list = separated_list(COMMA, program_variable_target); RBRACE { (proc_name, param_list) } ; @@ -301,11 +303,11 @@ use_subst_target: ; lvar_le_pair_target: - lv = LVAR; COLON; e=expr_target { (lv, e )} + lv = just_logic_variable_target; COLON; e=expr_target { (lv, e )} ; phi_target: - v = VAR; COLON; args = separated_list(COMMA, expr_target) + v = program_variable_target; COLON; args = separated_list(COMMA, expr_target) { (v, args) } call_with_target: @@ -319,13 +321,13 @@ call_with_target: assertion_id_target: | LBRACKET; v=VAR; RBRACKET { (v, []) } - | LBRACKET; v=VAR; COLON; lvars=separated_nonempty_list(COMMA, LVAR); RBRACKET + | LBRACKET; v=VAR; COLON; lvars=separated_nonempty_list(COMMA, just_logic_variable_target); RBRACKET { (v, lvars) } ; pred_param_target: (* Program variable with in-parameter status and optional type *) - | in_param = option(FPLUS); v = VAR; t = option(preceded(COLON, type_target)) + | in_param = option(FPLUS); v = program_variable_target; t = option(preceded(COLON, type_target)) { let in_param = Option.fold ~some:(fun _ -> true) ~none:false in_param in (v, t), in_param } ; @@ -356,10 +358,10 @@ atomic_expr_target: { lvar } (* Abstract locations are *normally* computed on normalisation *) | ALOC - { Expr.ALoc $1 } + { Expr.ALoc (ALoc.of_string $1) } (* Program variable (including the special variable "ret") *) | pvar = program_variable_target - { pvar } + { Expr.PVar pvar } (* {{ e, ..., e }} *) | LSTOPEN; exprlist = separated_nonempty_list(COMMA, expr_target); LSTCLOSE { Expr.EList exprlist } @@ -535,12 +537,12 @@ top_level_expr_target: ; var_and_le_target: - | LBRACE; lvar = LVAR; DEFEQ; le = expr_target; RBRACE; + | LBRACE; lvar = just_logic_variable_target; DEFEQ; le = expr_target; RBRACE; { (lvar, le) } ; var_and_var_target: - | LBRACE; lvar1 = LVAR; DEFEQ; lvar2 = LVAR; RBRACE; + | LBRACE; lvar1 = just_logic_variable_target; DEFEQ; lvar2 = just_logic_variable_target; RBRACE; { (lvar1, lvar2) } ; @@ -680,10 +682,10 @@ gcmd_target: (* skip *) | SKIP { Cmd.Skip } (* x := [laction](e1, ..., en) *) - | v=VAR; DEFEQ; LBRACKET; laction=VAR; RBRACKET; LBRACE; es=separated_list(COMMA, expr_target); RBRACE + | v=program_variable_target; DEFEQ; LBRACKET; laction=VAR; RBRACKET; LBRACE; es=separated_list(COMMA, expr_target); RBRACE { Cmd.LAction(v, laction, es) } (* x := e *) - | v=VAR; DEFEQ; e=expr_target + | v=program_variable_target; DEFEQ; e=expr_target { Cmd.Assignment (v, e) } (* goto i *) | GOTO; i=VAR @@ -692,22 +694,22 @@ gcmd_target: | GOTO LBRACKET; e=expr_target; RBRACKET; i=VAR; j=VAR { Cmd.GuardedGoto (e, i, j) } (* x := e(e1, ..., en) with j use_subst [bla - #x: bla, #y: ble] *) - | v=VAR; DEFEQ; e=expr_target; + | v=program_variable_target; DEFEQ; e=expr_target; LBRACE; es=separated_list(COMMA, expr_target); RBRACE; oi = option(call_with_target); subst = option(use_subst_target) { Cmd.Call (v, e, es, oi, subst) } (* x := e(e1, ..., en) with j *) - | v=VAR; DEFEQ; EXTERN; pname=VAR; + | v=program_variable_target; DEFEQ; EXTERN; pname=program_variable_target; LBRACE; es=separated_list(COMMA, expr_target); RBRACE; oi = option(call_with_target) { Cmd.ECall (v, PVar pname, es, oi) } (* x := apply (e1, ..., en) with j *) - | v=VAR; DEFEQ; APPLY; + | v=program_variable_target; DEFEQ; APPLY; LBRACE; es=expr_target; RBRACE; oi = option(call_with_target) { Cmd.Apply (v, es, oi) } (* x := args *) - | v = VAR; DEFEQ; ARGUMENTS + | v = program_variable_target; DEFEQ; ARGUMENTS { Cmd.Arguments v } (* x := PHI(e1, e2, ... en); *) | PHI; LBRACE; phi_args =separated_list(SCOLON, phi_target); RBRACE @@ -908,7 +910,7 @@ g_logic_cmd_target: (* x := e *) - | v=VAR; DEFEQ; FRESH_SVAR; LBRACE; RBRACE + | v=program_variable_target; DEFEQ; FRESH_SVAR; LBRACE; RBRACE { LCmd.FreshSVar (v) } (* branch (fo) *) @@ -986,7 +988,7 @@ variant_target: lemma_head_target: - lemma_name = proc_name; LBRACE; lemma_params = separated_list(COMMA, VAR); RBRACE + lemma_name = proc_name; LBRACE; lemma_params = separated_list(COMMA, program_variable_target); RBRACE { (lemma_name, lemma_params) } @@ -1063,21 +1065,21 @@ macro_head_target: (* *) lab_spec_target: - | FLT; sspec_name = VAR; COLON; lvars = separated_list (COMMA, LVAR); FGT + | FLT; sspec_name = VAR; COLON; lvars = separated_list (COMMA, just_logic_variable_target); FGT { (sspec_name, lvars) } | FLT; sspec_name = VAR; FGT { (sspec_name, []) } ; spec_head_target: - spec_name = proc_name; LBRACE; spec_params = separated_list(COMMA, VAR); RBRACE + spec_name = proc_name; LBRACE; spec_params = separated_list(COMMA, program_variable_target); RBRACE { (* enter_specs spec_params; *) (spec_name, spec_params) } ; macro_head_def_target: - | name = VAR; LBRACE; params = separated_list(COMMA, VAR); RBRACE + | name = VAR; LBRACE; params = separated_list(COMMA, program_variable_target); RBRACE { (name, params) } ; @@ -1094,8 +1096,8 @@ unfold_info_target: ; lvar_or_pvar: - | LVAR { $1 } - | VAR { $1 } + | just_logic_variable_target { ($1 :> [ `LVar | `Var ] Id.t) } + | program_variable_target { ($1 :> [ `LVar | `Var ] Id.t) } binders_target: | LBRACKET; BIND; COLON; xs = separated_list(COMMA, lvar_or_pvar); RBRACKET @@ -1103,7 +1105,7 @@ binders_target: ; existentials_target: - | LBRACKET; EXISTENTIALS; COLON; xs = separated_list(COMMA, LVAR); RBRACKET + | LBRACKET; EXISTENTIALS; COLON; xs = separated_list(COMMA, just_logic_variable_target); RBRACKET { xs } ; @@ -1126,16 +1128,16 @@ logic_variable_target: { let v_imported = Str.replace_first normalised_lvar_r "_lvar_n" v in (* Prefixed with _n_ to avoid clashes *) - Expr.LVar v_imported } + Expr.LVar (LVar.of_string v_imported) } ; just_logic_variable_target: v = LVAR - { (* validate_lvar v; *) v } + { (* validate_lvar v; *) LVar.of_string v } program_variable_target: | v = VAR - { (* let _ = validate_pvar v in *) Expr.PVar v } + { (* let _ = validate_pvar v in *) Var.of_string v } ; (********* COMMON *********) @@ -1152,7 +1154,7 @@ lit_target: | NAN { Literal.Num nan } | INFINITY { Literal.Num infinity } | STRING { Literal.String $1 } - | LOC { Literal.Loc $1 } + | LOC { Literal.Loc (Loc.of_string $1) } | type_target { Literal.Type $1 } | LSTNIL { Literal.LList [] } | LSTOPEN LSTCLOSE { Literal.LList [] } diff --git a/GillianCore/monadic/FOSolver.ml b/GillianCore/monadic/FOSolver.ml index 97a8e621b..a35f8c74e 100644 --- a/GillianCore/monadic/FOSolver.ml +++ b/GillianCore/monadic/FOSolver.ml @@ -1,9 +1,5 @@ -module FOSolver = Engine.FOSolver -module PFS = Engine.PFS -module Type_env = Engine.Type_env -module Reduction = Engine.Reduction -module Expr = Gil_syntax.Expr -module Typing = Engine.Typing +open Engine +open Gil_syntax (** FIXME: optimization? *) let build_full_pfs (pc : Pc.t) = @@ -32,20 +28,18 @@ let sat ~(pc : Pc.t) formula = let check_entailment ~(pc : Pc.t) formula = let pfs, gamma = (build_full_pfs pc, build_full_gamma pc) in try - let f = - Engine.Reduction.reduce_lexpr ~matching:pc.matching ~gamma ~pfs formula - in + let f = Reduction.reduce_lexpr ~matching:pc.matching ~gamma ~pfs formula in match f with | Lit (Bool b) -> b | _ -> - FOSolver.check_entailment ~matching:pc.matching - Utils.Containers.SS.empty pfs [ f ] gamma - with Engine.Reduction.ReductionException (e, msg) -> + FOSolver.check_entailment ~matching:pc.matching LVar.Set.empty pfs [ f ] + gamma + with Reduction.ReductionException (e, msg) -> Logging.verbose (fun m -> m "check_entailment: couldn't check due to an error reducing %a - %s\n\ Formula:%a" - Gil_syntax.Expr.pp e msg Expr.pp formula); + Expr.pp e msg Expr.pp formula); false let of_comp_fun comp ~(pc : Pc.t) e1 e2 = diff --git a/GillianCore/monadic/MonadicSMemory.ml b/GillianCore/monadic/MonadicSMemory.ml index df4fdb969..77fad0cdc 100644 --- a/GillianCore/monadic/MonadicSMemory.ml +++ b/GillianCore/monadic/MonadicSMemory.ml @@ -40,8 +40,8 @@ module type S = sig val substitution_in_place : st -> t -> t Delayed.t val clean_up : ?keep:Expr.Set.t -> t -> Expr.Set.t * Expr.Set.t - val lvars : t -> Containers.SS.t - val alocs : t -> Containers.SS.t + val lvars : t -> LVar.Set.t + val alocs : t -> ALoc.Set.t val assertions : ?to_keep:Containers.SS.t -> t -> Asrt.t val mem_constraints : t -> Expr.t list val get_recovery_tactic : t -> err_t -> vt Recovery_tactic.t @@ -49,8 +49,8 @@ module type S = sig val get_failing_constraint : err_t -> Expr.t val get_fixes : err_t -> Asrt.t list val can_fix : err_t -> bool - val pp_by_need : Containers.SS.t -> Format.formatter -> t -> unit - val get_print_info : Containers.SS.t -> t -> Containers.SS.t * Containers.SS.t + val pp_by_need : Id.Sets.LocSet.t -> Format.formatter -> t -> unit + val get_print_info : Id.Sets.LocSet.t -> t -> LVar.Set.t * Id.Sets.LocSet.t val sure_is_nonempty : t -> bool (** See {!val:SMemory.S.split_further} *) @@ -94,7 +94,7 @@ module Lift (MSM : S) : Gbranch.{ pc = gpc; value } let substitution_in_place ~pfs ~gamma subst mem : - (t * Expr.Set.t * (string * Type.t) list) list = + (t * Expr.Set.t * (Id.any_var Id.t * Type.t) list) list = let process = substitution_in_place subst mem in let curr_pc = Pc.make ~matching:false ~pfs ~gamma () in match Delayed.resolve ~curr_pc process with diff --git a/GillianCore/monadic/branch.mli b/GillianCore/monadic/branch.mli index 11b106b53..d77d3a744 100644 --- a/GillianCore/monadic/branch.mli +++ b/GillianCore/monadic/branch.mli @@ -1,8 +1,10 @@ +open Gil_syntax + type 'a t = { pc : Pc.t; value : 'a } val make : pc:Pc.t -> value:'a -> 'a t val value : 'a t -> 'a val pc : 'a t -> Pc.t -val learned : 'a t -> Gil_syntax.Expr.Set.t -val learned_types : 'a t -> (string * Gil_syntax.Type.t) list +val learned : 'a t -> Expr.Set.t +val learned_types : 'a t -> (Id.any_var Id.t * Type.t) list val pp : 'a Fmt.t -> 'a t Fmt.t diff --git a/GillianCore/monadic/delayed.ml b/GillianCore/monadic/delayed.ml index deae9e9a4..c5b8cff44 100644 --- a/GillianCore/monadic/delayed.ml +++ b/GillianCore/monadic/delayed.ml @@ -1,5 +1,4 @@ -module Expr = Gil_syntax.Expr -module Type = Gil_syntax.Type +open Gil_syntax exception NonExhaustiveEntailment of Expr.t list @@ -19,7 +18,12 @@ let resolve ~curr_pc p = p ~curr_pc (** When using Branching, it should be certain that the paths are complete *) let return ?(learned = []) ?(learned_types = []) final_value ~curr_pc = - let new_pc = Pc.extend (Pc.extend_types curr_pc learned_types) learned in + let new_pc = + Pc.extend + (Pc.extend_types curr_pc + (learned_types :> (Id.any_var Id.t * Type.t) list)) + learned + in [ Branch.make ~pc:new_pc ~value:final_value ] let vanish () ~curr_pc = [] diff --git a/GillianCore/monadic/delayed.mli b/GillianCore/monadic/delayed.mli index dc0413bf4..e6960af07 100644 --- a/GillianCore/monadic/delayed.mli +++ b/GillianCore/monadic/delayed.mli @@ -5,9 +5,12 @@ type 'a t val resolve : curr_pc:Pc.t -> 'a t -> 'a Branch.t list val return : - ?learned:Expr.t list -> ?learned_types:(string * Type.t) list -> 'a -> 'a t + ?learned:Expr.t list -> + ?learned_types:([< Id.any_var ] Id.t * Type.t) list -> + 'a -> + 'a t -val resolve_loc : Expr.t -> string option t +val resolve_loc : Expr.t -> Id.any_loc Id.t option t val reduce : Expr.t -> Expr.t t val entails : Expr.t list -> Expr.t -> bool t val check_sat : Expr.t -> bool t diff --git a/GillianCore/monadic/pc.ml b/GillianCore/monadic/pc.ml index d4172947a..1152e860a 100644 --- a/GillianCore/monadic/pc.ml +++ b/GillianCore/monadic/pc.ml @@ -7,7 +7,7 @@ type t = { pfs : Pure_context.t; gamma : Type_env.t; learned : Expr.Set.t; - learned_types : (string * Type.t) list; + learned_types : (Id.any_var Id.t * Type.t) list; matching : bool; } @@ -29,9 +29,9 @@ let init ?(matching = false) () = let empty = init () let pfs_to_pfs_and_gamma pfs = - let expr_type_binding_to_gamma etb = - match etb with - | Expr.PVar s, t | Expr.LVar s, t -> Some (s, t) + let expr_type_binding_to_gamma = function + | Expr.PVar s, t -> Some ((s :> Id.any_var Id.t), t) + | LVar s, t -> Some ((s :> Id.any_var Id.t), t) | _ -> None in let rec aux = function @@ -82,7 +82,7 @@ let equal pca pcb = pca.pfs = pcb.pfs && pca.gamma = pcb.gamma && Expr.Set.equal pca.learned pcb.learned && List.for_all2 - (fun (n1, t1) (n2, t2) -> String.equal n1 n2 && Type.equal t1 t2) + (fun (n1, t1) (n2, t2) -> Id.equal n1 n2 && Type.equal t1 t2) pca.learned_types pcb.learned_types let pp = @@ -99,8 +99,7 @@ let pp = (Fmt.Dump.seq Expr.pp); Fmt.field "learned_types" (fun x -> x.learned_types) - (Fmt.Dump.list - (Fmt.Dump.pair Fmt.string (Fmt.of_to_string Type.str))); + (Fmt.Dump.list (Fmt.Dump.pair Id.pp (Fmt.of_to_string Type.str))); ]) let diff pca pcb = diff --git a/GillianCore/smt/smt.ml b/GillianCore/smt/smt.ml index eb38bbd20..d8f91ba26 100644 --- a/GillianCore/smt/smt.ml +++ b/GillianCore/smt/smt.ml @@ -33,9 +33,10 @@ let is_true = function | Sexplib.Sexp.Atom "true" -> true | _ -> false -type typenv = (string, Type.t) Hashtbl.t +type typenv = (Id.any_var Id.t, Type.t) Hashtbl.t -let pp_typenv = Fmt.(Dump.hashtbl string (Fmt.of_to_string Type.str)) +let pp_typenv : typenv Fmt.t = + Fmt.(Dump.hashtbl Id.pp (Fmt.of_to_string Type.str)) let encoding_cache : (Expr.Set.t, sexp list) Hashtbl.t = Hashtbl.create Config.big_tbl_size @@ -53,19 +54,17 @@ let quant q (vars : (sexp * sexp) list) (s : sexp) : sexp = let forall' = quant "forall" -let forall (vars : (string * sexp) list) (s : sexp) : sexp = - let vars = - vars |> List.map (fun (v, t) -> (atom (sanitize_identifier v), t)) - in - forall' vars s +let forall (vars : (LVar.t * sexp) list) : sexp -> sexp = + vars + |> List.map (fun (v, t) -> (atom @@ sanitize_identifier @@ LVar.str v, t)) + |> forall' let exists' = quant "exists" -let exists (vars : (string * sexp) list) (s : sexp) : sexp = - let vars = - vars |> List.map (fun (v, t) -> (atom (sanitize_identifier v), t)) - in - exists' vars s +let exists (vars : (LVar.t * sexp) list) : sexp -> sexp = + vars + |> List.map (fun (v, t) -> (atom @@ sanitize_identifier @@ LVar.str v, t)) + |> exists' let t_seq t = list [ atom "Seq"; t ] let seq_len s = atom "seq.len" <| s @@ -508,7 +507,7 @@ let rec encode_lit (lit : Literal.t) : Encoding.t = | Int i -> int_zk i >- IntType | Num n -> real_k (Q.of_float n) >- NumberType | String s -> encode_string s >- StringType - | Loc l -> encode_string l >- ObjectType + | Loc l -> encode_string (Loc.str l) >- ObjectType | Type t -> encode_type t >- TypeType | LList lits -> let args = List.map (fun lit -> simple_wrap (encode_lit lit)) lits in @@ -619,7 +618,7 @@ let encode_unop ~llen_lvars ~e (op : UnOp.t) le = (* If we only use an LVar as an argument to llen, then encode it as an uninterpreted function. *) let enc = match e with - | Expr.LVar l when SS.mem l llen_lvars -> llen <| get_list le + | Expr.LVar l when LVar.Set.mem l llen_lvars -> llen <| get_list le | _ -> seq_len (get_list le) in enc >- IntType @@ -667,8 +666,8 @@ let encode_unop ~llen_lvars ~e (op : UnOp.t) le = let encode_quantified_expr ~(encode_expr : gamma:typenv -> - llen_lvars:SS.t -> - list_elem_vars:SS.t -> + llen_lvars:LVar.Set.t -> + list_elem_vars:LVar.Set.t -> 'a -> Encoding.t) ~mk_quant @@ -692,8 +691,8 @@ let encode_quantified_expr quantified_vars |> List.iter (fun (x, typ) -> match typ with - | None -> Hashtbl.remove gamma x - | Some typ -> Hashtbl.replace gamma x typ) + | None -> Hashtbl.remove gamma (x :> Id.any_var Id.t) + | Some typ -> Hashtbl.replace gamma (x :> Id.any_var Id.t) typ) in (* Not the same gamma now!*) let encoded_assertion, consts, extra_asrts = @@ -716,15 +715,17 @@ let encode_quantified_expr let () = consts |> Hashtbl.filter_map_inplace (fun c () -> - if List.mem c quantified_vars then None else Some ()) + if List.exists (fun (var, t) -> (Id.str var, t) = c) quantified_vars + then None + else Some ()) in let expr = mk_quant quantified_vars encoded_assertion in native ~consts ~extra_asrts BooleanType expr let rec encode_logical_expression ~(gamma : typenv) - ~(llen_lvars : SS.t) - ~(list_elem_vars : SS.t) + ~(llen_lvars : LVar.Set.t) + ~(list_elem_vars : LVar.Set.t) (le : Expr.t) : Encoding.t = let open Encoding in let f = encode_logical_expression ~gamma ~llen_lvars ~list_elem_vars in @@ -733,14 +734,15 @@ let rec encode_logical_expression | Lit lit -> encode_lit lit | LVar var -> let kind, typ = - match Hashtbl.find_opt gamma var with + match Hashtbl.find_opt gamma (var :> Id.any_var Id.t) with | Some typ -> (Native typ, native_sort_of_type typ) | None -> - if SS.mem var list_elem_vars then (Simple_wrapped, t_gil_literal) + if LVar.Set.mem var list_elem_vars then + (Simple_wrapped, t_gil_literal) else (Extended_wrapped, t_gil_ext_literal) in - make_const ~typ kind var - | ALoc var -> native_const ObjectType var + make_const ~typ kind @@ LVar.str var + | ALoc var -> native_const ObjectType @@ ALoc.str var | PVar _ -> failwith "HORROR: Program variable in pure formula" | UnOp (op, le) -> encode_unop ~llen_lvars ~e:le op (f le) | BinOp (le1, op, le2) -> encode_binop op (f le1) (f le2) @@ -776,8 +778,8 @@ let rec encode_logical_expression let encode_assertion_top_level ~(gamma : typenv) - ~(llen_lvars : SS.t) - ~(list_elem_vars : SS.t) + ~(llen_lvars : LVar.Set.t) + ~(list_elem_vars : LVar.Set.t) (a : Expr.t) : Encoding.t = try encode_logical_expression ~gamma ~llen_lvars ~list_elem_vars @@ -791,39 +793,40 @@ let encode_assertion_top_level let () = L.print_to_all msg in raise e -let lvars_only_in_llen (fs : Expr.Set.t) : SS.t = +let lvars_only_in_llen (fs : Expr.Set.t) : LVar.Set.t = let inspector = object inherit [_] Visitors.iter as super - val mutable llen_vars = SS.empty - val mutable other_vars = SS.empty - method get_diff = SS.diff llen_vars other_vars + val mutable llen_vars = LVar.Set.empty + val mutable other_vars = LVar.Set.empty + method get_diff = LVar.Set.diff llen_vars other_vars method! visit_expr () e = match e with - | UnOp (UnOp.LstLen, Expr.LVar l) -> llen_vars <- SS.add l llen_vars - | LVar l -> other_vars <- SS.add l other_vars + | UnOp (LstLen, LVar l) -> llen_vars <- LVar.Set.add l llen_vars + | LVar l -> other_vars <- LVar.Set.add l other_vars | _ -> super#visit_expr () e end in fs |> Expr.Set.iter (inspector#visit_expr ()); inspector#get_diff -let lvars_as_list_elements (assertions : Expr.Set.t) : SS.t = +let lvars_as_list_elements (assertions : Expr.Set.t) : LVar.Set.t = let collector = object (self) inherit [_] Visitors.reduce - inherit Visitors.Utils.ss_monoid + method private zero = LVar.Set.empty + method private plus = LVar.Set.union method! visit_ForAll (exclude, is_in_list) binders f = (* Quantified variables need to be excluded *) let univ_quant = List.to_seq binders |> Seq.map fst in - let exclude = Containers.SS.add_seq univ_quant exclude in + let exclude = LVar.Set.add_seq univ_quant exclude in self#visit_expr (exclude, is_in_list) f method! visit_Exists (exclude, is_in_list) binders e = let exist_quants = List.to_seq binders |> Seq.map fst in - let exclude = Containers.SS.add_seq exist_quants exclude in + let exclude = LVar.Set.add_seq exist_quants exclude in self#visit_expr (exclude, is_in_list) e method! visit_EList (exclude, _) es = @@ -831,18 +834,15 @@ let lvars_as_list_elements (assertions : Expr.Set.t) : SS.t = (fun acc e -> match e with | Expr.LVar x -> - if not (Containers.SS.mem x exclude) then - Containers.SS.add x acc - else acc + if not (LVar.Set.mem x exclude) then LVar.Set.add x acc else acc | _ -> let inner = self#visit_expr (exclude, true) e in - Containers.SS.union acc inner) - Containers.SS.empty es + LVar.Set.union acc inner) + LVar.Set.empty es method! visit_LVar (exclude, is_in_list) x = - if is_in_list && not (Containers.SS.mem x exclude) then - Containers.SS.singleton x - else Containers.SS.empty + if is_in_list && not (LVar.Set.mem x exclude) then LVar.Set.singleton x + else LVar.Set.empty method! visit_'label _ (_ : int) = self#zero method! visit_'annot _ () = self#zero @@ -850,9 +850,9 @@ let lvars_as_list_elements (assertions : Expr.Set.t) : SS.t = in Expr.Set.fold (fun f acc -> - let new_lvars = collector#visit_expr (SS.empty, false) f in - SS.union new_lvars acc) - assertions SS.empty + let new_lvars = collector#visit_expr (LVar.Set.empty, false) f in + LVar.Set.union new_lvars acc) + assertions LVar.Set.empty let encode_assertions (fs : Expr.Set.t) (gamma : typenv) : sexp list = let open Encoding in @@ -1008,14 +1008,14 @@ let is_sat (fs : Expr.Set.t) (gamma : typenv) : bool = let lift_model (model : sexp) (gamma : typenv) - (subst_update : string -> Expr.t -> unit) - (target_vars : Expr.Set.t) : unit = + (subst_update : LVar.t -> Expr.t -> unit) + (target_vars : LVar.Set.t) : unit = let () = reset_solver () in let model_eval = (model_eval' solver model).eval [] in let get_val x = try - let x = x |> sanitize_identifier |> atom in + let x = x |> Id.str |> sanitize_identifier |> atom in model_eval x |> Option.some with UnexpectedSolverResponse _ -> None in @@ -1028,8 +1028,8 @@ let lift_model try Some (to_z n) with UnexpectedSolverResponse _ -> None in - let lift_val (x : string) : Literal.t option = - let* gil_type = Hashtbl.find_opt gamma x in + let lift_val (x : [< Id.any_var ] Id.t) : Literal.t option = + let* gil_type = Hashtbl.find_opt gamma (x :> Id.any_var Id.t) in let* v = get_val x in match gil_type with | NumberType -> @@ -1047,24 +1047,13 @@ let lift_model let () = L.verbose (fun m -> m "Inside lift_model") in target_vars - |> Expr.Set.iter (fun x -> - let x = - match x with - | LVar x -> x - | _ -> - failwith "INTERNAL ERROR: SMT lifting of a non-logical variable" - in + |> LVar.Set.iter (fun x -> let v = lift_val x in - let () = - L.verbose (fun m -> - let binding = - v - |> Option.fold - ~some:(Fmt.to_to_string Literal.pp) - ~none:"NO BINDING!" - in - m "SMT binding for %s: %s\n" x binding) - in + L.verbose (fun m -> + let binding_pp = + Fmt.option ~none:(Fmt.any "NO BINDING!") Literal.pp + in + m "SMT binding for %a: %a\n" Id.pp x binding_pp v); v |> Option.iter (fun v -> subst_update x (Expr.Lit v))) let () = diff --git a/GillianCore/smt/smt.mli b/GillianCore/smt/smt.mli index 18cebadeb..c28866b2f 100644 --- a/GillianCore/smt/smt.mli +++ b/GillianCore/smt/smt.mli @@ -2,17 +2,13 @@ open Gil_syntax exception SMT_unknown -val exec_sat : Expr.Set.t -> (string, Type.t) Hashtbl.t -> Sexplib.Sexp.t option -val is_sat : Expr.Set.t -> (string, Type.t) Hashtbl.t -> bool +type typenv := (Id.any_var Id.t, Type.t) Hashtbl.t -val check_sat : - Expr.Set.t -> (string, Type.t) Hashtbl.t -> Sexplib.Sexp.t option +val exec_sat : Expr.Set.t -> typenv -> Sexplib.Sexp.t option +val is_sat : Expr.Set.t -> typenv -> bool +val check_sat : Expr.Set.t -> typenv -> Sexplib.Sexp.t option val lift_model : - Sexplib.Sexp.t -> - (string, Type.t) Hashtbl.t -> - (string -> Expr.t -> unit) -> - Expr.Set.t -> - unit + Sexplib.Sexp.t -> typenv -> (LVar.t -> Expr.t -> unit) -> LVar.Set.t -> unit val pp_sexp : Sexplib.Sexp.t Fmt.t diff --git a/GillianCore/utils/allocators.ml b/GillianCore/utils/allocators.ml index 29a99607b..e5363b541 100644 --- a/GillianCore/utils/allocators.ml +++ b/GillianCore/utils/allocators.ml @@ -7,7 +7,7 @@ let reset_all () = List.iter (fun f -> f ()) !resetters module Basic () = struct open Containers - type t = int [@@deriving yojson, eq, ord] + type t = int [@@deriving yojson, eq, ord, show] let counter = ref 0 let freed = ref SI.empty @@ -26,17 +26,17 @@ module Basic () = struct let () = register_resetter reset let of_string = int_of_string - let to_string = string_of_int + let str = string_of_int end module Make_with_prefix (A : S_with_stringify) (P : sig val prefix : string - end) : S with type t = string = struct - type t = string [@@deriving yojson, eq, ord] + end) : S_with_stringify with type t = string = struct + type t = string [@@deriving yojson, eq, ord, show] - let construct x = P.prefix ^ A.to_string x + let construct x = P.prefix ^ A.str x let deconstruct str = let lp = String.length P.prefix in @@ -52,4 +52,6 @@ module Make_with_prefix let dealloc s = A.dealloc (deconstruct s) let eq = String.equal let reset = A.reset + let str s : string = s + let of_string s = s end diff --git a/GillianCore/utils/allocators_intf.ml b/GillianCore/utils/allocators_intf.ml index 2dd166b66..09f25a3fe 100644 --- a/GillianCore/utils/allocators_intf.ml +++ b/GillianCore/utils/allocators_intf.ml @@ -1,16 +1,16 @@ module type S = sig - type t [@@deriving yojson, eq, ord] + type t [@@deriving yojson, eq, ord, show] val alloc : unit -> t val dealloc : t -> unit val eq : t -> t -> bool val reset : unit -> unit + val str : t -> string end module type S_with_stringify = sig include S - val to_string : t -> string val of_string : string -> t end @@ -34,20 +34,20 @@ module type Intf = sig end (** @canonical Gillian.Utils.Allocators.Basic - + A basic int allocator - + Automatically registers a resetter *) module Basic () : S_with_stringify with type t = int (** @canonical Gillian.Utils.Allocators.Make_with_prefix - + Wraps an allocator [A] with a string prefix - + Assumes that [A]'s resetter has already been registered *) module Make_with_prefix (A : S_with_stringify) (P : sig val prefix : string - end) : S with type t = string + end) : S_with_stringify with type t = string end diff --git a/GillianCore/utils/names.ml b/GillianCore/utils/names.ml index c59f0431e..dd989e327 100644 --- a/GillianCore/utils/names.ml +++ b/GillianCore/utils/names.ml @@ -35,11 +35,10 @@ let is_aloc_name (name : string) : bool = try String.sub name 0 4 = aloc_prefix with _ -> false let is_lvar_name (name : string) : bool = - try String.sub name 0 1 = "#" || String.sub name 0 6 = lvar_prefix - with _ -> false + try name.[0] = '#' || String.sub name 0 6 = lvar_prefix with _ -> false let is_spec_var_name (name : string) : bool = - try String.sub name 0 1 = "#" with _ -> false + try name.[0] = '#' with _ -> false let is_lloc_name (name : string) : bool = try String.sub name 0 2 = lloc_prefix with _ -> false diff --git a/ppx_sat/test/test.ml b/ppx_sat/test/test.ml index cfcc375cc..9eedba504 100644 --- a/ppx_sat/test/test.ml +++ b/ppx_sat/test/test.ml @@ -43,7 +43,7 @@ module Test_if_sat = struct ~gamma:(Engine.Type_env.init ()) ~matching:false () let results = - let x = Expr.LVar "x" in + let x = Expr.LVar (LVar.of_string "x") in let curr_pc = starting_pc x in resolve ~curr_pc (process x) @@ -67,12 +67,12 @@ module Test_match_ent = struct ~gamma:(Engine.Type_env.init ()) ~matching:false () let results_no_info = - let x = Expr.LVar "x" in + let x = Expr.LVar (LVar.of_string "x") in let curr_pc = pc_with_no_info in resolve ~curr_pc (process x) let results_two = - let x = Expr.LVar "x" in + let x = Expr.LVar (LVar.of_string "x") in let curr_pc = pc_with_two x in resolve ~curr_pc (process x) @@ -103,7 +103,7 @@ module Test_match_sat = struct ~gamma:(Engine.Type_env.init ()) ~matching:false () let results = - let x = Expr.LVar "x" in + let x = Expr.LVar (LVar.of_string "x") in let curr_pc = starting_pc x in resolve ~curr_pc (process x) diff --git a/transformers/lib/prebuilt/JSIL.ml b/transformers/lib/prebuilt/JSIL.ml index 6303e49a7..b86e813f8 100644 --- a/transformers/lib/prebuilt/JSIL.ml +++ b/transformers/lib/prebuilt/JSIL.ml @@ -230,10 +230,12 @@ module PatchedALocPMap (S : MyMonadicSMemory) = struct let pp ft (h : t) = let open Fmt in let sorted_locs_with_vals = - States.MyUtils.SMap.bindings h - |> List.sort (fun (k1, _) (k2, _) -> String.compare k1 k2) + States.MyUtils.LMap.bindings h + |> List.sort (fun (k1, _) (k2, _) -> Id.compare k1 k2) + in + let pp_one ft (loc, fv_pairs) = + pf ft "@[%a |-> %a@]" Id.pp loc S.pp fv_pairs in - let pp_one ft (loc, fv_pairs) = pf ft "@[%s |-> %a@]" loc S.pp fv_pairs in (list ~sep:(any "@\n") pp_one) ft sorted_locs_with_vals end @@ -246,8 +248,6 @@ module PatchAlloc (Map : OpenPMapType with type entry = Obj.t) = struct include Map - module SS = Gillian.Utils.Containers.SS - module SMap = States.MyUtils.SMap (* Patch the alloc action *) let execute_action a s args = @@ -256,7 +256,8 @@ struct | "alloc", [ idx; v ] -> let* idx = match idx with - | Expr.Lit Empty -> Delayed.return (Some (ALoc.alloc ())) + | Expr.Lit Empty -> + Delayed.return (Some (ALoc.alloc () :> Id.any_loc Id.t)) | _ -> States.MyUtils.get_loc idx in let idx = diff --git a/transformers/lib/prebuilt/c_states/BlockTree.ml b/transformers/lib/prebuilt/c_states/BlockTree.ml index 230b23cdc..fc07a94ef 100644 --- a/transformers/lib/prebuilt/c_states/BlockTree.ml +++ b/transformers/lib/prebuilt/c_states/BlockTree.ml @@ -91,8 +91,8 @@ module Range = struct l < x && x < h let split_at (l, h) x = ((l, x), (x, h)) - let lvars (a, b) = SS.union (Expr.lvars a) (Expr.lvars b) - let alocs (a, b) = SS.union (Expr.alocs a) (Expr.alocs b) + let lvars (a, b) = LVar.Set.union (Expr.lvars a) (Expr.lvars b) + let alocs (a, b) = ALoc.Set.union (Expr.alocs a) (Expr.alocs b) let substitution ~le_subst (a, b) = (le_subst a, le_subst b) let is_concrete (a, b) = Expr.is_concrete a && Expr.is_concrete b end @@ -510,12 +510,12 @@ module Node = struct let lvars = function | MemVal { mem_val = Single { value = e; _ }; _ } -> SVal.lvars e - | _ -> SS.empty + | _ -> LVar.Set.empty let alocs = function | MemVal { mem_val = Single { value = e; _ }; _ } -> SVal.alocs e | MemVal { mem_val = Array { values = Arr e; _ }; _ } -> Expr.alocs e - | _ -> SS.empty + | _ -> ALoc.Set.empty let substitution ~sval_subst ~svarr_subst n = let smv = function @@ -1042,20 +1042,20 @@ module Tree = struct let span_lvars = Range.lvars span in let children_lvars = match children with - | Some (a, b) -> SS.union (lvars a) (lvars b) - | None -> SS.empty + | Some (a, b) -> LVar.Set.union (lvars a) (lvars b) + | None -> LVar.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + LVar.Set.union (LVar.Set.union node_lvars span_lvars) children_lvars let rec alocs { node; span; children; _ } = let node_lvars = Node.alocs node in let span_lvars = Range.alocs span in let children_lvars = match children with - | Some (a, b) -> SS.union (alocs a) (alocs b) - | None -> SS.empty + | Some (a, b) -> ALoc.Set.union (alocs a) (alocs b) + | None -> ALoc.Set.empty in - SS.union (SS.union node_lvars span_lvars) children_lvars + ALoc.Set.union (ALoc.Set.union node_lvars span_lvars) children_lvars let rec assertions { node; span; children; _ } = let low, high = span in @@ -1187,14 +1187,14 @@ module M = struct && Option.fold ~none:true ~some:Tree.is_concrete root let lvars { bounds; root } = - SS.union - (Option.fold ~none:SS.empty ~some:Range.lvars bounds) - (Option.fold ~none:SS.empty ~some:Tree.lvars root) + LVar.Set.union + (Option.fold ~none:LVar.Set.empty ~some:Range.lvars bounds) + (Option.fold ~none:LVar.Set.empty ~some:Tree.lvars root) let alocs { bounds; root } = - SS.union - (Option.fold ~none:SS.empty ~some:Range.alocs bounds) - (Option.fold ~none:SS.empty ~some:Tree.alocs root) + ALoc.Set.union + (Option.fold ~none:ALoc.Set.empty ~some:Range.alocs bounds) + (Option.fold ~none:ALoc.Set.empty ~some:Tree.alocs root) let is_in_bounds range bounds = match bounds with diff --git a/transformers/lib/prebuilt/c_states/CGEnv.ml b/transformers/lib/prebuilt/c_states/CGEnv.ml index 44d533503..f74bddc3a 100644 --- a/transformers/lib/prebuilt/c_states/CGEnv.ml +++ b/transformers/lib/prebuilt/c_states/CGEnv.ml @@ -26,8 +26,8 @@ module M : States.MyMonadicSMemory.S with type t = Global_env.t = struct (* Execute action *) let execute_action GetDef s args = match args with - | [ (Expr.Lit (Loc loc) | Expr.ALoc loc | Expr.LVar loc) ] -> ( - match Global_env.find_def_opt s loc with + | [ Expr.Lit (Loc loc) ] -> ( + match Global_env.find_def_opt s (Loc.of_string @@ Id.str loc) with | Some def -> let v = Global_env.serialize_def def in DR.ok (s, [ Expr.Lit (Loc loc); Expr.Lit v ]) @@ -36,8 +36,11 @@ module M : States.MyMonadicSMemory.S with type t = Global_env.t = struct signal. *) if !Gillian.Utils.Config.under_approximation then Delayed.vanish () else - Fmt.failwith "execute_genvgetdef: couldn't find %s\nGENV:\n%a" loc - Global_env.pp s) + Fmt.failwith "execute_genvgetdef: couldn't find %a\nGENV:\n%a" + Id.pp loc Global_env.pp s) + (* Again: are these two cases even relevant?? + | [ Expr.ALoc loc ] -> fn loc + | [ Expr.LVar loc ] -> fn loc *) | _ -> failwith "Invalid arguments for GetDef" let consume () _ _ = failwith "Invalid C GEnv consume" @@ -53,8 +56,8 @@ module M : States.MyMonadicSMemory.S with type t = Global_env.t = struct let assertions_others _ = [] let can_fix () = false let get_fixes () = [] - let lvars _ = Gillian.Utils.Containers.SS.empty - let alocs _ = Gillian.Utils.Containers.SS.empty + let lvars _ = LVar.Set.empty + let alocs _ = ALoc.Set.empty let substitution_in_place _ s = Delayed.return s let get_recovery_tactic _ = Gillian.General.Recovery_tactic.none let list_actions () = [ (GetDef, [], []) ] diff --git a/transformers/lib/states/Agreement.ml b/transformers/lib/states/Agreement.ml index 68233b48b..b4c07ba32 100644 --- a/transformers/lib/states/Agreement.ml +++ b/transformers/lib/states/Agreement.ml @@ -81,11 +81,11 @@ let instantiate = function args let lvars = function - | None -> Containers.SS.empty + | None -> LVar.Set.empty | Some v -> Expr.lvars v let alocs = function - | None -> Containers.SS.empty + | None -> ALoc.Set.empty | Some v -> Expr.alocs v let assertions = function @@ -104,4 +104,9 @@ let can_fix = function let get_fixes = function | MissingState -> - [ [ MyAsrt.CorePred (Ag, [], [ LVar (Generators.fresh_svar ()) ]) ] ] + [ + [ + MyAsrt.CorePred + (Ag, [], [ LVar (LVar.of_string @@ Generators.fresh_svar ()) ]); + ]; + ] diff --git a/transformers/lib/states/Exclusive.ml b/transformers/lib/states/Exclusive.ml index 8bd28fff2..85d4a6b8f 100644 --- a/transformers/lib/states/Exclusive.ml +++ b/transformers/lib/states/Exclusive.ml @@ -79,11 +79,11 @@ let instantiate = function | _ -> failwith "Invalid Excl instantiation" let lvars = function - | None -> Containers.SS.empty + | None -> LVar.Set.empty | Some v -> Expr.lvars v let alocs = function - | None -> Containers.SS.empty + | None -> ALoc.Set.empty | Some v -> Expr.alocs v let assertions = function @@ -95,4 +95,9 @@ let get_recovery_tactic _ = Recovery_tactic.none let can_fix MissingState = true let get_fixes MissingState = - [ [ MyAsrt.CorePred (Ex, [], [ LVar (Generators.fresh_svar ()) ]) ] ] + [ + [ + MyAsrt.CorePred + (Ex, [], [ LVar (LVar.of_string @@ Generators.fresh_svar ()) ]); + ]; + ] diff --git a/transformers/lib/states/Fractional.ml b/transformers/lib/states/Fractional.ml index db0a02aee..59ca24970 100644 --- a/transformers/lib/states/Fractional.ml +++ b/transformers/lib/states/Fractional.ml @@ -1,4 +1,3 @@ -open Gillian.Utils open Gillian.Monadic open Gillian.Symbolic open Gil_syntax @@ -99,11 +98,11 @@ let instantiate = function | _ -> failwith "Invalid Fractional instantiation" let lvars = function - | None -> Containers.SS.empty + | None -> LVar.Set.empty | Some (v, _) -> Expr.lvars v let alocs = function - | None -> Containers.SS.empty + | None -> ALoc.Set.empty | Some (v, _) -> Expr.alocs v let assertions = function diff --git a/transformers/lib/states/Freeable.ml b/transformers/lib/states/Freeable.ml index f6027b427..e063d0702 100644 --- a/transformers/lib/states/Freeable.ml +++ b/transformers/lib/states/Freeable.ml @@ -1,4 +1,4 @@ -open Gillian.Utils +open Gil_syntax open Gillian.Monadic open Gillian.Symbolic module DR = Delayed_result @@ -148,11 +148,11 @@ module Make (S : MyMonadicSMemory.S) : let lvars = function | SubState s -> S.lvars s - | _ -> Containers.SS.empty + | _ -> LVar.Set.empty let alocs = function | SubState s -> S.alocs s - | _ -> Containers.SS.empty + | _ -> ALoc.Set.empty let lift_corepred (p, i, o) = (SubPred p, i, o) diff --git a/transformers/lib/states/MList.ml b/transformers/lib/states/MList.ml index d585ec235..515f1f73c 100644 --- a/transformers/lib/states/MList.ml +++ b/transformers/lib/states/MList.ml @@ -1,4 +1,3 @@ -open Gillian.Utils open Gillian.Monadic open Gillian.Symbolic open Gil_syntax @@ -179,7 +178,7 @@ module Make (S : MyMonadicSMemory.S) : (b', n') let lvars (b, n) = - let open Containers.SS in + let open LVar.Set in let lvars_map = ExpMap.fold (fun k v acc -> S.lvars v |> union (Expr.lvars k) |> union acc) @@ -190,7 +189,7 @@ module Make (S : MyMonadicSMemory.S) : | None -> lvars_map let alocs (b, n) = - let open Containers.SS in + let open ALoc.Set in let alocs_map = ExpMap.fold (fun k v acc -> union (union (Expr.alocs k) (S.alocs v)) acc) diff --git a/transformers/lib/states/MyMonadicSMemory.ml b/transformers/lib/states/MyMonadicSMemory.ml index a4553d73e..45304ee29 100644 --- a/transformers/lib/states/MyMonadicSMemory.ml +++ b/transformers/lib/states/MyMonadicSMemory.ml @@ -70,10 +70,10 @@ module type S = sig val get_recovery_tactic : err_t -> Expr.t Recovery_tactic.t (** The set of logical variables in the state *) - val lvars : t -> Containers.SS.t + val lvars : t -> LVar.Set.t (** The set of abstract locations in the state *) - val alocs : t -> Containers.SS.t + val alocs : t -> ALoc.Set.t (** Applies a substitution to the state. This can branch, eg. when attempting to resolve equality of expressions. *) @@ -98,7 +98,7 @@ module Defaults = struct let is_overlapping_asrt _ = false let copy state = state (* assumes state is immutable *) - let get_print_info _ _ = (Containers.SS.empty, Containers.SS.empty) + let get_print_info _ _ = (LVar.Set.empty, Id.Sets.LocSet.empty) let sure_is_nonempty _ = false let get_failing_constraint _ = diff --git a/transformers/lib/states/MyUtils.ml b/transformers/lib/states/MyUtils.ml index 43e93a453..8e4856aa8 100644 --- a/transformers/lib/states/MyUtils.ml +++ b/transformers/lib/states/MyUtils.ml @@ -67,15 +67,17 @@ end) : SymExprMap = struct match (k, k') with (* THIS IS ONLY TRUE IF WE'RE NOT MATCHING ! *) | Expr.ALoc l1, Expr.ALoc l2 when not matching -> - if String.equal l1 l2 then Delayed.return (Some (k', v)) + if Id.equal l1 l2 then Delayed.return (Some (k', v)) else find_match tl (* This is already done by the #==, but putting it here speeds it up a tiny bit :) *) - | Expr.Lit (Loc l1), Expr.Lit (Loc l2) + | Expr.Lit (Loc l1), Expr.Lit (Loc l2) -> + if Id.equal l1 l2 then Delayed.return (Some (k', v)) + else find_match tl | Expr.Lit (String l1), Expr.Lit (String l2) -> if String.equal l1 l2 then Delayed.return (Some (k', v)) else find_match tl - | Expr.ALoc l1, Expr.ALoc l2 when matching && String.equal l1 l2 - -> Delayed.return (Some (k', v)) + | Expr.ALoc l1, Expr.ALoc l2 when matching && Id.equal l1 l2 -> + Delayed.return (Some (k', v)) | _ -> Check.check Expr.Infix.(k' == k) @@ -140,8 +142,8 @@ let get_loc = let open Delayed.Syntax in let open Delayed_option in function - | Expr.Lit (Loc loc) -> some loc - | Expr.ALoc loc -> some loc + | Expr.Lit (Loc loc) -> some (loc :> Id.any_loc Id.t) + | Expr.ALoc loc -> some (loc :> Id.any_loc Id.t) | e when not (Expr.is_concrete e) -> ( let* loc = Delayed.resolve_loc e in match loc with @@ -149,7 +151,7 @@ let get_loc = | None -> let open Expr.Infix in let loc_name = ALoc.alloc () in - some ~learned:[ e == ALoc loc_name ] loc_name) + some ~learned:[ e == ALoc loc_name ] (loc_name :> Id.any_loc Id.t)) | _ -> none () module SMap = Gillian.Utils.Prelude.Map.Make (struct @@ -162,6 +164,15 @@ module SMap = Gillian.Utils.Prelude.Map.Make (struct let to_yojson s = `String s end) +module LMap = Gillian.Utils.Prelude.Map.Make (struct + include Id + + type nonrec t = any_loc t + + let of_yojson = of_yojson' + let to_yojson = to_yojson' +end) + let bind_vanish_on_err (x : ('a, 'e) result Delayed.t) (f : 'a -> 'b Delayed.t) : 'b Delayed.t = Delayed.bind x (function diff --git a/transformers/lib/states/PMap.ml b/transformers/lib/states/PMap.ml index 96dce274d..fc038a855 100644 --- a/transformers/lib/states/PMap.ml +++ b/transformers/lib/states/PMap.ml @@ -345,18 +345,14 @@ struct let+ h' = I.substitution_in_place sub h in (h', d') - let accumulate ~fn_k ~fn_v h = - let open Utils.Containers.SS in - I.fold (fun k s acc -> fn_v s |> union @@ fn_k k |> union acc) h empty - let lvars (h, d) = - let open Utils.Containers.SS in - accumulate ~fn_k:Expr.lvars ~fn_v:S.lvars h + let open LVar.Set in + I.fold (fun k s -> Expr.lvars k |> union @@ S.lvars s |> union) h empty |> union @@ Option.fold ~none:empty ~some:Expr.lvars d let alocs (h, d) = - let open Utils.Containers.SS in - accumulate ~fn_k:Expr.alocs ~fn_v:S.alocs h + let open ALoc.Set in + I.fold (fun k s -> Expr.alocs k |> union @@ S.alocs s |> union) h empty |> union @@ Option.fold ~none:empty ~some:Expr.alocs d let lift_corepred k (p, i, o) = (SubPred p, k :: i, o) @@ -521,12 +517,14 @@ struct let substitution_in_place = I.substitution_in_place - let accumulate ~fn_k ~fn_v h = - let open Utils.Containers.SS in - I.fold (fun k s acc -> fn_v s |> union @@ fn_k k |> union acc) h empty + let lvars h = + let open LVar.Set in + I.fold (fun k s -> S.lvars s |> union @@ Expr.lvars k |> union) h empty + + let alocs h = + let open ALoc.Set in + I.fold (fun k s -> S.alocs s |> union @@ Expr.alocs k |> union) h empty - let lvars = accumulate ~fn_k:Expr.lvars ~fn_v:S.lvars - let alocs = accumulate ~fn_k:Expr.alocs ~fn_v:S.alocs let lift_corepred k (p, i, o) = (p, k :: i, o) let assertions h = @@ -743,24 +741,23 @@ end module SplitImplSat = MakeSplitImpl (MyUtils.ExpMap) module SplitImplEnt = MakeSplitImpl (MyUtils.ExpMapEnt) +module LMap = MyUtils.LMap (** Implementation of an open PMap with abstract locations. *) module ALocImpl (S : MyMonadicSMemory.S) = struct - module SMap = MyUtils.SMap - type entry = S.t - type t = S.t MyUtils.SMap.t [@@deriving yojson] + type t = S.t LMap.t [@@deriving yojson] let mode : index_mode = Static let make_fresh () = ALoc.alloc () |> Expr.loc_from_loc_name |> Delayed.return let default_instantiation = [] - let empty = SMap.empty - let fold f = SMap.fold (fun k v acc -> f (Expr.loc_from_loc_name k) v acc) - let for_all f = SMap.for_all (fun _ v -> f v) + let empty = LMap.empty + let fold f = LMap.fold (fun k v acc -> f (Expr.loc_from_loc_name k) v acc) + let for_all f = LMap.for_all (fun _ v -> f v) let get_loc_fast = function - | Expr.Lit (Loc loc) -> loc - | Expr.ALoc loc -> loc + | Expr.Lit (Loc loc) -> (loc :> Id.any_loc Id.t) + | Expr.ALoc loc -> (loc :> Id.any_loc Id.t) | e -> Fmt.failwith "ALocImpl: get_loc_fast: non-trivial location passed to \ @@ -771,25 +768,25 @@ module ALocImpl (S : MyMonadicSMemory.S) = struct let get h idx = let idx_s = get_loc_fast idx in - match SMap.find_opt idx_s h with + match LMap.find_opt idx_s h with | Some v -> DO.some (idx, v) | None -> DO.none () let set ~idx:_ ~idx' s h = let idx_s = get_loc_fast idx' in - if S.is_empty s then SMap.remove idx_s h else SMap.add idx_s s h + if S.is_empty s then LMap.remove idx_s h else LMap.add idx_s s h let compose h1 h2 = let open Delayed.Syntax in let compose_binding m (k, v) = let* m = m in - match SMap.find_opt k m with + match LMap.find_opt k m with | Some v' -> let+ v'' = S.compose v v' in - SMap.add k v'' m - | None -> Delayed.return (SMap.add k v m) + LMap.add k v'' m + | None -> Delayed.return (LMap.add k v m) in - List.fold_left compose_binding (Delayed.return h1) (SMap.bindings h2) + List.fold_left compose_binding (Delayed.return h1) (LMap.bindings h2) let substitution_in_place sub h = let open Delayed.Syntax in @@ -797,31 +794,31 @@ module ALocImpl (S : MyMonadicSMemory.S) = struct Subst.fold sub (fun l r acc -> match l with - | ALoc aloc -> (aloc, r) :: acc + | ALoc aloc -> ((aloc :> Id.any_loc Id.t), r) :: acc | _ -> acc) [] in let* substituted = - SMap.fold + LMap.fold (fun k v acc -> let* acc = acc in let+ s' = S.substitution_in_place sub v in - SMap.add k s' acc) + LMap.add k s' acc) h - (Delayed.return SMap.empty) + (Delayed.return LMap.empty) in List.fold_left (fun acc (idx, idx') -> let* acc = acc in - match SMap.find_opt idx acc with + match LMap.find_opt idx acc with | None -> Delayed.return acc | Some s -> ( let idx' = get_loc_fast idx' in - match SMap.find_opt idx' acc with - | None -> Delayed.return (SMap.remove idx acc |> SMap.add idx' s) + match LMap.find_opt idx' acc with + | None -> Delayed.return (LMap.remove idx acc |> LMap.add idx' s) | Some s' -> let+ s'' = S.compose s s' in - SMap.remove idx acc |> SMap.add idx' s'')) + LMap.remove idx acc |> LMap.add idx' s'')) (Delayed.return substituted) aloc_subst end diff --git a/transformers/lib/states/PMap.mli b/transformers/lib/states/PMap.mli index fa7ee0c9f..2e3d60506 100644 --- a/transformers/lib/states/PMap.mli +++ b/transformers/lib/states/PMap.mli @@ -60,7 +60,7 @@ type 'e t_base_sat := 'e MyUtils.ExpMap.t type 'e t_base_ent := 'e MyUtils.ExpMapEnt.t type 'e t_split_sat := 'e MyUtils.ExpMap.t * 'e MyUtils.ExpMap.t type 'e t_split_ent := 'e MyUtils.ExpMapEnt.t * 'e MyUtils.ExpMapEnt.t -type 'e t_aloc := 'e MyUtils.SMap.t +type 'e t_aloc := 'e MyUtils.LMap.t module BaseImplSat : functor (I : PMapIndex) (S : MyMonadicSMemory.S) -> PMapImpl with type t = S.t t_base_sat and type entry = S.t diff --git a/transformers/lib/states/Product.ml b/transformers/lib/states/Product.ml index eca0bf7a0..f43ba2dfe 100644 --- a/transformers/lib/states/Product.ml +++ b/transformers/lib/states/Product.ml @@ -112,8 +112,8 @@ module Make (IDs : IDs) (S1 : MyMonadicSMemory.S) (S2 : MyMonadicSMemory.S) : let+ s2' = S2.substitution_in_place st s2 in (s1', s2') - let lvars (s1, s2) = Containers.SS.union (S1.lvars s1) (S2.lvars s2) - let alocs (s1, s2) = Containers.SS.union (S1.alocs s1) (S2.alocs s2) + let lvars (s1, s2) = Gil_syntax.LVar.Set.union (S1.lvars s1) (S2.lvars s2) + let alocs (s1, s2) = Gil_syntax.ALoc.Set.union (S1.alocs s1) (S2.alocs s2) let lift_corepred_1 (p, i, o) = (P1 p, i, o) let lift_corepred_2 (p, i, o) = (P2 p, i, o) diff --git a/transformers/lib/states/Sum.ml b/transformers/lib/states/Sum.ml index c0ce11120..7885a1344 100644 --- a/transformers/lib/states/Sum.ml +++ b/transformers/lib/states/Sum.ml @@ -1,4 +1,3 @@ -open Gillian.Utils open Gillian.Monadic open MyUtils module DR = Delayed_result @@ -159,12 +158,12 @@ module Make (IDs : IDs) (S1 : MyMonadicSMemory.S) (S2 : MyMonadicSMemory.S) : let lvars = function | S1 s1 -> S1.lvars s1 | S2 s2 -> S2.lvars s2 - | None -> Containers.SS.empty + | None -> Gil_syntax.LVar.Set.empty let alocs = function | S1 s1 -> S1.alocs s1 | S2 s2 -> S2.alocs s2 - | None -> Containers.SS.empty + | None -> Gil_syntax.ALoc.Set.empty let lift_corepred_1 (p, i, o) = (P1 p, i, o) let lift_corepred_2 (p, i, o) = (P2 p, i, o) diff --git a/wisl/lib/ParserAndCompiler/wisl2Gil.ml b/wisl/lib/ParserAndCompiler/wisl2Gil.ml index cb04c256e..edc3e0ae5 100644 --- a/wisl/lib/ParserAndCompiler/wisl2Gil.ml +++ b/wisl/lib/ParserAndCompiler/wisl2Gil.ml @@ -68,7 +68,7 @@ let rec compile_val v = let rec compile_expr ?(fname = "main") ?(is_loop_prefix = false) expr : (WAnnot.t * string option * string Cmd.t) list * Expr.t = - let gen_str = Generators.gen_str fname in + let gen_str pre = Var.of_string @@ Generators.gen_str fname pre in let compile_expr = compile_expr ~fname ~is_loop_prefix in let expr_of_string s = Expr.Lit (Literal.String s) in let expr_fname_of_binop b = @@ -103,7 +103,7 @@ let rec compile_expr ?(fname = "main") ?(is_loop_prefix = false) expr : \ value in the logic. It cannot be used \ as a variable name" (CodeLoc.str (get_loc expr))) - | Var x -> ([], Expr.PVar x) + | Var x -> ([], Expr.PVar (Var.of_string x)) | BinOp (e1, WBinOp.LSTCONS, e2) -> let cmdl1, comp_expr1 = compile_expr e1 in let cmdl2, comp_expr2 = compile_expr e2 in @@ -146,12 +146,12 @@ let rec compile_expr ?(fname = "main") ?(is_loop_prefix = false) expr : let cmds = List.concat cmds in (cmds, Expr.EList comp_es) -(* compile_lexpr : WLExpr.t -> (string list * Asrt.t list * Expr.t) +(* compile_lexpr : WLExpr.t -> (LVar.t list * Asrt.t list * Expr.t) compiles a WLExpr into an output expression and a list of Global Assertions. the string list contains the name of the variables that are generated. They are existentials. *) let rec compile_lexpr ?(fname = "main") (lexpr : WLExpr.t) : - string list * Asrt.t * Expr.t = - let gen_str = Generators.gen_str fname in + LVar.t list * Asrt.t * Expr.t = + let gen_str_l pre = LVar.of_string @@ Generators.gen_str fname pre in let compile_lexpr = compile_lexpr ~fname in let expr_pname_of_binop b = WBinOp.( @@ -163,10 +163,8 @@ let rec compile_lexpr ?(fname = "main") (lexpr : WLExpr.t) : | GREATEREQUAL -> internal_pred_geq | GREATERTHAN -> internal_pred_gt | _ -> - failwith - (Format.asprintf - "Binop %a does not correspond to an internal function" WBinOp.pp - b)) + Fmt.failwith "Binop %a does not correspond to an internal function" + WBinOp.pp b) in let is_internal_pred = WBinOp.( @@ -177,8 +175,8 @@ let rec compile_lexpr ?(fname = "main") (lexpr : WLExpr.t) : WLExpr.( match get lexpr with | LVal v -> ([], [], Expr.Lit (compile_val v)) - | PVar x -> ([], [], Expr.PVar x) - | LVar x -> ([], [], Expr.LVar x) + | PVar x -> ([], [], Expr.PVar (Var.of_string x)) + | LVar x -> ([], [], Expr.LVar (LVar.of_string x)) | LBinOp (e1, WBinOp.NEQ, e2) -> let gvars1, asrtl1, comp_expr1 = compile_lexpr e1 in let gvars2, asrtl2, comp_expr2 = compile_lexpr e2 in @@ -188,7 +186,7 @@ let rec compile_lexpr ?(fname = "main") (lexpr : WLExpr.t) : (gvars1 @ gvars2, asrtl1 @ asrtl2, expr) | LBinOp (e1, b, e2) when is_internal_pred b -> (* Operator corresponds to pointer arithmetics *) - let lout = gen_str sgvar in + let lout = gen_str_l sgvar in let internal_pred = expr_pname_of_binop b in let gvars1, asrtl1, comp_expr1 = compile_lexpr e1 in let gvars2, asrtl2, comp_expr2 = compile_lexpr e2 in @@ -238,7 +236,7 @@ let rec compile_lexpr ?(fname = "main") (lexpr : WLExpr.t) : (* TODO: compile_lformula should return also the list of created existentials *) let rec compile_lformula ?(fname = "main") formula : Asrt.t * Expr.t = - let gen_str = Generators.gen_str fname in + let gen_str pre = LVar.of_string @@ Generators.gen_str fname pre in let compile_lformula = compile_lformula ~fname in let compile_lexpr = compile_lexpr ~fname in WLFormula.( @@ -286,9 +284,9 @@ let rec compile_lformula ?(fname = "main") formula : Asrt.t * Expr.t = (a1 @ a2 @ [ pred ], BinOp (expr_l_var_out, Equal, Expr.true_))) (* compile_lassert returns the compiled assertion + the list of generated existentials *) -let rec compile_lassert ?(fname = "main") asser : string list * Asrt.t = +let rec compile_lassert ?(fname = "main") asser : LVar.t list * Asrt.t = let compile_lassert = compile_lassert ~fname in - let gen_str = Generators.gen_str fname in + let gen_str pre = LVar.of_string @@ Generators.gen_str fname pre in let compile_lexpr = compile_lexpr ~fname in let compile_lformula = compile_lformula ~fname in let gil_add e k = @@ -304,7 +302,7 @@ let rec compile_lassert ?(fname = "main") asser : string list * Asrt.t = ?(ptr_opt = None) ?(curr = 0) (le1 : WLExpr.t) - (lle : WLExpr.t list) : string list * Asrt.t = + (lle : WLExpr.t list) : LVar.t list * Asrt.t = let compile_pointsto = compile_pointsto ~start:false in let exs1, la1, (loc, offset), expr_offset = match ptr_opt with @@ -349,11 +347,10 @@ let rec compile_lassert ?(fname = "main") asser : string list * Asrt.t = in match lle with | [] -> - failwith - (Format.asprintf - "In LPointsTo assertions, a location should always point to at \ - least one value\n\ - It is not the case in : %a" WLAssert.pp asser) + Fmt.failwith + "In LPointsTo assertions, a location should always point to at least \ + one value\n\ + It is not the case in : %a" WLAssert.pp asser | [ le ] -> let exs2, la2, e2 = compile_lexpr le in ( exs1 @ exs2, @@ -402,7 +399,10 @@ let rec compile_lcmd ?(fname = "main") lcmd = match lasrts with | [] -> None | _ -> - let cmd = LCmd.SL (SLCmd.SepAssert (lasrts, existentials)) in + let cmd = + LCmd.SL + (SLCmd.SepAssert (lasrts, (existentials :> Id.any_var Id.t list))) + in (* assert (assertions) {existentials: gvars} *) Some cmd in @@ -436,6 +436,9 @@ let rec compile_lcmd ?(fname = "main") lcmd = let gvars, lasrts, params = list_split_3 (List.map compile_lexpr lel) in let existentials = List.concat gvars in let to_assert = List.concat lasrts in + let bindings = + (List.map LVar.of_string bindings :> Id.any_var Id.t list) + in ( build_assert existentials to_assert, LCmd.SL (SLCmd.ApplyLem (ln, params, bindings)) ) | LogicIf (guard, lc1, lc2) -> @@ -451,15 +454,18 @@ let rec compile_lcmd ?(fname = "main") lcmd = ( build_assert existentials to_assert, LCmd.If (comp_guard, comp_lc1, comp_lc2) ) | Assert (la, lb) -> + let lb = List.map LVar.of_string lb in let exs, comp_la = compile_lassert la in - (None, LCmd.SL (SLCmd.SepAssert (comp_la, exs @ lb))) + ( None, + LCmd.SL (SLCmd.SepAssert (comp_la, (exs @ lb :> Id.any_var Id.t list))) + ) | Invariant _ -> failwith "Invariant is not before a loop." let compile_inv_and_while ~fname ~while_stmt ~invariant = (* FIXME: Variables that are in the invariant but not existential might be wrong. *) let loopretvar = "loopretvar__" in - let gen_str = Generators.gen_str fname in - let loop_fname = gen_str (fname ^ "_loop") in + let gen_str pre = Var.of_string @@ Generators.gen_str fname pre in + let loop_fname = Generators.gen_str fname (fname ^ "_loop") in let while_loc = WStmt.get_loc while_stmt in let invariant_loc = WLCmd.get_loc invariant in let inv_asrt, inv_exs, inv_variant = @@ -585,7 +591,7 @@ let compile_inv_and_while ~fname ~while_stmt ~invariant = Cmd.Call ( retv, Lit (String loop_fname), - List.map (fun x -> Expr.PVar x) vars, + List.map (fun x -> Expr.PVar (Var.of_string x)) vars, None, None ) in @@ -593,7 +599,8 @@ let compile_inv_and_while ~fname ~while_stmt ~invariant = List.mapi (fun i vn -> Cmd.Assignment - (vn, BinOp (PVar retv, BinOp.LstNth, Lit (Int (Z.of_int i))))) + ( Var.of_string vn, + BinOp (PVar retv, BinOp.LstNth, Lit (Int (Z.of_int i))) )) vars in let annot_while = @@ -690,7 +697,7 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = (* Variable assignment *) | { snode = VarAssign (v, e); sid; sloc } :: rest -> let cmdle, comp_e = compile_expr e in - let cmd = Cmd.Assignment (v, comp_e) in + let cmd = Cmd.Assignment (Var.of_string v, comp_e) in let annot = WAnnot.make ~origin_id:sid ~origin_loc:(CodeLoc.to_location sloc) () in @@ -698,7 +705,7 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = (cmdle @ [ (annot, None, cmd) ] @ comp_rest, new_functions) (* Fresh s-var *) | { snode = Fresh v; sid; sloc } :: rest -> - let cmd = Cmd.Logic (LCmd.FreshSVar v) in + let cmd = Cmd.Logic (LCmd.FreshSVar (Var.of_string v)) in let annot = WAnnot.make ~origin_id:sid ~origin_loc:(CodeLoc.to_location sloc) () in @@ -718,7 +725,7 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = ctnlab, faillab ) in - let g_var = gen_str gvar in + let g_var = Var.of_string @@ gen_str gvar in let failcmd = Cmd.Fail ("InvalidBlockPointer", [ comp_e ]) in let cmd = Cmd.LAction (g_var, dispose, [ nth comp_e 0 ]) in let comp_rest, new_functions = compile_list rest in @@ -742,7 +749,7 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = WAnnot.make_multi ~origin_id:sid ~origin_loc:(CodeLoc.to_location sloc) () in - let v_get = gen_str gvar in + let v_get = Var.of_string @@ gen_str gvar in let faillab, ctnlab = (gen_str fail_lab, gen_str ctn_lab) in let checkptrcmd = Cmd.GuardedGoto @@ -757,7 +764,9 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = let lookupcmd = Cmd.LAction (v_get, getcell, [ nth comp_e 0; nth comp_e 1 ]) in - let getvalcmd = Cmd.Assignment (x, nth (Expr.PVar v_get) 2) in + let getvalcmd = + Cmd.Assignment (Var.of_string x, nth (Expr.PVar v_get) 2) + in let cmds = [ (annot, None, checkptrcmd); @@ -782,12 +791,12 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = in let cmdle1, comp_e1 = compile_expr e1 in let cmdle2, comp_e2 = compile_expr e2 in - let v_get = gen_str gvar in + let v_get = Var.of_string @@ gen_str gvar in let getcmd = Cmd.LAction (v_get, getcell, [ nth comp_e1 0; nth comp_e1 1 ]) in let e_v_get = Expr.PVar v_get in - let v_set = gen_str gvar in + let v_set = Var.of_string @@ gen_str gvar in let setcmd = Cmd.LAction (v_set, setcell, [ nth e_v_get 0; nth e_v_get 1; comp_e2 ]) in @@ -811,7 +820,8 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = WAnnot.make ~origin_id:sid ~origin_loc:(CodeLoc.to_location sloc) () in let newcmd = - Cmd.LAction (x, alloc, [ Expr.Lit (Literal.Int (Z.of_int k)) ]) + Cmd.LAction + (Var.of_string x, alloc, [ Expr.Lit (Literal.Int (Z.of_int k)) ]) in let comp_rest, new_functions = compile_list rest in ((annot, None, newcmd) :: comp_rest, new_functions) @@ -825,10 +835,14 @@ let rec compile_stmt_list ?(fname = "main") ?(is_loop_prefix = false) stmtl = let bindings = match to_bind with | Some (spec_name, lvars) -> - Some (spec_name, List.map (fun x -> (x, Expr.LVar x)) lvars) + Some + ( spec_name, + List.map + (fun x -> (LVar.of_string x, Expr.LVar (LVar.of_string x))) + lvars ) | None -> None in - let cmd = Cmd.Call (x, expr_fn, params, None, bindings) in + let cmd = Cmd.Call (Var.of_string x, expr_fn, params, None, bindings) in let annot = WAnnot.make ~origin_id:sid ~origin_loc:(CodeLoc.to_location sloc) ~nest_kind:(FunCall fn) () @@ -933,6 +947,7 @@ let compile_spec Spec.s_init ~ss_label comp_pre [ comp_post ] comp_variant Flag.Normal true in + let fparams = List.map Var.of_string fparams in Spec.init fname fparams [ single_spec ] false false true let compile_pred filepath pred = @@ -941,7 +956,7 @@ let compile_pred filepath pred = let getWISLTypes str = (str, WType.of_variable str types) in let paramsWISLType = List.map (fun (x, _) -> getWISLTypes x) pred_params in let getGILTypes (str, t) = - (str, Option.fold ~some:compile_type ~none:None t) + (Var.of_string str, Option.fold ~some:compile_type ~none:None t) in let pred_params = List.map getGILTypes paramsWISLType in let build_def pred_def = @@ -983,11 +998,7 @@ let rec compile_function in let retassigncmds = cmdle - @ [ - ( ret_annot, - None, - Cmd.Assignment (Gillian.Utils.Names.return_variable, comp_ret_expr) ); - ] + @ [ (ret_annot, None, Cmd.Assignment (Id.return_variable, comp_ret_expr)) ] in let retcmd = (final_ret_annot, None, Cmd.ReturnNormal) in let lbody_withret = lbodylist @ retassigncmds @ [ retcmd ] in @@ -1000,7 +1011,7 @@ let rec compile_function proc_internal = false; proc_body = gil_body; proc_spec = gil_spec; - proc_params = params; + proc_params = List.map Var.of_string params; proc_aliases = []; proc_calls = []; (* TODO *) @@ -1103,6 +1114,7 @@ let compile_lemma let _, lemma_hyp = compile_lassert lemma_hypothesis in let _, post = compile_lassert lemma_conclusion in let lemma_existentials = [] in + let lemma_params = List.map Var.of_string lemma_params in (* TODO: What about existentials for lemma in WISL ? *) Lemma. { @@ -1155,7 +1167,10 @@ let compile ~filepath WProg.{ context; predicates; lemmas } = (fun name proc -> let pre = List.map - (fun var -> Asrt.Pure (BinOp (PVar var, Equal, LVar ("#" ^ var)))) + (fun var -> + Asrt.Pure + (BinOp + (PVar var, Equal, LVar (LVar.of_string ("#" ^ Var.str var))))) proc.Proc.proc_params in diff --git a/wisl/lib/debugging/wislLifter.ml b/wisl/lib/debugging/wislLifter.ml index bd7704497..f9ce40cd3 100644 --- a/wisl/lib/debugging/wislLifter.ml +++ b/wisl/lib/debugging/wislLifter.ml @@ -836,7 +836,7 @@ struct let open WislLActions in match gil_cmd with | Some (Cmd.LAction (_, name, [ _; Expr.BinOp (PVar var, _, _) ]), _) - when name = str_ac GetCell -> Some var + when name = str_ac GetCell -> Some (Var.str var) | _ -> None) let free_error_to_string msg_prefix prev_annot gil_cmd wisl_ast = @@ -855,9 +855,9 @@ struct let* cmd, _ = gil_cmd in match cmd with | Cmd.LAction (_, name, [ Expr.BinOp (PVar var, _, _) ]) - when name = str_ac Dispose -> Some var + when name = str_ac Dispose -> Some (Var.str var) | Cmd.LAction (_, name, [ _; Expr.BinOp (PVar var, _, _) ]) - when name = str_ac GetCell -> Some var + when name = str_ac GetCell -> Some (Var.str var) | _ -> None) in let var = Option.value ~default:"" var in @@ -875,6 +875,7 @@ struct Fmt.str "%s at %a" msg_prefix Location.pp origin_loc) let get_previously_freed_annot loc = + let loc = Id.str loc in let annot = Logging.Log_queryer.get_previously_freed_annot loc in match annot with | None -> None @@ -893,9 +894,9 @@ struct let core_pred, loc, offset = missing_resource_error_info in let default_err_msg = let prefix = - Fmt.str "Missing %s at location='%s'" + Fmt.str "Missing %s at location='%a'" (WislLActions.str_ga core_pred) - loc + Id.pp loc in match offset with | None -> prefix diff --git a/wisl/lib/debugging/wislLifter.mli b/wisl/lib/debugging/wislLifter.mli index 2d079bca9..6c798a3d6 100644 --- a/wisl/lib/debugging/wislLifter.mli +++ b/wisl/lib/debugging/wislLifter.mli @@ -2,12 +2,12 @@ open WSemantics open Gillian.Debugger module Make - (Gil : Gillian.Debugger.Lifter.Gil_fallback_lifter.Gil_lifter_with_state) + (Gil : Lifter.Gil_fallback_lifter.Gil_lifter_with_state) (V : Engine.Verifier.S with type annot = WParserAndCompiler.Annot.t) : Lifter.S - with type memory_error = WSemantics.WislSHeap.err + with type memory = WislSMemory.t and type tl_ast = WParserAndCompiler.tl_ast - and type memory = WislSMemory.t + and type memory_error = WSemantics.WislSHeap.err and type cmd_report = V.SAInterpreter.Logging.ConfigReport.t and type annot = WParserAndCompiler.Annot.t and type init_data = WParserAndCompiler.init_data diff --git a/wisl/lib/semantics/SFVL.ml b/wisl/lib/semantics/SFVL.ml index de9aba5fe..577792214 100644 --- a/wisl/lib/semantics/SFVL.ml +++ b/wisl/lib/semantics/SFVL.ml @@ -11,8 +11,6 @@ type field_value = Expr.t [@@deriving yojson] (* Definition *) type t = field_value Expr.Map.t [@@deriving yojson] -let gsbsts = Expr.substitutables - (* Printing *) let pp ft sfvl = let open Fmt in @@ -77,18 +75,19 @@ let add_with_test add actual_ofs new_val sfvl (** Returns the logical variables occuring in --sfvl-- *) -let lvars (sfvl : t) : SS.t = +let lvars (sfvl : t) : LVar.Set.t = let gllv = Expr.lvars in Expr.Map.fold - (fun e_field e_val ac -> SS.union ac (SS.union (gllv e_field) (gllv e_val))) - sfvl SS.empty + (fun e_field e_val ac -> + LVar.Set.union ac (LVar.Set.union (gllv e_field) (gllv e_val))) + sfvl LVar.Set.empty (** Returns the abstract locations occuring in --sfvl-- *) -let alocs (sfvl : t) : SS.t = +let alocs (sfvl : t) : ALoc.Set.t = Expr.Map.fold (fun e_field e_val ac -> - SS.union ac (SS.union (Expr.alocs e_field) (Expr.alocs e_val))) - sfvl SS.empty + ALoc.Set.union ac (ALoc.Set.union (Expr.alocs e_field) (Expr.alocs e_val))) + sfvl ALoc.Set.empty (* Substitution *) let substitution (subst : SSubst.t) (partial : bool) (fv_list : t) : t = diff --git a/wisl/lib/semantics/wislCHeap.ml b/wisl/lib/semantics/wislCHeap.ml index 6c038fbd4..ec9afc78d 100644 --- a/wisl/lib/semantics/wislCHeap.ml +++ b/wisl/lib/semantics/wislCHeap.ml @@ -1,14 +1,14 @@ +open Gil_syntax open Gillian.Concrete -module Literal = Gillian.Gil_syntax.Literal -type t = (string * int, Values.t) Hashtbl.t +type t = (Loc.t * int, Values.t) Hashtbl.t let init () = Hashtbl.create 1 let get heap loc offset = Hashtbl.find_opt heap (loc, offset) let set heap loc offset value = Hashtbl.replace heap (loc, offset) value let alloc heap size = - let loc = Gillian.Utils.Generators.fresh_loc () in + let loc = Loc.alloc () in let rec aux current_offset = if current_offset < 0 then () else @@ -40,7 +40,7 @@ let get_beautiful_list heap = let rec aux rest = match rest with | [] -> [ (loc, [ (offset, value) ]) ] - | (locp, assocs) :: r when String.equal loc locp -> + | (locp, assocs) :: r when Id.equal loc locp -> (locp, insert (offset, value) assocs) :: r | a :: r -> a :: aux r in @@ -50,11 +50,11 @@ let get_beautiful_list heap = let str heap = let vstr v = Format.asprintf "%a" Values.pp v in - let one_loc_str loc l = + let one_loc_str (loc : Loc.t) l = String.concat "\n" (List.map (fun (offset, value) -> - Printf.sprintf "(%s, %i) -> %s" loc offset (vstr value)) + Fmt.str "(%a, %i) -> %s" Id.pp loc offset (vstr value)) l) in let bl = get_beautiful_list heap in diff --git a/wisl/lib/semantics/wislCHeap.mli b/wisl/lib/semantics/wislCHeap.mli index 12c27edbb..886f2d114 100644 --- a/wisl/lib/semantics/wislCHeap.mli +++ b/wisl/lib/semantics/wislCHeap.mli @@ -1,10 +1,10 @@ type t val init : unit -> t -val get : t -> string -> int -> Gillian.Concrete.Values.t option -val set : t -> string -> int -> Gillian.Concrete.Values.t -> unit -val alloc : t -> int -> string -val remove : t -> string -> int -> unit -val dispose : t -> string -> unit +val get : t -> Gil_syntax.Loc.t -> int -> Gillian.Concrete.Values.t option +val set : t -> Gil_syntax.Loc.t -> int -> Gillian.Concrete.Values.t -> unit +val alloc : t -> int -> Gil_syntax.Loc.t +val remove : t -> Gil_syntax.Loc.t -> int -> unit +val dispose : t -> Gil_syntax.Loc.t -> unit val str : t -> string val copy : t -> t diff --git a/wisl/lib/semantics/wislSHeap.ml b/wisl/lib/semantics/wislSHeap.ml index 5801c0e81..8d99aa173 100644 --- a/wisl/lib/semantics/wislSHeap.ml +++ b/wisl/lib/semantics/wislSHeap.ml @@ -5,12 +5,16 @@ module Solver = Gillian.Logic.FOSolver module Reduction = Gillian.Logic.Reduction open Gillian.Debugger.Utils +type loc_t = Id.any_loc Id.t [@@deriving yojson] + +let pp_loc_t = Id.pp + type err = - | MissingResource of (WislLActions.ga * string * Expr.t option) - | DoubleFree of string - | UseAfterFree of string + | MissingResource of (WislLActions.ga * loc_t * Expr.t option) + | DoubleFree of loc_t + | UseAfterFree of loc_t | MemoryLeak - | OutOfBounds of (int option * string * Expr.t) + | OutOfBounds of (int option * loc_t * Expr.t) | InvalidLocation of Expr.t [@@deriving yojson, show] @@ -51,9 +55,9 @@ module Block = struct let pp ~loc fmt block = match block with - | Freed -> Fmt.pf fmt "%s -> FREED" loc + | Freed -> Fmt.pf fmt "%a -> FREED" Id.pp loc | Allocated { data; bound } -> - Fmt.pf fmt "%s -> @[BOUND: %a@ %a@]" loc + Fmt.pf fmt "%a -> @[BOUND: %a@ %a@]" Id.pp loc (Fmt.option ~none:(Fmt.any "NONE") Fmt.int) bound (Fmt.braces @@ Fmt.vbox @@ -63,16 +67,16 @@ module Block = struct let lvars block = match block with - | Freed -> SS.empty + | Freed -> LVar.Set.empty | Allocated { data; _ } -> SFVL.lvars data let alocs block = match block with - | Freed -> SS.empty + | Freed -> ALoc.Set.empty | Allocated { data; _ } -> SFVL.alocs data end -type t = (string, Block.t) Hashtbl.t [@@deriving yojson] +type t = (loc_t, Block.t) Hashtbl.t [@@deriving yojson] (* A symbolic heap is a map from location and offset to symbolic values *) @@ -86,10 +90,10 @@ let copy heap = Hashtbl.copy heap (****** Types and functions for logging when blocks have been freed ********) -type set_freed_info = { loc : string } [@@deriving yojson] +type set_freed_info = { loc : loc_t } [@@deriving yojson] let set_freed_info_pp fmt set_freed = - Fmt.pf fmt "Set Freed at location %s" set_freed.loc + Fmt.pf fmt "Set Freed at location %a" Id.pp set_freed.loc let set_freed_with_logging heap loc = let set_freed_info = { loc } in @@ -114,8 +118,8 @@ let alloc (heap : t) size = let l = get_list (size - 1) in let sfvl = SFVL.of_list l in let block = Block.Allocated { data = sfvl; bound = Some size } in - let () = Hashtbl.replace heap loc block in - loc + let () = Hashtbl.replace heap (loc :> loc_t) block in + (loc :> loc_t) let dispose (heap : t) loc = match Hashtbl.find_opt heap loc with @@ -264,8 +268,7 @@ let merge_loc (heap : t) new_loc old_loc : unit = let () = Hashtbl.replace heap new_loc (Allocated { data; bound }) in Hashtbl.remove heap old_loc) -let substitution_in_place subst heap : - (t * Expr.Set.t * (string * Type.t) list) list = +let substitution_in_place subst heap = (* First we replace in the offset and values using fvl *) let () = Hashtbl.iter @@ -274,48 +277,41 @@ let substitution_in_place subst heap : heap in (* Then we replace within the locations themselves *) - let aloc_subst = - Subst.filter subst (fun var _ -> - match var with - | ALoc _ -> true - | _ -> false) - in - Subst.iter aloc_subst (fun aloc new_loc -> - let aloc = - match aloc with - | ALoc loc -> loc - | _ -> raise (Failure "Impossible by construction") - in - let new_loc_str = - match new_loc with - | Expr.Lit (Literal.Loc loc) -> loc - | Expr.ALoc loc -> loc - | _ -> - raise - (Failure - (Printf.sprintf "Heap substitution fail for loc: %s" - ((WPrettyUtils.to_str Expr.pp) new_loc))) - in - merge_loc heap new_loc_str aloc); + subst |> Subst.to_list + |> List.filter_map (fun (from, subst_to) -> + match from with + | Expr.ALoc a -> Some ((a :> loc_t), subst_to) + | _ -> None) + |> List.iter (fun (aloc, new_loc) -> + let new_loc = + match new_loc with + | Expr.Lit (Literal.Loc loc) -> (loc :> loc_t) + | Expr.ALoc loc -> (loc :> loc_t) + | _ -> + Fmt.failwith "Heap substitution fail for loc: %s" + ((WPrettyUtils.to_str Expr.pp) new_loc) + in + merge_loc heap new_loc aloc); [ (heap, Expr.Set.empty, []) ] let assertions heap = Hashtbl.fold (fun loc block acc -> Block.assertions ~loc block @ acc) heap [] -let lvars heap : SS.t = +let lvars heap : LVar.Set.t = Hashtbl.fold - (fun _ block acc -> SS.union (Block.lvars block) acc) - heap SS.empty + (fun _ block acc -> LVar.Set.union (Block.lvars block) acc) + heap LVar.Set.empty -let alocs heap : SS.t = +let alocs heap : ALoc.Set.t = Hashtbl.fold - (fun loc block acc -> - SS.union - (SS.union (Block.alocs block) acc) - (match Gillian.Utils.Names.is_aloc_name loc with - | true -> SS.singleton loc - | false -> SS.empty)) - heap SS.empty + (fun loc block -> + ALoc.Set.union + @@ ALoc.Set.union (Block.alocs block) + @@ + match Id.as_aloc loc with + | Some loc -> ALoc.Set.singleton loc + | None -> ALoc.Set.empty) + heap ALoc.Set.empty (***** small things useful for printing ******) @@ -328,6 +324,7 @@ let pp fmt heap = let get_store_vars store is_gil_file = List.filter_map (fun (var, (value : Gil_syntax.Expr.t)) -> + let var = Var.str var in if (not is_gil_file) && Str.string_match (Str.regexp "gvar") var 0 then None else @@ -342,8 +339,8 @@ let get_store_vars store is_gil_file = in let value = match value with - | Expr.EList (Lit (Loc loc) :: rest) | Expr.EList (LVar loc :: rest) - -> match_offset rest loc Fmt.string + | Expr.EList (Lit (Loc loc) :: rest) -> match_offset rest loc Id.pp + | Expr.EList (LVar loc :: rest) -> match_offset rest loc Id.pp | _ -> Fmt.to_to_string (Fmt.hbox Expr.pp) value in Some ({ name = var; value; type_ = None; var_ref = 0 } : Variable.t)) @@ -378,7 +375,7 @@ let add_memory_vars (smemory : t) (get_new_scope_id : unit -> int) variables : smemory |> Hashtbl.to_seq |> Seq.map (fun (loc, blocks) -> match blocks with - | Block.Freed -> Variable.create_leaf loc "freed" () + | Block.Freed -> Variable.create_leaf (Id.str loc) "freed" () | Allocated { data; bound } -> let bound = match bound with @@ -394,7 +391,7 @@ let add_memory_vars (smemory : t) (get_new_scope_id : unit -> int) variables : let cells = Variable.create_node "cells" cells_id () in let loc_id = get_new_scope_id () in let () = Hashtbl.replace variables loc_id [ bound; cells ] in - Variable.create_node loc loc_id ~value:"allocated" ()) + Variable.create_node (Id.str loc) loc_id ~value:"allocated" ()) |> List.of_seq let add_debugger_variables @@ -426,22 +423,25 @@ let is_empty t = Hashtbl.to_seq_values t |> Seq.for_all Block.is_empty let clean_up (keep : Expr.Set.t) (heap : t) : Expr.Set.t * Expr.Set.t = let forgettables = Hashtbl.fold - (fun (aloc : string) (block : Block.t) forgettables -> + (fun aloc (block : Block.t) forgettables -> match block with | Freed -> forgettables | Allocated { data; bound } -> ( + (* TODO: why do we not check if it's an ALoc here? Why assume? *) + let aloc = ALoc.of_string @@ Id.str aloc in match (SFVL.is_empty data, bound, Expr.Set.mem (ALoc aloc) keep) with | true, None, false -> - let () = Hashtbl.remove heap aloc in + let () = Hashtbl.remove heap (aloc :> loc_t) in Expr.Set.add (Expr.ALoc aloc) forgettables | _ -> forgettables)) heap Expr.Set.empty in let keep = Hashtbl.fold - (fun (aloc : string) (block : Block.t) keep -> + (fun aloc (block : Block.t) keep -> + let aloc = ALoc.of_string @@ Id.str aloc in let keep = Expr.Set.add (ALoc aloc) keep in match block with | Freed -> keep @@ -450,13 +450,13 @@ let clean_up (keep : Expr.Set.t) (heap : t) : Expr.Set.t * Expr.Set.t = Expr.Set.of_list (List.map (fun x -> Expr.ALoc x) - (SS.elements (SFVL.alocs data))) + (ALoc.Set.elements (SFVL.alocs data))) in let data_lvars = Expr.Set.of_list (List.map (fun x -> Expr.LVar x) - (SS.elements (SFVL.lvars data))) + (LVar.Set.elements (SFVL.lvars data))) in Expr.Set.union keep (Expr.Set.union data_alocs data_lvars)) heap keep diff --git a/wisl/lib/semantics/wislSHeap.mli b/wisl/lib/semantics/wislSHeap.mli index b24a341ba..e5aa1efc4 100644 --- a/wisl/lib/semantics/wislSHeap.mli +++ b/wisl/lib/semantics/wislSHeap.mli @@ -2,20 +2,21 @@ open Gillian.Symbolic open Gil_syntax open Gillian.Debugger.Utils +type loc_t := Id.any_loc Id.t type t [@@deriving yojson] type err = - | MissingResource of (WislLActions.ga * string * Expr.t option) - | DoubleFree of string - | UseAfterFree of string + | MissingResource of (WislLActions.ga * loc_t * Expr.t option) + | DoubleFree of loc_t + | UseAfterFree of loc_t | MemoryLeak - | OutOfBounds of (int option * string * Expr.t) + | OutOfBounds of (int option * loc_t * Expr.t) | InvalidLocation of Expr.t [@@deriving yojson, show] val init : unit -> t -val alloc : t -> int -> string -val dispose : t -> string -> (unit, err) Result.t +val alloc : t -> int -> loc_t +val dispose : t -> loc_t -> (unit, err) Result.t val clean_up : Expr.Set.t -> t -> Expr.Set.t * Expr.Set.t val is_empty : t -> bool @@ -23,43 +24,40 @@ val get_cell : pfs:Pure_context.t -> gamma:Type_env.t -> t -> - string -> + loc_t -> Expr.t -> - (string * Expr.t * Expr.t, err) result + (loc_t * Expr.t * Expr.t, err) result val set_cell : pfs:Pure_context.t -> gamma:Type_env.t -> t -> - string -> + loc_t -> Expr.t -> Expr.t -> (unit, err) result -val rem_cell : t -> string -> Expr.t -> (unit, err) result -val get_bound : t -> string -> (int, err) result -val set_bound : t -> string -> int -> (unit, err) result -val rem_bound : t -> string -> (unit, err) result -val get_freed : t -> string -> (unit, err) result -val set_freed : t -> string -> unit -val rem_freed : t -> string -> (unit, err) result +val rem_cell : t -> loc_t -> Expr.t -> (unit, err) result +val get_bound : t -> loc_t -> (int, err) result +val set_bound : t -> loc_t -> int -> (unit, err) result +val rem_bound : t -> loc_t -> (unit, err) result +val get_freed : t -> loc_t -> (unit, err) result +val set_freed : t -> loc_t -> unit +val rem_freed : t -> loc_t -> (unit, err) result val pp : t Fmt.t val copy : t -> t -val lvars : t -> SS.t -val alocs : t -> SS.t +val lvars : t -> LVar.Set.t +val alocs : t -> ALoc.Set.t val substitution_in_place : Gillian.Symbolic.Subst.t -> t -> - (t - * Gillian.Gil_syntax.Expr.Set.t - * (string * Gillian.Gil_syntax.Type.t) list) - list + (t * Expr.Set.t * (Id.any_var Id.t * Type.t) list) list -val assertions : t -> Gillian.Gil_syntax.Asrt.t +val assertions : t -> Asrt.t val add_debugger_variables : - store:(string * Gillian.Gil_syntax.Expr.t) list -> + store:(Var.t * Expr.t) list -> memory:t -> is_gil_file:bool -> get_new_scope_id:(unit -> int) -> diff --git a/wisl/lib/semantics/wislSMemory.ml b/wisl/lib/semantics/wislSMemory.ml index 4e39e94c3..35d6a5c23 100644 --- a/wisl/lib/semantics/wislSMemory.ml +++ b/wisl/lib/semantics/wislSMemory.ml @@ -34,12 +34,10 @@ let set_cell heap pfs gamma (loc : vt) (offset : vt) (value : vt) = add to the path condition that it is equal to the given loc *) let resolved_loc_opt = resolve_loc pfs gamma loc in match resolved_loc_opt with - | Some loc_name -> - if Gillian.Utils.Names.is_aloc_name loc_name then (loc_name, []) - else (loc_name, []) + | Some loc_name -> (loc_name, []) | None -> let al = ALoc.alloc () in - (al, [ Expr.BinOp (Expr.ALoc al, Equal, loc) ]) + ((al :> Id.any_loc Id.t), [ Expr.BinOp (Expr.ALoc al, Equal, loc) ]) in match WislSHeap.set_cell ~pfs ~gamma heap loc_name offset value with | Error e -> Error [ e ] @@ -72,12 +70,10 @@ let set_bound heap pfs gamma (loc : vt) (bound : int) = add to the path condition that it is equal to the given loc *) let resolved_loc_opt = resolve_loc pfs gamma loc in match resolved_loc_opt with - | Some loc_name -> - if Gillian.Utils.Names.is_aloc_name loc_name then (loc_name, []) - else (loc_name, []) + | Some loc_name -> (loc_name, []) | None -> let al = ALoc.alloc () in - (al, [ Expr.BinOp (ALoc al, Equal, loc) ]) + ((al :> Id.any_loc Id.t), [ Expr.BinOp (ALoc al, Equal, loc) ]) in match WislSHeap.set_bound heap loc_name bound with | Error e -> Error [ e ] @@ -109,12 +105,10 @@ let set_freed heap pfs gamma (loc : vt) = add to the path condition that it is equal to the given loc *) let resolved_loc_opt = resolve_loc pfs gamma loc in match resolved_loc_opt with - | Some loc_name -> - if Gillian.Utils.Names.is_aloc_name loc_name then (loc_name, []) - else (loc_name, []) + | Some loc_name -> (loc_name, []) | None -> let al = ALoc.alloc () in - (al, [ Expr.BinOp (ALoc al, Equal, loc) ]) + ((al :> Id.any_loc Id.t), [ Expr.BinOp (ALoc al, Equal, loc) ]) in let () = WislSHeap.set_freed heap loc_name in Ok [ (heap, [], new_pfs, []) ] @@ -134,7 +128,7 @@ let alloc heap _pfs _gamma (size : int) = Ok [ ( heap, - [ Expr.Lit (Literal.Loc loc); Expr.Lit (Literal.Int Z.zero) ], + [ Expr.loc_from_loc_name loc; Expr.Lit (Literal.Int Z.zero) ], [], [] ); ] @@ -265,7 +259,7 @@ let pp fmt h = Format.fprintf fmt "%a" WislSHeap.pp h let pp_by_need _ fmt h = pp fmt h (* TODO: Implement properly *) -let get_print_info _ _ = (SS.empty, SS.empty) +let get_print_info _ _ = (LVar.Set.empty, Id.Sets.LocSet.empty) let pp_err fmt t = match t with diff --git a/wisl/lib/semantics/wislSMemory.mli b/wisl/lib/semantics/wislSMemory.mli index 63553eead..5108a9b2f 100644 --- a/wisl/lib/semantics/wislSMemory.mli +++ b/wisl/lib/semantics/wislSMemory.mli @@ -6,7 +6,7 @@ include and type init_data = unit val add_debugger_variables : - store:(string * Gillian.Gil_syntax.Expr.t) list -> + store:(Gillian.Gil_syntax.Var.t * Gillian.Gil_syntax.Expr.t) list -> memory:t -> is_gil_file:bool -> get_new_scope_id:(unit -> int) ->