packages feed

th-desugar 1.4.2.1 → 1.5

raw patch · 14 files changed

+1373/−442 lines, 14 filesdep +th-liftdep ~basedep ~hspecdep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: th-lift

Dependency ranges changed: base, hspec, template-haskell

API changes (from Hackage documentation)

- Language.Haskell.TH.Desugar.Lift: instance Lift ModName
- Language.Haskell.TH.Desugar.Lift: instance Lift Name
- Language.Haskell.TH.Desugar.Lift: instance Lift NameFlavour
- Language.Haskell.TH.Desugar.Lift: instance Lift NameSpace
- Language.Haskell.TH.Desugar.Lift: instance Lift OccName
- Language.Haskell.TH.Desugar.Lift: instance Lift PkgName
- Language.Haskell.TH.Desugar.Lift: instance Lift Rational
- Language.Haskell.TH.Desugar.Sweeten: tySynEqnToTH :: DTySynEqn -> TySynEqn
+ Language.Haskell.TH.Desugar: DDefaultSigD :: Name -> DType -> DDec
+ Language.Haskell.TH.Desugar: DLineP :: Int -> String -> DPragma
+ Language.Haskell.TH.Desugar: DStandaloneDerivD :: DCxt -> DType -> DDec
+ Language.Haskell.TH.Desugar: DStaticE :: DExp -> DExp
+ Language.Haskell.TH.Desugar: class Quasi m => DsMonad m
+ Language.Haskell.TH.Desugar: data DsM q a
+ Language.Haskell.TH.Desugar: dsReify :: DsMonad q => Name -> q (Maybe DInfo)
+ Language.Haskell.TH.Desugar: expand :: (DsMonad q, Data a) => a -> q a
+ Language.Haskell.TH.Desugar: expandType :: DsMonad q => DType -> q DType
+ Language.Haskell.TH.Desugar: localDeclarations :: DsMonad m => m [Dec]
+ Language.Haskell.TH.Desugar: reifyWithLocals :: DsMonad q => Name -> q Info
+ Language.Haskell.TH.Desugar: reifyWithLocals_maybe :: DsMonad q => Name -> q (Maybe Info)
+ Language.Haskell.TH.Desugar: scExp :: DsMonad q => DExp -> q DExp
+ Language.Haskell.TH.Desugar: scLetDec :: DsMonad q => DLetDec -> q DLetDec
+ Language.Haskell.TH.Desugar: substTy :: DsMonad q => Map Name DType -> DType -> q DType
+ Language.Haskell.TH.Desugar: tupleDegree_maybe :: String -> Maybe Int
+ Language.Haskell.TH.Desugar: tupleNameDegree_maybe :: Name -> Maybe Int
+ Language.Haskell.TH.Desugar: unboxedTupleDegree_maybe :: String -> Maybe Int
+ Language.Haskell.TH.Desugar: unboxedTupleNameDegree_maybe :: Name -> Maybe Int
+ Language.Haskell.TH.Desugar: withLocalDeclarations :: DsMonad q => [Dec] -> DsM q a -> q a
- Language.Haskell.TH.Desugar: desugar :: (Desugar th ds, Quasi q) => th -> q ds
+ Language.Haskell.TH.Desugar: desugar :: (Desugar th ds, DsMonad q) => th -> q ds
- Language.Haskell.TH.Desugar: dsBody :: Quasi q => Body -> [Dec] -> DExp -> q DExp
+ Language.Haskell.TH.Desugar: dsBody :: DsMonad q => Body -> [Dec] -> DExp -> q DExp
- Language.Haskell.TH.Desugar: dsClauses :: Quasi q => Name -> [Clause] -> q [DClause]
+ Language.Haskell.TH.Desugar: dsClauses :: DsMonad q => Name -> [Clause] -> q [DClause]
- Language.Haskell.TH.Desugar: dsComp :: Quasi q => [Stmt] -> q DExp
+ Language.Haskell.TH.Desugar: dsComp :: DsMonad q => [Stmt] -> q DExp
- Language.Haskell.TH.Desugar: dsCon :: Quasi q => Con -> q DCon
+ Language.Haskell.TH.Desugar: dsCon :: DsMonad q => Con -> q DCon
- Language.Haskell.TH.Desugar: dsCxt :: Quasi q => Cxt -> q DCxt
+ Language.Haskell.TH.Desugar: dsCxt :: DsMonad q => Cxt -> q DCxt
- Language.Haskell.TH.Desugar: dsDec :: Quasi q => Dec -> q [DDec]
+ Language.Haskell.TH.Desugar: dsDec :: DsMonad q => Dec -> q [DDec]
- Language.Haskell.TH.Desugar: dsDecs :: Quasi q => [Dec] -> q [DDec]
+ Language.Haskell.TH.Desugar: dsDecs :: DsMonad q => [Dec] -> q [DDec]
- Language.Haskell.TH.Desugar: dsDoStmts :: Quasi q => [Stmt] -> q DExp
+ Language.Haskell.TH.Desugar: dsDoStmts :: DsMonad q => [Stmt] -> q DExp
- Language.Haskell.TH.Desugar: dsExp :: Quasi q => Exp -> q DExp
+ Language.Haskell.TH.Desugar: dsExp :: DsMonad q => Exp -> q DExp
- Language.Haskell.TH.Desugar: dsForeign :: Quasi q => Foreign -> q DForeign
+ Language.Haskell.TH.Desugar: dsForeign :: DsMonad q => Foreign -> q DForeign
- Language.Haskell.TH.Desugar: dsGuards :: Quasi q => [(Guard, Exp)] -> DExp -> q DExp
+ Language.Haskell.TH.Desugar: dsGuards :: DsMonad q => [(Guard, Exp)] -> DExp -> q DExp
- Language.Haskell.TH.Desugar: dsInfo :: Quasi q => Info -> q DInfo
+ Language.Haskell.TH.Desugar: dsInfo :: DsMonad q => Info -> q DInfo
- Language.Haskell.TH.Desugar: dsKind :: Quasi q => Kind -> q DKind
+ Language.Haskell.TH.Desugar: dsKind :: DsMonad q => Kind -> q DKind
- Language.Haskell.TH.Desugar: dsLetDec :: Quasi q => Dec -> q [DLetDec]
+ Language.Haskell.TH.Desugar: dsLetDec :: DsMonad q => Dec -> q [DLetDec]
- Language.Haskell.TH.Desugar: dsLetDecs :: Quasi q => [Dec] -> q [DLetDec]
+ Language.Haskell.TH.Desugar: dsLetDecs :: DsMonad q => [Dec] -> q [DLetDec]
- Language.Haskell.TH.Desugar: dsMatches :: Quasi q => Name -> [Match] -> q [DMatch]
+ Language.Haskell.TH.Desugar: dsMatches :: DsMonad q => Name -> [Match] -> q [DMatch]
- Language.Haskell.TH.Desugar: dsPat :: Quasi q => Pat -> PatM q DPat
+ Language.Haskell.TH.Desugar: dsPat :: DsMonad q => Pat -> PatM q DPat
- Language.Haskell.TH.Desugar: dsPatOverExp :: Quasi q => Pat -> DExp -> q (DPat, DExp)
+ Language.Haskell.TH.Desugar: dsPatOverExp :: DsMonad q => Pat -> DExp -> q (DPat, DExp)
- Language.Haskell.TH.Desugar: dsPatX :: Quasi q => Pat -> q (DPat, [(Name, DExp)])
+ Language.Haskell.TH.Desugar: dsPatX :: DsMonad q => Pat -> q (DPat, [(Name, DExp)])
- Language.Haskell.TH.Desugar: dsPatsOverExp :: Quasi q => [Pat] -> DExp -> q ([DPat], DExp)
+ Language.Haskell.TH.Desugar: dsPatsOverExp :: DsMonad q => [Pat] -> DExp -> q ([DPat], DExp)
- Language.Haskell.TH.Desugar: dsPragma :: Quasi q => Pragma -> q DPragma
+ Language.Haskell.TH.Desugar: dsPragma :: DsMonad q => Pragma -> q DPragma
- Language.Haskell.TH.Desugar: dsPred :: Quasi q => Pred -> q DCxt
+ Language.Haskell.TH.Desugar: dsPred :: DsMonad q => Pred -> q DCxt
- Language.Haskell.TH.Desugar: dsRuleBndr :: Quasi q => RuleBndr -> q DRuleBndr
+ Language.Haskell.TH.Desugar: dsRuleBndr :: DsMonad q => RuleBndr -> q DRuleBndr
- Language.Haskell.TH.Desugar: dsTvb :: Quasi q => TyVarBndr -> q DTyVarBndr
+ Language.Haskell.TH.Desugar: dsTvb :: DsMonad q => TyVarBndr -> q DTyVarBndr
- Language.Haskell.TH.Desugar: dsType :: Quasi q => Type -> q DType
+ Language.Haskell.TH.Desugar: dsType :: DsMonad q => Type -> q DType
- Language.Haskell.TH.Desugar: removeWilds :: Quasi q => DPat -> q DPat
+ Language.Haskell.TH.Desugar: removeWilds :: DsMonad q => DPat -> q DPat
- Language.Haskell.TH.Desugar.Expand: expand :: (Quasi q, Data a) => a -> q a
+ Language.Haskell.TH.Desugar.Expand: expand :: (DsMonad q, Data a) => a -> q a
- Language.Haskell.TH.Desugar.Expand: expandType :: Quasi q => DType -> q DType
+ Language.Haskell.TH.Desugar.Expand: expandType :: DsMonad q => DType -> q DType
- Language.Haskell.TH.Desugar.Expand: substTy :: Quasi q => Map Name DType -> DType -> q DType
+ Language.Haskell.TH.Desugar.Expand: substTy :: DsMonad q => Map Name DType -> DType -> q DType

Files

