sv2v/src/Convert/Typedef.hs

84 lines
3.5 KiB
Haskell
Raw Normal View History

2019-02-18 09:59:17 +01:00
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `typedef`
-
- Aliased types can (probably) appear in all item declarations, including
- modules, blocks, and function parameters.
2019-02-18 09:59:17 +01:00
-}
module Convert.Typedef (convert) where
import Control.Monad.Writer
2019-02-18 09:59:17 +01:00
import qualified Data.Map as Map
import Convert.Traverse
2019-02-18 09:59:17 +01:00
import Language.SystemVerilog.AST
type Types = Map.Map Identifier Type
convert :: AST -> AST
convert descriptions =
traverseDescriptions removeTypedef $
traverseDescriptions (convertDescription types) $
descriptions
2019-02-18 09:59:17 +01:00
where
types = execWriter $ collectDescriptionsM getTypedef descriptions
getTypedef :: Description -> Writer Types ()
getTypedef (PackageItem (Typedef a b)) = tell $ Map.singleton b a
getTypedef _ = return ()
removeTypedef :: Description -> Description
removeTypedef (PackageItem (Typedef _ x)) =
PackageItem $ Comment $ "removed typedef: " ++ x
removeTypedef other = other
2019-02-18 09:59:17 +01:00
convertDescription :: Types -> Description -> Description
convertDescription globalTypes description =
traverseModuleItems removeTypedef $
traverseModuleItems (traverseExprs $ traverseNestedExprs $ convertExpr) $
traverseModuleItems (traverseTypes $ resolveType types) $
description
where
types = Map.union globalTypes $
execWriter $ collectModuleItemsM getTypedef description
getTypedef :: ModuleItem -> Writer Types ()
getTypedef (MIPackageItem (Typedef a b)) = tell $ Map.singleton b a
getTypedef _ = return ()
removeTypedef :: ModuleItem -> ModuleItem
removeTypedef (MIPackageItem (Typedef _ x)) =
MIPackageItem $ Comment $ "removed typedef: " ++ x
removeTypedef other = other
convertExpr :: Expr -> Expr
convertExpr (Bits (Right (Ident x))) =
if Map.member x types
then Bits $ Left $ resolveType types (Alias x [])
else Bits $ Right $ Ident x
convertExpr other = other
2019-02-18 09:59:17 +01:00
resolveType :: Types -> Type -> Type
resolveType _ (Net kw rs) = Net kw rs
resolveType _ (Implicit sg rs) = Implicit sg rs
resolveType _ (IntegerVector kw sg rs) = IntegerVector kw sg rs
resolveType _ (IntegerAtom kw sg ) = IntegerAtom kw sg
resolveType _ (NonInteger kw ) = NonInteger kw
resolveType _ (InterfaceT x my rs) = InterfaceT x my rs
2019-02-24 03:24:13 +01:00
resolveType _ (Enum Nothing vals rs) = Enum Nothing vals rs
resolveType types (Enum (Just t) vals rs) = Enum (Just $ resolveType types t) vals rs
2019-03-02 02:26:44 +01:00
resolveType types (Struct p items rs) = Struct p items' rs
where
items' = map resolveItem items
resolveItem (t, x) = (resolveType types t, x)
resolveType types (Alias st rs1) =
if Map.notMember st types
then InterfaceT st Nothing rs1
else case resolveType types $ types Map.! st of
(Net kw rs2) -> Net kw $ rs1 ++ rs2
(Implicit sg rs2) -> Implicit sg $ rs1 ++ rs2
(IntegerVector kw sg rs2) -> IntegerVector kw sg $ rs1 ++ rs2
(Enum t v rs2) -> Enum t v $ rs1 ++ rs2
(Struct p l rs2) -> Struct p l $ rs1 ++ rs2
(InterfaceT x my rs2) -> InterfaceT x my $ rs1 ++ rs2
(IntegerAtom kw _ ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
(NonInteger kw ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
2019-02-24 03:24:13 +01:00
(Alias _ _) -> error $ "resolveType invariant failed on " ++ st