hydra-0.1.0: src/main/haskell/Hydra/Ext/Graphql/Coder.hs
module Hydra.Ext.Graphql.Coder where -- (printGraph) where
import Hydra.All
--import Hydra.Adapter
--import Hydra.Adapters.Term
--import Hydra.CoreDecoding
--import Hydra.CoreLanguage
--import Hydra.Adapters.Coders
--import Hydra.Ext.Graphql.Language
--import Hydra.Ext.Graphql.Serde
--import qualified Hydra.Ext.Graphql.Syntax as G
--import qualified Hydra.Impl.Haskell.Dsl.Types as Types
--import Hydra.Util.Codetree.Script
import qualified Control.Monad as CM
import qualified Data.List as L
import qualified Data.Map as M
import qualified Data.Maybe as Y
--printGraph :: (Ord m, Read m, Show m) => Graph m -> GraphFlow m (M.Map FilePath String)
--printGraph g = do
-- sf <- moduleToGraphqlSchema g
-- let s = printExpr $ parenthesize $ exprDocument sf
-- return $ M.fromList [(graphNameToFilePath False (FileExtension "graphql") $ graphName g, s)]
--
--constructModule :: (Ord m, Read m, Show m)
-- => Graph m
-- -> M.Map (Type m) (Coder (Context m) (Term m) ())
-- -> [(Element m, TypedTerm m)]
-- -> GraphFlow m G.Document
--constructModule g coders pairs = do
-- fail "TODO"
---- let ns = pdlNameForGraph g
---- let pkg = Nothing
---- let imports = [] -- TODO
---- sortedPairs <- case (topologicalSortElements $ fst <$> pairs) of
---- Nothing -> fail $ "types form a cycle (unsupported in PDL)"
---- Just sorted -> pure $ Y.catMaybes $ fmap (\n -> M.lookup n pairByName) sorted
---- schemas <- CM.mapM toSchema sortedPairs
---- return $ PDL.SchemaFile ns pkg imports schemas
---- where
---- pairByName = L.foldl (\m p@(el, tt) -> M.insert (elementName el) p m) M.empty pairs
---- aliases = importAliasesForGraph g
---- toSchema (el, TypedTerm typ term) = if stripType typ == TypeNominal _Type
---- then decodeType term >>= typeToSchema el
---- else fail $ "mapping of non-type elements to PDL is not yet supported: " ++ show typ
---- typeToSchema el typ = do
---- let qname = pdlNameForElement aliases False $ elementName el
---- res <- encodeAdaptedType aliases typ
---- let ptype = case res of
---- Left schema -> PDL.NamedSchema_TypeTyperef schema
---- Right t -> t
---- cx <- getState
---- r <- annotationClassTermDescription (contextAnnotations cx) $ elementTerm el
---- let anns = doc r
---- return $ PDL.NamedSchema qname ptype anns
--
--moduleToGraphqlSchema :: (Ord m, Read m, Show m) => Graph m -> GraphFlow m G.Document
--moduleToGraphqlSchema g = graphToExternalModule language (encodeTerm aliases) constructModule g
-- where
-- aliases = importAliasesForGraph g
--
----doc :: Y.Maybe String -> PDL.Annotations
----doc s = PDL.Annotations s False
----
----encodeAdaptedType :: (Ord m, Read m, Show m)
---- => M.Map GraphName String -> Type m
---- -> GraphFlow m (Either PDL.Schema PDL.NamedSchema_Type)
----encodeAdaptedType aliases typ = do
---- cx <- getState
---- let acx = AdapterContext cx hydraCoreLanguage language
---- ad <- withState acx $ termAdapter typ
---- encodeType aliases $ adapterTarget ad
--
--encodeTerm :: (Eq m, Ord m, Read m, Show m) => M.Map GraphName String -> Term m -> GraphFlow m ()
--encodeTerm aliases term = fail "term encoding is not yet implemented"
--
----encodeType :: (Eq m, Show m) => M.Map GraphName String -> Type m -> GraphFlow m (Either PDL.Schema PDL.NamedSchema_Type)
----encodeType aliases typ = case stripType typ of
---- TypeList lt -> Left . PDL.SchemaArray <$> encode lt
---- TypeLiteral lt -> Left . PDL.SchemaPrimitive <$> case lt of
---- LiteralTypeBinary -> pure PDL.PrimitiveTypeBytes
---- LiteralTypeBoolean -> pure PDL.PrimitiveTypeBoolean
---- LiteralTypeFloat ft -> case ft of
---- FloatTypeFloat32 -> pure PDL.PrimitiveTypeFloat
---- FloatTypeFloat64 -> pure PDL.PrimitiveTypeDouble
---- _ -> fail $ "unexpected floating-point type: " ++ show ft
---- LiteralTypeInteger it -> case it of
---- IntegerTypeInt32 -> pure PDL.PrimitiveTypeInt
---- IntegerTypeInt64 -> pure PDL.PrimitiveTypeLong
---- _ -> fail $ "unexpected integer type: " ++ show it
---- LiteralTypeString -> pure PDL.PrimitiveTypeString
---- TypeMap (MapType kt vt) -> Left . PDL.SchemaMap <$> encode vt -- note: we simply assume string as a key type
---- TypeNominal name -> pure $ Left $ PDL.SchemaNamed $ pdlNameForElement aliases True name
---- TypeOptional ot -> fail $ "optionals unexpected at top level"
---- TypeRecord (RowType _ fields) -> do
---- let includes = []
---- rfields <- CM.mapM encodeRecordField fields
---- return $ Right $ PDL.NamedSchema_TypeRecord $ PDL.RecordSchema rfields includes
---- TypeUnion (RowType _ fields) -> if isEnum
---- then do
---- fs <- CM.mapM encodeEnumField fields
---- return $ Right $ PDL.NamedSchema_TypeEnum $ PDL.EnumSchema fs
---- else Left . PDL.SchemaUnion . PDL.UnionSchema <$> CM.mapM encodeUnionField fields
---- where
---- isEnum = L.foldl (\b t -> b && stripType t == Types.unit) True $ fmap fieldTypeType fields
---- _ -> fail $ "unexpected type: " ++ show typ
---- where
---- encode t = case stripType t of
---- TypeRecord (RowType _ []) -> encode Types.int32 -- special case for the unit type
---- _ -> do
---- res <- encodeType aliases t
---- case res of
---- Left schema -> pure schema
---- Right _ -> fail $ "type resolved to an unsupported nested named schema: " ++ show t
---- encodeRecordField (FieldType (FieldName name) typ) = do
---- anns <- getAnns typ
---- (schema, optional) <- encodePossiblyOptionalType typ
---- return PDL.RecordField {
---- PDL.recordFieldName = PDL.FieldName name,
---- PDL.recordFieldValue = schema,
---- PDL.recordFieldOptional = optional,
---- PDL.recordFieldDefault = Nothing,
---- PDL.recordFieldAnnotations = anns}
---- encodeUnionField (FieldType (FieldName name) typ) = do
---- anns <- getAnns typ
---- (s, optional) <- encodePossiblyOptionalType typ
---- let schema = if optional
---- then PDL.SchemaUnion $ PDL.UnionSchema (simpleUnionMember <$> [PDL.SchemaNull, s])
---- else s
---- return PDL.UnionMember {
---- PDL.unionMemberAlias = Just $ PDL.FieldName name,
---- PDL.unionMemberValue = schema,
---- PDL.unionMemberAnnotations = anns}
---- encodeEnumField (FieldType (FieldName name) typ) = do
---- anns <- getAnns typ
---- return PDL.EnumField {
---- PDL.enumFieldName = PDL.EnumFieldName $ convertCase CaseCamel CaseUpperSnake name,
---- PDL.enumFieldAnnotations = anns}
---- encodePossiblyOptionalType typ = case stripType typ of
---- TypeOptional ot -> do
---- t <- encode ot
---- return (t, True)
---- _ -> do
---- t <- encode typ
---- return (t, False)
---- getAnns typ = do
---- cx <- getState
---- r <- annotationClassTypeDescription (contextAnnotations cx) typ
---- return $ doc r
--
--importAliasesForGraph g = M.empty -- TODO
--
----noAnnotations :: PDL.Annotations
----noAnnotations = PDL.Annotations Nothing False
----
----pdlNameForElement :: M.Map GraphName String -> Bool -> Name -> PDL.QualifiedName
----pdlNameForElement aliases withNs name = PDL.QualifiedName (PDL.Name local)
---- $ if withNs
---- then PDL.Namespace . slashesToDots <$> alias
---- else Nothing
---- where
---- (ns, local) = toQname name
---- alias = M.lookup ns aliases
----
----pdlNameForGraph :: Graph m -> PDL.Namespace
----pdlNameForGraph = PDL.Namespace . slashesToDots . h . graphName
---- where
---- h (GraphName n) = n
----
----simpleUnionMember :: PDL.Schema -> PDL.UnionMember
----simpleUnionMember schema = PDL.UnionMember Nothing schema noAnnotations
----
----slashesToDots :: String -> String
----slashesToDots = fmap (\c -> if c == '/' then '.' else c)