From 454c1cd507f2cf8a5712f8b4451e4abd85f2492a Mon Sep 17 00:00:00 2001 From: Paul Cadman Date: Tue, 19 Nov 2024 17:29:13 +0000 Subject: [PATCH] Separate nockma run commands into subcommands ``` Usage: juvix dev nockma run COMMAND Subcommands used to run an Anoma program. Use with artefacts obtained from compilation with the anoma target Available options: -h,--help Show this help text Available commands: builtin-evaluator Run with the builtin Nockma evaluator ephemeral-client Run with an ephemeral Anoma client with-client Run with a running Anoma client ``` --- app/Commands/Dev/Nockma/Options.hs | 6 +- app/Commands/Dev/Nockma/Run.hs | 56 +++----------- app/Commands/Dev/Nockma/Run/Anoma.hs | 38 ++++++++++ app/Commands/Dev/Nockma/Run/BuiltinClient.hs | 29 ++++++++ .../Dev/Nockma/Run/BuiltinClient/Options.hs | 25 +++++++ .../Dev/Nockma/Run/EphemeralClient.hs | 19 +++++ .../Dev/Nockma/Run/EphemeralClient/Options.hs | 19 +++++ app/Commands/Dev/Nockma/Run/Options.hs | 73 ++++++++++++------- app/Commands/Dev/Nockma/Run/WithClient.hs | 23 ++++++ .../Dev/Nockma/Run/WithClient/Options.hs | 35 +++++++++ app/CommonOptions.hs | 12 +++ 11 files changed, 257 insertions(+), 78 deletions(-) create mode 100644 app/Commands/Dev/Nockma/Run/Anoma.hs create mode 100644 app/Commands/Dev/Nockma/Run/BuiltinClient.hs create mode 100644 app/Commands/Dev/Nockma/Run/BuiltinClient/Options.hs create mode 100644 app/Commands/Dev/Nockma/Run/EphemeralClient.hs create mode 100644 app/Commands/Dev/Nockma/Run/EphemeralClient/Options.hs create mode 100644 app/Commands/Dev/Nockma/Run/WithClient.hs create mode 100644 app/Commands/Dev/Nockma/Run/WithClient/Options.hs diff --git a/app/Commands/Dev/Nockma/Options.hs b/app/Commands/Dev/Nockma/Options.hs index def0d10493..ad17c2637f 100644 --- a/app/Commands/Dev/Nockma/Options.hs +++ b/app/Commands/Dev/Nockma/Options.hs @@ -12,7 +12,7 @@ data NockmaCommand = NockmaRepl NockmaReplOptions | NockmaEval NockmaEvalOptions | NockmaFormat NockmaFormatOptions - | NockmaRun NockmaRunOptions + | NockmaRun NockmaRunCommand | NockmaEncode NockmaEncodeOptions | NockmaIde NockmaIdeCommand deriving stock (Data) @@ -53,8 +53,8 @@ parseNockmaCommand = runInfo :: ParserInfo NockmaCommand runInfo = info - (NockmaRun <$> parseNockmaRunOptions) - (progDesc ("Run an Anoma program. It should be used with artefacts obtained from compilation with the anoma target. If the --" <> anomaDirOptLongStr <> " is given, then it runs the code in an anoma node")) + (NockmaRun <$> parseNockmaRunCommand) + (progDesc "Subcommands used to run an Anoma program. Use with artefacts obtained from compilation with the anoma target") commandFromAsm :: Mod CommandFields NockmaCommand commandFromAsm = command "eval" fromAsmInfo diff --git a/app/Commands/Dev/Nockma/Run.hs b/app/Commands/Dev/Nockma/Run.hs index 1fd1ba6f88..7f9b3138a9 100644 --- a/app/Commands/Dev/Nockma/Run.hs +++ b/app/Commands/Dev/Nockma/Run.hs @@ -1,51 +1,13 @@ module Commands.Dev.Nockma.Run where -import Anoma.Effect -import Commands.Base hiding (Atom) +import Commands.Base +import Commands.Dev.Nockma.Run.BuiltinClient as BuiltinClient +import Commands.Dev.Nockma.Run.EphemeralClient as EphemeralClient import Commands.Dev.Nockma.Run.Options -import Juvix.Compiler.Nockma.Anoma -import Juvix.Compiler.Nockma.EvalCompiled -import Juvix.Compiler.Nockma.Evaluator -import Juvix.Compiler.Nockma.Pretty -import Juvix.Compiler.Nockma.Translation.FromSource qualified as Nockma +import Commands.Dev.Nockma.Run.WithClient as WithClient -runCommand :: forall r. (Members AppEffects r) => NockmaRunOptions -> Sem r () -runCommand opts = do - afile <- fromAppPathFile inputFile - argsFile <- mapM fromAppPathFile (opts ^. nockmaRunArgs) - parsedArgs <- runAppError @JuvixError (mapM Nockma.cueJammedFileOrPretty argsFile) - parsedTerm <- runAppError @JuvixError (Nockma.cueJammedFileOrPretty afile) - case parsedTerm of - TermAtom {} -> exitFailMsg "Expected nockma input to be a cell" - t@(TermCell {}) -> case opts ^. nockmaRunAnomaDir of - Just path -> do - anomaDir <- AnomaPath <$> fromAppPathDir path - runInAnoma anomaDir t (maybe [] unfoldList parsedArgs) - Nothing -> do - let formula = anomaCallTuple parsedArgs - (counts, res) <- - runOpCounts - . runReader defaultEvalOptions - . runOutputSem @(Term Natural) (logInfo . mkAnsiText . ppTrace) - $ evalCompiledNock' t formula - putStrLn (ppPrint res) - let statsFile = replaceExtension' ".profile" afile - writeFileEnsureLn statsFile (prettyText counts) - where - inputFile :: AppPath File - inputFile = opts ^. nockmaRunFile - -runInAnoma :: (Members AppEffects r) => AnomaPath -> Term Natural -> [Term Natural] -> Sem r () -runInAnoma anoma t args = runAppError @SimpleError . runAnomaEphemeral anoma $ do - res <- - runNockma - RunNockmaInput - { _runNockmaProgram = t, - _runNockmaArgs = args - } - let traces = res ^. runNockmaTraces - renderStdOutLn (annotate AnnImportant $ "Traces (" <> show (length traces) <> "):") - forM_ traces $ \tr -> - renderStdOutLn (ppPrint tr) - renderStdOutLn (annotate AnnImportant "Result:") - renderStdOutLn (ppPrint (res ^. runNockmaResult)) +runCommand :: forall r. (Members AppEffects r) => NockmaRunCommand -> Sem r () +runCommand = \case + NockmaRunBuiltinClient opts -> BuiltinClient.runCommand opts + NockmaRunEphemeralClient opts -> EphemeralClient.runCommand opts + NockmaRunWithClient opts -> WithClient.runCommand opts diff --git a/app/Commands/Dev/Nockma/Run/Anoma.hs b/app/Commands/Dev/Nockma/Run/Anoma.hs new file mode 100644 index 0000000000..748037321d --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/Anoma.hs @@ -0,0 +1,38 @@ +module Commands.Dev.Nockma.Run.Anoma where + +import Anoma.Effect +import Commands.Base hiding (Atom) +import Juvix.Compiler.Nockma.Pretty +import Juvix.Compiler.Nockma.Translation.FromSource qualified as Nockma + +data RunCommandArgs = RunCommandArgs + { _runCommandArgsFile :: Maybe (AppPath File), + _runCommandProgramFile :: AppPath File + } + +makeLenses ''RunCommandArgs + +runInAnoma :: forall r. (Members '[Error SimpleError, Anoma] r, Members AppEffects r) => RunCommandArgs -> Sem r () +runInAnoma runArgs = do + afile <- fromAppPathFile (runArgs ^. runCommandProgramFile) + argsFile <- mapM fromAppPathFile (runArgs ^. runCommandArgsFile) + parsedArgs <- runAppError @JuvixError (mapM Nockma.cueJammedFileOrPretty argsFile) + parsedTerm <- runAppError @JuvixError (Nockma.cueJammedFileOrPretty afile) + case parsedTerm of + TermAtom {} -> exitFailMsg "Expected nockma input to be a cell" + t@(TermCell {}) -> go t (maybe [] unfoldList parsedArgs) + where + go :: Term Natural -> [Term Natural] -> Sem r () + go t args = do + res <- + runNockma + RunNockmaInput + { _runNockmaProgram = t, + _runNockmaArgs = args + } + let traces = res ^. runNockmaTraces + renderStdOutLn (annotate AnnImportant $ "Traces (" <> show (length traces) <> "):") + forM_ traces $ \tr -> + renderStdOutLn (ppPrint tr) + renderStdOutLn (annotate AnnImportant "Result:") + renderStdOutLn (ppPrint (res ^. runNockmaResult)) diff --git a/app/Commands/Dev/Nockma/Run/BuiltinClient.hs b/app/Commands/Dev/Nockma/Run/BuiltinClient.hs new file mode 100644 index 0000000000..b819ca7e4d --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/BuiltinClient.hs @@ -0,0 +1,29 @@ +module Commands.Dev.Nockma.Run.BuiltinClient where + +import Commands.Base hiding (Atom) +import Commands.Dev.Nockma.Run.BuiltinClient.Options +import Juvix.Compiler.Nockma.Anoma +import Juvix.Compiler.Nockma.EvalCompiled +import Juvix.Compiler.Nockma.Evaluator +import Juvix.Compiler.Nockma.Pretty +import Juvix.Compiler.Nockma.Translation.FromSource qualified as Nockma + +runCommand :: forall r. (Members AppEffects r) => NockmaRunBuiltinClientOptions -> Sem r () +runCommand opts = do + afile <- fromAppPathFile (opts ^. nockmaRunBuiltinFile) + argsFile <- mapM fromAppPathFile (opts ^. nockmaRunBuiltinArgs) + parsedArgs <- runAppError @JuvixError (mapM Nockma.cueJammedFileOrPretty argsFile) + parsedTerm <- runAppError @JuvixError (Nockma.cueJammedFileOrPretty afile) + case parsedTerm of + TermAtom {} -> exitFailMsg "Expected nockma input to be a cell" + t@(TermCell {}) -> do + let formula = anomaCallTuple parsedArgs + (counts, res) <- + runOpCounts + . runReader defaultEvalOptions + . runOutputSem @(Term Natural) (logInfo . mkAnsiText . ppTrace) + $ evalCompiledNock' t formula + putStrLn (ppPrint res) + when (opts ^. nockmaRunBuiltinProfile) $ do + let statsFile = replaceExtension' ".profile" afile + writeFileEnsureLn statsFile (prettyText counts) diff --git a/app/Commands/Dev/Nockma/Run/BuiltinClient/Options.hs b/app/Commands/Dev/Nockma/Run/BuiltinClient/Options.hs new file mode 100644 index 0000000000..01f98f9608 --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/BuiltinClient/Options.hs @@ -0,0 +1,25 @@ +module Commands.Dev.Nockma.Run.BuiltinClient.Options where + +import CommonOptions + +data NockmaRunBuiltinClientOptions = NockmaRunBuiltinClientOptions + { _nockmaRunBuiltinFile :: AppPath File, + _nockmaRunBuiltinAnomaDir :: Maybe (AppPath Dir), + _nockmaRunBuiltinProfile :: Bool, + _nockmaRunBuiltinArgs :: Maybe (AppPath File) + } + deriving stock (Data) + +makeLenses ''NockmaRunBuiltinClientOptions + +parseNockmaRunBuiltinClientOptions :: Parser NockmaRunBuiltinClientOptions +parseNockmaRunBuiltinClientOptions = do + _nockmaRunBuiltinFile <- parseInputFile FileExtNockma + _nockmaRunBuiltinArgs <- optional anomaArgsOpt + _nockmaRunBuiltinAnomaDir <- optional anomaDirOpt + _nockmaRunBuiltinProfile <- + switch + ( long "profile" + <> help "Report evaluator profiling statistics" + ) + pure NockmaRunBuiltinClientOptions {..} diff --git a/app/Commands/Dev/Nockma/Run/EphemeralClient.hs b/app/Commands/Dev/Nockma/Run/EphemeralClient.hs new file mode 100644 index 0000000000..92193d30f5 --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/EphemeralClient.hs @@ -0,0 +1,19 @@ +module Commands.Dev.Nockma.Run.EphemeralClient where + +import Anoma.Effect +import Commands.Base hiding (Atom) +import Commands.Dev.Nockma.Run.Anoma +import Commands.Dev.Nockma.Run.EphemeralClient.Options + +runCommand :: forall r. (Members AppEffects r) => NockmaRunEphemeralClientOptions -> Sem r () +runCommand opts = do + anomaDir <- AnomaPath <$> fromAppPathDir (opts ^. nockmaRunEphemeralAnomaDir) + runAppError @SimpleError + . runAnomaEphemeral anomaDir + $ runInAnoma runArgs + where + runArgs = + RunCommandArgs + { _runCommandProgramFile = opts ^. nockmaRunEphemeralFile, + _runCommandArgsFile = opts ^. nockmaRunEphemeralArgs + } diff --git a/app/Commands/Dev/Nockma/Run/EphemeralClient/Options.hs b/app/Commands/Dev/Nockma/Run/EphemeralClient/Options.hs new file mode 100644 index 0000000000..df255a1b00 --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/EphemeralClient/Options.hs @@ -0,0 +1,19 @@ +module Commands.Dev.Nockma.Run.EphemeralClient.Options where + +import CommonOptions + +data NockmaRunEphemeralClientOptions = NockmaRunEphemeralClientOptions + { _nockmaRunEphemeralFile :: AppPath File, + _nockmaRunEphemeralAnomaDir :: AppPath Dir, + _nockmaRunEphemeralArgs :: Maybe (AppPath File) + } + deriving stock (Data) + +makeLenses ''NockmaRunEphemeralClientOptions + +parseNockmaRunEphemeralClientOptions :: Parser NockmaRunEphemeralClientOptions +parseNockmaRunEphemeralClientOptions = do + _nockmaRunEphemeralFile <- parseInputFile FileExtNockma + _nockmaRunEphemeralArgs <- optional anomaArgsOpt + _nockmaRunEphemeralAnomaDir <- anomaDirOpt + pure NockmaRunEphemeralClientOptions {..} diff --git a/app/Commands/Dev/Nockma/Run/Options.hs b/app/Commands/Dev/Nockma/Run/Options.hs index 3ee5813608..ec68c771ce 100644 --- a/app/Commands/Dev/Nockma/Run/Options.hs +++ b/app/Commands/Dev/Nockma/Run/Options.hs @@ -1,34 +1,51 @@ -module Commands.Dev.Nockma.Run.Options where +module Commands.Dev.Nockma.Run.Options + ( module Commands.Dev.Nockma.Run.BuiltinClient.Options, + module Commands.Dev.Nockma.Run.EphemeralClient.Options, + module Commands.Dev.Nockma.Run.WithClient.Options, + module Commands.Dev.Nockma.Run.Options, + ) +where +import Commands.Dev.Nockma.Run.BuiltinClient.Options +import Commands.Dev.Nockma.Run.EphemeralClient.Options +import Commands.Dev.Nockma.Run.WithClient.Options import CommonOptions -data NockmaRunOptions = NockmaRunOptions - { _nockmaRunFile :: AppPath File, - _nockmaRunAnomaDir :: Maybe (AppPath Dir), - _nockmaRunProfile :: Bool, - _nockmaRunArgs :: Maybe (AppPath File) - } +data NockmaRunCommand + = NockmaRunBuiltinClient NockmaRunBuiltinClientOptions + | NockmaRunEphemeralClient NockmaRunEphemeralClientOptions + | NockmaRunWithClient NockmaRunWithClientOptions deriving stock (Data) -makeLenses ''NockmaRunOptions +makeLenses ''NockmaRunCommand -parseNockmaRunOptions :: Parser NockmaRunOptions -parseNockmaRunOptions = do - _nockmaRunFile <- parseInputFile FileExtNockma - _nockmaRunArgs <- optional $ do - _pathPath <- - option - somePreFileOpt - ( long "args" - <> metavar "ARGS_FILE" - <> help "Path to file containing args. When run on anoma, the args file should contain a list (i.e. to pass 2 and [1 4] as args, the contents should be [2 [1 4] 0])." - <> action "file" - ) - pure AppPath {_pathIsInput = True, ..} - _nockmaRunAnomaDir <- optional anomaDirOpt - _nockmaRunProfile <- - switch - ( long "profile" - <> help "Report evaluator profiling statistics" - ) - pure NockmaRunOptions {..} +parseNockmaRunCommand :: Parser NockmaRunCommand +parseNockmaRunCommand = + hsubparser + ( mconcat + [ commandRunBuiltinClient, + commandRunEphemeralClient, + commandRunWithClient + ] + ) + +commandRunBuiltinClient :: Mod CommandFields NockmaRunCommand +commandRunBuiltinClient = + command "builtin-evaluator" $ + info + (NockmaRunBuiltinClient <$> parseNockmaRunBuiltinClientOptions) + (progDesc "Run with the builtin Nockma evaluator") + +commandRunEphemeralClient :: Mod CommandFields NockmaRunCommand +commandRunEphemeralClient = + command "ephemeral-client" $ + info + (NockmaRunEphemeralClient <$> parseNockmaRunEphemeralClientOptions) + (progDesc "Run with an ephemeral Anoma client") + +commandRunWithClient :: Mod CommandFields NockmaRunCommand +commandRunWithClient = + command "with-client" $ + info + (NockmaRunWithClient <$> parseNockmaRunWithClientOptions) + (progDesc "Run with a running Anoma client") diff --git a/app/Commands/Dev/Nockma/Run/WithClient.hs b/app/Commands/Dev/Nockma/Run/WithClient.hs new file mode 100644 index 0000000000..58fcdd73e6 --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/WithClient.hs @@ -0,0 +1,23 @@ +module Commands.Dev.Nockma.Run.WithClient where + +import Anoma.Effect +import Commands.Base hiding (Atom) +import Commands.Dev.Nockma.Run.Anoma +import Commands.Dev.Nockma.Run.WithClient.Options + +runCommand :: forall r. (Members AppEffects r) => NockmaRunWithClientOptions -> Sem r () +runCommand opts = + runAppError @SimpleError + . runAnomaWithClient grpcInfo + $ runInAnoma runArgs + where + grpcInfo = + AnomaGrpcClientInfo + { _anomaGrpcClientInfoUrl = opts ^. nockmaRunWithClientUrl, + _anomaGrpcClientInfoPort = opts ^. nockmaRunWithClientGrpcPort + } + runArgs = + RunCommandArgs + { _runCommandProgramFile = opts ^. nockmaRunWithClientFile, + _runCommandArgsFile = opts ^. nockmaRunWithClientArgs + } diff --git a/app/Commands/Dev/Nockma/Run/WithClient/Options.hs b/app/Commands/Dev/Nockma/Run/WithClient/Options.hs new file mode 100644 index 0000000000..7527409a7f --- /dev/null +++ b/app/Commands/Dev/Nockma/Run/WithClient/Options.hs @@ -0,0 +1,35 @@ +module Commands.Dev.Nockma.Run.WithClient.Options where + +import CommonOptions + +data NockmaRunWithClientOptions = NockmaRunWithClientOptions + { _nockmaRunWithClientFile :: AppPath File, + _nockmaRunWithClientGrpcPort :: Int, + _nockmaRunWithClientUrl :: String, + _nockmaRunWithClientArgs :: Maybe (AppPath File) + } + deriving stock (Data) + +makeLenses ''NockmaRunWithClientOptions + +parseNockmaRunWithClientOptions :: Parser NockmaRunWithClientOptions +parseNockmaRunWithClientOptions = do + _nockmaRunWithClientFile <- parseInputFile FileExtNockma + _nockmaRunWithClientArgs <- optional anomaArgsOpt + _nockmaRunWithClientGrpcPort <- + option + (fromIntegral <$> naturalNumberOpt) + ( long "grpc-port" + <> short 'p' + <> help ("The GRPC port of a running Anoma client") + <> metavar "PORT" + ) + _nockmaRunWithClientUrl <- do + let defaultUrl :: String = "localhost" + strOption + ( long "url" + <> help ("The URL of a running Anoma client. default: " <> defaultUrl) + <> value defaultUrl + <> metavar "URL" + ) + pure NockmaRunWithClientOptions {..} diff --git a/app/CommonOptions.hs b/app/CommonOptions.hs index 7a5a225d2e..c256ef1286 100644 --- a/app/CommonOptions.hs +++ b/app/CommonOptions.hs @@ -95,6 +95,18 @@ anomaDirOpt = do _pathPath = path } +anomaArgsOpt :: Parser (AppPath File) +anomaArgsOpt = do + _pathPath <- + option + somePreFileOpt + ( long "args" + <> metavar "ARGS_FILE" + <> help "Path to file containing args. The args file should contain a list (i.e. to pass 2 and [1 4] as args, the contents should be [2 [1 4] 0])." + <> action "file" + ) + pure AppPath {_pathIsInput = True, ..} + parseNumThreads :: Parser NumThreads parseNumThreads = do option