{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.CodeGen.Server.Interpreting.Transform
  ( parseServerTypeDefinitions,
  )
where

import Data.ByteString.Lazy.Char8 (ByteString)
import Data.Morpheus.CodeGen.Internal.AST
  ( AssociatedType (..),
    CodeGenConstructor (..),
    CodeGenField (..),
    CodeGenType (..),
    CodeGenTypeName (CodeGenTypeName, typeParameters),
    MethodArgument (..),
    TypeClassInstance (..),
    fromTypeName,
    getFullName,
  )
import Data.Morpheus.CodeGen.Server.Internal.AST
  ( CodeGenConfig (..),
    DerivingClass (..),
    FIELD_TYPE_WRAPPER (..),
    GQLTypeDefinition (..),
    InterfaceDefinition (..),
    Kind (..),
    ServerDeclaration (..),
    ServerMethod (..),
  )
import Data.Morpheus.CodeGen.Server.Interpreting.Directive
  ( getDefaultValueDir,
    getDirectives,
    getNamespaceDirs,
    getRenameDir,
  )
import Data.Morpheus.CodeGen.Server.Interpreting.Utils
  ( CodeGenM,
    CodeGenMonad (printWarnings),
    ServerCodeGenContext (..),
    checkTypeExistence,
    getEnumName,
    getFieldName,
    getFieldTypeName,
    inType,
    isParamResolverType,
    isSubscription,
  )
import Data.Morpheus.CodeGen.TH (ToName (..))
import Data.Morpheus.CodeGen.Utils
  ( Flag (..),
    Flags,
    camelCaseTypeName,
    langExtension,
    runCodeGenT,
    toHaskellTypeName,
  )
import Data.Morpheus.Core (parseDefinitions)
import Data.Morpheus.Error (renderGQLErrors)
import Data.Morpheus.Internal.Ext (Result (..))
import Data.Morpheus.Server.Types (Arg, DIRECTIVE_LOCATIONS, GQLDirective, GQLType (..), SubscriptionField)
import Data.Morpheus.Types.Internal.AST
  ( ANY,
    ArgumentDefinition (..),
    CONST,
    DataEnumValue (..),
    DirectiveDefinition (..),
    FieldContent (..),
    FieldDefinition (..),
    FieldName,
    FieldsDefinition,
    IN,
    OUT,
    RawTypeDefinition (..),
    TRUE,
    TypeContent (..),
    TypeDefinition (..),
    TypeKind (..),
    TypeName,
    TypeRef (..),
    UnionMember (..),
    isNullable,
    isPossibleInterfaceType,
    isResolverType,
    kindOf,
    packName,
    unpackName,
  )
import Relude hiding (ByteString, get)

parseServerTypeDefinitions :: (CodeGenMonad m) => CodeGenConfig -> ByteString -> m ([ServerDeclaration], Flags)
parseServerTypeDefinitions :: forall (m :: * -> *).
CodeGenMonad m =>
CodeGenConfig -> ByteString -> m ([ServerDeclaration], Flags)
parseServerTypeDefinitions CodeGenConfig
ctx ByteString
txt =
  case ByteString -> GQLResult [RawTypeDefinition]
parseDefinitions ByteString
txt of
    Failure NonEmpty GQLError
errors -> String -> m ([ServerDeclaration], Flags)
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (NonEmpty GQLError -> String
renderGQLErrors NonEmpty GQLError
errors)
    Success {[RawTypeDefinition]
result :: [RawTypeDefinition]
result :: forall err a. Result err a -> a
result, [GQLError]
warnings :: [GQLError]
warnings :: forall err a. Result err a -> [err]
warnings} -> [GQLError] -> m ()
forall (m :: * -> *). CodeGenMonad m => [GQLError] -> m ()
printWarnings [GQLError]
warnings m ()
-> m ([ServerDeclaration], Flags) -> m ([ServerDeclaration], Flags)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> [RawTypeDefinition] -> m ([ServerDeclaration], Flags)
forall (m :: * -> *).
CodeGenMonad m =>
Bool -> [RawTypeDefinition] -> m ([ServerDeclaration], Flags)
toTHDefinitions (CodeGenConfig -> Bool
namespace CodeGenConfig
ctx) [RawTypeDefinition]
result

getExternals :: [ServerDeclaration] -> Flags
getExternals :: [ServerDeclaration] -> Flags
getExternals [ServerDeclaration]
xs =
  [Text -> Flag
FlagExternal Text
scalarTypeName | ScalarType {Text
scalarTypeName :: Text
scalarTypeName :: ServerDeclaration -> Text
scalarTypeName} <- [ServerDeclaration]
xs]
    Flags -> Flags -> Flags
forall a. Semigroup a => a -> a -> a
<> [Text -> Flag
FlagExternal (TypeName -> Text
forall a (t :: NAME). NamePacking a => Name t -> a
forall (t :: NAME). Name t -> Text
unpackName (TypeName -> Text) -> TypeName -> Text
forall a b. (a -> b) -> a -> b
$ CodeGenTypeName -> TypeName
getFullName (CodeGenTypeName -> TypeName) -> CodeGenTypeName -> TypeName
forall a b. (a -> b) -> a -> b
$ TypeClassInstance ServerMethod -> CodeGenTypeName
forall body. TypeClassInstance body -> CodeGenTypeName
typeClassTarget TypeClassInstance ServerMethod
v) | GQLTypeInstance Kind
Scalar TypeClassInstance ServerMethod
v <- [ServerDeclaration]
xs]

toTHDefinitions ::
  (CodeGenMonad m) =>
  Bool ->
  [RawTypeDefinition] ->
  m ([ServerDeclaration], Flags)
toTHDefinitions :: forall (m :: * -> *).
CodeGenMonad m =>
Bool -> [RawTypeDefinition] -> m ([ServerDeclaration], Flags)
toTHDefinitions Bool
namespace [RawTypeDefinition]
defs = do
  ([ServerDeclaration]
types, Flags
flags) <- ([[ServerDeclaration]] -> [ServerDeclaration])
-> ([Flags] -> Flags)
-> ([[ServerDeclaration]], [Flags])
-> ([ServerDeclaration], Flags)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [[ServerDeclaration]] -> [ServerDeclaration]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [Flags] -> Flags
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (([[ServerDeclaration]], [Flags]) -> ([ServerDeclaration], Flags))
-> ([([ServerDeclaration], Flags)]
    -> ([[ServerDeclaration]], [Flags]))
-> [([ServerDeclaration], Flags)]
-> ([ServerDeclaration], Flags)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [([ServerDeclaration], Flags)] -> ([[ServerDeclaration]], [Flags])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([ServerDeclaration], Flags)] -> ([ServerDeclaration], Flags))
-> m [([ServerDeclaration], Flags)]
-> m ([ServerDeclaration], Flags)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (RawTypeDefinition -> m ([ServerDeclaration], Flags))
-> [RawTypeDefinition] -> m [([ServerDeclaration], Flags)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse RawTypeDefinition -> m ([ServerDeclaration], Flags)
forall (m :: * -> *).
CodeGenMonad m =>
RawTypeDefinition -> m ([ServerDeclaration], Flags)
generateTypes [RawTypeDefinition]
defs
  ([ServerDeclaration], Flags) -> m ([ServerDeclaration], Flags)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ServerDeclaration]
types, Flags
flags Flags -> Flags -> Flags
forall a. Semigroup a => a -> a -> a
<> [ServerDeclaration] -> Flags
getExternals [ServerDeclaration]
types)
  where
    typeDefinitions :: [TypeDefinition ANY CONST]
