bond-haskell-compiler-0.1.0.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 : 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", []), (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")
]
typeSig = TypeSig noLoc (map (mkVar . constantName) (enumConstants decl)) typeCon
values = makeValue 0 (enumConstants decl)
makeValue _ [] = []
makeValue _ (Constant{constantName = cname, constantValue = Just i} : xs)
= mkConst cname i : makeValue (i + 1) xs
makeValue i (Constant{constantName = cname} : xs)
= mkConst cname i : makeValue (i + 1) xs
mkConst 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"