1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071(* more than a set, rules are in fact stored in a semilattice *)openParsetreetypecell={rule:Rule.t;mutablehigher:celllist;mutablelevel:int}letmake_cell?(level=(-1))?(higher=[])rule={rule;higher;level}letidentity=letname="'a -> 'a"inletmatcher(itype,otype)=ifParsetree_utils.equal_core_typeitypeotypethenSome[]elseNoneinletbuildercasts=assert(casts=[]);[%exprfunx->x]inmake_cell(Rule.make~name~matcher~builder())moduleSMap=Map.Make(String)letcells:cellSMap.tref=ref(SMap.singleton(Rule.name_identity.rule)identity)letlookup_cellrule=SMap.find(Rule.name_rule)!cellsletlookupname=(SMap.findname!cells).ruleletregister?(applies_before=[])?(applies_after=[])rule=letcell=make_cell~higher:(List.maplookup_cellapplies_before)ruleincells:=SMap.add(Rule.name_rule)cell!cells;identity.higher<-cell::identity.higher;List.iter(funrule'->letcell'=lookup_cellrule'incell'.higher<-cell::cell'.higher)applies_afterletfill_levels()=letrecfill_levelilowercell=assert(not(List.memcelllower));ifcell.level<ithencell.level<-i;List.iter(fill_level(i+1)(cell::lower))cell.higherinSMap.iter(fun_cell->cell.level<--1)!cells;fill_level0[]identityletfold_by_priorityfx=letrecfoldxlevel=function|[]->x|cells_at_that_level->letx'=f(List.map(funcell->cell.rule)cells_at_that_level)xinletnext_level=level+1inletcells_at_next_level=List.map(funcell->cell.higher)cells_at_that_level|>List.flatten|>List.filter(funcell->cell.level=next_level)infoldx'next_levelcells_at_next_levelinfill_levels();foldxidentity.level[identity]