{-| Copyright : (C) 2012-2016, University of Twente, 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij Variables in CoreHW -} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} module Clash.Core.Var ( Attr' (..) , Var (..) , IdScope (..) , Id , TyVar , mkId , mkLocalId , mkGlobalId , mkTyVar , setVarUnique , setVarType , setIdScope , modifyVarName , isGlobalId , isLocalId , attrName ) where import Control.DeepSeq (NFData (..)) import Data.Binary (Binary) import Data.Function (on) import Data.Hashable (Hashable) import GHC.Generics (Generic) import Clash.Core.Name (Name (..)) import {-# SOURCE #-} Clash.Core.Term (Term, TmName) import {-# SOURCE #-} Clash.Core.Type (Kind, Type, TyName) import Clash.Unique -- | Interal version of Clash.Annotations.SynthesisAttributes.Attr. -- -- Needed because Clash.Annotations.SynthesisAttributes.Attr uses the Symbol -- kind for names, which do not have a term-level representation data Attr' = BoolAttr' String Bool | IntegerAttr' String Integer | StringAttr' String String | Attr' String deriving (Eq, Show, NFData, Generic, Hashable, Ord, Binary) attrName :: Attr' -> String attrName (BoolAttr' n _) = n attrName (IntegerAttr' n _) = n attrName (StringAttr' n _) = n attrName (Attr' n) = n -- | Variables in CoreHW data Var a -- | Constructor for type variables = TyVar { varName :: !(Name a) , varUniq :: {-# UNPACK #-} !Unique -- ^ Invariant: forall x . varUniq x ~ nameUniq (varName x) , varType :: Kind } -- | Constructor for term variables | Id { varName :: !(Name a) , varUniq :: {-# UNPACK #-} !Unique -- ^ Invariant: forall x . varUniq x ~ nameUniq (varName x) , varType :: Type , idScope :: IdScope } deriving (Show,Generic,NFData,Hashable,Binary) -- | Gets a _key_ in the DBMS sense: a value that uniquely identifies a -- Var. In case of a "Var" that is its unique and (if applicable) scope varKey :: Var a -> (Unique, Maybe IdScope) varKey TyVar{varUniq} = (varUniq, Nothing) varKey Id{varUniq,idScope} = (varUniq, Just idScope) instance Eq (Var a) where (==) = (==) `on` varKey (/=) = (/=) `on` varKey instance Ord (Var a) where compare = compare `on` varKey instance Uniquable (Var a) where getUnique = varUniq setUnique var u = var {varUniq=u, varName=(varName var){nameUniq=u}} data IdScope = GlobalId | LocalId deriving (Show,Generic,NFData,Hashable,Binary,Eq,Ord) -- | Term variable type Id = Var Term -- | Type variable type TyVar = Var Type -- | Change the name of a variable modifyVarName :: (Name a -> Name a) -> Var a -> Var a modifyVarName f (TyVar n _ k) = let n' = f n in TyVar n' (nameUniq n') k modifyVarName f (Id n _ t s) = let n' = f n in Id n' (nameUniq n') t s -- | Make a type variable mkTyVar :: Kind -> TyName -> TyVar mkTyVar tyKind tyName = TyVar tyName (nameUniq tyName) tyKind -- | Make a term variable mkId :: Type -> IdScope -> TmName -> Id mkId tmType scope tmName = Id tmName (nameUniq tmName) tmType scope mkLocalId :: Type -> TmName -> Id mkLocalId tmType tmName = Id tmName (nameUniq tmName) tmType LocalId mkGlobalId :: Type -> TmName -> Id mkGlobalId tmType tmName = Id tmName (nameUniq tmName) tmType GlobalId setVarUnique :: Var a -> Unique -> Var a setVarUnique v u = v { varUniq = u, varName = (varName v) {nameUniq = u} } setVarType :: Var a -> Type -> Var a setVarType v t = v { varType = t } isGlobalId :: Var a -> Bool isGlobalId (Id {idScope = GlobalId}) = True isGlobalId _ = False isLocalId :: Var a -> Bool isLocalId (Id {idScope = LocalId}) = True isLocalId _ = False setIdScope :: IdScope -> Var a -> Var a setIdScope s (Id nm u t _) = Id nm u t s setIdScope _ v = v