CHANGES.md view
@@ -1,6 +1,24 @@-Version 1.4.2.1-----------------* Fix compilation error with updated HSpec.+Version 1.5+-----------+* There is now a facility to register a list of `Dec` that internal reification+  should use when necessary. This avoids the user needing to break up their+  definition across different top-level splices. See `withLocalDeclarations`.+  This has a side effect of changing the `Quasi` typeclass constraint on many+  functions to be the new `DsMonad` constraint. Happily, there are `DsMonad`+  instances for `Q` and `IO`, the two normal inhabitants of `Quasi`.++* "Match flattening" is implemented! The functions `scExp` and `scLetDec` remove+  any nested pattern matches.++* More is now exported from `Language.Haskell.TH.Desugar` for ease of use.++* `expand` can now expand closed type families! It still requires that the+  type to expand contain no type variables.++* Support for standalone-deriving and default signatures in GHC 7.10.+  This means that there are now two new constructors for `DDec`.++* Support for `static` expressions, which are new in GHC 7.10.  Version 1.4.2 -------------
Language/Haskell/TH/Desugar.hs view
@@ -42,14 +42,34 @@   PatM, dsPred, dsPat, dsDec, dsLetDec,   dsMatches, dsBody, dsGuards, dsDoStmts, dsComp, dsClauses,  +  -- * Converting desugared AST back to TH AST+  module Language.Haskell.TH.Desugar.Sweeten,+  +  -- * Expanding type synonyms+  expand, expandType,++  -- * Reification+  reifyWithWarning,++  -- | The following definitions allow you to register a list of+  -- @Dec@s to be used in reification queries.+  withLocalDeclarations, dsReify, reifyWithLocals_maybe, reifyWithLocals,+  DsMonad(..), DsM,++  -- * Nested pattern flattening+  scExp, scLetDec,+   -- * Utility functions   applyDExp, applyDType,-  dPatToDExp, removeWilds, reifyWithWarning,+  dPatToDExp, removeWilds,   getDataD, dataConNameToDataName, dataConNameToCon,   nameOccursIn, allNamesIn, flattenDValD, getRecordSelectors,   mkTypeName, mkDataName, newUniqueName,   mkTupleDExp, mkTupleDPat, maybeDLetE, maybeDCaseE,-+  substTy,+  tupleDegree_maybe, tupleNameDegree_maybe,+  unboxedTupleDegree_maybe, unboxedTupleNameDegree_maybe,+     -- ** Extracting bound names   extractBoundNamesStmt, extractBoundNamesDec, extractBoundNamesPat   ) where@@ -58,9 +78,14 @@ import Language.Haskell.TH.Desugar.Util import Language.Haskell.TH.Desugar.Sweeten import Language.Haskell.TH.Syntax+import Language.Haskell.TH.Desugar.Reify+import Language.Haskell.TH.Desugar.Expand+import Language.Haskell.TH.Desugar.Match  import qualified Data.Set as S+#if __GLASGOW_HASKELL__ < 709 import Data.Foldable ( foldMap )+#endif import Prelude hiding ( exp )  -- | This class relates a TH type with its th-desugar type and allows@@ -68,7 +93,7 @@ -- way because `Type` and `Kind` are type synonyms, but they desugar -- to different types. class Desugar th ds | ds -> th where-  desugar :: Quasi q => th -> q ds+  desugar :: DsMonad q => th -> q ds   sweeten :: ds -> th  instance Desugar Exp DExp where
Language/Haskell/TH/Desugar/Core.hs view
@@ -28,6 +28,7 @@ import GHC.Exts  import Language.Haskell.TH.Desugar.Util+import Language.Haskell.TH.Desugar.Reify  -- | Corresponds to TH's @Exp@ type. Note that @DLamE@ takes names, not patterns. data DExp = DVarE Name@@ -38,6 +39,7 @@           | DCaseE DExp [DMatch]           | DLetE [DLetDec] DExp           | DSigE DExp DType+          | DStaticE DExp           deriving (Show, Typeable, Data)  @@ -118,6 +120,8 @@           | DTySynInstD Name DTySynEqn           | DClosedTypeFamilyD Name [DTyVarBndr] (Maybe DKind) [DTySynEqn]           | DRoleAnnotD Name [Role]+          | DStandaloneDerivD DCxt DType+          | DDefaultSigD Name DType           deriving (Show, Typeable, Data)  -- | Corresponds to TH's @Con@ type.@@ -147,6 +151,7 @@              | DSpecialiseInstP DType              | DRuleP String [DRuleBndr] DExp DExp Phases              | DAnnP AnnTarget DExp+             | DLineP Int String              deriving (Show, Typeable, Data)  -- | Corresponds to TH's @RuleBndr@ type.@@ -185,7 +190,7 @@ type DInstanceDec = DDec -- ^ Guaranteed to be an instance declaration  -- | Desugar an expression-dsExp :: Quasi q => Exp -> q DExp+dsExp :: DsMonad q => Exp -> q DExp dsExp (VarE n) = return $ DVarE n dsExp (ConE n) = return $ DConE n dsExp (LitE lit) = return $ DLitE lit@@ -253,7 +258,7 @@   first_name <- case field_exps of                   ((name, _) : _) -> return name                   _ -> impossible "Record update with no fields listed."-  info <- reifyWithWarning first_name+  info <- reifyWithLocals first_name   applied_type <- case info of                     VarI _name ty _m_dec _fixity -> extract_first_arg ty                     _ -> impossible "Record update with an invalid field name."@@ -262,41 +267,52 @@   let filtered_cons = filter_cons_with_names cons (map fst field_exps)   exp' <- dsExp exp   matches <- mapM con_to_dmatch filtered_cons-  return $ DCaseE exp' (matches ++ [error_match])+  let all_matches+        | length filtered_cons == length cons = matches+        | otherwise                           = matches ++ [error_match]+  return $ DCaseE exp' all_matches   where-    extract_first_arg :: Quasi q => Type -> q Type+    extract_first_arg :: DsMonad q => Type -> q Type     extract_first_arg (AppT (AppT ArrowT arg) _) = return arg     extract_first_arg (ForallT _ _ t) = extract_first_arg t     extract_first_arg (SigT t _) = extract_first_arg t     extract_first_arg _ = impossible "Record selector not a function." -    extract_type_name :: Quasi q => Type -> q Name+    extract_type_name :: DsMonad q => Type -> q Name     extract_type_name (AppT t1 _) = extract_type_name t1     extract_type_name (SigT t _) = extract_type_name t     extract_type_name (ConT n) = return n     extract_type_name _ = impossible "Record selector domain not a datatype."          filter_cons_with_names cons field_names =-      filter (\case RecC _con_name args -> let con_field_names = map fst_of_3 args in-                                           all (`elem` con_field_names) field_names-                    _ -> False) cons+      filter has_names cons+      where+        has_names (RecC _con_name args) =+          let con_field_names = map fst_of_3 args in+          all (`elem` con_field_names) field_names+        has_names (ForallC _ _ c) = has_names c+        has_names _               = False -    con_to_dmatch :: Quasi q => Con -> q DMatch+    con_to_dmatch :: DsMonad q => Con -> q DMatch     con_to_dmatch (RecC con_name args) = do       let con_field_names = map fst_of_3 args       field_var_names <- mapM (newUniqueName . nameBase) con_field_names       DMatch (DConPa con_name (map DVarPa field_var_names)) <$>              (foldl DAppE (DConE con_name) <$>                     (reorderFields args field_exps (map DVarE field_var_names)))+    con_to_dmatch (ForallC _ _ c) = con_to_dmatch c     con_to_dmatch _ = impossible "Internal error within th-desugar."      error_match = DMatch DWildPa (DAppE (DVarE 'error)-                    (DLitE (StringL "Non-exhaustive patterns in record update")))+                   (DLitE (StringL "Non-exhaustive patterns in record update")))      fst_of_3 (x, _, _) = x+#if __GLASGOW_HASKELL__ >= 709+dsExp (StaticE exp) = DStaticE <$> dsExp exp+#endif  -- | Desugar a lambda expression, where the body has already been desugared-dsLam :: Quasi q => [Pat] -> DExp -> q DExp+dsLam :: DsMonad q => [Pat] -> DExp -> q DExp dsLam pats exp   | Just names <- mapM stripVarP_maybe pats   = return $ DLamE names exp@@ -308,13 +324,13 @@        return $ DLamE arg_names (DCaseE scrutinee [match])  -- | Desugar a list of matches for a @case@ statement-dsMatches :: Quasi q+dsMatches :: DsMonad q           => Name     -- ^ Name of the scrutinee, which must be a bare var           -> [Match]  -- ^ Matches of the @case@ statement           -> q [DMatch] dsMatches scr = go   where-    go :: Quasi q => [Match] -> q [DMatch]+    go :: DsMonad q => [Match] -> q [DMatch]     go [] = return []     go (Match pat body where_decs : rest) = do       rest' <- go rest@@ -327,7 +343,7 @@       else return (DMatch pat' exp'' : rest')  -- | Desugar a @Body@-dsBody :: Quasi q+dsBody :: DsMonad q        => Body      -- ^ body to desugar        -> [Dec]     -- ^ "where" declarations        -> DExp      -- ^ what to do if the guards don't match@@ -348,7 +364,7 @@ maybeDCaseE _   scrut matches = DCaseE scrut matches  -- | Desugar guarded expressions-dsGuards :: Quasi q+dsGuards :: DsMonad q          => [(Guard, Exp)]  -- ^ Guarded expressions          -> DExp            -- ^ What to do if none of the guards match          -> q DExp@@ -361,7 +377,7 @@   dsGuardStmts stmts success failure  -- | Desugar the @Stmt@s in a guard-dsGuardStmts :: Quasi q+dsGuardStmts :: DsMonad q              => [Stmt]  -- ^ The @Stmt@s to desugar              -> DExp    -- ^ What to do if the @Stmt@s yield success              -> DExp    -- ^ What to do if the @Stmt@s yield failure@@ -394,7 +410,7 @@ dsGuardStmts (ParS _ : _) _ _ = impossible "Parallel comprehension in a pattern guard."  -- | Desugar the @Stmt@s in a @do@ expression-dsDoStmts :: Quasi q => [Stmt] -> q DExp+dsDoStmts :: DsMonad q => [Stmt] -> q DExp dsDoStmts [] = impossible "do-expression ended with something other than bare statement." dsDoStmts [NoBindS exp] = dsExp exp dsDoStmts (BindS pat exp : rest) = do@@ -409,7 +425,7 @@ dsDoStmts (ParS _ : _) = impossible "Parallel comprehension in a do-statement."  -- | Desugar the @Stmt@s in a list or monad comprehension-dsComp :: Quasi q => [Stmt] -> q DExp+dsComp :: DsMonad q => [Stmt] -> q DExp dsComp [] = impossible "List/monad comprehension ended with something other than a bare statement." dsComp [NoBindS exp] = DAppE (DVarE 'return) <$> dsExp exp dsComp (BindS pat exp : rest) = do@@ -429,7 +445,7 @@ -- | Desugar the contents of a parallel comprehension. --   Returns a @Pat@ containing a tuple of all bound variables and an expression --   to produce the values for those variables-dsParComp :: Quasi q => [[Stmt]] -> q (Pat, DExp)+dsParComp :: DsMonad q => [[Stmt]] -> q (Pat, DExp) dsParComp [] = impossible "Empty list of parallel comprehension statements." dsParComp [r] = do   let rv = foldMap extractBoundNamesStmt r@@ -454,14 +470,14 @@  -- | Desugar a pattern, along with processing a (desugared) expression that -- is the entire scope of the variables bound in the pattern.-dsPatOverExp :: Quasi q => Pat -> DExp -> q (DPat, DExp)+dsPatOverExp :: DsMonad q => Pat -> DExp -> q (DPat, DExp) dsPatOverExp pat exp = do   (pat', vars) <- runWriterT $ dsPat pat   let name_decs = uncurry (zipWith (DValD . DVarPa)) $ unzip vars   return (pat', maybeDLetE name_decs exp)  -- | Desugar multiple patterns. Like 'dsPatOverExp'.-dsPatsOverExp :: Quasi q => [Pat] -> DExp -> q ([DPat], DExp)+dsPatsOverExp :: DsMonad q => [Pat] -> DExp -> q ([DPat], DExp) dsPatsOverExp pats exp = do   (pats', vars) <- runWriterT $ mapM dsPat pats   let name_decs = uncurry (zipWith (DValD . DVarPa)) $ unzip vars@@ -469,7 +485,7 @@  -- | Desugar a pattern, returning a list of (Name, DExp) pairs of extra -- variables that must be bound within the scope of the pattern-dsPatX :: Quasi q => Pat -> q (DPat, [(Name, DExp)])+dsPatX :: DsMonad q => Pat -> q (DPat, [(Name, DExp)]) dsPatX = runWriterT . dsPat  -- | Desugaring a pattern also returns the list of variables bound in as-patterns@@ -478,7 +494,7 @@ type PatM q = WriterT [(Name, DExp)] q  -- | Desugar a pattern.-dsPat :: Quasi q => Pat -> PatM q DPat+dsPat :: DsMonad q => Pat -> PatM q DPat dsPat (LitP lit) = return $ DLitPa lit dsPat (VarP n) = return $ DVarPa n dsPat (TupP pats) = DConPa (tupleDataName (length pats)) <$> mapM dsPat pats@@ -528,7 +544,7 @@  -- | Remove all wildcards from a pattern, replacing any wildcard with a fresh --   variable-removeWilds :: Quasi q => DPat -> q DPat+removeWilds :: DsMonad q => DPat -> q DPat removeWilds p@(DLitPa _) = return p removeWilds p@(DVarPa _) = return p removeWilds (DConPa con_name pats) = DConPa con_name <$> mapM removeWilds pats@@ -537,7 +553,7 @@ removeWilds DWildPa = DVarPa <$> newUniqueName "wild"  -- | Desugar @Info@-dsInfo :: Quasi q => Info -> q DInfo+dsInfo :: DsMonad q => Info -> q DInfo dsInfo (ClassI dec instances) = do   [ddec]     <- dsDec dec   dinstances <- dsDecs instances@@ -563,7 +579,7 @@   impossible $ "Declaration supplied with variable: " ++ show name dsInfo (TyVarI name ty) = DTyVarI name <$> dsKind ty -fixBug8884ForFamilies :: Quasi q => DDec -> q (DDec, Int)+fixBug8884ForFamilies :: DsMonad q => DDec -> q (DDec, Int) #if __GLASGOW_HASKELL__ < 708 fixBug8884ForFamilies (DFamilyD flav name tvbs m_kind) = do   let num_args = length tvbs@@ -577,7 +593,7 @@ fixBug8884ForFamilies dec =   impossible $ "Reifying yielded a FamilyI with a non-family Dec: " ++ show dec -remove_arrows :: Quasi q => Int -> DKind -> q DKind+remove_arrows :: DsMonad q => Int -> DKind -> q DKind remove_arrows 0 k = return k remove_arrows n (DArrowK _ k) = remove_arrows (n-1) k remove_arrows _ _ =@@ -602,11 +618,11 @@ #endif  -- | Desugar arbitrary @Dec@s-dsDecs :: Quasi q => [Dec] -> q [DDec]+dsDecs :: DsMonad q => [Dec] -> q [DDec] dsDecs = concatMapM dsDec  -- | Desugar a single @Dec@, perhaps producing multiple 'DDec's-dsDec :: Quasi q => Dec -> q [DDec]+dsDec :: DsMonad q => Dec -> q [DDec] dsDec d@(FunD {}) = (fmap . map) DLetDec $ dsLetDec d dsDec d@(ValD {}) = (fmap . map) DLetDec $ dsLetDec d dsDec (DataD cxt n tvbs cons derivings) =@@ -647,13 +663,19 @@                                   <*> mapM dsTySynEqn eqns) dsDec (RoleAnnotD n roles) = return [DRoleAnnotD n roles] #endif-             +#if __GLASGOW_HASKELL__ >= 709+dsDec (StandaloneDerivD cxt ty) = (:[]) <$> (DStandaloneDerivD <$> dsCxt cxt+                                                               <*> dsType ty)+dsDec (DefaultSigD n ty) = (:[]) <$> (DDefaultSigD n <$> dsType ty)+#endif++   -- | Desugar @Dec@s that can appear in a let expression-dsLetDecs :: Quasi q => [Dec] -> q [DLetDec]+dsLetDecs :: DsMonad q => [Dec] -> q [DLetDec] dsLetDecs = concatMapM dsLetDec  -- | Desugar a single @Dec@, perhaps producing multiple 'DLetDec's-dsLetDec :: Quasi q => Dec -> q [DLetDec]+dsLetDec :: DsMonad q => Dec -> q [DLetDec] dsLetDec (FunD name clauses) = do   clauses' <- dsClauses name clauses   return [DFunD name clauses']@@ -672,7 +694,7 @@ dsLetDec _dec = impossible "Illegal declaration in let expression."  -- | Desugar a single @Con@.-dsCon :: Quasi q => Con -> q DCon+dsCon :: DsMonad q => Con -> q DCon dsCon (NormalC n stys) = DCon [] [] n <$> (DNormalC <$> mapM (liftSndM dsType) stys) dsCon (RecC n vstys) = DCon [] [] n <$> (DRecC <$> mapM (liftThdOf3M dsType) vstys) dsCon (InfixC (s1, ty1) n (s2, ty2)) = do@@ -686,12 +708,12 @@   return $ DCon (dtvbs ++ dtvbs') (dcxt ++ dcxt') n fields  -- | Desugar a @Foreign@.-dsForeign :: Quasi q => Foreign -> q DForeign+dsForeign :: DsMonad q => Foreign -> q DForeign dsForeign (ImportF cc safety str n ty) = DImportF cc safety str n <$> dsType ty dsForeign (ExportF cc str n ty)        = DExportF cc str n <$> dsType ty  -- | Desugar a @Pragma@.-dsPragma :: Quasi q => Pragma -> q DPragma+dsPragma :: DsMonad q => Pragma -> q DPragma dsPragma (InlineP n inl rm phases)       = return $ DInlineP n inl rm phases dsPragma (SpecialiseP n ty m_inl phases) = DSpecialiseP n <$> dsType ty                                                           <*> pure m_inl@@ -704,20 +726,23 @@ #if __GLASGOW_HASKELL__ >= 707 dsPragma (AnnP target exp)               = DAnnP target <$> dsExp exp #endif+#if __GLASGOW_HASKELL__ >= 709+dsPragma (LineP n str)                   = return $ DLineP n str+#endif  -- | Desugar a @RuleBndr@.-dsRuleBndr :: Quasi q => RuleBndr -> q DRuleBndr+dsRuleBndr :: DsMonad q => RuleBndr -> q DRuleBndr dsRuleBndr (RuleVar n)         = return $ DRuleVar n dsRuleBndr (TypedRuleVar n ty) = DTypedRuleVar n <$> dsType ty  #if __GLASGOW_HASKELL__ >= 707 -- | Desugar a @TySynEqn@. (Available only with GHC 7.8+)-dsTySynEqn :: Quasi q => TySynEqn -> q DTySynEqn+dsTySynEqn :: DsMonad q => TySynEqn -> q DTySynEqn dsTySynEqn (TySynEqn lhs rhs) = DTySynEqn <$> mapM dsType lhs <*> dsType rhs #endif  -- | Desugar clauses to a function definition-dsClauses :: Quasi q+dsClauses :: DsMonad q           => Name         -- ^ Name of the function           -> [Clause]     -- ^ Clauses to desugar           -> q [DClause]@@ -737,7 +762,7 @@               (DCaseE scrutinee <$> foldrM (clause_to_dmatch scrutinee) [] clauses)   return [clause]   where-    clause_to_dmatch :: Quasi q => DExp -> Clause -> [DMatch] -> q [DMatch]+    clause_to_dmatch :: DsMonad q => DExp -> Clause -> [DMatch] -> q [DMatch]     clause_to_dmatch scrutinee (Clause pats body where_decs) failure_matches = do       let failure_exp = maybeDCaseE ("Non-exhaustive patterns in " ++ (show n))                                     scrutinee failure_matches@@ -750,7 +775,7 @@       else return (match : failure_matches)  -- | Desugar a type-dsType :: Quasi q => Type -> q DType+dsType :: DsMonad q => Type -> q DType dsType (ForallT tvbs preds ty) = DForallT <$> mapM dsTvb tvbs <*> dsCxt preds <*> dsType ty dsType (AppT t1 t2) = DAppT <$> dsType t1 <*> dsType t2 dsType (SigT ty ki) = DSigT <$> dsType ty <*> dsKind ki@@ -776,16 +801,16 @@ #endif  -- | Desugar a @TyVarBndr@-dsTvb :: Quasi q => TyVarBndr -> q DTyVarBndr+dsTvb :: DsMonad q => TyVarBndr -> q DTyVarBndr dsTvb (PlainTV n) = return $ DPlainTV n dsTvb (KindedTV n k) = DKindedTV n <$> dsKind k  -- | Desugar a @Cxt@-dsCxt :: Quasi q => Cxt -> q DCxt+dsCxt :: DsMonad q => Cxt -> q DCxt dsCxt = concatMapM dsPred  -- | Desugar a @Pred@, flattening any internal tuples-dsPred :: Quasi q => Pred -> q DCxt+dsPred :: DsMonad q => Pred -> q DCxt #if __GLASGOW_HASKELL__ < 709 dsPred (ClassP n tys) = do   ts' <- mapM dsType tys@@ -830,7 +855,7 @@ #endif  -- | Desugar a kind-dsKind :: Quasi q => Kind -> q DKind+dsKind :: DsMonad q => Kind -> q DKind dsKind (ForallT tvbs cxt ki)   | [] <- cxt   , Just names <- mapM stripPlainTV_maybe tvbs@@ -863,15 +888,20 @@ #if __GLASGOW_HASKELL__ >= 709 dsKind EqualityT = impossible "(~) used in a kind." #endif-                       ++-- | Like 'reify', but safer and desugared. Uses local declarations where+-- available.+dsReify :: DsMonad q => Name -> q (Maybe DInfo)+dsReify = traverse dsInfo <=< reifyWithLocals_maybe+   -- create a list of expressions in the same order as the fields in the first argument -- but with the values as given in the second argument -- if a field is missing from the second argument, use the corresponding expression -- from the third argument-reorderFields :: Quasi q => [VarStrictType] -> [FieldExp] -> [DExp] -> q [DExp]+reorderFields :: DsMonad q => [VarStrictType] -> [FieldExp] -> [DExp] -> q [DExp] reorderFields = reorderFields' dsExp -reorderFieldsPat :: Quasi q => [VarStrictType] -> [FieldPat] -> PatM q [DPat]+reorderFieldsPat :: DsMonad q => [VarStrictType] -> [FieldPat] -> PatM q [DPat] reorderFieldsPat field_decs field_pats =   reorderFields' dsPat field_decs field_pats (repeat DWildPa) @@ -909,7 +939,7 @@ mkTuplePat pats = ConP (tupleDataName (length pats)) pats  -- | Is this pattern guaranteed to match?-isUniversalPattern :: Quasi q => DPat -> q Bool+isUniversalPattern :: DsMonad q => DPat -> q Bool isUniversalPattern (DLitPa {}) = return False isUniversalPattern (DVarPa {}) = return True isUniversalPattern (DConPa con_name pats) = do
Language/Haskell/TH/Desugar/Expand.hs view
@@ -26,21 +26,24 @@   ) where  import qualified Data.Map as M+import qualified Data.Set as S import Control.Monad import Control.Applicative import Language.Haskell.TH hiding (cxt) import Language.Haskell.TH.Syntax ( Quasi(..) ) import Data.Data import Data.Generics-import Data.Monoid+import Data.List+import qualified Data.Traversable as T  import Language.Haskell.TH.Desugar.Core import Language.Haskell.TH.Desugar.Util import Language.Haskell.TH.Desugar.Sweeten+import Language.Haskell.TH.Desugar.Reify  -- | Expands all type synonyms in a desugared type. Also expands open type family -- applications, as long as the arguments have no free variables.-expandType :: Quasi q => DType -> q DType+expandType :: DsMonad q => DType -> q DType expandType = go []   where     go [] (DForallT tvbs cxt ty) =@@ -57,7 +60,7 @@     go args ty = return $ foldl DAppT ty args  -- | Expands all type synonyms in a desugared predicate.-expandPred :: Quasi q => DPred -> q DPred+expandPred :: DsMonad q => DPred -> q DPred expandPred = go []   where     go args (DAppPr p t) = do@@ -72,13 +75,14 @@     go args p = return $ foldl DAppPr p args  -- | Expand a constructor with given arguments-expandCon :: Quasi q+expandCon :: DsMonad q           => Name     -- ^ Tycon name           -> [DType]  -- ^ Arguments           -> q DType  -- ^ Expanded type expandCon n args = do-  info <- reifyWithWarning n+  info <- reifyWithLocals n   dinfo <- dsInfo info+  args_ok <- allM no_tyvars_tyfams args   case dinfo of     DTyConI (DTySynD _n tvbs rhs) _       |  length args >= length tvbs   -- this should always be true!@@ -90,7 +94,7 @@      DTyConI (DFamilyD TypeFam _n tvbs _mkind) _       |  length args >= length tvbs   -- this should always be true!-      ,  all no_tyvars args+      ,  args_ok       -> do         let (syn_args, rest_args) = splitAtList tvbs args         -- need to get the correct instance@@ -98,42 +102,90 @@         dinsts <- dsDecs insts         case dinsts of           [DTySynInstD _n (DTySynEqn lhs rhs)] -> do-            let subst = mconcat $ zipWith build_subst lhs syn_args+            subst <-+              expectJustM "Impossible: reification returned a bogus instance" $+              merge_maps $ zipWith build_subst lhs syn_args             ty <- substTy subst rhs             ty' <- expandType ty             return $ foldl DAppT ty' rest_args           _ -> return $ foldl DAppT (DConT n) args-    ++    DTyConI (DClosedTypeFamilyD _n tvbs _resk eqns) _+      |  length args >= length tvbs+      ,  args_ok+      -> do+        let (syn_args, rest_args) = splitAtList tvbs args+        rhss <- mapMaybeM (check_eqn syn_args) eqns+        case rhss of+          (rhs : _) -> do+            rhs' <- expandType rhs+            return $ foldl DAppT rhs' rest_args+          [] -> return $ foldl DAppT (DConT n) args++      where+         -- returns the substed rhs+        check_eqn :: DsMonad q => [DType] -> DTySynEqn -> q (Maybe DType)+        check_eqn arg_tys (DTySynEqn lhs rhs) = do+          let m_subst = merge_maps $ zipWith build_subst lhs arg_tys+          T.mapM (flip substTy rhs) m_subst+               _ -> return $ foldl DAppT (DConT n) args    where-    no_tyvars :: Data a => a -> Bool-    no_tyvars = everything (&&) (mkQ True no_tyvar)+    no_tyvars_tyfams :: (DsMonad q, Data a) => a -> q Bool+    no_tyvars_tyfams = everything (liftM2 (&&)) (mkQ (return True) no_tyvar_tyfam) -    no_tyvar :: DType -> Bool-    no_tyvar (DVarT _) = False-    no_tyvar t         = gmapQl (&&) True no_tyvars t+    no_tyvar_tyfam :: DsMonad q => DType -> q Bool+    no_tyvar_tyfam (DVarT _) = return False+    no_tyvar_tyfam (DConT con_name) = do+      m_info <- dsReify con_name+      return $ case m_info of+        Nothing -> False   -- we don't know anything. False is safe.+        Just (DTyConI (DFamilyD {}) _)           -> False+        Just (DTyConI (DClosedTypeFamilyD {}) _) -> False+        _                                        -> True+    no_tyvar_tyfam t = gmapQl (liftM2 (&&)) (return True) no_tyvars_tyfams t -    build_subst :: DType -> DType -> M.Map Name DType-    build_subst (DVarT var_name) arg = M.singleton var_name arg-      -- ignore kind signatures; any kind constraints are already-      -- handled in reifyInstances+    build_subst :: DType -> DType -> Maybe (M.Map Name DType)+    build_subst (DVarT var_name) arg = Just $ M.singleton var_name arg+      -- if a pattern has a kind signature, it's really easy to get+      -- this wrong.+    build_subst (DSigT {}) _ = Nothing+      -- but we can safely ignore kind signatures on the target     build_subst pat (DSigT ty _ki) = build_subst pat ty-    build_subst (DSigT ty _ki) arg = build_subst ty arg     build_subst (DForallT {}) _ =       error "Impossible: forall-quantified pattern to type family"       -- reifyInstances should fail if an argument is forall-quantified.     build_subst _ (DForallT {}) =       error "Impossible: forall-quantified argument to type family"     build_subst (DAppT pat1 pat2) (DAppT arg1 arg2) =-      build_subst pat1 arg1 <> build_subst pat2 arg2-    build_subst (DConT _pat_con) (DConT _arg_con) = mempty-    build_subst DArrowT DArrowT = mempty-    build_subst (DLitT _pat_lit) (DLitT _arg_lit) = mempty-    build_subst pat arg = error $ "Impossible: reifyInstances succeeded but unification failed; pat=" ++ show pat ++ "; arg=" ++ show arg+      merge_maps [build_subst pat1 arg1, build_subst pat2 arg2]+    build_subst (DConT pat_con) (DConT arg_con)+      | pat_con == arg_con = Just M.empty+    build_subst DArrowT DArrowT = Just M.empty+    build_subst (DLitT pat_lit) (DLitT arg_lit)+      | pat_lit == arg_lit = Just M.empty+    build_subst _ _ = Nothing +    merge_maps :: [Maybe (M.Map Name DType)] -> Maybe (M.Map Name DType)+    merge_maps = foldl' merge_map1 (Just M.empty)++    merge_map1 :: Maybe (M.Map Name DType) -> Maybe (M.Map Name DType)+               -> Maybe (M.Map Name DType)+    merge_map1 ma mb = do+      a <- ma+      b <- mb+      let shared_key_set = M.keysSet a `S.intersection` M.keysSet b+          matches_up     = S.foldr (\name -> ((a M.! name) `geq` (b M.! name) &&))+                                   True shared_key_set+      if matches_up then return (a `M.union` b) else Nothing++    allM :: Monad m => (a -> m Bool) -> [a] -> m Bool+    allM f = foldM (\b x -> (b &&) `liftM` f x) True++ -- | Capture-avoiding substitution on types-substTy :: Quasi q => M.Map Name DType -> DType -> q DType+substTy :: DsMonad q => M.Map Name DType -> DType -> q DType substTy vars (DForallT tvbs cxt ty) =   substTyVarBndrs vars tvbs $ \vars' tvbs' -> do     cxt' <- mapM (substPred vars') cxt@@ -150,7 +202,7 @@   = return $ DVarT n substTy _ ty = return ty -substTyVarBndrs :: Quasi q => M.Map Name DType -> [DTyVarBndr]+substTyVarBndrs :: DsMonad q => M.Map Name DType -> [DTyVarBndr]                 -> (M.Map Name DType -> [DTyVarBndr] -> q DType)                 -> q DType substTyVarBndrs vars tvbs thing = do@@ -168,7 +220,7 @@ extractDTvbName (DPlainTV n) = n extractDTvbName (DKindedTV n _) = n -substPred :: Quasi q => M.Map Name DType -> DPred -> q DPred+substPred :: DsMonad q => M.Map Name DType -> DPred -> q DPred substPred vars (DAppPr p t) = DAppPr <$> substPred vars p <*> substTy vars t substPred vars (DSigPr p k) = DSigPr <$> substPred vars p <*> pure k substPred vars (DVarPr n)@@ -179,7 +231,7 @@ substPred _ p = return p  -- | Convert a 'DType' to a 'DPred'-dTypeToDPred :: Quasi q => DType -> q DPred+dTypeToDPred :: DsMonad q => DType -> q DPred dTypeToDPred (DForallT _ _ _) = impossible "Forall-type used as constraint" dTypeToDPred (DAppT t1 t2)   = DAppPr <$> dTypeToDPred t1 <*> pure t2 dTypeToDPred (DSigT ty ki)   = DSigPr <$> dTypeToDPred ty <*> pure ki@@ -192,5 +244,5 @@ -- | Expand all type synonyms and open type families in the desugared abstract -- syntax tree provided. Normally, the first parameter should have a type like -- 'DExp' or 'DLetDec'.-expand :: (Quasi q, Data a) => a -> q a+expand :: (DsMonad q, Data a) => a -> q a expand = everywhereM (mkM expandType >=> mkM expandPred)
Language/Haskell/TH/Desugar/Lift.hs view
@@ -14,243 +14,29 @@ -- ---------------------------------------------------------------------------- -{-# LANGUAGE TemplateHaskell, MagicHash, TypeSynonymInstances, FlexibleInstances #-}+{-# LANGUAGE CPP, TemplateHaskell #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Language.Haskell.TH.Desugar.Lift () where -import Prelude hiding ( mod, words ) import Language.Haskell.TH.Desugar-import Language.Haskell.TH.Syntax-import Control.Applicative-import GHC.Exts-import GHC.Word--foldApp :: Exp -> [Exp] -> Exp-foldApp = foldl AppE-           -instance Lift DExp where-  lift (DVarE n)      = foldApp (ConE 'DVarE)  <$> sequence [lift n]-  lift (DConE n)      = foldApp (ConE 'DConE)  <$> sequence [lift n]-  lift (DLitE l)      = foldApp (ConE 'DLitE)  <$> sequence [lift l]-  lift (DAppE e1 e2)  = foldApp (ConE 'DAppE)  <$> sequence [lift e1, lift e2]-  lift (DLamE ns e)   = foldApp (ConE 'DLamE)  <$> sequence [lift ns, lift e]-  lift (DCaseE e ms)  = foldApp (ConE 'DCaseE) <$> sequence [lift e, lift ms]-  lift (DLetE decs e) = foldApp (ConE 'DLetE)  <$> sequence [lift decs, lift e]-  lift (DSigE e t)    = foldApp (ConE 'DSigE)  <$> sequence [lift e, lift t]--instance Lift DPat where-  lift (DLitPa l)    = foldApp (ConE 'DLitPa)   <$> sequence [lift l]-  lift (DVarPa n)    = foldApp (ConE 'DVarPa)   <$> sequence [lift n]-  lift (DConPa n ps) = foldApp (ConE 'DConPa)   <$> sequence [lift n, lift ps]-  lift (DTildePa p)  = foldApp (ConE 'DTildePa) <$> sequence [lift p]-  lift (DBangPa p)   = foldApp (ConE 'DBangPa)  <$> sequence [lift p]-  lift DWildPa       = return $ ConE 'DWildPa--instance Lift DType where-  lift (DForallT tvbs cxt t) =-    foldApp (ConE 'DForallT) <$> sequence [lift tvbs, lift cxt, lift t]-  lift (DAppT t1 t2) = foldApp (ConE 'DAppT) <$> sequence [lift t1, lift t2]-  lift (DSigT t k)   = foldApp (ConE 'DSigT) <$> sequence [lift t, lift k]-  lift (DVarT n)     = foldApp (ConE 'DVarT) <$> sequence [lift n]-  lift (DConT n)     = foldApp (ConE 'DConT) <$> sequence [lift n]-  lift DArrowT       = return $ ConE 'DArrowT-  lift (DLitT l)     = foldApp (ConE 'DLitT) <$> sequence [lift l]--instance Lift DKind where-  lift (DForallK ns k) = foldApp (ConE 'DForallK) <$> sequence [lift ns, lift k]-  lift (DVarK n)       = foldApp (ConE 'DVarK)    <$> sequence [lift n]-  lift (DConK n ks)    = foldApp (ConE 'DConK)    <$> sequence [lift n, lift ks]-  lift (DArrowK k1 k2) = foldApp (ConE 'DArrowK)  <$> sequence [lift k1, lift k2]-  lift DStarK          = return $ ConE 'DStarK--instance Lift DPred where-  lift (DAppPr p t) = foldApp (ConE 'DAppPr) <$> sequence [lift p, lift t]-  lift (DSigPr p k) = foldApp (ConE 'DSigPr) <$> sequence [lift p, lift k]-  lift (DVarPr n)   = foldApp (ConE 'DVarPr) <$> sequence [lift n]-  lift (DConPr n)   = foldApp (ConE 'DConPr) <$> sequence [lift n]--instance Lift DTyVarBndr where-  lift (DPlainTV n)    = foldApp (ConE 'DPlainTV)  <$> sequence [lift n]-  lift (DKindedTV n k) = foldApp (ConE 'DKindedTV) <$> sequence [lift n, lift k]--instance Lift DMatch where-  lift (DMatch p e) = foldApp (ConE 'DMatch) <$> sequence [lift p, lift e]--instance Lift DClause where-  lift (DClause ps e) = foldApp (ConE 'DClause) <$> sequence [lift ps, lift e]--instance Lift DLetDec where-  lift (DFunD n cs)  = foldApp (ConE 'DFunD)   <$> sequence [lift n, lift cs]-  lift (DValD p e)   = foldApp (ConE 'DValD)   <$> sequence [lift p, lift e]-  lift (DSigD n t)   = foldApp (ConE 'DSigD)   <$> sequence [lift n, lift t]-  lift (DInfixD f n) = foldApp (ConE 'DInfixD) <$> sequence [lift f, lift n]--instance Lift NewOrData where-  lift Newtype = return $ ConE 'Newtype-  lift Data    = return $ ConE 'Data--instance Lift DDec where-  lift (DLetDec dec) = foldApp (ConE 'DLetDec) <$> sequence [lift dec]-  lift (DDataD nd cxt n tvbs cons derivs) =-    foldApp (ConE 'DDataD) <$> sequence [ lift nd, lift cxt, lift n-                                        , lift tvbs, lift cons, lift derivs ]-  lift (DTySynD n tvbs ty) =-    foldApp (ConE 'DTySynD) <$> sequence [lift n, lift tvbs, lift ty]-  lift (DClassD cxt n tvbs fds decs) =-    foldApp (ConE 'DClassD) <$> sequence [ lift cxt, lift n, lift tvbs-                                         , lift fds, lift decs ]-  lift (DInstanceD cxt ty decs) =-    foldApp (ConE 'DInstanceD) <$> sequence [lift cxt, lift ty, lift decs]-  lift (DForeignD for) = foldApp (ConE 'DForeignD) <$> sequence [lift for]-  lift (DPragmaD prag) = foldApp (ConE 'DPragmaD) <$> sequence [lift prag]-  lift (DFamilyD flav n tvbs res) =-    foldApp (ConE 'DFamilyD) <$> sequence [lift flav, lift n, lift tvbs, lift res]-  lift (DDataInstD nd cxt n tys cons derivs) =-    foldApp (ConE 'DDataInstD) <$> sequence [ lift nd, lift cxt, lift n-                                            , lift tys, lift cons, lift derivs ]-  lift (DTySynInstD n eqn) = foldApp (ConE 'DTySynInstD) <$> sequence [lift n, lift eqn]-  lift (DClosedTypeFamilyD n tvbs res eqns) =-    foldApp (ConE 'DClosedTypeFamilyD) <$> sequence [ lift n, lift tvbs-                                                    , lift res, lift eqns ]-  lift (DRoleAnnotD n rs) =-    foldApp (ConE 'DRoleAnnotD) <$> sequence [lift n, lift rs]--instance Lift DCon where-  lift (DCon tvbs cxt n fields) =-    foldApp (ConE 'DCon) <$> sequence [lift tvbs, lift cxt, lift n, lift fields]--instance Lift DConFields where-  lift (DNormalC stys) = foldApp (ConE 'DNormalC) <$> sequence [lift stys]-  lift (DRecC vstys)   = foldApp (ConE 'DRecC)    <$> sequence [lift vstys]--instance Lift DForeign where-  lift (DImportF cc safe str n ty) =-    foldApp (ConE 'DImportF) <$> sequence [ lift cc, lift safe, lift str-                                          , lift n, lift ty ]-  lift (DExportF cc str n ty) =-    foldApp (ConE 'DExportF) <$> sequence [lift cc, lift str, lift n, lift ty]--instance Lift DPragma where-  lift (DInlineP n i rm phases) =-    foldApp (ConE 'DInlineP) <$> sequence [lift n, lift i, lift rm, lift phases]-  lift (DSpecialiseP n ty m_i phases) =-    foldApp (ConE 'DSpecialiseP) <$> sequence [ lift n, lift ty-                                              , lift m_i, lift phases ]-  lift (DSpecialiseInstP ty) = foldApp (ConE 'DSpecialiseInstP) <$> sequence [lift ty]-  lift (DRuleP str bndrs e1 e2 phases) =-    foldApp (ConE 'DRuleP) <$> sequence [ lift str, lift bndrs, lift e1-                                        , lift e2, lift phases ]-  lift (DAnnP targ e) = foldApp (ConE 'DAnnP) <$> sequence [lift targ, lift e]--instance Lift DRuleBndr where-  lift (DRuleVar n) = foldApp (ConE 'DRuleVar) <$> sequence [lift n]-  lift (DTypedRuleVar n ty) =-    foldApp (ConE 'DTypedRuleVar) <$> sequence [lift n, lift ty]--instance Lift DTySynEqn where-  lift (DTySynEqn lhs rhs) = foldApp (ConE 'DTySynEqn) <$> sequence [lift lhs, lift rhs]-                                 --- Template Haskell liftings--instance Lift OccName where-  lift (OccName n) = foldApp (ConE 'OccName) <$> sequence [lift n]--instance Lift ModName where-  lift (ModName n) = foldApp (ConE 'ModName) <$> sequence [lift n]--instance Lift PkgName where-  lift (PkgName n) = foldApp (ConE 'PkgName) <$> sequence [lift n]--instance Lift NameSpace where-  lift VarName   = return $ ConE 'VarName-  lift DataName  = return $ ConE 'DataName-  lift TcClsName = return $ ConE 'TcClsName--instance Lift NameFlavour where-  lift NameS       = return $ ConE 'NameS-  lift (NameQ mod) = foldApp (ConE 'NameQ) <$> sequence [lift mod]-  lift (NameU n)   = return $ foldApp (ConE 'NameU) [LitE $ IntPrimL $ toInteger $ I# n]-  lift (NameL n)   = return $ foldApp (ConE 'NameL) [LitE $ IntPrimL $ toInteger $ I# n]-  lift (NameG ns pkg mod) =-    foldApp (ConE 'NameG) <$> sequence [lift ns, lift pkg, lift mod]--instance Lift Name where-  lift (Name occ flav) = foldApp (ConE 'Name) <$> sequence [lift occ, lift flav]-                                  -instance Lift Lit where-  lift (CharL ch)          = foldApp (ConE 'CharL)       <$> sequence [lift ch]-  lift (StringL str)       = foldApp (ConE 'StringL)     <$> sequence [lift str]-  lift (IntegerL i)        = foldApp (ConE 'IntegerL)    <$> sequence [lift i]-  lift (RationalL rat)     = foldApp (ConE 'RationalL)   <$> sequence [lift rat]-  lift (IntPrimL i)        = foldApp (ConE 'IntPrimL)    <$> sequence [lift i]-  lift (WordPrimL i)       = foldApp (ConE 'WordPrimL)   <$> sequence [lift i]-  lift (FloatPrimL rat)    = foldApp (ConE 'FloatPrimL)  <$> sequence [lift rat]-  lift (DoublePrimL rat)   = foldApp (ConE 'DoublePrimL) <$> sequence [lift rat]-  lift (StringPrimL words) = foldApp (ConE 'StringPrimL) <$> sequence [lift words]--instance Lift TyLit where-  lift (NumTyLit i) = foldApp (ConE 'NumTyLit) <$> sequence [lift i]-  lift (StrTyLit s) = foldApp (ConE 'StrTyLit) <$> sequence [lift s]--instance Lift Fixity where-  lift (Fixity i dir) = foldApp (ConE 'Fixity) <$> sequence [lift i, lift dir]--instance Lift FixityDirection where-  lift InfixL = return $ ConE 'InfixL-  lift InfixR = return $ ConE 'InfixR-  lift InfixN = return $ ConE 'InfixN--instance Lift Strict where-  lift IsStrict  = return $ ConE 'IsStrict-  lift NotStrict = return $ ConE 'NotStrict-  lift Unpacked  = return $ ConE 'Unpacked--instance Lift Callconv where-  lift CCall   = return $ ConE 'CCall-  lift StdCall = return $ ConE 'StdCall--instance Lift Safety where-  lift Unsafe = return $ ConE 'Unsafe-  lift Safe   = return $ ConE 'Safe-  lift Interruptible = return $ ConE 'Interruptible--instance Lift Inline where-  lift NoInline  = return $ ConE 'NoInline-  lift Inline    = return $ ConE 'Inline-  lift Inlinable = return $ ConE 'Inlinable--instance Lift RuleMatch where-  lift ConLike = return $ ConE 'ConLike-  lift FunLike = return $ ConE 'FunLike--instance Lift Phases where-  lift AllPhases       = return $ ConE 'AllPhases-  lift (FromPhase i)   = foldApp (ConE 'FromPhase)   <$> sequence [lift i]-  lift (BeforePhase i) = foldApp (ConE 'BeforePhase) <$> sequence [lift i]--instance Lift AnnTarget where-  lift ModuleAnnotation    = return $ ConE 'ModuleAnnotation-  lift (TypeAnnotation n)  = foldApp (ConE 'TypeAnnotation)  <$> sequence [lift n]-  lift (ValueAnnotation n) = foldApp (ConE 'ValueAnnotation) <$> sequence [lift n]--instance Lift FunDep where-  lift (FunDep lhs rhs) = foldApp (ConE 'FunDep) <$> sequence [lift lhs, lift rhs]--instance Lift FamFlavour where-  lift TypeFam = return $ ConE 'TypeFam-  lift DataFam = return $ ConE 'DataFam+import Language.Haskell.TH.Lift+import Language.Haskell.TH+#if __GLASGOW_HASKELL__ <= 708+import Data.Word+#endif -instance Lift Role where-  lift NominalR          = return $ ConE 'NominalR-  lift RepresentationalR = return $ ConE 'RepresentationalR-  lift PhantomR          = return $ ConE 'PhantomR-  lift InferR            = return $ ConE 'InferR+$(deriveLiftMany [ ''DExp, ''DPat, ''DType, ''DKind, ''DPred, ''DTyVarBndr+                 , ''DMatch, ''DClause, ''DLetDec, ''DDec, ''DCon+                 , ''DConFields, ''DForeign, ''DPragma, ''DRuleBndr, ''DTySynEqn+                 , ''NewOrData+                 , ''Lit, ''TyLit, ''Fixity, ''FixityDirection, ''Strict+                 , ''Callconv, ''Safety, ''Inline, ''RuleMatch, ''Phases+                 , ''AnnTarget, ''FunDep, ''FamFlavour, ''Role ]) +#if __GLASGOW_HASKELL__ <= 708 -- Other type liftings:                                       -instance Lift Rational where-  lift rat = return $ LitE $ RationalL rat- instance Lift Word8 where-  lift word = return $ foldApp (VarE 'fromInteger) [LitE $ IntegerL (toInteger word)]+  lift word = return $ (VarE 'fromInteger) `AppE` (LitE $ IntegerL (toInteger word))+#endif
+ Language/Haskell/TH/Desugar/Match.hs view
@@ -0,0 +1,393 @@+{- Language/Haskell/TH/Desugar/Match.hs++(c) Richard Eisenberg 2013+eir@cis.upenn.edu++Simplifies case statements in desugared TH. After this pass, there are no+more nested patterns.++This code is directly based on the analogous operation as written in GHC.+-}++{-# LANGUAGE CPP, TemplateHaskell #-}++#if __GLASGOW_HASKELL__ <= 708+{-# LANGUAGE StandaloneDeriving #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}   -- we need Ord Lit. argh.+#endif++module Language.Haskell.TH.Desugar.Match (scExp, scLetDec) where++import Prelude hiding ( fail, exp )++import Control.Applicative+import Control.Monad hiding ( fail )+import qualified Data.Set as S+import qualified Data.Map as Map+import Language.Haskell.TH.Syntax++import Language.Haskell.TH.Desugar.Core+import Language.Haskell.TH.Desugar.Util+import Language.Haskell.TH.Desugar.Reify++-- | Remove all nested pattern-matches within this expression. This also+-- removes all 'DTildePa's and 'DBangPa's. After this is run, every pattern+-- is guaranteed to be either a 'DConPa' with bare variables as arguments,+-- a 'DLitPa', or a 'DWildPa'.+scExp :: DsMonad q => DExp -> q DExp+scExp (DAppE e1 e2) = DAppE <$> scExp e1 <*> scExp e2+scExp (DLamE names exp) = DLamE names <$> scExp exp+scExp (DCaseE scrut matches)+  | DVarE name <- scrut+  = simplCaseExp [name] clauses+  | otherwise+  = do scrut_name <- newUniqueName "scrut"+       case_exp <- simplCaseExp [scrut_name] clauses+       return $ DLetE [DValD (DVarPa scrut_name) scrut] case_exp+  where+    clauses = map match_to_clause matches+    match_to_clause (DMatch pat exp) = DClause [pat] exp++scExp (DLetE decs body) = DLetE <$> mapM scLetDec decs <*> scExp body+scExp (DSigE exp ty) = DSigE <$> scExp exp <*> pure ty+scExp e = return e++-- | Like 'scExp', but for a 'DLetDec'.+scLetDec :: DsMonad q => DLetDec -> q DLetDec+scLetDec (DFunD name clauses@(DClause pats1 _ : _)) = do+  arg_names <- mapM (const (newUniqueName "_arg")) pats1+  clauses' <- mapM sc_clause_rhs clauses+  case_exp <- simplCaseExp arg_names clauses'+  return $ DFunD name [DClause (map DVarPa arg_names) case_exp]+  where+    sc_clause_rhs (DClause pats exp) = DClause pats <$> scExp exp+scLetDec (DValD pat exp) = DValD pat <$> scExp exp+scLetDec dec = return dec++type MatchResult = DExp -> DExp++matchResultToDExp :: MatchResult -> DExp+matchResultToDExp mr = mr failed_pattern_match+  where+    failed_pattern_match = DAppE (DVarE 'error)+                                 (DLitE $ StringL "Pattern-match failure")++simplCaseExp :: DsMonad q+             => [Name]+             -> [DClause]+             -> q DExp+simplCaseExp vars clauses =+  do let eis = [ EquationInfo pats (\_ -> rhs) |+                 DClause pats rhs <- clauses ]+     matchResultToDExp `liftM` simplCase vars eis++data EquationInfo = EquationInfo [DPat] MatchResult  -- like DClause, but with a hole+                            +-- analogous to GHC's match (in deSugar/Match.lhs)+simplCase :: DsMonad q+          => [Name]         -- the names of the scrutinees+          -> [EquationInfo] -- the matches (where the # of pats == length (1st arg))+          -> q MatchResult+simplCase [] clauses = return (foldr1 (.) match_results)+  where+    match_results = [ mr | EquationInfo _ mr <- clauses ]+simplCase vars@(v:_) clauses = do+  (aux_binds, tidy_clauses) <- mapAndUnzipM (tidyClause v) clauses+  let grouped = groupClauses tidy_clauses+  match_results <- match_groups grouped+  return (adjustMatchResult (foldr (.) id aux_binds) $+          foldr1 (.) match_results)+  where+    match_groups :: DsMonad q => [[(PatGroup, EquationInfo)]] -> q [MatchResult]+    match_groups [] = matchEmpty v+    match_groups gs = mapM match_group gs++    match_group :: DsMonad q => [(PatGroup, EquationInfo)] -> q MatchResult+    match_group [] = error "Internal error in th-desugar (match_group)"+    match_group eqns@((group,_) : _) =+      case group of+        PgCon _ -> matchConFamily vars (subGroup [(c,e) | (PgCon c, e) <- eqns])+        PgLit _ -> matchLiterals  vars (subGroup [(l,e) | (PgLit l, e) <- eqns])+        PgBang  -> matchBangs     vars (drop_group eqns)+        PgAny   -> matchVariables vars (drop_group eqns)++    drop_group = map snd++#if __GLASGOW_HASKELL__ <= 708+deriving instance Ord Lit   -- ew. necessary for `subGroup`+#endif++-- analogous to GHC's tidyEqnInfo+tidyClause :: DsMonad q => Name -> EquationInfo -> q (DExp -> DExp, EquationInfo)+tidyClause _ (EquationInfo [] _) =+  error "Internal error in th-desugar: no patterns in tidyClause."+tidyClause v (EquationInfo (pat : pats) body) = do+  (wrap, pat') <- tidy1 v pat+  return (wrap, EquationInfo (pat' : pats) body)++tidy1 :: DsMonad q+      => Name   -- the name of the variable that ...+      -> DPat   -- ... this pattern is matching against+      -> q (DExp -> DExp, DPat)   -- a wrapper and tidied pattern+tidy1 _ p@(DLitPa {}) = return (id, p)+tidy1 v (DVarPa var) = return (wrapBind var v, DWildPa)+tidy1 _ p@(DConPa {}) = return (id, p)+tidy1 v (DTildePa pat) = do+  sel_decs <- mkSelectorDecs pat v+  return (maybeDLetE sel_decs, DWildPa)+tidy1 v (DBangPa pat) =+  case pat of+    DLitPa _   -> tidy1 v pat   -- already strict+    DVarPa _   -> return (id, DBangPa pat)  -- no change+    DConPa _ _ -> tidy1 v pat   -- already strict+    DTildePa p -> tidy1 v (DBangPa p) -- discard ~ under !+    DBangPa p  -> tidy1 v (DBangPa p) -- discard ! under !+    DWildPa    -> return (id, DBangPa pat)  -- no change+tidy1 _ DWildPa = return (id, DWildPa)+    +wrapBind :: Name -> Name -> DExp -> DExp+wrapBind new old+  | new == old = id+  | otherwise  = DLetE [DValD (DVarPa new) (DVarE old)]++-- like GHC's mkSelectorBinds+mkSelectorDecs :: DsMonad q+               => DPat      -- pattern to deconstruct+               -> Name      -- variable being matched against+               -> q [DLetDec]+mkSelectorDecs (DVarPa v) name = return [DValD (DVarPa v) (DVarE name)]+mkSelectorDecs pat name+  | S.null binders+  = return []++  | S.size binders == 1+  = do val_var <- newUniqueName "var"+       err_var <- newUniqueName "err"+       bind    <- mk_bind val_var err_var (head $ S.elems binders)+       return [DValD (DVarPa val_var) (DVarE name),+               DValD (DVarPa err_var) (DVarE 'error `DAppE`+                                       (DLitE $ StringL "Irrefutable match failed")),+               bind]++  | otherwise+  = do tuple_expr <- simplCaseExp [name] [DClause [pat] local_tuple]+       tuple_var <- newUniqueName "tuple"+       projections <- mapM (mk_projection tuple_var) [0 .. tuple_size-1]+       return (DValD (DVarPa tuple_var) tuple_expr :+               zipWith DValD (map DVarPa binders_list) projections)++  where+    binders = extractBoundNamesDPat pat+    binders_list = S.toAscList binders+    tuple_size = length binders_list+    local_tuple = mkTupleDExp (map DVarE binders_list)++    mk_projection :: DsMonad q+                  => Name   -- of the tuple+                  -> Int    -- which element to get (0-indexed)+                  -> q DExp+    mk_projection tup_name i = do+      var_name <- newUniqueName "proj"+      return $ DCaseE (DVarE tup_name) [DMatch (DConPa (tupleDataName tuple_size) (mk_tuple_pats var_name i))+                                               (DVarE var_name)]++    mk_tuple_pats :: Name   -- of the projected element+                  -> Int    -- which element to get (0-indexed)+                  -> [DPat]+    mk_tuple_pats elt_name i = replicate i DWildPa ++ DVarPa elt_name : replicate (tuple_size - i - 1) DWildPa++    mk_bind scrut_var err_var bndr_var = do+      rhs_mr <- simplCase [scrut_var] [EquationInfo [pat] (\_ -> DVarE bndr_var)]+      return (DValD (DVarPa bndr_var) (rhs_mr (DVarE err_var)))++extractBoundNamesDPat :: DPat -> S.Set Name+extractBoundNamesDPat (DLitPa _)      = S.empty+extractBoundNamesDPat (DVarPa n)      = S.singleton n+extractBoundNamesDPat (DConPa _ pats) = S.unions (map extractBoundNamesDPat pats)+extractBoundNamesDPat (DTildePa p)    = extractBoundNamesDPat p+extractBoundNamesDPat (DBangPa p)     = extractBoundNamesDPat p+extractBoundNamesDPat DWildPa         = S.empty++data PatGroup+  = PgAny         -- immediate match (wilds, vars, lazies)+  | PgCon Name +  | PgLit Lit  +  | PgBang     ++-- like GHC's groupEquations+groupClauses :: [EquationInfo] -> [[(PatGroup, EquationInfo)]]+groupClauses clauses+  = runs same_gp [(patGroup (firstPat clause), clause) | clause <- clauses]+  where+    same_gp :: (PatGroup, EquationInfo) -> (PatGroup, EquationInfo) -> Bool+    (pg1,_) `same_gp` (pg2,_) = pg1 `sameGroup` pg2++patGroup :: DPat -> PatGroup+patGroup (DLitPa l)     = PgLit l+patGroup (DVarPa {})    = error "Internal error in th-desugar (patGroup DVarP)"+patGroup (DConPa con _) = PgCon con+patGroup (DTildePa {})  = error "Internal error in th-desugar (patGroup DTildeP)"+patGroup (DBangPa {})   = PgBang+patGroup DWildPa        = PgAny++sameGroup :: PatGroup -> PatGroup -> Bool+sameGroup PgAny     PgAny     = True+sameGroup PgBang    PgBang    = True+sameGroup (PgCon _) (PgCon _) = True+sameGroup (PgLit _) (PgLit _) = True+sameGroup _         _         = False++subGroup :: Ord a => [(a, EquationInfo)] -> [[EquationInfo]]+subGroup group+  = map reverse $ Map.elems $ foldl accumulate Map.empty group+  where+    accumulate pg_map (pg, eqn)+      = case Map.lookup pg pg_map of+          Just eqns -> Map.insert pg (eqn:eqns) pg_map+          Nothing   -> Map.insert pg [eqn]      pg_map++firstPat :: EquationInfo -> DPat+firstPat (EquationInfo (pat : _) _) = pat+firstPat _ = error "Clause encountered with no patterns -- should never happen"++data CaseAlt = CaseAlt { alt_con  :: Name         -- con name+                       , _alt_args :: [Name]       -- bound var names+                       , _alt_rhs  :: MatchResult  -- RHS+                       }++-- from GHC's MatchCon.lhs+matchConFamily :: DsMonad q => [Name] -> [[EquationInfo]] -> q MatchResult+matchConFamily (var:vars) groups+  = do alts <- mapM (matchOneCon vars) groups+       mkDataConCase var alts+matchConFamily [] _ = error "Internal error in th-desugar (matchConFamily)"++-- like matchOneConLike from MatchCon+matchOneCon :: DsMonad q => [Name] -> [EquationInfo] -> q CaseAlt+matchOneCon vars eqns@(eqn1 : _)+  = do arg_vars <- selectMatchVars (pat_args pat1)+       match_result <- match_group arg_vars++       return $ CaseAlt (pat_con pat1) arg_vars match_result+  where+    pat1 = firstPat eqn1+    +    pat_args (DConPa _ pats) = pats+    pat_args _               = error "Internal error in th-desugar (pat_args)"++    pat_con (DConPa con _) = con+    pat_con _              = error "Internal error in th-desugar (pat_con)"++    match_group :: DsMonad q => [Name] -> q MatchResult+    match_group arg_vars+      = simplCase (arg_vars ++ vars) (map shift eqns)++    shift (EquationInfo (DConPa _ args : pats) exp) = EquationInfo (args ++ pats) exp+    shift _ = error "Internal error in th-desugar (shift)"+matchOneCon _ _ = error "Internal error in th-desugar (matchOneCon)"++mkDataConCase :: DsMonad q => Name -> [CaseAlt] -> q MatchResult+mkDataConCase var case_alts = do+  all_ctors <- get_all_ctors (alt_con $ head case_alts)+  return $ \fail ->+    let matches = map (mk_alt fail) case_alts in+    DCaseE (DVarE var) (matches ++ mk_default all_ctors fail)+  where+    mk_alt fail (CaseAlt con args body_fn)+      = let body = body_fn fail in+        DMatch (DConPa con (map DVarPa args)) body++    mk_default all_ctors fail | exhaustive_case all_ctors = []+                              | otherwise       = [DMatch DWildPa fail]++    mentioned_ctors = S.fromList $ map alt_con case_alts+    exhaustive_case all_ctors = all_ctors `S.isSubsetOf` mentioned_ctors++    get_all_ctors :: DsMonad q => Name -> q (S.Set Name)+    get_all_ctors con_name = do+      ty_name <- dataConNameToDataName con_name+      Just (DTyConI tycon_dec _) <- dsReify ty_name+      return $ S.fromList $ map get_con_name $ get_cons tycon_dec++    get_cons (DDataD _ _ _ _ cons _)     = cons+    get_cons (DDataInstD _ _ _ _ cons _) = cons+    get_cons _                           = []++    get_con_name (DCon _ _ n _) = n++matchEmpty :: DsMonad q => Name -> q [MatchResult]+matchEmpty var = return [mk_seq]+  where+    mk_seq fail = DCaseE (DVarE var) [DMatch DWildPa fail]++matchLiterals :: DsMonad q => [Name] -> [[EquationInfo]] -> q MatchResult+matchLiterals (var:vars) sub_groups+  = do alts <- mapM match_group sub_groups+       return (mkCoPrimCaseMatchResult var alts)+  where+    match_group :: DsMonad q => [EquationInfo] -> q (Lit, MatchResult)+    match_group eqns+      = do let DLitPa lit = firstPat (head eqns)+           match_result <- simplCase vars (shiftEqns eqns)+           return (lit, match_result)+matchLiterals [] _ = error "Internal error in th-desugar (matchLiterals)"++mkCoPrimCaseMatchResult :: Name -- Scrutinee+                        -> [(Lit, MatchResult)]+                        -> MatchResult+mkCoPrimCaseMatchResult var match_alts = mk_case+  where+    mk_case fail = let alts = map (mk_alt fail) match_alts in+                   DCaseE (DVarE var) (alts ++ [DMatch DWildPa fail])+    mk_alt fail (lit, body_fn)+      = DMatch (DLitPa lit) (body_fn fail)++matchBangs :: DsMonad q => [Name] -> [EquationInfo] -> q MatchResult+matchBangs (var:vars) eqns+  = do match_result <- simplCase (var:vars) $+                       map (decomposeFirstPat getBangPat) eqns+       return (mkEvalMatchResult var match_result)+matchBangs [] _ = error "Internal error in th-desugar (matchBangs)"++decomposeFirstPat :: (DPat -> DPat) -> EquationInfo -> EquationInfo+decomposeFirstPat extractpat (EquationInfo (pat:pats) body)+  = EquationInfo (extractpat pat : pats) body+decomposeFirstPat _ _ = error "Internal error in th-desugar (decomposeFirstPat)"++getBangPat :: DPat -> DPat+getBangPat (DBangPa p) = p+getBangPat _           = error "Internal error in th-desugar (getBangPat)"++mkEvalMatchResult :: Name -> MatchResult -> MatchResult+mkEvalMatchResult var body_fn fail+  = foldl DAppE (DVarE 'seq) [DVarE var, body_fn fail]++matchVariables :: DsMonad q => [Name] -> [EquationInfo] -> q MatchResult+matchVariables (_:vars) eqns = simplCase vars (shiftEqns eqns)+matchVariables _ _ = error "Internal error in th-desugar (matchVariables)"++shiftEqns :: [EquationInfo] -> [EquationInfo]+shiftEqns = map shift+  where+    shift (EquationInfo pats rhs) = EquationInfo (tail pats) rhs+++adjustMatchResult :: (DExp -> DExp) -> MatchResult -> MatchResult+adjustMatchResult wrap mr fail = wrap $ mr fail++-- from DsUtils+selectMatchVars :: DsMonad q => [DPat] -> q [Name]+selectMatchVars = mapM selectMatchVar++-- from DsUtils+selectMatchVar :: DsMonad q => DPat -> q Name+selectMatchVar (DBangPa pat)  = selectMatchVar pat+selectMatchVar (DTildePa pat) = selectMatchVar pat+selectMatchVar (DVarPa var)   = newUniqueName ('_' : nameBase var)+selectMatchVar _              = newUniqueName "_pat"++-- like GHC's runs+runs :: (a -> a -> Bool) -> [a] -> [[a]]+runs _ [] = []+runs p (x:xs) = case span (p x) xs of+                  (first, rest) -> (x:first) : (runs p rest)
+ Language/Haskell/TH/Desugar/Reify.hs view
@@ -0,0 +1,367 @@+{- Language/Haskell/TH/Desugar/Reify.hs++(c) Richard Eisenberg 2014+eir@cis.upenn.edu++Allows for reification from a list of declarations, without looking a name+up in the environment.+-}++{-# LANGUAGE CPP, GeneralizedNewtypeDeriving #-}++module Language.Haskell.TH.Desugar.Reify (+  -- * Reification+  reifyWithLocals_maybe, reifyWithLocals, reifyWithWarning, reifyInDecs,++  -- * Datatype lookup+  getDataD, dataConNameToCon, dataConNameToDataName,++  -- * Monad support+  DsMonad(..), DsM, withLocalDeclarations+  ) where++import Control.Monad.Reader+import Data.List+import Data.Maybe+#if __GLASGOW_HASKELL__ < 709+import Control.Applicative+#endif+import qualified Data.Set as S++import Language.Haskell.TH.Syntax hiding ( lift )++import Language.Haskell.TH.Desugar.Util++-- | Like @reify@ from Template Haskell, but looks also in any not-yet-typechecked+-- declarations. To establish this list of not-yet-typechecked declarations,+-- use 'withLocalDeclarations'. Returns 'Nothing' if reification fails.+-- Note that no inferred type information is available from local declarations;+-- bottoms may be used if necessary.+reifyWithLocals_maybe :: DsMonad q => Name -> q (Maybe Info)+reifyWithLocals_maybe name = qRecover+  (return . reifyInDecs name =<< localDeclarations)+  (Just `fmap` qReify name)++-- | Like 'reifyWithLocals_maybe', but throws an exception upon failure,+-- warning the user about separating splices.+reifyWithLocals :: DsMonad q => Name -> q Info+reifyWithLocals name = do+  m_info <- reifyWithLocals_maybe name+  case m_info of+    Nothing -> reifyFail name+    Just i  -> return i++-- | Reify a declaration, warning the user about splices if the reify fails.+-- The warning says that reification can fail if you try to reify a type in+-- the same splice as it is declared.+reifyWithWarning :: Quasi q => Name -> q Info+reifyWithWarning name = qRecover (reifyFail name) (qReify name)++-- | Print out a warning about separating splices and fail.+reifyFail :: Monad m => Name -> m a+reifyFail name =+  fail $ "Looking up " ++ (show name) ++ " in the list of available " +++       "declarations failed.\nThis lookup fails if the declaration " +++       "referenced was made in the same Template\nHaskell splice as the use " +++       "of the declaration. If this is the case, put\nthe reference to " +++       "the declaration in a new splice."++---------------------------------+-- Utilities+---------------------------------++-- | Extract the @TyVarBndr@s and constructors given the @Name@ of a type+getDataD :: Quasi q+         => String       -- ^ Print this out on failure+         -> Name         -- ^ Name of the datatype (@data@ or @newtype@) of interest+         -> q ([TyVarBndr], [Con])+getDataD err name = do+  info <- reifyWithWarning name+  dec <- case info of+           TyConI dec -> return dec+           _ -> badDeclaration+  case dec of+    DataD _cxt _name tvbs cons _derivings -> return (tvbs, cons)+    NewtypeD _cxt _name tvbs con _derivings -> return (tvbs, [con])+    _ -> badDeclaration+  where badDeclaration =+          fail $ "The name (" ++ (show name) ++ ") refers to something " +++                 "other than a datatype. " ++ err++-- | From the name of a data constructor, retrive the datatype definition it+-- is a part of.+dataConNameToDataName :: Quasi q => Name -> q Name+dataConNameToDataName con_name = do+  info <- reifyWithWarning con_name+  case info of+    DataConI _name _type parent_name _fixity -> return parent_name+    _ -> fail $ "The name " ++ show con_name ++ " does not appear to be " +++                "a data constructor."++-- | From the name of a data constructor, retrieve its definition as a @Con@+dataConNameToCon :: Quasi q => Name -> q Con+dataConNameToCon con_name = do+  -- we need to get the field ordering from the constructor. We must reify+  -- the constructor to get the tycon, and then reify the tycon to get the `Con`s+  type_name <- dataConNameToDataName con_name+  (_, cons) <- getDataD "This seems to be an error in GHC." type_name+  let m_con = find ((con_name ==) . get_con_name) cons+  case m_con of+    Just con -> return con+    Nothing -> impossible "Datatype does not contain one of its own constructors."++  where+    get_con_name (NormalC name _)  = name+    get_con_name (RecC name _)     = name+    get_con_name (InfixC _ name _) = name+    get_con_name (ForallC _ _ con) = get_con_name con++--------------------------------------------------+-- DsMonad+--------------------------------------------------++-- | A 'DsMonad' stores some list of declarations that should be considered+-- in scope. 'DsM' is the prototypical inhabitant of 'DsMonad'.+class Quasi m => DsMonad m where+  -- | Produce a list of local declarations.+  localDeclarations :: m [Dec]++instance DsMonad Q where+  localDeclarations = return []+instance DsMonad IO where+  localDeclarations = return []++-- | A convenient implementation of the 'DsMonad' class. Use by calling+-- 'withLocalDeclarations'.+newtype DsM q a = DsM (ReaderT [Dec] q a)+  deriving (Functor, Applicative, Monad, MonadTrans)++instance Quasi q => Quasi (DsM q) where+  qNewName          = lift `comp1` qNewName+  qReport           = lift `comp2` qReport+  qLookupName       = lift `comp2` qLookupName+  qReify            = lift `comp1` qReify+  qReifyInstances   = lift `comp2` qReifyInstances+  qLocation         = lift qLocation+  qRunIO            = lift `comp1` qRunIO+  qAddDependentFile = lift `comp1` qAddDependentFile+#if __GLASGOW_HASKELL__ >= 707+  qReifyRoles       = lift `comp1` qReifyRoles+  qReifyAnnotations = lift `comp1` qReifyAnnotations+  qReifyModule      = lift `comp1` qReifyModule+  qAddTopDecls      = lift `comp1` qAddTopDecls+  qAddModFinalizer  = lift `comp1` qAddModFinalizer+  qGetQ             = lift qGetQ+  qPutQ             = lift `comp1` qPutQ+#endif+                      +  qRecover (DsM handler) (DsM body) = DsM $ do+    env <- ask+    lift $ qRecover (runReaderT handler env) (runReaderT body env)++instance Quasi q => DsMonad (DsM q) where+  localDeclarations = DsM ask++-- | Add a list of declarations to be considered when reifying local+-- declarations.+withLocalDeclarations :: DsMonad q => [Dec] -> DsM q a -> q a+withLocalDeclarations new_decs (DsM x) = do+  orig_decs <- localDeclarations+  runReaderT x (orig_decs ++ new_decs)++-- helper functions for composition+comp1 :: (b -> c) -> (a -> b) -> a -> c+comp1 = (.)++comp2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d+comp2 f g a b = f (g a b)++---------------------------+-- Reifying local declarations+---------------------------++-- | Look through a list of declarations and possibly return a relevant 'Info'+reifyInDecs :: Name -> [Dec] -> Maybe Info+reifyInDecs n decs = firstMatch (reifyInDec n decs) decs++reifyInDec :: Name -> [Dec] -> Dec -> Maybe Info+reifyInDec n decs (FunD n' _) | n `nameMatches` n' = Just $ mkVarI n decs+reifyInDec n decs (ValD pat _ _)+  | any (nameMatches n) (S.elems (extractBoundNamesPat pat)) = Just $ mkVarI n decs+reifyInDec n _    dec@(DataD    _ n' _ _ _) | n `nameMatches` n' = Just $ TyConI dec+reifyInDec n _    dec@(NewtypeD _ n' _ _ _) | n `nameMatches` n' = Just $ TyConI dec+reifyInDec n _    dec@(TySynD n' _ _)       | n `nameMatches` n' = Just $ TyConI dec+reifyInDec n decs dec@(ClassD _ n' _ _ _)   | n `nameMatches` n'+  = Just $ ClassI (stripClassDec dec) (findInstances n decs)+reifyInDec n decs (ForeignD (ImportF _ _ _ n' ty)) | n `nameMatches` n'+  = Just $ mkVarITy n decs ty+reifyInDec n decs (ForeignD (ExportF _ _ n' ty)) | n `nameMatches` n'+  = Just $ mkVarITy n decs ty+reifyInDec n decs dec@(FamilyD _ n' _ _) | n `nameMatches` n'+  = Just $ FamilyI (handleBug8884 dec) (findInstances n decs)+#if __GLASGOW_HASKELL__ >= 707+reifyInDec n _    dec@(ClosedTypeFamilyD n' _ _ _) | n `nameMatches` n'+  = Just $ FamilyI dec []+#endif++reifyInDec n decs (DataD _ ty_name tvbs cons _)+  | Just info <- maybeReifyCon n decs ty_name (map tvbToType tvbs) cons+  = Just info+reifyInDec n decs (NewtypeD _ ty_name tvbs con _)+  | Just info <- maybeReifyCon n decs ty_name (map tvbToType tvbs) [con]+  = Just info+reifyInDec n decs (ClassD _ _ _ _ sub_decs)+  | Just info <- firstMatch (reifyInDec n (sub_decs ++ decs)) sub_decs+  = Just info    -- must necessarily *not* be a method, because type signatures+                 -- don't reify+reifyInDec n decs (ClassD _ ty_name tvbs _ sub_decs)+  | Just ty <- findType n sub_decs+  = Just $ ClassOpI n (addClassCxt ty_name tvbs ty)+                    ty_name (findFixity n $ sub_decs ++ decs)+reifyInDec n decs (InstanceD _ _ sub_decs)+  | Just info <- firstMatch reify_in_instance sub_decs+  = Just info+  where+    reify_in_instance dec@(DataInstD {})    = reifyInDec n (sub_decs ++ decs) dec+    reify_in_instance dec@(NewtypeInstD {}) = reifyInDec n (sub_decs ++ decs) dec+    reify_in_instance _                     = Nothing+reifyInDec n decs (DataInstD _ ty_name tys cons _)+  | Just info <- maybeReifyCon n decs ty_name tys cons+  = Just info+reifyInDec n decs (NewtypeInstD _ ty_name tys con _)+  | Just info <- maybeReifyCon n decs ty_name tys [con]+  = Just info++reifyInDec _ _ _ = Nothing++maybeReifyCon :: Name -> [Dec] -> Name -> [Type] -> [Con] -> Maybe Info+maybeReifyCon n decs ty_name ty_args cons+  | Just con <- findCon n cons+  = Just $ DataConI n (maybeForallT tvbs [] $ con_to_type con)+                    ty_name fixity++  | Just ty <- findRecSelector n cons+      -- we don't try to ferret out naughty record selectors.+  = Just $ VarI n (maybeForallT tvbs [] $ mkArrows [result_ty] ty) Nothing fixity+  where+    result_ty = foldl AppT (ConT ty_name) ty_args++    con_to_type (NormalC _ stys) = mkArrows (map snd    stys)  result_ty+    con_to_type (RecC _ vstys)   = mkArrows (map thdOf3 vstys) result_ty+    con_to_type (InfixC t1 _ t2) = mkArrows (map snd [t1, t2]) result_ty+    con_to_type (ForallC bndrs cxt c) = ForallT bndrs cxt (con_to_type c)++    fixity = findFixity n decs+    tvbs = map PlainTV $ S.elems $ freeNamesOfTypes ty_args+maybeReifyCon _ _ _ _ _ = Nothing++mkVarI :: Name -> [Dec] -> Info+mkVarI n decs = mkVarITy n decs (fromMaybe no_type $ findType n decs)+  where+    no_type = error $ "No type information found in local declaration for "+                      ++ show n    ++mkVarITy :: Name -> [Dec] -> Type -> Info+mkVarITy n decs ty = VarI n ty Nothing (findFixity n decs)+    +findFixity :: Name -> [Dec] -> Fixity+findFixity n = fromMaybe defaultFixity . firstMatch match_fixity+  where+    match_fixity (InfixD fixity n') | n `nameMatches` n' = Just fixity+    match_fixity _                                   = Nothing++findType :: Name -> [Dec] -> Maybe Type+findType n = firstMatch match_type+  where+    match_type (SigD n' ty) | n `nameMatches` n' = Just ty+    match_type _                             = Nothing++findInstances :: Name -> [Dec] -> [Dec]+findInstances n = map stripInstanceDec . concatMap match_instance+  where+    match_instance d@(InstanceD _ ty _)        | ConT n' <- ty_head ty+                                               , n `nameMatches` n' = [d]+    match_instance d@(DataInstD _ n' _ _ _)    | n `nameMatches` n' = [d]+    match_instance d@(NewtypeInstD _ n' _ _ _) | n `nameMatches` n' = [d]+#if __GLASGOW_HASKELL__ >= 707+    match_instance d@(TySynInstD n' _)         | n `nameMatches` n' = [d]+#else+    match_instance d@(TySynInstD n' _ _)       | n `nameMatches` n' = [d]+#endif+    match_instance (InstanceD _ _ decs) = concatMap match_instance decs+    match_instance _                    = []++    ty_head (ForallT _ _ ty) = ty_head ty+    ty_head (AppT ty _)      = ty_head ty+    ty_head (SigT ty _)      = ty_head ty+    ty_head ty               = ty++stripClassDec :: Dec -> Dec+stripClassDec (ClassD cxt name tvbs fds sub_decs)+  = ClassD cxt name tvbs fds sub_decs'+  where+    sub_decs' = mapMaybe go sub_decs+    go (SigD n ty) = Just $ SigD n $ addClassCxt name tvbs ty+    go _           = Nothing+stripClassDec dec = dec++addClassCxt :: Name -> [TyVarBndr] -> Type -> Type+addClassCxt class_name tvbs ty = ForallT tvbs class_cxt ty+  where+#if __GLASGOW_HASKELL__ < 709+    class_cxt = [ClassP class_name (map tvbToType tvbs)]+#else+    class_cxt = [foldl AppT (ConT class_name) (map tvbToType tvbs)]+#endif++stripInstanceDec :: Dec -> Dec+stripInstanceDec (InstanceD cxt ty _) = InstanceD cxt ty []+stripInstanceDec dec                  = dec++mkArrows :: [Type] -> Type -> Type+mkArrows []     res_ty = res_ty+mkArrows (t:ts) res_ty = AppT (AppT ArrowT t) $ mkArrows ts res_ty++maybeForallT :: [TyVarBndr] -> Cxt -> Type -> Type+maybeForallT tvbs cxt ty+  | null tvbs && null cxt        = ty+  | ForallT tvbs2 cxt2 ty2 <- ty = ForallT (tvbs ++ tvbs2) (cxt ++ cxt2) ty2+  | otherwise                    = ForallT tvbs cxt ty++findCon :: Name -> [Con] -> Maybe Con+findCon n = find match_con+  where+    match_con (NormalC n' _)  = n `nameMatches` n'+    match_con (RecC n' _)     = n `nameMatches` n'+    match_con (InfixC _ n' _) = n `nameMatches` n'+    match_con (ForallC _ _ c) = match_con c++findRecSelector :: Name -> [Con] -> Maybe Type+findRecSelector n = firstMatch match_con+  where+    match_con (RecC _ vstys)  = firstMatch match_rec_sel vstys+    match_con (ForallC _ _ c) = match_con c+    match_con _               = Nothing++    match_rec_sel (n', _, ty) | n `nameMatches` n' = Just ty+    match_rec_sel _                     = Nothing+    ++handleBug8884 :: Dec -> Dec+#if __GLASGOW_HASKELL__ >= 707+handleBug8884 = id+#else+handleBug8884 (FamilyD flav name tvbs m_kind)+  = FamilyD flav name tvbs (Just stupid_kind)+  where+    kind_from_maybe = fromMaybe StarT+    tvb_kind (PlainTV _)    = Nothing+    tvb_kind (KindedTV _ k) = Just k+    +    result_kind = kind_from_maybe m_kind+    args_kinds  = map (kind_from_maybe . tvb_kind) tvbs++    stupid_kind = mkArrows args_kinds result_kind+handleBug8884 dec = dec+#endif    +
Language/Haskell/TH/Desugar/Sweeten.hs view
@@ -22,8 +22,14 @@ -- ---------------------------------------------------------------------------- -module Language.Haskell.TH.Desugar.Sweeten where+module Language.Haskell.TH.Desugar.Sweeten (+  expToTH, matchToTH, patToTH, decsToTH, decToTH,+  letDecToTH, typeToTH, kindToTH, +  conToTH, foreignToTH, pragmaToTH, ruleBndrToTH,+  clauseToTH, tvbToTH, cxtToTH, predToTH+  ) where+ import Prelude hiding (exp) import Language.Haskell.TH hiding (cxt) @@ -41,6 +47,11 @@ expToTH (DCaseE exp matches) = CaseE (expToTH exp) (map matchToTH matches) expToTH (DLetE decs exp)     = LetE (map letDecToTH decs) (expToTH exp) expToTH (DSigE exp ty)       = SigE (expToTH exp) (typeToTH ty)+#if __GLASGOW_HASKELL__ < 709+expToTH (DStaticE _)         = error "Static expressions supported only in GHC 7.10+"+#else+expToTH (DStaticE exp)       = StaticE (expToTH exp)+#endif  matchToTH :: DMatch -> Match matchToTH (DMatch pat exp) = Match (patToTH pat) (NormalB (expToTH exp)) []@@ -90,6 +101,16 @@                        (map tySynEqnToTH eqns)] decToTH (DRoleAnnotD n roles) = [RoleAnnotD n roles] #endif+#if __GLASGOW_HASKELL__ < 709+decToTH (DStandaloneDerivD {}) =+  error "Standalone deriving supported only in GHC 7.10+"+decToTH (DDefaultSigD {})      =+  error "Default method signatures supported only in GHC 7.10+"+#else+decToTH (DStandaloneDerivD cxt ty) =+  [StandaloneDerivD (cxtToTH cxt) (typeToTH ty)]+decToTH (DDefaultSigD n ty)        = [DefaultSigD n (typeToTH ty)]+#endif decToTH _ = error "Newtype declaration without exactly 1 constructor."  letDecToTH :: DLetDec -> Dec@@ -123,6 +144,11 @@ #else pragmaToTH (DAnnP target exp) = Just $ AnnP target (expToTH exp) #endif+#if __GLASGOW_HASKELL__ < 709+pragmaToTH (DLineP {}) = Nothing+#else+pragmaToTH (DLineP n str) = Just $ LineP n str+#endif  ruleBndrToTH :: DRuleBndr -> RuleBndr ruleBndrToTH (DRuleVar n) = RuleVar n@@ -167,7 +193,7 @@     go _   (DVarPr _)       = error "Template Haskell in GHC <= 7.8 does not support variable constraints."     go acc (DConPr n) -      | nameBase n == "(~)"+      | nameBase n == "~"       , [t1, t2] <- acc       = EqualP t1 t2       | otherwise
Language/Haskell/TH/Desugar/Util.hs view
@@ -8,30 +8,36 @@  {-# LANGUAGE CPP, TupleSections #-} -module Language.Haskell.TH.Desugar.Util where+module Language.Haskell.TH.Desugar.Util (+  newUniqueName,+  impossible, +  nameOccursIn, allNamesIn, mkTypeName, mkDataName,+  stripVarP_maybe, extractBoundNamesStmt,+  concatMapM, mapMaybeM, expectJustM,+  liftSndM, liftThdOf3M, stripPlainTV_maybe,+  liftSnd, liftThdOf3, splitAtList, extractBoundNamesDec,+  extractBoundNamesPat,+  tvbName, tvbToType, nameMatches, freeNamesOfTypes, thdOf3, firstMatch,+  tupleDegree_maybe, tupleNameDegree_maybe, unboxedTupleDegree_maybe,+  unboxedTupleNameDegree_maybe, splitTuple_maybe+  ) where -import Prelude hiding (mapM)+import Prelude hiding (mapM, foldl, concatMap, any) -import Language.Haskell.TH-import Language.Haskell.TH.Syntax ( Quasi(..), mkNameG_tc, mkNameG_d )+import Language.Haskell.TH hiding ( cxt )+import Language.Haskell.TH.Syntax +import Control.Arrow  ( second ) import qualified Data.Set as S import Data.Foldable-import Data.Generics+import Data.Generics hiding ( Fixity ) import Data.Traversable+import Data.Maybe import Data.Monoid --- | Reify a declaration, warning the user about splices if the reify fails.--- The warning says that reification can fail if you try to reify a type in--- the same splice as it is declared.-reifyWithWarning :: Quasi q => Name -> q Info-reifyWithWarning name = qRecover-  (fail $ "Looking up " ++ (show name) ++ " in the list of available " ++-        "declarations failed.\nThis lookup fails if the declaration " ++-        "referenced was made in the same Template\nHaskell splice as the use " ++-        "of the declaration. If this is the case, put\nthe reference to " ++-        "the declaration in a new splice.")-  (qReify name)+----------------------------------------+-- TH manipulations+----------------------------------------  -- | Like newName, but even more unique (unique across different splices), -- and with unique @nameBase@s.@@ -40,64 +46,6 @@   n <- qNewName str   qNewName $ show n --- | Report that a certain TH construct is impossible-impossible :: Quasi q => String -> q a-impossible err = fail (err ++ "\n    This should not happen in Haskell.\n    Please email eir@cis.upenn.edu with your code if you see this.")---- | Extract the @TyVarBndr@s and constructors given the @Name@ of a type-getDataD :: Quasi q-         => String       -- ^ Print this out on failure-         -> Name         -- ^ Name of the datatype (@data@ or @newtype@) of interest-         -> q ([TyVarBndr], [Con])-getDataD err name = do-  info <- reifyWithWarning name-  dec <- case info of-           TyConI dec -> return dec-           _ -> badDeclaration-  case dec of-    DataD _cxt _name tvbs cons _derivings -> return (tvbs, cons)-    NewtypeD _cxt _name tvbs con _derivings -> return (tvbs, [con])-    _ -> badDeclaration-  where badDeclaration =-          fail $ "The name (" ++ (show name) ++ ") refers to something " ++-                 "other than a datatype. " ++ err---- | From the name of a data constructor, retrive the datatype definition it--- is a part of.-dataConNameToDataName :: Quasi q => Name -> q Name-dataConNameToDataName con_name = do-  info <- reifyWithWarning con_name-  case info of-    DataConI _name _type parent_name _fixity -> return parent_name-    _ -> fail $ "The name " ++ show con_name ++ " does not appear to be " ++-                "a data constructor."---- | From the name of a data constructor, retrieve its definition as a @Con@-dataConNameToCon :: Quasi q => Name -> q Con-dataConNameToCon con_name = do-  -- we need to get the field ordering from the constructor. We must reify-  -- the constructor to get the tycon, and then reify the tycon to get the `Con`s-  type_name <- dataConNameToDataName con_name-  (_, cons) <- getDataD "This seems to be an error in GHC." type_name-  let m_con = find ((con_name ==) . get_con_name) cons-  case m_con of-    Just con -> return con-    Nothing -> impossible "Datatype does not contain one of its own constructors."--  where-    get_con_name (NormalC name _)  = name-    get_con_name (RecC name _)     = name-    get_con_name (InfixC _ name _) = name-    get_con_name (ForallC _ _ con) = get_con_name con---- | Check if a name occurs anywhere within a TH tree.-nameOccursIn :: Data a => Name -> a -> Bool-nameOccursIn n = everything (||) $ mkQ False (== n)---- | Extract all Names mentioned in a TH tree.-allNamesIn :: Data a => a -> [Name]-allNamesIn = everything (++) $ mkQ [] (:[])-                -- | Like TH's @lookupTypeName@, but if this name is not bound, then we assume -- it is declared in the current module. mkTypeName :: Quasi q => String -> q Name@@ -130,6 +78,90 @@ stripPlainTV_maybe (PlainTV n) = Just n stripPlainTV_maybe _           = Nothing +-- | Report that a certain TH construct is impossible+impossible :: Monad q => String -> q a+impossible err = fail (err ++ "\n    This should not happen in Haskell.\n    Please email eir@cis.upenn.edu with your code if you see this.")++-- | Extract a 'Name' from a 'TyVarBndr'+tvbName :: TyVarBndr -> Name+tvbName (PlainTV n)    = n+tvbName (KindedTV n _) = n++-- | Convert a 'TyVarBndr' into a 'Type'+tvbToType :: TyVarBndr -> Type+tvbToType = VarT . tvbName++-- | Do two names name the same thing?+nameMatches :: Name -> Name -> Bool+nameMatches n1@(Name occ1 flav1) n2@(Name occ2 flav2)+  | NameS <- flav1 = occ1 == occ2+  | NameS <- flav2 = occ1 == occ2+  | NameQ mod1 <- flav1+  , NameQ mod2 <- flav2+  = mod1 == mod2 && occ1 == occ2+  | NameQ mod1 <- flav1+  , NameG _ _ mod2 <- flav2+  = mod1 == mod2 && occ1 == occ2+  | NameG _ _ mod1 <- flav1+  , NameQ mod2 <- flav2+  = mod1 == mod2 && occ1 == occ2+  | otherwise+  = n1 == n2++-- | Extract the degree of a tuple+tupleDegree_maybe :: String -> Maybe Int+tupleDegree_maybe s = do+  '(' : s1 <- return s+  (commas, ")") <- return $ span (== ',') s1+  let degree+        | "" <- commas = 0+        | otherwise    = length commas + 1+  return degree++-- | Extract the degree of a tuple name+tupleNameDegree_maybe :: Name -> Maybe Int+tupleNameDegree_maybe = tupleDegree_maybe . nameBase++-- | Extract the degree of an unboxed tuple+unboxedTupleDegree_maybe :: String -> Maybe Int+unboxedTupleDegree_maybe s = do+  '(' : '#' : s1 <- return s+  (commas, "#)") <- return $ span (== ',') s1+  let degree+        | "" <- commas = 0+        | otherwise    = length commas + 1+  return degree++-- | Extract the degree of a tuple name+unboxedTupleNameDegree_maybe :: Name -> Maybe Int+unboxedTupleNameDegree_maybe = unboxedTupleDegree_maybe . nameBase++-- | If the argument is a tuple type, return the components+splitTuple_maybe :: Type -> Maybe [Type]+splitTuple_maybe t = go [] t+  where go args (t1 `AppT` t2) = go (t2:args) t1+        go args (t1 `SigT` _k) = go args t1+        go args (ConT con_name)+          | Just degree <- tupleNameDegree_maybe con_name+          , length args == degree+          = Just args+        go args (TupleT degree)+          | length args == degree+          = Just args+        go _ _ = Nothing++----------------------------------------+-- Free names, etc.+----------------------------------------++-- | Check if a name occurs anywhere within a TH tree.+nameOccursIn :: Data a => Name -> a -> Bool+nameOccursIn n = everything (||) $ mkQ False (== n)++-- | Extract all Names mentioned in a TH tree.+allNamesIn :: Data a => a -> [Name]+allNamesIn = everything (++) $ mkQ [] (:[])+                -- | Extract the names bound in a @Stmt@ extractBoundNamesStmt :: Stmt -> S.Set Name extractBoundNamesStmt (BindS pat _) = extractBoundNamesPat pat@@ -165,6 +197,27 @@ extractBoundNamesPat (SigP pat _)        = extractBoundNamesPat pat extractBoundNamesPat (ViewP _ pat)       = extractBoundNamesPat pat +freeNamesOfTypes :: [Type] -> S.Set Name+freeNamesOfTypes = mconcat . map go+  where+    go (ForallT tvbs cxt ty) = (go ty <> mconcat (map go_pred cxt))+                               S.\\ S.fromList (map tvbName tvbs)+    go (AppT t1 t2)          = go t1 <> go t2+    go (SigT ty _)           = go ty+    go (VarT n)              = S.singleton n+    go _                     = S.empty++#if __GLASGOW_HASKELL__ >= 709+    go_pred = go+#else+    go_pred (ClassP _ tys) = freeNamesOfTypes tys+    go_pred (EqualP t1 t2) = go t1 <> go t2+#endif++----------------------------------------+-- General utility+----------------------------------------+ -- like GHC's splitAtList :: [a] -> [b] -> ([b], [b]) splitAtList [] x = ([], x)@@ -173,40 +226,15 @@   (x : as, bs) splitAtList (_ : _) [] = ([], []) --- | If a type is a fully-applied tuple type, break it down into a list--- of its constituents. Otherwise, return Nothing.-splitTuple_maybe :: Type -> Maybe [Type]-splitTuple_maybe = go []-  where-    go acc (AppT left right) = go (right:acc) left-    go acc (SigT ty _)       = go acc ty-    go acc (TupleT n)-      | n == length acc = Just acc-    go acc (ConT name)-      | Just n <- tupleNameDegree_maybe name-      , n == length acc = Just acc-    go _ _ = Nothing---- | Extract the degree of a tuple, if the argument is a tuple-tupleDegree_maybe :: String -> Maybe Int-tupleDegree_maybe s = do-  '(' : s1 <- return s-  (commas, ")") <- return $ span (== ',') s1-  let degree-        | "" <- commas = 0-        | otherwise    = length commas + 1-  return degree---- | Extract the degree of a tuple name, if the argument is a tuple name-tupleNameDegree_maybe :: Name -> Maybe Int-tupleNameDegree_maybe = tupleDegree_maybe . nameBase- liftSnd :: (a -> b) -> (c, a) -> (c, b)-liftSnd f (c, a) = (c, f a)+liftSnd = second  liftSndM :: Monad m => (a -> m b) -> (c, a) -> m (c, b) liftSndM f (c, a) = f a >>= return . (c, ) +thdOf3 :: (a,b,c) -> c+thdOf3 (_,_,c) = c+ liftThdOf3 :: (a -> b) -> (c, d, a) -> (c, d, b) liftThdOf3 f (c, d, a) = (c, d, f a) @@ -221,3 +249,21 @@ concatMapM fn list = do   bss <- mapM fn list   return $ fold bss++-- like GHC's+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]+mapMaybeM _ [] = return []+mapMaybeM f (x:xs) = do+  y <- f x+  ys <- mapMaybeM f xs+  return $ case y of+    Nothing -> ys+    Just z  -> z : ys++expectJustM :: Monad m => String -> Maybe a -> m a+expectJustM _   (Just x) = return x+expectJustM err Nothing  = fail err++firstMatch :: (a -> Maybe b) -> [a] -> Maybe b+firstMatch f xs = listToMaybe $ mapMaybe f xs+    
Test/Dec.hs view
@@ -6,7 +6,8 @@  {-# LANGUAGE TemplateHaskell, GADTs, PolyKinds, TypeFamilies,              MultiParamTypeClasses, FunctionalDependencies,-             FlexibleInstances, DataKinds, CPP, RankNTypes #-}+             FlexibleInstances, DataKinds, CPP, RankNTypes,+             StandaloneDeriving, DefaultSignatures #-} #if __GLASGOW_HASKELL__ >= 707 {-# LANGUAGE RoleAnnotations #-} #endif@@ -28,6 +29,9 @@ $(S.dectest8) $(S.dectest9) $(S.dectest10)+#if __GLASGOW_HASKELL__ >= 709+$(S.dectest11)+#endif  $(fmap unqualify S.instance_test) 
Test/DsDec.hs view
@@ -6,7 +6,8 @@  {-# LANGUAGE TemplateHaskell, GADTs, PolyKinds, TypeFamilies,              MultiParamTypeClasses, FunctionalDependencies,-             FlexibleInstances, DataKinds, CPP, RankNTypes #-}+             FlexibleInstances, DataKinds, CPP, RankNTypes,+             StandaloneDeriving, DefaultSignatures #-} #if __GLASGOW_HASKELL__ >= 707 {-# LANGUAGE RoleAnnotations #-} #endif@@ -21,7 +22,6 @@  import Language.Haskell.TH  ( reportError ) import Language.Haskell.TH.Desugar-import Language.Haskell.TH.Desugar.Sweeten  import Control.Monad @@ -46,6 +46,11 @@ $(return $ decsToTH [S.ds_dectest10]) #else $(dsDecSplice S.dectest10)+#endif++#if __GLASGOW_HASKELL__ >= 709+$(dsDecSplice S.dectest11)+$(dsDecSplice S.standalone_deriving_test) #endif  $(do decs <- S.rec_sel_test
Test/Run.hs view
@@ -6,35 +6,52 @@  {-# LANGUAGE TemplateHaskell, UnboxedTuples, ParallelListComp, CPP,              RankNTypes, ImpredicativeTypes, TypeFamilies,-             DataKinds, ConstraintKinds, PolyKinds #-}+             DataKinds, ConstraintKinds, PolyKinds, MultiParamTypeClasses,+             FlexibleInstances, ExistentialQuantification #-} {-# OPTIONS -fno-warn-incomplete-patterns -fno-warn-overlapping-patterns             -fno-warn-unused-matches -fno-warn-type-defaults-            -fno-warn-missing-signatures -fno-warn-unused-do-bind-            -fno-warn-warnings-deprecations #-}+            -fno-warn-missing-signatures -fno-warn-unused-do-bind #-}  module Test.Run where  import Prelude hiding ( exp )  import Test.HUnit-import Test.Hspec-import Test.Hspec.HUnit+import Test.Hspec hiding ( runIO )+-- import Test.Hspec.HUnit  import Test.Splices import qualified Test.DsDec import qualified Test.Dec import Test.Dec ( RecordSel ) import Language.Haskell.TH.Desugar-import Language.Haskell.TH.Desugar.Expand-import Language.Haskell.TH.Desugar.Sweeten-import Language.Haskell.TH as TH+import Language.Haskell.TH+import qualified Language.Haskell.TH.Syntax as Syn ( lift )  import Control.Monad+import Control.Applicative  #if __GLASGOW_HASKELL__ >= 707 import Data.Proxy #endif +-- |+-- Convert a HUnit test suite to a spec.  This can be used to run existing+-- HUnit tests with Hspec.+fromHUnitTest :: Test -> Spec+-- copied from https://github.com/hspec/hspec/blob/master/hspec-contrib/src/Test/Hspec/Contrib/HUnit.hs+fromHUnitTest t = case t of+  TestList xs -> mapM_ go xs+  x -> go x+  where+    go :: Test -> Spec+    go t_ = case t_ of+      TestLabel s (TestCase e) -> it s e+      TestLabel s (TestList xs) -> describe s (mapM_ go xs)+      TestLabel s x -> describe s (go x)+      TestList xs -> describe "<unlabeled>" (mapM_ go xs)+      TestCase e -> it "<unlabeled>" e+ tests :: Test tests = test [ "sections" ~: $test1_sections  @=? $(dsSplice test1_sections)              , "lampats"  ~: $test2_lampats   @=? $(dsSplice test2_lampats)@@ -89,6 +106,12 @@ test_e3b = $(test_expand3 >>= dsExp >>= expand >>= return . expToTH) test_e4a = $test_expand4 test_e4b = $(test_expand4 >>= dsExp >>= expand >>= return . expToTH)+#if __GLASGOW_HASKELL__ >= 707+test_e5a = $test_expand5+test_e5b = $(test_expand5 >>= dsExp >>= expand >>= return . expToTH)+test_e6a = $test_expand6+test_e6b = $(test_expand6 >>= dsExp >>= expand >>= return . expToTH)+#endif  hasSameType :: a -> a -> Bool hasSameType _ _ = True@@ -97,7 +120,12 @@ test_expand = and [ hasSameType test35a test35b                   , hasSameType test36a test36b                   , hasSameType test_e3a test_e3b-                  , hasSameType test_e4a test_e4b ]+                  , hasSameType test_e4a test_e4b+#if __GLASGOW_HASKELL__ >= 707+                  , hasSameType test_e5a test_e5b+                  , hasSameType test_e6a test_e6b+#endif+                  ]  test_dec :: [Bool] test_dec = $(do bools <- mapM testDecSplice dec_test_nums@@ -120,9 +148,13 @@                                    (Just [DTySynInstD _name2 (DTySynEqn lhs _rhs)]))                       <- dsInfo info                     case (resK, lhs) of+#if __GLASGOW_HASKELL__ < 709                       (DStarK, [DVarT _]) -> [| True |]+#else+                      (DStarK, [DSigT (DVarT _) (DVarK _)]) -> [| True |]+#endif                       _                                     -> do-                        TH.runIO $ do+                        runIO $ do                           putStrLn "Failed bug8884 test:"                           putStrLn $ show dinfo                         [| False |] )@@ -139,6 +171,42 @@ test_rec_sels = and $(do bools <- mapM testRecSelTypes [1..rec_sel_test_num_sels]                          return $ ListE bools) +test_standalone_deriving :: Bool+#if __GLASGOW_HASKELL__ >= 709+test_standalone_deriving = (MkBlarggie 5 'x') == (MkBlarggie 5 'x')+#else+test_standalone_deriving = True+#endif++local_reifications :: [String]+local_reifications = $(do decs <- reifyDecs+                          m_infos <- withLocalDeclarations decs $+                                     mapM reifyWithLocals_maybe reifyDecsNames+                          let m_infos' = assumeStarT m_infos+                          ListE <$> mapM (Syn.lift . show) (unqualify m_infos'))++$reifyDecs++$(return [])  -- somehow, this is necessary to get the staging correct for the+              -- reifications below. Weird.++normal_reifications :: [String]+normal_reifications = $(do infos <- mapM reify reifyDecsNames+                           ListE <$> mapM (Syn.lift . show . Just)+                                          (dropTrailing0s $ unqualify infos))++zipWith3M :: Monad m => (a -> b -> c -> m d) -> [a] -> [b] -> [c] -> m [d]+zipWith3M f (a:as) (b:bs) (c:cs) = liftM2 (:) (f a b c) (zipWith3M f as bs cs)+zipWith3M _ _ _ _ = return []++simplCase :: [Bool]+simplCase = $( do exps <- sequence simplCaseTests+                  dexps <- mapM dsExp exps+                  sexps <- mapM scExp dexps+                  bools <- zipWithM (\e1 e2 -> [| $(return e1) == $(return e2) |])+                    exps (map sweeten sexps)+                  return $ ListE bools )+ main :: IO () main = hspec $ do   describe "th-desugar library" $ do@@ -163,6 +231,13 @@      it "flattens DValDs" $ flatten_dvald -    it "extract record selectors" $ test_rec_sels+    it "extracts record selectors" $ test_rec_sels++    it "works with standalone deriving" $ test_standalone_deriving++    zipWith3M (\a b n -> it ("reifies local definition " ++ show n) $ a == b)+      local_reifications normal_reifications [1..]++    zipWithM (\b n -> it ("works on simplCase test " ++ show n) b) simplCase [1..]      fromHUnitTest tests
Test/Splices.hs view
@@ -8,19 +8,20 @@              MultiWayIf, ParallelListComp, CPP, BangPatterns,              ScopedTypeVariables, RankNTypes, TypeFamilies, ImpredicativeTypes,              DataKinds, PolyKinds, GADTs, MultiParamTypeClasses,-             FunctionalDependencies, FlexibleInstances #-}+             FunctionalDependencies, FlexibleInstances, StandaloneDeriving,+             DefaultSignatures #-} {-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-type-defaults                 -fno-warn-name-shadowing #-}  module Test.Splices where  import Data.List+import Data.Char import GHC.Exts import GHC.TypeLits  import Language.Haskell.TH import Language.Haskell.TH.Desugar-import Language.Haskell.TH.Desugar.Sweeten import Data.Generics  #if __GLASGOW_HASKELL__ < 707@@ -50,6 +51,25 @@ unqualify :: Data a => a -> a unqualify = everywhere (mkT (mkName . nameBase)) +assumeStarT :: Data a => a -> a+#if __GLASGOW_HASKELL__ < 709+assumeStarT = id+#else+assumeStarT = everywhere (mkT go)+  where+    go :: TyVarBndr -> TyVarBndr+    go (PlainTV n) = KindedTV n StarT+    go (KindedTV n k) = KindedTV n (assumeStarT k)+#endif++dropTrailing0s :: Data a => a -> a+dropTrailing0s = everywhere (mkT (mkName . frob . nameBase))+  where+    frob str+      | head str == 'r' = str+      | head str == 'R' = str+      | otherwise       = dropWhileEnd isDigit str+ eqTH :: (Data a, Show a) => a -> a -> Bool eqTH a b = show (unqualify a) == show (unqualify b) @@ -121,7 +141,7 @@  test27_kisig = [| let f :: Proxy (a :: Bool) -> ()                       f _ = () in-                  (f (Proxy :: Proxy False), f (Proxy :: Proxy True)) |]+                  (f (Proxy :: Proxy 'False), f (Proxy :: Proxy 'True)) |] test28_tupt = [| let f :: (a,b) -> a                      f (a,_) = a in                  map f [(1,'a'),(2,'b')] |]@@ -164,6 +184,19 @@                       f [True, False] = () in                   f |] +#if __GLASGOW_HASKELL__ >= 707+type family ClosedTF a where+  ClosedTF Int = Bool+  ClosedTF x   = Char++test_expand5 = [| let f :: ClosedTF Int -> ()+                      f True = () in+                  f |]+test_expand6 = [| let f :: ClosedTF Double -> ()+                      f 'x' = () in+                  f |]+#endif+ #if __GLASGOW_HASKELL__ >= 709 test37_pred = [| let f :: (Read a, (Show a, Num a)) => a -> a                      f x = read (show x) + x in@@ -180,8 +213,10 @@  #if __GLASGOW_HASKELL__ < 707 dec_test_nums = [1..9] :: [Int]-#else+#elif __GLASGOW_HASKELL__ < 709 dec_test_nums = [1..10] :: [Int]+#else+dec_test_nums = [1..11] :: [Int] #endif  dectest1 = [d| data Dec1 = Foo | Bar Int |]@@ -217,6 +252,16 @@                   Dec10 Bool = [] |] #endif +data Blarggie a = MkBlarggie Int a+#if __GLASGOW_HASKELL__ >= 709+dectest11 = [d| class Dec11 a where+                  meth13 :: a -> a -> Bool+                  default meth13 :: Eq a => a -> a -> Bool+                  meth13 = (==)+              |]+standalone_deriving_test = [d| deriving instance Eq a => Eq (Blarggie a) |]+#endif+ instance_test = [d| instance (Show a, Show b) => Show (a -> b) where                        show _ = "function" |] @@ -263,3 +308,58 @@     -- used for expand+++reifyDecs :: Q [Dec]+reifyDecs = [d|+  r1 :: a -> a+  r1 x = x++  class R2 a b where+    r3 :: a -> b -> c -> a+    type R4 b a :: *+    data R5 a :: *++  data R6 a = R7 { r8 :: a -> a, r9 :: Bool }++  instance R2 (R6 a) a where+    r3 = undefined+    type R4 a (R6 a) = a+    data R5 (R6 a) = forall b. Show b => R10 { r11 :: a, naughty :: b }++  type family R12 a b :: *++  data family R13 a :: *++  data instance R13 Int = R14 { r15 :: Bool }++  r16, r17 :: Int+  (r16, r17) = (5, 6)++  newtype R18 = R19 Bool++  type R20 = Bool+#if __GLASGOW_HASKELL__ >= 707+  type family R21 (a :: k) (b :: k) :: k where R21 a b = b+#endif+  |]++reifyDecsNames :: [Name]+reifyDecsNames = map mkName+  [ "r1", "R2", "r3", "R4", "R5", "R6", "R7", "r8", "r9", "R10", "r11"+  , "R12", "R13", "R14", "r15", "r16", "r17", "R18", "R19", "R20"+#if __GLASGOW_HASKELL__ >= 707+  , "R21"+#endif+  ]++simplCaseTests :: [Q Exp]+simplCaseTests =+  [ [| map (\a -> case a :: [Int] of+        (_:_:_:_) -> (5 :: Int)+        _         -> 6) [[], [1], [1,2,3]]+     |]+  , [| let foo [] = True+           foo _  = False in (foo [], foo "hi") |]+  ]+                             
th-desugar.cabal view
@@ -1,5 +1,5 @@ name:           th-desugar-version:        1.4.2.1+version:        1.5 cabal-version:  >= 1.10 synopsis:       Functions to desugar Template Haskell homepage:       http://www.cis.upenn.edu/~eir/packages/th-desugar@@ -26,7 +26,7 @@ source-repository this   type:     git   location: https://github.com/goldfirere/th-desugar.git-  tag:      v1.4.2.1+  tag:      v1.5  library   build-depends:      @@ -34,14 +34,17 @@       template-haskell,       containers >= 0.5,       mtl >= 2.1,-      syb >= 0.4+      syb >= 0.4,+      th-lift >= 0.6.1   default-extensions: TemplateHaskell   exposed-modules:    Language.Haskell.TH.Desugar,                       Language.Haskell.TH.Desugar.Sweeten,-                      Language.Haskell.TH.Desugar.Expand,-                      Language.Haskell.TH.Desugar.Lift+                      Language.Haskell.TH.Desugar.Lift,+                      Language.Haskell.TH.Desugar.Expand   other-modules:      Language.Haskell.TH.Desugar.Core,-                      Language.Haskell.TH.Desugar.Util+                      Language.Haskell.TH.Desugar.Match,+                      Language.Haskell.TH.Desugar.Util,+                      Language.Haskell.TH.Desugar.Reify   default-language:   Haskell2010   ghc-options:        -Wall @@ -61,4 +64,5 @@       mtl >= 2.1,       syb >= 0.4,       HUnit >= 1.2,-      hspec >= 1.11+      hspec >= 1.3,+      th-lift >= 0.6.1