typeDefinitions = [TypeDefinition ANY CONST
td | RawTypeDefinition TypeDefinition ANY CONST
td <- [RawTypeDefinition]
defs]
    directiveDefinitions :: [DirectiveDefinition CONST]
directiveDefinitions = [DirectiveDefinition CONST
td | RawDirectiveDefinition DirectiveDefinition CONST
td <- [RawTypeDefinition]
defs]
    generateTypes :: (CodeGenMonad m) => RawTypeDefinition -> m ([ServerDeclaration], Flags)
    generateTypes :: forall (m :: * -> *).
CodeGenMonad m =>
RawTypeDefinition -> m ([ServerDeclaration], Flags)
generateTypes (RawTypeDefinition TypeDefinition ANY CONST
typeDef) =
      CodeGenT ServerCodeGenContext m [ServerDeclaration]
-> ServerCodeGenContext -> m ([ServerDeclaration], Flags)
forall (m :: * -> *) ctx a.
Monad m =>
CodeGenT ctx m a -> ctx -> m (a, Flags)
runCodeGenT
        (TypeDefinition ANY CONST
-> CodeGenT ServerCodeGenContext m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
TypeDefinition ANY CONST -> m [ServerDeclaration]
genTypeDefinition TypeDefinition ANY CONST
typeDef)
        ServerCodeGenContext
          { toArgsTypeName :: FieldName -> TypeName
toArgsTypeName = Bool -> TypeName -> FieldName -> TypeName
mkArgsTypeName Bool
namespace (TypeDefinition ANY CONST -> TypeName
forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeName
typeName TypeDefinition ANY CONST
typeDef),
            [TypeDefinition ANY CONST]
typeDefinitions :: [TypeDefinition ANY CONST]
typeDefinitions :: [TypeDefinition ANY CONST]
typeDefinitions,
            [DirectiveDefinition CONST]
directiveDefinitions :: [DirectiveDefinition CONST]
directiveDefinitions :: [DirectiveDefinition CONST]
directiveDefinitions,
            currentTypeName :: Maybe TypeName
currentTypeName = TypeName -> Maybe TypeName
forall a. a -> Maybe a
Just (Text -> TypeName
forall a (t :: NAME). NamePacking a => a -> Name t
forall (t :: NAME). Text -> Name t
packName (Text -> TypeName) -> Text -> TypeName
forall a b. (a -> b) -> a -> b
$ TypeName -> Text
toHaskellTypeName (TypeName -> Text) -> TypeName -> Text
forall a b. (a -> b) -> a -> b
$ TypeDefinition ANY CONST -> TypeName
forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeName
typeName TypeDefinition ANY CONST
typeDef),
            currentKind :: Maybe TypeKind
currentKind = TypeKind -> Maybe TypeKind
forall a. a -> Maybe a
Just (TypeDefinition ANY CONST -> TypeKind
forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeKind
kindOf TypeDefinition ANY CONST
typeDef),
            hasNamespace :: Bool
hasNamespace = Bool
namespace
          }
    generateTypes (RawDirectiveDefinition DirectiveDefinition CONST
dirDef) =
      CodeGenT ServerCodeGenContext m [ServerDeclaration]
-> ServerCodeGenContext -> m ([ServerDeclaration], Flags)
forall (m :: * -> *) ctx a.
Monad m =>
CodeGenT ctx m a -> ctx -> m (a, Flags)
runCodeGenT
        (DirectiveDefinition CONST
-> CodeGenT ServerCodeGenContext m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
DirectiveDefinition CONST -> m [ServerDeclaration]
genDirectiveDefinition DirectiveDefinition CONST
dirDef)
        ServerCodeGenContext
          { toArgsTypeName :: FieldName -> TypeName
toArgsTypeName = FieldName -> TypeName
forall a b. Coercible a b => a -> b
coerce,
            [TypeDefinition ANY CONST]
typeDefinitions :: [TypeDefinition ANY CONST]
typeDefinitions :: [TypeDefinition ANY CONST]
typeDefinitions,
            currentTypeName :: Maybe TypeName
currentTypeName = TypeName -> Maybe TypeName
forall a. a -> Maybe a
Just ((DirectiveDefinition CONST -> FieldName)
-> DirectiveDefinition CONST -> TypeName
forall a b. Coercible a b => a -> b
coerce DirectiveDefinition CONST -> FieldName
forall (s :: Stage). DirectiveDefinition s -> FieldName
directiveDefinitionName DirectiveDefinition CONST
dirDef),
            [DirectiveDefinition CONST]
directiveDefinitions :: [DirectiveDefinition CONST]
directiveDefinitions :: [DirectiveDefinition CONST]
directiveDefinitions,
            currentKind :: Maybe TypeKind
currentKind = Maybe TypeKind
forall a. Maybe a
Nothing,
            hasNamespace :: Bool
hasNamespace = Bool
namespace
          }
    generateTypes RawTypeDefinition
_ = ([ServerDeclaration], Flags) -> m ([ServerDeclaration], Flags)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ServerDeclaration]
forall a. Monoid a => a
mempty, Flags
forall a. Monoid a => a
mempty)

mkInterfaceName :: TypeName -> TypeName
mkInterfaceName :: TypeName -> TypeName
mkInterfaceName = (TypeName
"Interface" TypeName -> TypeName -> TypeName
forall a. Semigroup a => a -> a -> a
<>)

mkPossibleTypesName :: TypeName -> TypeName
mkPossibleTypesName :: TypeName -> TypeName
mkPossibleTypesName = (TypeName
"PossibleTypes" TypeName -> TypeName -> TypeName
forall a. Semigroup a => a -> a -> a
<>)

genDirectiveDefinition :: (CodeGenM m) => DirectiveDefinition CONST -> m [ServerDeclaration]
genDirectiveDefinition :: forall (m :: * -> *).
CodeGenM m =>
DirectiveDefinition CONST -> m [ServerDeclaration]
genDirectiveDefinition DirectiveDefinition {[DirectiveLocation]
Maybe Text
ArgumentsDefinition CONST
FieldName
directiveDefinitionName :: forall (s :: Stage). DirectiveDefinition s -> FieldName
directiveDefinitionName :: FieldName
directiveDefinitionDescription :: Maybe Text
directiveDefinitionArgs :: ArgumentsDefinition CONST
directiveDefinitionLocations :: [DirectiveLocation]
directiveDefinitionDescription :: forall (s :: Stage). DirectiveDefinition s -> Maybe Text
directiveDefinitionArgs :: forall (s :: Stage). DirectiveDefinition s -> ArgumentsDefinition s
directiveDefinitionLocations :: forall (s :: Stage). DirectiveDefinition s -> [DirectiveLocation]
..} = do
  [CodeGenField]
