1{-# LANGUAGE ScopedTypeVariables #-}
2--tools to execute an atom function body
3module ProjectM36.AtomFunctionBody where
7import Control.Monad.IO.Class
8import Control.Exception
9import Data.Text hiding (map)
13import GHC.Paths (libdir)
16import Outputable hiding ((<>))
18import Type hiding (pprTyThing)
19import System.FilePath.Glob
21data ScriptSession = ScriptSession {
23 atomFunctionBodyType :: Type
26data ScriptSessionError = ScriptSessionLoadError GhcException
29-- | Configure a GHC environment/session which we will use for all script compilation.
30initScriptSession :: [String] -> IO (Either ScriptSessionError ScriptSession)
31initScriptSession ghcPkgPaths = do
32 --for the sake of convenience, for developers' builds, include the local cabal sandbox pacakge database
33 sandboxPkgPaths <- liftIO (glob ".cabal-sandbox/*packages.conf.d")
34 let excHandler exc = pure $ Left (ScriptSessionLoadError exc)
35 handleGhcException excHandler $ runGhc (Just libdir) $ do
36 dflags <- getSessionDynFlags
37 let localPkgPaths = map PkgConfFile (ghcPkgPaths ++ sandboxPkgPaths)
39 let dflags' = dflags { hscTarget = HscInterpreted ,
40 ghcLink = LinkInMemory,
41 safeHaskell = Sf_Trustworthy,
44 --trustFlags = [TrustPackage "base"] -- new in 8
45 packageFlags = (packageFlags dflags) ++ packages,
46 extraPkgConfs = const ([GlobalPkgConf, UserPkgConf] ++ localPkgPaths)
48 `xopt_set` Opt_ExtendedDefaultRules
49 `xopt_set` Opt_ImplicitPrelude
50 `xopt_set` Opt_OverloadedStrings
51 `gopt_set` Opt_DistrustAllPackages
52 `xopt_set` Opt_ScopedTypeVariables
53 `gopt_set` Opt_PackageTrust
54 --`gopt_set` Opt_ImplicitImportQualified
55 packages = map TrustPackage ["base",
57 "unordered-containers",
63 "vector-binary-instances",
66 "bytestring"] -- package flags changed in 8.0
67 _ <- setSessionDynFlags dflags'
68 let safeImportDecl mn = ImportDecl {
69 ideclSourceSrc = Nothing,
71 ideclPkgQual = Nothing,
74 ideclImplicit = False,
75 ideclQualified = False,
79 setContext (map (\modn -> IIDecl $ safeImportDecl (mkModuleName modn))
84 fType <- mkAtomFunctionBodyType
85 pure (Right (ScriptSession env fType))
87mkAtomFunctionBodyType :: Ghc Type
88mkAtomFunctionBodyType = do
89 lBodyName <- parseName "AtomFunctionBodyType"
91 [] -> error "failed to parse AtomFunctionBodyType"
92 _:_:_ -> error "too many name matches"
94 mThing <- lookupName bodyName
96 Nothing -> error "failed to find AtomFunctionBodyType"
97 Just (ATyCon tyCon) -> case synTyConRhs_maybe tyCon of
99 Nothing -> error "AtomFunctionBodyType is not a type synonym"
100 Just _ -> error "failed to find type synonym AtomFunctionBodyType"
102addImport :: String -> Ghc ()
103addImport moduleNam = do
105 setContext ( (IIDecl $ simpleImportDecl (mkModuleName moduleNam)) : ctx )
107showType :: DynFlags -> Type -> String
108showType dflags ty = showSDocForUser dflags alwaysQualify (pprTypeForUser ty)
110-- | Typecheck and validate the
111typeCheckAtomFunctionScript :: Type -> AtomFunctionBodyScript -> Ghc (Maybe AtomFunctionBodyCompilationError)
112typeCheckAtomFunctionScript expectedType inp = do
113 dflags <- getSessionDynFlags
114 --catch exception for SyntaxError
115 funcType <- GHC.exprType (unpack inp)
117 if eqType funcType expectedType then
120 pure (Just (TypeCheckCompilationError (showType dflags expectedType) (showType dflags funcType)))
122-- | After compiling the script, it must accept a list of Atoms and return an Atom, otherwise an AtomFunctionBodyCompilationError is returned
123compileAtomFunctionScript :: ScriptSession -> AtomFunctionBodyScript -> Ghc (Either AtomFunctionBodyCompilationError AtomFunctionBodyType)
124compileAtomFunctionScript (ScriptSession _ funcType) script = do
125 let sScript = unpack script
126 mErr <- typeCheckAtomFunctionScript funcType script
128 Just err -> pure (Left err)
130 --catch exception here
131 --we could potentially wrap the script with Atom pattern matching so that the script doesn't have to do it, but the change to an Atom ADT should make it easier. Still, it would be nice if the script didn't have to handle a list of arguments, for example.
132 -- we can't use dynCompileExpr here because
133 func <- compileExpr sScript
134 pure $ Right (unsafeCoerce func)
136catchCompileException :: MonadIO m => IO a -> m (Either AtomFunctionBodyCompilationError a)
137catchCompileException m = liftIO $ do
140 Left (err :: SomeException) -> do
141 pure (Left (OtherScriptCompilationError (show err)))
142 Right res -> pure (Right res)
144compiledAtomFunctionBody :: AtomFunctionBodyType -> AtomFunctionBody
145compiledAtomFunctionBody func = AtomFunctionBody Nothing func
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list