moduleAgda.Compiler.JS.SubstitutionwhereimportPreludehiding(map,lookup)importData.Generics(Data,Typeable)importData.Map(Map,empty,toList,unionWith,singleton,findWithDefault)importqualifiedData.MapasM(map)importData.Map(Map)importData.List(genericIndex)importqualifiedData.ListasL(map)importAgda.Syntax.Common(Nat)importAgda.Compiler.JS.Syntax(Exp(Self,Undefined,Local,Lambda,Object,Apply,Lookup,If,BinOp,PreOp),MemberId,LocalId(LocalId),GlobalId(GlobalId))importAgda.Utils.Function(iterate')-- Map for expressionsmap::Nat->(Nat->LocalId->Exp)->Exp->Expmapmf(Locali)=fmimapmf(Lambdaie)=Lambdai(map(m+i)fe)mapmf(Objecto)=Object(M.map(mapmf)o)mapmf(Applyees)=Apply(mapmfe)(L.map(mapmf)es)mapmf(Lookupel)=Lookup(mapmfe)lmapmf(Ifee'e'')=If(mapmfe)(mapmfe')(mapmfe'')mapmf(PreOpope)=PreOpop(mapmfe)mapmf(BinOpeope')=BinOp(mapmfe)op(mapmfe')mapmfe=e-- Shiftingshift::Nat->Exp->Expshift=shiftFrom0shiftFrom::Nat->Nat->Exp->ExpshiftFromm0e=eshiftFrommne=mapm(shiftern)eshifter::Nat->Nat->LocalId->Expshifternm(LocalIdi)|i<m=Local(LocalIdi)shifternm(LocalIdi)|otherwise=Local(LocalId(i+n))-- Substitutionsubst::Nat->[Exp]->Exp->Expsubst0ese=esubstnese=map0(substituternes)esubstituter::Nat->[Exp]->Nat->LocalId->Expsubstituternesm(LocalIdi)|i<m=Local(LocalIdi)substituternesm(LocalIdi)|(i-m)<n=shiftm(genericIndex(es++repeatUndefined)(n-(i+1-m)))substituternesm(LocalIdi)|otherwise=Local(LocalId(i-n))-- A variant on substitution which performs beta-reductionmap'::Nat->(Nat->LocalId->Exp)->Exp->Expmap'mf(Locali)=fmimap'mf(Lambdaie)=Lambdai(map'(m+i)fe)map'mf(Objecto)=Object(M.map(map'mf)o)map'mf(Applyees)=apply(map'mfe)(L.map(map'mf)es)map'mf(Lookupel)=lookup(map'mfe)lmap'mf(Ifee'e'')=If(map'mfe)(map'mfe')(map'mfe'')map'mf(PreOpope)=PreOpop(map'mfe)map'mf(BinOpeope')=BinOp(map'mfe)op(map'mfe')map'mfe=esubst'::Nat->[Exp]->Exp->Expsubst'0ese=esubst'nese=map'0(substituternes)e-- Beta-reducing application and field accessapply::Exp->[Exp]->Expapply(Lambdaie)es=subst'ieseapplyees=Applyeeslookup::Exp->MemberId->Explookup(Objecto)l=findWithDefaultUndefinedlolookupel=Lookupel-- Replace any top-level occurrences of self-- (needed because JS is a cbv language, so any top-level-- recursions would evaluate before the module has been defined,-- e.g. exports = { x: 1, y: exports.x } results in an exception,-- as exports is undefined at the point that exports.x is evaluated),self::Exp->Exp->Expselfe(Self)=eselfe(Objecto)=Object(M.map(selfe)o)selfe(Applyfes)=case(selfef)of(Lambdang)->selfe(subst'nesg)g->Applyg(L.map(selfe)es)selfe(Lookupfl)=lookup(selfef)lselfe(Iffgh)=If(selfef)(selfeg)(selfeh)selfe(BinOpfopg)=BinOp(selfef)op(selfeg)selfe(PreOpopf)=PreOpop(selfef)selfef=f-- Find the fixed point of an expression, with no top-level occurrences-- of self.fix::Exp->Expfixf=ewheree=selfef-- Some helper functionscurriedApply::Exp->[Exp]->ExpcurriedApply=foldl(\fe->applyf[e])curriedLambda::Nat->Exp->ExpcurriedLambdan=iterate'n(Lambda1)emp::Expemp=Object(empty)union::Exp->Exp->Expunion(Objecto)(Objectp)=Object(unionWithunionop)unionef=evine::[MemberId]->Exp->Expvinelse=foldr(\le->Object(singletonle))elsobject::[([MemberId],Exp)]->Expobject=foldr(\(ls,e)->(union(vinelse)))emp