123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206openCore_kernelopenImportopenTypes.KindmoduleAs_adjust_heights_list=Node.Packed.As_list(structletnext(Node.Packed.Tnode)=node.next_in_adjust_heights_heapend)moduleNodes_by_height=structtypet=As_adjust_heights_list.tArray.t[@@derivingsexp_of]letsexp_of_tt=letmax_nonempty_index=ref(-1)inArray.iterit~f:(funil->ifUopt.is_somelthenmax_nonempty_index:=i);Array.subt~pos:0~len:(!max_nonempty_index+1)|>[%sexp_of:t];;letinvariantt=Invariant.invariant[%here]t[%sexp_of:t](fun()->Array.iterit~f:(funheightnodes->As_adjust_heights_list.invariantnodes;As_adjust_heights_list.iternodes~f:(fun(Tnode)->assert(node.height_in_adjust_heights_heap=height);assert(node.height>node.height_in_adjust_heights_heap);ifNode.is_in_recompute_heapnodethenassert(node.height_in_recompute_heap=node.height_in_adjust_heights_heap))));;letcreate~max_height_allowed=Array.create~len:(max_height_allowed+1)Uopt.noneletlengtht=letr=ref0inArray.itert~f:(funnode->r:=!r+As_adjust_heights_list.lengthnode);!r;;endtypet={mutablelength:int;mutableheight_lower_bound:int;mutablemax_height_seen:int;mutablenodes_by_height:Nodes_by_height.t}[@@derivingfields,sexp_of]letis_emptyt=lengtht=0letmax_height_allowedt=Array.lengtht.nodes_by_height-1letinvariantt=Invariant.invariant[%here]t[%sexp_of:t](fun()->letcheckf=Invariant.check_fieldtfinFields.iter~length:(check(funlength->assert(length=Nodes_by_height.lengtht.nodes_by_height)))~height_lower_bound:(check(funheight_lower_bound->assert(height_lower_bound>=0);assert(height_lower_bound<=Array.lengtht.nodes_by_height);forheight=0toheight_lower_bound-1doassert(Uopt.is_nonet.nodes_by_height.(height))done))~max_height_seen:(check(funmax_height_seen->assert(max_height_seen>=0);assert(max_height_seen<=max_height_allowedt)))~nodes_by_height:(checkNodes_by_height.invariant));;letcreate~max_height_allowed={length=0;height_lower_bound=max_height_allowed+1;max_height_seen=0;nodes_by_height=Nodes_by_height.create~max_height_allowed};;letset_max_height_allowedtmax_height_allowed=ifmax_height_allowed<t.max_height_seenthenfailwiths"cannot set_max_height_allowed less than the max height already seen"(max_height_allowed,`max_height_seent.max_height_seen)[%sexp_of:int*[`max_height_seenofint]];ifdebugthenassert(is_emptyt);t.nodes_by_height<-Nodes_by_height.create~max_height_allowed;;letadd_unless_mem(typea)t(node:aNode.t)=ifnode.height_in_adjust_heights_heap=-1then(letheight=node.heightin(* We process nodes in increasing order of pre-adjusted height, so it is a bug if we
ever try to add a node that would violate that. *)ifdebugthenassert(height>=t.height_lower_bound);(* Whenever we set a node's height, we use [set_height], which enforces this. *)ifdebugthenassert(height<=max_height_allowedt);node.height_in_adjust_heights_heap<-height;t.length<-t.length+1;node.next_in_adjust_heights_heap<-t.nodes_by_height.(height);Array.unsafe_sett.nodes_by_heightheight(Uopt.some(Node.Packed.Tnode)));;letremove_min_exnt:Node.Packed.t=ifdebug&&is_emptytthenfailwiths"Adjust_heights_heap.remove_min of empty heap"t[%sexp_of:t];letr=reft.height_lower_boundinwhileUopt.is_nonet.nodes_by_height.(!r)doincrrdone;letheight=!rint.height_lower_bound<-height;let(Tnode)=Uopt.unsafe_value(Array.unsafe_gett.nodes_by_heightheight)innode.height_in_adjust_heights_heap<--1;t.length<-t.length-1;Array.unsafe_sett.nodes_by_heightheightnode.next_in_adjust_heights_heap;node.next_in_adjust_heights_heap<-Uopt.none;Tnode;;letset_heightt(node:_Node.t)height=ifheight>t.max_height_seenthen(t.max_height_seen<-height;ifheight>max_height_allowedtthenfailwiths"node with too large height"(`Heightheight,`Max(max_height_allowedt))[%sexp_of:[`Heightofint]*[`Maxofint]]);node.height<-height;;letensure_height_requirementt~original_child~original_parent~child~parent=ifdebugthenassert(Node.is_necessarychild);ifdebugthenassert(Node.is_necessaryparent);ifNode.sameparentoriginal_childthenfailwiths"adding edge made graph cyclic"(`childoriginal_child,`parentoriginal_parent)[%sexp_of:[`childof_Node.t]*[`parentof_Node.t]];ifchild.height>=parent.heightthen(add_unless_memtparent;(* We set [parent.height] after adding [parent] to the heap, so that [parent] goes
in the heap with its pre-adjusted height. *)set_heighttparent(child.height+1));;letadjust_heights(typeab)trecompute_heap~child:(original_child:aNode.t)~parent:(original_parent:bNode.t)=ifverbosethenDebug.ams[%here]"adjust_heights"(`childoriginal_child,`parentoriginal_parent)[%sexp_of:[`childof_Node.t]*[`parentof_Node.t]];ifdebugthenassert(is_emptyt);ifdebugthenassert(original_child.height>=original_parent.height);t.height_lower_bound<-original_parent.height;ensure_height_requirementt~original_child~original_parent~child:original_child~parent:original_parent;whilelengtht>0dolet(Tchild)=remove_min_exntinifNode.is_in_recompute_heapchildthenRecompute_heap.increase_heightrecompute_heapchild;ifchild.num_parents>0then(let(Tparent)=Uopt.value_exnchild.parent0inensure_height_requirementt~original_child~original_parent~child~parent;forparent_index=1tochild.num_parents-1dolet(Tparent)=Uopt.value_exnchild.parent1_and_beyond.(parent_index-1)inensure_height_requirementt~original_child~original_parent~child~parentdone);matchchild.kindwith|Bind_lhs_change{all_nodes_created_on_rhs;_}->letr=refall_nodes_created_on_rhsinwhileUopt.is_some!rdolet(Tnode_on_rhs)=Uopt.unsafe_value!rinr:=node_on_rhs.next_node_in_same_scope;ifNode.is_necessarynode_on_rhsthenensure_height_requirementt~original_child~original_parent~child~parent:node_on_rhsdone|_->()done;ifdebugthenassert(is_emptyt);ifdebugthenassert(original_child.height<original_parent.height);;