fields <- (ArgumentDefinition CONST -> m CodeGenField)
-> [ArgumentDefinition CONST] -> m [CodeGenField]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (FieldDefinition IN CONST -> m CodeGenField
forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m CodeGenField
renderDataField (FieldDefinition IN CONST -> m CodeGenField)
-> (ArgumentDefinition CONST -> FieldDefinition IN CONST)
-> ArgumentDefinition CONST
-> m CodeGenField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ArgumentDefinition CONST -> FieldDefinition IN CONST
forall (s :: Stage). ArgumentDefinition s -> FieldDefinition IN s
argument) (ArgumentsDefinition CONST -> [ArgumentDefinition CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ArgumentsDefinition CONST
directiveDefinitionArgs)
  let typename :: TypeName
typename = FieldName -> TypeName
forall a b. Coercible a b => a -> b
coerce FieldName
directiveDefinitionName
  [ServerDirectiveUsage]
namespaceDirs <- Text -> m [ServerDirectiveUsage]
forall (m :: * -> *).
CodeGenM m =>
Text -> m [ServerDirectiveUsage]
getNamespaceDirs (TypeName -> Text
forall a (t :: NAME). NamePacking a => Name t -> a
forall (t :: NAME). Name t -> Text
unpackName TypeName
typename)
  let cgTypeName :: CodeGenTypeName
cgTypeName = TypeName -> CodeGenTypeName
fromTypeName TypeName
typename
  [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    [ CodeGenType -> ServerDeclaration
DataType
        CodeGenType
          { CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgTypeName,
            cgConstructors :: [CodeGenConstructor]
cgConstructors = [CodeGenTypeName -> [CodeGenField] -> CodeGenConstructor
CodeGenConstructor (TypeName -> CodeGenTypeName
fromTypeName TypeName
typename) [CodeGenField]
fields],
            cgDerivations :: [DerivingClass]
cgDerivations = [DerivingClass
SHOW, DerivingClass
GENERIC]
          },
      TypeClassInstance ServerMethod -> ServerDeclaration
GQLDirectiveInstance
        TypeClassInstance
          { typeClassName :: Name
typeClassName = ''GQLDirective,
            typeClassContext :: [(Name, Name)]
typeClassContext = [],
            typeClassTarget :: CodeGenTypeName
typeClassTarget = CodeGenTypeName
cgTypeName,
            assoc :: [(Name, AssociatedType)]
assoc = [(''DIRECTIVE_LOCATIONS, [DirectiveLocation] -> AssociatedType
AssociatedLocations [DirectiveLocation]
directiveDefinitionLocations)],
            typeClassMethods :: [(Name, MethodArgument, ServerMethod)]
typeClassMethods = []
          },
      GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance
        GQLTypeDefinition
          { gqlTarget :: CodeGenTypeName
gqlTarget = CodeGenTypeName
cgTypeName,
            gqlKind :: Kind
gqlKind = Kind
Directive,
            gqlTypeDirectiveUses :: [ServerDirectiveUsage]
gqlTypeDirectiveUses = [ServerDirectiveUsage]
namespaceDirs
          }
    ]

genTypeDefinition ::
  (CodeGenM m) =>
  TypeDefinition ANY CONST ->
  m [ServerDeclaration]
genTypeDefinition :: forall (m :: * -> *).
CodeGenM m =>
TypeDefinition ANY CONST -> m [ServerDeclaration]
genTypeDefinition
  typeDef :: TypeDefinition ANY CONST
typeDef@TypeDefinition {typeName :: forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeName
typeName = TypeName
originalTypeName, TypeContent TRUE ANY CONST
typeContent :: TypeContent TRUE ANY CONST
typeContent :: forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeContent TRUE a s
typeContent} =
    case TypeKind
tKind of
      TypeKind
KIND_SCALAR -> do
        ServerDeclaration
scalarGQLType <- m ServerDeclaration
deriveGQL
        [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text -> ServerDeclaration
ScalarType (TypeName -> Text
toHaskellTypeName TypeName
typeName), ServerDeclaration
scalarGQLType]
      TypeKind
_ -> TypeName -> TypeContent TRUE ANY CONST -> m BuildPlan
forall (m :: * -> *).
CodeGenM m =>
TypeName -> TypeContent TRUE ANY CONST -> m BuildPlan
genTypeContent TypeName
originalTypeName TypeContent TRUE ANY CONST
typeContent m BuildPlan
-> (BuildPlan -> m [ServerDeclaration]) -> m [ServerDeclaration]
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BuildPlan -> m [ServerDeclaration]
withType
    where
      typeName :: TypeName
typeName
        | TypeKind
tKind TypeKind -> TypeKind -> Bool
forall a. Eq a => a -> a -> Bool
== TypeKind
KIND_INTERFACE = TypeName -> TypeName
mkInterfaceName TypeName
originalTypeName
        | Bool
otherwise = TypeName
originalTypeName
      tKind :: TypeKind
tKind = TypeDefinition ANY CONST -> TypeKind
forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeKind
kindOf TypeDefinition ANY CONST
typeDef
      hsTypeName :: TypeName
hsTypeName = Text -> TypeName
forall a (t :: NAME). NamePacking a => a -> Name t
forall (t :: NAME). Text -> Name t
packName (Text -> TypeName) -> Text -> TypeName
forall a b. (a -> b) -> a -> b
$ TypeName -> Text
toHaskellTypeName TypeName
typeName
      cgTypeName :: CodeGenTypeName
cgTypeName = [FieldName] -> [Text] -> TypeName -> CodeGenTypeName
CodeGenTypeName [] [Text
"m" | TypeKind -> Bool
forall t. Strictness t => t -> Bool
isResolverType TypeKind
tKind] TypeName
hsTypeName
      deriveGQL :: m ServerDeclaration
deriveGQL = do
        [ServerDirectiveUsage]
defaultValueDirs <- [[ServerDirectiveUsage]] -> [ServerDirectiveUsage]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ServerDirectiveUsage]] -> [ServerDirectiveUsage])
-> m [[ServerDirectiveUsage]] -> m [ServerDirectiveUsage]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition IN CONST -> m [ServerDirectiveUsage])
-> [FieldDefinition IN CONST] -> m [[ServerDirectiveUsage]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition IN CONST -> m [ServerDirectiveUsage]
forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m [ServerDirectiveUsage]
getDefaultValueDir (TypeDefinition ANY CONST -> [FieldDefinition IN CONST]
forall (c :: TypeCategory) (s :: Stage).
TypeDefinition c s -> [FieldDefinition IN s]
getInputFields TypeDefinition ANY CONST
typeDef)
        [ServerDirectiveUsage]
namespaceDirs <- Text -> m [ServerDirectiveUsage]
forall (m :: * -> *).
CodeGenM m =>
Text -> m [ServerDirectiveUsage]
getNamespaceDirs (TypeName -> Text
forall a (t :: NAME). NamePacking a => Name t -> a
forall (t :: NAME). Name t -> Text
unpackName TypeName
hsTypeName)
        [ServerDirectiveUsage]
dirs <- TypeDefinition ANY CONST -> m [ServerDirectiveUsage]
forall (m :: * -> *) a.
(CodeGenM m, Meta a) =>
a -> m [ServerDirectiveUsage]
getDirectives TypeDefinition ANY CONST
typeDef
        [ServerDirectiveUsage]
renameDir <- TypeName -> TypeName -> m [ServerDirectiveUsage]
forall (m :: * -> *) (t :: NAME).
CodeGenM m =>
Name t -> Name t -> m [ServerDirectiveUsage]
getRenameDir TypeName
originalTypeName TypeName
hsTypeName
        ServerDeclaration -> m ServerDeclaration
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ServerDeclaration -> m ServerDeclaration)
-> ServerDeclaration -> m ServerDeclaration
forall a b. (a -> b) -> a -> b
$
          GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance
            GQLTypeDefinition
              { gqlTarget :: CodeGenTypeName
gqlTarget = CodeGenTypeName
cgTypeName,
                gqlTypeDirectiveUses :: [ServerDirectiveUsage]
gqlTypeDirectiveUses = [ServerDirectiveUsage]
renameDir [ServerDirectiveUsage]
-> [ServerDirectiveUsage] -> [ServerDirectiveUsage]
forall a. Semigroup a => a -> a -> a
<> [ServerDirectiveUsage]
namespaceDirs [ServerDirectiveUsage]
-> [ServerDirectiveUsage] -> [ServerDirectiveUsage]
forall a. Semigroup a => a -> a -> a
<> [ServerDirectiveUsage]
dirs [ServerDirectiveUsage]
-> [ServerDirectiveUsage] -> [ServerDirectiveUsage]
forall a. Semigroup a => a -> a -> a
<> [ServerDirectiveUsage]
defaultValueDirs,
                gqlKind :: Kind
gqlKind = TypeKind -> Kind
derivingKind TypeKind
tKind
              }
      cgDerivations :: [DerivingClass]
