packages feed

free-foil 0.1.0 → 0.2.0

raw patch · 9 files changed

+1705/−24 lines, 9 filesdep +kind-genericsPVP ok

version bump matches the API change (PVP)

Dependencies added: kind-generics

API changes (from Hackage documentation)

+ Control.Monad.Foil: [NameBinderListCons] :: forall (n :: S) (i :: S) (l :: S). NameBinder n i -> NameBinderList i l -> NameBinderList n l
+ Control.Monad.Foil: [NameBinderListEmpty] :: forall (n :: S). NameBinderList n n
+ Control.Monad.Foil: addNameBinderList :: forall (n :: S) (l :: S) a. NameBinderList n l -> [a] -> NameMap n a -> NameMap l a
+ Control.Monad.Foil: addNameBinders :: forall binder (n :: S) (l :: S) a. CoSinkable binder => binder n l -> [a] -> NameMap n a -> NameMap l a
+ Control.Monad.Foil: addSubstList :: forall e (i :: S) (o :: S) (i' :: S). Substitution e i o -> NameBinderList i i' -> [e o] -> Substitution e i' o
+ Control.Monad.Foil: addSubstPattern :: forall binder e (i :: S) (o :: S) (i' :: S). CoSinkable binder => Substitution e i o -> binder i i' -> [e o] -> Substitution e i' o
+ Control.Monad.Foil: data NameBinderList (n :: S) (l :: S)
+ Control.Monad.Foil: nameMapToSubstitution :: forall (i :: S) e (o :: S). NameMap i (e o) -> Substitution e i o
+ Control.Monad.Foil: voidSubst :: forall (e :: S -> Type) (n :: S). Substitution e 'VoidS n
+ Control.Monad.Foil.Internal: WithNameBinderList :: (NameBinderList l r -> NameBinderList n r) -> WithNameBinderList (r :: S) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: addNameBinderList :: forall (n :: S) (l :: S) a. NameBinderList n l -> [a] -> NameMap n a -> NameMap l a
+ Control.Monad.Foil.Internal: addNameBinders :: forall binder (n :: S) (l :: S) a. CoSinkable binder => binder n l -> [a] -> NameMap n a -> NameMap l a
+ Control.Monad.Foil.Internal: addSubstList :: forall e (i :: S) (o :: S) (i' :: S). Substitution e i o -> NameBinderList i i' -> [e o] -> Substitution e i' o
+ Control.Monad.Foil.Internal: addSubstPattern :: forall binder e (i :: S) (o :: S) (i' :: S). CoSinkable binder => Substitution e i o -> binder i i' -> [e o] -> Substitution e i' o
+ Control.Monad.Foil.Internal: compWithNameBinderList :: forall (o :: S) (o' :: S) (o'' :: S) (r :: S) (n :: S) (i :: S) (l :: S). (DExt o o', DExt o' o'') => WithNameBinderList r n i o o' -> WithNameBinderList r i l o' o'' -> WithNameBinderList r n l o o''
+ Control.Monad.Foil.Internal: idWithNameBinderList :: forall (o :: S) (o' :: S) (r :: S) (n :: S). DExt o o' => WithNameBinderList r n n o o'
+ Control.Monad.Foil.Internal: nameBinderListOf :: forall binder (n :: S) (l :: S). CoSinkable binder => binder n l -> NameBinderList n l
+ Control.Monad.Foil.Internal: nameMapToSubstitution :: forall (i :: S) e (o :: S). NameMap i (e o) -> Substitution e i o
+ Control.Monad.Foil.Internal: newtype WithNameBinderList (r :: S) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: voidSubst :: forall (e :: S -> Type) (n :: S). Substitution e 'VoidS n
+ Control.Monad.Free.Foil: substitutePattern :: forall (sig :: Type -> Type -> Type) (o :: S) binder' (binder :: S -> S -> Type) (n :: S) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder', CoSinkable binder) => Scope o -> Substitution (AST binder sig) n o -> binder' n i -> [AST binder sig o] -> AST binder sig i -> AST binder sig o
+ Control.Monad.Free.Foil.Generic: ($dmzipMatchWithK) :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (ZipMatchK f, GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Control.Monad.Free.Foil.Generic: [:^:] :: forall {k1} a b c (as1 :: LoT k1) (bs1 :: LoT k1) (cs1 :: LoT k1). (a -> b -> Maybe c) -> Mappings as1 bs1 cs1 -> Mappings (a ':&&: as1) (b ':&&: bs1) (c ':&&: cs1)
+ Control.Monad.Free.Foil.Generic: [M0] :: Mappings 'LoT0 'LoT0 'LoT0
+ Control.Monad.Free.Foil.Generic: applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). ApplyMappings v => Mappings as bs cs -> Interpret ('Var v) as -> Interpret ('Var v) bs -> Maybe (Interpret ('Var v) cs)
+ Control.Monad.Free.Foil.Generic: class ApplyMappings (v :: TyVar d Type)
+ Control.Monad.Free.Foil.Generic: class GZipMatch (f :: LoT k -> Type) where {
+ Control.Monad.Free.Foil.Generic: class PairMappings (as :: LoT k) (bs :: LoT k)
+ Control.Monad.Free.Foil.Generic: class ZipMatchFields (t :: Atom d Type) where {
+ Control.Monad.Free.Foil.Generic: class ZipMatchK (f :: k)
+ Control.Monad.Free.Foil.Generic: data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k)
+ Control.Monad.Free.Foil.Generic: genericZipMatch2 :: forall sig scope scope' term term'. (GenericK sig, GZipMatch (RepK sig), ReqsZipMatch (RepK sig) (scope ':&&: (term ':&&: 'LoT0)) (scope' ':&&: (term' ':&&: 'LoT0))) => sig scope term -> sig scope' term' -> Maybe (sig (scope, scope') (term, term'))
+ Control.Monad.Free.Foil.Generic: genericZipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
+ Control.Monad.Free.Foil.Generic: genericZipMatchWithK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Control.Monad.Free.Foil.Generic: gzipMatchWith :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GZipMatch f, ReqsZipMatchWith f as bs cs) => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ApplyMappings 'Data.PolyKinded.Atom.VZ
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.GZipMatch GHC.Generics.U1
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.GZipMatch GHC.Generics.V1
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.PairMappings 'Data.PolyKinded.LoT0 'Data.PolyKinded.LoT0
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK Data.Either.Either
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK GHC.Maybe.Maybe
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK []
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK a => Control.Monad.Free.Foil.Generic.ZipMatchK (Data.Either.Either a)
+ Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK k => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k)
+ Control.Monad.Free.Foil.Generic: instance forall d (a :: Data.PolyKinded.Atom.Atom d (Fcf.Core.Exp (*))). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Eval a)
+ Control.Monad.Free.Foil.Generic: instance forall d (c :: Data.PolyKinded.Atom.Atom d GHC.Types.Constraint) (a :: Data.PolyKinded.Atom.Atom d (*)). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields (c 'Data.PolyKinded.Atom.:=>>: a)
+ Control.Monad.Free.Foil.Generic: instance forall d (t :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> *). (Control.Monad.Free.Foil.Generic.ZipMatchFields t, Control.Monad.Free.Foil.Generic.ZipMatchK k) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t)
+ Control.Monad.Free.Foil.Generic: instance forall d (t1 :: Data.PolyKinded.Atom.Atom d (*)) (t2 :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> * -> *). (Control.Monad.Free.Foil.Generic.ZipMatchFields t1, Control.Monad.Free.Foil.Generic.ZipMatchFields t2, Control.Monad.Free.Foil.Generic.ZipMatchK k) => Control.Monad.Free.Foil.Generic.ZipMatchFields (('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t1) 'Data.PolyKinded.Atom.:@: t2)
+ Control.Monad.Free.Foil.Generic: instance forall d (v :: Data.PolyKinded.Atom.TyVar d (*)). Control.Monad.Free.Foil.Generic.ApplyMappings v => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Var v)
+ Control.Monad.Free.Foil.Generic: instance forall d k1 (f :: Data.PolyKinded.Atom.Atom d (k1 -> *)) (t :: Data.PolyKinded.Atom.Atom d k1). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields (f 'Data.PolyKinded.Atom.:@: t)
+ Control.Monad.Free.Foil.Generic: instance forall d1 d (a :: Data.PolyKinded.Atom.Atom (d1 -> d) (*)). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.ForAll a)
+ Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (c :: Data.PolyKinded.Atom.Atom k GHC.Types.Constraint). Control.Monad.Free.Foil.Generic.GZipMatch f => Control.Monad.Free.Foil.Generic.GZipMatch (c Generics.Kind.:=>: f)
+ Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Free.Foil.Generic.GZipMatch f, Control.Monad.Free.Foil.Generic.GZipMatch g) => Control.Monad.Free.Foil.Generic.GZipMatch (f GHC.Generics.:*: g)
+ Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Free.Foil.Generic.GZipMatch f, Control.Monad.Free.Foil.Generic.GZipMatch g) => Control.Monad.Free.Foil.Generic.GZipMatch (f GHC.Generics.:+: g)
+ Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) i (c :: GHC.Generics.Meta). Control.Monad.Free.Foil.Generic.GZipMatch f => Control.Monad.Free.Foil.Generic.GZipMatch (GHC.Generics.M1 i c f)
+ Control.Monad.Free.Foil.Generic: instance forall k (t :: Data.PolyKinded.Atom.Atom k (*)). Control.Monad.Free.Foil.Generic.ZipMatchFields t => Control.Monad.Free.Foil.Generic.GZipMatch (Generics.Kind.Field t)
+ Control.Monad.Free.Foil.Generic: instance forall k1 k2 (f :: Data.PolyKinded.LoT (k2 -> k1) -> *). (TypeError ...) => Control.Monad.Free.Foil.Generic.GZipMatch (Generics.Kind.Exists k2 f)
+ Control.Monad.Free.Foil.Generic: instance forall ks (as :: Data.PolyKinded.LoT ks) (bs :: Data.PolyKinded.LoT ks) a b. Control.Monad.Free.Foil.Generic.PairMappings as bs => Control.Monad.Free.Foil.Generic.PairMappings (a 'Data.PolyKinded.:&&: as) (b 'Data.PolyKinded.:&&: bs)
+ Control.Monad.Free.Foil.Generic: instance forall tys (v :: Data.PolyKinded.Atom.TyVar tys (*)) ty. Control.Monad.Free.Foil.Generic.ApplyMappings v => Control.Monad.Free.Foil.Generic.ApplyMappings ('Data.PolyKinded.Atom.VS v)
+ Control.Monad.Free.Foil.Generic: pairMappings :: PairMappings as bs => Mappings as bs (ZipLoT as bs)
+ Control.Monad.Free.Foil.Generic: type ReqsZipMatch (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) = ReqsZipMatchWith f as bs ZipLoT as bs
+ Control.Monad.Free.Foil.Generic: type ReqsZipMatchFieldsWith (t :: Atom d Type) (as :: LoT d) (bs :: LoT d) (cs :: LoT d);
+ Control.Monad.Free.Foil.Generic: type ReqsZipMatchWith (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) (cs :: LoT k);
+ Control.Monad.Free.Foil.Generic: type family ZipLoT (as :: LoT k) (bs :: LoT k) :: LoT k
+ Control.Monad.Free.Foil.Generic: zipMatchFieldsWith :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). (ZipMatchFields t, ReqsZipMatchFieldsWith t as bs cs) => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)
+ Control.Monad.Free.Foil.Generic: zipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (ZipMatchK f, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
+ Control.Monad.Free.Foil.Generic: zipMatchViaChooseLeft :: forall {k} (as :: LoT k) (bs :: LoT k) (cs :: LoT k) a. Mappings as bs cs -> a -> a -> Maybe a
+ Control.Monad.Free.Foil.Generic: zipMatchViaEq :: forall {k} a (as :: LoT k) (bs :: LoT k) (cs :: LoT k). Eq a => Mappings as bs cs -> a -> a -> Maybe a
+ Control.Monad.Free.Foil.Generic: zipMatchWithK :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). ZipMatchK f => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Control.Monad.Free.Foil.Generic: }
+ Control.Monad.Free.Foil.TH.MkFreeFoil: FreeFoilConfig :: [Name] -> [FreeFoilTermConfig] -> (String -> String) -> (String -> String) -> (String -> String) -> (String -> String) -> (String -> String) -> (String -> String) -> FreeFoilConfig
+ Control.Monad.Free.Foil.TH.MkFreeFoil: FreeFoilTermConfig :: Name -> Name -> Name -> Name -> Name -> [Name] -> [Name] -> Name -> Name -> Name -> Name -> FreeFoilTermConfig
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilConNameModifier] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilConvertFromName] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilConvertToName] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilNameModifier] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilScopeNameModifier] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [freeFoilTermConfigs] :: FreeFoilConfig -> [FreeFoilTermConfig]
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [intToRawIdentName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawBindingName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawIdentName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawQuantifiedNames] :: FreeFoilConfig -> [Name]
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawScopeName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawScopeToTermName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawSubScopeNames] :: FreeFoilTermConfig -> [Name]
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawSubTermNames] :: FreeFoilTermConfig -> [Name]
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawTermName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawTermToScopeName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawVarConName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [rawVarIdentToTermName] :: FreeFoilTermConfig -> Name
+ Control.Monad.Free.Foil.TH.MkFreeFoil: [signatureNameModifier] :: FreeFoilConfig -> String -> String
+ Control.Monad.Free.Foil.TH.MkFreeFoil: data FreeFoilConfig
+ Control.Monad.Free.Foil.TH.MkFreeFoil: data FreeFoilTermConfig
+ Control.Monad.Free.Foil.TH.MkFreeFoil: mkFreeFoil :: FreeFoilConfig -> Q [Dec]
+ Control.Monad.Free.Foil.TH.MkFreeFoil: mkFreeFoilConversions :: FreeFoilConfig -> Q [Dec]
- Control.Monad.Free.Foil: convertFromAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> AST binder sig n -> rawTerm
+ Control.Monad.Free.Foil: convertFromAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> AST binder sig n -> rawTerm
- Control.Monad.Free.Foil: convertFromScopedAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> ScopedAST binder sig n -> (rawPattern, rawScopedTerm)
+ Control.Monad.Free.Foil: convertFromScopedAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> ScopedAST binder sig n -> (rawPattern, rawScopedTerm)
- Control.Monad.Free.Foil.TH.PatternSynonyms: mkPatternSynonym :: Type -> Name -> Name -> Con -> Q [Dec]
+ Control.Monad.Free.Foil.TH.PatternSynonyms: mkPatternSynonym :: Type -> Name -> Name -> Con -> Q [(Name, Dec)]

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # CHANGELOG for `free-foil` +# 0.2.0 — 2024-10-27++- Generate [`COMPLETE` pragma](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pragmas.html#complete-pragmas) in `mkPatternSynonyms` (see [#26](https://github.com/fizruk/free-foil/pull/26))+- Polykind `ZipMatchK` class with default generic implementation via [`kind-generics`](https://hackage.haskell.org/package/kind-generics) (see [#27](https://github.com/fizruk/free-foil/pull/27))+- New experimental TH generation for Free Foil with support for rich syntax in `Control.Monad.Free.Foil.TH.MkFreeFoil` (see [#28](https://github.com/fizruk/free-foil/pull/28))+ # 0.1.0 — 2024-08-18  - Generalize functions for binders, support general patterns (see [#16](https://github.com/fizruk/free-foil/pull/16))
free-foil.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.36.0.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack  name:           free-foil-version:        0.1.0+version:        0.2.0 synopsis:       Efficient Type-Safe Capture-Avoiding Substitution for Free (Scoped Monads) description:    Please see the README on GitHub at <https://github.com/fizruk/free-foil#readme> category:       Parsing@@ -40,8 +40,10 @@       Control.Monad.Foil.TH.Util       Control.Monad.Free.Foil       Control.Monad.Free.Foil.Example+      Control.Monad.Free.Foil.Generic       Control.Monad.Free.Foil.TH       Control.Monad.Free.Foil.TH.Convert+      Control.Monad.Free.Foil.TH.MkFreeFoil       Control.Monad.Free.Foil.TH.PatternSynonyms       Control.Monad.Free.Foil.TH.Signature       Control.Monad.Free.Foil.TH.ZipMatch@@ -56,6 +58,7 @@     , bifunctors     , containers     , deepseq+    , kind-generics >=0.5.0     , template-haskell >=2.21.0.0     , text >=1.2.3.1   default-language: Haskell2010@@ -75,6 +78,7 @@     , deepseq     , doctest-parallel     , free-foil+    , kind-generics >=0.5.0     , template-haskell >=2.21.0.0     , text >=1.2.3.1   default-language: Haskell2010@@ -94,6 +98,7 @@     , containers     , deepseq     , free-foil+    , kind-generics >=0.5.0     , template-haskell >=2.21.0.0     , text >=1.2.3.1   default-language: Haskell2010
src/Control/Monad/Foil.hs view
@@ -47,7 +47,10 @@   Substitution,   lookupSubst,   identitySubst,+  voidSubst,   addSubst,+  addSubstPattern,+  addSubstList,   addRename,   -- * Unification of binders   UnifyNameBinders(..),@@ -66,6 +69,10 @@   emptyNameMap,   lookupName,   addNameBinder,+  nameMapToSubstitution,+  addNameBinders,+  addNameBinderList,+  NameBinderList(..),   -- * Constraints   Ext,   ExtEvidence(..),
src/Control/Monad/Foil/Internal.hs view
@@ -708,6 +708,35 @@     -- ^ Continuation, accepting result for the entire pattern and a (possibly refreshed) pattern.     -> r +-- | Auxiliary data structure for collecting name binders. Used in 'nameBinderListOf'.+newtype WithNameBinderList r n l (o :: S) (o' :: S) = WithNameBinderList (NameBinderList l r -> NameBinderList n r)++-- | Empty list of name binders (identity).+idWithNameBinderList :: DExt o o' => WithNameBinderList r n n o o'+idWithNameBinderList = WithNameBinderList id++-- | Concatenating lists of name binders (compose).+compWithNameBinderList+  :: (DExt o o', DExt o' o'')+  => WithNameBinderList r n i o o'+  -> WithNameBinderList r i l o' o''+  -> WithNameBinderList r n l o o''+compWithNameBinderList (WithNameBinderList f) (WithNameBinderList g) =+  WithNameBinderList (f . g)++-- | Collect name binders of a generalized pattern into a name binder list,+-- which can be more easily traversed.+nameBinderListOf :: (CoSinkable binder) => binder n l -> NameBinderList n l+nameBinderListOf pat = withPattern+  (\_scope' binder k ->+    unsafeAssertFresh binder $ \binder' ->+      k (WithNameBinderList (NameBinderListCons binder)) binder')+  idWithNameBinderList+  compWithNameBinderList+  emptyScope+  pat+  (\(WithNameBinderList f) _ -> f NameBinderListEmpty)+ instance CoSinkable NameBinder where   coSinkabilityProof _rename (UnsafeNameBinder name) cont =     cont unsafeCoerce (UnsafeNameBinder name)@@ -733,6 +762,10 @@   :: InjectName e => Substitution e i i identitySubst = UnsafeSubstitution IntMap.empty +-- | An empty substitution from an empty scope.+voidSubst :: Substitution e VoidS n+voidSubst = UnsafeSubstitution IntMap.empty+ -- | Extend substitution with a particular mapping. addSubst   :: Substitution e i o@@ -742,6 +775,24 @@ addSubst (UnsafeSubstitution env) (UnsafeNameBinder (UnsafeName name)) ex   = UnsafeSubstitution (IntMap.insert name ex env) +addSubstPattern+  :: CoSinkable binder+  => Substitution e i o+  -> binder i i'+  -> [e o]+  -> Substitution e i' o+addSubstPattern subst pat = addSubstList subst (nameBinderListOf pat)++addSubstList+  :: Substitution e i o+  -> NameBinderList i i'+  -> [e o]+  -> Substitution e i' o+addSubstList subst NameBinderListEmpty _ = subst+addSubstList subst (NameBinderListCons binder binders) (x:xs) =+  addSubstList (addSubst subst binder x) binders xs+addSubstList _ _ [] = error "cannot add a binder to Substitution since the value list does not have enough elements"+ -- | Add variable renaming to a substitution. -- This includes the performance optimization of eliding names mapped to themselves. addRename :: InjectName e => Substitution e i o -> NameBinder i i' -> Name o -> Substitution e i' o@@ -762,6 +813,29 @@ -- | An empty map belongs in the empty scope. emptyNameMap :: NameMap VoidS a emptyNameMap = NameMap IntMap.empty++-- | Convert a 'NameMap' of expressions into a 'Substitution'.+nameMapToSubstitution :: NameMap i (e o) -> Substitution e i o+nameMapToSubstitution (NameMap m) = (UnsafeSubstitution m)++-- | Extend a map with multiple mappings (by repeatedly applying 'addNameBinder').+--+-- Note that the input list is expected to have __at least__ the same number of elements+-- as there are binders in the input pattern (generalized binder).+addNameBinders :: CoSinkable binder => binder n l -> [a] -> NameMap n a -> NameMap l a+addNameBinders pat = addNameBinderList (nameBinderListOf pat)++-- | Extend a map with multiple mappings (by repeatedly applying 'addNameBinder').+--+-- Note that the input list is expected to have __at least__ the same number of elements+-- as there are binders in the input name binder list.+--+-- See also 'addNameBinders' for a generalized version.+addNameBinderList :: NameBinderList n l -> [a] -> NameMap n a -> NameMap l a+addNameBinderList NameBinderListEmpty _ = id+addNameBinderList (NameBinderListCons binder binders) (x:xs) =+  addNameBinderList binders xs . addNameBinder binder x+addNameBinderList _ [] = error "cannot add a binder to NameMap since the value list does not have enough elements"  -- | Looking up a name should always succeed. --
src/Control/Monad/Free/Foil.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE DataKinds             #-}-{-# LANGUAGE RankNTypes             #-} {-# LANGUAGE DeriveAnyClass        #-} {-# LANGUAGE DeriveGeneric         #-} {-# LANGUAGE FlexibleContexts      #-}@@ -9,6 +8,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds             #-} {-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes            #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE StandaloneDeriving    #-} {-# LANGUAGE UndecidableInstances  #-}@@ -122,6 +122,20 @@               subst' = extendSubst subst            in ScopedAST binder' (Foil.rbind scope' body subst') +-- | Substitution for a single generalized pattern.+substitutePattern+  :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder', Foil.CoSinkable binder)+  => Foil.Scope o                           -- ^ Resulting scope.+  -> Foil.Substitution (AST binder sig) n o -- ^ Environment mapping names in scope @n@.+  -> binder' n i                            -- ^ Binders that extend scope @n@ to scope @i@.+  -> [AST binder sig o]                     -- ^ A list of terms intended to serve as+  -> AST binder sig i+  -> AST binder sig o+substitutePattern scope env binders args body =+  substitute scope env' body+  where+    env' = Foil.addSubstPattern env binders args+ -- * \(\alpha\)-equivalence  -- | Refresh (force) all binders in a term, minimizing the used indices.@@ -338,7 +352,7 @@   -- ^ Peel back one layer of syntax.   -> (rawIdent -> rawTerm)   -- ^ Convert identifier into a raw variable term.-  -> (forall x y. (Int -> rawIdent) -> binder x y -> rawPattern)+  -> (forall x y. binder x y -> rawPattern)   -- ^ Convert scope-safe pattern into a raw pattern.   -> (rawTerm -> rawScopedTerm)   -- ^ Wrap raw term into a scoped term.@@ -362,7 +376,7 @@   -- ^ Peel back one layer of syntax.   -> (rawIdent -> rawTerm)   -- ^ Convert identifier into a raw variable term.-  -> (forall x y. (Int -> rawIdent) -> binder x y -> rawPattern)+  -> (forall x y. binder x y -> rawPattern)   -- ^ Convert scope-safe pattern into a raw pattern.   -> (rawTerm -> rawScopedTerm)   -- ^ Wrap raw term into a scoped term.@@ -373,5 +387,5 @@   -> (rawPattern, rawScopedTerm) convertFromScopedAST fromSig fromVar makePattern makeScoped f = \case   ScopedAST binder body ->-    ( makePattern f binder+    ( makePattern binder     , makeScoped (convertFromAST fromSig fromVar makePattern makeScoped f body))
+ src/Control/Monad/Free/Foil/Generic.hs view
@@ -0,0 +1,196 @@+{-# OPTIONS_GHC -Wno-missing-methods #-}+{-# LANGUAGE AllowAmbiguousTypes      #-}+{-# LANGUAGE ConstraintKinds          #-}+{-# LANGUAGE DataKinds                #-}+{-# LANGUAGE DefaultSignatures        #-}+{-# LANGUAGE FlexibleContexts         #-}+{-# LANGUAGE FlexibleInstances        #-}+{-# LANGUAGE GADTs                    #-}+{-# LANGUAGE InstanceSigs             #-}+{-# LANGUAGE MultiParamTypeClasses    #-}+{-# LANGUAGE PolyKinds                #-}+{-# LANGUAGE RankNTypes               #-}+{-# LANGUAGE ScopedTypeVariables      #-}+{-# LANGUAGE StandaloneKindSignatures #-}+{-# LANGUAGE TypeApplications         #-}+{-# LANGUAGE TypeFamilies             #-}+{-# LANGUAGE TypeOperators            #-}+{-# LANGUAGE UndecidableInstances     #-}+module Control.Monad.Free.Foil.Generic where++import           Data.Kind              (Constraint, Type)+import           Generics.Kind+import           Generics.Kind.Examples ()+import           GHC.TypeError++type ZipLoT :: LoT k -> LoT k -> LoT k+type family ZipLoT as bs where+  ZipLoT LoT0 LoT0 = LoT0+  ZipLoT (a :&&: as) (b :&&: bs) = ((a, b) :&&: ZipLoT as bs)++type Mappings :: LoT k -> LoT k -> LoT k -> Type+data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k) where+  M0 :: Mappings LoT0 LoT0 LoT0+  (:^:) :: (a -> b -> Maybe c) -> Mappings as bs cs -> Mappings (a :&&: as) (b :&&: bs) (c :&&: cs)++class PairMappings (as :: LoT k) (bs :: LoT k) where+  pairMappings :: Mappings as bs (ZipLoT as bs)++instance PairMappings LoT0 LoT0 where+  pairMappings = M0++instance PairMappings as bs => PairMappings ((a :: Type) :&&: as) ((b :: Type) :&&: bs) where+  pairMappings = (\x y -> Just (x, y)) :^: pairMappings++class ApplyMappings (v :: TyVar d Type) where+  applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d).+    Mappings as bs cs -> Interpret (Var v) as -> Interpret (Var v) bs -> Maybe (Interpret (Var v) cs)++instance ApplyMappings (VZ :: TyVar (Type -> tys) Type) where+  applyMappings (f :^: _) x y = f x y++instance ApplyMappings v => ApplyMappings (VS v :: TyVar (ty -> tys) Type) where+  applyMappings (_ :^: fs) x y = applyMappings @_ @v fs x y++genericZipMatchK :: forall f as bs.+    (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs)+    => f :@@: as -> f :@@: bs -> Maybe (f :@@: (ZipLoT as bs))+genericZipMatchK = genericZipMatchWithK @f @as @bs pairMappings++genericZipMatchWithK :: forall f as bs cs.+    (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)+    => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+genericZipMatchWithK mappings x y = toK @_ @f @cs <$> gzipMatchWith mappings+  (fromK @_ @f @as x)+  (fromK @_ @f @bs y)++genericZipMatch2+   :: forall sig scope scope' term term'.+   (GenericK sig, GZipMatch (RepK sig), ReqsZipMatch (RepK sig) (scope :&&: term :&&: 'LoT0) (scope' :&&: term' :&&: 'LoT0))+   => sig scope term -> sig scope' term' -> Maybe (sig (scope, scope') (term, term'))+genericZipMatch2 = genericZipMatchK @sig @(scope :&&: term :&&: 'LoT0) @(scope' :&&: term' :&&: 'LoT0)++zipMatchK :: forall f as bs. (ZipMatchK f, PairMappings as bs) => f :@@: as -> f :@@: bs -> Maybe (f :@@: ZipLoT as bs)+zipMatchK = zipMatchWithK @_ @f @as @bs pairMappings++class ZipMatchK (f :: k) where+  zipMatchWithK :: forall as bs cs. Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+  default zipMatchWithK :: forall as bs cs.+    (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)+    => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+  zipMatchWithK = genericZipMatchWithK @f @as @bs @cs++zipMatchViaEq :: Eq a => Mappings as bs cs -> a -> a -> Maybe a+zipMatchViaEq _ x y+  | x == y = Just x+  | otherwise = Nothing++zipMatchViaChooseLeft :: Mappings as bs cs -> a -> a -> Maybe a+zipMatchViaChooseLeft _ x _ = Just x++-- instance ZipMatchK (,)     -- missing GenericK instance upstream+instance ZipMatchK []+instance ZipMatchK Maybe+instance ZipMatchK Either+instance ZipMatchK a => ZipMatchK (Either a)++type ReqsZipMatch f as bs = ReqsZipMatchWith f as bs (ZipLoT as bs)+class GZipMatch (f :: LoT k -> Type) where+  type ReqsZipMatchWith f (as :: LoT k) (bs :: LoT k) (cs :: LoT k) :: Constraint+  gzipMatchWith :: ReqsZipMatchWith f as bs cs => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)++instance GZipMatch V1 where+  type ReqsZipMatchWith V1 as bs cs = ()+  gzipMatchWith _ _ _ = error "impossible: Generics.Kind.V1 value!" -- FIXME: should be absurd++instance GZipMatch U1 where+  type ReqsZipMatchWith U1 as bs cs = ()+  gzipMatchWith _ U1 U1 = Just U1++instance GZipMatch f => GZipMatch (M1 i c f) where+  type ReqsZipMatchWith (M1 i c f) as bs cs = ReqsZipMatchWith f as bs cs+  gzipMatchWith g (M1 x) (M1 y) = M1 <$> gzipMatchWith g x y++instance (GZipMatch f, GZipMatch g) => GZipMatch (f :+: g) where+  type ReqsZipMatchWith (f :+: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)+  gzipMatchWith g (L1 x) (L1 y) = L1 <$> gzipMatchWith g x y+  gzipMatchWith g (R1 x) (R1 y) = R1 <$> gzipMatchWith g x y+  gzipMatchWith _ _ _           = Nothing++instance (GZipMatch f, GZipMatch g) => GZipMatch (f :*: g) where+  type ReqsZipMatchWith (f :*: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)+  gzipMatchWith g (x :*: y) (x' :*: y') =+    liftA2 (:*:) (gzipMatchWith g x x') (gzipMatchWith g y y')++instance ZipMatchFields t => GZipMatch (Field t) where+  type ReqsZipMatchWith (Field t) as bs cs = ReqsZipMatchFieldsWith t as bs cs+  gzipMatchWith f x y = zipMatchFieldsWith f x y++instance GZipMatch f => GZipMatch (c :=>: f) where+  type ReqsZipMatchWith (c :=>: f) as bs cs = (ReqsZipMatchWith f as bs cs, Interpret c cs)+  -- really we want          = (Interpret c as, Interpret c bs) => (ReqsZipMatch f as bs, Interpret c (ZipLoT as bs))+  gzipMatchWith g (SuchThat x) (SuchThat y) = SuchThat <$> gzipMatchWith g x y++instance TypeError ('Text "Existentials are not supported")+         => GZipMatch (Exists k f) where+  type ReqsZipMatchWith (Exists k f) as bs cs = TypeError ('Text "Existentials are not supported")+  gzipMatchWith = undefined++class ZipMatchFields (t :: Atom d Type) where+  type ReqsZipMatchFieldsWith t (as :: LoT d) (bs :: LoT d) (cs :: LoT d) :: Constraint+  zipMatchFieldsWith :: ReqsZipMatchFieldsWith t as bs cs => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)++instance ApplyMappings v => ZipMatchFields (Var v) where+  -- this is always true, but GHC is not smart enough to know that, I think+  type ReqsZipMatchFieldsWith (Var v) as bs cs = () -- InterpretVar v cs ~ (InterpretVar v as, InterpretVar v bs))+  zipMatchFieldsWith g (Field x) (Field y) = Field <$> applyMappings @_ @v g x y++instance ZipMatchK k => ZipMatchFields (Kon k) where+  type ReqsZipMatchFieldsWith (Kon k) as bs cs = ()+  zipMatchFieldsWith _ (Field l) (Field r) = Field <$> zipMatchWithK @_ @k M0 l r++instance (ZipMatchFields t, ZipMatchK k) => ZipMatchFields (Kon k :@: t) where+  type ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs = ReqsZipMatchFieldsWith t as bs cs++  zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs =>+    Mappings as bs cs -> Field (Kon k :@: t) as -> Field (Kon k :@: t) bs -> Maybe (Field (Kon k :@: t) cs)+  zipMatchFieldsWith g (Field l) (Field r) =+    Field <$> zipMatchWithK @_ @k @(Interpret t as :&&: LoT0) @(Interpret t bs :&&: LoT0) @(Interpret t cs :&&: LoT0)+      ((\ll rr -> unField @t <$> zipMatchFieldsWith g (Field ll) (Field rr)) :^: M0) l r++instance (ZipMatchFields t1, ZipMatchFields t2, ZipMatchK k) => ZipMatchFields ((Kon k :@: t1) :@: t2) where+  type ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs = (ReqsZipMatchFieldsWith t1 as bs cs, ReqsZipMatchFieldsWith t2 as bs cs)++  zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs =>+    Mappings as bs cs -> Field ((Kon k :@: t1) :@: t2) as -> Field ((Kon k :@: t1) :@: t2) bs -> Maybe (Field ((Kon k :@: t1) :@: t2) cs)+  zipMatchFieldsWith g (Field l) (Field r) =+    Field <$> zipMatchWithK @_ @k @(Interpret t1 as :&&: Interpret t2 as :&&: LoT0) @(Interpret t1 bs :&&: Interpret t2 bs :&&: LoT0) @(Interpret t1 cs :&&: Interpret t2 cs :&&: LoT0)+      ((\ll rr -> unField @t1 <$> zipMatchFieldsWith g (Field ll) (Field rr))+        :^: ((\ll rr -> unField @t2 <$> zipMatchFieldsWith g (Field ll) (Field rr))+        :^: M0)) l r++instance {-# OVERLAPPABLE #-} TypeError ('Text "Atom :@: is not supported by ZipMatchFields is a general form") => ZipMatchFields (f :@: t) where+  -- type ReqsZipMatchFieldsWith (f :@: t) as bs cs = TypeError ('Text "Atom :@: is not supported by ZipMatchFields is a general form")+  zipMatchFieldsWith = undefined++instance TypeError ('Text "Atom ForAll is not supported by ZipMatchFields") => ZipMatchFields (ForAll a) where+  type ReqsZipMatchFieldsWith (ForAll a) as bs cs = TypeError ('Text "Atom ForAll is not supported by ZipMatchFields")+  zipMatchFieldsWith = undefined+instance TypeError ('Text "Atom :=>>: is not supported by ZipMatchFields") => ZipMatchFields (c :=>>: a) where+  type ReqsZipMatchFieldsWith (c :=>>: a) as bs cs = TypeError ('Text "Atom :=>>: is not supported by ZipMatchFields")+  zipMatchFieldsWith = undefined+instance TypeError ('Text "Atom Eval is not supported by ZipMatchFields") => ZipMatchFields (Eval a) where+  type ReqsZipMatchFieldsWith (Eval a) as bs cs = TypeError ('Text "Atom Eval is not supported by ZipMatchFields")+  zipMatchFieldsWith = undefined++-- instance ZipMatchFields (ForAll f) where+--   type ReqsZipMatchFields (ForAll f) as bs = ???+--   zipMatchFields = ???++-- instance ZipMatchFields (c :=>>: f) where+--   type ReqsZipMatchFields (c :=>>: f) as bs = ???+--   zipMatchFields = ???++-- instance ZipMatchFields (Eval f) where+--   type ReqsZipMatchFields (Eval f) as bs = ???+--   zipMatchFields = ???
+ src/Control/Monad/Free/Foil/TH/MkFreeFoil.hs view
@@ -0,0 +1,1310 @@+{-# LANGUAGE LambdaCase      #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns    #-}+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}+{-# HLINT ignore "Use ++" #-}+-- | Template Haskell generation for Free Foil (generic scope-safe representation of syntax).+module Control.Monad.Free.Foil.TH.MkFreeFoil (+  FreeFoilConfig(..),+  FreeFoilTermConfig(..),+  mkFreeFoil,+  mkFreeFoilConversions,+) where++import           Language.Haskell.TH+import           Language.Haskell.TH.Syntax (addModFinalizer)++import           Control.Monad              (forM, forM_, when)+import qualified Control.Monad.Foil         as Foil+import           Control.Monad.Foil.TH.Util+import qualified Control.Monad.Free.Foil    as Foil+import           Data.Bifunctor+import           Data.List                  (find, unzip4, (\\), nub)+import           Data.Maybe                 (catMaybes, mapMaybe)+import Data.Map (Map)+import qualified Data.Map as Map+import qualified GHC.Generics               as GHC++-- | Config for the Template Haskell generation of data types,+-- pattern synonyms, and conversion functions for the Free Foil representation,+-- based on a raw recursive representation.+data FreeFoilConfig = FreeFoilConfig+  { rawQuantifiedNames        :: [Name]+  -- ^ Names of raw types that may include other binders and terms as components.+  -- Some examples of syntax that might be suitable here:+  --+  --  1. a type scheme in HM-style type system (to explicitly disallow nested forall)+  --  2. defining equation of a function (which itself is not a term)+  --  3. data or type synonym declaration (which itself is not a type)+  --  4. unification constraints (quantified or not)+  , freeFoilTermConfigs       :: [FreeFoilTermConfig]+  -- ^ Configurations for each term (e.g. expressions, types) group.+  , freeFoilNameModifier      :: String -> String+  -- ^ Name modifier for the Free Foil conterpart of a raw type name.+  -- Normally, this is just 'id'.+  , freeFoilScopeNameModifier :: String -> String+  -- ^ Name modifier for the scoped Free Foil conterpart of a raw type name.+  -- Normally, this is something like @("Scoped" ++)@.+  , signatureNameModifier     :: String -> String+  -- ^ Name modifier for the signature conterpart of a raw type name or raw constructor name.+  -- Normally, this is something like @(++ "Sig")@.+  , freeFoilConNameModifier   :: String -> String+  -- ^ Name modifier for the Free Foil conterpart (pattern synonym) of a raw constructor name.+  -- Normally, this is just 'id'.+  , freeFoilConvertToName     :: String -> String+  -- ^ Name of a conversion function (from raw to scope-safe) for a raw type name.+  -- Normally, this is something like @("to" ++)@.+  , freeFoilConvertFromName   :: String -> String+  -- ^ Name of a conversion function (from scope-safe to raw) for a raw type name.+  -- Normally, this is something like @("from" ++)@.+  }++-- | Config for a single term group,+-- for the Template Haskell generation of data types,+-- pattern synonyms, and conversion functions for the Free Foil representation,+-- based on a raw recursive representation.+data FreeFoilTermConfig = FreeFoilTermConfig+  { rawIdentName          :: Name+    -- ^ The type name for the identifiers.+    -- When identifiers occur in a term, they are converted to 'Foil.Name' (with an appropriate type-level scope parameter).+    -- When identifiers occur in a pattern, they are converted to 'Foil.NameBinder' (with appropriate type-level scope parameters).+  , rawTermName           :: Name+    -- ^ The type name for the term.+    -- This will be the main recursive type to be converted into an 'Foil.AST'.+  , rawBindingName        :: Name+    -- ^ The type name for the binders (patterns).+    -- This will be the main binder type to used in 'Foil.AST'-representation of the terms.+  , rawScopeName          :: Name+    -- ^ The type name for the scoped term.+    -- This will be replaced with either 'Foil.ScopedAST' (with outer scope) or 'Foil.AST' (with inner scope)+    -- depending on its occurrence in a regular (sub)term or some quantified syntax.+  , rawVarConName         :: Name+    -- ^ The constructor name for the variables in a term.+    -- This constructor will be replaced with the standard 'Foil.Var'.+    -- It is expected to have exactly one field of type 'rawIdentName'.+  , rawSubTermNames       :: [Name]+    -- ^ Type names for subterm syntax.+    -- This will rely on the main term type ('rawTermName') for recursive occurrences.+    -- Template Haskell will also generate signatures for these.+  , rawSubScopeNames      :: [Name]+    -- ^ Type names for scoped subterm syntax.+    -- This will rely on the main term type ('rawTermName') for recursive occurrences.+    -- Template Haskell will also generate signatures for these.+  , intToRawIdentName     :: Name+    -- ^ Name of a function that converts 'Int' to a raw identifier.+    -- Normally, this is something like @(\i -> VarIdent ("x" ++ show i))@.+    -- This is required to generate standard conversions from scope-safe to raw representation.+  , rawVarIdentToTermName :: Name+    -- ^ Name of a function that converts a raw identifier into a raw term.+    -- Normally, this is some kind of @Var@ or @TypeVar@ data constructor.+    -- This is required to generate standard conversions from scope-safe to raw representation.+  , rawTermToScopeName    :: Name+    -- ^ Name of a function that converts a raw term into a raw scoped term.+    -- Normally, this is some kind of @ScopedTerm@ or @ScopedType@ data constructor.+  , rawScopeToTermName    :: Name+    -- ^ Name of a function that extracts a raw term from a raw scoped term.+    -- Normally, this is something like @(\(ScopedTerm term) -> term)@.+  }++toFreeFoilName :: FreeFoilConfig -> Name -> Name+toFreeFoilName FreeFoilConfig{..} name = mkName (freeFoilNameModifier (nameBase name))++toFreeFoilNameFrom :: FreeFoilConfig -> Name -> Name+toFreeFoilNameFrom FreeFoilConfig{..} name = mkName (freeFoilConvertFromName (nameBase name))++toFreeFoilNameTo :: FreeFoilConfig -> Name -> Name+toFreeFoilNameTo FreeFoilConfig{..} name = mkName (freeFoilConvertToName (nameBase name))++toFreeFoilScopedName :: FreeFoilConfig -> Name -> Name+toFreeFoilScopedName FreeFoilConfig{..} name = mkName (freeFoilScopeNameModifier (nameBase name))++toSignatureName :: FreeFoilConfig -> Name -> Name+toSignatureName FreeFoilConfig{..} name = mkName (signatureNameModifier (nameBase name))++toConName :: FreeFoilConfig -> Name -> Name+toConName FreeFoilConfig{..} name = mkName (freeFoilConNameModifier (nameBase name))++lookupIdentName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupIdentName name = find (\FreeFoilTermConfig{..} -> rawIdentName == name)++lookupTermName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupTermName name = find (\FreeFoilTermConfig{..} -> rawTermName == name)++lookupSubTermName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupSubTermName name = find (\FreeFoilTermConfig{..} -> name `elem` rawSubTermNames)++lookupSubScopeName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupSubScopeName name = find (\FreeFoilTermConfig{..} -> name `elem` rawSubScopeNames)++lookupBindingName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupBindingName name = find (\FreeFoilTermConfig{..} -> rawBindingName == name)++lookupScopeName :: Name -> [FreeFoilTermConfig] -> Maybe FreeFoilTermConfig+lookupScopeName name = find (\FreeFoilTermConfig{..} -> rawScopeName == name)++data Sort+  = SortBinder | SortTerm | SortSubTerm++toFreeFoilType :: Sort -> FreeFoilConfig -> Type -> Type -> Type -> Type+toFreeFoilType isBinder config@FreeFoilConfig{..} outerScope innerScope = go+  where+    go = \case+      PeelConT typeName (map go -> typeParams)+        | typeName `elem` rawQuantifiedNames ->+            PeelConT (toFreeFoilName config typeName) (typeParams ++ [outerScope])+        | typeName `elem` map rawIdentName freeFoilTermConfigs ->+            case isBinder of+              SortBinder -> PeelConT ''Foil.NameBinder [outerScope, innerScope]+              _          -> PeelConT ''Foil.Name [outerScope]+        | Just _ <- lookupTermName typeName freeFoilTermConfigs ->+            PeelConT (toFreeFoilName config typeName) (typeParams ++ [outerScope])+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs ->+            PeelConT (toFreeFoilName config typeName) (typeParams ++ [outerScope, innerScope])+        | Just FreeFoilTermConfig{..} <- lookupScopeName typeName freeFoilTermConfigs ->+            PeelConT (toFreeFoilName config rawTermName) (typeParams ++ [innerScope])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs ->+            PeelConT (toFreeFoilName config typeName) (typeParams ++ [outerScope])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs ->+            PeelConT (toFreeFoilName config typeName) (typeParams ++ [innerScope])+      ForallT bndrs ctx type_ -> ForallT bndrs ctx (go type_)+      ForallVisT bndrs type_ -> ForallVisT bndrs (go type_)+      AppT f x -> AppT (go f) (go x)+      AppKindT f k -> AppKindT (go f) k+      SigT t k -> SigT (go t) k+      t@ConT{} -> t+      t@VarT{} -> t+      t@PromotedT{} -> t+      InfixT l op r -> InfixT (go l) op (go r)+      UInfixT l op r -> UInfixT (go l) op (go r)+      PromotedInfixT l op r -> PromotedInfixT (go l) op (go r)+      PromotedUInfixT l op r -> PromotedUInfixT (go l) op (go r)+      ParensT t -> ParensT (go t)+      t@TupleT{} -> t+      t@UnboxedTupleT{} -> t+      t@UnboxedSumT{} -> t+      t@ArrowT{} -> t+      t@MulArrowT{} -> t+      t@EqualityT{} -> t+      t@ListT{} -> t+      t@PromotedTupleT{} -> t+      t@PromotedNilT{} -> t+      t@PromotedConsT{} -> t+      t@StarT{} -> t+      t@ConstraintT{} -> t+      t@LitT{} -> t+      t@WildCardT{} -> t+      ImplicitParamT s t -> ImplicitParamT s (go t)++toFreeFoilSigType :: Sort -> FreeFoilConfig -> Type -> Type -> Type -> Maybe Type+toFreeFoilSigType sort config@FreeFoilConfig{..} scope term = go+  where+    go :: Type -> Maybe Type+    go = \case+      PeelConT _typeName (mapM go -> Nothing) ->+        error "bad type params"+      PeelConT typeName (mapM go -> Just typeParams)+        | Just _ <- lookupTermName typeName freeFoilTermConfigs ->+            case sort of+              SortSubTerm -> Just (PeelConT (toSignatureName config typeName) (typeParams ++ [scope, term]))+              _           -> Just term+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs ->+            Nothing+        | Just _ <- lookupScopeName typeName freeFoilTermConfigs ->+            Just scope+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs ->+            Just (PeelConT (toSignatureName config typeName) (typeParams ++ [scope, term]))+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs ->+            Just (PeelConT (toSignatureName config typeName) (typeParams ++ [scope, term]))+      ForallT bndrs ctx type_ -> ForallT bndrs ctx <$> go type_+      ForallVisT bndrs type_ -> ForallVisT bndrs <$> go type_+      AppT f x -> AppT <$> go f <*> go x+      AppKindT f k -> AppKindT <$> go f <*> pure k+      SigT t k -> SigT <$> go t <*> pure k+      t@ConT{} -> pure t+      t@VarT{} -> pure t+      t@PromotedT{} -> pure t+      InfixT l op r -> InfixT <$> go l <*> pure op <*> go r+      UInfixT l op r -> UInfixT <$> go l <*> pure op <*> go r+      PromotedInfixT l op r -> PromotedInfixT <$> go l <*> pure op <*> go r+      PromotedUInfixT l op r -> PromotedUInfixT <$> go l <*> pure op <*> go r+      ParensT t -> ParensT <$> go t+      t@TupleT{} -> pure t+      t@UnboxedTupleT{} -> pure t+      t@UnboxedSumT{} -> pure t+      t@ArrowT{} -> pure t+      t@MulArrowT{} -> pure t+      t@EqualityT{} -> pure t+      t@ListT{} -> pure t+      t@PromotedTupleT{} -> pure t+      t@PromotedNilT{} -> pure t+      t@PromotedConsT{} -> pure t+      t@StarT{} -> pure t+      t@ConstraintT{} -> pure t+      t@LitT{} -> pure t+      t@WildCardT{} -> pure t+      ImplicitParamT s t -> ImplicitParamT s <$> go t++toFreeFoilCon :: FreeFoilConfig -> Type -> Type -> Type -> Con -> Q Con+toFreeFoilCon config rawRetType outerScope innerScope = go+  where+    goType = toFreeFoilType SortTerm config outerScope innerScope+    go = \case+      GadtC conNames argTypes retType -> do+        let newConNames = map (toConName config) conNames+        forM_ (zip conNames newConNames) $ \(conName, newConName) ->+          addModFinalizer $ putDoc (DeclDoc newConName)+            ("Corresponds to '" ++ show conName ++ "'.")+        return (GadtC newConNames (map (fmap goType) argTypes) (goType retType))+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC params ctx con -> ForallC params ctx <$> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++toFreeFoilSigCon :: FreeFoilConfig -> FreeFoilTermConfig -> Name -> Type -> Type -> Type -> Con -> Q (Maybe Con)+toFreeFoilSigCon config FreeFoilTermConfig{..} sigName rawRetType scope term = go+  where+    goType = toFreeFoilSigType SortTerm config scope term+    go = \case+      GadtC conNames argTypes retType+        | null newConNames -> pure Nothing+        | otherwise -> do+            forM_ (zip conNames newConNames) $ \(conName, newConName) ->+              addModFinalizer $ putDoc (DeclDoc newConName)+                ("Corresponds to '" ++ show conName ++ "'.")+            return (Just (GadtC newConNames newArgTypes theRetType))+        where+          newArgTypes = mapMaybe (traverse goType) argTypes+          newConNames =+            [ toSignatureName config rawConName+            | rawConName <- conNames+            , rawConName /= rawVarConName ]+          theRetType =+            case retType of+              PeelConT _rawTypeName (mapM goType -> Just params) ->+                PeelConT sigName (params ++ [scope, term])+              _ -> error "unexpected return type!"+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC params ctx con -> fmap (ForallC params ctx) <$> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++toFreeFoilBindingCon :: FreeFoilConfig -> Type -> Type -> Con -> Q Con+toFreeFoilBindingCon config rawRetType theOuterScope = go+  where+    goType = toFreeFoilType SortBinder config theOuterScope++    goTypeArgs :: Int -> Type -> [BangType] -> Q (Type, [BangType])+    goTypeArgs _ outerScope [] = pure (outerScope, [])+    goTypeArgs i outerScope ((bang_, rawArgType) : rawArgs) = do+      case rawArgType of+        PeelConT rawTypeName _rawTypeParams+          | rawTypeName `elem` map rawIdentName (freeFoilTermConfigs config) -> do+            innerScope <- VarT <$> newName ("i" <> show i)+            let argType = toFreeFoilType SortBinder config outerScope innerScope rawArgType+            (theInnerScope, argTypes) <- goTypeArgs (i + 1) innerScope rawArgs+            return (theInnerScope, ((bang_, argType) : argTypes))++          | Just _ <- lookupBindingName rawTypeName (freeFoilTermConfigs config) -> do+            innerScope <- VarT <$> newName ("i" <> show i)+            let argType = toFreeFoilType SortBinder config outerScope innerScope rawArgType+            (theInnerScope, argTypes) <- goTypeArgs (i + 1) innerScope rawArgs+            return (theInnerScope, ((bang_, argType) : argTypes))++        _ -> do+          let argType = toFreeFoilType SortBinder config outerScope outerScope rawArgType+          (theInnerScope, argTypes) <- goTypeArgs (i + 1) outerScope rawArgs+          return (theInnerScope, ((bang_, argType) : argTypes))++    go :: Con -> Q Con+    go = \case+      GadtC conNames argTypes retType -> do+        (theInnerScope, newArgs) <- goTypeArgs 0 theOuterScope argTypes+        let newConNames = map (toConName config) conNames+        forM_ (zip conNames newConNames) $ \(conName, newConName) ->+          addModFinalizer $ putDoc (DeclDoc newConName)+            ("Corresponds to '" ++ show conName ++ "'.")+        return (GadtC newConNames newArgs (goType theInnerScope retType))+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC params ctx con -> ForallC params ctx <$> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++termConToPat :: Name -> FreeFoilConfig -> FreeFoilTermConfig -> Con -> Q [([Name], Pat, Pat, [Exp])]+termConToPat rawTypeName config@FreeFoilConfig{..} FreeFoilTermConfig{..} = go+  where+    rawRetType = error "impossible happened!"++    fromArgType :: Type -> Q ([Name], [Pat], [Pat], [Exp])+    fromArgType = \case+      PeelConT typeName _params+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs -> do+            return ([], [], [], [])+        | Just _ <- lookupScopeName typeName freeFoilTermConfigs -> do+            binder <- newName "binder"+            body <- newName "body"+            return ([binder, body], [ConP 'Foil.ScopedAST [] [VarP binder, VarP body]], [TupP [VarP binder, VarP body]], [VarE binder, VarE body])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+        | typeName == '[] -> do+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [ConE 'False])+      AppT _ (PeelConT typeName _params)+        -- | Just _ <- lookupTermName typeName freeFoilTermConfigs -> do+        --     let funName = toFreeFoilNameFrom config typeName+        --     x <- newName "x"+        --     return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+      _ -> do+        x <- newName "x"+        return ([x], [VarP x], [VarP x], [VarE x])++    go :: Con -> Q [([Name], Pat, Pat, [Exp])]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        forM conNames $ \conName -> do+          let newConName = toSignatureName config conName+          (concat -> vars, concat -> pats, concat -> pats', concat -> exps) <- unzip4 <$>+            mapM (fromArgType . snd) rawArgTypes+          return $+            if rawTypeName == rawTermName+              then [ (vars, ConP 'Foil.Node [] [ConP newConName [] pats], ConP newConName [] pats', exps) ]+              else [ (vars, ConP newConName [] pats, ConP newConName [] pats', exps) ]+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++termConToPatBinding :: Name -> FreeFoilConfig -> FreeFoilTermConfig -> Con -> Q [([Name], Pat, Pat, [Exp])]+termConToPatBinding rawTypeName config@FreeFoilConfig{..} FreeFoilTermConfig{..} = go+  where+    rawRetType = error "impossible happened!"++    fromArgType :: Type -> Q ([Name], [Pat], [Pat], [Exp])+    fromArgType = \case+      PeelConT typeName _params+        | typeName == rawIdentName -> do+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE intToRawIdentName `AppE` (VarE 'Foil.nameId `AppE` (VarE 'Foil.nameOf `AppE` VarE x))])+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE funName `AppE` VarE x])+        | Just _ <- lookupScopeName typeName freeFoilTermConfigs -> do+            binder <- newName "binder"+            body <- newName "body"+            return ([binder, body], [ConP 'Foil.ScopedAST [] [VarP binder, VarP body]], [TupP [VarP binder, VarP body]], [VarE binder, VarE body])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+      AppT _ (PeelConT typeName _params)+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+      _ -> do+        x <- newName "x"+        return ([x], [VarP x], [VarP x], [VarE x])++    go :: Con -> Q [([Name], Pat, Pat, [Exp])]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        forM conNames $ \conName -> do+          let newConName = toFreeFoilName config conName+          (concat -> vars, concat -> pats, concat -> pats', concat -> exps) <- unzip4 <$>+            mapM (fromArgType . snd) rawArgTypes+          return $+            if rawTypeName == rawTermName+              then [ (vars, ConP 'Foil.Node [] [ConP newConName [] pats], ConP newConName [] pats', exps) ]+              else [ (vars, ConP newConName [] pats, ConP newConName [] pats', exps) ]+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++termConToPatQuantified :: FreeFoilConfig -> Con -> Q [([Name], Pat, Pat, [Exp])]+termConToPatQuantified config@FreeFoilConfig{..} = go+  where+    rawRetType = error "impossible happened!"++    fromArgType :: Type -> Q ([Name], [Pat], [Pat], [Exp])+    fromArgType = \case+      PeelConT typeName _params+        | Just _ <- lookupTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE funName `AppE` VarE x])+        | Just FreeFoilTermConfig{..} <- lookupScopeName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config rawTermName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE rawTermToScopeName `AppE` (VarE funName `AppE` VarE x)])+        | Just FreeFoilTermConfig{..} <- lookupIdentName typeName freeFoilTermConfigs -> do+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE intToRawIdentName `AppE` (VarE 'Foil.nameId `AppE` VarE x)])+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [VarE funName `AppE` VarE x])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameFrom config rawSigName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (VarE funName) (VarE x)])+      AppT _ (PeelConT typeName _params)+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameFrom config typeName+            x <- newName "x"+            return ([x], [VarP x], [VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+      _ -> do+        x <- newName "x"+        return ([x], [VarP x], [VarP x], [VarE x])++    go :: Con -> Q [([Name], Pat, Pat, [Exp])]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        forM conNames $ \conName -> do+          let newConName = toFreeFoilName config conName+          (concat -> vars, concat -> pats, concat -> pats', concat -> exps) <- unzip4 <$>+            mapM (fromArgType . snd) rawArgTypes+          return [ (vars, ConP newConName [] pats, ConP newConName [] pats', exps) ]+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++mkPatternSynonym :: Name -> FreeFoilConfig -> FreeFoilTermConfig -> Type -> Con -> Q [(Name, [Dec])]+mkPatternSynonym rawTypeName config termConfig@FreeFoilTermConfig{..} rawRetType = go+  where+    go :: Con -> Q [(Name, [Dec])]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        forM (conNames \\ [rawVarConName]) $ \conName -> do+          let patName = toConName config conName+              rawConType = foldr (\x y -> AppT (AppT ArrowT x) y) rawRetType (map snd rawArgTypes)+              outerScope = VarT (mkName "o")+              innerScope+                | rawTypeName `elem` rawSubScopeNames = outerScope+                | otherwise = VarT (mkName "i")+          [(vars, pat, _, _)] <- termConToPat rawTypeName config termConfig (GadtC [conName] rawArgTypes rawRetType)    -- FIXME: unsafe matching!+          addModFinalizer $ putDoc (DeclDoc patName)+            ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Pattern synonym for an '" ++ show ''Foil.AST ++ "' node of type '" ++ show conName ++ "'.")+          return [(patName,+            [ PatSynSigD patName (toFreeFoilType SortTerm config outerScope innerScope rawConType)+            , PatSynD patName (PrefixPatSyn vars) ImplBidir pat+            ])]++      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con  -- FIXME: params and ctx!+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++toFreeFoilClauseFrom :: Name -> FreeFoilConfig -> FreeFoilTermConfig -> Type -> Con -> Q [Clause]+toFreeFoilClauseFrom rawTypeName config termConfig@FreeFoilTermConfig{..} rawRetType = go+  where+    go = \case+      GadtC conNames rawArgTypes rawRetType' -> concat <$> do+        forM (conNames \\ [rawVarConName]) $ \conName -> do+          [(_vars, _pat, pat, exps)] <- termConToPat rawTypeName config termConfig+            (GadtC [conName] rawArgTypes rawRetType')    -- FIXME: unsafe matching!+          return [ Clause [pat] (NormalB (foldl AppE (ConE conName) exps)) [] ]++      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++toFreeFoilClauseFromBinding :: FreeFoilConfig -> FreeFoilTermConfig -> Type -> Con -> Q [Clause]+toFreeFoilClauseFromBinding config termConfig@FreeFoilTermConfig{..} rawRetType = go+  where+    go = \case+      GadtC conNames rawArgTypes rawRetType' -> concat <$> do+        forM (conNames \\ [rawVarConName]) $ \conName -> do+          [(_vars, _pat, pat, exps)] <- termConToPatBinding rawBindingName config termConfig+            (GadtC [conName] rawArgTypes rawRetType')    -- FIXME: unsafe matching!+          return [ Clause [pat] (NormalB (foldl AppE (ConE conName) exps)) [] ]++      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++toFreeFoilClauseFromQuantified :: FreeFoilConfig -> Type -> Con -> Q [Clause]+toFreeFoilClauseFromQuantified config rawRetType = go+  where+    go = \case+      GadtC conNames rawArgTypes rawRetType' -> concat <$> do+        forM conNames $ \conName -> do+          [(_vars, _pat, pat, exps)] <- termConToPatQuantified config+            (GadtC [conName] rawArgTypes rawRetType')    -- FIXME: unsafe matching!+          return [ Clause [pat] (NormalB (foldl AppE (ConE conName) exps)) [] ]++      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++-- | Generate scope-safe types and pattern synonyms for a given raw set of types:+--+--  1. Scope-safe quantified types (e.g. type schemas, defining equations of functions, unification constraints, data/type declarations)+--  2. Scope-safe terms, scoped terms, subterms, scoped subterms.+--  3. Scope-safe patterns.+--  4. Signatures for terms, subterms, and scoped subterms.+--  5. Pattern synonyms for terms, subterms, and scoped subterms.+mkFreeFoil :: FreeFoilConfig -> Q [Dec]+mkFreeFoil config@FreeFoilConfig{..} = concat <$> sequence+  [ mapM mkQuantifiedType rawQuantifiedNames+  , mapM mkBindingType freeFoilTermConfigs+  , concat <$> mapM mkSignatureTypes freeFoilTermConfigs+  , concat <$> mapM mkPatternSynonyms freeFoilTermConfigs+  ]+  where+    scope = mkName "scope"+    term = mkName "term"+    outerScope = mkName "o"+    innerScope = mkName "i"++    mkPatternSynonyms termConfig@FreeFoilTermConfig{..} = do+      ds <- mkPatternSynonyms' termConfig rawTermName+      ds' <- concat <$> mapM (mkPatternSynonyms' termConfig) (rawSubTermNames <> rawSubScopeNames)+      return (ds <> ds')++    mkPatternSynonyms' FreeFoilTermConfig{..} rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      let rawRetType = PeelConT rawName (map (VarT . tvarName) tvars)+      (unzip -> (patNames, decls)) <- concat <$> mapM (mkPatternSynonym rawName config FreeFoilTermConfig{..} rawRetType) cons+      let completeDecl+            | rawName == rawTermName = PragmaD (CompleteP ('Foil.Var : patNames) Nothing)+            | otherwise = PragmaD (CompleteP patNames Nothing)+      return (concat decls ++ [completeDecl])++    mkQuantifiedType rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      let name = toFreeFoilName config rawName+          rawRetType = PeelConT rawName (map (VarT . tvarName) tvars)+          newParams = tvars ++ [PlainTV outerScope BndrReq]+          toCon = toFreeFoilCon config rawRetType (VarT outerScope) (VarT innerScope)+      newCons <- mapM toCon cons+      addModFinalizer $ putDoc (DeclDoc name)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A scope-safe version of '" ++ show rawName ++ "'.")+      return (DataD [] name newParams Nothing newCons [])++    mkBindingType FreeFoilTermConfig{..} = do+      (tvars, cons) <- reifyDataOrNewtype rawBindingName+      let bindingName = toFreeFoilName config rawBindingName+          rawRetType = PeelConT rawBindingName (map (VarT . tvarName) tvars)+          newParams = tvars ++ [PlainTV outerScope BndrReq, PlainTV innerScope BndrReq]+          toCon = toFreeFoilBindingCon config rawRetType (VarT outerScope)+      newCons <- mapM toCon cons+      addModFinalizer $ putDoc (DeclDoc bindingName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A binding type, scope-safe version of '" ++ show rawBindingName ++ "'.")+      return (DataD [] bindingName newParams Nothing newCons [])++    mkSignatureTypes termConfig@FreeFoilTermConfig{..} = do+      sig <- mkSignatureType termConfig rawTermName+      subsigs <- concat <$> mapM (mkSignatureType termConfig) (rawSubTermNames <> rawSubScopeNames)+      return (sig ++ subsigs)++    mkSignatureType termConfig@FreeFoilTermConfig{..} rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      let sigName = toSignatureName config rawName+          tvars' = map (VarT . tvarName) tvars+          rawRetType = PeelConT rawName tvars'+          newParams = tvars ++ [PlainTV scope BndrReq, PlainTV term BndrReq]+          toCon = toFreeFoilSigCon config termConfig sigName rawRetType (VarT scope) (VarT term)+      newCons <- catMaybes <$> mapM toCon cons+      let bindingT = PeelConT (toFreeFoilName config rawBindingName) tvars'+          sigNameT = PeelConT (toSignatureName config rawTermName) tvars'+          astName = toFreeFoilName config rawName+          scopeName = toFreeFoilScopedName config rawName+          termAST = PeelConT ''Foil.AST [bindingT, sigNameT]+          scopedTermAST = PeelConT ''Foil.ScopedAST [bindingT, sigNameT]+          n = mkName "n"+      addModFinalizer $ putDoc (DeclDoc sigName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A signature based on '" ++ show rawName ++ "'.")+      addModFinalizer $ putDoc (DeclDoc astName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A scope-safe version of '" ++ show rawName ++ "'.")+      when (rawTermName == rawName) $ do+        addModFinalizer $ putDoc (DeclDoc scopeName)+          ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A scoped (and scope-safe) version of '" ++ show rawName ++ "'.")+      return $ concat+        [ [ DataD [] sigName newParams Nothing newCons [DerivClause Nothing [ConT ''GHC.Generic, ConT ''Functor, ConT ''Foldable, ConT ''Traversable]] ]+        , if rawTermName == rawName+            then [ TySynD astName   tvars termAST+                 , TySynD scopeName tvars scopedTermAST ]+            else [ TySynD astName   (tvars ++ [PlainTV n BndrReq])+                    (PeelConT sigName+                      (tvars' +++                      [ AppT scopedTermAST (VarT n)+                      , AppT termAST (VarT n) ])) ]+        ]++infixr 3 -->+(-->) :: Type -> Type -> Type+a --> b = AppT (AppT ArrowT a) b++reifyDataOrNewtype :: Name -> Q ([TyVarBndr BndrVis], [Con])+reifyDataOrNewtype name = reify name >>= \case+  TyConI (DataD _ctx _name tvars _kind cons _deriv) -> return (tvars, cons)+  TyConI (NewtypeD _ctx _name tvars _kind con _deriv) -> return (tvars, [con])+  _ -> error ("not a data or newtype: " ++ show name)++-- | Generate conversions to and from scope-safe representation:+--+--  1. Conversions for scope-safe quantified types (e.g. type schemas, defining equations of functions, unification constraints, data/type declarations)+--  2. Conversions for scope-safe terms, scoped terms, subterms, scoped subterms.+--  3. CPS-style conversions for scope-safe patterns.+--  4. Helpers for signatures of terms, subterms, and scoped subterms.+mkFreeFoilConversions :: FreeFoilConfig -> Q [Dec]+mkFreeFoilConversions config@FreeFoilConfig{..} = concat <$> sequence+  [ concat <$> mapM mkConvertFrom freeFoilTermConfigs+  , concat <$> mapM mkConvertFromQuantified rawQuantifiedNames+  , concat <$> mapM mkConvertTo freeFoilTermConfigs+  , concat <$> mapM mkConvertToQuantified rawQuantifiedNames+  ]+  where+    outerScope = mkName "o"+    innerScope = mkName "i"++    mkConvertFrom termConfig@FreeFoilTermConfig{..} = concat <$> sequence+      [ concat <$> mapM (mkConvertFromSig termConfig) (rawTermName : (rawSubTermNames <> rawSubScopeNames))+      , mkConvertFromBinding termConfig+      , concat <$> mapM (mkConvertFromSubTerm termConfig) (rawSubTermNames <> rawSubScopeNames)+      , mkConvertFromTerm termConfig+      ]++    mkConvertFromSig termConfig@FreeFoilTermConfig{..} rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      let rawSigName = toSignatureName config rawName+          funName = toFreeFoilNameFrom config rawSigName+          rawRetType = PeelConT rawName (map (VarT . tvarName) tvars)+          rawTermType = PeelConT rawTermName (map (VarT . tvarName) tvars)+          rawScopedTermType = PeelConT rawScopeName (map (VarT . tvarName) tvars)+          rawBindingType = PeelConT rawBindingName (map (VarT . tvarName) tvars)+          rawScopeType = TupleT 2 `AppT` rawBindingType `AppT` rawScopedTermType+      case toFreeFoilSigType SortSubTerm config rawScopeType rawTermType rawRetType of+        Just termType -> do+          clauses <- concat <$> mapM (toFreeFoilClauseFrom rawSigName config termConfig rawRetType) cons+          addModFinalizer $ putDoc (DeclDoc funName)+            ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A helper used to convert from scope-safe to raw representation.")+          return+            [ SigD funName (AppT (AppT ArrowT termType) rawRetType)+            , FunD funName clauses ]+        Nothing -> error "impossible happened"++    mkConvertFromTerm FreeFoilTermConfig{..} = do+      (tvars, _cons) <- reifyDataOrNewtype rawTermName+      let funName = toFreeFoilNameFrom config rawTermName+          rawSigName = toSignatureName config rawTermName+          funSigName = toFreeFoilNameFrom config rawSigName+          funBindingName = toFreeFoilNameFrom config rawBindingName+          rawTermType = PeelConT rawTermName (map (VarT . tvarName) tvars)+          termType =  toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawTermType+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+      return+        [ SigD funName (AppT (AppT ArrowT termType) rawTermType)+        , FunD funName [+            Clause [] (NormalB+              (VarE 'Foil.convertFromAST+                `AppE` VarE funSigName+                `AppE` VarE rawVarIdentToTermName+                `AppE` VarE funBindingName+                `AppE` VarE rawTermToScopeName+                `AppE` VarE intToRawIdentName)) []+          ]+        ]++    mkConvertFromSubTerm FreeFoilTermConfig{..} rawName = do+      (tvars, _cons) <- reifyDataOrNewtype rawName+      let funName = toFreeFoilNameFrom config rawName+          funSigName = toFreeFoilNameFrom config (toSignatureName config rawName)+          funTermName = toFreeFoilNameFrom config rawTermName+          funBindingName = toFreeFoilNameFrom config rawBindingName+          rawType = PeelConT rawName (map (VarT . tvarName) tvars)+          safeType =  toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawType+      binders <- newName "binders"+      body <- newName "body"+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+      return+        [ SigD funName (AppT (AppT ArrowT safeType) rawType)+        , FunD funName [+            Clause [] (NormalB $+              InfixE+              (Just (VarE funSigName))+              (VarE '(.))+              (Just (VarE 'bimap+                `AppE` LamE [ConP 'Foil.ScopedAST [] [VarP binders, VarP body]]+                  (TupE [ Just (VarE funBindingName `AppE` VarE binders)+                        , Just (VarE rawTermToScopeName `AppE` (VarE funTermName `AppE` VarE body))])+                `AppE` VarE funTermName))) []+          ]+        ]++    mkConvertFromQuantified rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      let funName = toFreeFoilNameFrom config rawName+          rawType = PeelConT rawName (map (VarT . tvarName) tvars)+          safeType = toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawType+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+      clauses <- concat <$> mapM (toFreeFoilClauseFromQuantified config rawType) cons+      return+        [ SigD funName (AppT (AppT ArrowT safeType) rawType)+        , FunD funName clauses+        ]++    mkConvertFromBinding termConfig@FreeFoilTermConfig{..} = do+      (tvars, cons) <- reifyDataOrNewtype rawBindingName+      let funName = toFreeFoilNameFrom config rawBindingName+          rawRetType = PeelConT rawBindingName (map (VarT . tvarName) tvars)+          bindingType = toFreeFoilType SortBinder config (VarT outerScope) (VarT innerScope) rawRetType+      clauses <- concat <$> mapM (toFreeFoilClauseFromBinding config termConfig rawRetType) cons+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert a scope-safe to a raw binding.")+      return+        [ SigD funName (bindingType --> rawRetType)+        , FunD funName clauses ]++    mkConvertTo termConfig@FreeFoilTermConfig{..} = concat <$> sequence+      [ mkConvertToSig SortTerm termConfig rawTermName+      , concat <$> mapM (mkConvertToSig SortSubTerm termConfig) (rawSubTermNames <> rawSubScopeNames)+      , mkConvertToBinding termConfig+      , concat <$> mapM (mkConvertToSubTerm termConfig) (rawSubTermNames <> rawSubScopeNames)+      , mkConvertToTerm termConfig+      ]++    mkConvertToSubTerm termConfig@FreeFoilTermConfig{..} rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      (itvars, _cons) <- reifyDataOrNewtype rawIdentName+      let funName = toFreeFoilNameTo config rawName+          rawIdentType = PeelConT rawIdentName (map (VarT . tvarName) (take (length itvars) tvars)) -- FIXME: undocumented hack :(+          rawType = PeelConT rawName (map (VarT . tvarName) tvars)+          safeType =  toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawType+      clauses <- concat <$> mapM (subTermConToClause rawType config termConfig) cons+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+      let scope+            | rawName `elem` rawSubTermNames = outerScope+            | otherwise = innerScope+      return+        [ SigD funName $+            ForallT+              (PlainTV scope SpecifiedSpec : map (SpecifiedSpec <$) tvars)+              [ ConT ''Foil.Distinct `AppT` VarT scope+              , ConT ''Ord `AppT` rawIdentType ] $+                (ConT ''Foil.Scope `AppT` VarT scope)+                --> (ConT ''Map `AppT` rawIdentType `AppT` (ConT ''Foil.Name `AppT` VarT scope))+                --> rawType+                --> safeType+        , FunD funName clauses+        ]++    mkConvertToTerm FreeFoilTermConfig{..} = do+      (tvars, _cons) <- reifyDataOrNewtype rawTermName+      (itvars, _cons) <- reifyDataOrNewtype rawIdentName+      let funName = toFreeFoilNameTo config rawTermName+          rawSigName = toSignatureName config rawTermName+          rawIdentType = PeelConT rawIdentName (map (VarT . tvarName) (take (length itvars) tvars)) -- FIXME: undocumented hack :(+          funSigName = toFreeFoilNameTo config rawSigName+          funBindingName = toFreeFoilNameTo config rawBindingName+          rawTermType = PeelConT rawTermName (map (VarT . tvarName) tvars)+          termType =  toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawTermType+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+      return+        [ SigD funName $+            ForallT+              (PlainTV outerScope SpecifiedSpec : map (SpecifiedSpec <$) tvars)+              [ ConT ''Foil.Distinct `AppT` VarT outerScope+              , ConT ''Ord `AppT` rawIdentType ] $+                (ConT ''Foil.Scope `AppT` VarT outerScope)+                --> (ConT ''Map `AppT` rawIdentType `AppT` (ConT ''Foil.Name `AppT` VarT outerScope))+                --> rawTermType+                --> termType+        , FunD funName [+            Clause [] (NormalB+              (VarE 'Foil.convertToAST+                `AppE` VarE funSigName+                `AppE` VarE funBindingName+                `AppE` VarE rawScopeToTermName)) []+          ]+        ]++    mkConvertToSig sort termConfig@FreeFoilTermConfig{..} rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      (itvars, _cons) <- reifyDataOrNewtype rawIdentName+      let rawSigName = toSignatureName config rawName+          funName = toFreeFoilNameTo config rawSigName+          rawType = PeelConT rawName (map (VarT . tvarName) tvars)+          rawIdentType = PeelConT rawIdentName (map (VarT . tvarName) (take (length itvars) tvars)) -- FIXME: undocumented hack :(+          rawTermType = PeelConT rawTermName (map (VarT . tvarName) tvars)+          rawScopedTermType = PeelConT rawScopeName (map (VarT . tvarName) tvars)+          rawBindingType = PeelConT rawBindingName (map (VarT . tvarName) tvars)+          rawScopeType = TupleT 2 `AppT` rawBindingType `AppT` rawScopedTermType+      case toFreeFoilSigType SortSubTerm config rawScopeType rawTermType rawType of+        Just safeType -> do+          let retType = case sort of+                SortTerm -> ConT ''Either `AppT` rawIdentType `AppT` safeType+                _        -> safeType+          clauses <- concat <$> mapM (sigConToClause sort rawType config termConfig) cons+          addModFinalizer $ putDoc (DeclDoc funName)+            ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. A helper used to convert from raw to scope-safe representation.")+          return+            [ SigD funName (AppT (AppT ArrowT rawType) retType)+            , FunD funName clauses ]+        Nothing -> error "impossible happened"++    mkConvertToBinding termConfig@FreeFoilTermConfig{..} = do+      (tvars, cons) <- reifyDataOrNewtype rawBindingName+      (itvars, _cons) <- reifyDataOrNewtype rawIdentName+      let funName = toFreeFoilNameTo config rawBindingName+          rawBindingType = PeelConT rawBindingName (map (VarT . tvarName) tvars)+          rawIdentType = PeelConT rawIdentName (map (VarT . tvarName) (take (length itvars) tvars)) -- FIXME: undocumented hack :(+          safeType = toFreeFoilType SortBinder config (VarT outerScope) (VarT innerScope) rawBindingType+      clauses <- concat <$> mapM (bindingConToClause rawBindingType config termConfig) cons+      r <- newName "r"+      addModFinalizer $ putDoc (DeclDoc funName)+        ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from raw to scope-safe binding (CPS-style).")+      return+        [ SigD funName $+            ForallT+              (PlainTV outerScope SpecifiedSpec : map (SpecifiedSpec <$) tvars ++ [PlainTV r SpecifiedSpec])+              [ ConT ''Foil.Distinct `AppT` VarT outerScope+              , ConT ''Ord `AppT` rawIdentType ] $+                (ConT ''Foil.Scope `AppT` VarT outerScope)+                --> (ConT ''Map `AppT` rawIdentType `AppT` (ConT ''Foil.Name `AppT` VarT outerScope))+                --> rawBindingType+                --> ForallT [PlainTV innerScope SpecifiedSpec]+                      [ConT ''Foil.DExt `AppT` VarT outerScope `AppT` VarT innerScope]+                      (safeType+                        --> (ConT ''Map `AppT` rawIdentType `AppT` (ConT ''Foil.Name `AppT` VarT innerScope))+                        --> VarT r)+                --> VarT r+        , FunD funName clauses ]++    mkConvertToQuantified rawName = do+      (tvars, cons) <- reifyDataOrNewtype rawName+      rawIdentNamesOfQuantifiedName rawName config >>= \case+        [] -> error "unexpected: quantified type not connected to any known terms"+        [rawIdentName'] -> do+          (itvars, _cons) <- reifyDataOrNewtype rawIdentName'+          let funName = toFreeFoilNameTo config rawName+              rawIdentType = PeelConT rawIdentName' (map (VarT . tvarName) (take (length itvars) tvars)) -- FIXME: undocumented hack :(+              rawType = PeelConT rawName (map (VarT . tvarName) tvars)+              safeType = toFreeFoilType SortTerm config (VarT outerScope) (VarT innerScope) rawType+          addModFinalizer $ putDoc (DeclDoc funName)+            ("/Generated/ with '" ++ show 'mkFreeFoil ++ "'. Convert from scope-safe to raw representation.")+          clauses <- concat <$> mapM (quantifiedConToClause rawType config) cons+          return+            [ SigD funName $+                ForallT+                  (PlainTV outerScope SpecifiedSpec : map (SpecifiedSpec <$) tvars)+                  [ ConT ''Foil.Distinct `AppT` VarT outerScope+                  , ConT ''Ord `AppT` rawIdentType ] $+                    (ConT ''Foil.Scope `AppT` VarT outerScope)+                    --> (ConT ''Map `AppT` rawIdentType `AppT` (ConT ''Foil.Name `AppT` VarT outerScope))+                    --> rawType+                    --> safeType+            , FunD funName clauses+            ]+        _ -> do+          -- error ("unsupported: more than one known term connected to the quantified type: " <> show rawName)+          return []++quantifiedConToClause :: Type -> FreeFoilConfig -> Con -> Q [Clause]+quantifiedConToClause rawType config@FreeFoilConfig{..} = go+  where+    goArgTypes :: Name -> Name -> Name -> Name -> [Type] -> Q ([Pat], [Exp], Exp -> Exp, Name, Name)+    goArgTypes _theScope _theEnv scope env [] = return ([], [], id, scope, env)+    goArgTypes theScope theEnv scope env (t:ts) = case t of+      PeelConT typeName _params+        | typeName `elem` map rawIdentName freeFoilTermConfigs -> do+            x <- newName "_x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, (InfixE (Just (VarE env)) (VarE '(Map.!)) (Just (VarE x))) : exps, wrap, scope', env')+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs -> do+            x <- newName "_x"+            x' <- newName "_x'"+            scope' <- newName "_scope"+            env' <- newName "_env"+            let funName = toFreeFoilNameTo config typeName+            (pats, exps, wrap, scope'', env'') <- goArgTypes theScope theEnv scope' env' ts+            return (VarP x : pats, VarE x' : exps, \e ->+              VarE funName `AppE` VarE scope `AppE` VarE env `AppE` VarE x `AppE`+                LamE [VarP x', VarP env']+                  (LetE [ ValD (VarP scope') (NormalB (VarE 'Foil.extendScopePattern `AppE` VarE x' `AppE` VarE scope)) []]+                    (wrap e)), scope'', env'')+        | Just FreeFoilTermConfig{..} <- lookupScopeName typeName freeFoilTermConfigs -> do+            x <- newName "_x"+            let funName = toFreeFoilNameTo config rawTermName+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats,+              (VarE funName `AppE` VarE scope' `AppE` VarE env' `AppE` (VarE rawScopeToTermName `AppE` VarE x)) : exps,+              wrap, scope', env')+        | Just _ <- lookupTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameTo config typeName+            x <- newName "x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, (VarE funName `AppE` VarE scope' `AppE` VarE env' `AppE` VarE x) : exps, wrap, scope', env')+      AppT _ (PeelConT typeName _params)+        | Just _ <- lookupTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameTo config typeName+            x <- newName "x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, AppE (AppE (VarE 'fmap) (VarE funName `AppE` VarE theScope `AppE` VarE theEnv)) (VarE x) : exps, wrap, scope', env')+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameTo config typeName+            x <- newName "x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, AppE (AppE (VarE 'fmap) (VarE funName `AppE` VarE theScope `AppE` VarE theEnv)) (VarE x) : exps, wrap, scope', env')+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameTo config typeName+            x <- newName "x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, AppE (AppE (VarE 'fmap) (VarE funName `AppE` VarE scope' `AppE` VarE env')) (VarE x) : exps, wrap, scope', env')+        | Just FreeFoilTermConfig{..} <- lookupScopeName typeName freeFoilTermConfigs -> do+            let funName = toFreeFoilNameTo config rawTermName+            x <- newName "x"+            (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+            return (VarP x : pats, AppE (AppE (VarE 'fmap) (VarE funName `AppE` VarE scope' `AppE` VarE env')) (VarE x) : exps, wrap, scope', env')+      _ -> do+        x <- newName "_x"+        (pats, exps, wrap, scope', env') <- goArgTypes theScope theEnv scope env ts+        return (VarP x : pats, VarE x : exps, wrap, scope', env')++    go :: Con -> Q [Clause]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        scope <- newName "_scope"+        env <- newName "_env"+        forM conNames $ \conName -> do+          let newConName = toConName config conName+          (pats, exps, wrap, _scope', _env') <- goArgTypes scope env scope env (map snd rawArgTypes)+          return+            [ Clause [VarP scope, VarP env, ConP conName [] pats]+                (NormalB (wrap (foldl AppE (ConE newConName) exps))) [] ]+      NormalC conName types -> go (GadtC [conName] types rawType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++subTermConToClause :: Type -> FreeFoilConfig -> FreeFoilTermConfig -> Con -> Q [Clause]+subTermConToClause rawType config FreeFoilTermConfig{..} = go+  where+    goArgTypes :: Name -> Name -> [Type] -> Q ([Pat], [Exp], Exp -> Exp, Name, Name)+    goArgTypes scope env [] = return ([], [], id, scope, env)+    goArgTypes scope env (t:ts) = case t of+      PeelConT typeName _params+        | typeName == rawBindingName -> do+            x <- newName "_x"+            x' <- newName "_x'"+            scope' <- newName "_scope"+            env' <- newName "_env"+            let funName = toFreeFoilNameTo config typeName+            (pats, exps, wrap, scope'', env'') <- goArgTypes scope' env' ts+            return (VarP x : pats, VarE x' : exps, \e ->+              VarE funName `AppE` VarE scope `AppE` VarE env `AppE` VarE x `AppE`+                LamE [VarP x', VarP env']+                  (LetE [ ValD (VarP scope') (NormalB (VarE 'Foil.extendScopePattern `AppE` VarE x' `AppE` VarE scope)) []]+                    (wrap e)), scope'', env'')+        | typeName == rawScopeName -> do+            x <- newName "_x"+            let funName = toFreeFoilNameTo config rawTermName+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE funName `AppE` VarE scope' `AppE` VarE env' `AppE` (VarE rawScopeToTermName `AppE` VarE x)) : exps,+              wrap, scope', env')+        | typeName == rawTermName -> do+            x <- newName "_x"+            let funName = toFreeFoilNameTo config rawTermName+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE funName `AppE` VarE scope `AppE` VarE env `AppE` VarE x) : exps,+              wrap, scope', env')+        | typeName `elem` rawSubTermNames -> do+            x <- newName "_x"+            let funName = toFreeFoilNameTo config typeName+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE funName `AppE` VarE scope `AppE` VarE env `AppE` VarE x) : exps,+              wrap, scope', env')+      AppT _ (PeelConT typeName _params)+        | typeName == rawTermName -> do+            let funName = toFreeFoilNameTo config typeName+            x <- newName "_x"+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE 'fmap `AppE` (VarE funName `AppE` VarE scope `AppE` VarE env) `AppE` VarE x) : exps,+              wrap, scope', env')+        | typeName `elem` rawSubTermNames -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE 'fmap `AppE` (VarE funName `AppE` VarE scope `AppE` VarE env) `AppE` VarE x) : exps,+              wrap, scope', env')+        | typeName `elem` rawSubScopeNames -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+            return (VarP x : pats,+              (VarE 'fmap `AppE` (VarE funName `AppE` VarE scope' `AppE` VarE env') `AppE` VarE x) : exps,+              wrap, scope', env')+      _ -> do+        x <- newName "_x"+        (pats, exps, wrap, scope', env') <- goArgTypes scope env ts+        return (VarP x : pats, VarE x : exps, wrap, scope', env')++    go :: Con -> Q [Clause]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        scope <- newName "_scope"+        env <- newName "_env"+        forM conNames $ \conName -> do+          let newConName = toConName config conName+          (pats, exps, wrap, _scope', _env') <- goArgTypes scope env (map snd rawArgTypes)+          return+            [ Clause [VarP scope, VarP env, ConP conName [] pats]+                (NormalB (wrap (foldl AppE (ConE newConName) exps))) [] ]+      NormalC conName types -> go (GadtC [conName] types rawType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++bindingConToClause :: Type -> FreeFoilConfig -> FreeFoilTermConfig -> Con -> Q [Clause]+bindingConToClause rawType config FreeFoilTermConfig{..} = go+  where+    goArgTypes :: Name -> Name -> [Type] -> Q ([Pat], [Exp], Exp -> Exp, Name)+    goArgTypes _scope env [] = return ([], [], id, env)+    goArgTypes scope env (t:ts) = case t of+      PeelConT typeName _params+        | typeName == rawIdentName -> do+            x <- newName "_x"+            x' <- newName "_x'"+            scope' <- newName "_scope"+            env' <- newName "_env"+            (pats, exps, wrap, env'') <- goArgTypes scope' env' ts+            return (VarP x : pats, VarE x' : exps, \e ->+              VarE 'Foil.withFresh `AppE` VarE scope `AppE`+                LamE [VarP x']+                  (LetE [ ValD (VarP scope') (NormalB (VarE 'Foil.extendScope `AppE` VarE x' `AppE` VarE scope)) []+                        , ValD (VarP env') (NormalB (VarE 'Map.insert `AppE` VarE x `AppE` (VarE 'Foil.nameOf `AppE` VarE x') `AppE` (VarE 'fmap `AppE` VarE 'Foil.sink `AppE` VarE env))) []]+                    (wrap e)), env'')+        | typeName == rawBindingName -> do+            x <- newName "_x"+            x' <- newName "_x'"+            scope' <- newName "_scope"+            env' <- newName "_env"+            let funName = toFreeFoilNameTo config typeName+            (pats, exps, wrap, env'') <- goArgTypes scope' env' ts+            return (VarP x : pats, VarE x' : exps, \e ->+              VarE funName `AppE` VarE scope `AppE` VarE env `AppE` VarE x `AppE`+                LamE [VarP x', VarP env']+                  (LetE [ ValD (VarP scope') (NormalB (VarE 'Foil.extendScopePattern `AppE` VarE x' `AppE` VarE scope)) []]+                    (wrap e)), env'')+      _ -> do+        x <- newName "_x"+        (pats, exps, wrap, env') <- goArgTypes scope env ts+        return (VarP x : pats, VarE x : exps, wrap, env')++    go :: Con -> Q [Clause]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        scope <- newName "_scope"+        env <- newName "_env"+        cont <- newName "_cont"+        forM conNames $ \conName -> do+          let newConName = toConName config conName+          (pats, exps, wrap, env') <- goArgTypes scope env (map snd rawArgTypes)+          return+            [ Clause [VarP scope, VarP env, ConP conName [] pats, VarP cont]+                (NormalB (wrap (VarE cont `AppE` foldl AppE (ConE newConName) exps `AppE` VarE env'))) [] ]+      NormalC conName types -> go (GadtC [conName] types rawType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)+++sigConToClause :: Sort -> Type -> FreeFoilConfig -> FreeFoilTermConfig -> Con -> Q [Clause]+sigConToClause sort rawRetType config@FreeFoilConfig{..} FreeFoilTermConfig{..} = go+  where+    fromArgType :: Bool -> Name -> Type -> Q ([Pat], [Exp])+    fromArgType isVarCon theIdent = \case+      PeelConT typeName _params+        | typeName == rawIdentName, SortTerm <- sort, isVarCon -> do+            return ([VarP theIdent], [VarE theIdent])+        | Just _ <- lookupBindingName typeName freeFoilTermConfigs -> do+            return ([], [])+        | Just _ <- lookupScopeName typeName freeFoilTermConfigs -> do+            binder <- newName "binder"+            body <- newName "body"+            return ([VarP binder, VarP body], [TupE [Just (VarE binder), Just (VarE body)]])+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            return ([VarP x], [AppE (VarE funName) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            return ([VarP x], [AppE (VarE funName) (VarE x)])+      AppT _ (PeelConT typeName _params)+        | Just _ <- lookupSubTermName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            return ([VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+        | Just _ <- lookupSubScopeName typeName freeFoilTermConfigs -> do+            let rawSigName = toSignatureName config typeName+                funName = toFreeFoilNameTo config rawSigName+            x <- newName "_x"+            return ([VarP x], [AppE (AppE (VarE 'fmap) (VarE funName)) (VarE x)])+      _ -> do+        x <- newName "_x"+        return ([VarP x], [VarE x])++    go :: Con -> Q [Clause]+    go = \case+      GadtC conNames rawArgTypes _rawRetType -> concat <$> do+        theIdent <- newName "_theRawIdent"+        forM conNames $ \conName -> do+          let newConName = toSignatureName config conName+              isVarCon = conName == rawVarConName+          (concat -> pats, concat -> exps) <- unzip <$>+            mapM (fromArgType isVarCon theIdent . snd) rawArgTypes+          case sort of+            SortTerm+              | isVarCon -> return+                  [ Clause [ConP conName [] pats] (NormalB (ConE 'Left `AppE` VarE theIdent)) [] ]  -- FIXME!+              | otherwise -> return+                  [ Clause [ConP conName [] pats] (NormalB (ConE 'Right `AppE` (foldl AppE (ConE newConName) exps))) [] ]+            _ -> return+              [ Clause [ConP conName [] pats] (NormalB (foldl AppE (ConE newConName) exps)) [] ]+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++rawIdentNamesOfQuantifiedName :: Name -> FreeFoilConfig -> Q [Name]+rawIdentNamesOfQuantifiedName rawName config = do+  (_tvars, cons) <- reifyDataOrNewtype rawName+  return (nub (concatMap go cons))+  where+    rawRetType = error "impossible happened!"++    go :: Con -> [Name]+    go = \case+      GadtC _conNames rawArgTypes _rawRetType ->+        concatMap (rawIdentNamesOfType config . snd) rawArgTypes+      NormalC conName types -> go (GadtC [conName] types rawRetType)+      RecC conName types -> go (NormalC conName (map removeName types))+      InfixC l conName r -> go (GadtC [conName] [l, r] rawRetType)+      ForallC _params _ctx con -> go con+      RecGadtC conNames argTypes retType -> go (GadtC conNames (map removeName argTypes) retType)++rawIdentNamesOfType :: FreeFoilConfig -> Type -> [Name]+rawIdentNamesOfType FreeFoilConfig{..} = go+  where+    go = \case+      PeelConT typeName _params+        | typeName `elem` rawQuantifiedNames -> []+        | typeName `elem` map rawIdentName freeFoilTermConfigs -> [typeName]+        | Just FreeFoilTermConfig{..} <- lookupTermName typeName freeFoilTermConfigs ->+            [rawIdentName]+        | Just FreeFoilTermConfig{..} <- lookupBindingName typeName freeFoilTermConfigs ->+            [rawIdentName]+        | Just FreeFoilTermConfig{..} <- lookupScopeName typeName freeFoilTermConfigs ->+            [rawIdentName]+        | Just FreeFoilTermConfig{..} <- lookupSubTermName typeName freeFoilTermConfigs ->+            [rawIdentName]+        | Just FreeFoilTermConfig{..} <- lookupSubScopeName typeName freeFoilTermConfigs ->+            [rawIdentName]+      ForallT _bndrs _ctx type_ -> go type_+      ForallVisT _bndrs type_ -> go type_+      AppT f x -> go f <> go x+      AppKindT f _k -> go f+      SigT t _k -> go t+      ConT{} -> []+      VarT{} -> []+      PromotedT{} -> []+      InfixT l _op r -> go l <> go r+      UInfixT l _op r -> go l <> go r+      PromotedInfixT l _op r -> go l <> go r+      PromotedUInfixT l _op r -> go l <> go r+      ParensT t -> go t+      TupleT{} -> []+      UnboxedTupleT{} -> []+      UnboxedSumT{} -> []+      ArrowT{} -> []+      MulArrowT{} -> []+      EqualityT{} -> []+      ListT{} -> []+      PromotedTupleT{} -> []+      PromotedNilT{} -> []+      PromotedConsT{} -> []+      StarT{} -> []+      ConstraintT{} -> []+      LitT{} -> []+      WildCardT{} -> []+      ImplicitParamT _s t -> go t
src/Control/Monad/Free/Foil/TH/PatternSynonyms.hs view
@@ -1,13 +1,14 @@-{-# LANGUAGE LambdaCase      #-}+{-# LANGUAGE LambdaCase            #-} {-# OPTIONS_GHC -fno-warn-type-defaults      #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns    #-}+{-# LANGUAGE PatternSynonyms       #-}+{-# LANGUAGE TemplateHaskellQuotes #-}+{-# LANGUAGE ViewPatterns          #-} module Control.Monad.Free.Foil.TH.PatternSynonyms where  import           Control.Monad              (forM_) import           Control.Monad.Foil.TH.Util import           Control.Monad.Free.Foil+import           Data.List                  (nub) import           Language.Haskell.TH import           Language.Haskell.TH.Syntax @@ -20,10 +21,12 @@    case reverse signatureTVars of     (tvarName -> term) : (tvarName -> scope) : (reverse -> params) -> do-      concat <$> mapM (mkPatternSynonym (PeelConT signatureT (map (VarT . tvarName) params)) scope term) signatureCons+      (names, decs) <- unzip . concat <$> mapM (mkPatternSynonym (PeelConT signatureT (map (VarT . tvarName) params)) scope term) signatureCons+      return $ decs +++        [ PragmaD (CompleteP ('Var : nub names) Nothing)]     _ -> fail "cannot generate pattern synonyms" -mkPatternSynonym :: Type -> Name -> Name -> Con -> Q [Dec]+mkPatternSynonym :: Type -> Name -> Name -> Con -> Q [(Name, Dec)] mkPatternSynonym signatureType scope term = \case   NormalC conName types -> mkPatternSynonym signatureType scope term     (GadtC [conName] types (AppT (AppT signatureType (VarT scope)) (VarT term)))@@ -33,9 +36,9 @@   InfixC l conName r -> mkPatternSynonym signatureType scope term (NormalC conName [l, r])    ForallC params ctx con -> do-    [ PatSynSigD patName patType, patD ] <- mkPatternSynonym signatureType scope term con+    [ (name, PatSynSigD patName patType), patD ] <- mkPatternSynonym signatureType scope term con     return-      [ PatSynSigD patName (ForallT params ctx patType)+      [ (name, PatSynSigD patName (ForallT params ctx patType))       , patD       ] @@ -49,8 +52,8 @@       addModFinalizer $ putDoc (DeclDoc (mkPatternName conName))         ("/Generated/ with '" ++ show 'mkPatternSynonyms ++ "'. Pattern synonym for an '" ++ show ''AST ++ "' node of type '" ++ show conName ++ "'.")     return $ concat-      [ [ PatSynSigD patternName (foldr (AppT . AppT ArrowT) termType types')-        , PatSynD  patternName (PrefixPatSyn args) ImplBidir (ConP 'Node [] [ConP conName [] pats])+      [ [ (patternName, PatSynSigD patternName (foldr (AppT . AppT ArrowT) termType types'))+        , (patternName, PatSynD  patternName (PrefixPatSyn args) ImplBidir (ConP 'Node [] [ConP conName [] pats]))         ]       | conName <- conNames       , let patternName = mkPatternName conName@@ -66,17 +69,19 @@       Left ((b, _), (x, _)) -> ConP 'ScopedAST [] [VarP b, VarP x]       Right (x, _) -> VarP x -    toPatternArgType i (_bang, VarT typeName)+    toPatternArgType i (_bang, type_@(VarT typeName))       | typeName == scope =           Left             ( (mkName ("b" ++ show i), foldl AppT binderT [VarT n, VarT l])-            , (mkName ("x" ++ show i), PeelConT ''AST [binderT, signatureType, VarT l]))+            , (mkName ("x" ++ show i), replaceScopeTermInType l type_))       | typeName == term =-          Right (mkName ("x" ++ show i), PeelConT ''AST [binderT, signatureType, VarT n])+          Right (mkName ("x" ++ show i), replaceScopeTermInType l type_)       where         l = mkName ("l" ++ show i)     toPatternArgType i (_bang, type_)-      = Right (mkName ("z" ++ show i), type_)+      = Right (mkName ("z" ++ show i), replaceScopeTermInType l type_)+      where+        l = mkName ("l" ++ show i)      mkPatternName conName = mkName (dropEnd (length "Sig") (nameBase conName))     dropEnd k = reverse . drop k . reverse@@ -84,3 +89,36 @@     collapse = \case       Left (x, y) -> [x, y]       Right x -> [x]++    replaceScopeTermInType lscope = \case+      VarT typeName+        | typeName == scope -> PeelConT ''AST [binderT, signatureType, VarT lscope]+        | typeName == term  -> PeelConT ''AST [binderT, signatureType, VarT n]+      ForallT bndrs ctx type_ -> ForallT bndrs ctx (replaceScopeTermInType lscope type_)+      ForallVisT bndrs type_ -> ForallVisT bndrs (replaceScopeTermInType lscope type_)+      AppT f x -> AppT (replaceScopeTermInType lscope f) (replaceScopeTermInType lscope x)+      AppKindT f k -> AppKindT (replaceScopeTermInType lscope f) k+      SigT t k -> SigT (replaceScopeTermInType lscope t) k+      t@ConT{} -> t+      t@VarT{} -> t+      t@PromotedT{} -> t+      InfixT l op r -> InfixT (replaceScopeTermInType lscope l) op (replaceScopeTermInType lscope r)+      UInfixT l op r -> UInfixT (replaceScopeTermInType lscope l) op (replaceScopeTermInType lscope r)+      PromotedInfixT l op r -> PromotedInfixT (replaceScopeTermInType lscope l) op (replaceScopeTermInType lscope r)+      PromotedUInfixT l op r -> PromotedUInfixT (replaceScopeTermInType lscope l) op (replaceScopeTermInType lscope r)+      ParensT t -> ParensT (replaceScopeTermInType lscope t)+      t@TupleT{} -> t+      t@UnboxedTupleT{} -> t+      t@UnboxedSumT{} -> t+      t@ArrowT{} -> t+      t@MulArrowT{} -> t+      t@EqualityT{} -> t+      t@ListT{} -> t+      t@PromotedTupleT{} -> t+      t@PromotedNilT{} -> t+      t@PromotedConsT{} -> t+      t@StarT{} -> t+      t@ConstraintT{} -> t+      t@LitT{} -> t+      t@WildCardT{} -> t+      ImplicitParamT s t -> ImplicitParamT s (replaceScopeTermInType lscope t)
src/Control/Monad/Free/Foil/TH/Signature.hs view
@@ -89,9 +89,40 @@           where             k (x, y) = (name, x, y) -        toSignatureParam (bang_, PeelConT typeName _typeParams)+        toSignatureParam (_bang, PeelConT typeName _typeParams)           | typeName == nameT = fail ("variable with other stuff in constructor: " ++ show con')           | typeName == patternT = pure Nothing -- skip binders, they will be inserted automatically with each scoped term-          | typeName == scopeT = pure (Just (bang_, VarT scope))-          | typeName == termT = pure (Just (bang_, VarT term))-        toSignatureParam bt = pure (Just bt)  -- everything else remains as is+        toSignatureParam (bang_, type_) = pure (Just (bang_, replaceScopeTermInType type_))++        replaceScopeTermInType = \case+          PeelConT typeName _typeParams+            | typeName == scopeT -> VarT scope+            | typeName == termT -> VarT term+          ForallT bndrs ctx type_ -> ForallT bndrs ctx (replaceScopeTermInType type_)+          ForallVisT bndrs type_ -> ForallVisT bndrs (replaceScopeTermInType type_)+          AppT f x -> AppT (replaceScopeTermInType f) (replaceScopeTermInType x)+          AppKindT f k -> AppKindT (replaceScopeTermInType f) k+          SigT t k -> SigT (replaceScopeTermInType t) k+          t@ConT{} -> t+          t@VarT{} -> t+          t@PromotedT{} -> t+          InfixT l op r -> InfixT (replaceScopeTermInType l) op (replaceScopeTermInType r)+          UInfixT l op r -> UInfixT (replaceScopeTermInType l) op (replaceScopeTermInType r)+          PromotedInfixT l op r -> PromotedInfixT (replaceScopeTermInType l) op (replaceScopeTermInType r)+          PromotedUInfixT l op r -> PromotedUInfixT (replaceScopeTermInType l) op (replaceScopeTermInType r)+          ParensT t -> ParensT (replaceScopeTermInType t)+          t@TupleT{} -> t+          t@UnboxedTupleT{} -> t+          t@UnboxedSumT{} -> t+          t@ArrowT{} -> t+          t@MulArrowT{} -> t+          t@EqualityT{} -> t+          t@ListT{} -> t+          t@PromotedTupleT{} -> t+          t@PromotedNilT{} -> t+          t@PromotedConsT{} -> t+          t@StarT{} -> t+          t@ConstraintT{} -> t+          t@LitT{} -> t+          t@WildCardT{} -> t+          ImplicitParamT s t -> ImplicitParamT s (replaceScopeTermInType t)