1
1
mirror of https://github.com/anoma/juvix.git synced 2024-11-09 22:11:27 +03:00
juvix/app/App.hs

139 lines
4.6 KiB
Haskell
Raw Normal View History

module App where
2022-09-14 17:16:15 +03:00
import CommonOptions
import Data.ByteString qualified as ByteString
import GlobalOptions
import Juvix.Compiler.Builtins.Effect
import Juvix.Compiler.Pipeline
import Juvix.Data.Error qualified as Error
import Juvix.Prelude.Pretty hiding (Doc)
import System.Console.ANSI qualified as Ansi
data App m a where
ExitMsg :: ExitCode -> Text -> App m a
ExitJuvixError :: JuvixError -> App m a
PrintJuvixError :: JuvixError -> App m ()
2022-12-20 15:05:40 +03:00
AskInvokeDir :: App m (Path Abs Dir)
AskPkgDir :: App m (Path Abs Dir)
AskBuildDir :: App m (Path Abs Dir)
2022-09-14 17:16:15 +03:00
AskPackage :: App m Package
AskGlobalOptions :: App m GlobalOptions
RenderStdOut :: (HasAnsiBackend a, HasTextBackend a) => a -> App m ()
2022-12-20 15:05:40 +03:00
RunPipelineEither :: AppPath File -> Sem PipelineEff a -> App m (Either JuvixError (Artifacts, a))
Say :: Text -> App m ()
2022-12-20 15:05:40 +03:00
SayRaw :: ByteString -> App m ()
makeSem ''App
data RunAppIOArgs = RunAppIOArgs
{ _runAppIOArgsGlobalOptions :: GlobalOptions,
_runAppIOArgsInvokeDir :: Path Abs Dir,
_runAppIOArgsBuildDir :: Path Abs Dir,
_runAppIOArgsPkgDir :: Path Abs Dir,
_runAppIOArgsPkg :: Package
}
runAppIO ::
forall r a.
Member (Embed IO) r =>
RunAppIOArgs ->
Sem (App ': r) a ->
Sem r a
runAppIO args@RunAppIOArgs {..} =
interpret $ \case
RenderStdOut t
| _runAppIOArgsGlobalOptions ^. globalOnlyErrors -> return ()
| otherwise -> embed $ do
sup <- Ansi.hSupportsANSIColor stdout
renderIO (not (_runAppIOArgsGlobalOptions ^. globalNoColors) && sup) t
AskGlobalOptions -> return _runAppIOArgsGlobalOptions
AskPackage -> return _runAppIOArgsPkg
AskInvokeDir -> return _runAppIOArgsInvokeDir
AskPkgDir -> return _runAppIOArgsPkgDir
AskBuildDir -> return _runAppIOArgsBuildDir
RunPipelineEither input p -> do
entry <- embed (getEntryPoint' args input)
embed (runIOEither iniState entry p)
Say t
| g ^. globalOnlyErrors -> return ()
| otherwise -> embed (putStrLn t)
PrintJuvixError e -> do
printErr e
ExitJuvixError e -> do
printErr e
embed exitFailure
ExitMsg exitCode t -> embed (putStrLn t >> exitWith exitCode)
SayRaw b -> embed (ByteString.putStr b)
where
g :: GlobalOptions
g = _runAppIOArgsGlobalOptions
printErr e =
embed $ hPutStrLn stderr $ run $ runReader (project' @GenericOptions g) $ Error.render (not (_runAppIOArgsGlobalOptions ^. globalNoColors)) (g ^. globalOnlyErrors) e
getEntryPoint' :: RunAppIOArgs -> AppPath File -> IO EntryPoint
getEntryPoint' RunAppIOArgs {..} inputFile = do
let opts = _runAppIOArgsGlobalOptions
root = _runAppIOArgsPkgDir
2022-09-14 17:16:15 +03:00
estdin <-
if
| opts ^. globalStdin -> Just <$> getContents
| otherwise -> return Nothing
return
EntryPoint
{ _entryPointRoot = root,
2022-12-20 15:05:40 +03:00
_entryPointResolverRoot = root,
_entryPointBuildDir = _runAppIOArgsBuildDir,
2022-09-14 17:16:15 +03:00
_entryPointNoTermination = opts ^. globalNoTermination,
_entryPointNoPositivity = opts ^. globalNoPositivity,
_entryPointNoStdlib = opts ^. globalNoStdlib,
_entryPointPackage = _runAppIOArgsPkg,
_entryPointModulePaths = pure (someBaseToAbs _runAppIOArgsInvokeDir (inputFile ^. pathPath)),
2022-09-14 17:16:15 +03:00
_entryPointGenericOptions = project opts,
_entryPointStdin = estdin
}
2022-12-20 15:05:40 +03:00
someBaseToAbs' :: Members '[App] r => SomeBase a -> Sem r (Path Abs a)
someBaseToAbs' f = do
r <- askInvokeDir
return (someBaseToAbs r f)
2022-09-14 17:16:15 +03:00
askGenericOptions :: Members '[App] r => Sem r GenericOptions
askGenericOptions = project <$> askGlobalOptions
2022-12-20 15:05:40 +03:00
getEntryPoint :: Members '[Embed IO, App] r => AppPath File -> Sem r EntryPoint
2022-09-14 17:16:15 +03:00
getEntryPoint inputFile = do
_runAppIOArgsGlobalOptions <- askGlobalOptions
_runAppIOArgsPkgDir <- askPkgDir
_runAppIOArgsPkg <- askPackage
_runAppIOArgsBuildDir <- askBuildDir
_runAppIOArgsInvokeDir <- askInvokeDir
embed (getEntryPoint' (RunAppIOArgs {..}) inputFile)
2022-09-14 17:16:15 +03:00
2022-12-20 15:05:40 +03:00
runPipeline :: Member App r => AppPath File -> Sem PipelineEff a -> Sem r a
2022-09-14 17:16:15 +03:00
runPipeline input p = do
r <- runPipelineEither input p
case r of
Left err -> exitJuvixError err
Right res -> return (snd res)
newline :: Member App r => Sem r ()
newline = say ""
printSuccessExit :: Member App r => Text -> Sem r a
printSuccessExit = exitMsg ExitSuccess
printFailureExit :: Member App r => Text -> Sem r a
printFailureExit = exitMsg (ExitFailure 1)
getRight :: (Members '[App] r, AppError e) => Either e a -> Sem r a
getRight = either appError return
instance AppError Text where
appError = printFailureExit
instance AppError JuvixError where
appError = exitJuvixError
class AppError e where
appError :: Members '[App] r => e -> Sem r a