cgDerivations = Bool -> [DerivingClass]
derivesClasses (TypeKind -> Bool
forall t. Strictness t => t -> Bool
isResolverType TypeKind
tKind)
      -------------------------
      withType :: BuildPlan -> m [ServerDeclaration]
withType (ConsIN [CodeGenConstructor]
cgConstructors) = do
        ServerDeclaration
gqlType <- m ServerDeclaration
deriveGQL
        [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [CodeGenType -> ServerDeclaration
DataType CodeGenType {[CodeGenConstructor]
[DerivingClass]
CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgConstructors :: [CodeGenConstructor]
cgDerivations :: [DerivingClass]
cgTypeName :: CodeGenTypeName
cgDerivations :: [DerivingClass]
cgConstructors :: [CodeGenConstructor]
..}, ServerDeclaration
gqlType]
      withType (ConsOUT [ServerDeclaration]
others [CodeGenConstructor]
cgConstructors) = do
        ServerDeclaration
gqlType <- m ServerDeclaration
deriveGQL
        [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CodeGenType -> ServerDeclaration
DataType CodeGenType {[CodeGenConstructor]
[DerivingClass]
CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgConstructors :: [CodeGenConstructor]
cgDerivations :: [DerivingClass]
cgTypeName :: CodeGenTypeName
cgDerivations :: [DerivingClass]
cgConstructors :: [CodeGenConstructor]
..} ServerDeclaration -> [ServerDeclaration] -> [ServerDeclaration]
forall a. a -> [a] -> [a]
: ServerDeclaration
gqlType ServerDeclaration -> [ServerDeclaration] -> [ServerDeclaration]
forall a. a -> [a] -> [a]
: [ServerDeclaration]
others)

derivingKind :: TypeKind -> Kind
derivingKind :: TypeKind -> Kind
derivingKind TypeKind
KIND_SCALAR = Kind
Scalar
derivingKind TypeKind
_ = Kind
Type

derivesClasses :: Bool -> [DerivingClass]
derivesClasses :: Bool -> [DerivingClass]
derivesClasses Bool
isResolver = DerivingClass
GENERIC DerivingClass -> [DerivingClass] -> [DerivingClass]
forall a. a -> [a] -> [a]
: [DerivingClass
SHOW | Bool -> Bool
not Bool
isResolver]

mkObjectCons :: TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons :: TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons TypeName
name = CodeGenConstructor -> [CodeGenConstructor]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CodeGenConstructor -> [CodeGenConstructor])
-> ([CodeGenField] -> CodeGenConstructor)
-> [CodeGenField]
-> [CodeGenConstructor]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodeGenTypeName -> [CodeGenField] -> CodeGenConstructor
CodeGenConstructor (TypeName -> CodeGenTypeName
fromTypeName TypeName
name)

mkArgsTypeName :: Bool -> TypeName -> FieldName -> TypeName
mkArgsTypeName :: Bool -> TypeName -> FieldName -> TypeName
mkArgsTypeName Bool
namespace TypeName
typeName FieldName
fieldName
  | Bool
namespace = TypeName
typeName TypeName -> TypeName -> TypeName
forall a. Semigroup a => a -> a -> a
<> TypeName
argTName
  | Bool
otherwise = TypeName
argTName
  where
    argTName :: TypeName
argTName = [FieldName] -> TypeName -> TypeName
forall (t :: NAME). [Name t] -> TypeName -> TypeName
camelCaseTypeName [FieldName
fieldName] TypeName
"Args"

mkObjectField ::
  (CodeGenM m) =>
  FieldDefinition OUT CONST ->
  m CodeGenField
mkObjectField :: forall (m :: * -> *).
CodeGenM m =>
FieldDefinition OUT CONST -> m CodeGenField
mkObjectField
  FieldDefinition
    { fieldName :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> FieldName
fieldName = FieldName
fName,
      Maybe (FieldContent TRUE OUT CONST)
fieldContent :: Maybe (FieldContent TRUE OUT CONST)
fieldContent :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> Maybe (FieldContent TRUE cat s)
fieldContent,
      fieldType :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> TypeRef
fieldType = TypeRef {TypeName
typeConName :: TypeName
typeConName :: TypeRef -> TypeName
typeConName, TypeWrapper
typeWrappers :: TypeWrapper
typeWrappers :: TypeRef -> TypeWrapper
typeWrappers}
    } = do
    Bool
isParametrized <- TypeName -> m Bool
forall (m :: * -> *). CodeGenM m => TypeName -> m Bool
isParamResolverType TypeName
typeConName
    FieldName -> TypeName
genName <- (ServerCodeGenContext -> FieldName -> TypeName)
-> m (FieldName -> TypeName)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ServerCodeGenContext -> FieldName -> TypeName
toArgsTypeName
    Maybe TypeKind
kind <- (ServerCodeGenContext -> Maybe TypeKind) -> m (Maybe TypeKind)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ServerCodeGenContext -> Maybe TypeKind
currentKind
    FieldName
fieldName <- FieldName -> m FieldName
forall (m :: * -> *). CodeGenM m => FieldName -> m FieldName
getFieldName FieldName
fName
    [FIELD_TYPE_WRAPPER]
args <- FieldName
-> (FieldName -> TypeName)
-> [ArgumentDefinition CONST]
-> m [FIELD_TYPE_WRAPPER]
forall (m :: * -> *) (s :: Stage).
CodeGenM m =>
FieldName
-> (FieldName -> TypeName)
-> [ArgumentDefinition s]
-> m [FIELD_TYPE_WRAPPER]
mkFieldArguments FieldName
fName FieldName -> TypeName
genName (Maybe (FieldContent TRUE OUT CONST) -> [ArgumentDefinition CONST]
forall (bool :: Bool) (cat :: TypeCategory) (s :: Stage).
Maybe (FieldContent bool cat s) -> [ArgumentDefinition s]
toArgList Maybe (FieldContent TRUE OUT CONST)
fieldContent)
    TypeName
fieldType <- TypeName -> m TypeName
forall (m :: * -> *). CodeGenM m => TypeName -> m TypeName
getFieldTypeName TypeName
typeConName
    CodeGenField -> m CodeGenField
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
      CodeGenField
        { TypeName
fieldType :: TypeName
fieldType :: TypeName
fieldType,
          fieldIsNullable :: Bool
fieldIsNullable = TypeWrapper -> Bool
forall a. Nullable a => a -> Bool
isNullable TypeWrapper
typeWrappers,
          wrappers :: [FIELD_TYPE_WRAPPER]
wrappers =
            [FIELD_TYPE_WRAPPER]
args
              [FIELD_TYPE_WRAPPER]
-> [FIELD_TYPE_WRAPPER] -> [FIELD_TYPE_WRAPPER]
forall a. Semigroup a => a -> a -> a
<> [Name -> FIELD_TYPE_WRAPPER
SUBSCRIPTION ''SubscriptionField | (TypeKind -> Bool) -> Maybe TypeKind -> Maybe Bool
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TypeKind -> Bool
isSubscription Maybe TypeKind
kind Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True]
              [FIELD_TYPE_WRAPPER]
-> [FIELD_TYPE_WRAPPER] -> [FIELD_TYPE_WRAPPER]
forall a. Semigroup a => a -> a -> a
<> [FIELD_TYPE_WRAPPER
MONAD]
              [FIELD_TYPE_WRAPPER]
-> [FIELD_TYPE_WRAPPER] -> [FIELD_TYPE_WRAPPER]
forall a. Semigroup a => a -> a -> a
<> [TypeWrapper -> FIELD_TYPE_WRAPPER
GQL_WRAPPER TypeWrapper
typeWrappers]
              [FIELD_TYPE_WRAPPER]
-> [FIELD_TYPE_WRAPPER] -> [FIELD_TYPE_WRAPPER]
forall a. Semigroup a => a -> a -> a
<> [FIELD_TYPE_WRAPPER
PARAMETRIZED | Bool
isParametrized],
          FieldName
fieldName :: FieldName
fieldName :: FieldName
..
        }

