package mopsa
Install
Dune Dependency
Authors
Maintainers
Sources
md5=fdee20e988343751de440b4f6b67c0f4
sha512=f5cbf1328785d3f5ce40155dada2d95e5de5cce4f084ea30cfb04d1ab10cc9403a26cfb3fa55d0f9da72244482130fdb89c286a9aed0d640bba46b7c00e09500
doc/core/Core/All/index.html
Module Core.All
Source
include module type of struct include Ast.Semantic end
include module type of struct include Ast.Constant end
type constant = Ast.Constant.constant = ..
Extensible constants
compare_constant c1 c2
provides a total order between any pair c1
and c2
of registered constants
val pp_constant : Stdlib.Format.formatter -> constant -> unit
pp_constant fmt c
pretty-prints a registered constant c
with formatter fmt
Registration
val register_constant : constant Mopsa_utils.TypeExt.info -> unit
register_constant info
registers a new constant with a comparison function info.compare
and a pretty-printer info.print
val register_constant_compare : constant Mopsa_utils.TypeExt.compare -> unit
register_constant_compare compare
registers a new comparison function for constants
val register_constant_pp : constant Mopsa_utils.TypeExt.print -> unit
register_constant_compare compare
registers a new pretty-printer for constants
Common constants
include module type of struct include Ast.Expr end
type expr_kind = Ast.Expr.expr_kind = ..
Extensible type of expression kinds
type expr = Ast.Expr.expr = {
ekind : expr_kind;
(*kind of the expression
*)etyp : Ast.Typ.typ;
(*type of the expression
*)erange : Mopsa_utils.Location.range;
(*location range of the expression
*)etrans : expr Ast.Semantic.SemanticMap.t;
(*translations of the expression into other semantics
*)ehistory : expr list;
(*History of preceding evaluations of the expression
*)
}
Expressions
compare_expr e1 e2
implements a total order between expressions
val pp_expr : Stdlib.Format.formatter -> expr -> unit
pp_expr fmt e
pretty-prints expression e
with format fmt
val etyp : expr -> Ast.Typ.typ
Get the type of an expression
val erange : expr -> Mopsa_utils.Location.range
Get the location of an expression
val etrans : expr -> expr Ast.Semantic.SemanticMap.t
Get the translation map of an expression
val mk_expr :
?etyp:Ast.Typ.typ ->
?etrans:expr Ast.Semantic.SemanticMap.t ->
?ehistory:expr list ->
expr_kind ->
Mopsa_utils.Location.range ->
expr
Construct an expression
val add_expr_translation : Ast.Semantic.semantic -> expr -> expr -> expr
Add a translation of an expression
val get_expr_translations : expr -> expr Ast.Semantic.SemanticMap.t
Get all translations of an expression
val get_expr_translation : Ast.Semantic.semantic -> expr -> expr
Get the translation of an expression into a given semantic
Get the ancestor expression verifying a predicate
Registration
val register_expr : expr Mopsa_utils.TypeExt.info -> unit
register_expr info
registers new expressions with their comparison function info.compare
and pretty-printer info.print
val register_expr_compare : expr Mopsa_utils.TypeExt.compare -> unit
register_expr_compare compare
registers a new expression comparison
val register_expr_pp : expr Mopsa_utils.TypeExt.print -> unit
register_expr_compare compare
registers a new expression printer
Some common expressions
Variable expressions
type expr_kind +=
| E_var of Ast.Var.var * Ast.Var.mode option
(*optional access mode overloading the variable's access mode
*)
Variables
val mk_var :
Ast.Var.var ->
?mode:Ast.Var.mode option ->
Mopsa_utils.Location.range ->
expr
Create a variable expression
val var_mode : Ast.Var.var -> Ast.Var.mode option -> Ast.Var.mode
Get the overloaded access mode of a variable
Heap addresses expressions
type expr_kind +=
| E_addr of Ast.Addr.addr * Ast.Var.mode option
(*optional access mode overloading the address access mode
*)| E_alloc_addr of Ast.Addr.addr_kind * Ast.Var.mode
Heap addresses
val mk_addr :
Ast.Addr.addr ->
?etyp:Ast.Typ.typ ->
?mode:Ast.Var.mode option ->
Mopsa_utils.Location.range ->
expr
Create an address expression
val mk_alloc_addr :
?mode:Ast.Var.mode ->
Ast.Addr.addr_kind ->
Mopsa_utils.Location.range ->
expr
Create an allocation expression
Constant expressions
Constants
val mk_constant :
?etyp:Ast.Typ.typ ->
Ast.Constant.constant ->
Mopsa_utils.Location.range ->
expr
Create a constant expression
val mk_top : Ast.Typ.typ -> Mopsa_utils.Location.range -> expr
Create ⊤ expression of a given type
Unary expressions
Unary operator expressions
val mk_unop :
?etyp:Ast.Typ.typ ->
Ast.Operator.operator ->
expr ->
Mopsa_utils.Location.range ->
expr
Create a unary operator expression
val mk_not : expr -> Mopsa_utils.Location.range -> expr
mk_not e range
returns the negation of expression e
using the operator Operator.O_log_not
Binary expressions
Binary operator expressions
val mk_binop :
?etyp:Ast.Typ.typ ->
expr ->
Ast.Operator.operator ->
expr ->
Mopsa_utils.Location.range ->
expr
Create a binary operator expression
Expressions containers
module ExprSet = Ast.Expr.ExprSet
Sets of expression
module ExprMap = Ast.Expr.ExprMap
Maps of expressions
include module type of struct include Ast.Stmt end
type stmt_kind = Ast.Stmt.stmt_kind = ..
Extensible kinds of statements
type stmt = Ast.Stmt.stmt = {
skind : stmt_kind;
(*kind of the statement
*)srange : Mopsa_utils.Location.range;
(*location range of the statement
*)
}
Statements
val mk_stmt : stmt_kind -> Mopsa_utils.Location.range -> stmt
Create a statement
val srange : stmt -> Mopsa_utils.Location.range
Get the location range of a statement
val pp_stmt : Stdlib.Format.formatter -> stmt -> unit
Pretty-printer of statements
Registration
val register_stmt : stmt Mopsa_utils.TypeExt.info -> unit
register_stmt info
registers a new statement by registering its compare function info.compare
and pretty-printer info.print
val register_stmt_compare : stmt Mopsa_utils.TypeExt.compare -> unit
Register a comparison function for statements
val register_stmt_pp : stmt Mopsa_utils.TypeExt.print -> unit
Register a pretty-printer function for statements
Blocks
type block = stmt list
Blocks are sequences of statements
val pp_block : Stdlib.Format.formatter -> block -> unit
Pretty-printer for blocks
Common statements
type stmt_kind +=
| S_program of Ast.Program.program * string list option
(*Command-line arguments as given to Mopsa after
*)--
Programs
Assignments
val mk_assign :
Ast.Expr.expr ->
Ast.Expr.expr ->
Mopsa_utils.Location.range ->
stmt
mk_assign lhs rhs range
creates the assignment lhs = rhs;
Tests
val mk_assume : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmt
Create a test statement
type stmt_kind +=
| S_add of Ast.Expr.expr
(*Add a dimension to the environment
*)| S_remove of Ast.Expr.expr
(*Remove a dimension from the environment and invalidate all references to it
*)| S_invalidate of Ast.Expr.expr
(*Invalidate all references to a dimension without removing it
*)| S_rename of Ast.Expr.expr * Ast.Expr.expr
(*new
*)| S_forget of Ast.Expr.expr
(*Forget a dimension by putting ⊤ (all possible values) in it. Note that the dimension is not removed
*)| S_project of Ast.Expr.expr list
(*Project the environment on the given list of dimensions. All other dimensions are removed
*)| S_expand of Ast.Expr.expr * Ast.Expr.expr list
(*Expand a dimension into a list of other dimensions. The expanded dimension is untouched
*)| S_fold of Ast.Expr.expr * Ast.Expr.expr list
(*Fold a list of dimensions into a single one. The folded dimensions are removed
*)| S_block of stmt list * Ast.Var.var list
(*local variables declared within the block
*)| S_breakpoint of string
(*Trigger a breakpoint
*)
Dimensions
val mk_rename :
Ast.Expr.expr ->
Ast.Expr.expr ->
Mopsa_utils.Location.range ->
stmt
Utility functions to create various statements for dimension management
val mk_rename_var :
Ast.Var.var ->
Ast.Var.var ->
Mopsa_utils.Location.range ->
stmt
val mk_remove : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmt
val mk_remove_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmt
val mk_invalidate : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmt
val mk_invalidate_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmt
val mk_add : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmt
val mk_add_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmt
val mk_project : Ast.Expr.expr list -> Mopsa_utils.Location.range -> stmt
val mk_project_vars : Ast.Var.var list -> Mopsa_utils.Location.range -> stmt
val mk_forget : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmt
val mk_forget_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmt
val mk_expand :
Ast.Expr.expr ->
Ast.Expr.expr list ->
Mopsa_utils.Location.range ->
stmt
val mk_expand_var :
Ast.Var.var ->
Ast.Var.var list ->
Mopsa_utils.Location.range ->
stmt
val mk_fold :
Ast.Expr.expr ->
Ast.Expr.expr list ->
Mopsa_utils.Location.range ->
stmt
val mk_fold_var :
Ast.Var.var ->
Ast.Var.var list ->
Mopsa_utils.Location.range ->
stmt
val mk_breakpoint : string -> Mopsa_utils.Location.range -> stmt
Containers of statements
module StmtSet = Ast.Stmt.StmtSet
Sets of statements
module StmtMap = Ast.Stmt.StmtMap
Maps of statements
include module type of struct include Ast.Typ end
type typ = Ast.Typ.typ = ..
Extensible types
val pp_typ : Stdlib.Format.formatter -> typ -> unit
Pretty-print a type
Registration
val register_typ : typ Mopsa_utils.TypeExt.info -> unit
Register a new type
val register_typ_compare : typ Mopsa_utils.TypeExt.compare -> unit
Register a new type comparison
val register_typ_pp : typ Mopsa_utils.TypeExt.print -> unit
Register a new type pretty-printer
Common types
include module type of struct include Ast.Program end
type prog_kind = Ast.Program.prog_kind = ..
Extensible type of program kinds
type program = Ast.Program.program = {
prog_kind : prog_kind;
(*kind of the program
*)prog_range : Mopsa_utils.Location.range;
(*program location
*)
}
Programs
val pp_program : Stdlib.Format.formatter -> program -> unit
Pretty-printer for programs
Registration
val register_program : program Mopsa_utils.TypeExt.info -> unit
register_program info
registers a new program kind by registering its comparison function info.compare
and pretty-printer info.print
val register_program_compare : program Mopsa_utils.TypeExt.compare -> unit
Register a comparison function between programs
val register_program_pp : program Mopsa_utils.TypeExt.print -> unit
Register a pretty-printer for programs
include module type of struct include Ast.Frontend end
type frontend = Ast.Frontend.frontend = {
lang : string;
(*Language of the frontend
*)parse : string list -> Ast.Program.program;
(*Parser function that translates a list of input source files into a Mopsa
*)Program.program
on_panic : exn -> string list -> float -> unit;
(*Function called when the analysis of a program terminates with an exception, and *when the output is in text mode*. Provided with the exception, list of files and analysis time. Current usecase: provide automated testcase reduction capabilities in the C analysis.
*)
}
Frontends
val register_frontend : frontend -> unit
Register a new frontend
val find_language_frontend : string -> frontend
Find the frontend of a given language
include module type of struct include Ast.Operator end
type operator = Ast.Operator.operator = ..
Extensible type of operators
val pp_operator : Stdlib.Format.formatter -> operator -> unit
Pretty-printer of operators
Registration
val register_operator : operator Mopsa_utils.TypeExt.info -> unit
register_operator info
registers a new operator by registering its compare function info.compare
and pretty-printer info.print
val register_operator_compare : operator Mopsa_utils.TypeExt.compare -> unit
Register a comparison function for operators
val register_operator_pp : operator Mopsa_utils.TypeExt.print -> unit
Register a pretty-printer for operators
Some common operators
type operator +=
| O_eq
(*equality ==
*)| O_ne
(*inequality !=
*)| O_lt
(*less than <
*)| O_le
(*less or equal <=
*)| O_gt
(*greater than >
*)| O_ge
(*greater or equal >=
*)| O_log_not
(*logical negation
*)| O_log_or
(*logical disjunction ||
*)| O_log_and
(*logical conjunction &&
*)| O_log_xor
(*logical strict disjonction xor
*)| O_cast
(*type cast
*)
Common operators
val is_comparison_op : operator -> bool
Test whether an operator is a comparison operator
val is_logic_op : operator -> bool
Test whether an is a logical operator
include module type of struct include Ast.Var end
Access modes
type var_kind = Ast.Var.var_kind = ..
Extensible kind of variables
type mode = Ast.Var.mode =
Access mode of a variable
val pp_mode : Stdlib.Format.formatter -> mode -> unit
Pretty-print an access mode
Variables
type var = Ast.Var.var = {
vname : string;
(*unique name of the variable
*)vkind : var_kind;
(*kind the variable
*)vtyp : Ast.Typ.typ;
(*type of the variable
*)vmode : mode;
(*access mode of the variable
*)vsemantic : Ast.Semantic.semantic;
(*semantic of the variable
*)
}
Variables
val vname : var -> string
Accessor function to the fields of a variable
val vtyp : var -> Ast.Typ.typ
val vsemantic : var -> Ast.Semantic.semantic
val mkv :
string ->
var_kind ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
var
Create a variable with a unique name, a kind, a type and an access mode (STRONG if not given)
val pp_var : Stdlib.Format.formatter -> var -> unit
Pretty-print a variable
Registration
val register_var : var Mopsa_utils.TypeExt.info -> unit
Register a new kind of variables
val register_var_compare : var Mopsa_utils.TypeExt.compare -> unit
Register a new variable comparison
val register_var_pp : var Mopsa_utils.TypeExt.print -> unit
Register a new variable pretty-printer
Common variables
type var_kind +=
| V_uniq of string * int
(*Unique ID
*)| V_tmp of int
(*Unique ID
*)| V_var_attr of var * string
(*Attribute
*)| V_range_attr of Mopsa_utils.Location.range * string
(*Attribute
*)
val mk_uniq_var : string -> int -> ?mode:mode -> Ast.Typ.typ -> var
Create a unique variable
val mk_fresh_uniq_var : string -> ?mode:mode -> Ast.Typ.typ -> unit -> var
Create a fresh variable with a fresh ID
val mktmp : ?typ:Ast.Typ.typ -> ?mode:mode -> unit -> var
Create a fresh temporary variable
val mk_attr_var :
var ->
string ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
var
mk_attr_var v a t
creates a variable representing an attribute a
of another variable v
val mk_range_attr_var :
Mopsa_utils.Location.range ->
string ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
var
mk_range_attr_var r a t
creates a variable representing an attribute a
of a program location r
Containers for variables
module VarSet = Ast.Var.VarSet
Sets of variables
module VarMap = Ast.Var.VarMap
Maps of variables
Deprecated
val get_orig_vname : var -> string
include module type of struct include Ast.Addr end
type addr_kind = Ast.Addr.addr_kind = ..
Kind of heap addresses, used to store extra information.
val addr_kind_pp_chain :
(Stdlib.Format.formatter -> addr_kind -> unit) Stdlib.ref
val pp_addr_kind : Stdlib.Format.formatter -> addr_kind -> unit
val register_addr_kind : addr_kind Mopsa_utils.TypeExt.info -> unit
type addr_partitioning = Ast.Addr.addr_partitioning = ..
Addresses are grouped by static criteria to make them finite
val addr_partitioning_compare_chain :
(addr_partitioning -> addr_partitioning -> int) Stdlib.ref
val addr_partitioning_pp_chain :
(Stdlib.Format.formatter -> addr_partitioning -> unit) Stdlib.ref
val pp_addr_partitioning_hash :
Stdlib.Format.formatter ->
addr_partitioning ->
unit
val pp_addr_partitioning :
?full:bool ->
Stdlib.Format.formatter ->
addr_partitioning ->
unit
Print a partitioning policy. Flag full
overloads the option opt_hash_addr
and displays the full partitioning string (not its hash, which is useful for creating unique names of addresses)
val pp_addr_partitioning_full :
Stdlib.Format.formatter ->
addr_partitioning ->
unit
val compare_addr_partitioning : addr_partitioning -> addr_partitioning -> int
val register_addr_partitioning :
addr_partitioning Mopsa_utils.TypeExt.info ->
unit
type addr = Ast.Addr.addr = {
addr_kind : addr_kind;
(*Kind of the address.
*)addr_partitioning : addr_partitioning;
(*Partitioning policy of the address
*)addr_mode : Ast.Var.mode;
(*Assignment mode of address (string or weak)
*)
}
Heap addresses.
val pp_addr : Stdlib.Format.formatter -> addr -> unit
val addr_uniq_name : addr -> string
Get the unique name of an address. This is safer and faster than calling Format.asprintf "%s" pp_addr a
when opt_hash_addr
is set.
val addr_mode : addr -> Ast.Var.mode option -> Ast.Var.mode
Address variables
val mk_addr_attr : addr -> string -> Ast.Typ.typ -> Ast.Var.var
include module type of struct include Ast.Visitor end
type parts = Ast.Visitor.parts = {
exprs : Ast.Expr.expr list;
(*sub-expressions
*)stmts : Ast.Stmt.stmt list;
(*sub-statements
*)
}
Parts of a statement/expression
val structure_of_expr : Ast.Expr.expr -> Ast.Expr.expr structure
Get the structure of an expression
val structure_of_stmt : Ast.Stmt.stmt -> Ast.Stmt.stmt structure
Get the structure of a statement
val leaf : 'a -> 'a structure
Visitor for leaf statements/expressions that have no sub-elements
Registration
type 'a visit_info = 'a Ast.Visitor.visit_info = {
compare : 'a Mopsa_utils.TypeExt.compare;
(*Comparison function for
*)'a
print : 'a Mopsa_utils.TypeExt.print;
(*Pretty-printer for
*)'a'
visit : ('a -> 'a structure) -> 'a -> 'a structure;
(*Visitor for
*)'a
}
Registration descriptor for visitors
val register_expr_with_visitor : Ast.Expr.expr visit_info -> unit
Register an expression with its visitor
val register_expr_visitor :
((Ast.Expr.expr -> Ast.Expr.expr structure) ->
Ast.Expr.expr ->
Ast.Expr.expr structure) ->
unit
Register a visitor of an expression
val register_stmt_with_visitor : Ast.Stmt.stmt visit_info -> unit
Register a statement with its visitor
val register_stmt_visitor :
((Ast.Stmt.stmt -> Ast.Stmt.stmt structure) ->
Ast.Stmt.stmt ->
Ast.Stmt.stmt structure) ->
unit
Register a visitor of a statement
Visiting iterators
type 'a visit_action = 'a Ast.Visitor.visit_action =
Actions of a visiting iterator
val map_expr :
(Ast.Expr.expr -> Ast.Expr.expr visit_action) ->
(Ast.Stmt.stmt -> Ast.Stmt.stmt visit_action) ->
Ast.Expr.expr ->
Ast.Expr.expr
map_expr fe fs e
transforms the expression e
into a new one by applying visitor action fe
and fs
on its sub-expression and sub-statements respectively
val map_stmt :
(Ast.Expr.expr -> Ast.Expr.expr visit_action) ->
(Ast.Stmt.stmt -> Ast.Stmt.stmt visit_action) ->
Ast.Stmt.stmt ->
Ast.Stmt.stmt
Similar to map_expr
but on statements
val fold_expr :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Expr.expr ->
'a
fold_expr fe fs e
folds the accumulated result of visitors fe
and fs
on the structure of expression e
val fold_stmt :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Stmt.stmt ->
'a
Similar to fold_expr
but on statements
val fold_map_expr :
('a -> Ast.Expr.expr -> ('a * Ast.Expr.expr) visit_action) ->
('a -> Ast.Stmt.stmt -> ('a * Ast.Stmt.stmt) visit_action) ->
'a ->
Ast.Expr.expr ->
'a * Ast.Expr.expr
Combination of map and fold for expressions
val fold_map_stmt :
('a -> Ast.Expr.expr -> ('a * Ast.Expr.expr) visit_action) ->
('a -> Ast.Stmt.stmt -> ('a * Ast.Stmt.stmt) visit_action) ->
'a ->
Ast.Stmt.stmt ->
'a * Ast.Stmt.stmt
Combination of map and fold for statements
val exists_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
bool
val for_all_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
bool
val exists_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
bool
val for_all_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
bool
val exists_child_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
bool
val for_all_child_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
bool
val exists_child_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
bool
val for_all_child_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
bool
Utility functions
val is_leaf_expr : Ast.Expr.expr -> bool
Test whether an expression is a leaf expression
val is_atomic_expr : Ast.Expr.expr -> bool
Test whether an expression has no sub-statement
val is_atomic_stmt : Ast.Stmt.stmt -> bool
Test whether a statement has no sub-statement
val expr_vars : Ast.Expr.expr -> Ast.Var.var list
Get all variables present in an expression
val stmt_vars : Ast.Stmt.stmt -> Ast.Var.var list
Get all variables present in a statement
val is_var_in_expr : Ast.Var.var -> Ast.Expr.expr -> bool
Check whether a variable appears in an expression
val is_var_in_stmt : Ast.Var.var -> Ast.Stmt.stmt -> bool
Check whether a variable appears in a statement
Deprecated
val fold_sub_expr :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Expr.expr ->
'a
include module type of struct include Alarm end
Checks
**********
Domains can add new checks by extending the type check
and registering them using register_check
. Note that checks should be simple variant constructs without any argument.
val register_check :
((Stdlib.Format.formatter -> check -> unit) ->
Stdlib.Format.formatter ->
check ->
unit) ->
unit
Register a check with its printer
Alarms
**********
Alarms are issues related to a check in a given range and a given callstack. Domains can add new kinds of alarms to store information related to the issue, such suspect values that raised the alarm. Nevertheless, domains can use the generic alarm A_generic of check
if they don't have addition static information to attach to the alarm.
type alarm = Alarm.alarm = {
alarm_kind : alarm_kind;
alarm_check : check;
alarm_range : Mopsa_utils.Location.range;
alarm_callstack : Mopsa_utils.Callstack.callstack;
}
val mk_alarm :
alarm_kind ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
alarm
Create an alarm
Return the range of an alarm
Return the callstack of an alarm
Compare two kinds of alarms
Print an alarm kind
Join two alarm kinds by merging the static information attached to them
val register_alarm_compare :
((alarm_kind -> alarm_kind -> int) -> alarm_kind -> alarm_kind -> int) ->
unit
Register a comparison function for alarms
val register_alarm_pp :
((Stdlib.Format.formatter -> alarm_kind -> unit) ->
Stdlib.Format.formatter ->
alarm_kind ->
unit) ->
unit
Register a print function for alarms
Register a function giving the check of an alarm
val register_alarm_join :
((alarm_kind -> alarm_kind -> alarm_kind option) ->
alarm_kind ->
alarm_kind ->
alarm_kind option) ->
unit
Register a join function for alarms
type alarm_info = Alarm.alarm_info = {
check : (alarm_kind -> check) -> alarm_kind -> check;
compare : (alarm_kind -> alarm_kind -> int) -> alarm_kind -> alarm_kind -> int;
print : (Stdlib.Format.formatter -> alarm_kind -> unit) -> Stdlib.Format.formatter -> alarm_kind -> unit;
join : (alarm_kind -> alarm_kind -> alarm_kind option) -> alarm_kind -> alarm_kind -> alarm_kind option;
}
Registration record for a new kind of alarms
Register a new kind of alarms
Diagnostic
**************
A diagnostic gives the status of all alarms raised at the program location for the same check
module AlarmSet = Alarm.AlarmSet
Set of alarms
Kind of a diagnostic
type 'a diagnostic_ = 'a Alarm.diagnostic_ = {
diag_range : Mopsa_utils.Location.range;
diag_check : check;
diag_kind : diagnostic_kind;
diag_alarms : AlarmSet.t;
diag_callstack : 'a;
}
val mk_safe_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check is safe
Create a diagnostic that says that a check is unsafe
val mk_warning_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check maybe unsafe
val mk_unreachable_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check is unreachable
Print a diagnostic kind
Print a diagnostic
Check whether a diagnostic is covered by another
Compute the union of two diagnostics
Compute the intersection of two diagnostics
Add an alarm to a diagnostic
Compare two diagnostics
Soundness assumption
************************
When a domain can't ensure total soundness when analyzing a piece of code, it can emit assumptions under which the result is still sound.
type assumption_scope = Alarm.assumption_scope =
| A_local of Mopsa_utils.Location.range
(*Local assumptions concern a specific location range in the program
*)| A_global
(*Global assumptions can concern the entire program
*)
Scope of an assumption
Domains can add new kinds of assumptions by extending the type assumption_kind
Generic assumptions for specifying potential unsoundness due to unsupported statements/expressions
type assumption = Alarm.assumption = {
assumption_scope : assumption_scope;
assumption_kind : assumption_kind;
}
Register a new kind of assumptions
Print an assumption kind
Print an assumption
Compare two assumption kinds
Compare two assumptions
Create a global assumption
Create a local assumption
Analysis report
*******************
Alarms are organized in a report that maps each range and each check to a diagnostic. A report also contains the set of soundness assumptions made by the domains.
module RangeMap = Alarm.RangeMap
module RangeCallStackMap = Alarm.RangeCallStackMap
module CheckMap = Alarm.CheckMap
module AssumptionSet = Alarm.AssumptionSet
type report = Alarm.report = {
report_diagnostics : diagnostic CheckMap.t RangeCallStackMap.t;
report_assumptions : AssumptionSet.t;
}
Checks whether a report is safe, i.e. it doesn't contain an error or a warning
subset_report r1 r2
checks whether report r1
is included in r2
filter_report p r
keeps only diagnostics in report r
that verify predicate p
add_alarm a r
adds alarm a
to a report r
. If a diagnostic exists for the same range and the same check as a
, join_diagnostic
is used to join it with an error diagnostic containing a
.
set_diagnostic d r
adds diagnostic d
to r
. Any existing diagnostic for the same range and the same check as d
is removed.
add_diagnostic d r
adds diagnostic d
to r
. If a diagnostic exists for the same range and the same check as d
, join_diagnostic
is used to join it with d
.
Remove a diagnostic from a report
val find_diagnostic :
(Mopsa_utils.Location.range * Mopsa_utils.Callstack.callstack) ->
check ->
report ->
diagnostic
find_diagnostic range chk r
finds the diagnostic of check chk
at location range
in report r
Check whether any diagnostic verifies a predicate
Check whether all diagnostics verify a predicate
module RangeDiagnosticWoCsMap = Alarm.RangeDiagnosticWoCsMap
module CallstackSet = Alarm.CallstackSet
Set of callstacks
val group_diagnostics :
diagnostic CheckMap.t RangeCallStackMap.t ->
CallstackSet.t RangeDiagnosticWoCsMap.t
Group diagnostics by their range and diagnostic kind
Add an assumption to a report
Add a global assumption to a report
Add a local assumption to a report
val map2zo_report :
(diagnostic -> diagnostic) ->
(diagnostic -> diagnostic) ->
(diagnostic -> diagnostic -> diagnostic) ->
report ->
report ->
report
val fold2zo_report :
(diagnostic -> 'b -> 'b) ->
(diagnostic -> 'b -> 'b) ->
(diagnostic -> diagnostic -> 'b -> 'b) ->
report ->
report ->
'b ->
'b
val exists2zo_report :
(diagnostic -> bool) ->
(diagnostic -> bool) ->
(diagnostic -> diagnostic -> bool) ->
report ->
report ->
bool
include module type of struct include Context end
Key to access an element in the context
The context
mem_ctx k ctx
returns true
when an element at key k
is in the context ctx
.
find_ctx k ctx
returns the element at key k
in the context ctx
. Raises Not_found
if no element is found.
find_ctx k ctx
returns the element of the key k
in the context ctx
. Returns None
if no element is found.
add_ctx k v ctx
add element v
at key k
in the context ctx
. The previous element is overwritten if present.
add_ctx k v ctx
removes the element at key k
in the context ctx
. If key k
was not in ctx
, ctx
is returned unchanged.
Print a context
type ctx_pool = Context.ctx_pool = {
ctx_pool_equal : 'a 'v 'w. ('a, 'v) ctx_key -> ('a, 'w) ctx_key -> ('v, 'w) Mopsa_utils.Eq.eq option;
ctx_pool_print : 'a 'v. (Print.printer -> 'a -> unit) -> Stdlib.Format.formatter -> ('a, 'v) ctx_key -> 'v -> unit;
}
Pool registered keys
type ctx_info = Context.ctx_info = {
ctx_equal : 'a 'v 'w. ctx_pool -> ('a, 'v) ctx_key -> ('a, 'w) ctx_key -> ('v, 'w) Mopsa_utils.Eq.eq option;
ctx_print : 'a 'v. ctx_pool -> (Print.printer -> 'a -> unit) -> Stdlib.Format.formatter -> ('a, 'v) ctx_key -> 'v -> unit;
}
Registration information for a new key
Generate a new key
Key for storing the callstack
val bind :
('a Cases.case -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases
val (>>=) :
('a, 'b) Cases.cases ->
('b Cases.case -> 'a Flow.flow -> ('a, 'c) Cases.cases) ->
('a, 'c) Cases.cases
val bind_opt :
('a Cases.case -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases option
val (>>=?) :
('a, 'b) Cases.cases ->
('b Cases.case -> 'a Flow.flow -> ('a, 'c) Cases.cases option) ->
('a, 'c) Cases.cases option
val bind_result :
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases
val (>>$) :
('a, 'b) Cases.cases ->
('b -> 'a Flow.flow -> ('a, 'c) Cases.cases) ->
('a, 'c) Cases.cases
val bind_result_opt :
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases option
val (>>$?) :
('a, 'b) Cases.cases ->
('b -> 'a Flow.flow -> ('a, 'c) Cases.cases option) ->
('a, 'c) Cases.cases option
val bind_list :
'a list ->
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
'b Flow.flow ->
('b, 'c list) Cases.cases
val bind_list_opt :
'a list ->
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
'b Flow.flow ->
('b, 'c list) Cases.cases option
val (>>%?) :
'a Post.post ->
('a Flow.flow -> ('a, 'b) Cases.cases option) ->
('a, 'b) Cases.cases option
include module type of struct include Path end
module PathMap = Path.PathMap
module PathSet = Path.PathSet
include module type of struct include Change end
Join two changes
val concat_change_map :
change Path.PathMap.t ->
change Path.PathMap.t ->
change Path.PathMap.t
val add_stmt_to_change_map :
Ast.Stmt.stmt ->
Path.PathMap.key ->
change Path.PathMap.t ->
change Path.PathMap.t
Generic merge
*****************
type change_vars = Change.change_vars = {
modified : Ast.Var.VarSet.t;
removed : Ast.Var.VarSet.t;
}
Change of a statement in terms of modified and removed variables
val get_stmt_change_vars :
custom:(Ast.Stmt.stmt -> change_vars option) ->
Ast.Stmt.stmt ->
change_vars
Get the changes of a statement
val apply_change_vars :
change_vars ->
add:(Ast.Var.VarSet.elt -> 'b -> 'a -> 'a) ->
remove:(Ast.Var.VarSet.elt -> 'a -> 'a) ->
find:(Ast.Var.VarSet.elt -> 'a -> 'b) ->
'a ->
'a ->
'a
Apply changes on an abstract element
val generic_merge :
add:(Ast.Var.VarSet.elt -> 'a -> 'b -> 'b) ->
find:(Ast.Var.VarSet.elt -> 'b -> 'a) ->
remove:(Ast.Var.VarSet.elt -> 'b -> 'b) ->
?custom:(Ast.Stmt.stmt -> change_vars option) ->
('b * change) ->
('b * change) ->
'b * 'b
Generic merge operator for non-relational domains
include module type of struct include Query end
Extensible type of queries
val join_query :
?ctx:'a Context.ctx option ->
?lattice:'a Lattice.lattice option ->
('a, 'r) query ->
'r ->
'r ->
'r
Join two queries
val meet_query :
?ctx:'a Context.ctx option ->
?lattice:'a Lattice.lattice option ->
('a, 'r) query ->
'r ->
'r ->
'r
Meet two queries
Registration
****************
type query_pool = Query.query_pool = {
pool_join : 'a 'r. ('a, 'r) query -> 'r -> 'r -> 'r;
pool_meet : 'a 'r. ('a, 'r) query -> 'r -> 'r -> 'r;
}
Pool of registered queries
type query_info = Query.query_info = {
join : 'a 'r. query_pool -> ('a, 'r) query -> 'r -> 'r -> 'r;
meet : 'a 'r. query_pool -> ('a, 'r) query -> 'r -> 'r -> 'r;
}
Registraction info for new queries
Register a new query
type lattice_query_pool = Query.lattice_query_pool = {
pool_join : 'a 'r. 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
pool_meet : 'a 'r. 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
}
Pool of registered lattice queries. Lattice queries are queries that return elements of the global abstract state lattice. Join/meet operators are enriched with the lattice and the context so that we can compute join/meet over the abstract elements.
type lattice_query_info = Query.lattice_query_info = {
join : 'a 'r. lattice_query_pool -> 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
meet : 'a 'r. lattice_query_pool -> 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
}
Registration info for new lattice queries
Register a new lattice query
Common queries
******************
type query +=
| Q_defined_variables : string option -> ('a, Ast.Var.var list) query
(*Extract the list of defined variables, in a given function call site, or in all scopes
*)| Q_allocated_addresses : ('a, Ast.Addr.addr list) query
(*Query to extract the list of addresses allocated in the heap
*)| Q_variables_linked_to : Ast.Expr.expr -> ('a, Ast.Var.VarSet.t) query
(*Query to extract the auxiliary variables related to an expression
*)
include module type of struct include Token end
Flow tokens are used to distinguish between different control flows
Register a new token with its compare and print functions
include module type of struct include Ast.Semantic end
val pp_semantic : Stdlib.Format.formatter -> semantic -> unit
val any_semantic : semantic
val is_any_semantic : semantic -> bool
module SemanticSet = Ast.Semantic.SemanticSet
module SemanticMap = Ast.Semantic.SemanticMap
include module type of struct include Route end
type route = Route.route =
| Below of domain
(*Sub-tree below a domain
*)| Semantic of Ast.Semantic.semantic
(*Sub-tree identified by a semantic
*)
Routes
module DomainSet = Route.DomainSet
Routing table providing the domains that are part of a route
Empty routing table
Resolve a route into domains
Add a route between a route and a domain
Add a set of routing_table linking a route and a set of domains
Get all routing_table in a routing table
Join two routing_table table
Print a routing table
include module type of struct include Lattice end
Signature of a lattice module.
type 'a lattice = 'a Lattice.lattice = {
bottom : 'a;
top : 'a;
is_bottom : 'a -> bool;
subset : 'a Context.ctx -> 'a -> 'a -> bool;
join : 'a Context.ctx -> 'a -> 'a -> 'a;
meet : 'a Context.ctx -> 'a -> 'a -> 'a;
widen : 'a Context.ctx -> 'a -> 'a -> 'a;
merge : 'a -> ('a * Change.change_map) -> ('a * Change.change_map) -> 'a;
print : Print.printer -> 'a -> unit;
}
Lattice operators
include module type of struct include Id end
type witness = Id.witness = {
eq : 'a 'b. 'a id -> 'b id -> ('a, 'b) Mopsa_utils.Eq.eq option;
}
type witness_chain = Id.witness_chain = {
eq : 'a 'b. witness -> 'a id -> 'b id -> ('a, 'b) Mopsa_utils.Eq.eq option;
}
Equality witness of an identifier
Register a new descriptor
Equality witness of identifiers
Generator of a new domain identifier
Generator of a new identifier for stateless domains
Generator of a new value identifier
include module type of struct include Manager end
Managers
type ('a, 't) man = ('a, 't) Manager.man = {
lattice : 'a Lattice.lattice;
(*Access to lattice operators on the toplevel abstract element
*)'a
.get : Token.token -> 'a Flow.flow -> ('a, 't) Cases.cases;
(*Returns the domain's abstract element
*)'t
. A disjunction of cases is returned when partitioning is used.set : Token.token -> 't -> 'a Flow.flow -> 'a Post.post;
(*Sets the domain's abstract element
*)'t
.exec : ?route:Route.route -> Ast.Stmt.stmt -> 'a Flow.flow -> 'a Post.post;
(*
*)man.exec stmt flow
executesstmt
inflow
and returns the post state.eval : ?route:Route.route -> ?translate:Ast.Semantic.semantic -> ?translate_when:(Ast.Semantic.semantic * (Ast.Expr.expr -> bool)) list -> Ast.Expr.expr -> 'a Flow.flow -> 'a Eval.eval;
(*man.eval expr flow
evaluatesexpr
inflow
and returns the result expression.There are two kinds of evaluations: within the same semantic (simplifications), or to another semantic (translations). Calling
*)man.eval expr flow
performs both kinds of evaluations. The resulte'
ofman.eval expr flow
is a simplification ofe
within the same semantic. To retrieve a translation to another semantic, one can use the?translate
parameter:man.eval expr flow ~translate:semantic
is a translation of the simplification ofe
insemantic
. A common use case is to translate expressions to Universal withman.eval expr flow ~translate:"Universal"
. It is possible to control when the translation is applied with?translate_when
.ask : 'r. ?route:Route.route -> ('a, 'r) Query.query -> 'a Flow.flow -> ('a, 'r) Cases.cases;
(*
*)man.ask query flow
performs a query to other domains. If no domain can answer the query,man.ask query flow
results in a runtime error.print_expr : ?route:Route.route -> 'a Flow.flow -> Print.printer -> Ast.Expr.expr -> unit;
(*
*)man.print_expr flow
is the expression printer for the type'a
.add_change : Ast.Stmt.stmt -> Path.path -> 'a Flow.flow -> Change.change_map -> Change.change_map;
(*Add a statement to the changes map.
*)
}
Managers provide access to full analyzer.
'a
is the type of the toplevel abstract element, and 't
is the type of local abstract element (that is, the type of the domain that calls the manager).
include module type of struct include Print end
Print objects
Symbols for printing maps, lists and sets
Structured print objects
type print_object = Print.print_object =
| Empty
| Bool of bool
| Int of Z.t
| Float of float
| String of string
| Var of Ast.Var.var
| Map of (print_object, print_object) map * symbols
| List of print_object list * symbols
| Set of print_object set * symbols
Printers
Printers encapsulate the structured objects to print along the history of printed expression
Get the structured print object of a printer
Get the expressions that were already printed
Mark an expression as printed
Check whether an expression was already printed
Print paths
type print_selector = Print.print_selector =
| Key of string
| Index of int
| Obj of print_object
Selectors of print objects
Path of a print object
find_print_object path obj
returns the object placed at path
in obj
match_print_object_keys re obj
slices obj
to paths containing keys that match re
Generic print functions
pprint ~path:p printer o
prints object o
at path p
in printer
.
pbox f x
returns a boxed object created by f
when applied to x
. It is equivalent to
let printer = empty_printer () in
f printer x;
get_printed_object printer
fbox fmt
returns a string object of a formatted value
sprint f x
returns the string representing the boxed object pbox f x
fkey fmt
returns a key selector with a formatted string
pkey f x
returns a key selector with a printed string
Typed print functions
Print a string object
Print a boolean object
Print an integer object
Print an integer object
Print a float object
Print a variable
val pp_list :
?path:print_path ->
?lopen:string ->
?lsep:string ->
?lclose:string ->
(printer -> 'a -> unit) ->
printer ->
'a list ->
unit
pp_list ~path:p f printer l
prints a list l
at path p
by boxing f
on every element of l
val pp_obj_list :
?path:print_path ->
?lopen:string ->
?lsep:string ->
?lclose:string ->
printer ->
print_object list ->
unit
pp_obj_list ~path:p printer l
prints a list of objects at path p
. Useful for printing heterogenous lists.
val pp_map :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
(printer -> 'k -> unit) ->
(printer -> 'v -> unit) ->
printer ->
('k * 'v) list ->
unit
pp_smap ~path:p fk fv printer l
prints a map from a list l
of pairs of keys and values. Keys are boxed with function fk
and values with function fv
.
val pp_mapi :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
(printer -> 'k -> unit) ->
(printer -> ('k * 'v) -> unit) ->
printer ->
('k * 'v) list ->
unit
val pp_obj_map :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
printer ->
(print_object * print_object) list ->
unit
pp_obj_smap ~path:p printer l
prints a map from a list of pairs of print objects
val pp_obj_set :
?path:print_path ->
?sopen:string ->
?ssep:string ->
?sclose:string ->
printer ->
print_object set ->
unit
pp_obj_set ~path:p printer l
prints a set of objects at path p
. Useful for printing heterogenous sets.
val pp_set :
?path:print_path ->
?sopen:string ->
?ssep:string ->
?sclose:string ->
(printer -> 'a -> unit) ->
printer ->
'a set ->
unit
pp_set ~path:p f printer l
prints a set from a list l
at path p
by boxing f
on every element of l
Format
Pretty-print a printer objct
Pretty-print the printer output in a format string
Convert a printer function into a format function
val unformat :
?path:print_path ->
(Stdlib.Format.formatter -> 'a -> unit) ->
printer ->
'a ->
unit
Convert a format function into a printer
JSON
Convert a printer object to JSON
Convert JSON to a printer object
include module type of struct include Avalue end
type avalue_pool = Avalue.avalue_pool = {
pool_typ : 'v. 'v avalue_kind -> Ast.Typ.typ;
pool_bottom : 'v. 'v avalue_kind -> 'v;
pool_top : 'v. 'v avalue_kind -> 'v;
pool_join : 'v. 'v avalue_kind -> 'v -> 'v -> 'v;
pool_meet : 'v. 'v avalue_kind -> 'v -> 'v -> 'v;
pool_compare : 'v 'w. 'v avalue_kind -> 'v -> 'w avalue_kind -> 'w -> int;
pool_print : 'v. 'v avalue_kind -> Stdlib.Format.formatter -> 'v -> unit;
}
type avalue_info = Avalue.avalue_info = {
typ : 'v. avalue_pool -> 'v avalue_kind -> Ast.Typ.typ;
bottom : 'v. avalue_pool -> 'v avalue_kind -> 'v;
top : 'v. avalue_pool -> 'v avalue_kind -> 'v;
join : 'v. avalue_pool -> 'v avalue_kind -> 'v -> 'v -> 'v;
meet : 'v. avalue_pool -> 'v avalue_kind -> 'v -> 'v -> 'v;
compare : 'v 'w. avalue_pool -> 'v avalue_kind -> 'v -> 'w avalue_kind -> 'w -> int;
print : 'v. avalue_pool -> 'v avalue_kind -> Stdlib.Format.formatter -> 'v -> unit;
}
include module type of struct include Utils end
val exec_cleaner :
Ast.Stmt.stmt ->
('a, 'b) Manager.man ->
'a Flow.flow ->
('a, unit) Cases.cases
val assume :
Ast.Expr.expr ->
?route:Route.route ->
?translate:Ast.Semantic.semantic ->
fthen:('a Flow.flow -> ('a, 'b) Cases.cases) ->
felse:('a Flow.flow -> ('a, 'b) Cases.cases) ->
?fboth:('a Flow.flow -> 'a Flow.flow -> ('a, 'b) Cases.cases) ->
?fnone:('a Flow.flow -> 'a Flow.flow -> ('a, 'b) Cases.cases) ->
?eval:bool ->
('a, 'c) Manager.man ->
'a Flow.flow ->
('a, 'b) Cases.cases
val switch :
(Ast.Expr.expr list * ('a Flow.flow -> ('a, 'r) Cases.cases)) list ->
?route:Route.route ->
('a, 'b) Manager.man ->
'a Flow.flow ->
('a, 'r) Cases.cases
val map_env :
Token.token ->
('t -> 't) ->
('a, 't) Manager.man ->
'a Flow.flow ->
'a Post.post
val get_pair_fst :
('a, 'b * 'c) Manager.man ->
Token.token ->
'a Flow.flow ->
('a, 'b) Cases.cases
val set_pair_fst :
('a, 'b * 'c) Manager.man ->
Token.token ->
'b ->
'a Flow.flow ->
('a, unit) Cases.cases
val get_pair_snd :
('a, 'b * 'c) Manager.man ->
Token.token ->
'a Flow.flow ->
('a, 'c) Cases.cases
val set_pair_snd :
('a, 'b * 'c) Manager.man ->
Token.token ->
'c ->
'a Flow.flow ->
('a, unit) Cases.cases
val env_exec :
('a Flow.flow -> 'a Post.post) ->
'a Context.ctx ->
('a, 't) Manager.man ->
'a ->
'a
val ask_and_reduce_cases :
(('a, 'b) Query.query -> 'c -> ('d, 'b) Cases.cases) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'b
val ask_and_reduce_list :
(('a, 'b) Query.query -> 'c -> ('d * 'b) list) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'b
val ask_and_reduce :
(('a, 'b) Query.query -> 'c -> ('d, 'b) Cases.cases) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'b
val find_var_by_name :
?function_scope:string option ->
string ->
('a, 'b) Manager.man ->
'a Flow.flow ->
Ast.Var.var
val pp_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Var.var list ->
unit
val pp_vars_info_by_name :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
string list ->
unit
val pp_expr_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Expr.expr ->
unit
val pp_stmt_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Stmt.stmt ->
unit
include module type of struct include Marker end
type marker_info = Marker.marker_info = {
marker_name : string;
marker_print_name : (marker -> string) -> marker -> string;
marker_print : (Stdlib.Format.formatter -> marker -> unit) -> Stdlib.Format.formatter -> marker -> unit;
marker_compare : (marker -> marker -> int) -> marker -> marker -> int;
}