-compileToCore session@(Session ref) fn = do
- hsc_env <- readIORef ref
- -- First, determine the module name.
- modSummary <- summariseFile hsc_env [] fn Nothing Nothing
- let mod = moduleName $ ms_mod modSummary
- -- Next, parse and typecheck the module
- maybeCheckedModule <- checkModule session mod
- case maybeCheckedModule of
- Nothing -> return Nothing
- Just checkedMod -> do
- let parsedMod = parsedSource checkedMod
- -- Note: this typechecks the module twice (because checkModule
- -- also calls tcRnModule), but arranging for checkModule to
- -- return the type env would require changing a lot of data
- -- structures, so I'm leaving it like that for now.
- (_, maybe_tc_result) <- tcRnModule hsc_env HsSrcFile False parsedMod
- -- Get the type environment from the typechecking result
- case maybe_tc_result of
- -- TODO: this ignores the type error messages and just returns Nothing
- Nothing -> return Nothing
- Just tcgEnv -> do
- let dflags = hsc_dflags hsc_env
- -- Finally, compile to Core and return the resulting bindings
- maybeModGuts <- deSugar hsc_env (ms_location modSummary) tcgEnv
- case maybeModGuts of
- Nothing -> return Nothing
- Just mg -> return $ Just $ mg_binds mg
- -- ---------------------------------------------------------------------------
+compileToCore session fn = do
+ maybeCoreModule <- compileToCoreModule session fn
+ return $ fmap cm_binds maybeCoreModule
+
+-- | Takes a CoreModule and compiles the bindings therein
+-- to object code. The first argument is a bool flag indicating
+-- whether to run the simplifier.
+-- The resulting .o, .hi, and executable files, if any, are stored in the
+-- current directory, and named according to the module name.
+-- Returns True iff compilation succeeded.
+-- This has only so far been tested with a single self-contained module.
+compileCoreToObj :: Bool -> Session -> CoreModule -> IO Bool
+compileCoreToObj simplify session cm@(CoreModule{ cm_module = mName }) = do
+ hscEnv <- sessionHscEnv session
+ dflags <- getSessionDynFlags session
+ currentTime <- getClockTime
+ cwd <- getCurrentDirectory
+ modLocation <- mkHiOnlyModLocation dflags (hiSuf dflags) cwd
+ ((moduleNameSlashes . moduleName) mName)
+
+ let modSummary = ModSummary { ms_mod = mName,
+ ms_hsc_src = ExtCoreFile,
+ ms_location = modLocation,
+ -- By setting the object file timestamp to Nothing,
+ -- we always force recompilation, which is what we
+ -- want. (Thus it doesn't matter what the timestamp
+ -- for the (nonexistent) source file is.)
+ ms_hs_date = currentTime,
+ ms_obj_date = Nothing,
+ -- Only handling the single-module case for now, so no imports.
+ ms_srcimps = [],
+ ms_imps = [],
+ -- No source file
+ ms_hspp_file = "",
+ ms_hspp_opts = dflags,
+ ms_hspp_buf = Nothing
+ }
+
+ mbHscResult <- evalComp
+ ((if simplify then hscSimplify else return) (mkModGuts cm)
+ >>= hscNormalIface >>= hscWriteIface >>= hscOneShot)
+ (CompState{ compHscEnv=hscEnv,
+ compModSummary=modSummary,
+ compOldIface=Nothing})
+ return $ isJust mbHscResult
+
+-- Makes a "vanilla" ModGuts.
+mkModGuts :: CoreModule -> ModGuts
+mkModGuts coreModule = ModGuts {
+ mg_module = cm_module coreModule,
+ mg_boot = False,
+ mg_exports = [],
+ mg_deps = noDependencies,
+ mg_dir_imps = emptyModuleEnv,
+ mg_used_names = emptyNameSet,
+ mg_rdr_env = emptyGlobalRdrEnv,
+ mg_fix_env = emptyFixityEnv,
+ mg_types = emptyTypeEnv,
+ mg_insts = [],
+ mg_fam_insts = [],
+ mg_rules = [],
+ mg_binds = cm_binds coreModule,
+ mg_foreign = NoStubs,
+ mg_deprecs = NoDeprecs,
+ mg_hpc_info = emptyHpcInfo False,
+ mg_modBreaks = emptyModBreaks,
+ mg_vect_info = noVectInfo,
+ mg_inst_env = emptyInstEnv,
+ mg_fam_inst_env = emptyFamInstEnv
+}
+
+compileCore :: Bool -> Session -> FilePath -> IO (Maybe CoreModule)
+compileCore simplify session fn = do
+ -- First, set the target to the desired filename
+ target <- guessTarget fn Nothing
+ addTarget session target
+ load session LoadAllTargets
+ -- Then find dependencies
+ maybeModGraph <- depanal session [] True
+ case maybeModGraph of
+ Nothing -> return Nothing
+ Just modGraph -> do
+ case find ((== fn) . msHsFilePath) modGraph of
+ Just modSummary -> do
+ -- Now we have the module name;
+ -- parse, typecheck and desugar the module
+ let mod = ms_mod_name modSummary
+ maybeCheckedModule <- checkModule session mod True
+ case maybeCheckedModule of
+ Nothing -> return Nothing
+ Just checkedMod -> (liftM $ fmap gutsToCoreModule) $
+ case (coreModule checkedMod) of
+ Just mg | simplify -> (sessionHscEnv session)
+ -- If simplify is true: simplify (hscSimplify),
+ -- then tidy (tidyProgram).
+ >>= \ hscEnv -> evalComp (hscSimplify mg)
+ (CompState{ compHscEnv=hscEnv,
+ compModSummary=modSummary,
+ compOldIface=Nothing})
+ >>= (tidyProgram hscEnv)
+ >>= (return . Just . Left)
+ Just guts -> return $ Just $ Right guts
+ Nothing -> return Nothing
+ Nothing -> panic "compileToCoreModule: target FilePath not found in\
+ module dependency graph"
+ where -- two versions, based on whether we simplify (thus run tidyProgram,
+ -- which returns a (CgGuts, ModDetails) pair, or not (in which case
+ -- we just have a ModGuts.
+ gutsToCoreModule :: Either (CgGuts, ModDetails) ModGuts -> CoreModule
+ gutsToCoreModule (Left (cg, md)) = CoreModule {
+ cm_module = cg_module cg, cm_types = md_types md,
+ cm_imports = cg_dir_imps cg, cm_binds = cg_binds cg
+ }
+ gutsToCoreModule (Right mg) = CoreModule {
+ cm_module = mg_module mg, cm_types = mg_types mg,
+ cm_imports = moduleEnvKeys (mg_dir_imps mg), cm_binds = mg_binds mg
+ }
+
+-- ---------------------------------------------------------------------------