123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288(*
Copyright 2012-2025 Codinuum Software Lab <https://codinuum.com>
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.
*)(* context.ml *)[%%prepare_logger]moduleAstloc=Langs_common.AstlocmoduleLoc=Astloctypetag=|Cunknown|Ctoplevel|Cmodule_item_list|Cgenerate_item_list|Cblock_decl_stmt_list|Ccase_item_list|Ccase_inside_item_list|Ccellpin_list|Clist_of_ports|Cpev_expr|Cev_expr|Cexprlettag_to_string=function|Cunknown->"unknown"|Ctoplevel->"toplevel"|Cmodule_item_list->"module_item_list"|Cgenerate_item_list->"generate_item_list"|Cblock_decl_stmt_list->"block_decl_stmt_list"|Ccase_item_list->"case_item_list"|Ccase_inside_item_list->"case_inside_item_list"|Ccellpin_list->"cellpin_list"|Clist_of_ports->"list_of_ports"|Cpev_expr->"pev_expr"|Cev_expr->"ev_expr"|Cexpr->"expr"typet={tag:tag;mutableis_active:bool;}letcopy_contextc={tag=c.tag;is_active=c.is_active}letdeactivate_contextc=c.is_active<-falseletto_string{tag=tag;is_active=is_active}=Printf.sprintf"%s[%sACTIVE]"(tag_to_stringtag)(ifis_activethen""else"NOT ")letunknown()={tag=Cunknown;is_active=false;}lettoplevel()={tag=Ctoplevel;is_active=true;}letmodule_item_list()={tag=Cmodule_item_list;is_active=true;}letgenerate_item_list()={tag=Cgenerate_item_list;is_active=true;}letblock_decl_stmt_list()={tag=Cblock_decl_stmt_list;is_active=true;}letcase_item_list()={tag=Ccase_item_list;is_active=true;}letcase_inside_item_list()={tag=Ccase_inside_item_list;is_active=true;}letcellpin_list()={tag=Ccellpin_list;is_active=true;}letlist_of_ports()={tag=Clist_of_ports;is_active=true;}letpev_expr()={tag=Cpev_expr;is_active=true;}letev_expr()={tag=Cev_expr;is_active=true;}letexpr()={tag=Cexpr;is_active=true;}letget_tag{tag=tag;is_active=_;}=tagletis_unknownc=c.tag=Cunknownletis_toplevelc=c.tag=Ctoplevelletis_module_item_listc=c.tag=Cmodule_item_listletis_generate_item_listc=c.tag=Cgenerate_item_listletis_block_decl_stmt_listc=c.tag=Cblock_decl_stmt_listletis_case_item_listc=c.tag=Ccase_item_listletis_case_inside_item_listc=c.tag=Ccase_inside_item_listletis_cellpin_listc=c.tag=Ccellpin_listletis_list_of_portsc=c.tag=Clist_of_portsletis_pev_exprc=c.tag=Cpev_exprletis_ev_exprc=c.tag=Cev_exprletis_exprc=c.tag=Cexpr[%%capture_pathclassstackenv=object(self)valcheckpoint_tbl=Hashtbl.create0(* Loc.t -> t Stack.t *)valmutablestack:tStack.t=Stack.create()valmutablesuspended=falsevalmutablepush_callback=fun_->()valmutablepop_callback=fun__->()valmutableactivate_callback=fun_->()valmutabledeactivate_callback=fun_->()methodsize=Stack.lengthstackmethodregister_push_callbackf=push_callback<-fmethodregister_pop_callbackf=pop_callback<-fmethodregister_activate_callbackf=activate_callback<-fmethodregister_deactivate_callbackf=deactivate_callback<-fmethodclear=Stack.clearstackmethodtop=Stack.topstackmethodsuspended=suspendedmethodsuspend=[%debug_log"called"];suspended<-true;methodresume=[%debug_log"called"];suspended<-false;(*
method _force_pop n stack =
for i = 1 to n do
ignore (Stack.pop stack)
done
*)methodcheckpoint(key:Loc.t)=begin%debug_block[%debug_log"key=%s"(Loc.to_stringkey)];Stack.iter(func->[%debug_log"stack: %s"(to_stringc)])stack;end;(*
if Hashtbl.mem checkpoint_tbl key then
[%warn_log "already checkpointed: key=%s" (Loc.to_string key)];
*)letcopy=self#_copy_stackstackinHashtbl.replacecheckpoint_tblkeycopy;methodrecoverkey=trystack<-self#_copy_stack(Hashtbl.findcheckpoint_tblkey);begin%debug_block[%debug_log"key=%s"(Loc.to_stringkey)];Stack.iter(func->[%debug_log"stack: %s"(to_stringc)])stack;endwithNot_found->[%fatal_log"stack not found: key=%s"(Loc.to_stringkey)];exit1method_copy_stacks=letcopy=Stack.create()inletcs=ref[]inStack.iter(func->cs:=(copy_contextc)::!cs)s;List.iter(func->Stack.pushccopy)!cs;copymethodpushc=ifnotsuspendedthenbeginbegin%debug_block[%debug_log"%s"(to_stringc)];Stack.iter(fun_c->[%debug_log"stack: %s"(to_string_c)])stack;end;Stack.pushcstack;push_callbackcendelse[%debug_log"suspended"];env#set_context_enter_flagmethodpop=self#_popfalsemethodpop_and_activate=self#_poptruemethod_popterminates_surrounding_construct=ifnotsuspendedthenbeginbegin%debug_blockStack.iter(fun_c->[%debug_log"stack: %s"(to_string_c)])stack;end;ignore(Stack.popstack);letnew_top=tryStack.topstackwithStack.Empty->assertfalsein[%debug_log"(new top: %s)"(to_stringnew_top)];pop_callbackterminates_surrounding_constructnew_topendelse[%debug_log"suspended"]methodactivate_top:unit=ifnotsuspendedthenbeginletc=self#topinifnotc.is_activethen[%debug_log"%s"(to_stringc)];c.is_active<-trueend;env#set_context_activate_flagmethodactivate_top_no_delay=ifnotsuspendedthenbeginletc=self#topinifnotc.is_activethen[%debug_log"%s"(to_stringc)];c.is_active<-true;activate_callbackcendmethoddeactivate_top=ifnotsuspendedthenbeginletc=self#topinifc.is_activethen[%debug_log"%s"(to_stringc)];c.is_active<-falseendmethoddeactivate_top_no_delay=ifnotsuspendedthenbeginletc=self#topinifc.is_activethen[%debug_log"%s"(to_stringc)];c.is_active<-false;deactivate_callbackcendmethodtop_is_active=letc=self#topinc.is_activemethodtop_is_unknown=letc=self#topinis_unknowncmethodreset=self#clear;Hashtbl.clearcheckpoint_tbl;self#push(toplevel())initializerself#resetend(* of class Context.stack *)]