mkFieldArguments :: (CodeGenM m) => FieldName -> (FieldName -> TypeName) -> [ArgumentDefinition s] -> m [FIELD_TYPE_WRAPPER]
mkFieldArguments :: forall (m :: * -> *) (s :: Stage).
CodeGenM m =>
FieldName
-> (FieldName -> TypeName)
-> [ArgumentDefinition s]
-> m [FIELD_TYPE_WRAPPER]
mkFieldArguments FieldName
_ FieldName -> TypeName
_ [] = [FIELD_TYPE_WRAPPER] -> m [FIELD_TYPE_WRAPPER]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
mkFieldArguments
  FieldName
_
  FieldName -> TypeName
_
  [ ArgumentDefinition FieldDefinition {FieldName
fieldName :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> FieldName
fieldName :: FieldName
fieldName, TypeRef
fieldType :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> TypeRef
fieldType :: TypeRef
fieldType}
    ] =
    TypeName -> m ()
forall (m :: * -> *). CodeGenM m => TypeName -> m ()
checkTypeExistence (TypeRef -> TypeName
typeConName TypeRef
fieldType)
      m () -> m [FIELD_TYPE_WRAPPER] -> m [FIELD_TYPE_WRAPPER]
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> m ()
forall (m :: * -> *). MonadState Flags m => Text -> m ()
langExtension Text
"DataKinds" m () -> [FIELD_TYPE_WRAPPER] -> m [FIELD_TYPE_WRAPPER]
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> [Name -> FieldName -> TypeRef -> FIELD_TYPE_WRAPPER
TAGGED_ARG ''Arg FieldName
fieldName TypeRef
fieldType]
mkFieldArguments FieldName
fName FieldName -> TypeName
genName [ArgumentDefinition s]
_ = [FIELD_TYPE_WRAPPER] -> m [FIELD_TYPE_WRAPPER]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TypeName -> FIELD_TYPE_WRAPPER
ARG (FieldName -> TypeName
genName FieldName
fName)]

toArgList :: Maybe (FieldContent bool cat s) -> [ArgumentDefinition s]
toArgList :: forall (bool :: Bool) (cat :: TypeCategory) (s :: Stage).
Maybe (FieldContent bool cat s) -> [ArgumentDefinition s]
toArgList (Just (FieldArgs ArgumentsDefinition s
args)) = ArgumentsDefinition s -> [ArgumentDefinition s]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ArgumentsDefinition s
args
toArgList Maybe (FieldContent bool cat s)
_ = []

data BuildPlan
  = ConsIN [CodeGenConstructor]
  | ConsOUT [ServerDeclaration] [CodeGenConstructor]

gqlTypeToInstance :: GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance :: GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance GQLTypeDefinition {[ServerDirectiveUsage]
CodeGenTypeName
Kind
gqlTarget :: GQLTypeDefinition -> CodeGenTypeName
gqlKind :: GQLTypeDefinition -> Kind
gqlTypeDirectiveUses :: GQLTypeDefinition -> [ServerDirectiveUsage]
gqlTarget :: CodeGenTypeName
gqlKind :: Kind
gqlTypeDirectiveUses :: [ServerDirectiveUsage]
..} =
  Kind -> TypeClassInstance ServerMethod -> ServerDeclaration
GQLTypeInstance
    Kind
gqlKind
    TypeClassInstance
      { typeClassName :: Name
typeClassName = ''GQLType,
        typeClassContext :: [(Name, Name)]
typeClassContext = (Text -> (Name, Name)) -> [Text] -> [(Name, Name)]
forall a b. (a -> b) -> [a] -> [b]
map ((''Typeable,) (Name -> (Name, Name)) -> (Text -> Name) -> Text -> (Name, Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Name
forall a. ToName a => a -> Name
toName) (CodeGenTypeName -> [Text]
typeParameters CodeGenTypeName
gqlTarget),
        typeClassTarget :: CodeGenTypeName
typeClassTarget = CodeGenTypeName
gqlTarget,
        assoc :: [(Name, AssociatedType)]
assoc = [(''KIND, Name -> AssociatedType
AssociatedTypeName (Kind -> Name
forall a. ToName a => a -> Name
toName Kind
gqlKind))],
        typeClassMethods :: [(Name, MethodArgument, ServerMethod)]
typeClassMethods =
          [ ('directives, MethodArgument
ProxyArgument, [ServerDirectiveUsage] -> ServerMethod
ServerMethodDirectives [ServerDirectiveUsage]
gqlTypeDirectiveUses)
            | Bool -> Bool
not ([ServerDirectiveUsage] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ServerDirectiveUsage]
gqlTypeDirectiveUses)
          ]
      }

genInterfaceUnion :: (CodeGenM m) => TypeName -> m [ServerDeclaration]
genInterfaceUnion :: forall (m :: * -> *).
CodeGenM m =>
TypeName -> m [ServerDeclaration]
genInterfaceUnion TypeName
interfaceName =
  (ServerCodeGenContext -> [TypeDefinition ANY CONST])
-> m [TypeDefinition ANY CONST]
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ServerCodeGenContext -> [TypeDefinition ANY CONST]
typeDefinitions m [TypeDefinition ANY CONST]
-> ([TypeDefinition ANY CONST] -> m [ServerDeclaration])
-> m [ServerDeclaration]
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [TypeName] -> m [ServerDeclaration]
mkInterface ([TypeName] -> m [ServerDeclaration])
-> ([TypeDefinition ANY CONST] -> [TypeName])
-> [TypeDefinition ANY CONST]
-> m [ServerDeclaration]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TypeDefinition ANY CONST -> TypeName)
-> [TypeDefinition ANY CONST] -> [TypeName]
forall a b. (a -> b) -> [a] -> [b]
map TypeDefinition ANY CONST -> TypeName
forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeName
typeName ([TypeDefinition ANY CONST] -> [TypeName])
-> ([TypeDefinition ANY CONST] -> [TypeDefinition ANY CONST])
-> [TypeDefinition ANY CONST]
-> [TypeName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TypeDefinition ANY CONST -> Maybe (TypeDefinition ANY CONST))
-> [TypeDefinition ANY CONST] -> [TypeDefinition ANY CONST]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (TypeName
-> TypeDefinition ANY CONST -> Maybe (TypeDefinition ANY CONST)
forall (c :: TypeCategory) (s :: Stage).
TypeName -> TypeDefinition c s -> Maybe (TypeDefinition c s)
isPossibleInterfaceType TypeName
interfaceName)
  where
    mkInterface :: [TypeName] -> m [ServerDeclaration]
