123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118openJg_typesopenJg_ast_mapper(** [dead_code_elimination ast] perform a dead code elimination on [ast].
It is able to remove from ast:
- macro and function definitions not being actually used in ast
*)letdead_code_eliminationstmts=letused=Hashtbl.create512inletlocal_variables:(string*stringlist)listref=ref[("",[])]inletpush_blockname=local_variables:=(name,[])::!local_variablesinletpop_block()=local_variables:=List.tl!local_variablesinletset_localx=letfst,snd=List.hd!local_variablesinlocal_variables:=(fst,x::snd)::(List.tl!local_variables)inletis_local(x:string)=List.exists(fun(_,l)->List.memxl)!local_variablesinletscope()=letrecloop=function|[]->""|("",_)::tl->looptl|(s,_)::_->sinloop!local_variablesinletrecmaybe_set=function|SetExprset->List.itermaybe_setset|IdentExprid->set_localid|_->()inletstatementself=function|SetStatement(id,_)ass->maybe_setid;default_mapper.statementselfs|SetBlockStatement(id,_)ass->set_localid;push_blockid;lets=default_mapper.statementselfsinpop_block();s|ForStatement(ids,_,_)ass->push_block"";List.iterset_localids;lets=default_mapper.statementselfsinpop_block();s|FunctionStatement(id,args,_)|MacroStatement(id,args,_)ass->push_blockid;set_localid;List.iter(fun(i,_)->set_locali)args;lets=default_mapper.statementselfsinpop_block();s|CallStatement(id,args,_,_)ass->Hashtbl.addusedid(scope());push_block"";List.iter(fun(i,_)->set_locali)args;lets=default_mapper.statementselfsinpop_block();s|TextStatement(_)|ExpandStatement(_)|IfStatement(_)|SwitchStatement(_,_)|IncludeStatement(_,_)|RawIncludeStatement_|ExtendsStatement_|ImportStatement(_,_)|FromImportStatement(_,_)|BlockStatement(_,_)|FilterStatement(_,_)|WithStatement(_,_)|AutoEscapeStatement(_,_)|NamespaceStatement(_,_)|Statements(_)ass->default_mapper.statementselfsinletexpressionself=function|IdentExprnameasxwhennot(is_localname)->Hashtbl.addusedname(scope());x|e->default_mapper.expressionselfeinletmapper={default_mapperwithexpression;statement}inlet_=mapper.astmapperstmtsinletstatementself=function|MacroStatement(id,_,_)|FunctionStatement(id,_,_)ass->(* Find if name is present in instructions called from toplevel *)letreclooplists=matchlistswith|[]->Statements[]|[[]]->Statements[]|list::_whenList.mem""list->default_mapper.statementselfs(* id is used in toplevel *)|list::_->letlist'=list|>List.map(Hashtbl.find_allused)|>List.flatten|>List.sort_uniqcompareinifList.memlist'liststhenStatements[]elseloop(list'::lists)inloop[List.sort_uniqcompare@@Hashtbl.find_allusedid]|s->default_mapper.statementselfsinletmapper={default_mapperwithstatement}inmapper.astmapperstmts(** [inline_include env ast]
Inline the templates included in [ast] so it won't be necessary to
open and parse theses parts when execution [ast].
*)letinline_includeenvstmts=letopenJg_ast_mapperinletstatementself=function|IncludeStatement(LiteralExpr(Tstrfile),true)->Statements(self.astself@@Jg_interp.ast_from_file~envfile)|RawIncludeStatement(LiteralExpr(Tstrfile))->Statements(self.astself@@Jg_interp.ast_from_file~envfile)|e->default_mapper.statementselfeinletmapper={default_mapperwithstatement}inmapper.astmapperstmts