+++ /dev/null
-module CLasH.Utils.HsTools where
-
--- Standard modules
-import qualified Unsafe.Coerce
-import qualified Maybe
-
--- GHC API
-import qualified GHC
-import qualified HscMain
-import qualified HscTypes
-import qualified DynFlags
-import qualified FastString
-import qualified StringBuffer
-import qualified MonadUtils
-import Outputable ( showSDoc, ppr )
-import qualified Outputable
--- Lexer & Parser, i.e. up to HsExpr
-import qualified Lexer
-import qualified Parser
--- HsExpr representation, renaming, typechecking and desugaring
--- (i.e., everything up to Core).
-import qualified HsSyn
-import qualified HsExpr
-import qualified HsTypes
-import qualified HsBinds
-import qualified TcRnMonad
-import qualified TcRnTypes
-import qualified RnExpr
-import qualified RnEnv
-import qualified TcExpr
-import qualified TcEnv
-import qualified TcSimplify
-import qualified TcTyFuns
-import qualified Desugar
-import qualified PrelNames
-import qualified Module
-import qualified OccName
-import qualified RdrName
-import qualified Name
-import qualified SrcLoc
-import qualified LoadIface
-import qualified BasicTypes
--- Core representation and handling
-import qualified CoreSyn
-import qualified Id
-import qualified Type
-import qualified TyCon
-
--- | Translate a HsExpr to a Core expression. This does renaming, type
--- checking, simplification of class instances and desugaring. The result is
--- a let expression that holds the given expression and a number of binds that
--- are needed for any type classes used to work. For example, the HsExpr:
--- \x = x == (1 :: Int)
--- will result in the CoreExpr
--- let
--- $dInt = ...
--- (==) = Prelude.(==) Int $dInt
--- in
--- \x = (==) x 1
-toCore ::
- HsSyn.HsExpr RdrName.RdrName -- ^ The expression to translate to Core.
- -> GHC.Ghc CoreSyn.CoreExpr -- ^ The resulting core expression.
-toCore expr = do
- env <- GHC.getSession
- let icontext = HscTypes.hsc_IC env
-
- (binds, tc_expr) <- HscTypes.ioMsgMaybe $ MonadUtils.liftIO $
- -- Translage the TcRn (typecheck-rename) monad into an IO monad
- TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
- (tc_expr, insts) <- TcRnMonad.getLIE $ do
- -- Rename the expression, resulting in a HsExpr Name
- (rn_expr, freevars) <- RnExpr.rnExpr expr
- -- Typecheck the expression, resulting in a HsExpr Id and a list of
- -- Insts
- (res, _) <- TcExpr.tcInferRho (SrcLoc.noLoc rn_expr)
- return res
- -- Translate the instances into bindings
- --(insts', binds) <- TcSimplify.tcSimplifyRuleLhs insts
- binds <- TcSimplify.tcSimplifyTop insts
- return (binds, tc_expr)
-
- -- Create a let expression with the extra binds (for polymorphism etc.) and
- -- the resulting expression.
- let letexpr = SrcLoc.noLoc $ HsExpr.HsLet
- (HsBinds.HsValBinds $ HsBinds.ValBindsOut [(BasicTypes.NonRecursive, binds)] [])
- tc_expr
- -- Desugar the expression, resulting in core.
- let rdr_env = HscTypes.ic_rn_gbl_env icontext
- HscTypes.ioMsgMaybe $ Desugar.deSugarExpr env PrelNames.iNTERACTIVE rdr_env HscTypes.emptyTypeEnv letexpr
-
-
--- | Create an Id from a RdrName. Might not work for DataCons...
-mkId :: RdrName.RdrName -> GHC.Ghc Id.Id
-mkId rdr_name = do
- env <- GHC.getSession
- HscTypes.ioMsgMaybe $ MonadUtils.liftIO $
- -- Translage the TcRn (typecheck-rename) monad in an IO monad
- TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $
- -- Automatically import all available modules, so fully qualified names
- -- always work
- TcRnMonad.setOptM DynFlags.Opt_ImplicitImportQualified $ do
- -- Lookup a Name for the RdrName. This finds the package (version) in
- -- which the name resides.
- name <- RnEnv.lookupGlobalOccRn rdr_name
- -- Lookup an Id for the Name. This finds out the the type of the thing
- -- we're looking for.
- --
- -- Note that tcLookupId doesn't seem to work for DataCons. See source for
- -- tcLookupId to find out.
- TcEnv.tcLookupId name
-
-normalizeType ::
- HscTypes.HscEnv
- -> Type.Type
- -> IO Type.Type
-normalizeType env ty = do
- (err, nty) <- MonadUtils.liftIO $
- -- Initialize the typechecker monad
- TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
- -- Normalize the type
- (_, nty) <- TcTyFuns.tcNormaliseFamInst ty
- return nty
- let normalized_ty = Maybe.fromJust nty
- return normalized_ty
-
--- | Translate a core Type to an HsType. Far from complete so far.
-coreToHsType :: Type.Type -> HsTypes.LHsType RdrName.RdrName
--- Translate TyConApps
-coreToHsType ty = case Type.splitTyConApp_maybe ty of
- Just (tycon, tys) ->
- foldl (\t a -> SrcLoc.noLoc $ HsTypes.HsAppTy t a) tycon_ty (map coreToHsType tys)
- where
- tycon_name = TyCon.tyConName tycon
- mod_name = Module.moduleName $ Name.nameModule tycon_name
- occ_name = Name.nameOccName tycon_name
- tycon_rdrname = RdrName.mkRdrQual mod_name occ_name
- tycon_ty = SrcLoc.noLoc $ HsTypes.HsTyVar tycon_rdrname
- Nothing -> error "HsTools.coreToHsType Cannot translate non-tycon type"
-
--- | Evaluate a CoreExpr and return its value. For this to work, the caller
--- should already know the result type for sure, since the result value is
--- unsafely coerced into this type.
-execCore :: CoreSyn.CoreExpr -> GHC.Ghc a
-execCore expr = do
- -- Setup session flags (yeah, this seems like a noop, but
- -- setSessionDynFlags really does some extra work...)
- dflags <- GHC.getSessionDynFlags
- GHC.setSessionDynFlags dflags
- -- Compile the expressions. This runs in the IO monad, but really wants
- -- to run an IO-monad-inside-a-GHC-monad for some reason. I don't really
- -- understand what it means, but it works.
- env <- GHC.getSession
- let srcspan = SrcLoc.noSrcSpan
- hval <- MonadUtils.liftIO $ HscMain.compileExpr env srcspan expr
- let res = Unsafe.Coerce.unsafeCoerce hval :: Int
- return $ Unsafe.Coerce.unsafeCoerce hval
-
--- These functions build (parts of) a LHSExpr RdrName.
-
--- | A reference to the Prelude.undefined function.
-hsUndef :: HsExpr.LHsExpr RdrName.RdrName
-hsUndef = SrcLoc.noLoc $ HsExpr.HsVar PrelNames.undefined_RDR
-
--- | A typed reference to the Prelude.undefined function.
-hsTypedUndef :: HsTypes.LHsType RdrName.RdrName -> HsExpr.LHsExpr RdrName.RdrName
-hsTypedUndef ty = SrcLoc.noLoc $ HsExpr.ExprWithTySig hsUndef ty
-
--- | Create a qualified RdrName from a module name and a variable name
-mkRdrName :: String -> String -> RdrName.RdrName
-mkRdrName mod var =
- RdrName.mkRdrQual (Module.mkModuleName mod) (OccName.mkVarOcc var)
-
--- These three functions are simplified copies of those in HscMain, because
--- those functions are not exported. These versions have all error handling
--- removed.
-hscParseType = hscParseThing Parser.parseType
-hscParseStmt = hscParseThing Parser.parseStmt
-
-hscParseThing :: Lexer.P thing -> DynFlags.DynFlags -> String -> GHC.Ghc thing
-hscParseThing parser dflags str = do
- buf <- MonadUtils.liftIO $ StringBuffer.stringToStringBuffer str
- let loc = SrcLoc.mkSrcLoc (FastString.fsLit "<interactive>") 1 0
- let Lexer.POk _ thing = Lexer.unP parser (Lexer.mkPState buf loc dflags)
- return thing
-
--- | This function imports the module with the given name, for the renamer /
--- typechecker to use. It also imports any "orphans" and "family instances"
--- from modules included by this module, but not the actual modules
--- themselves. I'm not 100% sure how this works, but it seems that any
--- functions defined in included modules are available just by loading the
--- original module, and by doing this orphan stuff, any (type family or class)
--- instances are available as well.
---
--- Most of the code is based on tcRnImports and rnImportDecl, but those
--- functions do a lot more (which I hope we won't need...).
-importModule :: Module.ModuleName -> TcRnTypes.RnM ()
-importModule mod = do
- let reason = Outputable.text "Hardcoded import" -- Used for trace output
- let pkg = Nothing
- -- Load the interface.
- iface <- LoadIface.loadSrcInterface reason mod False pkg
- -- Load orphan an familiy instance dependencies as well. I think these
- -- dependencies are needed for the type checker to know all instances. Any
- -- other instances (on other packages) are only useful to the
- -- linker, so we can probably safely ignore them here. Dependencies within
- -- the same package are also listed in deps, but I'm not so sure what to do
- -- with them.
- let deps = HscTypes.mi_deps iface
- let orphs = HscTypes.dep_orphs deps
- let finsts = HscTypes.dep_finsts deps
- LoadIface.loadOrphanModules orphs False
- LoadIface.loadOrphanModules finsts True