Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add internal core read command #1517

Merged
merged 7 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions app/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Juvix.Prelude.Pretty hiding (Doc)
import System.Console.ANSI qualified as Ansi

data App m a where
ExitMsg :: ExitCode -> Text -> App m ()
ExitMsg :: ExitCode -> Text -> App m a
ExitJuvixError :: JuvixError -> App m a
PrintJuvixError :: JuvixError -> App m ()
ReadGlobalOptions :: App m GlobalOptions
Expand Down Expand Up @@ -53,8 +53,20 @@ runPipeline p = do
newline :: Member App r => Sem r ()
newline = say ""

printSuccessExit :: Member App r => Text -> Sem r ()
printSuccessExit :: Member App r => Text -> Sem r a
printSuccessExit = exitMsg ExitSuccess

printFailureExit :: Member App r => Text -> Sem r ()
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
70 changes: 54 additions & 16 deletions app/Commands/Dev/Core.hs
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
module Commands.Dev.Core where

import Juvix.Compiler.Core.Data.TransformationId.Parser
import Juvix.Prelude hiding (Doc)
import Options.Applicative

data CoreCommand
= Repl CoreReplOptions
| Eval CoreEvalOptions
| Read CoreReadOptions

newtype CoreReplOptions = CoreReplOptions
{ _coreReplShowDeBruijn :: Bool
}