mkInterface [] = [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
    mkInterface [TypeName
possibleTypeName] = [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TypeName -> ServerDeclaration
mkGuardWithPossibleType TypeName
possibleTypeName]
    mkInterface [TypeName]
members = do
      [CodeGenConstructor]
cgConstructors <- (TypeName -> m CodeGenConstructor)
-> [TypeName] -> m [CodeGenConstructor]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (TypeName -> TypeName -> m CodeGenConstructor
forall (m :: * -> *).
CodeGenM m =>
TypeName -> TypeName -> m CodeGenConstructor
mkUnionFieldDefinition TypeName
tName) [TypeName]
members
      [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        [ TypeName -> ServerDeclaration
mkGuardWithPossibleType TypeName
tName,
          CodeGenType -> ServerDeclaration
DataType
            CodeGenType
              { cgTypeName :: CodeGenTypeName
cgTypeName = CodeGenTypeName
possTypeName,
                [CodeGenConstructor]
cgConstructors :: [CodeGenConstructor]
cgConstructors :: [CodeGenConstructor]
cgConstructors,
                cgDerivations :: [DerivingClass]
cgDerivations = Bool -> [DerivingClass]
derivesClasses Bool
True
              },
          GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance
            GQLTypeDefinition
              { gqlTarget :: CodeGenTypeName
gqlTarget = CodeGenTypeName
possTypeName,
                gqlKind :: Kind
gqlKind = Kind
Type,
                gqlTypeDirectiveUses :: [ServerDirectiveUsage]
gqlTypeDirectiveUses = [ServerDirectiveUsage]
forall a. [a]
forall (f :: * -> *) a. Alternative f => f a
empty
              }
        ]
      where
        possTypeName :: CodeGenTypeName
possTypeName = [FieldName] -> [Text] -> TypeName -> CodeGenTypeName
CodeGenTypeName [] [Text
"m"] (Text -> TypeName
forall a (t :: NAME). NamePacking a => a -> Name t
forall (t :: NAME). Text -> Name t
packName (Text -> TypeName) -> Text -> TypeName
forall a b. (a -> b) -> a -> b
$ TypeName -> Text
toHaskellTypeName TypeName
tName)
    mkGuardWithPossibleType :: TypeName -> ServerDeclaration
mkGuardWithPossibleType = InterfaceDefinition -> ServerDeclaration
InterfaceType (InterfaceDefinition -> ServerDeclaration)
-> (TypeName -> InterfaceDefinition)
-> TypeName
-> ServerDeclaration
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeName -> TypeName -> TypeName -> InterfaceDefinition
InterfaceDefinition TypeName
interfaceName (TypeName -> TypeName
mkInterfaceName TypeName
interfaceName)
    tName :: TypeName
tName = TypeName -> TypeName
mkPossibleTypesName TypeName
interfaceName

mkConsEnum :: (CodeGenM m) => DataEnumValue CONST -> m CodeGenConstructor
mkConsEnum :: forall (m :: * -> *).
CodeGenM m =>
DataEnumValue CONST -> m CodeGenConstructor
mkConsEnum DataEnumValue {TypeName
enumName :: TypeName
enumName :: forall (s :: Stage). DataEnumValue s -> TypeName
enumName} = do
  CodeGenTypeName
constructorName <- TypeName -> m CodeGenTypeName
forall (m :: * -> *).
MonadReader ServerCodeGenContext m =>
TypeName -> m CodeGenTypeName
getEnumName TypeName
enumName
  CodeGenConstructor -> m CodeGenConstructor
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CodeGenConstructor {CodeGenTypeName
constructorName :: CodeGenTypeName
constructorName :: CodeGenTypeName
constructorName, constructorFields :: [CodeGenField]
constructorFields = []}

renderDataField :: (CodeGenM m) => FieldDefinition c CONST -> m CodeGenField
renderDataField :: forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m CodeGenField
renderDataField FieldDefinition {fieldType :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> TypeRef
fieldType = TypeRef {TypeName
typeConName :: TypeRef -> TypeName
typeConName :: TypeName
typeConName, TypeWrapper
typeWrappers :: TypeRef -> TypeWrapper
typeWrappers :: TypeWrapper
typeWrappers}, fieldName :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> FieldName
fieldName = FieldName
fName} = do
  FieldName
fieldName <- FieldName -> m FieldName
forall (m :: * -> *). CodeGenM m => FieldName -> m FieldName
getFieldName FieldName
fName
  let wrappers :: [FIELD_TYPE_WRAPPER]
wrappers = [TypeWrapper -> FIELD_TYPE_WRAPPER
GQL_WRAPPER TypeWrapper
typeWrappers]
  TypeName
fieldType <- TypeName -> m TypeName
forall (m :: * -> *). CodeGenM m => TypeName -> m TypeName
getFieldTypeName TypeName
typeConName
  let fieldIsNullable :: Bool
fieldIsNullable = TypeWrapper -> Bool
forall a. Nullable a => a -> Bool
isNullable TypeWrapper
typeWrappers
  CodeGenField -> m CodeGenField
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CodeGenField {Bool
[FIELD_TYPE_WRAPPER]
TypeName
FieldName
fieldType :: TypeName
fieldIsNullable :: Bool
wrappers :: [FIELD_TYPE_WRAPPER]
fieldName :: FieldName
fieldName :: FieldName
wrappers :: [FIELD_TYPE_WRAPPER]
fieldType :: TypeName
fieldIsNullable :: Bool
..}

genTypeContent :: (CodeGenM m) => TypeName -> TypeContent TRUE ANY CONST -> m BuildPlan
genTypeContent :: forall (m :: * -> *).
CodeGenM m =>
TypeName -> TypeContent TRUE ANY CONST -> m BuildPlan
genTypeContent TypeName
_ DataScalar {} = BuildPlan -> m BuildPlan
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CodeGenConstructor] -> BuildPlan
ConsIN [])
genTypeContent TypeName
_ (DataEnum DataEnum CONST
tags) = [CodeGenConstructor] -> BuildPlan
ConsIN ([CodeGenConstructor] -> BuildPlan)
-> m [CodeGenConstructor] -> m BuildPlan
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DataEnumValue CONST -> m CodeGenConstructor)
-> DataEnum CONST -> m [CodeGenConstructor]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse DataEnumValue CONST -> m CodeGenConstructor
forall (m :: * -> *).
CodeGenM m =>
DataEnumValue CONST -> m CodeGenConstructor
mkConsEnum DataEnum CONST
tags
genTypeContent TypeName
typeName (DataInputObject FieldsDefinition IN CONST
fields) =
  [CodeGenConstructor] -> BuildPlan
