module MagicHaskeller.ExecuteAPI610 where
import qualified HscMain
import GHC
import GHC.Exts
import GHC.Paths(libdir)
import DynFlags
import SrcLoc (SrcSpan(..), noSrcSpan, noSrcLoc, interactiveSrcLoc, noLoc)
import CorePrep(corePrepExpr)
import FastString
import ByteCodeGen ( coreExprToBCOs )
import Linker
import HscTypes
import SimplCore
import VarEnv ( emptyTidyEnv )
import CoreSyn ( CoreExpr, Expr(..), Bind(..) )
import CoreTidy ( tidyExpr )
import Parser (parseStmt)
import Lexer
import TcRnDriver ( tcRnStmt, tcRnExpr, tcRnType )
import Desugar (deSugarExpr)
#if __GLASGOW_HASKELL__ < 708
import PrelNames ( iNTERACTIVE )
#else
import PrelNames (mkInteractiveModule)
#endif
import ErrUtils
import StringBuffer (stringToStringBuffer)
import Outputable (ppr, pprPanic, showSDocDebug, showSDoc)
import Type (pprType, Type)
import CoreLint (lintUnfolding)
import VarSet (varSetElems)
import Panic (panic)
import Var
import System.IO
import System.IO.Unsafe
import Data.IORef
import System.Exit
import Control.Monad(when)
import MagicHaskeller.MyDynamic
import qualified MagicHaskeller.CoreLang as CoreLang
import Language.Haskell.TH as TH hiding (ppr)
import Data.List(isSuffixOf)
#ifdef GHC6
import TysPrim(anyPrimTy)
#endif
import Bag
import RdrName
import OccName
import Convert
import HsUtils
import HsExpr
import IdInfo
import Data.Char(ord,chr)
import qualified Data.Map as Map
import qualified MagicHaskeller.Types as Types
import Data.List
import Unique
import Id
import UniqSupply
import ByteCodeLink(linkBCO,extendClosureEnv)
#ifdef PRELINK
# if __GLASGOW_HASKELL__ >= 800
import ByteCodeTypes(UnlinkedBCO(unlinkedBCOName))
# else
import ByteCodeAsm(UnlinkedBCO(unlinkedBCOName))
# endif
#endif
# if __GLASGOW_HASKELL__ >= 800
import GHCi(wormhole)
#endif
import Data.Array
pathToGHC :: FilePath
pathToGHC = libdir
loadObj :: [String]
-> IO (CoreLang.VarLib -> CoreLang.CoreExpr -> Dynamic)
loadObj fss = fmap unsafeExecuteAPI $ prepareAPI [] fss
prepareAPI :: [FilePath]
-> [FilePath]
-> IO HscEnv
prepareAPI loadfss visfss
#if __GLASGOW_HASKELL__ >= 700
# if __GLASGOW_HASKELL__ >= 706
= defaultErrorHandler defaultFatalMessager defaultFlushOut $
# else
= defaultErrorHandler defaultLogAction $
# endif
#else
= defaultErrorHandler defaultDynFlags $
#endif
runGhc (Just pathToGHC) $ do
dfs <- getSessionDynFlags
let newf = dfs{
packageFlags = [ packageNameToFlag "ghc", packageNameToFlag "old-time", packageNameToFlag "ghc-paths" ]
}
setSessionDynFlags newf
ts <- mapM (\fs -> guessTarget fs Nothing) loadfss
setTargets ts
sf <- defaultCleanupHandler newf (load LoadAllTargets)
case sf of Succeeded -> return ()
Failed -> error "failed to load modules"
#if __GLASGOW_HASKELL__ >= 700
modules <- mapM (\fs -> fmap (\x -> (x,Nothing)) $ findModule (mkModuleName fs) Nothing) ("Prelude":visfss)
#else
modules <- mapM (\fs -> findModule (mkModuleName fs) Nothing) ("Prelude":visfss)
#endif
#if __GLASGOW_HASKELL__ >= 700
setContext [ IIDecl $ (simpleImportDecl . mkModuleName $ moduleName){GHC.ideclQualified = False} | moduleName <- "Prelude":visfss ]
#else
setContext [] modules
#endif
#ifdef PRELINK
newdfs <- getSessionDynFlags
initDynLinker newdfs
#endif
getSession
packageNameToFlag :: String -> PackageFlag
#if __GLASGOW_HASKELL__ < 710
packageNameToFlag = ExposePackage
#else
# if __GLASGOW_HASKELL__ < 800
packageNameToFlag name = ExposePackage (PackageArg name) (ModRenaming False [])
# else
packageNameToFlag name = ExposePackage ("-package "++name) (PackageArg name) (ModRenaming False [])
# endif
#endif
unsafeExecuteAPI :: HscEnv -> CoreLang.VarLib -> CoreLang.CoreExpr -> Dynamic
unsafeExecuteAPI session vl cece = unsafeToDyn undefined undefined (unsafeCoerce# $ unsafePerformIO $ executeAPI session vl cece) undefined
executeAPI :: HscEnv -> CoreLang.VarLib -> CoreLang.CoreExpr -> IO a
executeAPI session vl cece = executeTHExp session (CoreLang.exprToTHExp vl cece)
executeTHExp :: HscEnv -> TH.Exp -> IO a
executeTHExp session the = unwrapCore session =<< compileCoreExpr session the
compileCoreExpr :: HscEnv -> TH.Exp -> IO CoreSyn.CoreExpr
compileCoreExpr hscEnv the
=
do mbt <- stmtToCore hscEnv $ thExpToStmt hscEnv the
case mbt of Nothing -> error ("could not compile " ++ TH.pprint the ++ " to core.")
Just ([i ], ce) -> return ce
unwrapCore :: HscEnv -> CoreSyn.CoreExpr -> IO a
unwrapCore hscEnv ce = do
iohvs <- unsafeCoerce# $ compileExprHscMain hscEnv ce
[hv] <- iohvs
return hv
#if __GLASGOW_HASKELL__ >= 800
ce2b hscEnv pe = coreExprToBCOs hscEnv undefined pe
#else
# if __GLASGOW_HASKELL__ >= 700
ce2b hscEnv pe = coreExprToBCOs (hsc_dflags hscEnv) undefined pe
# else
ce2b hscEnv pe = coreExprToBCOs (hsc_dflags hscEnv) pe
# endif
#endif
runCoreExpr, runPrepedCoreExpr :: HscEnv -> CoreExpr -> IO a
runCoreExpr hscEnv ce
=
do
let dfs = hsc_dflags hscEnv
#if __GLASGOW_HASKELL__ >= 706
pe <- corePrepExpr dfs hscEnv ce
#else
pe <- corePrepExpr dfs ce
#endif
bcos <-
ce2b hscEnv pe
#ifdef PRELINK
hv <- linkTheExpr bcos
#else
hv <-linkExpr hscEnv noSrcSpan bcos
#endif
return $ unsafeCoerce# hv
runPrepedCoreExpr hscEnv ce
=
do
bcos <- ce2b hscEnv ce
#ifdef PRELINK
hv <- linkTheExpr bcos
#else
hv <-linkExpr hscEnv noSrcSpan bcos
#endif
return $ unsafeCoerce# hv
#ifdef PRELINK
linkTheExpr :: UnlinkedBCO -> IO HValue
linkTheExpr ulbco
= do pls <- readIORef v_PersistentLinkerState
let ie = itbl_env pls
ce = closure_env pls
nm = unlinkedBCOName ulbco
fixIO (\hv -> linkBCO ie (extendClosureEnv ce [(nm,hv)]) ulbco)
#endif
stmtToCore hscEnv pst = do let dfs = hsc_dflags hscEnv
icxt = hsc_IC hscEnv
#if __GLASGOW_HASKELL__ >= 708
(tcmsgs, mbtc) <- tcRnStmt hscEnv pst
#else
(tcmsgs, mbtc) <- tcRnStmt hscEnv icxt pst
#endif
case mbtc of Nothing -> perror dfs tcmsgs
#if __GLASGOW_HASKELL__ >= 706
Just (ids, tc_expr, _fixtyenv) -> do
#else
Just (ids, tc_expr) -> do
#endif
#if __GLASGOW_HASKELL__ >= 708
(desmsgs, mbds) <- deSugarExpr hscEnv tc_expr
#else
# if __GLASGOW_HASKELL__ >= 700
let typeEnv = mkTypeEnv (ic_tythings icxt)
# else
let typeEnv = mkTypeEnv (map AnId (ic_tmp_ids icxt))
# endif
(desmsgs, mbds) <- deSugarExpr hscEnv iNTERACTIVE (ic_rn_gbl_env icxt) typeEnv tc_expr
#endif
case mbds of Nothing -> perror dfs desmsgs
Just ds -> return (Just (ids, ds))
#if __GLASGOW_HASKELL__ >= 706
perror dfs (wmsg,emsg) = printBagOfErrors dfs wmsg >> printBagOfErrors dfs emsg >> return Nothing
#else
# if __GLASGOW_HASKELL__ >= 700
perror dfs (wmsg,emsg) = let sdocs = pprErrMsgBag wmsg ++ pprErrMsgBag emsg in mapM_ (printError noSrcSpan) sdocs >> return Nothing
# else
perror dfs msg = printErrorsAndWarnings dfs msg >> return Nothing
# endif
#endif
thExpToStmt hscEnv = wrapLHsExpr . thExpToLHsExpr hscEnv
wrapLHsExpr expr =
noLoc $ LetStmt $
#if __GLASGOW_HASKELL__ >= 800
noLoc $
#endif
HsValBinds (ValBindsIn (Bag.unitBag (HsUtils.mk_easy_FunBind noSrcSpan (Unqual $ mkOccName OccName.varName "__cmCompileExpr") [] expr)) [])
thExpToLHsExpr :: HscEnv -> TH.Exp -> HsExpr.LHsExpr RdrName.RdrName
thExpToLHsExpr hscEnv e = case Convert.convertToHsExpr noSrcSpan e of
#if __GLASGOW_HASKELL__ >= 706
Left msg -> error $ showSDoc (hsc_dflags hscEnv) msg
#else
Left msg -> error $ showSDoc msg
#endif
Right expr -> expr
#if __GLASGOW_HASKELL__ < 706
instance Show b => Show (Expr b) where
showsPrec p (Var var) = ("Var "++) . (showSDocDebug (ppr var) ++)
showsPrec _ (Lit l) = ("Lit "++) . shows l
showsPrec _ (App e0@(App _ _) e1) = shows e0 . (" `App` "++) . showParen True (shows e1)
showsPrec _ (App e0 e1) = showParen True (shows e0) . (" `App` "++) . showParen True (shows e1)
showsPrec _ (Lam v e) = ('\\':) . shows v . shows e
showsPrec _ (Let bs e) = ("let"++) . shows bs . (" in "++) . shows e
showsPrec _ (Case _ _ _ _) = ("case"++)
showsPrec _ (Cast e t) = ("Cast "++) . showParen True (shows e) . ("<Coercion>"++)
showsPrec _ (Type t) = (showSDoc (pprType t) ++)
instance Show b => Show (Bind b) where
showsPrec _ (NonRec b e) = (' ':) . shows b . (" = "++) . shows e
showsPrec _ (Rec ts ) = ("rec { "++) . foldr (.) id (map hoge ts) . (" } "++)
hoge :: Show b => (b, Expr b) -> ShowS
hoge (b, e) = shows b . (" = "++) . shows e . (" ; "++)
#endif
compileExprHscMain :: HscEnv -> CoreExpr -> IO HValue
compileExprHscMain hscEnv ce
= do let dflags = hsc_dflags hscEnv
smpl <- simplifyExpr dflags ce
#if __GLASGOW_HASKELL__ >= 706
prep <- corePrepExpr dflags hscEnv smpl
#else
prep <- corePrepExpr dflags smpl
#endif
bcos <- ce2b hscEnv prep
linkExpr hscEnv noSrcSpan bcos
#if __GLASGOW_HASKELL__ >= 800
>>= wormhole dflags
#endif
#ifdef GHC6
unsafeDirectExecuteAPI hscEnv gm ce = unsafePerformIO $ directExecuteAPI hscEnv gm ce
directExecuteAPI :: HscEnv -> GlobalAr -> CoreLang.CoreExpr -> IO a
directExecuteAPI hscEnv gm ce
= runCoreExpr hscEnv $ ceToCSCE gm ce
compileVar :: HscEnv -> (a, TH.Exp, TH.Type) -> IO CoreSyn.CoreExpr
compileVar hscEnv (_, the, ty)
= do csce <- compileCoreExpr hscEnv the
let unr = unwrap csce
putStrLn ("csce = "++show unr)
case ty of TH.ForallT tvs [] _ -> do let dfs = hsc_dflags hscEnv
simplifyExpr dfs $ foldl CoreSyn.App unr $ replicate (length tvs) $ CoreSyn.Type anyPrimTy
_ -> return unr
unwrap (Let (Rec ((_,e):_)) _) = e
unwrap st = error (show st)
unforall (TH.ForallT _ _ t) = t
unforall t = t
type GlobalMap = Map.Map String CoreSyn.CoreExpr
mkGlobalMap :: HscEnv -> [(a, TH.Exp, TH.Type)] -> IO GlobalMap
mkGlobalMap hscEnv tups = do ces <- mapM (compileVar hscEnv) tups
return $ Map.fromList $ zip (map (\(_,b,_) -> thToBaseString b) tups) ces
thExpToCSCE :: GlobalMap -> TH.Exp -> CoreSyn.CoreExpr
thExpToCSCE gm ce = ctc [] ce
where ctc pvs (TH.LamE pvars e) = foldr CoreSyn.Lam (ctc (pvars++pvs) e) (map (mkStrVar . show . unVarP) pvars)
ctc pvs (e0 `TH.AppE` e1) = ctc pvs e0 `CoreSyn.App` ctc pvs e1
ctc pvs (InfixE (Just e0) e (Just e1)) = lup e `CoreSyn.App` ctc pvs e0 `CoreSyn.App` ctc pvs e1
ctc pvs (TH.VarE name) | VarP name `elem` pvs = CoreSyn.Var $ mkStrVar $ show name
ctc pvs e = lup e
lup e = case Map.lookup (thToBaseString e) gm of Nothing -> error (show e ++ ", i.e.,\n" ++ TH.pprint e ++ " : could not convert to CoreSyn.CoreExpr")
Just csce -> csce
thToBaseString (ConE name) = nameBase name
thToBaseString (VarE name) = nameBase name
unVarP (TH.VarP n) = n
mkIntVar i = Id.mkUserLocal (mkVarOcc [chr i]) (Unique.getUnique i) anyPrimTy noSrcSpan
mkStrVar str = Id.mkUserLocal (mkVarOcc str) (Unique.getUnique $ mkFastString str) anyPrimTy noSrcSpan
type GlobalAr = Array Int CoreSyn.CoreExpr
mkGlobalAr :: HscEnv -> [(a, TH.Exp, TH.Type)] -> IO GlobalAr
mkGlobalAr hscEnv tups = do ces <- mapM (compileVar hscEnv) tups
return $ listArray (0, length tups 1) ces
ceToCSCE :: GlobalAr -> CoreLang.CoreExpr -> CoreSyn.CoreExpr
ceToCSCE ga ce = ctc (ord 'a'1) ce
where ctc dep (CoreLang.Lambda e) = CoreSyn.Lam (mkIntVar (dep+1)) $ ctc (dep+1) e
ctc dep (CoreLang.X n) = CoreSyn.Var $ mkIntVar (depn)
ctc dep (CoreLang.Primitive n _) = ga ! n
ctc dep (e0 CoreLang.:$ e1) = ctc dep e0 `CoreSyn.App` ctc dep e1
es = map mkIntVar [ord 'e'..]
as = map mkIntVar [128..]
xs = map mkIntVar [192..]
hd = mkIntVar (ord 'a')
mkTV :: Int -> Types.Type
mkTV = Types.TV
tvrs = map mkTV [1..]
tvas = map mkTV [2000..]
tvr = mkTV 0
hdmnPreped :: Int -> Int -> CoreSyn.CoreExpr
hdmnPreped m 0 = hdmn m 0
hdmnPreped m n = lambdas $ lets $ foldl CoreSyn.App (CoreSyn.Var hd) (map CoreSyn.Var mxs)
where
mes = take m es
mxs = take m xs
nas = take n as
lambdas = flip (foldr ($)) (map CoreSyn.Lam (hd : mes ++ nas))
lets = flip (foldr CoreSyn.Let) binds
where binds = zipWith CoreSyn.NonRec mxs $ map appa1an mes
where appa1an var = foldl CoreSyn.App (CoreSyn.Var var) $ map CoreSyn.Var nas
hdmn m n = lambdas $ foldl CoreSyn.App (CoreSyn.Var hd) $ map appa1an mes
where appa1an var = foldl CoreSyn.App (CoreSyn.Var var) $ map CoreSyn.Var nas
mes = take m es
nas = take n as
lambdas = flip (foldr ($)) (map CoreSyn.Lam (hd : mes ++ nas))
hdmnty :: Int -> Int -> Types.Type
hdmnty m n = hdty Types.:-> foldr (Types.:->) (foldr (Types.:->) tvr nas) (map (\r -> foldr (Types.:->) r nas) mrs)
where hdty = foldr (Types.:->) tvr mrs
mrs = take m tvrs
nas = take n tvas
aimnPreped i m n = lambdas $ foldl CoreSyn.App (CoreSyn.Var (as!!i)) (map CoreSyn.Var mxs)
where mes = take m es
mxs = take m xs
nas = take n as
lambdas = flip (foldr ($)) (map CoreSyn.Lam (mes ++ nas))
lets = flip (foldr CoreSyn.Let) binds
where binds = zipWith CoreSyn.NonRec mxs $ map appa1an mes
where appa1an var = foldl CoreSyn.App (CoreSyn.Var var) $ map CoreSyn.Var nas
aimn i m n = lambdas $ foldl CoreSyn.App (CoreSyn.Var (as!!i)) $ map appa1an mes
where appa1an var = foldl CoreSyn.App (CoreSyn.Var var) $ map CoreSyn.Var nas
mes = take m es
nas = take n as
lambdas = flip (foldr ($)) (map CoreSyn.Lam (mes ++ nas))
aimnty :: Int -> Int -> Int -> Types.Type
aimnty i m n = foldr (Types.:->) (foldr (Types.:->) tvr nas) (map (\r -> foldr (Types.:->) r nas) mrs)
where hdty = foldr (Types.:->) tvr mrs
mrs = take m tvrs
nas = case splitAt i tvas of (tk,_:dr) -> tk ++ hdty : take (ni1) dr
mkHdmn :: HscEnv -> Int -> Int -> IO Dynamic
mkHdmn hscEnv m n = do let ce = hdmn m n
val <- runCoreExpr hscEnv ce
return $ unsafeToDyn undefined (hdmnty m n) val undefined
mkAimn :: HscEnv -> Int -> Int -> Int -> IO Dynamic
mkAimn hscEnv i m n = do let ce = aimn i m n
val <- runCoreExpr hscEnv ce
return $ unsafeToDyn undefined (aimnty i m n) val undefined
#endif
repeatN n f x = force $ map f $ replicate n x
repeatIO n act = fmap force $ sequence $ replicate n act
force = foldr1 seq
instance Eq (Expr a) where
Var i == Var j = True
Lit l == Lit m = l==m
App f e == App g i = g==f && e==i
Lam b e == Lam c f = e==f
Let b e == Let c f = e==f
Case e b t ab == Case f c u bc = e==f
Cast e c == Cast f d = e==f
Type t == Type u = True