123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467(*
Copyright 2013-2018 RIKEN
Copyright 2018-2025 Chiba Institude of Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)(* Author: Masatomo Hashimoto <m.hashimoto@stair.center> *)(* fact extractor *)moduleBinding=Diffast_misc.BindingmoduleAstml=Diffast_core.AstmlmoduleTriple=Diffast_core.TriplemoduleFact_base=Diffast_core.Fact_basemoduleCommon=Fortran_parsing.CommonmodulePinfo=Fortran_parsing.PinfomoduleLabel=F_labelmoduleTree=F_treemoduleA=AstmlmoduleB=BindingmoduleF(L:Label.T)=structmoduleFB=Fact_base.F(L)openFBletgetlab=getlabletp_in_module=mkfres"inModule"letp_in_ext_function=mkfres"inFunctionExternalSubprogram"letp_in_ext_subroutine=mkfres"inSubroutineExternalSubprogram"letp_in_mod_function=mkfres"inFunctionModuleSubprogram"letp_in_mod_subroutine=mkfres"inSubroutineModuleSubprogram"letp_in_int_function=mkfres"inFunctionInternalSubprogram"letp_in_int_subroutine=mkfres"inSubroutineInternalSubprogram"letp_in_main_program=mkfres"inMainProgram"letp_in_block_data=mkfres"inBlockData"letp_in_stmt=mkfres"inStmt"letp_in_fragment=mkfres"inFragment"letp_in_execution_part=mkfres"inExecutionPart"letp_in_subprogram_part=mkfres"inSubprogramPart"letp_in_do_construct=mkfres"inDoConstruct"letp_in_case_construct=mkfres"inCaseConstruct"letp_in_forall_construct=mkfres"inForallConstruct"letp_in_if_construct=mkfres"inIfConstruct"letp_in_where_construct=mkfres"inWhereConstruct"letp_in_select_type_construct=mkfres"inSelectTypeConstruct"letp_in_associate_construct=mkfres"inAssociateConstruct"letp_in_block_construct=mkfres"inBlockConstruct"letp_in_critical_construct=mkfres"inCriticalConstruct"letp_in_derived_type_def=mkfres"inDerivedTypeDef"letp_in_interface_block=mkfres"inInterfaceBlock"letp_in_if_then_block=mkfres"inIfThenBlock"letp_in_else_block=mkfres"inElseBlock"letp_in_else_if_block=mkfres"inElseIfBlock"letp_in_where_block=mkfres"inWhereBlock"letp_in_case_block=mkfres"inCaseBlock"letp_in_type_guard_block=mkfres"inTypeGuardBlock"letp_in_do_block=mkfres"inDoBlock"letp_in_pp_branch=mkfres"inPpBranch"letp_in_pp_branch_do=mkfres"inPpBranchDo"letp_in_pp_branch_end_do=mkfres"inPpBranchEndDo"letp_in_pp_branch_if=mkfres"inPpBranchIf"letp_in_pp_branch_end_if=mkfres"inPpBranchEndIf"letp_in_pp_branch_forall=mkfres"inPpBranchForall"letp_in_pp_branch_end_forall=mkfres"inPpBranchEndForall"letp_in_pp_branch_where=mkfres"inPpBranchWhere"letp_in_pp_branch_end_where=mkfres"inPpBranchEndWhere"letp_in_pp_branch_select=mkfres"inPpBranchSelect"letp_in_pp_branch_end_select=mkfres"inPpBranchEndSelect"letp_in_pp_section_ifdef=mkfres"inPpSectionIfdef"letp_in_pp_section_ifndef=mkfres"inPpSectionIfndef"letp_in_pp_section_if=mkfres"inPpSectionIf"letp_in_pp_section_elif=mkfres"inPpSectionElif"letp_in_pp_section_else=mkfres"inPpSectionElse"letp_in_omp_construct=mkfres"inOmpConstruct"letp_in_acc_construct=mkfres"inAccConstruct"letp_in_container_unit=mkfres"inContainerUnit"letp_in_pu_or_fragment=mkfres"inProgramUnitOrFragment"letp_in_pu_or_sp=mkfres"inProgramUnitOrSubprogram"letp_name=mkfres"name"letp_label=mkfres"label"letp_slabel=mkfres"slabel"letp_regexp=mkfres"regexp"letp_value=mkfres"value"letp_variable=mkfres"variableName"letp_rank=mkfres"rank"letp_requires=mkfres"requires"letp_provides=mkfres"provides"letp_type_spec=mkfres"typeSpec"letp_path=mkfres"path"letp_body=mkfres"body"letnode_filteroptionsnd=(* filter out inactive nodes *)ifoptions#fact_restricted_flagthenletlab=getlabndinL.is_stmtlab||L.is_program_unitlab||L.is_case_constructlab||L.is_do_constructlab||L.is_forall_constructlab||L.is_if_constructlab||L.is_where_constructlab||L.is_derived_type_deflab||L.is_interface_blocklabelsetrueletnode_pair_filteroptionsnd1nd2=(node_filteroptionsnd1)&&(node_filteroptionsnd2)letname_sep_pat=Str.regexp_string";"letconv_pat=letpat_conv_tbl=[Str.regexp_string"\\(","(";Str.regexp_string"\\)",")";Str.regexp_string"\\|","|";]infunx->List.fold_left(funs(re,rpl)->Str.global_replacererpls)xpat_conv_tblletmkpatn="^"^(conv_pat(String.lowercase_asciin))^"$"letis_patx=String.containsx'|'letrechas_subprogramnd=ifL.is_subprogram(getlabnd)thentrueelseArray.existshas_subprogramnd#initial_childrenclassextractoroptionscache_pathtree=object(self)inheritextractor_baseoptionscache_pathtreeassupermethod!id="Fortran"method!mkextnamen=super#mkextname(String.lowercase_asciin)method!scanner_body_after_subscanndlabentity=ifnode_filteroptionsndthenbeginself#add(entity,p_is_a,mkfresnd#data#get_category);(* self#add (entity, p_file_digest, tree#encoded_source_digest); *)beginleta=(Obj.objnd#data#_annotation:Label.annotation)inLabel.Annotation.iter(function|Label.Annotation.Requirens->List.iter(funn->leten=self#mkextnameninself#add(en,p_is_a,Triple.c_external_name);self#add(en,p_name,mklitn);self#add(entity,p_requires,en))ns|Label.Annotation.Providens->List.iter(fun_n->List.iter(funn->leten=self#mkextnameninself#add(en,p_is_a,Triple.c_external_name);ifis_patnthenself#add(en,p_regexp,mklit(mkpatn))elseself#add(en,p_name,mklitn);self#add(entity,p_provides,en))(Str.splitname_sep_pat_n))ns|Label.Annotation.Specnspec->beginbegintryletspec=Pinfo.Name.Spec.get_data_object_specnspecinlettspec=spec#type_specinifPinfo.TypeSpec.is_resolvedtspecthenbeginlettspec_lit=mklit(Pinfo.TypeSpec.to_stringtspec)inself#add(entity,p_type_spec,tspec_lit)end;leta=spec#attrintryletrank_lit=mklit~ty:lit_ty_nn_int(string_of_inta#get_rank)inself#add(entity,p_rank,rank_lit)withFailure_->()withNot_found->()end;begintryletmnd=get_nearest_surrounding_xxxL.is_modulendinifPinfo.Name.Spec.is_publicnspecthenbegintryList.iter(funx->letn=Tree.make_local_name(L.get_name(getlabmnd))xinleten=self#mkextnameninself#add(en,p_is_a,Triple.c_external_name);self#add(en,p_name,mklitn);self#add(entity,p_provides,en))(Str.splitname_sep_pat(L.get_namelab))with_->()endwith_->()endend)aend;ifL.is_program_unitlab||L.is_programlab||L.is_fragmentlab||L.is_subroutinelab||L.is_functionlab||(L.is_pp_branchlab&&has_subprogramnd)thenbeginletfent=letfid=nd#data#source_fidiniffid=""thenself#fileentityelseTriple.mkent(Triple.___make_file_entity(Triple.get_enc_stroptions())fid)inself#add(entity,p_in_file,fent);self#set_versionentityend;beginmatchL.to_taglabwith|"PpDefine",attrs->begintryletbody=List.assoc"body"attrsinself#add(entity,p_body,mklitbody)withNot_found->()end|_->()end;begintryletpath=L.get_pp_include_pathlabinself#add(entity,p_path,mklitpath)withNot_found->()end;begintryList.iter(funn->self#add(entity,p_name,mklitn))(Str.splitname_sep_pat(L.get_namelab))withNot_found->()end;begintryself#add(entity,p_label,mklit(L.get_labellab))withNot_found->()end;begintryself#add(entity,p_slabel,mklit(L.get_stmt_labellab))withNot_found->()end;begintryself#add(entity,p_variable,mklit(L.get_varlab))withNot_found->()end;letremove_kinds=tryletp=String.indexs'_'inString.subs0pwithNot_found->sinletconv_ints=remove_kindsinletconv_reals=lets'=remove_kindsinString.map(function|'D'|'d'->'e'|x->x)s'inbegintryletty,v=ifL.is_int_literallabthenlit_ty_int,conv_int(L.get_valuelab)elseifL.is_real_literallabthenlit_ty_real,conv_real(L.get_valuelab)elselit_ty_string,(L.get_valuelab)inself#add(entity,p_value,mklit~ty:tyv)withNot_found->()end;(*let is_included =
try
nd#data#src_loc.Loc.filename <> tree#root#data#src_loc.Loc.filename
with
_ -> false
in
let loc_opt =
if is_included then
Some nd#data#src_loc
else
None
in*)[%debug_log"nd=%s"nd#to_string];beginletb=nd#data#bindinginmatchbwith|B.Def(bid,_,_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|B.Use(bid,(*loc_opt*)_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|_->()end;beginList.iter(funb->matchbwith|B.Def(bid,_,_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|B.Use(bid,(*loc_opt*)_)->[%debug_log"%a"B.ID.psbid];self#add(entity,p_binding,self#mkbinding(*~loc_opt*)bid)|_->())nd#data#bindingsend;self#add_surrounding_xxxL.is_fragmentndentityp_in_fragment;self#add_surrounding_xxxL.is_execution_partndentityp_in_execution_part;self#add_surrounding_xxxL.is_subprogram_partndentityp_in_subprogram_part;self#add_surrounding_xxxL.is_modulendentityp_in_module;self#add_surrounding_xxxL.is_main_programndentityp_in_main_program;self#add_surrounding_xxxL.is_ext_functionndentityp_in_ext_function;self#add_surrounding_xxxL.is_ext_subroutinendentityp_in_ext_subroutine;self#add_surrounding_xxxL.is_int_functionndentityp_in_int_function;self#add_surrounding_xxxL.is_int_subroutinendentityp_in_int_subroutine;self#add_surrounding_xxxL.is_mod_functionndentityp_in_mod_function;self#add_surrounding_xxxL.is_mod_subroutinendentityp_in_mod_subroutine;self#add_surrounding_xxxL.is_block_datandentityp_in_block_data;self#add_surrounding_xxxL.is_stmtndentityp_in_stmt;self#add_surrounding_xxxL.is_do_constructndentityp_in_do_construct;self#add_surrounding_xxxL.is_case_constructndentityp_in_case_construct;self#add_surrounding_xxxL.is_forall_constructndentityp_in_forall_construct;self#add_surrounding_xxxL.is_if_constructndentityp_in_if_construct;self#add_surrounding_xxxL.is_where_constructndentityp_in_where_construct;self#add_surrounding_xxxL.is_select_type_constructndentityp_in_select_type_construct;self#add_surrounding_xxxL.is_associate_constructndentityp_in_associate_construct;self#add_surrounding_xxxL.is_block_constructndentityp_in_block_construct;self#add_surrounding_xxxL.is_critical_constructndentityp_in_critical_construct;self#add_surrounding_xxxL.is_derived_type_defndentityp_in_derived_type_def;self#add_surrounding_xxxL.is_interface_blockndentityp_in_interface_block;self#add_surrounding_xxxL.is_if_then_blockndentityp_in_if_then_block;self#add_surrounding_xxxL.is_else_blockndentityp_in_else_block;self#add_surrounding_xxxL.is_else_if_blockndentityp_in_else_if_block;self#add_surrounding_xxxL.is_where_blockndentityp_in_where_block;self#add_surrounding_xxxL.is_case_blockndentityp_in_case_block;self#add_surrounding_xxxL.is_type_guard_blockndentityp_in_type_guard_block;self#add_surrounding_xxxL.is_do_blockndentityp_in_do_block;self#add_surrounding_xxxL.is_pp_branchndentityp_in_pp_branch;self#add_surrounding_xxxL.is_pp_branch_dondentityp_in_pp_branch_do;self#add_surrounding_xxxL.is_pp_branch_end_dondentityp_in_pp_branch_end_do;self#add_surrounding_xxxL.is_pp_branch_ifndentityp_in_pp_branch_if;self#add_surrounding_xxxL.is_pp_branch_end_ifndentityp_in_pp_branch_end_if;self#add_surrounding_xxxL.is_pp_branch_forallndentityp_in_pp_branch_forall;self#add_surrounding_xxxL.is_pp_branch_end_forallndentityp_in_pp_branch_end_forall;self#add_surrounding_xxxL.is_pp_branch_wherendentityp_in_pp_branch_where;self#add_surrounding_xxxL.is_pp_branch_end_wherendentityp_in_pp_branch_end_where;self#add_surrounding_xxxL.is_pp_branch_selectndentityp_in_pp_branch_select;self#add_surrounding_xxxL.is_pp_branch_end_selectndentityp_in_pp_branch_end_select;self#add_surrounding_xxxL.is_pp_section_ifdefndentityp_in_pp_section_ifdef;self#add_surrounding_xxxL.is_pp_section_ifndefndentityp_in_pp_section_ifndef;self#add_surrounding_xxxL.is_pp_section_ifndentityp_in_pp_section_if;self#add_surrounding_xxxL.is_pp_section_elifndentityp_in_pp_section_elif;self#add_surrounding_xxxL.is_pp_section_elsendentityp_in_pp_section_else;self#add_surrounding_xxxL.is_omp_constructndentityp_in_omp_construct;self#add_surrounding_xxxL.is_acc_constructndentityp_in_acc_construct;self#add_surrounding_xxxL.is_container_unitndentityp_in_container_unit;self#add_surrounding_xxxL.is_program_unit_or_fragmentndentityp_in_pu_or_fragment;self#add_surrounding_xxxL.is_program_unit_or_subprogramndentityp_in_pu_or_sp;end;end(* of class Fortran.Fact.F.extractor *)(* main function *)letextractoptionscache_pathtree=tryletextractor=newextractoroptionscache_pathtreeinextractor#set_lang_prefixAstml.fortran_prefix;extractor#extractwith|Triple.File_existss->Common.warning_msg"file exists: \"%s\""s|Triple.Lock_failed->Common.warning_msg"fact buffer is already locked."end(* of functor Fortran.Fact.F *)