bond-haskell-compiler-0.1.3.0: src/Language/Bond/Codegen/Haskell/EnumDecl.hs
module Language.Bond.Codegen.Haskell.EnumDecl (
enumDecl,
enumHsBootDecl
) where
import Language.Bond.Syntax.Types
import Language.Bond.Codegen.TypeMapping (MappingContext(..))
import Language.Bond.Codegen.Haskell.Util
import Language.Haskell.Exts hiding (mode)
import Language.Haskell.Exts.SrcLoc (noLoc)
enumDecl :: CodegenOpts -> MappingContext -> ModuleName -> Declaration -> Maybe Module
enumDecl _ ctx moduleName decl@Enum{} = Just source
where
source = Module noLoc moduleName
[ LanguagePragma noLoc
[ Ident "GeneralizedNewtypeDeriving"
, Ident "DeriveDataTypeable"
, Ident "OverloadedStrings"
]
]
Nothing
Nothing
[importInternalModule, importPrelude]
(dataDecl : bondTypeDecl : bondEnumDecl : typeSig : values)
typeName = mkType $ makeDeclName decl
typeCon = TyCon (UnQual typeName)
dataDecl = DataDecl noLoc NewType [] typeName []
[ QualConDecl noLoc [] [] (ConDecl typeName [implType "Int32"]) ]
[ (pQual "Show", []), (pQual "Eq", []), (implQual "NFData", []), (pQual "Ord", []), (pQual "Enum", [])
, (implQual "Hashable", []), (implQual "Default", []), (implQual "Typeable", [])
]
bondTypeDecl = InstDecl noLoc Nothing [] [] (implQual "BondType")
[ typeCon ]
[ InsDecl $
FunBind
[Match noLoc (Ident "bondPut")
[PParen (PApp (UnQual typeName) [PVar $ Ident "v'"])]
Nothing
(UnGuardedRhs $
App (Var $ implQual "bondPut") (Var $ unqual "v'"))
noBinds]
, InsDecl $
PatBind noLoc (PVar $ Ident "bondGet")
(UnGuardedRhs $
appFun (Var $ pQual "fmap") [Con $ UnQual typeName, Var $ implQual "bondGet"])
noBinds
, InsDecl $ wildcardFunc "getName" $ strE (declName decl)
, InsDecl $ wildcardFunc "getQualifiedName" $ strE (getDeclTypeName ctx{namespaceMapping = []} decl)
, InsDecl $ wildcardFunc "getElementType" $ Con (implQual "ElementInt32")
]
bondEnumDecl = InstDecl noLoc Nothing [] [] (implQual "BondEnum")
[ typeCon ]
[ InsDecl $ FunBind $ map makeToNameMatch consts ++ [wildcardMatch "toName" $ Var $ pQual "Nothing"]
, InsDecl $ FunBind $ map makeFromNameMatch consts ++ [wildcardMatch "fromName" $ Var $ pQual "Nothing"]
]
makeToNameMatch (constName, i) =
Match noLoc (Ident "toName") [ PParen $ PApp (UnQual typeName) [intP $ fromIntegral i] ]
Nothing (UnGuardedRhs $ App (Var $ pQual "Just") (strE constName)) noBinds
makeFromNameMatch (constName, _) =
Match noLoc (Ident "fromName") [ strP constName ]
Nothing (UnGuardedRhs $ App (Var $ pQual "Just") (Var $ UnQual $ mkVar constName)) noBinds
typeSig = TypeSig noLoc (map (mkVar . constantName) (enumConstants decl)) typeCon
consts = makeConst 0 (enumConstants decl)
makeConst _ [] = []
makeConst _ (Constant{constantName = cname, constantValue = Just i} : xs)
= (cname, i) : makeConst (i + 1) xs
makeConst i (Constant{constantName = cname} : xs)
= (cname, i) : makeConst (i + 1) xs
values = map makeValue consts
makeValue (constName, val) = patBind noLoc (PVar $ mkVar constName) $ App (Con $ UnQual typeName) (parenIntL val)
enumDecl _ _ _ _ = error "enumDecl called for invalid type"
enumHsBootDecl :: CodegenOpts -> MappingContext -> ModuleName -> Declaration -> Maybe Module
enumHsBootDecl _ _ moduleName decl@Enum{} = Just hsboot
where
hsboot = Module noLoc moduleName [] Nothing Nothing [importInternalModule{importSrc = True}, importPrelude] [
DataDecl noLoc NewType [] typeName [] [QualConDecl noLoc [] [] (ConDecl typeName [implType "Int32"])] [],
showInstance,
eqInstance,
typeSig
]
typeName = mkType $ makeDeclName decl
typeCon = TyCon (UnQual typeName)
typeSig = TypeSig noLoc (map (mkVar . constantName) (enumConstants decl)) typeCon
showInstance = InstDecl noLoc Nothing [] [] (pQual "Show") [typeCon] []
eqInstance = InstDecl noLoc Nothing [] [] (pQual "Eq") [typeCon] []
enumHsBootDecl _ _ _ _ = error "enumDecl called for invalid type"