clash-0.1: CLasH/Utils/Core/BinderTools.hs
--
-- This module contains functions that manipulate binders in various ways.
--
module CLasH.Utils.Core.BinderTools where
-- Standard modules
import qualified Data.Accessor.Monad.Trans.State as MonadState
-- GHC API
import qualified CoreSyn
import qualified Type
import qualified UniqSupply
import qualified Unique
import qualified OccName
import qualified Name
import qualified Module
import qualified Var
import qualified SrcLoc
import qualified IdInfo
import qualified CoreUtils
-- Local imports
import CLasH.Translator.TranslatorTypes
-- Create a new Unique
mkUnique :: TranslatorSession Unique.Unique
mkUnique = do
us <- MonadState.get tsUniqSupply
let (us', us'') = UniqSupply.splitUniqSupply us
MonadState.set tsUniqSupply us'
return $ UniqSupply.uniqFromSupply us''
-- Create a new internal var with the given name and type. A Unique is
-- appended to the given name, to ensure uniqueness (not strictly neccesary,
-- since the Unique is also stored in the name, but this ensures variable
-- names are unique in the output).
mkInternalVar :: String -> Type.Type -> TranslatorSession Var.Var
mkInternalVar str ty = do
uniq <- mkUnique
let occname = OccName.mkVarOcc (str ++ show uniq)
let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
return $ Var.mkLocalVar IdInfo.VanillaId name ty IdInfo.vanillaIdInfo
-- Create a new type variable with the given name and kind. A Unique is
-- appended to the given name, to ensure uniqueness (not strictly neccesary,
-- since the Unique is also stored in the name, but this ensures variable
-- names are unique in the output).
mkTypeVar :: String -> Type.Kind -> TranslatorSession Var.Var
mkTypeVar str kind = do
uniq <- mkUnique
let occname = OccName.mkVarOcc (str ++ show uniq)
let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
return $ Var.mkTyVar name kind
-- Creates a binder for the given expression with the given name. This
-- works for both value and type level expressions, so it can return a Var or
-- TyVar (which is just an alias for Var).
mkBinderFor :: CoreSyn.CoreExpr -> String -> TranslatorSession Var.Var
mkBinderFor (CoreSyn.Type ty) string = mkTypeVar string (Type.typeKind ty)
mkBinderFor expr string = mkInternalVar string (CoreUtils.exprType expr)
-- Creates a reference to the given variable. This works for both a normal
-- variable as well as a type variable
mkReferenceTo :: Var.Var -> CoreSyn.CoreExpr
mkReferenceTo var | Var.isTyVar var = (CoreSyn.Type $ Type.mkTyVarTy var)
| otherwise = (CoreSyn.Var var)
cloneVar :: Var.Var -> TranslatorSession Var.Var
cloneVar v = do
uniq <- mkUnique
-- Swap out the unique, and reset the IdInfo (I'm not 100% sure what it
-- contains, but vannillaIdInfo is always correct, since it means "no info").
return $ Var.lazySetIdInfo (Var.setVarUnique v uniq) IdInfo.vanillaIdInfo
-- Creates a new function with the same name as the given binder (but with a
-- new unique) and with the given function body. Returns the new binder for
-- this function.
mkFunction :: CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreBndr
mkFunction bndr body = do
let ty = CoreUtils.exprType body
id <- cloneVar bndr
let newid = Var.setVarType id ty
addGlobalBind newid body
return newid
-- Returns the full name of a NamedThing, in the forum
-- modulename.occname
getFullString :: Name.NamedThing a => a -> String
getFullString thing = modstr ++ occstr
where
name = Name.getName thing
modstr = case Name.nameModule_maybe name of
Nothing -> ""
Just mod -> Module.moduleNameString (Module.moduleName mod) ++ "."
occstr = Name.getOccString name