ConsIN ([CodeGenConstructor] -> BuildPlan)
-> ([CodeGenField] -> [CodeGenConstructor])
-> [CodeGenField]
-> BuildPlan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons TypeName
typeName ([CodeGenField] -> BuildPlan) -> m [CodeGenField] -> m BuildPlan
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition IN CONST -> m CodeGenField)
-> [FieldDefinition IN CONST] -> m [CodeGenField]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition IN CONST -> m CodeGenField
forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m CodeGenField
renderDataField (FieldsDefinition IN CONST -> [FieldDefinition IN CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList FieldsDefinition IN CONST
fields)
genTypeContent TypeName
_ DataInputUnion {} = String -> m BuildPlan
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Input Unions not Supported"
genTypeContent TypeName
typeName DataInterface {FieldsDefinition OUT CONST
interfaceFields :: FieldsDefinition OUT CONST
interfaceFields :: forall (s :: Stage) (a :: TypeCategory).
CondTypeContent IMPLEMENTABLE a s -> FieldsDefinition OUT s
interfaceFields} =
  [ServerDeclaration] -> [CodeGenConstructor] -> BuildPlan
ConsOUT
    ([ServerDeclaration] -> [CodeGenConstructor] -> BuildPlan)
-> m [ServerDeclaration] -> m ([CodeGenConstructor] -> BuildPlan)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([ServerDeclaration] -> [ServerDeclaration] -> [ServerDeclaration]
forall a. Semigroup a => a -> a -> a
(<>) ([ServerDeclaration] -> [ServerDeclaration] -> [ServerDeclaration])
-> m [ServerDeclaration]
-> m ([ServerDeclaration] -> [ServerDeclaration])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FieldsDefinition OUT CONST -> m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
FieldsDefinition OUT CONST -> m [ServerDeclaration]
genArgumentTypes FieldsDefinition OUT CONST
interfaceFields m ([ServerDeclaration] -> [ServerDeclaration])
-> m [ServerDeclaration] -> m [ServerDeclaration]
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TypeName -> m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
TypeName -> m [ServerDeclaration]
genInterfaceUnion TypeName
typeName)
    m ([CodeGenConstructor] -> BuildPlan)
-> m [CodeGenConstructor] -> m BuildPlan
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ( do
            let interfaceName :: TypeName
interfaceName = TypeName -> TypeName
mkInterfaceName TypeName
typeName
            Maybe TypeName -> m [CodeGenConstructor] -> m [CodeGenConstructor]
forall (m :: * -> *) a.
MonadReader ServerCodeGenContext m =>
Maybe TypeName -> m a -> m a
inType
              (TypeName -> Maybe TypeName
forall a. a -> Maybe a
Just TypeName
interfaceName)
              ( TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons TypeName
interfaceName
                  ([CodeGenField] -> [CodeGenConstructor])
-> m [CodeGenField] -> m [CodeGenConstructor]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition OUT CONST -> m CodeGenField)
-> [FieldDefinition OUT CONST] -> m [CodeGenField]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition OUT CONST -> m CodeGenField
forall (m :: * -> *).
CodeGenM m =>
FieldDefinition OUT CONST -> m CodeGenField
mkObjectField (FieldsDefinition OUT CONST -> [FieldDefinition OUT CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList FieldsDefinition OUT CONST
interfaceFields)
              )
        )
genTypeContent TypeName
typeName DataObject {FieldsDefinition OUT CONST
objectFields :: FieldsDefinition OUT CONST
objectFields :: forall (s :: Stage) (a :: TypeCategory).
CondTypeContent OBJECT a s -> FieldsDefinition OUT s
objectFields} =
  [ServerDeclaration] -> [CodeGenConstructor] -> BuildPlan
ConsOUT
    ([ServerDeclaration] -> [CodeGenConstructor] -> BuildPlan)
-> m [ServerDeclaration] -> m ([CodeGenConstructor] -> BuildPlan)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FieldsDefinition OUT CONST -> m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
FieldsDefinition OUT CONST -> m [ServerDeclaration]
genArgumentTypes FieldsDefinition OUT CONST
objectFields
    m ([CodeGenConstructor] -> BuildPlan)
-> m [CodeGenConstructor] -> m BuildPlan
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ( TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons TypeName
typeName
            ([CodeGenField] -> [CodeGenConstructor])
-> m [CodeGenField] -> m [CodeGenConstructor]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition OUT CONST -> m CodeGenField)
-> [FieldDefinition OUT CONST] -> m [CodeGenField]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition OUT CONST -> m CodeGenField
forall (m :: * -> *).
CodeGenM m =>
FieldDefinition OUT CONST -> m CodeGenField
mkObjectField (FieldsDefinition OUT CONST -> [FieldDefinition OUT CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList FieldsDefinition OUT CONST
objectFields)
        )
genTypeContent TypeName
typeName (DataUnion UnionTypeDefinition OUT CONST
members) = do
  [ServerDeclaration] -> [CodeGenConstructor] -> BuildPlan
ConsOUT [] ([CodeGenConstructor] -> BuildPlan)
-> m [CodeGenConstructor] -> m BuildPlan
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (UnionMember OUT CONST -> m CodeGenConstructor)
-> [UnionMember OUT CONST] -> m [CodeGenConstructor]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse UnionMember OUT CONST -> m CodeGenConstructor
unionCon (UnionTypeDefinition OUT CONST -> [UnionMember OUT CONST]
forall a. OrdMap TypeName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList UnionTypeDefinition OUT CONST
members)
  where
    unionCon :: UnionMember OUT CONST -> m CodeGenConstructor
unionCon UnionMember {TypeName
memberName :: TypeName
memberName :: forall (cat :: TypeCategory) (s :: Stage).
UnionMember cat s -> TypeName
memberName} = TypeName -> TypeName -> m CodeGenConstructor
forall (m :: * -> *).
CodeGenM m =>
TypeName -> TypeName -> m CodeGenConstructor
mkUnionFieldDefinition TypeName
typeName TypeName
memberName

mkUnionFieldDefinition :: (CodeGenM m) => TypeName -> TypeName -> m CodeGenConstructor
mkUnionFieldDefinition :: forall (m :: * -> *).
CodeGenM m =>
TypeName -> TypeName -> m CodeGenConstructor
mkUnionFieldDefinition TypeName
typeName TypeName
memberName = do
  TypeName
fieldType <- TypeName -> m TypeName
forall (m :: * -> *). CodeGenM m => TypeName -> m TypeName
getFieldTypeName TypeName
memberName
  CodeGenConstructor -> m CodeGenConstructor
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CodeGenConstructor -> m CodeGenConstructor)
-> CodeGenConstructor -> m CodeGenConstructor
forall a b. (a -> b) -> a -> b
$
    CodeGenConstructor
      { CodeGenTypeName
constructorName :: CodeGenTypeName
constructorName :: CodeGenTypeName
constructorName,
        constructorFields :: [CodeGenField]
constructorFields =
          [ CodeGenField
              { fieldName :: FieldName
fieldName = FieldName
"_",
                TypeName
fieldType :: TypeName
fieldType :: TypeName
fieldType,
                wrappers :: [FIELD_TYPE_WRAPPER]
wrappers = [FIELD_TYPE_WRAPPER
MONAD, FIELD_TYPE_WRAPPER
PARAMETRIZED],
                fieldIsNullable :: Bool
fieldIsNullable = Bool
False
              }
          ]
      }
  where
    constructorName :: CodeGenTypeName
constructorName = [FieldName] -> [Text] -> TypeName -> CodeGenTypeName
CodeGenTypeName [TypeName -> FieldName
forall a b. Coercible a b => a -> b
coerce TypeName
typeName] [] TypeName
memberName

