123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2021 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Queries to retrieve variable values during an interactive session *)openMopsa_utilsopenCore.AllopenFormatopenLocationopenCallstack(** {2 Debug queries} *)(** ***************** *)(* In order to retrieve structured information from the abstract environment,
each language should implement a handler for the query [Q_debug_variable_value].
The query [Q_debug_variable_value] retrieves the value of a given
variable as a [var_value] record, containing a textual representation of
the value, and a structural encoding of the eventual sub-values.
*)(** Value of a variable *)typevar_value={var_value:stringoption;(** Direct value of the variable *)var_value_type:typ;(** Type of the value *)var_sub_value:var_sub_valueoption;(** Sub-values of the variable *)}(** Sub-value of a variable *)andvar_sub_value=|Named_sub_valueof(string(** key *)*var_value(** value *))list(** Named sub-values are maps from field names to values *)|Indexed_sub_valueofvar_valuelist(** Indexed sub-values are arrays of values *)(** Query to retrieve the value of a given variable *)type('a,_)query+=Q_debug_variable_value:var->('a,var_value)querytype('a,_)query+=Q_debug_addr_value:addr->('a,var_value)querylet()=register_query{join=(letdoit:typear.query_pool->(a,r)query->r->r->r=funnextqueryab->matchquerywith|Q_debug_addr_valueaddr->assert(a.var_value=None&&b.var_value=None);letvar_sub_value=beginmatcha.var_sub_value,b.var_sub_valuewith|None,Somesb->Somesb|Somesa,None->Somesa|SomeIndexed_sub_valuela,SomeIndexed_sub_valuelb->Some(Indexed_sub_value(la@lb))|SomeNamed_sub_valuema,SomeNamed_sub_valuemb->Some(Named_sub_value(ma@mb))|_,_->assertfalseendin{var_value=None;var_value_type=T_any;var_sub_value}|_->next.pool_joinqueryabindoit);meet=(funnextqab->next.pool_meetqab);}(** Compare two var values *)letreccompare_var_valuev1v2=Compare.compose[(fun()->Compare.optioncomparev1.var_valuev2.var_value);(fun()->Compare.optioncompare_var_sub_valuev1.var_sub_valuev2.var_sub_value);](** Compare two var sub-values *)andcompare_var_sub_valuesv1sv2=matchsv1,sv2with|Named_sub_valuem1,Named_sub_valuem2->Compare.list(funx1x2->Compare.paircomparecompare_var_valuex1x2)m1m2|Indexed_sub_valuel1,Indexed_sub_valuel2->Compare.listcompare_var_valuel1l2|_->comparesv1sv2(** Print a key with its type *)letpp_key_with_typefmt(k,t)=matchtwith|T_any->pp_print_stringfmtk|_->Format.fprintffmt"%s : %a"kpp_typt(** Print a variable with its type *)letpp_var_with_typefmt(v,t)=matchtwith|T_any->pp_varfmtv|_->Format.fprintffmt"%a : %a"pp_varvpp_typt(** Print the value of a variable *)letrecpp_var_valuefmtv=pp_print_option(Debug.color_strDebug.blue)fmtv.var_value;matchv.var_sub_valuewith|None->()|Somesv->fprintffmt"@,@[<v2> %a@]"pp_var_sub_valuesv(** Print the values of sub-variables *)andpp_var_sub_valuefmt=function|Named_sub_valuel->fprintffmt"%a"(pp_print_list~pp_sep:(funfmt()->fprintffmt"@,")(funfmt(k,v)->fprintffmt"%a = %a"pp_key_with_type(k,v.var_value_type)pp_var_valuev))l|Indexed_sub_valuel->(* Group consecutive elements with the same value *)letrecgroup_by_value=function|[]->[]|(i,v)::tl->matchgroup_by_valuetlwith|[]->[(i,i,v)]|(a,b,w)::tl->ifcompare_var_valuevw=0then(i,b,v)::tlelse(i,i,v)::(a,b,w)::tlinList.mapi(funiv->(i,v))l|>group_by_value|>fprintffmt"%a"(pp_print_list~pp_sep:(funfmt()->fprintffmt"@,")(funfmt(i,j,v)->ifi=jthenfprintffmt"[%d] = %a"ipp_var_valuevelsefprintffmt"[%d-%d] = %a"ijpp_var_valuev))