g2-0.2.0.0: src/G2/Translation/Interface.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module G2.Translation.Interface ( translateBase
, translateLoaded
, specialInject ) where
import Control.Monad.Extra
import qualified Data.HashMap.Lazy as HM
import Data.List
import Data.Maybe
import qualified Data.Text as T
import System.Directory
import G2.Config
import G2.Language as G2
import G2.Translation.GHC
import G2.Translation.Haskell
import G2.Translation.InjectSpecials
import G2.Translation.PrimInject
import G2.Translation.TransTypes
translateBase :: TranslationConfig
-> Config
-> [FilePath]
-> Maybe HscTarget
-> IO (ExtractedG2, NameMap, TypeNameMap)
translateBase tr_con config extra hsc = do
-- For base we have the advantage of knowing apriori the structure
-- So we can list the (proj, file) pairings
let base_inc = baseInclude config
let bases = nub $ base config ++ extra
(base_exg2, b_nm, b_tnm) <- translateLibPairs specialConstructors specialTypeNames tr_con emptyExtractedG2 hsc base_inc bases
let base_prog = exg2_binds base_exg2
base_tys = exg2_tycons base_exg2
let base_tys' = base_tys `HM.union` specialTypes
let base_prog' = addPrimsToBase base_tys' base_prog
return (base_exg2 { exg2_binds = base_prog', exg2_tycons = base_tys' }, b_nm, b_tnm)
translateLibPairs :: NameMap
-> TypeNameMap
-> TranslationConfig
-> ExtractedG2
-> Maybe HscTarget
-> [IncludePath]
-> [FilePath]
-> IO (ExtractedG2, NameMap, TypeNameMap)
translateLibPairs nm tnm _ exg2 _ _ [] = return (exg2, nm, tnm)
translateLibPairs nm tnm tr_con exg2 hsc inc_paths (f: fs) = do
(new_nm, new_tnm, exg2') <- hskToG2ViaCgGutsFromFile hsc inc_paths [f] nm tnm tr_con
translateLibPairs new_nm new_tnm tr_con (mergeExtractedG2s [exg2, exg2']) hsc inc_paths fs
#if MIN_VERSION_GLASGOW_HASKELL(9,6,0,0)
selectBackend :: TranslationConfig -> Maybe Backend
selectBackend tr | interpreter tr = Just interpreterBackend
selectBackend _ = Just noBackend
#elif MIN_VERSION_GLASGOW_HASKELL(9,2,0,0)
selectBackend :: TranslationConfig -> Maybe Backend
selectBackend tr | interpreter tr = Just Interpreter
selectBackend _ = Just NoBackend
#else
selectBackend :: TranslationConfig -> Maybe HscTarget
selectBackend tr | interpreter tr = Just HscInterpreted
selectBackend _ = Just HscNothing
#endif
translateLoaded :: [FilePath]
-> [FilePath]
-> TranslationConfig
-> Config
-> IO (Maybe T.Text, ExtractedG2)
translateLoaded proj src tr_con config = do
let tr_con' = tr_con { hpc_ticks = hpc config || search_strat config == Subpath }
-- Stuff with the actual target
let def_proj = extraDefaultInclude config
tar_ems <- envModSumModGutsFromFile (selectBackend tr_con') (def_proj ++ proj) src tr_con'
let imports = envModSumModGutsImports tar_ems
extra_imp <- return . catMaybes =<< mapM (findImports (baseInclude config)) imports
-- Stuff with the base library
(base_exg2, b_nm, b_tnm) <- translateBase tr_con' config extra_imp Nothing
-- Now the stuff with the actual target
(f_nm, f_tm, exg2) <- hskToG2ViaEMS tr_con' tar_ems b_nm b_tnm
let mb_modname = head $ exg2_mod_names exg2
let exg2' = adjustMkSymbolicPrim f_nm exg2
let merged_exg2 = mergeExtractedG2s [exg2', base_exg2]
let injected_exg2@ExtractedG2 { exg2_binds = near_final_prog } = specialInject merged_exg2
final_prog <- absVarLoc near_final_prog
let final_exg2 = injected_exg2 { exg2_binds = final_prog }
return (mb_modname, final_exg2)
adjustMkSymbolicPrim :: NameMap -> ExtractedG2 -> ExtractedG2
adjustMkSymbolicPrim nm exg2@(ExtractedG2 { exg2_binds = binds}) =
let
a = Id (Name "a" Nothing 0 Nothing) TYPE
m_sym_n = HM.lookup ("symgen", Just "G2.Symbolic") nm
symgen_e = G2.Lam TypeL a (SymGen SLog $ TyVar a)
in
case m_sym_n of
Just sym_n -> exg2 { exg2_binds = HM.insert sym_n symgen_e binds }
Nothing -> exg2
specialInject :: ExtractedG2 -> ExtractedG2
specialInject exg2 =
let
prog = exg2_binds exg2
tys = exg2_tycons exg2
rules = exg2_rules exg2
cls = exg2_classes exg2
(prog', tys', rules') = primInject $ dataInject (prog, tys, rules) tys
cls' = primInject cls
in
exg2 { exg2_binds = prog'
, exg2_tycons = tys'
, exg2_rules = rules'
, exg2_classes = cls' }
findImports :: [FilePath] -> FilePath -> IO (Maybe FilePath)
findImports roots fp = do
let fp' = map (\c -> if c == '.' then '/' else c) fp
mr <- findM (\r -> doesFileExist $ r ++ fp' ++ ".hs") roots
case mr of
Just r -> return . Just $ r ++ fp' ++ ".hs"
Nothing -> return Nothing