data CoreEvalOptions = CoreEvalOptions
{ _coreEvalShowDeBruijn :: Bool,
_coreEvalNoIO :: Bool
newtype CoreEvalOptions = CoreEvalOptions
{ _coreEvalNoIO :: Bool
}

data CoreReadOptions = CoreReadOptions
{ _coreReadTransformations :: [TransformationId],
_coreReadShowDeBruijn :: Bool
}

makeLenses ''CoreReplOptions
makeLenses ''CoreEvalOptions
makeLenses ''CoreReadOptions

defaultCoreEvalOptions :: CoreEvalOptions
defaultCoreEvalOptions =
CoreEvalOptions
{ _coreEvalShowDeBruijn = False,
_coreEvalNoIO = False
{ _coreEvalNoIO = False
}

defaultCoreReadOptions :: CoreReadOptions
defaultCoreReadOptions =
CoreReadOptions
{ _coreReadTransformations = mempty,
_coreReadShowDeBruijn = False
}

parseCoreCommand :: Parser CoreCommand
parseCoreCommand =
hsubparser $
mconcat
[ commandRepl,
commandEval
commandEval,
commandRead
]
where
commandRepl :: Mod CommandFields CoreCommand
Expand All @@ -40,6 +54,9 @@ parseCoreCommand =
commandEval :: Mod CommandFields CoreCommand
commandEval = command "eval" evalInfo

commandRead :: Mod CommandFields CoreCommand
commandRead = command "read" readInfo

replInfo :: ParserInfo CoreCommand
replInfo =
info
Expand All @@ -52,25 +69,46 @@ parseCoreCommand =
(Eval <$> parseCoreEvalOptions)
(progDesc "Evaluate a JuvixCore file and pretty print the result")

readInfo :: ParserInfo CoreCommand
readInfo =
info
(Read <$> parseCoreReadOptions)
(progDesc "Read a JuvixCore file, transform it, and pretty print it")

parseCoreReadOptions :: Parser CoreReadOptions
parseCoreReadOptions = do
_coreReadShowDeBruijn <- deBruijnOpt
_coreReadTransformations <-
option
(eitherReader parseTransf)
( long "transforms"
<> short 't'
<> value mempty
<> metavar "[Transform]"
<> help "comma sep list of transformations. Available: lifting"
)
pure CoreReadOptions {..}
where
parseTransf :: String -> Either String [TransformationId]
parseTransf = mapLeft unpack . parseTransformations . pack

parseCoreEvalOptions :: Parser CoreEvalOptions
parseCoreEvalOptions = do
_coreEvalShowDeBruijn <-
switch
( long "show-de-bruijn"
<> help "Show variable de Bruijn indices"
)
_coreEvalNoIO <-
switch
( long "no-io"
<> help "Don't interpret the IO effects"
)
pure CoreEvalOptions {..}

deBruijnOpt :: Parser Bool
deBruijnOpt =
switch
( long "show-de-bruijn"
<> help "Show variable de Bruijn indices"
)

parseCoreReplOptions :: Parser CoreReplOptions
parseCoreReplOptions = do
_coreReplShowDeBruijn <-
switch
( long "show-de-bruijn"
<> help "Show variable de Bruijn indices"
)
_coreReplShowDeBruijn <- deBruijnOpt
pure CoreReplOptions {..}
67 changes: 35 additions & 32 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import CLI
import Commands.Dev.Termination as Termination
import Commands.Init qualified as Init
import Control.Exception qualified as IO
import Control.Monad.Extra
import Data.ByteString qualified as ByteString
import Data.HashMap.Strict qualified as HashMap
import Data.Yaml
Expand All @@ -29,6 +28,7 @@ import Juvix.Compiler.Core.Info qualified as Info
import Juvix.Compiler.Core.Info.NoDisplayInfo qualified as Info
import Juvix.Compiler.Core.Language qualified as Core
import Juvix.Compiler.Core.Pretty qualified as Core
import Juvix.Compiler.Core.Transformation qualified as Core
import Juvix.Compiler.Core.Translation.FromSource qualified as Core
import Juvix.Compiler.Internal.Pretty qualified as Internal
import Juvix.Compiler.Internal.Translation.FromAbstract qualified as Internal
Expand All @@ -39,7 +39,7 @@ import Juvix.Compiler.Pipeline
import Juvix.Extra.Paths qualified as Paths
import Juvix.Extra.Process
import Juvix.Extra.Version (runDisplayVersion)
import Juvix.Prelude hiding (Doc)
import Juvix.Prelude
import Juvix.Prelude.Pretty hiding (Doc)
import Options.Applicative
import System.Environment (getProgName)
Expand Down Expand Up @@ -252,28 +252,30 @@ runCommand cmdWithOpts = do
printSuccessExit (n <> " Terminates with order " <> show (toList k))
_ -> impossible

runCoreCommand :: Members '[Embed IO, App] r => GlobalOptions -> CoreCommand -> Sem r ()
runCoreCommand :: forall r. Members '[Embed IO, App] r => GlobalOptions -> CoreCommand -> Sem r ()
runCoreCommand globalOpts = \case
Repl opts -> do
embed showReplWelcome
runRepl opts Core.emptyInfoTable
Eval opts ->
case globalOpts ^. globalInputFiles of
[] -> printFailureExit "Provide a JuvixCore file to run this command\nUse --help to see all the options"
files -> mapM_ (evalFile opts) files
Eval opts -> getFile >>= evalFile opts
Read opts -> getFile >>= runRead opts
where
genericOpts :: GenericOptions
genericOpts = genericFromGlobalOptions globalOpts
getFile :: Sem r FilePath
getFile = case globalOpts ^? globalInputFiles . _head of
Nothing -> printFailureExit "Provide a JuvixCore file to run this command\nUse --help to see all the options"
Just f -> return f

docOpts :: Bool -> Core.Options
docOpts showDeBruijn = set Core.optShowNameIds (genericOpts ^. showNameIds) (set Core.optShowDeBruijnIndices showDeBruijn Core.defaultOptions)
runRead :: CoreReadOptions -> FilePath -> Sem r ()
runRead opts f = do
s' <- embed (readFile f)
tab <- getRight (fst <$> mapLeft JuvixError (Core.runParser "" f Core.emptyInfoTable s'))
let tab' = Core.applyTransformations (opts ^. coreReadTransformations) tab
renderStdOut (Core.ppOut docOpts tab')
where
docOpts :: Core.Options
docOpts = set Core.optShowDeBruijnIndices (opts ^. coreReadShowDeBruijn) Core.defaultOptions

runRepl ::
forall r.
Members '[Embed IO, App] r =>
CoreReplOptions ->
Core.InfoTable ->
Sem r ()
runRepl :: CoreReplOptions -> Core.InfoTable -> Sem r ()
runRepl opts tab = do
embed (putStr "> ")
embed (hFlush stdout)
Expand All @@ -291,7 +293,7 @@ runCoreCommand globalOpts = \case
printJuvixError (JuvixError err)
runRepl opts tab
Right (tab', Just node) -> do
renderStdOut (Core.ppOut (docOpts (opts ^. coreReplShowDeBruijn)) node)
renderStdOut (Core.ppOut docOpts node)
embed (putStrLn "")
runRepl opts tab'
Right (tab', Nothing) ->
Expand All @@ -311,10 +313,9 @@ runCoreCommand globalOpts = \case
Left err -> do
printJuvixError (JuvixError err)
runRepl opts tab
Right (tab', Just node) ->
replEval False tab' node
Right (tab', Nothing) ->
runRepl opts tab'
Right (tab', mnode) -> case mnode of
Nothing -> runRepl opts tab'
Just node -> replEval False tab' node
":r" ->
runRepl opts Core.emptyInfoTable
_ ->
Expand All @@ -327,8 +328,8 @@ runCoreCommand globalOpts = \case
Right (tab', Nothing) ->
runRepl opts tab'
where
defaultLoc = singletonInterval (mkLoc "stdin" 0 (M.initialPos "stdin"))

docOpts :: Core.Options
docOpts = set Core.optShowDeBruijnIndices (opts ^. coreReplShowDeBruijn) Core.defaultOptions
replEval :: Bool -> Core.InfoTable -> Core.Node -> Sem r ()
replEval noIO tab' node = do
r <- doEval noIO defaultLoc tab' node
Expand All @@ -337,12 +338,13 @@ runCoreCommand globalOpts = \case
printJuvixError (JuvixError err)
runRepl opts tab'
Right node'
| Info.member Info.kNoDisplayInfo (Core.getInfo node') ->
| Info.member Info.kNoDisplayInfo (Core.getInfo node') -> runRepl opts tab'
| otherwise -> do
renderStdOut (Core.ppOut docOpts node')
embed (putStrLn "")
runRepl opts tab'
Right node' -> do
renderStdOut (Core.ppOut (docOpts (opts ^. coreReplShowDeBruijn)) node')
embed (putStrLn "")
runRepl opts tab'
where
defaultLoc = singletonInterval (mkLoc "stdin" 0 (M.initialPos "stdin"))

showReplWelcome :: IO ()
showReplWelcome = do
Expand All @@ -367,7 +369,7 @@ runCoreCommand globalOpts = \case
putStrLn ":h Display this help message."
putStrLn ""

evalFile :: Members '[Embed IO, App] r => CoreEvalOptions -> FilePath -> Sem r ()
evalFile :: CoreEvalOptions -> FilePath -> Sem r ()
evalFile opts f = do
s <- embed (readFile f)
case Core.runParser "" f Core.emptyInfoTable s of
Expand All @@ -380,14 +382,15 @@ runCoreCommand globalOpts = \case
| Info.member Info.kNoDisplayInfo (Core.getInfo node') ->
return ()
Right node' -> do
renderStdOut (Core.ppOut (docOpts (opts ^. coreEvalShowDeBruijn)) node')
renderStdOut (Core.ppOut docOpts node')
embed (putStrLn "")
Right (_, Nothing) -> return ()
where
docOpts :: Core.Options
docOpts = Core.defaultOptions
defaultLoc = singletonInterval (mkLoc f 0 (M.initialPos f))

doEval ::
Members '[Embed IO, App] r =>
Bool ->
Interval ->
Core.InfoTable ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ data ScoperResult = ScoperResult
makeLenses ''ScoperResult

mainModule :: Lens' ScoperResult (Module 'Scoped 'ModuleTop)
mainModule = resultModules . _head
mainModule = resultModules . _head1
4 changes: 4 additions & 0 deletions src/Juvix/Compiler/Core/Data/TransformationId.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Juvix.Compiler.Core.Data.TransformationId where

data TransformationId
= LambdaLifting
31 changes: 31 additions & 0 deletions src/Juvix/Compiler/Core/Data/TransformationId/Parser.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Juvix.Compiler.Core.Data.TransformationId.Parser (parseTransformations, TransformationId (..)) where

import Juvix.Compiler.Core.Data.TransformationId
import Juvix.Prelude
import Juvix.Prelude.Pretty hiding (comma)
import Text.Megaparsec
import Text.Megaparsec.Char qualified as L
import Text.Megaparsec.Char.Lexer qualified as L

parseTransformations :: Text -> Either Text [TransformationId]
parseTransformations t = case runParser transformations "<input>" t of
Left (err :: ParseErrorBundle Text Void) -> Left (prettyText (errorBundlePretty err))
Right r -> return r

transformations :: MonadParsec e Text m => m [TransformationId]
transformations = do
L.hspace
sepEndBy transformation comma <* eof

lexeme :: MonadParsec e Text m => m a -> m a
lexeme = L.lexeme L.hspace

comma :: MonadParsec e Text m => m ()
comma = symbol ","

symbol :: MonadParsec e Text m => Text -> m ()
symbol = void . lexeme . chunk

transformation :: MonadParsec e Text m => m TransformationId
transformation =
symbol "lifting" $> LambdaLifting
Loading