diff --git a/src/plugins/eva/contexts/abstract_context.ml b/src/plugins/eva/contexts/abstract_context.ml index 19ba4b09d2eab1ba3018b71d6d2d1b4a0d95572e..b93d201dfe43afc4f24b1af9968e75c19e4766e1 100644 --- a/src/plugins/eva/contexts/abstract_context.ml +++ b/src/plugins/eva/contexts/abstract_context.ml @@ -20,23 +20,41 @@ (* *) (**************************************************************************) +(** An abstract context can be used to transfer information from the state of + an abstract domain, in which an expression or lvalue is evaluated, to a + value abstraction, which interprets operations during this evaluation. + The context is built by the function [build_context] of abstract domains, + and passed as argument of most transfer functions from {!Abstract_value}. *) + open Eval module type S = sig - include Datatype.S + type t + + (** The default context used in a top abstract state, or if no domain has been + enabled — or no domain providing this context. *) val top : t - val is_included : t -> t -> bool - val join : t -> t -> t + + (** In a product of abstract domains, merges the context provided by the + abstract state of each domain. *) val narrow : t -> t -> t or_bottom end +(** Keys used to identify context modules. *) type 'c key = 'c Structure.Key_Context.key +(** Signature for a leaf module of context. *) module type Leaf = sig include S + + (** The key identifies the module and the type [t] of context. *) val key : t key end +(** Eva abstractions are divided between contexts, values, locations and domains. + Values and domains depend on contexts, and use this type to declare such + dependencies. In the standard case, a value or domain depends on a single + context module [Ctx] and uses [Leaf (module Ctx)] to declare this dependency. *) type 'c dependencies = | Leaf : (module Leaf with type t = 'c) -> 'c dependencies | Node : 'l dependencies * 'r dependencies -> ('l * 'r) dependencies diff --git a/src/plugins/eva/contexts/context_product.ml b/src/plugins/eva/contexts/context_product.ml index b1478d207f69bb46107a08c783704ccc9fcfb4ac..ad934208e87bb8fcc4fc4480a581f19e5ca6800c 100644 --- a/src/plugins/eva/contexts/context_product.ml +++ b/src/plugins/eva/contexts/context_product.ml @@ -21,9 +21,7 @@ (**************************************************************************) module Make (L : Abstract_context.S) (R : Abstract_context.S) = struct - include Datatype.Pair (L) (R) + type t = L.t * R.t let top = (L.top, R.top) - let join (l, r) (l', r') = (L.join l l', R.join r r') - let is_included (l, r) (l', r') = L.is_included l l' && R.is_included r r' let narrow (l, r) (l', r') = Eval.Bottom.zip (L.narrow l l') (R.narrow r r') end diff --git a/src/plugins/eva/contexts/unit_context.ml b/src/plugins/eva/contexts/unit_context.ml index d0039a3004f03af69fae2688fa0ced987659ab6d..86669eb7cde87661606d07dcea04d6b8780c0e7f 100644 --- a/src/plugins/eva/contexts/unit_context.ml +++ b/src/plugins/eva/contexts/unit_context.ml @@ -20,9 +20,7 @@ (* *) (**************************************************************************) -include Datatype.Unit +type t = unit let top = () -let is_included () () = true -let join () () = () let narrow () () = `Value () let key = Structure.Key_Context.create_key "Unit context" diff --git a/src/plugins/eva/values/abstract_value.ml b/src/plugins/eva/values/abstract_value.ml index ab72e136ec9c52b77176540c9d521e68a1c6b407..2f82d4852466d2fa7bb47e4a50974f7a5fc5bd59 100644 --- a/src/plugins/eva/values/abstract_value.ml +++ b/src/plugins/eva/values/abstract_value.ml @@ -46,12 +46,21 @@ type bound = Int of Integer.t | Float of float * fkind type pointer_comparison = Equality | Relation | Subtraction +(** Enriched context. + This record could easily be extended to contain more information about the + context in which an evaluation takes place, if the need arises. *) type 'a enriched = { from_domains : 'a } (** Signature of abstract numerical values. *) module type S = sig include Datatype.S + (** A numerical value abstraction can optionally require some context from + abstract domains. Most transfer functions take the context as argument; + it is provided by the abstract state in which operations are performed. + See {!Abstract_context} for more details about contexts. + For values that don't need context, this type can be defined as unit + and the context argument can be safely ignored. *) type context val pretty_typ: typ option -> t Pretty_utils.formatter