|
|
|
(*
|
|
|
|
* Copyright (c) 2009-2013, Monoidics ltd.
|
|
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*)
|
|
|
|
|
|
|
|
(** The Smallfoot Intermediate Language *)
|
|
|
|
open! IStd
|
|
|
|
|
|
|
|
module F = Format
|
|
|
|
|
|
|
|
(** {2 Programs and Types} *)
|
|
|
|
|
|
|
|
(** Kind of prune instruction *)
|
|
|
|
type if_kind =
|
|
|
|
| Ik_bexp (** boolean expressions, and exp ? exp : exp *)
|
|
|
|
| Ik_dowhile
|
|
|
|
| Ik_for
|
|
|
|
| Ik_if
|
|
|
|
| Ik_land_lor (** obtained from translation of && or || *)
|
|
|
|
| Ik_while
|
|
|
|
| Ik_switch
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
type instr_metadata =
|
|
|
|
| Abstract of Location.t
|
|
|
|
(** a good place to apply abstraction, mostly used in the biabduction analysis *)
|
|
|
|
| ExitScope of Var.t list * Location.t (** remove temporaries and dead program variables *)
|
|
|
|
| Nullify of Pvar.t * Location.t (** nullify stack variable *)
|
|
|
|
| Skip (** no-op *)
|
|
|
|
| VariableLifetimeBegins of Pvar.t * Typ.t * Location.t (** stack variable declared *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
(** An instruction. *)
|
|
|
|
type instr =
|
|
|
|
(* Note for frontend writers:
|
|
|
|
[x] must be used in a subsequent instruction, otherwise the entire
|
|
|
|
`Load` instruction may be eliminated by copy-propagation. *)
|
|
|
|
| Load of Ident.t * Exp.t * Typ.t * Location.t
|
|
|
|
(** Load a value from the heap into an identifier.
|
|
|
|
[x = *lexp:typ] where
|
|
|
|
[lexp] is an expression denoting a heap address
|
|
|
|
[typ] is the root type of [lexp]. *)
|
|
|
|
| Store of Exp.t * Typ.t * Exp.t * Location.t
|
|
|
|
(** Store the value of an expression into the heap.
|
|
|
|
[*lexp1:typ = exp2] where
|
|
|
|
[lexp1] is an expression denoting a heap address
|
|
|
|
[typ] is the root type of [lexp1]
|
|
|
|
[exp2] is the expression whose value is store. *)
|
|
|
|
| Prune of Exp.t * Location.t * bool * if_kind
|
|
|
|
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
|
|
|
|
| Call of (Ident.t * Typ.t) * Exp.t * (Exp.t * Typ.t) list * Location.t * CallFlags.t
|
|
|
|
(** [Call ((ret_id, ret_typ), e_fun, arg_ts, loc, call_flags)] represents an instruction
|
|
|
|
[ret_id = e_fun(arg_ts);] *)
|
|
|
|
| Metadata of instr_metadata
|
|
|
|
(** hints about the program that are not strictly needed to understand its semantics, for
|
|
|
|
instance information about its original syntactic structure *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
val equal_instr : instr -> instr -> bool
|
|
|
|
|
|
|
|
val skip_instr : instr
|
|
|
|
|
|
|
|
val instr_is_auxiliary : instr -> bool
|
|
|
|
(** Check if an instruction is auxiliary, or if it comes from source instructions. *)
|
|
|
|
|
|
|
|
(** Offset for an lvalue. *)
|
|
|
|
type offset = Off_fld of Typ.Fieldname.t * Typ.t | Off_index of Exp.t
|
|
|
|
|
|
|
|
(** {2 Components of Propositions} *)
|
|
|
|
|
|
|
|
(** an atom is a pure atomic formula *)
|
|
|
|
type atom =
|
|
|
|
| Aeq of Exp.t * Exp.t (** equality *)
|
|
|
|
| Aneq of Exp.t * Exp.t (** disequality *)
|
|
|
|
| Apred of PredSymb.t * Exp.t list (** predicate symbol applied to exps *)
|
|
|
|
| Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
val equal_atom : atom -> atom -> bool
|
|
|
|
|
|
|
|
val atom_has_local_addr : atom -> bool
|
|
|
|
|
|
|
|
(** kind of lseg or dllseg predicates *)
|
|
|
|
type lseg_kind =
|
|
|
|
| Lseg_NE (** nonempty (possibly circular) listseg *)
|
|
|
|
| Lseg_PE (** possibly empty (possibly circular) listseg *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
val equal_lseg_kind : lseg_kind -> lseg_kind -> bool
|
|
|
|
|
|
|
|
(** The boolean is true when the pointer was dereferenced without testing for zero. *)
|
|
|
|
type zero_flag = bool option
|
|
|
|
|
|
|
|
(** True when the value was obtained by doing case analysis on null in a procedure call. *)
|
|
|
|
type null_case_flag = bool
|
|
|
|
|
|
|
|
(** instrumentation of heap values *)
|
|
|
|
type inst =
|
|
|
|
| Iabstraction
|
|
|
|
| Iactual_precondition
|
|
|
|
| Ialloc
|
|
|
|
| Iformal of zero_flag * null_case_flag
|
|
|
|
| Iinitial
|
|
|
|
| Ilookup
|
|
|
|
| Inone
|
|
|
|
| Inullify
|
|
|
|
| Irearrange of zero_flag * null_case_flag * int * PredSymb.path_pos
|
|
|
|
| Itaint
|
|
|
|
| Iupdate of zero_flag * null_case_flag * int * PredSymb.path_pos
|
|
|
|
| Ireturn_from_call of int
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
val equal_inst : inst -> inst -> bool
|
|
|
|
|
|
|
|
val inst_actual_precondition : inst
|
|
|
|
|
|
|
|
val inst_formal : inst
|
|
|
|
|
|
|
|
val inst_initial : inst
|
|
|
|
(** for formal parameters and heap values at the beginning of the function *)
|
|
|
|
|
|
|
|
val inst_lookup : inst
|
|
|
|
(** for initial values *)
|
|
|
|
|
|
|
|
val inst_none : inst
|
|
|
|
|
|
|
|
val inst_nullify : inst
|
|
|
|
|
|
|
|
val inst_rearrange : bool -> Location.t -> PredSymb.path_pos -> inst
|
|
|
|
(** the boolean indicates whether the pointer is known nonzero *)
|
|
|
|
|
|
|
|
val inst_update : Location.t -> PredSymb.path_pos -> inst
|
|
|
|
|
|
|
|
val inst_set_null_case_flag : inst -> inst
|
|
|
|
(** Set the null case flag of the inst. *)
|
|
|
|
|
|
|
|
val inst_new_loc : Location.t -> inst -> inst
|
|
|
|
(** update the location of the instrumentation *)
|
|
|
|
|
|
|
|
val update_inst : inst -> inst -> inst
|
|
|
|
(** Update [inst_old] to [inst_new] preserving the zero flag *)
|
|
|
|
|
|
|
|
exception JoinFail
|
|
|
|
|
|
|
|
val inst_partial_join : inst -> inst -> inst
|
|
|
|
(** join of instrumentations, can raise JoinFail *)
|
|
|
|
|
|
|
|
val inst_partial_meet : inst -> inst -> inst
|
|
|
|
(** meet of instrumentations *)
|
|
|
|
|
|
|
|
(** structured expressions represent a value of structured type, such as an array or a struct. *)
|
|
|
|
type 'inst strexp0 =
|
|
|
|
| Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *)
|
|
|
|
| Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *)
|
|
|
|
| Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst
|
|
|
|
(** Array of given length
|
|
|
|
There are two conditions imposed / used in the array case.
|
|
|
|
First, if some index and value pair appears inside an array
|
|
|
|
in a strexp, then the index is less than the length of the array.
|
|
|
|
For instance, x |->[10 | e1: v1] implies that e1 <= 9.
|
|
|
|
Second, if two indices appear in an array, they should be different.
|
|
|
|
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
type strexp = inst strexp0
|
|
|
|
|
|
|
|
val compare_strexp : ?inst:bool -> strexp -> strexp -> int
|
|
|
|
(** Comparison function for strexp.
|
|
|
|
The inst:: parameter specifies whether instumentations should also
|
|
|
|
be considered (false by default). *)
|
|
|
|
|
|
|
|
val equal_strexp : ?inst:bool -> strexp -> strexp -> bool
|
|
|
|
(** Equality function for strexp.
|
|
|
|
The inst:: parameter specifies whether instumentations should also
|
|
|
|
be considered (false by default). *)
|
|
|
|
|
|
|
|
(** an atomic heap predicate *)
|
|
|
|
type 'inst hpred0 =
|
|
|
|
| Hpointsto of Exp.t * 'inst strexp0 * Exp.t
|
|
|
|
(** represents [exp|->strexp:typexp] where [typexp]
|
|
|
|
is an expression representing a type, e.h. [sizeof(t)]. *)
|
|
|
|
| Hlseg of lseg_kind * 'inst hpara0 * Exp.t * Exp.t * Exp.t list
|
|
|
|
(** higher - order predicate for singly - linked lists.
|
|
|
|
Should ensure that exp1!= exp2 implies that exp1 is allocated.
|
|
|
|
This assumption is used in the rearrangement. The last [exp list] parameter
|
|
|
|
is used to denote the shared links by all the nodes in the list. *)
|
|
|
|
| Hdllseg of lseg_kind * 'inst hpara_dll0 * Exp.t * Exp.t * Exp.t * Exp.t * Exp.t list
|
|
|
|
(** higher-order predicate for doubly-linked lists.
|
|
|
|
Parameter for the higher-order singly-linked list predicate.
|
|
|
|
Means "lambda (root,next,svars). Exists evars. body".
|
|
|
|
Assume that root, next, svars, evars are disjoint sets of
|
|
|
|
primed identifiers, and include all the free primed identifiers in body.
|
|
|
|
body should not contain any non - primed identifiers or program
|
|
|
|
variables (i.e. pvars). *)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
and 'inst hpara0 =
|
|
|
|
{root: Ident.t; next: Ident.t; svars: Ident.t list; evars: Ident.t list; body: 'inst hpred0 list}
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
(** parameter for the higher-order doubly-linked list predicates.
|
|
|
|
Assume that all the free identifiers in body_dll should belong to
|
|
|
|
cell, blink, flink, svars_dll, evars_dll. *)
|
|
|
|
and 'inst hpara_dll0 =
|
|
|
|
{ cell: Ident.t (** address cell *)
|
|
|
|
; blink: Ident.t (** backward link *)
|
|
|
|
; flink: Ident.t (** forward link *)
|
|
|
|
; svars_dll: Ident.t list
|
|
|
|
; evars_dll: Ident.t list
|
|
|
|
; body_dll: 'inst hpred0 list }
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
type hpred = inst hpred0
|
|
|
|
|
|
|
|
type hpara = inst hpara0
|
|
|
|
|
|
|
|
type hpara_dll = inst hpara_dll0
|
|
|
|
|
|
|
|
val compare_hpred : ?inst:bool -> hpred -> hpred -> int
|
|
|
|
(** Comparison function for hpred.
|
|
|
|
The inst:: parameter specifies whether instumentations should also
|
|
|
|
be considered (false by default). *)
|
|
|
|
|
|
|
|
val equal_hpred : ?inst:bool -> hpred -> hpred -> bool
|
|
|
|
(** Equality function for hpred.
|
|
|
|
The inst:: parameter specifies whether instumentations should also
|
|
|
|
be considered (false by default). *)
|
|
|
|
|
|
|
|
(** Sets of heap predicates *)
|
|
|
|
module HpredSet : Caml.Set.S with type elt = hpred
|
|
|
|
|
|
|
|
(** {2 Compaction} *)
|
|
|
|
|
|
|
|
type sharing_env
|
|
|
|
|
|
|
|
val create_sharing_env : unit -> sharing_env
|
|
|
|
(** Create a sharing env to store canonical representations *)
|
|
|
|
|
|
|
|
val hpred_compact : sharing_env -> hpred -> hpred
|
|
|
|
(** Return a compact representation of the exp *)
|
|
|
|
|
|
|
|
val is_objc_object : hpred -> bool
|
|
|
|
(** {2 Comparision And Inspection Functions} *)
|
|
|
|
|
|
|
|
val is_static_local_name : string -> Pvar.t -> bool
|
|
|
|
(** Check if a pvar is a local static in objc *)
|
|
|
|
|
|
|
|
val is_block_pvar : Pvar.t -> bool
|
|
|
|
(** Check if a pvar is a local pointing to a block in objc *)
|
|
|
|
|
|
|
|
val add_with_block_parameters_flag : instr -> instr
|
|
|
|
(** Adds a with_blocks_parameters flag to a method call, when the arguments
|
|
|
|
contain an Objective-C block, and the method is an Objective-C method
|
|
|
|
(to be extended to other methods) *)
|
|
|
|
|
|
|
|
(** {2 Pretty Printing} *)
|
|
|
|
|
|
|
|
val color_wrapper : Pp.env -> F.formatter -> 'a -> f:(Pp.env -> F.formatter -> 'a -> unit) -> unit
|
|
|
|
(** Wraps a printing function with an updated printenv when using diff printing *)
|
|
|
|
|
|
|
|
val pp_exp_printenv : ?print_types:bool -> Pp.env -> F.formatter -> Exp.t -> unit
|
|
|
|
(** Pretty print an expression. *)
|
|
|
|
|
|
|
|
val d_exp : Exp.t -> unit
|
|
|
|
(** dump an expression. *)
|
|
|
|
|
|
|
|
val pp_texp : Pp.env -> F.formatter -> Exp.t -> unit
|
|
|
|
(** Pretty print a type. *)
|
|
|
|
|
|
|
|
val pp_texp_full : Pp.env -> F.formatter -> Exp.t -> unit
|
|
|
|
(** Pretty print a type with all the details. *)
|
|
|
|
|
|
|
|
val d_texp_full : Exp.t -> unit
|
|
|
|
(** Dump a type expression with all the details. *)
|
|
|
|
|
|
|
|
val d_exp_list : Exp.t list -> unit
|
|
|
|
(** Dump a list of expressions. *)
|
|
|
|
|
|
|
|
val pp_offset : Pp.env -> F.formatter -> offset -> unit
|
|
|
|
|
|
|
|
val d_offset_list : offset list -> unit
|
|
|
|
(** Dump a list of offsets *)
|
|
|
|
|
|
|
|
val location_of_instr : instr -> Location.t
|
|
|
|
(** Get the location of the instruction *)
|
|
|
|
|
|
|
|
val exps_of_instr : instr -> Exp.t list
|
|
|
|
(** get the expressions occurring in the instruction *)
|
|
|
|
|
|
|
|
val if_kind_to_string : if_kind -> string
|
|
|
|
(** Pretty print an if_kind *)
|
|
|
|
|
|
|
|
val pp_instr_metadata : Pp.env -> F.formatter -> instr_metadata -> unit
|
|
|
|
|
|
|
|
val pp_instr : print_types:bool -> Pp.env -> F.formatter -> instr -> unit
|
|
|
|
(** Pretty print an instruction. *)
|
|
|
|
|
|
|
|
val d_instr : instr -> unit
|
|
|
|
(** Dump an instruction. *)
|
|
|
|
|
|
|
|
val pp_atom : Pp.env -> F.formatter -> atom -> unit
|
|
|
|
(** Pretty print an atom. *)
|
|
|
|
|
|
|
|
val d_atom : atom -> unit
|
|
|
|
(** Dump an atom. *)
|
|
|
|
|
|
|
|
val pp_inst : F.formatter -> inst -> unit
|
|
|
|
(** pretty-print an inst *)
|
|
|
|
|
|
|
|
val pp_sexp : Pp.env -> F.formatter -> strexp -> unit
|
|
|
|
(** Pretty print a strexp. *)
|
|
|
|
|
|
|
|
val d_sexp : strexp -> unit
|
|
|
|
(** Dump a strexp. *)
|
|
|
|
|
|
|
|
val pp_hpred : Pp.env -> F.formatter -> hpred -> unit
|
|
|
|
(** Pretty print a hpred. *)
|
|
|
|
|
|
|
|
val d_hpred : hpred -> unit
|
|
|
|
(** Dump a hpred. *)
|
|
|
|
|
|
|
|
val pp_hpara : Pp.env -> F.formatter -> hpara -> unit
|
|
|
|
(** Pretty print a hpara. *)
|
|
|
|
|
|
|
|
val pp_hpara_dll : Pp.env -> F.formatter -> hpara_dll -> unit
|
|
|
|
(** Pretty print a hpara_dll. *)
|
|
|
|
|
|
|
|
(** Module Predicates records the occurrences of predicates as parameters
|
|
|
|
of (doubly -)linked lists and Epara.
|
|
|
|
Provides unique numbering for predicates and an iterator. *)
|
|
|
|
module Predicates : sig
|
|
|
|
(** predicate environment *)
|
|
|
|
type env
|
|
|
|
|
|
|
|
val empty_env : unit -> env
|
|
|
|
(** create an empty predicate environment *)
|
|
|
|
|
|
|
|
val is_empty : env -> bool
|
|
|
|
(** return true if the environment is empty *)
|
|
|
|
|
|
|
|
val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit
|
|
|
|
(** [iter env f f_dll] iterates [f] and [f_dll] on all the hpara and hpara_dll,
|
|
|
|
passing the unique id to the functions. The iterator can only be used once. *)
|
|
|
|
|
|
|
|
val process_hpred : env -> hpred -> unit
|
|
|
|
(** Process one hpred, updating the predicate environment *)
|
|
|
|
end
|
|
|
|
|
|
|
|
val pp_hpred_env : Pp.env -> Predicates.env option -> F.formatter -> hpred -> unit
|
|
|
|
(** Pretty print a hpred with optional predicate env *)
|
|
|
|
|
|
|
|
(** {2 Functions for traversing SIL data types} *)
|
|
|
|
|
|
|
|
val strexp_expmap : (Exp.t * inst option -> Exp.t * inst option) -> strexp -> strexp
|
|
|
|
(** Change exps in strexp using [f].
|
|
|
|
WARNING: the result might not be normalized. *)
|
|
|
|
|
|
|
|
val hpred_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred -> hpred
|
|
|
|
(** Change exps in hpred by [f].
|
|
|
|
WARNING: the result might not be normalized. *)
|
|
|
|
|
|
|
|
val hpred_instmap : (inst -> inst) -> hpred -> hpred
|
|
|
|
(** Change instrumentations in hpred using [f]. *)
|
|
|
|
|
|
|
|
val hpred_list_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred list -> hpred list
|
|
|
|
(** Change exps in hpred list by [f].
|
|
|
|
WARNING: the result might not be normalized. *)
|
|
|
|
|
|
|
|
val atom_expmap : (Exp.t -> Exp.t) -> atom -> atom
|
|
|
|
(** Change exps in atom by [f].
|
|
|
|
WARNING: the result might not be normalized. *)
|
|
|
|
|
|
|
|
val hpred_list_get_lexps : (Exp.t -> bool) -> hpred list -> Exp.t list
|
|
|
|
|
|
|
|
val hpred_entries : hpred -> Exp.t list
|
|
|
|
|
|
|
|
val atom_free_vars : atom -> Ident.t Sequence.t
|
|
|
|
|
|
|
|
val atom_gen_free_vars : atom -> (unit, Ident.t) Sequence.Generator.t
|
|
|
|
|
|
|
|
val hpred_free_vars : hpred -> Ident.t Sequence.t
|
|
|
|
|
|
|
|
val hpred_gen_free_vars : hpred -> (unit, Ident.t) Sequence.Generator.t
|
|
|
|
|
|
|
|
val hpara_shallow_free_vars : hpara -> Ident.t Sequence.t
|
|
|
|
|
|
|
|
val hpara_dll_shallow_free_vars : hpara_dll -> Ident.t Sequence.t
|
|
|
|
(** Variables in hpara_dll, excluding bound vars in the body *)
|
|
|
|
|
|
|
|
(** {2 Substitution} *)
|
|
|
|
|
|
|
|
type subst = private (Ident.t * Exp.t) list [@@deriving compare]
|
|
|
|
|
|
|
|
val equal_subst : subst -> subst -> bool
|
|
|
|
(** Equality for substitutions. *)
|
|
|
|
|
|
|
|
val subst_of_list : (Ident.t * Exp.t) list -> subst
|
|
|
|
(** Create a substitution from a list of pairs.
|
|
|
|
For all (id1, e1), (id2, e2) in the input list,
|
|
|
|
if id1 = id2, then e1 = e2. *)
|
|
|
|
|
|
|
|
val subst_of_list_duplicates : (Ident.t * Exp.t) list -> subst
|
|
|
|
(** like subst_of_list, but allow duplicate ids and only keep the first occurrence *)
|
|
|
|
|
|
|
|
val sub_to_list : subst -> (Ident.t * Exp.t) list
|
|
|
|
(** Convert a subst to a list of pairs. *)
|
|
|
|
|
|
|
|
val sub_empty : subst
|
|
|
|
(** The empty substitution. *)
|
|
|
|
|
|
|
|
val is_sub_empty : subst -> bool
|
|
|
|
|
|
|
|
val sub_join : subst -> subst -> subst
|
|
|
|
(** Compute the common id-exp part of two inputs [subst1] and [subst2].
|
|
|
|
The first component of the output is this common part.
|
|
|
|
The second and third components are the remainder of [subst1]
|
|
|
|
and [subst2], respectively. *)
|
|
|
|
|
|
|
|
val sub_symmetric_difference : subst -> subst -> subst * subst * subst
|
|
|
|
(** Compute the common id-exp part of two inputs [subst1] and [subst2].
|
|
|
|
The first component of the output is this common part.
|
|
|
|
The second and third components are the remainder of [subst1]
|
|
|
|
and [subst2], respectively. *)
|
|
|
|
|
|
|
|
val sub_find : (Ident.t -> bool) -> subst -> Exp.t
|
|
|
|
(** [sub_find filter sub] returns the expression associated to the first identifier
|
|
|
|
that satisfies [filter].
|
|
|
|
Raise [Not_found] if there isn't one. *)
|
|
|
|
|
|
|
|
val sub_filter : (Ident.t -> bool) -> subst -> subst
|
|
|
|
(** [sub_filter filter sub] restricts the domain of [sub] to the
|
|
|
|
identifiers satisfying [filter]. *)
|
|
|
|
|
|
|
|
val sub_filter_pair : subst -> f:(Ident.t * Exp.t -> bool) -> subst
|
|
|
|
(** [sub_filter_exp filter sub] restricts the domain of [sub] to the
|
|
|
|
identifiers satisfying [filter(id, sub(id))]. *)
|
|
|
|
|
|
|
|
val sub_range_partition : (Exp.t -> bool) -> subst -> subst * subst
|
|
|
|
(** [sub_range_partition filter sub] partitions [sub] according to
|
|
|
|
whether range expressions satisfy [filter]. *)
|
|
|
|
|
|
|
|
val sub_domain_partition : (Ident.t -> bool) -> subst -> subst * subst
|
|
|
|
(** [sub_domain_partition filter sub] partitions [sub] according to
|
|
|
|
whether domain identifiers satisfy [filter]. *)
|
|
|
|
|
|
|
|
val sub_domain : subst -> Ident.t list
|
|
|
|
(** Return the list of identifiers in the domain of the substitution. *)
|
|
|
|
|
|
|
|
val sub_range : subst -> Exp.t list
|
|
|
|
(** Return the list of expressions in the range of the substitution. *)
|
|
|
|
|
|
|
|
val sub_range_map : (Exp.t -> Exp.t) -> subst -> subst
|
|
|
|
(** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. *)
|
|
|
|
|
|
|
|
val sub_map : (Ident.t -> Ident.t) -> (Exp.t -> Exp.t) -> subst -> subst
|
|
|
|
(** [sub_map f g sub] applies the renaming [f] to identifiers in the domain
|
|
|
|
of [sub] and the substitution [g] to the expressions in the range of [sub]. *)
|
|
|
|
|
|
|
|
val extend_sub : subst -> Ident.t -> Exp.t -> subst option
|
|
|
|
(** Extend substitution and return [None] if not possible. *)
|
|
|
|
|
|
|
|
val subst_free_vars : subst -> Ident.t Sequence.t
|
|
|
|
|
|
|
|
val subst_gen_free_vars : subst -> (unit, Ident.t) Sequence.Generator.t
|
|
|
|
|
|
|
|
(** substitution functions
|
|
|
|
WARNING: these functions do not ensure that the results are normalized. *)
|
|
|
|
|
|
|
|
val exp_sub : subst -> Exp.t -> Exp.t
|
|
|
|
|
|
|
|
val atom_sub : subst -> atom -> atom
|
|
|
|
|
|
|
|
val instr_sub : subst -> instr -> instr
|
|
|
|
(** apply [subst] to all id's in [instr], including LHS id's *)
|
|
|
|
|
|
|
|
val hpred_sub : subst -> hpred -> hpred
|
|
|
|
|
|
|
|
(** {2 Functions for replacing occurrences of expressions.} *)
|
|
|
|
|
|
|
|
val atom_replace_exp : (Exp.t * Exp.t) list -> atom -> atom
|
|
|
|
|
|
|
|
val hpred_replace_exp : (Exp.t * Exp.t) list -> hpred -> hpred
|
|
|
|
|
|
|
|
(** {2 Functions for constructing or destructing entities in this module} *)
|
|
|
|
|
|
|
|
val exp_get_offsets : Exp.t -> offset list
|
|
|
|
(** Compute the offset list of an expression *)
|
|
|
|
|
|
|
|
val exp_add_offsets : Exp.t -> offset list -> Exp.t
|
|
|
|
(** Add the offset list to an expression *)
|
|
|
|
|
|
|
|
val sigma_to_sigma_ne : hpred list -> (atom list * hpred list) list
|
|
|
|
|
|
|
|
val hpara_instantiate : hpara -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list
|
|
|
|
(** [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1],
|
|
|
|
[e2] and [elist]. If [para = lambda (x, y, xs). exists zs. b],
|
|
|
|
then the result of the instantiation is [b\[e1 / x, e2 / y, elist / xs, _zs'/ zs\]]
|
|
|
|
for some fresh [_zs'].*)
|
|
|
|
|
|
|
|
val hpara_dll_instantiate :
|
|
|
|
hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list
|
|
|
|
(** [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell],
|
|
|
|
[blink], [flink], and [elist]. If [para = lambda (x, y, z, xs). exists zs. b],
|
|
|
|
then the result of the instantiation is
|
|
|
|
[b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ zs\]]
|
|
|
|
for some fresh [_zs'].*)
|
|
|
|
|
|
|
|
val custom_error : Pvar.t
|