packages feed

groundhog-th 0.7.0 → 0.7.0.1

raw patch · 3 files changed

+71/−34 lines, 3 filesdep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: template-haskell

API changes (from Hackage documentation)

Files

Database/Groundhog/TH/CodeGen.hs view
@@ -29,11 +29,13 @@ import Database.Groundhog.TH.Settings
 import Language.Haskell.TH
 import Language.Haskell.TH.Syntax (Lift(..))
+import Control.Applicative
 import Control.Arrow (second)
 import Control.Monad (liftM, liftM2, forM, forM_, foldM, filterM, replicateM)
 import Data.Either (lefts, rights)
 import Data.List (findIndex, nub, partition)
 import Data.Maybe (catMaybes, mapMaybe)
+import qualified Text.Read as R
 
 mkEmbeddedPersistFieldInstance :: THEmbeddedDef -> Q [Dec]
 mkEmbeddedPersistFieldInstance def = do
@@ -119,12 +121,12 @@         return $ doE $ stmts ++ [noBindS expr]
       goPrim xs vars = do
         xs' <- newName "xs"
-        (prim, rest) <- spanM (isPrim . snd) vars
+        (prims, rest) <- spanM (isPrim . snd) vars
         body' <- case rest of
           [] -> return [| return ($result, $(varE xs')) |]
           _  -> goField xs' rest
-        let m = match (foldr (\(fname, _) p -> infixP (varP fname) '(:) p) (varP xs') prim) (normalB body') []
-        return $ if null prim
+        let m = match (foldr (\(fname, _) p -> infixP (varP fname) '(:) p) (varP xs') prims) (normalB body') []
+        return $ if null prims
           then caseE (varE xs) [m]
           else caseE (varE xs) [m, failure]
   body <- goPrim values allVars
@@ -151,14 +153,14 @@       return (isFailureUsed, letE stmts expr)
     goPrim xs vars result failure proxy = do
       xs' <- newName "xs"
-      (prim, rest) <- spanM (isPrim . snd) vars
+      (prims, rest) <- spanM (isPrim . snd) vars
       (isFailureUsed, body') <- case rest of
         [] -> return (False, [| ($result, $(varE xs')) |])
         _  -> goField xs' rest result failure proxy
-      let m = match (foldr (\(fname, _) p -> infixP (varP fname) '(:) p) (varP xs') prim) (normalB body') []
-      return $ if not (null prim)
-         then (True, caseE (varE xs) [m, failure])
-         else (isFailureUsed, caseE (varE xs) [m])
+      let m = match (foldr (\(fname, _) p -> infixP (varP fname) '(:) p) (varP xs') prims) (normalB body') []
+      return $ if null prims
+         then (isFailureUsed, caseE (varE xs) [m])
+         else (True, caseE (varE xs) [m, failure])
     mkArg proxy (fname, t) = isPrim t >>= \isP -> (if isP then [| fromPrimitivePersistValue $(varE proxy) $(varE fname) |] else (varE fname))
     in do
       xs <- newName "xs"
@@ -326,11 +328,13 @@ mkKeyEqShowInstances :: THEntityDef -> Q [Dec]
 mkKeyEqShowInstances def = do
   let entity = foldl AppT (ConT (thDataName def)) $ map extractType $ thTypeParams def
-  let keysInfo = maybe [] (\k -> [(thAutoKeyConstrName k, 1)]) (thAutoKey def)
-               ++ map (\k -> (thUniqueKeyConstrName k, length $ thUniqueKeyFields k)) (thUniqueKeys def)
+  let keysInfo = maybe [] (\k -> [(thAutoKeyConstrName k, 1, [t| BackendSpecific |])]) (thAutoKey def)
+               ++ map (\k -> (thUniqueKeyConstrName k, length $ thUniqueKeyFields k, [t| Unique $(conT $ mkName $ thUniqueKeyPhantomName k) |])) (thUniqueKeys def)
+  let context = paramsContext (thTypeParams def) (thConstructors def >>= thConstrFields)
+  typ <- [t| Key $(return entity) $(newName "a" >>= varT) |]
 
   showsPrec' <- let
-    mkClause (cName, fieldsNum) = do
+    mkClause (cName, fieldsNum, _) = do
       p <- newName "p"
       fields <- replicateM fieldsNum (newName "x")
       let pat = conP (mkName cName) $ map varP fields
@@ -341,7 +345,7 @@     in funD 'showsPrec $ map mkClause keysInfo
     
   eq' <- let
-    mkClause (cName, fieldsNum) = do
+    mkClause (cName, fieldsNum, _) = do
       let fields = replicateM fieldsNum (newName "x")
       (fields1, fields2) <- liftM2 (,) fields fields
       let mkPat = conP (mkName cName) . map varP
@@ -351,29 +355,39 @@     noMatch = if length clauses > 1 then [clause [wildP, wildP] (normalB [| False |]) []] else []
     in funD '(==) $ clauses ++ noMatch
 
-  let context = paramsContext (thTypeParams def) (thConstructors def >>= thConstrFields)
-  typ <- [t| Key $(return entity) $(newName "a" >>= varT) |]
+  read' <- let
+    mkRead (cName, fieldsNum, u) = do
+      let key = foldl (\a b -> [| $a <*> $b |]) [| $(conE $ mkName cName) <$> R.step R.readPrec |]
+            $ replicate (fieldsNum - 1) [| R.step R.readPrec |]
+          func = lamE [conP 'R.Ident [litP $ StringL cName]] key
+          body = [| R.parens $ R.prec 10 $ R.lexP >>= $func |]
+      keyType <- [t| Key $(return entity) $u |]
+      readPrec' <- funD 'R.readPrec [clause [] (normalB body) []]
+      readListPrec' <- funD 'R.readListPrec [clause [] (normalB [| R.readListPrecDefault |]) []]
+      return $ InstanceD context (AppT (ConT ''Read) keyType) [readPrec', readListPrec']
+    in mapM mkRead keysInfo
+
   return $ if null keysInfo
     then []
-    else [InstanceD context (AppT (ConT ''Eq) typ) [eq'], InstanceD context (AppT (ConT ''Show) typ) [showsPrec']]
+    else [InstanceD context (AppT (ConT ''Eq) typ) [eq'], InstanceD context (AppT (ConT ''Show) typ) [showsPrec']] ++ read'
 
 mkEmbeddedInstance :: THEmbeddedDef -> Q [Dec]
 mkEmbeddedInstance def = do
   let types = map extractType $ thEmbeddedTypeParams def
-  let embedded = foldl AppT (ConT (thEmbeddedName def)) types
-  let context = paramsContext (thEmbeddedTypeParams def) (thEmbeddedFields def)
+      embedded = foldl AppT (ConT (thEmbeddedName def)) types
+      context = paramsContext (thEmbeddedTypeParams def) (thEmbeddedFields def)
   mkEmbeddedInstance' embedded (thEmbeddedFields def) context
   
 mkEmbeddedInstance' :: Type -> [THFieldDef] -> Cxt -> Q [Dec]
 mkEmbeddedInstance' dataType fDefs context = do
   selector' <- do
     fParam <- newName "f"
-    let mkField field = ForallC [] ([EqualP (VarT fParam) (thFieldType field)]) $ NormalC (mkName $ thExprName field) []
+    let mkField field = ForallC [] ([equalP' (VarT fParam) (thFieldType field)]) $ NormalC (mkName $ thExprName field) []
     return $ DataInstD [] ''Selector [dataType, VarT fParam] (map mkField fDefs) []
 
   selectorNum' <- do
     let mkClause fNum field = clause [conP (mkName $ thExprName field) []] (normalB $ lift fNum) []
-    let clauses = zipWith mkClause [0 :: Int ..] fDefs
+        clauses = zipWith mkClause [0 :: Int ..] fDefs
     funD 'selectorNum clauses
 
   let decs = [selector', selectorNum']
@@ -386,7 +400,7 @@     v <- newName "v"
     let name = mkName $ thPhantomConstrName c
     phantom <- [t| ConstructorMarker $(return entity) |]
-    let constr = ForallC (thTypeParams def) [EqualP (VarT v) phantom] $ NormalC name []
+    let constr = ForallC (thTypeParams def) [equalP' (VarT v) phantom] $ NormalC name []
     return $ DataD [] name [PlainTV v] [constr] []
   
 mkEntityPhantomConstructorInstances :: THEntityDef -> Q [Dec]
@@ -405,7 +419,7 @@         v <- newName "v"
         let name = mkName $ thUniqueKeyPhantomName u
         phantom <- [t| UniqueMarker $(return entity) |]
-        let constr = ForallC (thTypeParams def) [EqualP (VarT v) phantom] $ NormalC name []
+        let constr = ForallC (thTypeParams def) [equalP' (VarT v) phantom] $ NormalC name []
         return [DataD [] name [PlainTV v] [constr] []]
       else return []
     
@@ -419,14 +433,14 @@       Nothing -> return []
       Just k -> do
         keyDescr <- [t| BackendSpecific |]
-        return [ForallC [] [EqualP (VarT uParam) keyDescr] $ NormalC (mkName $ thAutoKeyConstrName k) [(NotStrict, ConT ''PersistValue)]]
+        return [ForallC [] [equalP' (VarT uParam) keyDescr] $ NormalC (mkName $ thAutoKeyConstrName k) [(NotStrict, ConT ''PersistValue)]]
     uniques <- forM (thUniqueKeys def) $ \unique -> do
       uniqType <- [t| Unique $(conT $ mkName $ thUniqueKeyPhantomName unique) |]
       let cDef = head $ thConstructors def
           uniqFieldNames = lefts $ thUniqueFields $ findOne "unique" thUniqueName (thUniqueKeyName unique) $ thConstrUniques cDef
           uniqFields = concat $ flip map uniqFieldNames $ \name -> (filter ((== name) . thFieldName) $ thConstrFields cDef)
           uniqFields' = map (\f -> (NotStrict, thFieldType f)) uniqFields
-      return $ ForallC [] [EqualP (VarT uParam) uniqType] $ NormalC (mkName $ thUniqueKeyConstrName unique) uniqFields'
+      return $ ForallC [] [equalP' (VarT uParam) uniqType] $ NormalC (mkName $ thUniqueKeyConstrName unique) uniqFields'
     return $ DataInstD [] ''Key [entity, VarT uParam] (autoKey ++ uniques) []
 
   autoKey' <- do
@@ -452,7 +466,7 @@   fields' <- do
     cParam <- newName "c"
     fParam <- newName "f"
-    let mkField name field = ForallC [] [EqualP (VarT cParam) (ConT name), EqualP (VarT fParam) (thFieldType field)] $ NormalC (mkName $ thExprName field) []
+    let mkField name field = ForallC [] [equalP' (VarT cParam) (ConT name), equalP' (VarT fParam) (thFieldType field)] $ NormalC (mkName $ thExprName field) []
     let f cdef = map (mkField $ mkName $ thPhantomConstrName cdef) $ thConstrFields cdef
     let constrs = concatMap f $ thConstructors def
     return $ DataInstD [] ''Field [entity, VarT cParam, VarT fParam] constrs []
@@ -652,7 +666,7 @@ 
 mkPrimitivePersistFieldInstance :: THPrimitiveDef -> Q [Dec]
 mkPrimitivePersistFieldInstance def = do
-  let prim = ConT (thPrimitiveName def)
+  let primitive = ConT (thPrimitiveName def)
   persistName' <- do
     let body = normalB $ stringE $ nameBase $ thPrimitiveName def
     funD 'persistName $ [ clause [wildP] body [] ]
@@ -664,13 +678,13 @@           else [| DbTypePrimitive DbInt32  False Nothing Nothing |]
     funD 'dbType $ [ clause [wildP, wildP] (normalB typ) [] ]
   let decs = [persistName', toPersistValues', fromPersistValues', dbType']
-  return [ InstanceD [] (AppT (ConT ''PersistField) prim) decs
-         , InstanceD [] (AppT (ConT ''NeverNull) prim) []
+  return [ InstanceD [] (AppT (ConT ''PersistField) primitive) decs
+         , InstanceD [] (AppT (ConT ''NeverNull) primitive) []
          ]
 
 mkPrimitivePrimitivePersistFieldInstance :: THPrimitiveDef -> Q [Dec]
 mkPrimitivePrimitivePersistFieldInstance def = do
-  let prim = ConT (thPrimitiveName def)
+  let primitive = ConT (thPrimitiveName def)
   toPrim' <- do
     proxy <- newName "p"
     x <- newName "x"
@@ -689,9 +703,9 @@     funD 'fromPrimitivePersistValue [clause [varP proxy, varP x] (normalB body) []]
   let context = []
   let decs = [toPrim', fromPrim']
-  sequence $ [return $ InstanceD context (AppT (ConT ''PrimitivePersistField) prim) decs
-           , mkDefaultPurePersistFieldInstance context prim
-           , mkDefaultSinglePersistFieldInstance context prim]
+  sequence $ [return $ InstanceD context (AppT (ConT ''PrimitivePersistField) primitive) decs
+           , mkDefaultPurePersistFieldInstance context primitive
+           , mkDefaultSinglePersistFieldInstance context primitive]
 
 mkMigrateFunction :: String -> [THEntityDef] -> Q [Dec]
 mkMigrateFunction name defs = do
@@ -718,7 +732,7 @@ 
 paramsContext :: [TyVarBndr] -> [THFieldDef] -> Cxt
 paramsContext types fields = classPred ''PersistField params ++ classPred ''SinglePersistField maybys ++ classPred ''NeverNull maybys where
-  classPred clazz = map (\t -> ClassP clazz [t])
+  classPred clazz = map (\t -> classP' clazz [t])
   -- every type must be an instance of PersistField
   params = map extractType types
   -- all datatype fields also must be instances of PersistField
@@ -734,7 +748,7 @@   return $ case invalid of
     [] -> Just $ classPred ''PurePersistField params ++ classPred ''PrimitivePersistField maybys ++ classPred ''NeverNull maybys where
           params = map extractType types
-          classPred clazz = map (\t -> ClassP clazz [t])
+          classPred clazz = map (\t -> classP' clazz [t])
           -- all datatype fields also must be instances of PersistField
           -- if Maybe is applied to a type param, the param must be also an instance of NeverNull
           -- so that (Maybe param) is an instance of PersistField
@@ -810,3 +824,19 @@ #else
   TySynInstD name ts t
 #endif
+
+classP' :: Name -> [Type] -> Pred
+classP' name ts =
+#if MIN_VERSION_template_haskell(2, 10, 0)
+  foldl AppT (ConT name) ts
+#else
+  ClassP name ts
+#endif
+
+equalP' :: Type -> Type -> Pred
+equalP' t1 t2 =
+#if MIN_VERSION_template_haskell(2, 10, 0)
+  foldl AppT EqualityT [t1, t2]
+#else
+  EqualP t1 t2
+#endif
changelog view
@@ -1,3 +1,10 @@+0.7.0.1+* Compatibility with template-haskell-2.10++0.7.0+* Instances of ToJSON for settings+* Refactoring and export of some utility functions+ 0.6.0 * Entities without keys. It can be useful for many-to-many tables which hold keys but are not referenced * Entity and fields descriptions are parameterized so that they can be promoted
groundhog-th.cabal view
@@ -1,5 +1,5 @@ name:            groundhog-th-version:         0.7.0+version:         0.7.0.1 license:         BSD3 license-file:    LICENSE author:          Boris Lykah <lykahb@gmail.com>