genArgumentTypes :: (CodeGenM m) => FieldsDefinition OUT CONST -> m [ServerDeclaration]
genArgumentTypes :: forall (m :: * -> *).
CodeGenM m =>
FieldsDefinition OUT CONST -> m [ServerDeclaration]
genArgumentTypes = ([[ServerDeclaration]] -> [ServerDeclaration])
-> m [[ServerDeclaration]] -> m [ServerDeclaration]
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[ServerDeclaration]] -> [ServerDeclaration]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (m [[ServerDeclaration]] -> m [ServerDeclaration])
-> (FieldsDefinition OUT CONST -> m [[ServerDeclaration]])
-> FieldsDefinition OUT CONST
-> m [ServerDeclaration]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FieldDefinition OUT CONST -> m [ServerDeclaration])
-> [FieldDefinition OUT CONST] -> m [[ServerDeclaration]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition OUT CONST -> m [ServerDeclaration]
forall (m :: * -> *).
CodeGenM m =>
FieldDefinition OUT CONST -> m [ServerDeclaration]
genArgumentType ([FieldDefinition OUT CONST] -> m [[ServerDeclaration]])
-> (FieldsDefinition OUT CONST -> [FieldDefinition OUT CONST])
-> FieldsDefinition OUT CONST
-> m [[ServerDeclaration]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldsDefinition OUT CONST -> [FieldDefinition OUT CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

genArgumentType :: (CodeGenM m) => FieldDefinition OUT CONST -> m [ServerDeclaration]
genArgumentType :: forall (m :: * -> *).
CodeGenM m =>
FieldDefinition OUT CONST -> m [ServerDeclaration]
genArgumentType
  FieldDefinition
    { FieldName
fieldName :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> FieldName
fieldName :: FieldName
fieldName,
      fieldContent :: forall (cat :: TypeCategory) (s :: Stage).
FieldDefinition cat s -> Maybe (FieldContent TRUE cat s)
fieldContent = Just (FieldArgs ArgumentsDefinition CONST
arguments)
    }
    | ArgumentsDefinition CONST -> Int
forall a. OrdMap FieldName a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ArgumentsDefinition CONST
arguments Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 = do
        TypeName
tName <- (FieldName
fieldName FieldName -> (FieldName -> TypeName) -> TypeName
forall a b. a -> (a -> b) -> b
&) ((FieldName -> TypeName) -> TypeName)
-> m (FieldName -> TypeName) -> m TypeName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ServerCodeGenContext -> FieldName -> TypeName)
-> m (FieldName -> TypeName)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ServerCodeGenContext -> FieldName -> TypeName
toArgsTypeName
        Maybe TypeName -> m [ServerDeclaration] -> m [ServerDeclaration]
forall (m :: * -> *) a.
MonadReader ServerCodeGenContext m =>
Maybe TypeName -> m a -> m a
inType (TypeName -> Maybe TypeName
forall a. a -> Maybe a
Just TypeName
tName) (m [ServerDeclaration] -> m [ServerDeclaration])
-> m [ServerDeclaration] -> m [ServerDeclaration]
forall a b. (a -> b) -> a -> b
$ do
          let argumentFields :: [FieldDefinition IN CONST]
argumentFields = ArgumentDefinition CONST -> FieldDefinition IN CONST
forall (s :: Stage). ArgumentDefinition s -> FieldDefinition IN s
argument (ArgumentDefinition CONST -> FieldDefinition IN CONST)
-> [ArgumentDefinition CONST] -> [FieldDefinition IN CONST]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ArgumentsDefinition CONST -> [ArgumentDefinition CONST]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ArgumentsDefinition CONST
arguments
          [CodeGenField]
fields <- (FieldDefinition IN CONST -> m CodeGenField)
-> [FieldDefinition IN CONST] -> m [CodeGenField]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition IN CONST -> m CodeGenField
forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m CodeGenField
renderDataField [FieldDefinition IN CONST]
argumentFields
          let typename :: Text
typename = TypeName -> Text
toHaskellTypeName TypeName
tName
          [ServerDirectiveUsage]
namespaceDirs <- Text -> m [ServerDirectiveUsage]
forall (m :: * -> *).
CodeGenM m =>
Text -> m [ServerDirectiveUsage]
getNamespaceDirs Text
typename
          [ServerDirectiveUsage]
dirs <- [[ServerDirectiveUsage]] -> [ServerDirectiveUsage]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ServerDirectiveUsage]] -> [ServerDirectiveUsage])
-> m [[ServerDirectiveUsage]] -> m [ServerDirectiveUsage]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition IN CONST -> m [ServerDirectiveUsage])
-> [FieldDefinition IN CONST] -> m [[ServerDirectiveUsage]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition IN CONST -> m [ServerDirectiveUsage]
forall (m :: * -> *) a.
(CodeGenM m, Meta a) =>
a -> m [ServerDirectiveUsage]
getDirectives [FieldDefinition IN CONST]
argumentFields
          let cgTypeName :: CodeGenTypeName
cgTypeName = TypeName -> CodeGenTypeName
fromTypeName (Text -> TypeName
forall a (t :: NAME). NamePacking a => a -> Name t
forall (t :: NAME). Text -> Name t
packName Text
typename)
          [ServerDirectiveUsage]
defaultValueDirs <- [[ServerDirectiveUsage]] -> [ServerDirectiveUsage]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ServerDirectiveUsage]] -> [ServerDirectiveUsage])
-> m [[ServerDirectiveUsage]] -> m [ServerDirectiveUsage]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FieldDefinition IN CONST -> m [ServerDirectiveUsage])
-> [FieldDefinition IN CONST] -> m [[ServerDirectiveUsage]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse FieldDefinition IN CONST -> m [ServerDirectiveUsage]
forall (m :: * -> *) (c :: TypeCategory).
CodeGenM m =>
FieldDefinition c CONST -> m [ServerDirectiveUsage]
getDefaultValueDir [FieldDefinition IN CONST]
argumentFields
          [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
            [ CodeGenType -> ServerDeclaration
DataType
                CodeGenType
                  { CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgTypeName :: CodeGenTypeName
cgTypeName,
                    cgConstructors :: [CodeGenConstructor]
cgConstructors = TypeName -> [CodeGenField] -> [CodeGenConstructor]
mkObjectCons TypeName
tName [CodeGenField]
fields,
                    cgDerivations :: [DerivingClass]
cgDerivations = Bool -> [DerivingClass]
derivesClasses Bool
False
                  },
              GQLTypeDefinition -> ServerDeclaration
gqlTypeToInstance
                GQLTypeDefinition
                  { gqlTarget :: CodeGenTypeName
gqlTarget = CodeGenTypeName
cgTypeName,
                    gqlKind :: Kind
gqlKind = Kind
Type,
                    gqlTypeDirectiveUses :: [ServerDirectiveUsage]
gqlTypeDirectiveUses = [ServerDirectiveUsage]
namespaceDirs [ServerDirectiveUsage]
-> [ServerDirectiveUsage] -> [ServerDirectiveUsage]
forall a. Semigroup a => a -> a -> a
<> [ServerDirectiveUsage]
dirs [ServerDirectiveUsage]
-> [ServerDirectiveUsage] -> [ServerDirectiveUsage]
forall a. Semigroup a => a -> a -> a
<> [ServerDirectiveUsage]
defaultValueDirs
                  }
            ]
genArgumentType FieldDefinition OUT CONST
_ = [ServerDeclaration] -> m [ServerDeclaration]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []

getInputFields :: TypeDefinition c s -> [FieldDefinition IN s]
getInputFields :: forall (c :: TypeCategory) (s :: Stage).
TypeDefinition c s -> [FieldDefinition IN s]
getInputFields TypeDefinition {typeContent :: forall (a :: TypeCategory) (s :: Stage).
TypeDefinition a s -> TypeContent TRUE a s
typeContent = DataInputObject {FieldsDefinition IN s
inputObjectFields :: FieldsDefinition IN s
inputObjectFields :: forall (s :: Stage) (a :: TypeCategory).
CondTypeContent INPUT_OBJECT a s -> FieldsDefinition IN s
inputObjectFields}} = FieldsDefinition IN s -> [FieldDefinition IN s]
forall a. OrdMap FieldName a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList FieldsDefinition IN s
inputObjectFields
getInputFields TypeDefinition c s
_ = []