12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364openAstopenAst.Text(* The canonical pre-order walk of an instruction tree: visit [i], then recurse
into every nested instruction it carries. Keeping this in one place means a
new instruction that nests others (or a missed case, as [Hinted] once was)
is handled for every traversal at once. *)letrecfold_instrfacc(i:'infoinstr)=letacc=facciinmatchi.descwith|Block{block;_}|Loop{block;_}|TryTable{block;_}->fold_instrsfaccblock.desc|If{if_block;else_block;_}->fold_instrsf(fold_instrsfaccif_block.desc)else_block.desc|Try{block;catches;catch_all;_}->letacc=fold_instrsfaccblock.descinletacc=List.fold_left(funacc(_,is)->fold_instrsfaccis.desc)acccatchesinOption.fold~none:acc~some:(funb->fold_instrsfaccb.desc)catch_all|Folded(h,is)->fold_instrsf(fold_instrfacch)is|Hinted(_,inner)->fold_instrfaccinner(* The remaining variants carry no nested instruction. *)|_->accandfold_instrsfaccl=List.fold_left(fold_instrf)acclletiter_instrfi=fold_instr(fun()i->fi)()i(* compact-import-section: expand an [Import_group1]/[Import_group2] field into
the individual [Import] fields it stands for (carrying the group's location);
any other field is returned unchanged as a singleton. Passes that only need to
see individual imports flatten a field list with
[List.concat_map expand_import_group]. *)letexpand_import_groupf=matchf.descwith|Import_group1{module_;items}->List.map(fun(name,id,desc)->{fwithdesc=Import{module_;name;id;desc;exports=[]}})items|Import_group2{module_;desc;items}->List.map(fun(name,id)->{fwithdesc=Import{module_;name;id;desc;exports=[]}})items|_->[f](* Flatten binary import-section entries back into the individual imports they
denote, for the passes that only need the flat import list (index counting). *)letflatten_binary_imports(entries:Ast.Binary.import_entrylist):Ast.Binary.importlist=List.concat_map(function|Ast.Binary.Singlei->[i]|Group1{module_;items}->List.map(fun(name,desc)->{Ast.Binary.module_;name;desc})items|Group2{module_;desc;names}->List.map(funname->{Ast.Binary.module_;name;desc})names)entries