{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ >= 800
{-# LANGUAGE TemplateHaskellQuotes #-}
#else
{-# LANGUAGE TemplateHaskell #-}
#endif
#include "incoherent-compat.h"
#include "overlapping-compat.h"
module Data.Aeson.TH
(
Options(..)
, SumEncoding(..)
, defaultOptions
, defaultTaggedObject
, deriveJSON
, deriveJSON1
, deriveJSON2
, deriveToJSON
, deriveToJSON1
, deriveToJSON2
, deriveFromJSON
, deriveFromJSON1
, deriveFromJSON2
, mkToJSON
, mkLiftToJSON
, mkLiftToJSON2
, mkToEncoding
, mkLiftToEncoding
, mkLiftToEncoding2
, mkParseJSON
, mkLiftParseJSON
, mkLiftParseJSON2
) where
import Prelude.Compat
import Control.Applicative ((<|>))
import Data.Aeson (Object, (.:), FromJSON(..), FromJSON1(..), FromJSON2(..), ToJSON(..), ToJSON1(..), ToJSON2(..))
import Data.Aeson.Types (Options(..), Parser, SumEncoding(..), Value(..), defaultOptions, defaultTaggedObject)
import Data.Aeson.Types.Internal ((<?>), JSONPathElement(Key))
import Data.Aeson.Types.FromJSON (parseOptionalFieldWith)
import Data.Aeson.Types.ToJSON (fromPairs, pair)
import Control.Monad (liftM2, unless, when)
import Data.Foldable (foldr')
#if MIN_VERSION_template_haskell(2,8,0) && !MIN_VERSION_template_haskell(2,10,0)
import Data.List (nub)
#endif
import Data.List (foldl', genericLength, intercalate, partition, union)
import Data.List.NonEmpty ((<|), NonEmpty((:|)))
import Data.Map (Map)
import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
import qualified Data.Monoid as Monoid
import Data.Set (Set)
#if MIN_VERSION_template_haskell(2,8,0)
import Language.Haskell.TH hiding (Arity)
#else
import Language.Haskell.TH
#endif
import Language.Haskell.TH.Datatype
#if MIN_VERSION_template_haskell(2,7,0) && !(MIN_VERSION_template_haskell(2,8,0))
import Language.Haskell.TH.Lib (starK)
#endif
#if MIN_VERSION_template_haskell(2,8,0) && !(MIN_VERSION_template_haskell(2,10,0))
import Language.Haskell.TH.Syntax (mkNameG_tc)
#endif
import Text.Printf (printf)
import qualified Data.Aeson.Encoding.Internal as E
import qualified Data.Foldable as F (all)
import qualified Data.HashMap.Strict as H (lookup, toList)
import qualified Data.List.NonEmpty as NE (length, reverse)
import qualified Data.Map as M (fromList, keys, lookup , singleton, size)
import qualified Data.Semigroup as Semigroup (Option(..))
import qualified Data.Set as Set (empty, insert, member)
import qualified Data.Text as T (Text, pack, unpack)
import qualified Data.Vector as V (unsafeIndex, null, length, create, empty)
import qualified Data.Vector.Mutable as VM (unsafeNew, unsafeWrite)
deriveJSON :: Options
-> Name
-> Q [Dec]
deriveJSON :: Options -> Name -> Q [Dec]
deriveJSON = (Options -> Name -> Q [Dec])
-> (Options -> Name -> Q [Dec]) -> Options -> Name -> Q [Dec]
deriveJSONBoth Options -> Name -> Q [Dec]
deriveToJSON Options -> Name -> Q [Dec]
deriveFromJSON
deriveJSON1 :: Options
-> Name
-> Q [Dec]
deriveJSON1 :: Options -> Name -> Q [Dec]
deriveJSON1 = (Options -> Name -> Q [Dec])
-> (Options -> Name -> Q [Dec]) -> Options -> Name -> Q [Dec]
deriveJSONBoth Options -> Name -> Q [Dec]
deriveToJSON1 Options -> Name -> Q [Dec]
deriveFromJSON1
deriveJSON2 :: Options
-> Name
-> Q [Dec]
deriveJSON2 :: Options -> Name -> Q [Dec]
deriveJSON2 = (Options -> Name -> Q [Dec])
-> (Options -> Name -> Q [Dec]) -> Options -> Name -> Q [Dec]
deriveJSONBoth Options -> Name -> Q [Dec]
deriveToJSON2 Options -> Name -> Q [Dec]
deriveFromJSON2
deriveToJSON :: Options
-> Name
-> Q [Dec]
deriveToJSON :: Options -> Name -> Q [Dec]
deriveToJSON = JSONClass -> Options -> Name -> Q [Dec]
deriveToJSONCommon JSONClass
toJSONClass
deriveToJSON1 :: Options
-> Name
-> Q [Dec]
deriveToJSON1 :: Options -> Name -> Q [Dec]
deriveToJSON1 = JSONClass -> Options -> Name -> Q [Dec]
deriveToJSONCommon JSONClass
toJSON1Class
deriveToJSON2 :: Options
-> Name
-> Q [Dec]
deriveToJSON2 :: Options -> Name -> Q [Dec]
deriveToJSON2 = JSONClass -> Options -> Name -> Q [Dec]
deriveToJSONCommon JSONClass
toJSON2Class
deriveToJSONCommon :: JSONClass
-> Options
-> Name
-> Q [Dec]
deriveToJSONCommon :: JSONClass -> Options -> Name -> Q [Dec]
deriveToJSONCommon = [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> JSONClass -> Options -> Name -> Q [Dec]
deriveJSONClass [ (JSONFun
ToJSON, \jc :: JSONClass
jc _ -> ToJSONFun
-> JSONClass -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consToValue ToJSONFun
Value JSONClass
jc)
, (JSONFun
ToEncoding, \jc :: JSONClass
jc _ -> ToJSONFun
-> JSONClass -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consToValue ToJSONFun
Encoding JSONClass
jc)
]
mkToJSON :: Options
-> Name
-> Q Exp
mkToJSON :: Options -> Name -> Q Exp
mkToJSON = JSONClass -> Options -> Name -> Q Exp
mkToJSONCommon JSONClass
toJSONClass
mkLiftToJSON :: Options
-> Name
-> Q Exp
mkLiftToJSON :: Options -> Name -> Q Exp
mkLiftToJSON = JSONClass -> Options -> Name -> Q Exp
mkToJSONCommon JSONClass
toJSON1Class
mkLiftToJSON2 :: Options
-> Name
-> Q Exp
mkLiftToJSON2 :: Options -> Name -> Q Exp
mkLiftToJSON2 = JSONClass -> Options -> Name -> Q Exp
mkToJSONCommon JSONClass
toJSON2Class
mkToJSONCommon :: JSONClass
-> Options
-> Name
-> Q Exp
mkToJSONCommon :: JSONClass -> Options -> Name -> Q Exp
mkToJSONCommon = (JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> JSONClass -> Options -> Name -> Q Exp
mkFunCommon (\jc :: JSONClass
jc _ -> ToJSONFun
-> JSONClass -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consToValue ToJSONFun
Value JSONClass
jc)
mkToEncoding :: Options
-> Name
-> Q Exp
mkToEncoding :: Options -> Name -> Q Exp
mkToEncoding = JSONClass -> Options -> Name -> Q Exp
mkToEncodingCommon JSONClass
toJSONClass
mkLiftToEncoding :: Options
-> Name
-> Q Exp
mkLiftToEncoding :: Options -> Name -> Q Exp
mkLiftToEncoding = JSONClass -> Options -> Name -> Q Exp
mkToEncodingCommon JSONClass
toJSON1Class
mkLiftToEncoding2 :: Options
-> Name
-> Q Exp
mkLiftToEncoding2 :: Options -> Name -> Q Exp
mkLiftToEncoding2 = JSONClass -> Options -> Name -> Q Exp
mkToEncodingCommon JSONClass
toJSON2Class
mkToEncodingCommon :: JSONClass
-> Options
-> Name
-> Q Exp
mkToEncodingCommon :: JSONClass -> Options -> Name -> Q Exp
mkToEncodingCommon = (JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> JSONClass -> Options -> Name -> Q Exp
mkFunCommon (\jc :: JSONClass
jc _ -> ToJSONFun
-> JSONClass -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consToValue ToJSONFun
Encoding JSONClass
jc)
consToValue :: ToJSONFun
-> JSONClass
-> Options
-> [Type]
-> [ConstructorInfo]
-> Q Exp
consToValue :: ToJSONFun
-> JSONClass -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consToValue _ _ _ _ [] = [Char] -> Q Exp
forall a. HasCallStack => [Char] -> a
error ([Char] -> Q Exp) -> [Char] -> Q Exp
forall a b. (a -> b) -> a -> b
$ "Data.Aeson.TH.consToValue: "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ "Not a single constructor given!"
consToValue target :: ToJSONFun
target jc :: JSONClass
jc opts :: Options
opts instTys :: [Type]
instTys cons :: [ConstructorInfo]
cons = do
Name
value <- [Char] -> Q Name
newName "value"
[Name]
tjs <- [Char] -> Int -> Q [Name]
newNameList "_tj" (Int -> Q [Name]) -> Int -> Q [Name]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Int
arityInt JSONClass
jc
[Name]
tjls <- [Char] -> Int -> Q [Name]
newNameList "_tjl" (Int -> Q [Name]) -> Int -> Q [Name]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Int
arityInt JSONClass
jc
let zippedTJs :: [(Name, Name)]
zippedTJs = [Name] -> [Name] -> [(Name, Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
tjs [Name]
tjls
interleavedTJs :: [Name]
interleavedTJs = [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
interleave [Name]
tjs [Name]
tjls
lastTyVars :: [Name]
lastTyVars = (Type -> Name) -> [Type] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Name
varTToName ([Type] -> [Name]) -> [Type] -> [Name]
forall a b. (a -> b) -> a -> b
$ Int -> [Type] -> [Type]
forall a. Int -> [a] -> [a]
drop ([Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
instTys Int -> Int -> Int
forall a. Num a => a -> a -> a
- JSONClass -> Int
arityInt JSONClass
jc) [Type]
instTys
tvMap :: Map Name (Name, Name)
tvMap = [(Name, (Name, Name))] -> Map Name (Name, Name)
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Name, (Name, Name))] -> Map Name (Name, Name))
-> [(Name, (Name, Name))] -> Map Name (Name, Name)
forall a b. (a -> b) -> a -> b
$ [Name] -> [(Name, Name)] -> [(Name, (Name, Name))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
lastTyVars [(Name, Name)]
zippedTJs
[PatQ] -> Q Exp -> Q Exp
lamE ((Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP ([Name] -> [PatQ]) -> [Name] -> [PatQ]
forall a b. (a -> b) -> a -> b
$ [Name]
interleavedTJs [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
++ [Name
value]) (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$
Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
value) (Map Name (Name, Name) -> [MatchQ]
matches Map Name (Name, Name)
tvMap)
where
matches :: Map Name (Name, Name) -> [MatchQ]
matches tvMap :: Map Name (Name, Name)
tvMap = case [ConstructorInfo]
cons of
[con :: ConstructorInfo
con] | Bool -> Bool
not (Options -> Bool
tagSingleConstructors Options
opts) -> [ToJSONFun
-> JSONClass
-> Map Name (Name, Name)
-> Options
-> Bool
-> ConstructorInfo
-> MatchQ
argsToValue ToJSONFun
target JSONClass
jc Map Name (Name, Name)
tvMap Options
opts Bool
False ConstructorInfo
con]
_ | Options -> Bool
allNullaryToStringTag Options
opts Bool -> Bool -> Bool
&& (ConstructorInfo -> Bool) -> [ConstructorInfo] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ConstructorInfo -> Bool
isNullary [ConstructorInfo]
cons ->
[ PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP Name
conName []) (Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ ToJSONFun -> Options -> Name -> Q Exp
conStr ToJSONFun
target Options
opts Name
conName) []
| ConstructorInfo
con <- [ConstructorInfo]
cons
, let conName :: Name
conName = ConstructorInfo -> Name
constructorName ConstructorInfo
con
]
| Bool
otherwise -> [ToJSONFun
-> JSONClass
-> Map Name (Name, Name)
-> Options
-> Bool
-> ConstructorInfo
-> MatchQ
argsToValue ToJSONFun
target JSONClass
jc Map Name (Name, Name)
tvMap Options
opts Bool
True ConstructorInfo
con | ConstructorInfo
con <- [ConstructorInfo]
cons]
conStr :: ToJSONFun -> Options -> Name -> Q Exp
conStr :: ToJSONFun -> Options -> Name -> Q Exp
conStr Value opts :: Options
opts = Q Exp -> Q Exp -> Q Exp
appE [|String|] (Q Exp -> Q Exp) -> (Name -> Q Exp) -> Name -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> Name -> Q Exp
conTxt Options
opts
conStr Encoding opts :: Options
opts = Q Exp -> Q Exp -> Q Exp
appE [|E.text|] (Q Exp -> Q Exp) -> (Name -> Q Exp) -> Name -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> Name -> Q Exp
conTxt Options
opts
conTxt :: Options -> Name -> Q Exp
conTxt :: Options -> Name -> Q Exp
conTxt opts :: Options
opts = Q Exp -> Q Exp -> Q Exp
appE [|T.pack|] (Q Exp -> Q Exp) -> (Name -> Q Exp) -> Name -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Q Exp
stringE ([Char] -> Q Exp) -> (Name -> [Char]) -> Name -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> Name -> [Char]
conString Options
opts
conString :: Options -> Name -> String
conString :: Options -> Name -> [Char]
conString opts :: Options
opts = Options -> [Char] -> [Char]
constructorTagModifier Options
opts ([Char] -> [Char]) -> (Name -> [Char]) -> Name -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> [Char]
nameBase
isNullary :: ConstructorInfo -> Bool
isNullary :: ConstructorInfo -> Bool
isNullary ConstructorInfo { constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
tys } = [Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
tys
isNullary _ = Bool
False
opaqueSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> ExpQ -> ExpQ
opaqueSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> Q Exp -> Q Exp
opaqueSumToValue target :: ToJSONFun
target opts :: Options
opts multiCons :: Bool
multiCons nullary :: Bool
nullary conName :: Name
conName value :: Q Exp
value =
ToJSONFun
-> Options
-> Bool
-> Bool
-> Name
-> Q Exp
-> ([Char] -> Q Exp)
-> Q Exp
sumToValue ToJSONFun
target Options
opts Bool
multiCons Bool
nullary Name
conName
Q Exp
value
[Char] -> Q Exp
pairs
where
pairs :: [Char] -> Q Exp
pairs contentsFieldName :: [Char]
contentsFieldName = [Char] -> Q Exp -> Q Exp
pairE [Char]
contentsFieldName Q Exp
value
recordSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> ExpQ -> ExpQ
recordSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> Q Exp -> Q Exp
recordSumToValue target :: ToJSONFun
target opts :: Options
opts multiCons :: Bool
multiCons nullary :: Bool
nullary conName :: Name
conName pairs :: Q Exp
pairs =
ToJSONFun
-> Options
-> Bool
-> Bool
-> Name
-> Q Exp
-> ([Char] -> Q Exp)
-> Q Exp
sumToValue ToJSONFun
target Options
opts Bool
multiCons Bool
nullary Name
conName
(Q Exp -> Q Exp
fromPairsE Q Exp
pairs)
(Q Exp -> [Char] -> Q Exp
forall a b. a -> b -> a
const Q Exp
pairs)
sumToValue
:: ToJSONFun
-> Options
-> Bool
-> Bool
-> Name
-> ExpQ
-> (String -> ExpQ)
-> ExpQ
sumToValue :: ToJSONFun
-> Options
-> Bool
-> Bool
-> Name
-> Q Exp
-> ([Char] -> Q Exp)
-> Q Exp
sumToValue target :: ToJSONFun
target opts :: Options
opts multiCons :: Bool
multiCons nullary :: Bool
nullary conName :: Name
conName value :: Q Exp
value pairs :: [Char] -> Q Exp
pairs
| Bool
multiCons =
case Options -> SumEncoding
sumEncoding Options
opts of
TwoElemArray ->
ToJSONFun -> [Q Exp] -> Q Exp
array ToJSONFun
target [ToJSONFun -> Options -> Name -> Q Exp
conStr ToJSONFun
target Options
opts Name
conName, Q Exp
value]
TaggedObject{[Char]
tagFieldName :: SumEncoding -> [Char]
tagFieldName :: [Char]
tagFieldName, [Char]
contentsFieldName :: SumEncoding -> [Char]
contentsFieldName :: [Char]
contentsFieldName} ->
let tag :: Q Exp
tag = [Char] -> Q Exp -> Q Exp
pairE [Char]
tagFieldName (ToJSONFun -> Options -> Name -> Q Exp
conStr ToJSONFun
target Options
opts Name
conName)
content :: Q Exp
content = [Char] -> Q Exp
pairs [Char]
contentsFieldName
in Q Exp -> Q Exp
fromPairsE (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$
if Bool
nullary then Q Exp
tag else Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
tag [|(Monoid.<>)|] Q Exp
content
ObjectWithSingleField ->
[([Char], Q Exp)] -> Q Exp
objectE [(Options -> Name -> [Char]
conString Options
opts Name
conName, Q Exp
value)]
UntaggedValue | Bool
nullary -> ToJSONFun -> Options -> Name -> Q Exp
conStr ToJSONFun
target Options
opts Name
conName
UntaggedValue -> Q Exp
value
| Bool
otherwise = Q Exp
value
argsToValue :: ToJSONFun -> JSONClass -> TyVarMap -> Options -> Bool -> ConstructorInfo -> Q Match
argsToValue :: ToJSONFun
-> JSONClass
-> Map Name (Name, Name)
-> Options
-> Bool
-> ConstructorInfo
-> MatchQ
argsToValue target :: ToJSONFun
target jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap opts :: Options
opts multiCons :: Bool
multiCons
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys } = do
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
let len :: Int
len = [Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
argTys'
[Name]
args <- [Char] -> Int -> Q [Name]
newNameList "arg" Int
len
let js :: Q Exp
js = case [ ToJSONFun
-> JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchToJSON ToJSONFun
target JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
argTy
Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arg
| (arg :: Name
arg, argTy :: Type
argTy) <- [Name] -> [Type] -> [(Name, Type)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
args [Type]
argTys'
] of
[e :: Q Exp
e] -> Q Exp
e
es :: [Q Exp]
es -> ToJSONFun -> [Q Exp] -> Q Exp
array ToJSONFun
target [Q Exp]
es
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP Name
conName ([PatQ] -> PatQ) -> [PatQ] -> PatQ
forall a b. (a -> b) -> a -> b
$ (Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP [Name]
args)
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ ToJSONFun -> Options -> Bool -> Bool -> Name -> Q Exp -> Q Exp
opaqueSumToValue ToJSONFun
target Options
opts Bool
multiCons ([Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
argTys') Name
conName Q Exp
js)
[]
argsToValue target :: ToJSONFun
target jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap opts :: Options
opts multiCons :: Bool
multiCons
info :: ConstructorInfo
info@ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = RecordConstructor fields :: [Name]
fields
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys } =
case (Options -> Bool
unwrapUnaryRecords Options
opts, Bool -> Bool
not Bool
multiCons, [Type]
argTys) of
(True,True,[_]) -> ToJSONFun
-> JSONClass
-> Map Name (Name, Name)
-> Options
-> Bool
-> ConstructorInfo
-> MatchQ
argsToValue ToJSONFun
target JSONClass
jc Map Name (Name, Name)
tvMap Options
opts Bool
multiCons
(ConstructorInfo
info{constructorVariant :: ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor})
_ -> do
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
[Name]
args <- [Char] -> Int -> Q [Name]
newNameList "arg" (Int -> Q [Name]) -> Int -> Q [Name]
forall a b. (a -> b) -> a -> b
$ [Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
argTys'
let pairs :: Q Exp
pairs | Options -> Bool
omitNothingFields Options
opts = Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
maybeFields
[|(Monoid.<>)|]
Q Exp
restFields
| Bool
otherwise = [Q Exp] -> Q Exp
mconcatE (((Q Exp, Type, Name) -> Q Exp) -> [(Q Exp, Type, Name)] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (Q Exp, Type, Name) -> Q Exp
pureToPair [(Q Exp, Type, Name)]
argCons)
argCons :: [(Q Exp, Type, Name)]
argCons = [Q Exp] -> [Type] -> [Name] -> [(Q Exp, Type, Name)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 ((Name -> Q Exp) -> [Name] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Q Exp
varE [Name]
args) [Type]
argTys' [Name]
fields
maybeFields :: Q Exp
maybeFields = [Q Exp] -> Q Exp
mconcatE (((Q Exp, Type, Name) -> Q Exp) -> [(Q Exp, Type, Name)] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (Q Exp, Type, Name) -> Q Exp
maybeToPair [(Q Exp, Type, Name)]
maybes)
restFields :: Q Exp
restFields = [Q Exp] -> Q Exp
mconcatE (((Q Exp, Type, Name) -> Q Exp) -> [(Q Exp, Type, Name)] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (Q Exp, Type, Name) -> Q Exp
pureToPair [(Q Exp, Type, Name)]
rest)
(maybes0 :: [(Q Exp, Type, Name)]
maybes0, rest0 :: [(Q Exp, Type, Name)]
rest0) = ((Q Exp, Type, Name) -> Bool)
-> [(Q Exp, Type, Name)]
-> ([(Q Exp, Type, Name)], [(Q Exp, Type, Name)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Q Exp, Type, Name) -> Bool
forall a b. (a, Type, b) -> Bool
isMaybe [(Q Exp, Type, Name)]
argCons
(options :: [(Q Exp, Type, Name)]
options, rest :: [(Q Exp, Type, Name)]
rest) = ((Q Exp, Type, Name) -> Bool)
-> [(Q Exp, Type, Name)]
-> ([(Q Exp, Type, Name)], [(Q Exp, Type, Name)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Q Exp, Type, Name) -> Bool
forall a b. (a, Type, b) -> Bool
isOption [(Q Exp, Type, Name)]
rest0
maybes :: [(Q Exp, Type, Name)]
maybes = [(Q Exp, Type, Name)]
maybes0 [(Q Exp, Type, Name)]
-> [(Q Exp, Type, Name)] -> [(Q Exp, Type, Name)]
forall a. [a] -> [a] -> [a]
++ ((Q Exp, Type, Name) -> (Q Exp, Type, Name))
-> [(Q Exp, Type, Name)] -> [(Q Exp, Type, Name)]
forall a b. (a -> b) -> [a] -> [b]
map (Q Exp, Type, Name) -> (Q Exp, Type, Name)
forall b c. (Q Exp, b, c) -> (Q Exp, b, c)
optionToMaybe [(Q Exp, Type, Name)]
options
maybeToPair :: (Q Exp, Type, Name) -> Q Exp
maybeToPair = Bool -> (Q Exp, Type, Name) -> Q Exp
toPairLifted Bool
True
pureToPair :: (Q Exp, Type, Name) -> Q Exp
pureToPair = Bool -> (Q Exp, Type, Name) -> Q Exp
toPairLifted Bool
False
toPairLifted :: Bool -> (Q Exp, Type, Name) -> Q Exp
toPairLifted lifted :: Bool
lifted (arg :: Q Exp
arg, argTy :: Type
argTy, field :: Name
field) =
let toValue :: Q Exp
toValue = ToJSONFun
-> JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchToJSON ToJSONFun
target JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
argTy
fieldName :: [Char]
fieldName = Options -> Name -> [Char]
fieldLabel Options
opts Name
field
e :: Q Exp -> Q Exp
e arg' :: Q Exp
arg' = [Char] -> Q Exp -> Q Exp
pairE [Char]
fieldName (Q Exp
toValue Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
arg')
in if Bool
lifted
then do
Name
x <- [Char] -> Q Name
newName "x"
[|maybe mempty|] Q Exp -> Q Exp -> Q Exp
`appE` PatQ -> Q Exp -> Q Exp
lam1E (Name -> PatQ
varP Name
x) (Q Exp -> Q Exp
e (Name -> Q Exp
varE Name
x)) Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
arg
else Q Exp -> Q Exp
e Q Exp
arg
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP Name
conName ([PatQ] -> PatQ) -> [PatQ] -> PatQ
forall a b. (a -> b) -> a -> b
$ (Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP [Name]
args)
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ ToJSONFun -> Options -> Bool -> Bool -> Name -> Q Exp -> Q Exp
recordSumToValue ToJSONFun
target Options
opts Bool
multiCons ([Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
argTys) Name
conName Q Exp
pairs)
[]
argsToValue target :: ToJSONFun
target jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap opts :: Options
opts multiCons :: Bool
multiCons
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
InfixConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys } = do
[alTy :: Type
alTy, arTy :: Type
arTy] <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
Name
al <- [Char] -> Q Name
newName "argL"
Name
ar <- [Char] -> Q Name
newName "argR"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (PatQ -> Name -> PatQ -> PatQ
infixP (Name -> PatQ
varP Name
al) Name
conName (Name -> PatQ
varP Name
ar))
( Q Exp -> BodyQ
normalB
(Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ ToJSONFun -> Options -> Bool -> Bool -> Name -> Q Exp -> Q Exp
opaqueSumToValue ToJSONFun
target Options
opts Bool
multiCons Bool
False Name
conName
(Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ ToJSONFun -> [Q Exp] -> Q Exp
array ToJSONFun
target
[ ToJSONFun
-> JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchToJSON ToJSONFun
target JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
aTy
Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
a
| (a :: Name
a, aTy :: Type
aTy) <- [(Name
al,Type
alTy), (Name
ar,Type
arTy)]
]
)
[]
isMaybe :: (a, Type, b) -> Bool
isMaybe :: (a, Type, b) -> Bool
isMaybe (_, AppT (ConT t :: Name
t) _, _) = Name
t Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''Maybe
isMaybe _ = Bool
False
isOption :: (a, Type, b) -> Bool
isOption :: (a, Type, b) -> Bool
isOption (_, AppT (ConT t :: Name
t) _, _) = Name
t Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''Semigroup.Option
isOption _ = Bool
False
optionToMaybe :: (ExpQ, b, c) -> (ExpQ, b, c)
optionToMaybe :: (Q Exp, b, c) -> (Q Exp, b, c)
optionToMaybe (a :: Q Exp
a, b :: b
b, c :: c
c) = ([|Semigroup.getOption|] Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
a, b
b, c
c)
(<^>) :: ExpQ -> ExpQ -> ExpQ
<^> :: Q Exp -> Q Exp -> Q Exp
(<^>) a :: Q Exp
a b :: Q Exp
b = Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
a [|(E.><)|] Q Exp
b
infixr 6 <^>
(<%>) :: ExpQ -> ExpQ -> ExpQ
<%> :: Q Exp -> Q Exp -> Q Exp
(<%>) a :: Q Exp
a b :: Q Exp
b = Q Exp
a Q Exp -> Q Exp -> Q Exp
<^> [|E.comma|] Q Exp -> Q Exp -> Q Exp
<^> Q Exp
b
infixr 4 <%>
array :: ToJSONFun -> [ExpQ] -> ExpQ
array :: ToJSONFun -> [Q Exp] -> Q Exp
array Encoding [] = [|E.emptyArray_|]
array Value [] = [|Array V.empty|]
array Encoding es :: [Q Exp]
es = [|E.wrapArray|] Q Exp -> Q Exp -> Q Exp
`appE` (Q Exp -> Q Exp -> Q Exp) -> [Q Exp] -> Q Exp
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Q Exp -> Q Exp -> Q Exp
(<%>) [Q Exp]
es
array Value es :: [Q Exp]
es = do
Name
mv <- [Char] -> Q Name
newName "mv"
let newMV :: StmtQ
newMV = PatQ -> Q Exp -> StmtQ
bindS (Name -> PatQ
varP Name
mv)
([|VM.unsafeNew|] Q Exp -> Q Exp -> Q Exp
`appE`
Lit -> Q Exp
litE (Integer -> Lit
integerL (Integer -> Lit) -> Integer -> Lit
forall a b. (a -> b) -> a -> b
$ Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Q Exp] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Q Exp]
es)))
stmts :: [StmtQ]
stmts = [ Q Exp -> StmtQ
noBindS (Q Exp -> StmtQ) -> Q Exp -> StmtQ
forall a b. (a -> b) -> a -> b
$
[|VM.unsafeWrite|] Q Exp -> Q Exp -> Q Exp
`appE`
Name -> Q Exp
varE Name
mv Q Exp -> Q Exp -> Q Exp
`appE`
Lit -> Q Exp
litE (Integer -> Lit
integerL Integer
ix) Q Exp -> Q Exp -> Q Exp
`appE`
Q Exp
e
| (ix :: Integer
ix, e :: Q Exp
e) <- [Integer] -> [Q Exp] -> [(Integer, Q Exp)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(0::Integer)..] [Q Exp]
es
]
ret :: StmtQ
ret = Q Exp -> StmtQ
noBindS (Q Exp -> StmtQ) -> Q Exp -> StmtQ
forall a b. (a -> b) -> a -> b
$ [|return|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
mv
[|Array|] Q Exp -> Q Exp -> Q Exp
`appE`
(Name -> Q Exp
varE 'V.create Q Exp -> Q Exp -> Q Exp
`appE`
[StmtQ] -> Q Exp
doE (StmtQ
newMVStmtQ -> [StmtQ] -> [StmtQ]
forall a. a -> [a] -> [a]
:[StmtQ]
stmts[StmtQ] -> [StmtQ] -> [StmtQ]
forall a. [a] -> [a] -> [a]
++[StmtQ
ret]))
objectE :: [(String, ExpQ)] -> ExpQ
objectE :: [([Char], Q Exp)] -> Q Exp
objectE = Q Exp -> Q Exp
fromPairsE (Q Exp -> Q Exp)
-> ([([Char], Q Exp)] -> Q Exp) -> [([Char], Q Exp)] -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Q Exp] -> Q Exp
mconcatE ([Q Exp] -> Q Exp)
-> ([([Char], Q Exp)] -> [Q Exp]) -> [([Char], Q Exp)] -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Char], Q Exp) -> Q Exp) -> [([Char], Q Exp)] -> [Q Exp]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([Char] -> Q Exp -> Q Exp) -> ([Char], Q Exp) -> Q Exp
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [Char] -> Q Exp -> Q Exp
pairE)
mconcatE :: [ExpQ] -> ExpQ
mconcatE :: [Q Exp] -> Q Exp
mconcatE [] = [|Monoid.mempty|]
mconcatE [x :: Q Exp
x] = Q Exp
x
mconcatE (x :: Q Exp
x : xs :: [Q Exp]
xs) = Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
x [|(Monoid.<>)|] ([Q Exp] -> Q Exp
mconcatE [Q Exp]
xs)
fromPairsE :: ExpQ -> ExpQ
fromPairsE :: Q Exp -> Q Exp
fromPairsE = ([|fromPairs|] Q Exp -> Q Exp -> Q Exp
`appE`)
pairE :: String -> ExpQ -> ExpQ
pairE :: [Char] -> Q Exp -> Q Exp
pairE k :: [Char]
k v :: Q Exp
v = [|pair k|] Q Exp -> Q Exp -> Q Exp
`appE` Q Exp
v
deriveFromJSON :: Options
-> Name
-> Q [Dec]
deriveFromJSON :: Options -> Name -> Q [Dec]
deriveFromJSON = JSONClass -> Options -> Name -> Q [Dec]
deriveFromJSONCommon JSONClass
fromJSONClass
deriveFromJSON1 :: Options
-> Name
-> Q [Dec]
deriveFromJSON1 :: Options -> Name -> Q [Dec]
deriveFromJSON1 = JSONClass -> Options -> Name -> Q [Dec]
deriveFromJSONCommon JSONClass
fromJSON1Class
deriveFromJSON2 :: Options
-> Name
-> Q [Dec]
deriveFromJSON2 :: Options -> Name -> Q [Dec]
deriveFromJSON2 = JSONClass -> Options -> Name -> Q [Dec]
deriveFromJSONCommon JSONClass
fromJSON2Class
deriveFromJSONCommon :: JSONClass
-> Options
-> Name
-> Q [Dec]
deriveFromJSONCommon :: JSONClass -> Options -> Name -> Q [Dec]
deriveFromJSONCommon = [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> JSONClass -> Options -> Name -> Q [Dec]
deriveJSONClass [(JSONFun
ParseJSON, JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consFromJSON)]
mkParseJSON :: Options
-> Name
-> Q Exp
mkParseJSON :: Options -> Name -> Q Exp
mkParseJSON = JSONClass -> Options -> Name -> Q Exp
mkParseJSONCommon JSONClass
fromJSONClass
mkLiftParseJSON :: Options
-> Name
-> Q Exp
mkLiftParseJSON :: Options -> Name -> Q Exp
mkLiftParseJSON = JSONClass -> Options -> Name -> Q Exp
mkParseJSONCommon JSONClass
fromJSON1Class
mkLiftParseJSON2 :: Options
-> Name
-> Q Exp
mkLiftParseJSON2 :: Options -> Name -> Q Exp
mkLiftParseJSON2 = JSONClass -> Options -> Name -> Q Exp
mkParseJSONCommon JSONClass
fromJSON2Class
mkParseJSONCommon :: JSONClass
-> Options
-> Name
-> Q Exp
mkParseJSONCommon :: JSONClass -> Options -> Name -> Q Exp
mkParseJSONCommon = (JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> JSONClass -> Options -> Name -> Q Exp
mkFunCommon JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consFromJSON
consFromJSON :: JSONClass
-> Name
-> Options
-> [Type]
-> [ConstructorInfo]
-> Q Exp
consFromJSON :: JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consFromJSON _ _ _ _ [] = [Char] -> Q Exp
forall a. HasCallStack => [Char] -> a
error ([Char] -> Q Exp) -> [Char] -> Q Exp
forall a b. (a -> b) -> a -> b
$ "Data.Aeson.TH.consFromJSON: "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ "Not a single constructor given!"
consFromJSON jc :: JSONClass
jc tName :: Name
tName opts :: Options
opts instTys :: [Type]
instTys cons :: [ConstructorInfo]
cons = do
Name
value <- [Char] -> Q Name
newName "value"
[Name]
pjs <- [Char] -> Int -> Q [Name]
newNameList "_pj" (Int -> Q [Name]) -> Int -> Q [Name]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Int
arityInt JSONClass
jc
[Name]
pjls <- [Char] -> Int -> Q [Name]
newNameList "_pjl" (Int -> Q [Name]) -> Int -> Q [Name]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Int
arityInt JSONClass
jc
let zippedPJs :: [(Name, Name)]
zippedPJs = [Name] -> [Name] -> [(Name, Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
pjs [Name]
pjls
interleavedPJs :: [Name]
interleavedPJs = [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
interleave [Name]
pjs [Name]
pjls
lastTyVars :: [Name]
lastTyVars = (Type -> Name) -> [Type] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Name
varTToName ([Type] -> [Name]) -> [Type] -> [Name]
forall a b. (a -> b) -> a -> b
$ Int -> [Type] -> [Type]
forall a. Int -> [a] -> [a]
drop ([Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
instTys Int -> Int -> Int
forall a. Num a => a -> a -> a
- JSONClass -> Int
arityInt JSONClass
jc) [Type]
instTys
tvMap :: Map Name (Name, Name)
tvMap = [(Name, (Name, Name))] -> Map Name (Name, Name)
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Name, (Name, Name))] -> Map Name (Name, Name))
-> [(Name, (Name, Name))] -> Map Name (Name, Name)
forall a b. (a -> b) -> a -> b
$ [Name] -> [(Name, Name)] -> [(Name, (Name, Name))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
lastTyVars [(Name, Name)]
zippedPJs
[PatQ] -> Q Exp -> Q Exp
lamE ((Name -> PatQ) -> [Name] -> [PatQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> PatQ
varP ([Name] -> [PatQ]) -> [Name] -> [PatQ]
forall a b. (a -> b) -> a -> b
$ [Name]
interleavedPJs [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
++ [Name
value]) (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Map Name (Name, Name) -> Q Exp
lamExpr Name
value Map Name (Name, Name)
tvMap
where
checkExi :: Map Name (Name, Name) -> ConstructorInfo -> Q a -> Q a
checkExi tvMap :: Map Name (Name, Name)
tvMap con :: ConstructorInfo
con = JSONClass -> Map Name (Name, Name) -> [Type] -> Name -> Q a -> Q a
forall a.
JSONClass -> Map Name (Name, Name) -> [Type] -> Name -> Q a -> Q a
checkExistentialContext JSONClass
jc Map Name (Name, Name)
tvMap
(ConstructorInfo -> [Type]
constructorContext ConstructorInfo
con)
(ConstructorInfo -> Name
constructorName ConstructorInfo
con)
lamExpr :: Name -> Map Name (Name, Name) -> Q Exp
lamExpr value :: Name
value tvMap :: Map Name (Name, Name)
tvMap = case [ConstructorInfo]
cons of
[con :: ConstructorInfo
con]
| Bool -> Bool
not (Options -> Bool
tagSingleConstructors Options
opts)
-> Map Name (Name, Name) -> ConstructorInfo -> Q Exp -> Q Exp
forall a. Map Name (Name, Name) -> ConstructorInfo -> Q a -> Q a
checkExi Map Name (Name, Name)
tvMap ConstructorInfo
con (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ JSONClass
-> Map Name (Name, Name)
-> Name
-> Options
-> ConstructorInfo
-> Either ([Char], Name) Name
-> Q Exp
parseArgs JSONClass
jc Map Name (Name, Name)
tvMap Name
tName Options
opts ConstructorInfo
con (Name -> Either ([Char], Name) Name
forall a b. b -> Either a b
Right Name
value)
_ | Options -> SumEncoding
sumEncoding Options
opts SumEncoding -> SumEncoding -> Bool
forall a. Eq a => a -> a -> Bool
== SumEncoding
UntaggedValue
-> Map Name (Name, Name) -> [ConstructorInfo] -> Name -> Q Exp
parseUntaggedValue Map Name (Name, Name)
tvMap [ConstructorInfo]
cons Name
value
| Bool
otherwise
-> Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
value) ([MatchQ] -> Q Exp) -> [MatchQ] -> Q Exp
forall a b. (a -> b) -> a -> b
$
if Options -> Bool
allNullaryToStringTag Options
opts Bool -> Bool -> Bool
&& (ConstructorInfo -> Bool) -> [ConstructorInfo] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ConstructorInfo -> Bool
isNullary [ConstructorInfo]
cons
then [MatchQ]
allNullaryMatches
else Map Name (Name, Name) -> [MatchQ]
mixedMatches Map Name (Name, Name)
tvMap
allNullaryMatches :: [MatchQ]
allNullaryMatches =
[ do Name
txt <- [Char] -> Q Name
newName "txt"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'String [Name -> PatQ
varP Name
txt])
([Q (Guard, Exp)] -> BodyQ
guardedB ([Q (Guard, Exp)] -> BodyQ) -> [Q (Guard, Exp)] -> BodyQ
forall a b. (a -> b) -> a -> b
$
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG (Q Exp -> Q Guard) -> Q Exp -> Q Guard
forall a b. (a -> b) -> a -> b
$
Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
txt)
[|(==)|]
(Options -> Name -> Q Exp
conTxt Options
opts Name
conName)
)
([|pure|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
conE Name
conName)
| ConstructorInfo
con <- [ConstructorInfo]
cons
, let conName :: Name
conName = ConstructorInfo -> Name
constructorName ConstructorInfo
con
]
[Q (Guard, Exp)] -> [Q (Guard, Exp)] -> [Q (Guard, Exp)]
forall a. [a] -> [a] -> [a]
++
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,)
(Q Exp -> Q Guard
normalG [|otherwise|])
( [|noMatchFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|T.unpack|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
txt)
)
]
)
[]
, do Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [|noStringFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|valueConName|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
]
mixedMatches :: Map Name (Name, Name) -> [MatchQ]
mixedMatches tvMap :: Map Name (Name, Name)
tvMap =
case Options -> SumEncoding
sumEncoding Options
opts of
TaggedObject {[Char]
tagFieldName :: [Char]
tagFieldName :: SumEncoding -> [Char]
tagFieldName, [Char]
contentsFieldName :: [Char]
contentsFieldName :: SumEncoding -> [Char]
contentsFieldName} ->
(Name -> Q Exp) -> [MatchQ]
parseObject ((Name -> Q Exp) -> [MatchQ]) -> (Name -> Q Exp) -> [MatchQ]
forall a b. (a -> b) -> a -> b
$ Map Name (Name, Name) -> [Char] -> [Char] -> Name -> Q Exp
parseTaggedObject Map Name (Name, Name)
tvMap [Char]
tagFieldName [Char]
contentsFieldName
UntaggedValue -> [Char] -> [MatchQ]
forall a. HasCallStack => [Char] -> a
error "UntaggedValue: Should be handled already"
ObjectWithSingleField ->
(Name -> Q Exp) -> [MatchQ]
parseObject ((Name -> Q Exp) -> [MatchQ]) -> (Name -> Q Exp) -> [MatchQ]
forall a b. (a -> b) -> a -> b
$ Map Name (Name, Name) -> Name -> Q Exp
parseObjectWithSingleField Map Name (Name, Name)
tvMap
TwoElemArray ->
[ do Name
arr <- [Char] -> Q Name
newName "array"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'Array [Name -> PatQ
varP Name
arr])
([Q (Guard, Exp)] -> BodyQ
guardedB
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG (Q Exp -> Q Guard) -> Q Exp -> Q Guard
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp ([|V.length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr)
[|(==)|]
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ Integer -> Lit
integerL 2))
(Map Name (Name, Name) -> Name -> Q Exp
parse2ElemArray Map Name (Name, Name)
tvMap Name
arr)
, (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG [|otherwise|])
([|not2ElemArray|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|V.length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr))
]
)
[]
, do Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
( Q Exp -> BodyQ
normalB
(Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [|noArrayFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|valueConName|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
]
parseObject :: (Name -> Q Exp) -> [MatchQ]
parseObject f :: Name -> Q Exp
f =
[ do Name
obj <- [Char] -> Q Name
newName "obj"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'Object [Name -> PatQ
varP Name
obj]) (Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Name -> Q Exp
f Name
obj) []
, do Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
( Q Exp -> BodyQ
normalB
(Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [|noObjectFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|valueConName|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
]
parseTaggedObject :: Map Name (Name, Name) -> [Char] -> [Char] -> Name -> Q Exp
parseTaggedObject tvMap :: Map Name (Name, Name)
tvMap typFieldName :: [Char]
typFieldName valFieldName :: [Char]
valFieldName obj :: Name
obj = do
Name
conKey <- [Char] -> Q Name
newName "conKey"
[StmtQ] -> Q Exp
doE [ PatQ -> Q Exp -> StmtQ
bindS (Name -> PatQ
varP Name
conKey)
(Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
obj)
[|(.:)|]
([|T.pack|] Q Exp -> Q Exp -> Q Exp
`appE` [Char] -> Q Exp
stringE [Char]
typFieldName))
, Q Exp -> StmtQ
noBindS (Q Exp -> StmtQ) -> Q Exp -> StmtQ
forall a b. (a -> b) -> a -> b
$ Map Name (Name, Name)
-> Name -> Either ([Char], Name) Name -> Name -> Q Exp
parseContents Map Name (Name, Name)
tvMap Name
conKey (([Char], Name) -> Either ([Char], Name) Name
forall a b. a -> Either a b
Left ([Char]
valFieldName, Name
obj)) 'conNotFoundFailTaggedObject
]
parseUntaggedValue :: Map Name (Name, Name) -> [ConstructorInfo] -> Name -> Q Exp
parseUntaggedValue tvMap :: Map Name (Name, Name)
tvMap cons' :: [ConstructorInfo]
cons' conVal :: Name
conVal =
(Q Exp -> Q Exp -> Q Exp) -> [Q Exp] -> Q Exp
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (\e :: Q Exp
e e' :: Q Exp
e' -> Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
e [|(<|>)|] Q Exp
e')
((ConstructorInfo -> Q Exp) -> [ConstructorInfo] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map (\x :: ConstructorInfo
x -> Map Name (Name, Name) -> ConstructorInfo -> Name -> Q Exp
parseValue Map Name (Name, Name)
tvMap ConstructorInfo
x Name
conVal) [ConstructorInfo]
cons')
parseValue :: Map Name (Name, Name) -> ConstructorInfo -> Name -> Q Exp
parseValue _tvMap :: Map Name (Name, Name)
_tvMap
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [] }
conVal :: Name
conVal = do
Name
str <- [Char] -> Q Name
newName "str"
Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
conVal)
[ PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'String [Name -> PatQ
varP Name
str])
([Q (Guard, Exp)] -> BodyQ
guardedB
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG (Q Exp -> Q Guard) -> Q Exp -> Q Guard
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
str) [|(==)|] (Options -> Name -> Q Exp
conTxt Options
opts Name
conName)
)
([|pure|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
conE Name
conName)
]
)
[]
, Name -> Name -> [Char] -> MatchQ
matchFailed Name
tName Name
conName "String"
]
parseValue tvMap :: Map Name (Name, Name)
tvMap con :: ConstructorInfo
con conVal :: Name
conVal =
Map Name (Name, Name) -> ConstructorInfo -> Q Exp -> Q Exp
forall a. Map Name (Name, Name) -> ConstructorInfo -> Q a -> Q a
checkExi Map Name (Name, Name)
tvMap ConstructorInfo
con (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ JSONClass
-> Map Name (Name, Name)
-> Name
-> Options
-> ConstructorInfo
-> Either ([Char], Name) Name
-> Q Exp
parseArgs JSONClass
jc Map Name (Name, Name)
tvMap Name
tName Options
opts ConstructorInfo
con (Name -> Either ([Char], Name) Name
forall a b. b -> Either a b
Right Name
conVal)
parse2ElemArray :: Map Name (Name, Name) -> Name -> Q Exp
parse2ElemArray tvMap :: Map Name (Name, Name)
tvMap arr :: Name
arr = do
Name
conKey <- [Char] -> Q Name
newName "conKey"
Name
conVal <- [Char] -> Q Name
newName "conVal"
let letIx :: Name -> Integer -> DecQ
letIx n :: Name
n ix :: Integer
ix =
PatQ -> BodyQ -> [DecQ] -> DecQ
valD (Name -> PatQ
varP Name
n)
(Q Exp -> BodyQ
normalB ([|V.unsafeIndex|] Q Exp -> Q Exp -> Q Exp
`appE`
Name -> Q Exp
varE Name
arr Q Exp -> Q Exp -> Q Exp
`appE`
Lit -> Q Exp
litE (Integer -> Lit
integerL Integer
ix)))
[]
[DecQ] -> Q Exp -> Q Exp
letE [ Name -> Integer -> DecQ
letIx Name
conKey 0
, Name -> Integer -> DecQ
letIx Name
conVal 1
]
(Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
conKey)
[ do Name
txt <- [Char] -> Q Name
newName "txt"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'String [Name -> PatQ
varP Name
txt])
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Map Name (Name, Name)
-> Name -> Either ([Char], Name) Name -> Name -> Q Exp
parseContents Map Name (Name, Name)
tvMap
Name
txt
(Name -> Either ([Char], Name) Name
forall a b. b -> Either a b
Right Name
conVal)
'conNotFoundFail2ElemArray
)
[]
, do Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
( Q Exp -> BodyQ
normalB
(Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [|firstElemNoStringFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|valueConName|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
]
)
parseObjectWithSingleField :: Map Name (Name, Name) -> Name -> Q Exp
parseObjectWithSingleField tvMap :: Map Name (Name, Name)
tvMap obj :: Name
obj = do
Name
conKey <- [Char] -> Q Name
newName "conKey"
Name
conVal <- [Char] -> Q Name
newName "conVal"
Q Exp -> [MatchQ] -> Q Exp
caseE ([e|H.toList|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
obj)
[ PatQ -> BodyQ -> [DecQ] -> MatchQ
match ([PatQ] -> PatQ
listP [[PatQ] -> PatQ
tupP [Name -> PatQ
varP Name
conKey, Name -> PatQ
varP Name
conVal]])
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Map Name (Name, Name)
-> Name -> Either ([Char], Name) Name -> Name -> Q Exp
parseContents Map Name (Name, Name)
tvMap Name
conKey (Name -> Either ([Char], Name) Name
forall a b. b -> Either a b
Right Name
conVal) 'conNotFoundFailObjectSingleField)
[]
, do Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ [|wrongPairCountFail|]
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` ([|show . length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
]
parseContents :: Map Name (Name, Name)
-> Name -> Either ([Char], Name) Name -> Name -> Q Exp
parseContents tvMap :: Map Name (Name, Name)
tvMap conKey :: Name
conKey contents :: Either ([Char], Name) Name
contents errorFun :: Name
errorFun =
Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
conKey)
[ PatQ -> BodyQ -> [DecQ] -> MatchQ
match PatQ
wildP
( [Q (Guard, Exp)] -> BodyQ
guardedB ([Q (Guard, Exp)] -> BodyQ) -> [Q (Guard, Exp)] -> BodyQ
forall a b. (a -> b) -> a -> b
$
[ do Guard
g <- Q Exp -> Q Guard
normalG (Q Exp -> Q Guard) -> Q Exp -> Q Guard
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
conKey)
[|(==)|]
([|T.pack|] Q Exp -> Q Exp -> Q Exp
`appE`
Options -> ConstructorInfo -> Q Exp
conNameExp Options
opts ConstructorInfo
con)
Exp
e <- Map Name (Name, Name) -> ConstructorInfo -> Q Exp -> Q Exp
forall a. Map Name (Name, Name) -> ConstructorInfo -> Q a -> Q a
checkExi Map Name (Name, Name)
tvMap ConstructorInfo
con (Q Exp -> Q Exp) -> Q Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$
JSONClass
-> Map Name (Name, Name)
-> Name
-> Options
-> ConstructorInfo
-> Either ([Char], Name) Name
-> Q Exp
parseArgs JSONClass
jc Map Name (Name, Name)
tvMap Name
tName Options
opts ConstructorInfo
con Either ([Char], Name) Name
contents
(Guard, Exp) -> Q (Guard, Exp)
forall (m :: * -> *) a. Monad m => a -> m a
return (Guard
g, Exp
e)
| ConstructorInfo
con <- [ConstructorInfo]
cons
]
[Q (Guard, Exp)] -> [Q (Guard, Exp)] -> [Q (Guard, Exp)]
forall a. [a] -> [a] -> [a]
++
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,)
(Q Exp -> Q Guard
normalG [e|otherwise|])
( Name -> Q Exp
varE Name
errorFun
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` [Q Exp] -> Q Exp
listE ((ConstructorInfo -> Q Exp) -> [ConstructorInfo] -> [Q Exp]
forall a b. (a -> b) -> [a] -> [b]
map ( Lit -> Q Exp
litE
(Lit -> Q Exp)
-> (ConstructorInfo -> Lit) -> ConstructorInfo -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Lit
stringL
([Char] -> Lit)
-> (ConstructorInfo -> [Char]) -> ConstructorInfo -> Lit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> [Char] -> [Char]
constructorTagModifier Options
opts
([Char] -> [Char])
-> (ConstructorInfo -> [Char]) -> ConstructorInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> [Char]
nameBase
(Name -> [Char])
-> (ConstructorInfo -> Name) -> ConstructorInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConstructorInfo -> Name
constructorName
) [ConstructorInfo]
cons
)
Q Exp -> Q Exp -> Q Exp
`appE` ([|T.unpack|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
conKey)
)
]
)
[]
]
parseNullaryMatches :: Name -> Name -> [Q Match]
parseNullaryMatches :: Name -> Name -> [MatchQ]
parseNullaryMatches tName :: Name
tName conName :: Name
conName =
[ do Name
arr <- [Char] -> Q Name
newName "arr"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'Array [Name -> PatQ
varP Name
arr])
([Q (Guard, Exp)] -> BodyQ
guardedB
[ (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG (Q Exp -> Q Guard) -> Q Exp -> Q Guard
forall a b. (a -> b) -> a -> b
$ [|V.null|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr)
([|pure|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
conE Name
conName)
, (Guard -> Exp -> (Guard, Exp))
-> Q Guard -> Q Exp -> Q (Guard, Exp)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (Q Exp -> Q Guard
normalG [|otherwise|])
(Name -> Name -> Q Exp -> Q Exp -> Q Exp
parseTypeMismatch Name
tName Name
conName
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL "an empty Array")
(Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL "Array of length ")
[|(++)|]
([|show . V.length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr)
)
)
]
)
[]
, Name -> Name -> [Char] -> MatchQ
matchFailed Name
tName Name
conName "Array"
]
parseUnaryMatches :: JSONClass -> TyVarMap -> Type -> Name -> [Q Match]
parseUnaryMatches :: JSONClass -> Map Name (Name, Name) -> Type -> Name -> [MatchQ]
parseUnaryMatches jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap argTy :: Type
argTy conName :: Name
conName =
[ do Name
arg <- [Char] -> Q Name
newName "arg"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
arg)
( Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
conE Name
conName)
[|(<$>)|]
(JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchParseJSON JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
argTy
Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arg)
)
[]
]
parseRecord :: JSONClass
-> TyVarMap
-> [Type]
-> Options
-> Name
-> Name
-> [Name]
-> Name
-> ExpQ
parseRecord :: JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Options
-> Name
-> Name
-> [Name]
-> Name
-> Q Exp
parseRecord jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap argTys :: [Type]
argTys opts :: Options
opts tName :: Name
tName conName :: Name
conName fields :: [Name]
fields obj :: Name
obj =
(Q Exp -> Q Exp -> Q Exp) -> Q Exp -> [Q Exp] -> Q Exp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\a :: Q Exp
a b :: Q Exp
b -> Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
a [|(<*>)|] Q Exp
b)
(Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
conE Name
conName) [|(<$>)|] Q Exp
x)
[Q Exp]
xs
where
x :: Q Exp
x:xs :: [Q Exp]
xs = [ [|lookupField|]
Q Exp -> Q Exp -> Q Exp
`appE` JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchParseJSON JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
argTy
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName)
Q Exp -> Q Exp -> Q Exp
`appE` Lit -> Q Exp
litE ([Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Options -> [Char] -> [Char]
constructorTagModifier Options
opts ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
nameBase Name
conName)
Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
obj
Q Exp -> Q Exp -> Q Exp
`appE` ( [|T.pack|] Q Exp -> Q Exp -> Q Exp
`appE` [Char] -> Q Exp
stringE (Options -> Name -> [Char]
fieldLabel Options
opts Name
field)
)
| (field :: Name
field, argTy :: Type
argTy) <- [Name] -> [Type] -> [(Name, Type)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
fields [Type]
argTys
]
getValField :: Name -> String -> [MatchQ] -> Q Exp
getValField :: Name -> [Char] -> [MatchQ] -> Q Exp
getValField obj :: Name
obj valFieldName :: [Char]
valFieldName matches :: [MatchQ]
matches = do
Name
val <- [Char] -> Q Name
newName "val"
[StmtQ] -> Q Exp
doE [ PatQ -> Q Exp -> StmtQ
bindS (Name -> PatQ
varP Name
val) (Q Exp -> StmtQ) -> Q Exp -> StmtQ
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
obj)
[|(.:)|]
([|T.pack|] Q Exp -> Q Exp -> Q Exp
`appE`
Lit -> Q Exp
litE ([Char] -> Lit
stringL [Char]
valFieldName))
, Q Exp -> StmtQ
noBindS (Q Exp -> StmtQ) -> Q Exp -> StmtQ
forall a b. (a -> b) -> a -> b
$ Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
val) [MatchQ]
matches
]
matchCases :: Either (String, Name) Name -> [MatchQ] -> Q Exp
matchCases :: Either ([Char], Name) Name -> [MatchQ] -> Q Exp
matchCases (Left (valFieldName :: [Char]
valFieldName, obj :: Name
obj)) = Name -> [Char] -> [MatchQ] -> Q Exp
getValField Name
obj [Char]
valFieldName
matchCases (Right valName :: Name
valName) = Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
valName)
parseArgs :: JSONClass
-> TyVarMap
-> Name
-> Options
-> ConstructorInfo
-> Either (String, Name) Name
-> Q Exp
parseArgs :: JSONClass
-> Map Name (Name, Name)
-> Name
-> Options
-> ConstructorInfo
-> Either ([Char], Name) Name
-> Q Exp
parseArgs _ _ _ _
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [] }
(Left _) =
[|pure|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
conE Name
conName
parseArgs _ _ tName :: Name
tName _
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [] }
(Right valName :: Name
valName) =
Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
valName) ([MatchQ] -> Q Exp) -> [MatchQ] -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Name -> [MatchQ]
parseNullaryMatches Name
tName Name
conName
parseArgs jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap _ _
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [argTy :: Type
argTy] }
contents :: Either ([Char], Name) Name
contents = do
Type
argTy' <- Type -> Q Type
resolveTypeSynonyms Type
argTy
Either ([Char], Name) Name -> [MatchQ] -> Q Exp
matchCases Either ([Char], Name) Name
contents ([MatchQ] -> Q Exp) -> [MatchQ] -> Q Exp
forall a b. (a -> b) -> a -> b
$ JSONClass -> Map Name (Name, Name) -> Type -> Name -> [MatchQ]
parseUnaryMatches JSONClass
jc Map Name (Name, Name)
tvMap Type
argTy' Name
conName
parseArgs jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap tName :: Name
tName _
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys }
contents :: Either ([Char], Name) Name
contents = do
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
let len :: Integer
len = [Type] -> Integer
forall i a. Num i => [a] -> i
genericLength [Type]
argTys'
Either ([Char], Name) Name -> [MatchQ] -> Q Exp
matchCases Either ([Char], Name) Name
contents ([MatchQ] -> Q Exp) -> [MatchQ] -> Q Exp
forall a b. (a -> b) -> a -> b
$ JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Name
-> Name
-> Integer
-> [MatchQ]
parseProduct JSONClass
jc Map Name (Name, Name)
tvMap [Type]
argTys' Name
tName Name
conName Integer
len
parseArgs jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap tName :: Name
tName opts :: Options
opts
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = RecordConstructor fields :: [Name]
fields
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys }
(Left (_, obj :: Name
obj)) = do
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Options
-> Name
-> Name
-> [Name]
-> Name
-> Q Exp
parseRecord JSONClass
jc Map Name (Name, Name)
tvMap [Type]
argTys' Options
opts Name
tName Name
conName [Name]
fields Name
obj
parseArgs jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap tName :: Name
tName opts :: Options
opts
info :: ConstructorInfo
info@ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = RecordConstructor fields :: [Name]
fields
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys }
(Right valName :: Name
valName) =
case (Options -> Bool
unwrapUnaryRecords Options
opts,[Type]
argTys) of
(True,[_])-> JSONClass
-> Map Name (Name, Name)
-> Name
-> Options
-> ConstructorInfo
-> Either ([Char], Name) Name
-> Q Exp
parseArgs JSONClass
jc Map Name (Name, Name)
tvMap Name
tName Options
opts
(ConstructorInfo
info{constructorVariant :: ConstructorVariant
constructorVariant = ConstructorVariant
NormalConstructor})
(Name -> Either ([Char], Name) Name
forall a b. b -> Either a b
Right Name
valName)
_ -> do
Name
obj <- [Char] -> Q Name
newName "recObj"
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
Q Exp -> [MatchQ] -> Q Exp
caseE (Name -> Q Exp
varE Name
valName)
[ PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'Object [Name -> PatQ
varP Name
obj]) (Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$
JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Options
-> Name
-> Name
-> [Name]
-> Name
-> Q Exp
parseRecord JSONClass
jc Map Name (Name, Name)
tvMap [Type]
argTys' Options
opts Name
tName Name
conName [Name]
fields Name
obj) []
, Name -> Name -> [Char] -> MatchQ
matchFailed Name
tName Name
conName "Object"
]
parseArgs jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap tName :: Name
tName _
ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorVariant :: ConstructorInfo -> ConstructorVariant
constructorVariant = ConstructorVariant
InfixConstructor
, constructorFields :: ConstructorInfo -> [Type]
constructorFields = [Type]
argTys }
contents :: Either ([Char], Name) Name
contents = do
[Type]
argTys' <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
argTys
Either ([Char], Name) Name -> [MatchQ] -> Q Exp
matchCases Either ([Char], Name) Name
contents ([MatchQ] -> Q Exp) -> [MatchQ] -> Q Exp
forall a b. (a -> b) -> a -> b
$ JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Name
-> Name
-> Integer
-> [MatchQ]
parseProduct JSONClass
jc Map Name (Name, Name)
tvMap [Type]
argTys' Name
tName Name
conName 2
parseProduct :: JSONClass
-> TyVarMap
-> [Type]
-> Name
-> Name
-> Integer
-> [Q Match]
parseProduct :: JSONClass
-> Map Name (Name, Name)
-> [Type]
-> Name
-> Name
-> Integer
-> [MatchQ]
parseProduct jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap argTys :: [Type]
argTys tName :: Name
tName conName :: Name
conName numArgs :: Integer
numArgs =
[ do Name
arr <- [Char] -> Q Name
newName "arr"
let x :: Q Exp
x:xs :: [Q Exp]
xs = [ JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchParseJSON JSONClass
jc Name
conName Map Name (Name, Name)
tvMap Type
argTy
Q Exp -> Q Exp -> Q Exp
`appE`
Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
varE Name
arr)
[|V.unsafeIndex|]
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ Integer -> Lit
integerL Integer
ix)
| (argTy :: Type
argTy, ix :: Integer
ix) <- [Type] -> [Integer] -> [(Type, Integer)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Type]
argTys [0 .. Integer
numArgs Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1]
]
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> [PatQ] -> PatQ
conP 'Array [Name -> PatQ
varP Name
arr])
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Q Exp -> Q Exp -> Q Exp -> Q Exp
condE ( Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp ([|V.length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr)
[|(==)|]
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ Integer -> Lit
integerL Integer
numArgs)
)
( (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> [Q Exp] -> Q Exp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\a :: Q Exp
a b :: Q Exp
b -> Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp Q Exp
a [|(<*>)|] Q Exp
b)
(Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Name -> Q Exp
conE Name
conName) [|(<$>)|] Q Exp
x)
[Q Exp]
xs
)
( Name -> Name -> Q Exp -> Q Exp -> Q Exp
parseTypeMismatch Name
tName Name
conName
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ "Array of length " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Integer -> [Char]
forall a. Show a => a -> [Char]
show Integer
numArgs)
( Q Exp -> Q Exp -> Q Exp -> Q Exp
infixApp (Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL "Array of length ")
[|(++)|]
([|show . V.length|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
arr)
)
)
)
[]
, Name -> Name -> [Char] -> MatchQ
matchFailed Name
tName Name
conName "Array"
]
matchFailed :: Name -> Name -> String -> MatchQ
matchFailed :: Name -> Name -> [Char] -> MatchQ
matchFailed tName :: Name
tName conName :: Name
conName expected :: [Char]
expected = do
Name
other <- [Char] -> Q Name
newName "other"
PatQ -> BodyQ -> [DecQ] -> MatchQ
match (Name -> PatQ
varP Name
other)
( Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ Name -> Name -> Q Exp -> Q Exp -> Q Exp
parseTypeMismatch Name
tName Name
conName
(Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL [Char]
expected)
([|valueConName|] Q Exp -> Q Exp -> Q Exp
`appE` Name -> Q Exp
varE Name
other)
)
[]
parseTypeMismatch :: Name -> Name -> ExpQ -> ExpQ -> ExpQ
parseTypeMismatch :: Name -> Name -> Q Exp -> Q Exp -> Q Exp
parseTypeMismatch tName :: Name
tName conName :: Name
conName expected :: Q Exp
expected actual :: Q Exp
actual =
(Q Exp -> Q Exp -> Q Exp) -> Q Exp -> [Q Exp] -> Q Exp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Q Exp -> Q Exp -> Q Exp
appE
[|parseTypeMismatch'|]
[ Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
nameBase Name
conName
, Lit -> Q Exp
litE (Lit -> Q Exp) -> Lit -> Q Exp
forall a b. (a -> b) -> a -> b
$ [Char] -> Lit
stringL ([Char] -> Lit) -> [Char] -> Lit
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
tName
, Q Exp
expected
, Q Exp
actual
]
class LookupField a where
lookupField :: (Value -> Parser a) -> String -> String
-> Object -> T.Text -> Parser a
instance OVERLAPPABLE_ LookupField a where
lookupField :: (Value -> Parser a)
-> [Char] -> [Char] -> Object -> Text -> Parser a
lookupField = (Value -> Parser a)
-> [Char] -> [Char] -> Object -> Text -> Parser a
forall a.
(Value -> Parser a)
-> [Char] -> [Char] -> Object -> Text -> Parser a
lookupFieldWith
instance INCOHERENT_ LookupField (Maybe a) where
lookupField :: (Value -> Parser (Maybe a))
-> [Char] -> [Char] -> Object -> Text -> Parser (Maybe a)
lookupField pj :: Value -> Parser (Maybe a)
pj _ _ = (Value -> Parser (Maybe a)) -> Object -> Text -> Parser (Maybe a)
forall a.
(Value -> Parser (Maybe a)) -> Object -> Text -> Parser (Maybe a)
parseOptionalFieldWith Value -> Parser (Maybe a)
pj
instance INCOHERENT_ LookupField (Semigroup.Option a) where
lookupField :: (Value -> Parser (Option a))
-> [Char] -> [Char] -> Object -> Text -> Parser (Option a)
lookupField pj :: Value -> Parser (Option a)
pj tName :: [Char]
tName rec :: [Char]
rec obj :: Object
obj key :: Text
key =
(Maybe a -> Option a) -> Parser (Maybe a) -> Parser (Option a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe a -> Option a
forall a. Maybe a -> Option a
Semigroup.Option
((Value -> Parser (Maybe a))
-> [Char] -> [Char] -> Object -> Text -> Parser (Maybe a)
forall a.
LookupField a =>
(Value -> Parser a)
-> [Char] -> [Char] -> Object -> Text -> Parser a
lookupField ((Option a -> Maybe a) -> Parser (Option a) -> Parser (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Option a -> Maybe a
forall a. Option a -> Maybe a
Semigroup.getOption (Parser (Option a) -> Parser (Maybe a))
-> (Value -> Parser (Option a)) -> Value -> Parser (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser (Option a)
pj) [Char]
tName [Char]
rec Object
obj Text
key)
lookupFieldWith :: (Value -> Parser a) -> String -> String
-> Object -> T.Text -> Parser a
lookupFieldWith :: (Value -> Parser a)
-> [Char] -> [Char] -> Object -> Text -> Parser a
lookupFieldWith pj :: Value -> Parser a
pj tName :: [Char]
tName rec :: [Char]
rec obj :: Object
obj key :: Text
key =
case Text -> Object -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
H.lookup Text
key Object
obj of
Nothing -> [Char] -> [Char] -> [Char] -> Parser a
forall fail. [Char] -> [Char] -> [Char] -> Parser fail
unknownFieldFail [Char]
tName [Char]
rec (Text -> [Char]
T.unpack Text
key)
Just v :: Value
v -> Value -> Parser a
pj Value
v Parser a -> JSONPathElement -> Parser a
forall a. Parser a -> JSONPathElement -> Parser a
<?> Text -> JSONPathElement
Key Text
key
unknownFieldFail :: String -> String -> String -> Parser fail
unknownFieldFail :: [Char] -> [Char] -> [Char] -> Parser fail
unknownFieldFail tName :: [Char]
tName rec :: [Char]
rec key :: [Char]
key =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing the record %s of type %s the key %s was not present."
[Char]
rec [Char]
tName [Char]
key
noArrayFail :: String -> String -> Parser fail
noArrayFail :: [Char] -> [Char] -> Parser fail
noArrayFail t :: [Char]
t o :: [Char]
o = [Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected Array but got %s." [Char]
t [Char]
o
noObjectFail :: String -> String -> Parser fail
noObjectFail :: [Char] -> [Char] -> Parser fail
noObjectFail t :: [Char]
t o :: [Char]
o = [Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected Object but got %s." [Char]
t [Char]
o
firstElemNoStringFail :: String -> String -> Parser fail
firstElemNoStringFail :: [Char] -> [Char] -> Parser fail
firstElemNoStringFail t :: [Char]
t o :: [Char]
o = [Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected an Array of 2 elements where the first element is a String but got %s at the first element." [Char]
t [Char]
o
wrongPairCountFail :: String -> String -> Parser fail
wrongPairCountFail :: [Char] -> [Char] -> Parser fail
wrongPairCountFail t :: [Char]
t n :: [Char]
n =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected an Object with a single tag/contents pair but got %s pairs."
[Char]
t [Char]
n
noStringFail :: String -> String -> Parser fail
noStringFail :: [Char] -> [Char] -> Parser fail
noStringFail t :: [Char]
t o :: [Char]
o = [Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected String but got %s." [Char]
t [Char]
o
noMatchFail :: String -> String -> Parser fail
noMatchFail :: [Char] -> [Char] -> Parser fail
noMatchFail t :: [Char]
t o :: [Char]
o =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected a String with the tag of a constructor but got %s." [Char]
t [Char]
o
not2ElemArray :: String -> Int -> Parser fail
not2ElemArray :: [Char] -> Int -> Parser fail
not2ElemArray t :: [Char]
t i :: Int
i = [Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> Int -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected an Array of 2 elements but got %i elements" [Char]
t Int
i
conNotFoundFail2ElemArray :: String -> [String] -> String -> Parser fail
conNotFoundFail2ElemArray :: [Char] -> [[Char]] -> [Char] -> Parser fail
conNotFoundFail2ElemArray t :: [Char]
t cs :: [[Char]]
cs o :: [Char]
o =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected a 2-element Array with a tag and contents element where the tag is one of [%s], but got %s."
[Char]
t ([Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate ", " [[Char]]
cs) [Char]
o
conNotFoundFailObjectSingleField :: String -> [String] -> String -> Parser fail
conNotFoundFailObjectSingleField :: [Char] -> [[Char]] -> [Char] -> Parser fail
conNotFoundFailObjectSingleField t :: [Char]
t cs :: [[Char]]
cs o :: [Char]
o =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected an Object with a single tag/contents pair where the tag is one of [%s], but got %s."
[Char]
t ([Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate ", " [[Char]]
cs) [Char]
o
conNotFoundFailTaggedObject :: String -> [String] -> String -> Parser fail
conNotFoundFailTaggedObject :: [Char] -> [[Char]] -> [Char] -> Parser fail
conNotFoundFailTaggedObject t :: [Char]
t cs :: [[Char]]
cs o :: [Char]
o =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing %s expected an Object with a tag field where the value is one of [%s], but got %s."
[Char]
t ([Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate ", " [[Char]]
cs) [Char]
o
parseTypeMismatch' :: String -> String -> String -> String -> Parser fail
parseTypeMismatch' :: [Char] -> [Char] -> [Char] -> [Char] -> Parser fail
parseTypeMismatch' conName :: [Char]
conName tName :: [Char]
tName expected :: [Char]
expected actual :: [Char]
actual =
[Char] -> Parser fail
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Parser fail) -> [Char] -> Parser fail
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf "When parsing the constructor %s of type %s expected %s but got %s."
[Char]
conName [Char]
tName [Char]
expected [Char]
actual
deriveJSONBoth :: (Options -> Name -> Q [Dec])
-> (Options -> Name -> Q [Dec])
-> Options
-> Name
-> Q [Dec]
deriveJSONBoth :: (Options -> Name -> Q [Dec])
-> (Options -> Name -> Q [Dec]) -> Options -> Name -> Q [Dec]
deriveJSONBoth dtj :: Options -> Name -> Q [Dec]
dtj dfj :: Options -> Name -> Q [Dec]
dfj opts :: Options
opts name :: Name
name =
([Dec] -> [Dec] -> [Dec]) -> Q [Dec] -> Q [Dec] -> Q [Dec]
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 [Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
(++) (Options -> Name -> Q [Dec]
dtj Options
opts Name
name) (Options -> Name -> Q [Dec]
dfj Options
opts Name
name)
deriveJSONClass :: [(JSONFun, JSONClass -> Name -> Options -> [Type]
-> [ConstructorInfo] -> Q Exp)]
-> JSONClass
-> Options
-> Name
-> Q [Dec]
deriveJSONClass :: [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> JSONClass -> Options -> Name -> Q [Dec]
deriveJSONClass consFuns :: [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
consFuns jc :: JSONClass
jc opts :: Options
opts name :: Name
name = do
DatatypeInfo
info <- Name -> Q DatatypeInfo
reifyDatatype Name
name
case DatatypeInfo
info of
DatatypeInfo { datatypeContext :: DatatypeInfo -> [Type]
datatypeContext = [Type]
ctxt
, datatypeName :: DatatypeInfo -> Name
datatypeName = Name
parentName
#if MIN_VERSION_th_abstraction(0,3,0)
, datatypeInstTypes :: DatatypeInfo -> [Type]
datatypeInstTypes = [Type]
instTys
#else
, datatypeVars = instTys
#endif
, datatypeVariant :: DatatypeInfo -> DatatypeVariant
datatypeVariant = DatatypeVariant
variant
, datatypeCons :: DatatypeInfo -> [ConstructorInfo]
datatypeCons = [ConstructorInfo]
cons
} -> do
(instanceCxt :: [Type]
instanceCxt, instanceType :: Type
instanceType)
<- Name
-> JSONClass
-> [Type]
-> [Type]
-> DatatypeVariant
-> Q ([Type], Type)
buildTypeInstance Name
parentName JSONClass
jc [Type]
ctxt [Type]
instTys DatatypeVariant
variant
(Dec -> [Dec] -> [Dec]
forall a. a -> [a] -> [a]
:[]) (Dec -> [Dec]) -> DecQ -> Q [Dec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Q [Type] -> Q Type -> [DecQ] -> DecQ
instanceD ([Type] -> Q [Type]
forall (m :: * -> *) a. Monad m => a -> m a
return [Type]
instanceCxt)
(Type -> Q Type
forall (m :: * -> *) a. Monad m => a -> m a
return Type
instanceType)
(Name -> [Type] -> [ConstructorInfo] -> [DecQ]
methodDecs Name
parentName [Type]
instTys [ConstructorInfo]
cons)
where
methodDecs :: Name -> [Type] -> [ConstructorInfo] -> [Q Dec]
methodDecs :: Name -> [Type] -> [ConstructorInfo] -> [DecQ]
methodDecs parentName :: Name
parentName instTys :: [Type]
instTys cons :: [ConstructorInfo]
cons = (((JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> DecQ)
-> [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> [DecQ])
-> [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> ((JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> DecQ)
-> [DecQ]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> DecQ)
-> [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
-> [DecQ]
forall a b. (a -> b) -> [a] -> [b]
map [(JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)]
consFuns (((JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> DecQ)
-> [DecQ])
-> ((JSONFun,
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> DecQ)
-> [DecQ]
forall a b. (a -> b) -> a -> b
$ \(jf :: JSONFun
jf, jfMaker :: JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
jfMaker) ->
Name -> [ClauseQ] -> DecQ
funD (JSONFun -> Arity -> Name
jsonFunValName JSONFun
jf (JSONClass -> Arity
arity JSONClass
jc))
[ [PatQ] -> BodyQ -> [DecQ] -> ClauseQ
clause []
(Q Exp -> BodyQ
normalB (Q Exp -> BodyQ) -> Q Exp -> BodyQ
forall a b. (a -> b) -> a -> b
$ JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
jfMaker JSONClass
jc Name
parentName Options
opts [Type]
instTys [ConstructorInfo]
cons)
[]
]
mkFunCommon :: (JSONClass -> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> JSONClass
-> Options
-> Name
-> Q Exp
mkFunCommon :: (JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
-> JSONClass -> Options -> Name -> Q Exp
mkFunCommon consFun :: JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consFun jc :: JSONClass
jc opts :: Options
opts name :: Name
name = do
DatatypeInfo
info <- Name -> Q DatatypeInfo
reifyDatatype Name
name
case DatatypeInfo
info of
DatatypeInfo { datatypeContext :: DatatypeInfo -> [Type]
datatypeContext = [Type]
ctxt
, datatypeName :: DatatypeInfo -> Name
datatypeName = Name
parentName
#if MIN_VERSION_th_abstraction(0,3,0)
, datatypeInstTypes :: DatatypeInfo -> [Type]
datatypeInstTypes = [Type]
instTys
#else
, datatypeVars = instTys
#endif
, datatypeVariant :: DatatypeInfo -> DatatypeVariant
datatypeVariant = DatatypeVariant
variant
, datatypeCons :: DatatypeInfo -> [ConstructorInfo]
datatypeCons = [ConstructorInfo]
cons
} -> do
!([Type], Type)
_ <- Name
-> JSONClass
-> [Type]
-> [Type]
-> DatatypeVariant
-> Q ([Type], Type)
buildTypeInstance Name
parentName JSONClass
jc [Type]
ctxt [Type]
instTys DatatypeVariant
variant
JSONClass
-> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp
consFun JSONClass
jc Name
parentName Options
opts [Type]
instTys [ConstructorInfo]
cons
dispatchFunByType :: JSONClass
-> JSONFun
-> Name
-> TyVarMap
-> Bool
-> Type
-> Q Exp
dispatchFunByType :: JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType _ jf :: JSONFun
jf _ tvMap :: Map Name (Name, Name)
tvMap list :: Bool
list (VarT tyName :: Name
tyName) =
Name -> Q Exp
varE (Name -> Q Exp) -> Name -> Q Exp
forall a b. (a -> b) -> a -> b
$ case Name -> Map Name (Name, Name) -> Maybe (Name, Name)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Name
tyName Map Name (Name, Name)
tvMap of
Just (tfjExp :: Name
tfjExp, tfjlExp :: Name
tfjlExp) -> if Bool
list then Name
tfjlExp else Name
tfjExp
Nothing -> Bool -> JSONFun -> Arity -> Name
jsonFunValOrListName Bool
list JSONFun
jf Arity
Arity0
dispatchFunByType jc :: JSONClass
jc jf :: JSONFun
jf conName :: Name
conName tvMap :: Map Name (Name, Name)
tvMap list :: Bool
list (SigT ty :: Type
ty _) =
JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType JSONClass
jc JSONFun
jf Name
conName Map Name (Name, Name)
tvMap Bool
list Type
ty
dispatchFunByType jc :: JSONClass
jc jf :: JSONFun
jf conName :: Name
conName tvMap :: Map Name (Name, Name)
tvMap list :: Bool
list (ForallT _ _ ty :: Type
ty) =
JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType JSONClass
jc JSONFun
jf Name
conName Map Name (Name, Name)
tvMap Bool
list Type
ty
dispatchFunByType jc :: JSONClass
jc jf :: JSONFun
jf conName :: Name
conName tvMap :: Map Name (Name, Name)
tvMap list :: Bool
list ty :: Type
ty = do
let tyCon :: Type
tyArgs :: [Type]
tyCon :: Type
tyCon :| tyArgs :: [Type]
tyArgs = Type -> NonEmpty Type
unapplyTy Type
ty
numLastArgs :: Int
numLastArgs :: Int
numLastArgs = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (JSONClass -> Int
arityInt JSONClass
jc) ([Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
tyArgs)
lhsArgs, rhsArgs :: [Type]
(lhsArgs :: [Type]
lhsArgs, rhsArgs :: [Type]
rhsArgs) = Int -> [Type] -> ([Type], [Type])
forall a. Int -> [a] -> ([a], [a])
splitAt ([Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
tyArgs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
numLastArgs) [Type]
tyArgs
tyVarNames :: [Name]
tyVarNames :: [Name]
tyVarNames = Map Name (Name, Name) -> [Name]
forall k a. Map k a -> [k]
M.keys Map Name (Name, Name)
tvMap
Bool
itf <- Type -> Q Bool
isTyFamily Type
tyCon
if (Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`mentionsName` [Name]
tyVarNames) [Type]
lhsArgs
Bool -> Bool -> Bool
|| Bool
itf Bool -> Bool -> Bool
&& (Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`mentionsName` [Name]
tyVarNames) [Type]
tyArgs
then JSONClass -> Name -> Q Exp
forall a. JSONClass -> Name -> a
outOfPlaceTyVarError JSONClass
jc Name
conName
else if (Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`mentionsName` [Name]
tyVarNames) [Type]
rhsArgs
then [Q Exp] -> Q Exp
appsE ([Q Exp] -> Q Exp) -> [Q Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Q Exp
varE (Bool -> JSONFun -> Arity -> Name
jsonFunValOrListName Bool
list JSONFun
jf (Arity -> Name) -> Arity -> Name
forall a b. (a -> b) -> a -> b
$ Int -> Arity
forall a. Enum a => Int -> a
toEnum Int
numLastArgs)
Q Exp -> [Q Exp] -> [Q Exp]
forall a. a -> [a] -> [a]
: (Bool -> Type -> Q Exp) -> [Bool] -> [Type] -> [Q Exp]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType JSONClass
jc JSONFun
jf Name
conName Map Name (Name, Name)
tvMap)
([Bool] -> [Bool]
forall a. [a] -> [a]
cycle [Bool
False,Bool
True])
([Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
interleave [Type]
rhsArgs [Type]
rhsArgs)
else Name -> Q Exp
varE (Name -> Q Exp) -> Name -> Q Exp
forall a b. (a -> b) -> a -> b
$ Bool -> JSONFun -> Arity -> Name
jsonFunValOrListName Bool
list JSONFun
jf Arity
Arity0
dispatchToJSON
:: ToJSONFun -> JSONClass -> Name -> TyVarMap -> Type -> Q Exp
dispatchToJSON :: ToJSONFun
-> JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchToJSON target :: ToJSONFun
target jc :: JSONClass
jc n :: Name
n tvMap :: Map Name (Name, Name)
tvMap =
JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType JSONClass
jc (ToJSONFun -> JSONFun
targetToJSONFun ToJSONFun
target) Name
n Map Name (Name, Name)
tvMap Bool
False
dispatchParseJSON
:: JSONClass -> Name -> TyVarMap -> Type -> Q Exp
dispatchParseJSON :: JSONClass -> Name -> Map Name (Name, Name) -> Type -> Q Exp
dispatchParseJSON jc :: JSONClass
jc n :: Name
n tvMap :: Map Name (Name, Name)
tvMap = JSONClass
-> JSONFun
-> Name
-> Map Name (Name, Name)
-> Bool
-> Type
-> Q Exp
dispatchFunByType JSONClass
jc JSONFun
ParseJSON Name
n Map Name (Name, Name)
tvMap Bool
False
buildTypeInstance :: Name
-> JSONClass
-> Cxt
-> [Type]
-> DatatypeVariant
-> Q (Cxt, Type)
buildTypeInstance :: Name
-> JSONClass
-> [Type]
-> [Type]
-> DatatypeVariant
-> Q ([Type], Type)
buildTypeInstance tyConName :: Name
tyConName jc :: JSONClass
jc dataCxt :: [Type]
dataCxt varTysOrig :: [Type]
varTysOrig variant :: DatatypeVariant
variant = do
[Type]
varTysExp <- (Type -> Q Type) -> [Type] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
varTysOrig
let remainingLength :: Int
remainingLength :: Int
remainingLength = [Type] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
varTysOrig Int -> Int -> Int
forall a. Num a => a -> a -> a
- JSONClass -> Int
arityInt JSONClass
jc
droppedTysExp :: [Type]
droppedTysExp :: [Type]
droppedTysExp = Int -> [Type] -> [Type]
forall a. Int -> [a] -> [a]
drop Int
remainingLength [Type]
varTysExp
droppedStarKindStati :: [StarKindStatus]
droppedStarKindStati :: [StarKindStatus]
droppedStarKindStati = (Type -> StarKindStatus) -> [Type] -> [StarKindStatus]
forall a b. (a -> b) -> [a] -> [b]
map Type -> StarKindStatus
canRealizeKindStar [Type]
droppedTysExp
Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
remainingLength Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 0 Bool -> Bool -> Bool
|| StarKindStatus -> [StarKindStatus] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem StarKindStatus
NotKindStar [StarKindStatus]
droppedStarKindStati) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$
JSONClass -> Name -> Q ()
forall a. JSONClass -> Name -> Q a
derivingKindError JSONClass
jc Name
tyConName
let droppedKindVarNames :: [Name]
droppedKindVarNames :: [Name]
droppedKindVarNames = [StarKindStatus] -> [Name]
catKindVarNames [StarKindStatus]
droppedStarKindStati
varTysExpSubst :: [Type]
varTysExpSubst :: [Type]
varTysExpSubst = (Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar [Name]
droppedKindVarNames) [Type]
varTysExp
remainingTysExpSubst, droppedTysExpSubst :: [Type]
(remainingTysExpSubst :: [Type]
remainingTysExpSubst, droppedTysExpSubst :: [Type]
droppedTysExpSubst) =
Int -> [Type] -> ([Type], [Type])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
remainingLength [Type]
varTysExpSubst
droppedTyVarNames :: [Name]
droppedTyVarNames :: [Name]
droppedTyVarNames = [Type] -> [Name]
forall a. TypeSubstitution a => a -> [Name]
freeVariables [Type]
droppedTysExpSubst
Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
hasKindStar [Type]
droppedTysExpSubst) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$
JSONClass -> Name -> Q ()
forall a. JSONClass -> Name -> Q a
derivingKindError JSONClass
jc Name
tyConName
let preds :: [Maybe Pred]
kvNames :: [[Name]]
kvNames' :: [Name]
(preds :: [Maybe Type]
preds, kvNames :: [[Name]]
kvNames) = [(Maybe Type, [Name])] -> ([Maybe Type], [[Name]])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Maybe Type, [Name])] -> ([Maybe Type], [[Name]]))
-> [(Maybe Type, [Name])] -> ([Maybe Type], [[Name]])
forall a b. (a -> b) -> a -> b
$ (Type -> (Maybe Type, [Name])) -> [Type] -> [(Maybe Type, [Name])]
forall a b. (a -> b) -> [a] -> [b]
map (JSONClass -> Type -> (Maybe Type, [Name])
deriveConstraint JSONClass
jc) [Type]
remainingTysExpSubst
kvNames' :: [Name]
kvNames' = [[Name]] -> [Name]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Name]]
kvNames
remainingTysExpSubst' :: [Type]
remainingTysExpSubst' :: [Type]
remainingTysExpSubst' =
(Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar [Name]
kvNames') [Type]
remainingTysExpSubst
remainingTysOrigSubst :: [Type]
remainingTysOrigSubst :: [Type]
remainingTysOrigSubst =
(Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar ([Name]
droppedKindVarNames [Name] -> [Name] -> [Name]
forall a. Eq a => [a] -> [a] -> [a]
`union` [Name]
kvNames'))
([Type] -> [Type]) -> [Type] -> [Type]
forall a b. (a -> b) -> a -> b
$ Int -> [Type] -> [Type]
forall a. Int -> [a] -> [a]
take Int
remainingLength [Type]
varTysOrig
isDataFamily :: Bool
isDataFamily :: Bool
isDataFamily = case DatatypeVariant
variant of
Datatype -> Bool
False
Newtype -> Bool
False
DataInstance -> Bool
True
NewtypeInstance -> Bool
True
remainingTysOrigSubst' :: [Type]
remainingTysOrigSubst' :: [Type]
remainingTysOrigSubst' =
if Bool
isDataFamily
then [Type]
remainingTysOrigSubst
else (Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Type
unSigT [Type]
remainingTysOrigSubst
instanceCxt :: Cxt
instanceCxt :: [Type]
instanceCxt = [Maybe Type] -> [Type]
forall a. [Maybe a] -> [a]
catMaybes [Maybe Type]
preds
instanceType :: Type
instanceType :: Type
instanceType = Type -> Type -> Type
AppT (Name -> Type
ConT (Name -> Type) -> Name -> Type
forall a b. (a -> b) -> a -> b
$ JSONClass -> Name
jsonClassName JSONClass
jc)
(Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ Name -> [Type] -> Type
applyTyCon Name
tyConName [Type]
remainingTysOrigSubst'
Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`predMentionsName` [Name]
droppedTyVarNames) [Type]
dataCxt) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$
Name -> Type -> Q ()
forall a. Name -> Type -> Q a
datatypeContextError Name
tyConName Type
instanceType
Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Type] -> [Type] -> Bool
canEtaReduce [Type]
remainingTysExpSubst' [Type]
droppedTysExpSubst) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$
Type -> Q ()
forall a. Type -> Q a
etaReductionError Type
instanceType
([Type], Type) -> Q ([Type], Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type]
instanceCxt, Type
instanceType)
deriveConstraint :: JSONClass -> Type -> (Maybe Pred, [Name])
deriveConstraint :: JSONClass -> Type -> (Maybe Type, [Name])
deriveConstraint jc :: JSONClass
jc t :: Type
t
| Bool -> Bool
not (Type -> Bool
isTyVar Type
t) = (Maybe Type
forall a. Maybe a
Nothing, [])
| Type -> Bool
hasKindStar Type
t = (Type -> Maybe Type
forall a. a -> Maybe a
Just (Name -> Name -> Type
applyCon (Arity -> Name
jcConstraint Arity
Arity0) Name
tName), [])
| Bool
otherwise = case Int -> Type -> Maybe [Name]
hasKindVarChain 1 Type
t of
Just ns :: [Name]
ns | Arity
jcArity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
>= Arity
Arity1
-> (Type -> Maybe Type
forall a. a -> Maybe a
Just (Name -> Name -> Type
applyCon (Arity -> Name
jcConstraint Arity
Arity1) Name
tName), [Name]
ns)
_ -> case Int -> Type -> Maybe [Name]
hasKindVarChain 2 Type
t of
Just ns :: [Name]
ns | Arity
jcArity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
Arity2
-> (Type -> Maybe Type
forall a. a -> Maybe a
Just (Name -> Name -> Type
applyCon (Arity -> Name
jcConstraint Arity
Arity2) Name
tName), [Name]
ns)
_ -> (Maybe Type
forall a. Maybe a
Nothing, [])
where
tName :: Name
tName :: Name
tName = Type -> Name
varTToName Type
t
jcArity :: Arity
jcArity :: Arity
jcArity = JSONClass -> Arity
arity JSONClass
jc
jcConstraint :: Arity -> Name
jcConstraint :: Arity -> Name
jcConstraint = JSONClass -> Name
jsonClassName (JSONClass -> Name) -> (Arity -> JSONClass) -> Arity -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Direction -> Arity -> JSONClass
JSONClass (JSONClass -> Direction
direction JSONClass
jc)
checkExistentialContext :: JSONClass -> TyVarMap -> Cxt -> Name
-> Q a -> Q a
checkExistentialContext :: JSONClass -> Map Name (Name, Name) -> [Type] -> Name -> Q a -> Q a
checkExistentialContext jc :: JSONClass
jc tvMap :: Map Name (Name, Name)
tvMap ctxt :: [Type]
ctxt conName :: Name
conName q :: Q a
q =
if ((Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`predMentionsName` Map Name (Name, Name) -> [Name]
forall k a. Map k a -> [k]
M.keys Map Name (Name, Name)
tvMap) [Type]
ctxt
Bool -> Bool -> Bool
|| Map Name (Name, Name) -> Int
forall k a. Map k a -> Int
M.size Map Name (Name, Name)
tvMap Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< JSONClass -> Int
arityInt JSONClass
jc)
Bool -> Bool -> Bool
&& Bool -> Bool
not (JSONClass -> Bool
allowExQuant JSONClass
jc)
then Name -> Q a
forall a. Name -> a
existentialContextError Name
conName
else Q a
q
type TyVarMap = Map Name (Name, Name)
hasKindStar :: Type -> Bool
hasKindStar :: Type -> Bool
hasKindStar VarT{} = Bool
True
#if MIN_VERSION_template_haskell(2,8,0)
hasKindStar (SigT _ StarT) = Bool
True
#else
hasKindStar (SigT _ StarK) = True
#endif
hasKindStar _ = Bool
False
isStarOrVar :: Kind -> Bool
#if MIN_VERSION_template_haskell(2,8,0)
isStarOrVar :: Type -> Bool
isStarOrVar StarT = Bool
True
isStarOrVar VarT{} = Bool
True
#else
isStarOrVar StarK = True
#endif
isStarOrVar _ = Bool
False
newNameList :: String -> Int -> Q [Name]
newNameList :: [Char] -> Int -> Q [Name]
newNameList prefix :: [Char]
prefix len :: Int
len = ([Char] -> Q Name) -> [[Char]] -> Q [Name]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM [Char] -> Q Name
newName [[Char]
prefix [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n | Int
n <- [1..Int
len]]
hasKindVarChain :: Int -> Type -> Maybe [Name]
hasKindVarChain :: Int -> Type -> Maybe [Name]
hasKindVarChain kindArrows :: Int
kindArrows t :: Type
t =
let uk :: NonEmpty Type
uk = Type -> NonEmpty Type
uncurryKind (Type -> Type
tyKind Type
t)
in if (NonEmpty Type -> Int
forall a. NonEmpty a -> Int
NE.length NonEmpty Type
uk Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
kindArrows) Bool -> Bool -> Bool
&& (Type -> Bool) -> NonEmpty Type -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
F.all Type -> Bool
isStarOrVar NonEmpty Type
uk
then [Name] -> Maybe [Name]
forall a. a -> Maybe a
Just ((Type -> [Name]) -> NonEmpty Type -> [Name]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Type -> [Name]
forall a. TypeSubstitution a => a -> [Name]
freeVariables NonEmpty Type
uk)
else Maybe [Name]
forall a. Maybe a
Nothing
tyKind :: Type -> Kind
tyKind :: Type -> Type
tyKind (SigT _ k :: Type
k) = Type
k
tyKind _ = Type
starK
varTToNameMaybe :: Type -> Maybe Name
varTToNameMaybe :: Type -> Maybe Name
varTToNameMaybe (VarT n :: Name
n) = Name -> Maybe Name
forall a. a -> Maybe a
Just Name
n
varTToNameMaybe (SigT t :: Type
t _) = Type -> Maybe Name
varTToNameMaybe Type
t
varTToNameMaybe _ = Maybe Name
forall a. Maybe a
Nothing
varTToName :: Type -> Name
varTToName :: Type -> Name
varTToName = Name -> Maybe Name -> Name
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> Name
forall a. HasCallStack => [Char] -> a
error "Not a type variable!") (Maybe Name -> Name) -> (Type -> Maybe Name) -> Type -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> Maybe Name
varTToNameMaybe
interleave :: [a] -> [a] -> [a]
interleave :: [a] -> [a] -> [a]
interleave (a1 :: a
a1:a1s :: [a]
a1s) (a2 :: a
a2:a2s :: [a]
a2s) = a
a1a -> [a] -> [a]
forall a. a -> [a] -> [a]
:a
a2a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
interleave [a]
a1s [a]
a2s
interleave _ _ = []
applyTyCon :: Name -> [Type] -> Type
applyTyCon :: Name -> [Type] -> Type
applyTyCon = (Type -> Type -> Type) -> Type -> [Type] -> Type
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Type -> Type -> Type
AppT (Type -> [Type] -> Type)
-> (Name -> Type) -> Name -> [Type] -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Type
ConT
isTyVar :: Type -> Bool
isTyVar :: Type -> Bool
isTyVar (VarT _) = Bool
True
isTyVar (SigT t :: Type
t _) = Type -> Bool
isTyVar Type
t
isTyVar _ = Bool
False
isTyFamily :: Type -> Q Bool
isTyFamily :: Type -> Q Bool
isTyFamily (ConT n :: Name
n) = do
Info
info <- Name -> Q Info
reify Name
n
Bool -> Q Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Q Bool) -> Bool -> Q Bool
forall a b. (a -> b) -> a -> b
$ case Info
info of
#if MIN_VERSION_template_haskell(2,11,0)
FamilyI OpenTypeFamilyD{} _ -> Bool
True
#else
FamilyI (FamilyD TypeFam _ _ _) _ -> True
#endif
#if MIN_VERSION_template_haskell(2,9,0)
FamilyI ClosedTypeFamilyD{} _ -> Bool
True
#endif
_ -> Bool
False
isTyFamily _ = Bool -> Q Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
unSigT :: Type -> Type
unSigT :: Type -> Type
unSigT (SigT t :: Type
t _) = Type
t
unSigT t :: Type
t = Type
t
allDistinct :: Ord a => [a] -> Bool
allDistinct :: [a] -> Bool
allDistinct = Set a -> [a] -> Bool
forall a. Ord a => Set a -> [a] -> Bool
allDistinct' Set a
forall a. Set a
Set.empty
where
allDistinct' :: Ord a => Set a -> [a] -> Bool
allDistinct' :: Set a -> [a] -> Bool
allDistinct' uniqs :: Set a
uniqs (x :: a
x:xs :: [a]
xs)
| a
x a -> Set a -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set a
uniqs = Bool
False
| Bool
otherwise = Set a -> [a] -> Bool
forall a. Ord a => Set a -> [a] -> Bool
allDistinct' (a -> Set a -> Set a
forall a. Ord a => a -> Set a -> Set a
Set.insert a
x Set a
uniqs) [a]
xs
allDistinct' _ _ = Bool
True
mentionsName :: Type -> [Name] -> Bool
mentionsName :: Type -> [Name] -> Bool
mentionsName = Type -> [Name] -> Bool
go
where
go :: Type -> [Name] -> Bool
go :: Type -> [Name] -> Bool
go (AppT t1 :: Type
t1 t2 :: Type
t2) names :: [Name]
names = Type -> [Name] -> Bool
go Type
t1 [Name]
names Bool -> Bool -> Bool
|| Type -> [Name] -> Bool
go Type
t2 [Name]
names
go (SigT t :: Type
t _k :: Type
_k) names :: [Name]
names = Type -> [Name] -> Bool
go Type
t [Name]
names
#if MIN_VERSION_template_haskell(2,8,0)
Bool -> Bool -> Bool
|| Type -> [Name] -> Bool
go Type
_k [Name]
names
#endif
go (VarT n :: Name
n) names :: [Name]
names = Name
n Name -> [Name] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Name]
names
go _ _ = Bool
False
predMentionsName :: Pred -> [Name] -> Bool
#if MIN_VERSION_template_haskell(2,10,0)
predMentionsName :: Type -> [Name] -> Bool
predMentionsName = Type -> [Name] -> Bool
mentionsName
#else
predMentionsName (ClassP n tys) names = n `elem` names || any (`mentionsName` names) tys
predMentionsName (EqualP t1 t2) names = mentionsName t1 names || mentionsName t2 names
#endif
unapplyTy :: Type -> NonEmpty Type
unapplyTy :: Type -> NonEmpty Type
unapplyTy = NonEmpty Type -> NonEmpty Type
forall a. NonEmpty a -> NonEmpty a
NE.reverse (NonEmpty Type -> NonEmpty Type)
-> (Type -> NonEmpty Type) -> Type -> NonEmpty Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> NonEmpty Type
go
where
go :: Type -> NonEmpty Type
go :: Type -> NonEmpty Type
go (AppT t1 :: Type
t1 t2 :: Type
t2) = Type
t2 Type -> NonEmpty Type -> NonEmpty Type
forall a. a -> NonEmpty a -> NonEmpty a
<| Type -> NonEmpty Type
go Type
t1
go (SigT t :: Type
t _) = Type -> NonEmpty Type
go Type
t
go (ForallT _ _ t :: Type
t) = Type -> NonEmpty Type
go Type
t
go t :: Type
t = Type
t Type -> [Type] -> NonEmpty Type
forall a. a -> [a] -> NonEmpty a
:| []
uncurryTy :: Type -> (Cxt, NonEmpty Type)
uncurryTy :: Type -> ([Type], NonEmpty Type)
uncurryTy (AppT (AppT ArrowT t1 :: Type
t1) t2 :: Type
t2) =
let (ctxt :: [Type]
ctxt, tys :: NonEmpty Type
tys) = Type -> ([Type], NonEmpty Type)
uncurryTy Type
t2
in ([Type]
ctxt, Type
t1 Type -> NonEmpty Type -> NonEmpty Type
forall a. a -> NonEmpty a -> NonEmpty a
<| NonEmpty Type
tys)
uncurryTy (SigT t :: Type
t _) = Type -> ([Type], NonEmpty Type)
uncurryTy Type
t
uncurryTy (ForallT _ ctxt :: [Type]
ctxt t :: Type
t) =
let (ctxt' :: [Type]
ctxt', tys :: NonEmpty Type
tys) = Type -> ([Type], NonEmpty Type)
uncurryTy Type
t
in ([Type]
ctxt [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Type]
ctxt', NonEmpty Type
tys)
uncurryTy t :: Type
t = ([], Type
t Type -> [Type] -> NonEmpty Type
forall a. a -> [a] -> NonEmpty a
:| [])
uncurryKind :: Kind -> NonEmpty Kind
#if MIN_VERSION_template_haskell(2,8,0)
uncurryKind :: Type -> NonEmpty Type
uncurryKind = ([Type], NonEmpty Type) -> NonEmpty Type
forall a b. (a, b) -> b
snd (([Type], NonEmpty Type) -> NonEmpty Type)
-> (Type -> ([Type], NonEmpty Type)) -> Type -> NonEmpty Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> ([Type], NonEmpty Type)
uncurryTy
#else
uncurryKind (ArrowK k1 k2) = k1 <| uncurryKind k2
uncurryKind k = k :| []
#endif
createKindChain :: Int -> Kind
createKindChain :: Int -> Type
createKindChain = Type -> Int -> Type
go Type
starK
where
go :: Kind -> Int -> Kind
go :: Type -> Int -> Type
go k :: Type
k 0 = Type
k
#if MIN_VERSION_template_haskell(2,8,0)
go k :: Type
k !Int
n = Type -> Int -> Type
go (Type -> Type -> Type
AppT (Type -> Type -> Type
AppT Type
ArrowT Type
StarT) Type
k) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1)
#else
go k !n = go (ArrowK StarK k) (n - 1)
#endif
conNameExp :: Options -> ConstructorInfo -> Q Exp
conNameExp :: Options -> ConstructorInfo -> Q Exp
conNameExp opts :: Options
opts = Lit -> Q Exp
litE
(Lit -> Q Exp)
-> (ConstructorInfo -> Lit) -> ConstructorInfo -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Lit
stringL
([Char] -> Lit)
-> (ConstructorInfo -> [Char]) -> ConstructorInfo -> Lit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options -> [Char] -> [Char]
constructorTagModifier Options
opts
([Char] -> [Char])
-> (ConstructorInfo -> [Char]) -> ConstructorInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> [Char]
nameBase
(Name -> [Char])
-> (ConstructorInfo -> Name) -> ConstructorInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConstructorInfo -> Name
constructorName
fieldLabel :: Options
-> Name
-> String
fieldLabel :: Options -> Name -> [Char]
fieldLabel opts :: Options
opts = Options -> [Char] -> [Char]
fieldLabelModifier Options
opts ([Char] -> [Char]) -> (Name -> [Char]) -> Name -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> [Char]
nameBase
valueConName :: Value -> String
valueConName :: Value -> [Char]
valueConName (Object _) = "Object"
valueConName (Array _) = "Array"
valueConName (String _) = "String"
valueConName (Number _) = "Number"
valueConName (Bool _) = "Boolean"
valueConName Null = "Null"
applyCon :: Name -> Name -> Pred
applyCon :: Name -> Name -> Type
applyCon con :: Name
con t :: Name
t =
#if MIN_VERSION_template_haskell(2,10,0)
Type -> Type -> Type
AppT (Name -> Type
ConT Name
con) (Name -> Type
VarT Name
t)
#else
ClassP con [VarT t]
#endif
canEtaReduce :: [Type] -> [Type] -> Bool
canEtaReduce :: [Type] -> [Type] -> Bool
canEtaReduce remaining :: [Type]
remaining dropped :: [Type]
dropped =
(Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
isTyVar [Type]
dropped
Bool -> Bool -> Bool
&& [Name] -> Bool
forall a. Ord a => [a] -> Bool
allDistinct [Name]
droppedNames
Bool -> Bool -> Bool
&& Bool -> Bool
not ((Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`mentionsName` [Name]
droppedNames) [Type]
remaining)
where
droppedNames :: [Name]
droppedNames :: [Name]
droppedNames = (Type -> Name) -> [Type] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Name
varTToName [Type]
dropped
applySubstitutionKind :: Map Name Kind -> Type -> Type
#if MIN_VERSION_template_haskell(2,8,0)
applySubstitutionKind :: Map Name Type -> Type -> Type
applySubstitutionKind = Map Name Type -> Type -> Type
forall a. TypeSubstitution a => Map Name Type -> a -> a
applySubstitution
#else
applySubstitutionKind _ t = t
#endif
substNameWithKind :: Name -> Kind -> Type -> Type
substNameWithKind :: Name -> Type -> Type -> Type
substNameWithKind n :: Name
n k :: Type
k = Map Name Type -> Type -> Type
applySubstitutionKind (Name -> Type -> Map Name Type
forall k a. k -> a -> Map k a
M.singleton Name
n Type
k)
substNamesWithKindStar :: [Name] -> Type -> Type
substNamesWithKindStar :: [Name] -> Type -> Type
substNamesWithKindStar ns :: [Name]
ns t :: Type
t = (Name -> Type -> Type) -> Type -> [Name] -> Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr' (Name -> Type -> Type -> Type
`substNameWithKind` Type
starK) Type
t [Name]
ns
derivingKindError :: JSONClass -> Name -> Q a
derivingKindError :: JSONClass -> Name -> Q a
derivingKindError jc :: JSONClass
jc tyConName :: Name
tyConName = [Char] -> Q a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail
([Char] -> Q a) -> ([Char] -> [Char]) -> [Char] -> Q a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "Cannot derive well-kinded instance of form ‘"
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString [Char]
className
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> [Char] -> [Char]
showChar ' '
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> ([Char] -> [Char]) -> [Char] -> [Char]
showParen Bool
True
( [Char] -> [Char] -> [Char]
showString (Name -> [Char]
nameBase Name
tyConName)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString " ..."
)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "‘\n\tClass "
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString [Char]
className
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString " expects an argument of kind "
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString (Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint (Type -> [Char]) -> (Int -> Type) -> Int -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Type
createKindChain (Int -> [Char]) -> Int -> [Char]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Int
arityInt JSONClass
jc)
([Char] -> Q a) -> [Char] -> Q a
forall a b. (a -> b) -> a -> b
$ ""
where
className :: String
className :: [Char]
className = Name -> [Char]
nameBase (Name -> [Char]) -> Name -> [Char]
forall a b. (a -> b) -> a -> b
$ JSONClass -> Name
jsonClassName JSONClass
jc
etaReductionError :: Type -> Q a
etaReductionError :: Type -> Q a
etaReductionError instanceType :: Type
instanceType = [Char] -> Q a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> Q a) -> [Char] -> Q a
forall a b. (a -> b) -> a -> b
$
"Cannot eta-reduce to an instance of form \n\tinstance (...) => "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
instanceType
datatypeContextError :: Name -> Type -> Q a
datatypeContextError :: Name -> Type -> Q a
datatypeContextError dataName :: Name
dataName instanceType :: Type
instanceType = [Char] -> Q a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail
([Char] -> Q a) -> ([Char] -> [Char]) -> [Char] -> Q a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "Can't make a derived instance of ‘"
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString (Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
instanceType)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "‘:\n\tData type ‘"
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString (Name -> [Char]
nameBase Name
dataName)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "‘ must not have a class context involving the last type argument(s)"
([Char] -> Q a) -> [Char] -> Q a
forall a b. (a -> b) -> a -> b
$ ""
outOfPlaceTyVarError :: JSONClass -> Name -> a
outOfPlaceTyVarError :: JSONClass -> Name -> a
outOfPlaceTyVarError jc :: JSONClass
jc conName :: Name
conName = [Char] -> a
forall a. HasCallStack => [Char] -> a
error
([Char] -> a) -> ([Char] -> [Char]) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "Constructor ‘"
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString (Name -> [Char]
nameBase Name
conName)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "‘ must only use its last "
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Char] -> [Char]
forall a. Show a => a -> [Char] -> [Char]
shows Int
n
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString " type variable(s) within the last "
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Char] -> [Char]
forall a. Show a => a -> [Char] -> [Char]
shows Int
n
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString " argument(s) of a data type"
([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ ""
where
n :: Int
n :: Int
n = JSONClass -> Int
arityInt JSONClass
jc
existentialContextError :: Name -> a
existentialContextError :: Name -> a
existentialContextError conName :: Name
conName = [Char] -> a
forall a. HasCallStack => [Char] -> a
error
([Char] -> a) -> ([Char] -> [Char]) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "Constructor ‘"
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString (Name -> [Char]
nameBase Name
conName)
([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString "‘ must be truly polymorphic in the last argument(s) of the data type"
([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ ""
data Arity = Arity0 | Arity1 | Arity2
deriving (Int -> Arity
Arity -> Int
Arity -> [Arity]
Arity -> Arity
Arity -> Arity -> [Arity]
Arity -> Arity -> Arity -> [Arity]
(Arity -> Arity)
-> (Arity -> Arity)
-> (Int -> Arity)
-> (Arity -> Int)
-> (Arity -> [Arity])
-> (Arity -> Arity -> [Arity])
-> (Arity -> Arity -> [Arity])
-> (Arity -> Arity -> Arity -> [Arity])
-> Enum Arity
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Arity -> Arity -> Arity -> [Arity]
$cenumFromThenTo :: Arity -> Arity -> Arity -> [Arity]
enumFromTo :: Arity -> Arity -> [Arity]
$cenumFromTo :: Arity -> Arity -> [Arity]
enumFromThen :: Arity -> Arity -> [Arity]
$cenumFromThen :: Arity -> Arity -> [Arity]
enumFrom :: Arity -> [Arity]
$cenumFrom :: Arity -> [Arity]
fromEnum :: Arity -> Int
$cfromEnum :: Arity -> Int
toEnum :: Int -> Arity
$ctoEnum :: Int -> Arity
pred :: Arity -> Arity
$cpred :: Arity -> Arity
succ :: Arity -> Arity
$csucc :: Arity -> Arity
Enum, Arity -> Arity -> Bool
(Arity -> Arity -> Bool) -> (Arity -> Arity -> Bool) -> Eq Arity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Arity -> Arity -> Bool
$c/= :: Arity -> Arity -> Bool
== :: Arity -> Arity -> Bool
$c== :: Arity -> Arity -> Bool
Eq, Eq Arity
Eq Arity =>
(Arity -> Arity -> Ordering)
-> (Arity -> Arity -> Bool)
-> (Arity -> Arity -> Bool)
-> (Arity -> Arity -> Bool)
-> (Arity -> Arity -> Bool)
-> (Arity -> Arity -> Arity)
-> (Arity -> Arity -> Arity)
-> Ord Arity
Arity -> Arity -> Bool
Arity -> Arity -> Ordering
Arity -> Arity -> Arity
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Arity -> Arity -> Arity
$cmin :: Arity -> Arity -> Arity
max :: Arity -> Arity -> Arity
$cmax :: Arity -> Arity -> Arity
>= :: Arity -> Arity -> Bool
$c>= :: Arity -> Arity -> Bool
> :: Arity -> Arity -> Bool
$c> :: Arity -> Arity -> Bool
<= :: Arity -> Arity -> Bool
$c<= :: Arity -> Arity -> Bool
< :: Arity -> Arity -> Bool
$c< :: Arity -> Arity -> Bool
compare :: Arity -> Arity -> Ordering
$ccompare :: Arity -> Arity -> Ordering
$cp1Ord :: Eq Arity
Ord)
data Direction = To | From
data JSONFun = ToJSON | ToEncoding | ParseJSON
data ToJSONFun = Value | Encoding
targetToJSONFun :: ToJSONFun -> JSONFun
targetToJSONFun :: ToJSONFun -> JSONFun
targetToJSONFun Value = JSONFun
ToJSON
targetToJSONFun Encoding = JSONFun
ToEncoding
data JSONClass = JSONClass { JSONClass -> Direction
direction :: Direction, JSONClass -> Arity
arity :: Arity }
toJSONClass, toJSON1Class, toJSON2Class,
fromJSONClass, fromJSON1Class, fromJSON2Class :: JSONClass
toJSONClass :: JSONClass
toJSONClass = Direction -> Arity -> JSONClass
JSONClass Direction
To Arity
Arity0
toJSON1Class :: JSONClass
toJSON1Class = Direction -> Arity -> JSONClass
JSONClass Direction
To Arity
Arity1
toJSON2Class :: JSONClass
toJSON2Class = Direction -> Arity -> JSONClass
JSONClass Direction
To Arity
Arity2
fromJSONClass :: JSONClass
fromJSONClass = Direction -> Arity -> JSONClass
JSONClass Direction
From Arity
Arity0
fromJSON1Class :: JSONClass
fromJSON1Class = Direction -> Arity -> JSONClass
JSONClass Direction
From Arity
Arity1
fromJSON2Class :: JSONClass
fromJSON2Class = Direction -> Arity -> JSONClass
JSONClass Direction
From Arity
Arity2
jsonClassName :: JSONClass -> Name
jsonClassName :: JSONClass -> Name
jsonClassName (JSONClass To Arity0) = ''ToJSON
jsonClassName (JSONClass To Arity1) = ''ToJSON1
jsonClassName (JSONClass To Arity2) = ''ToJSON2
jsonClassName (JSONClass From Arity0) = ''FromJSON
jsonClassName (JSONClass From Arity1) = ''FromJSON1
jsonClassName (JSONClass From Arity2) = ''FromJSON2
jsonFunValName :: JSONFun -> Arity -> Name
jsonFunValName :: JSONFun -> Arity -> Name
jsonFunValName ToJSON Arity0 = 'toJSON
jsonFunValName ToJSON Arity1 = 'liftToJSON
jsonFunValName ToJSON Arity2 = 'liftToJSON2
jsonFunValName ToEncoding Arity0 = 'toEncoding
jsonFunValName ToEncoding Arity1 = 'liftToEncoding
jsonFunValName ToEncoding Arity2 = 'liftToEncoding2
jsonFunValName ParseJSON Arity0 = 'parseJSON
jsonFunValName ParseJSON Arity1 = 'liftParseJSON
jsonFunValName ParseJSON Arity2 = 'liftParseJSON2
jsonFunListName :: JSONFun -> Arity -> Name
jsonFunListName :: JSONFun -> Arity -> Name
jsonFunListName ToJSON Arity0 = 'toJSONList
jsonFunListName ToJSON Arity1 = 'liftToJSONList
jsonFunListName ToJSON Arity2 = 'liftToJSONList2
jsonFunListName ToEncoding Arity0 = 'toEncodingList
jsonFunListName ToEncoding Arity1 = 'liftToEncodingList
jsonFunListName ToEncoding Arity2 = 'liftToEncodingList2
jsonFunListName ParseJSON Arity0 = 'parseJSONList
jsonFunListName ParseJSON Arity1 = 'liftParseJSONList
jsonFunListName ParseJSON Arity2 = 'liftParseJSONList2
jsonFunValOrListName :: Bool
-> JSONFun -> Arity -> Name
jsonFunValOrListName :: Bool -> JSONFun -> Arity -> Name
jsonFunValOrListName False = JSONFun -> Arity -> Name
jsonFunValName
jsonFunValOrListName True = JSONFun -> Arity -> Name
jsonFunListName
arityInt :: JSONClass -> Int
arityInt :: JSONClass -> Int
arityInt = Arity -> Int
forall a. Enum a => a -> Int
fromEnum (Arity -> Int) -> (JSONClass -> Arity) -> JSONClass -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSONClass -> Arity
arity
allowExQuant :: JSONClass -> Bool
allowExQuant :: JSONClass -> Bool
allowExQuant (JSONClass To _) = Bool
True
allowExQuant _ = Bool
False
data StarKindStatus = NotKindStar
| KindStar
| IsKindVar Name
deriving StarKindStatus -> StarKindStatus -> Bool
(StarKindStatus -> StarKindStatus -> Bool)
-> (StarKindStatus -> StarKindStatus -> Bool) -> Eq StarKindStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StarKindStatus -> StarKindStatus -> Bool
$c/= :: StarKindStatus -> StarKindStatus -> Bool
== :: StarKindStatus -> StarKindStatus -> Bool
$c== :: StarKindStatus -> StarKindStatus -> Bool
Eq
canRealizeKindStar :: Type -> StarKindStatus
canRealizeKindStar :: Type -> StarKindStatus
canRealizeKindStar t :: Type
t = case Type
t of
_ | Type -> Bool
hasKindStar Type
t -> StarKindStatus
KindStar
#if MIN_VERSION_template_haskell(2,8,0)
SigT _ (VarT k :: Name
k) -> Name -> StarKindStatus
IsKindVar Name
k
#endif
_ -> StarKindStatus
NotKindStar
starKindStatusToName :: StarKindStatus -> Maybe Name
starKindStatusToName :: StarKindStatus -> Maybe Name
starKindStatusToName (IsKindVar n :: Name
n) = Name -> Maybe Name
forall a. a -> Maybe a
Just Name
n
starKindStatusToName _ = Maybe Name
forall a. Maybe a
Nothing
catKindVarNames :: [StarKindStatus] -> [Name]
catKindVarNames :: [StarKindStatus] -> [Name]
catKindVarNames = (StarKindStatus -> Maybe Name) -> [StarKindStatus] -> [Name]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe StarKindStatus -> Maybe Name
starKindStatusToName