123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051openTypesletrecoptimize(e:expr):expr=matchewith|Plus(Integerx,Integery)->Integer(x+y)(* Autoreduce constants *)|Sub(Integerx,Integery)->Integer(x-y)|Mult(Integerx,Integery)->Integer(x*y)|Eq(Integerx,Integery)->Boolean(x==y)|Gt(Integerx,Integery)->Boolean(x>y)|Lt(Integerx,Integery)->Boolean(x<y)|And(Booleanx,Booleany)->Boolean(x&&y)|Or(Booleanx,Booleany)->Boolean(x||y)|Eq(x,y)->Eq(optimizex,optimizey)|Gt(x,y)->Gt(optimizex,optimizey)|Lt(x,y)->Lt(optimizex,optimizey)|Not(Booleanx)->Boolean(notx)|Plus(x,y)->Plus(optimizex,optimizey)|Sub(x,y)->Sub(optimizex,optimizey)|Mult(x,y)->Mult(optimizex,optimizey)|And(x,y)->And(optimizex,optimizey)|Or(x,y)->Or(optimizex,optimizey)|Not(x)->Not(optimizex)|List(l)->List(List.mapoptimizel)|Dict(d)->Dict(List.map(fun(k,v)->(optimizek,optimizev))d)|IfThenElse(guard,iftrue,iffalse)->(* Short circuit an if that is always true or false *)letog=optimizeguardinifog=Booleantruethenoptimizeiftrueelseifog=BooleanfalsethenoptimizeiffalseelseIfThenElse(og,optimizeiftrue,optimizeiffalse)|Lambda(params,body)->Lambda(params,optimizebody)|Let(declarations,body)->optimize_letdeclarationsbodyfalse|Letlazy(declarations,body)->optimize_letdeclarationsbodytrue|Letrec(ident,dec,body)->Letrec(ident,optimizedec,optimizebody)|Letreclazy(ident,dec,body)->Letreclazy(ident,optimizedec,optimizebody)|Apply(func,params)->Apply(func,(List.mapoptimizeparams))|_->eandoptimize_letdeclarationsbodyislazy=letod=List.map(fun(i,v)->(i,optimizev))declarationsinletob=optimizebodyinifList.lengthod=1thenlet(ident,value)=List.hdodinifob=SymbolidentthenoptimizevalueelseifislazythenLetlazy(od,ob)elseLet(od,ob)elseifislazythenLetlazy(od,ob)elseLet(od,ob)(** Apply the optimizer again and again on an expression until it
is fully reduced and ready to be evaluated *)letreciterate_optimizere=letoe=optimizeeinifoe=ethene(* Bottoms out *)elseiterate_optimizeroe