2022-05-18 18:10:10 +03:00
|
|
|
module App where
|
|
|
|
|
2022-09-14 17:16:15 +03:00
|
|
|
import CommonOptions
|
2022-08-12 10:48:06 +03:00
|
|
|
import Data.ByteString qualified as ByteString
|
2022-05-18 18:10:10 +03:00
|
|
|
import GlobalOptions
|
2022-11-07 16:47:56 +03:00
|
|
|
import Juvix.Compiler.Builtins.Effect
|
2022-08-03 14:20:40 +03:00
|
|
|
import Juvix.Compiler.Pipeline
|
|
|
|
import Juvix.Data.Error qualified as Error
|
2022-07-08 14:59:45 +03:00
|
|
|
import Juvix.Prelude.Pretty hiding (Doc)
|
2022-05-18 18:10:10 +03:00
|
|
|
import System.Console.ANSI qualified as Ansi
|
|
|
|
|
|
|
|
data App m a where
|
2022-09-06 16:26:48 +03:00
|
|
|
ExitMsg :: ExitCode -> Text -> App m a
|
2022-07-08 14:59:45 +03:00
|
|
|
ExitJuvixError :: JuvixError -> App m a
|
2022-08-30 12:24:15 +03:00
|
|
|
PrintJuvixError :: JuvixError -> App m ()
|
2022-12-20 15:05:40 +03:00
|
|
|
AskInvokeDir :: App m (Path Abs Dir)
|
|
|
|
AskPkgDir :: App m (Path Abs Dir)
|
2023-01-06 19:54:13 +03:00
|
|
|
AskBuildDir :: App m (Path Abs Dir)
|
2022-09-14 17:16:15 +03:00
|
|
|
AskPackage :: App m Package
|
|
|
|
AskGlobalOptions :: App m GlobalOptions
|
2022-05-18 18:10:10 +03:00
|
|
|
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))
|
2022-06-09 17:36:07 +03:00
|
|
|
Say :: Text -> App m ()
|
2022-12-20 15:05:40 +03:00
|
|
|
SayRaw :: ByteString -> App m ()
|
2022-05-18 18:10:10 +03:00
|
|
|
|
|
|
|
makeSem ''App
|
|
|
|
|
2023-01-06 19:54:13 +03:00
|
|
|
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)
|
2022-08-30 12:24:15 +03:00
|
|
|
where
|
2023-01-06 19:54:13 +03:00
|
|
|
g :: GlobalOptions
|
|
|
|
g = _runAppIOArgsGlobalOptions
|
2022-08-30 12:24:15 +03:00
|
|
|
printErr e =
|
2023-01-06 19:54:13 +03:00
|
|
|
embed $ hPutStrLn stderr $ run $ runReader (project' @GenericOptions g) $ Error.render (not (_runAppIOArgsGlobalOptions ^. globalNoColors)) (g ^. globalOnlyErrors) e
|
2022-05-18 18:10:10 +03:00
|
|
|
|
2023-01-06 19:54:13 +03:00
|
|
|
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,
|
2023-01-06 19:54:13 +03:00
|
|
|
_entryPointBuildDir = _runAppIOArgsBuildDir,
|
2022-09-14 17:16:15 +03:00
|
|
|
_entryPointNoTermination = opts ^. globalNoTermination,
|
|
|
|
_entryPointNoPositivity = opts ^. globalNoPositivity,
|
|
|
|
_entryPointNoStdlib = opts ^. globalNoStdlib,
|
2023-01-06 19:54:13 +03:00
|
|
|
_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
|
2023-01-06 19:54:13 +03:00
|
|
|
_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
|
2022-05-18 18:10:10 +03:00
|
|
|
case r of
|
2022-07-08 14:59:45 +03:00
|
|
|
Left err -> exitJuvixError err
|
2022-11-07 16:47:56 +03:00
|
|
|
Right res -> return (snd res)
|
2022-05-18 18:10:10 +03:00
|
|
|
|
|
|
|
newline :: Member App r => Sem r ()
|
|
|
|
newline = say ""
|
2022-06-09 17:36:07 +03:00
|
|
|
|
2022-09-06 16:26:48 +03:00
|
|
|
printSuccessExit :: Member App r => Text -> Sem r a
|
2022-06-09 17:36:07 +03:00
|
|
|
printSuccessExit = exitMsg ExitSuccess
|
|
|
|
|
2022-09-06 16:26:48 +03:00
|
|
|
printFailureExit :: Member App r => Text -> Sem r a
|
2022-06-09 17:36:07 +03:00
|
|
|
printFailureExit = exitMsg (ExitFailure 1)
|
2022-09-06 16:26:48 +03:00
|
|
|
|
|
|
|
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
|