evoke-0.2022.8.26: source/library/Evoke/Generator/ToJSON.hs
module Evoke.Generator.ToJSON
( generate,
)
where
import qualified Data.List as List
import qualified Evoke.Constant.Module as Module
import qualified Evoke.Generator.Common as Common
import qualified Evoke.Hs as Hs
import qualified Evoke.Hsc as Hsc
import qualified Evoke.Options as Options
import qualified Evoke.Type.Constructor as Constructor
import qualified Evoke.Type.Field as Field
import qualified Evoke.Type.Type as Type
import qualified GHC.Plugins as Ghc
generate :: Common.Generator
generate _ lIdP lHsQTyVars lConDecls options srcSpan = do
type_ <- Type.make lIdP lHsQTyVars lConDecls srcSpan
case Type.constructors type_ of
[_] -> pure ()
_ -> Hsc.throwError srcSpan $ Ghc.text "requires exactly one constructor"
modifyFieldName <-
Common.applyAll
<$> Options.parse (Common.fieldNameOptions srcSpan) options srcSpan
fieldNames <-
mapM (fromField modifyFieldName)
. List.sort
. fmap Field.name
. concatMap Constructor.fields
$ Type.constructors type_
aeson <- Common.makeRandomModule Module.dataAeson
monoid <- Common.makeRandomModule Module.dataMonoid
string <- Common.makeRandomModule Module.dataString
var1 <- Common.makeRandomVariable srcSpan "var_"
var2 <- Common.makeRandomVariable srcSpan "var_"
let lImportDecls =
Hs.importDecls
srcSpan
[ (Module.dataAeson, aeson),
(Module.dataMonoid, monoid),
(Module.dataString, string)
]
toPair lRdrName (occName, fieldName) =
Hs.opApp
srcSpan
( Hs.app srcSpan (Hs.qualVar srcSpan string $ Ghc.mkVarOcc "fromString")
. Hs.lit srcSpan
$ Hs.string fieldName
)
(Hs.qualVar srcSpan aeson $ Ghc.mkVarOcc ".=")
. Hs.app srcSpan (Hs.var srcSpan $ Hs.unqual srcSpan occName)
$ Hs.var srcSpan lRdrName
lHsExprs lRdrName = fmap (toPair lRdrName) fieldNames
toJSON =
Common.makeLHsBind
srcSpan
(Ghc.mkVarOcc "toJSON")
[Hs.varPat srcSpan var1]
. Hs.app srcSpan (Hs.qualVar srcSpan aeson $ Ghc.mkVarOcc "object")
. Hs.explicitList srcSpan
$ lHsExprs var1
toEncoding =
Common.makeLHsBind
srcSpan
(Ghc.mkVarOcc "toEncoding")
[Hs.varPat srcSpan var2]
. Hs.app srcSpan (Hs.qualVar srcSpan aeson $ Ghc.mkVarOcc "pairs")
. Hs.par srcSpan
. Hs.app srcSpan (Hs.qualVar srcSpan monoid $ Ghc.mkVarOcc "mconcat")
. Hs.explicitList srcSpan
$ lHsExprs var2
lHsDecl =
Common.makeInstanceDeclaration
srcSpan
type_
aeson
(Ghc.mkClsOcc "ToJSON")
[toJSON, toEncoding]
pure (lImportDecls, [lHsDecl])
fromField ::
(String -> Ghc.Hsc String) -> Ghc.OccName -> Ghc.Hsc (Ghc.OccName, String)
fromField modifyFieldName occName = do
fieldName <- modifyFieldName $ Ghc.occNameString occName
pure (occName, fieldName)