{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} -- | Type Constructors in CoreHW module CLaSH.Core.TyCon ( TyCon (..) , TyConName , AlgTyConRhs (..) , PrimRep (..) , mkKindTyCon , isTupleTyConLike , tyConDataCons ) where -- External Import import Control.DeepSeq import Unbound.LocallyNameless as Unbound hiding (rnf) import Unbound.LocallyNameless.Name (Name(Nm,Bn)) -- Internal Imports import {-# SOURCE #-} CLaSH.Core.DataCon (DataCon) import {-# SOURCE #-} CLaSH.Core.Term (Term) import {-# SOURCE #-} CLaSH.Core.Type (Kind, TyName, Type) import CLaSH.Util -- | Type Constructor data TyCon -- | Algorithmic DataCons = AlgTyCon { tyConName :: TyConName -- ^ Name of the TyCon , tyConKind :: Kind -- ^ Kind of the TyCon , tyConArity :: Int -- ^ Number of type arguments , algTcRhs :: AlgTyConRhs -- ^ DataCon definitions } -- | Primitive TyCons | PrimTyCon { tyConName :: TyConName -- ^ Name of the TyCon , tyConKind :: Kind -- ^ Kind of the TyCon , tyConArity :: Int -- ^ Number of type arguments , primTyConRep :: PrimRep -- ^ Representation } -- | To close the loop on the type hierarchy | SuperKindTyCon { tyConName :: TyConName -- ^ Name of the TyCon } instance Show TyCon where show (AlgTyCon {tyConName = n}) = "AlgTyCon: " ++ show n show (PrimTyCon {tyConName = n}) = "PrimTyCon: " ++ show n show (SuperKindTyCon {tyConName = n}) = "SuperKindTyCon: " ++ show n instance Eq TyCon where (==) = (==) `on` tyConName instance Ord TyCon where compare = compare `on` tyConName -- | TyCon reference type TyConName = Name TyCon -- | The RHS of an Algebraic Datatype data AlgTyConRhs = DataTyCon { dataCons :: [DataCon] -- ^ The DataCons of a TyCon } | NewTyCon { dataCon :: DataCon -- ^ The newtype DataCon , ntEtadRhs :: ([TyName],Type) -- ^ The argument type of the newtype -- DataCon in eta-reduced form, which is -- just the representation of the TyCon. -- The TyName's are the type-variables from -- the corresponding TyCon. } deriving Show -- | Representations for primitive types data PrimRep = IntRep | VoidRep deriving Show Unbound.derive [''TyCon,''AlgTyConRhs,''PrimRep] instance Alpha PrimRep instance Alpha TyCon where swaps' _ _ d = d fv' _ _ = emptyC lfreshen' _ a f = f a empty freshen' _ a = return (a,empty) aeq' _ tc1 tc2 = aeq (tyConName tc1) (tyConName tc2) acompare' _ tc1 tc2 = acompare (tyConName tc1) (tyConName tc2) open _ _ d = d close _ _ d = d isPat _ = error "isPat TyCon" isTerm _ = error "isTerm TyCon" isEmbed _ = error "isEmbed TyCon" nthpatrec _ = error "nthpatrec TyCon" findpatrec _ _ = error "findpatrec TyCon" instance Alpha AlgTyConRhs instance Subst Type TyCon instance Subst Type AlgTyConRhs instance Subst Type PrimRep instance Subst Term TyCon instance Subst Term AlgTyConRhs instance Subst Term PrimRep instance NFData TyCon where rnf tc = case tc of AlgTyCon nm ki ar rhs -> rnf nm `seq` rnf ki `seq` rnf ar `seq` rnf rhs PrimTyCon nm ki ar rep -> rnf nm `seq` rnf ki `seq` rnf ar `seq` rnf rep SuperKindTyCon nm -> rnf nm instance NFData (Name TyCon) where rnf nm = case nm of (Nm _ s) -> rnf s (Bn _ l r) -> rnf l `seq` rnf r instance NFData AlgTyConRhs where rnf rhs = case rhs of DataTyCon dcs -> rnf dcs NewTyCon dc eta -> rnf dc `seq` rnf eta instance NFData PrimRep where rnf pm = case pm of IntRep -> () VoidRep -> () -- | Create a Kind out of a TyConName mkKindTyCon :: TyConName -> Kind -> TyCon mkKindTyCon name kind = PrimTyCon name kind 0 VoidRep -- | Does the TyCon look like a tuple TyCon isTupleTyConLike :: TyConName -> Bool isTupleTyConLike nm = tupleName (name2String nm) where tupleName nm | '(' <- head nm , ')' <- last nm = all (== ',') (init $ tail nm) tupleName _ = False -- | Get the DataCons belonging to a TyCon tyConDataCons :: TyCon -> [DataCon] tyConDataCons (AlgTyCon {algTcRhs = DataTyCon { dataCons = cons}}) = cons tyConDataCons (AlgTyCon {algTcRhs = NewTyCon { dataCon = con }}) = [con] tyConDataCons _ = []