The basic REPL now works; doesn't allow establishing definitions yet
This commit is contained in:
parent
e6abbdc91e
commit
99189e9536
|
@ -6,3 +6,4 @@ result
|
|||
TAGS
|
||||
ctags
|
||||
dist-newstyle
|
||||
/.history
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
--
|
||||
-- hash: d8e569439f4d52d30cbcfda7126f2175566ff4b9550032b2b7f91eabacf8c04a
|
||||
-- hash: aadafd05c71b074e10eb082201d88f7358d995ee842fc8308b3222482f43971c
|
||||
|
||||
name: hnix
|
||||
version: 0.5.0
|
||||
|
@ -121,6 +121,7 @@ executable hnix
|
|||
, exceptions
|
||||
, filepath
|
||||
, hnix
|
||||
, megaparsec
|
||||
, mtl
|
||||
, optparse-applicative
|
||||
, repline
|
||||
|
|
11
main/Main.hs
11
main/Main.hs
|
@ -27,6 +27,7 @@ import Nix.Parser
|
|||
import Nix.Pretty
|
||||
import Nix.Stack (NixException(..))
|
||||
import qualified Nix.Value as V
|
||||
import qualified Repl
|
||||
-- import Nix.TH
|
||||
import Options.Applicative hiding (ParserResult(..))
|
||||
import System.IO
|
||||
|
@ -48,9 +49,7 @@ main = do
|
|||
Just path ->
|
||||
mapM_ (processFile opts) =<< (lines <$> readFile path)
|
||||
Nothing -> case filePaths opts of
|
||||
[] ->
|
||||
handleResult opts Nothing . parseNixTextLoc
|
||||
=<< Text.getContents
|
||||
[] -> Repl.shell (pure ())
|
||||
["-"] ->
|
||||
handleResult opts Nothing . parseNixTextLoc
|
||||
=<< Text.getContents
|
||||
|
@ -74,8 +73,7 @@ main = do
|
|||
|
||||
process opts mpath expr = do
|
||||
when (check opts) $
|
||||
putStrLn $ runST $ Nix.runLintM . renderSymbolic
|
||||
=<< Nix.lint expr
|
||||
putStrLn $ runST $ runLintM . renderSymbolic =<< lint expr
|
||||
|
||||
let parseArg s = case parseNixText s of
|
||||
Success x -> x
|
||||
|
@ -144,3 +142,6 @@ main = do
|
|||
. renderPretty 0.4 80
|
||||
. prettyNix
|
||||
. stripAnnotation $ expr
|
||||
|
||||
when (repl opts) $
|
||||
Repl.shell (pure ())
|
||||
|
|
115
main/Repl.hs
115
main/Repl.hs
|
@ -10,6 +10,7 @@
|
|||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE TypeSynonymInstances #-}
|
||||
|
||||
{-# OPTIONS_GHC -Wno-unused-matches #-}
|
||||
|
@ -17,13 +18,23 @@
|
|||
|
||||
module Repl where
|
||||
|
||||
import Nix.Type.Infer
|
||||
import qualified Nix
|
||||
import qualified Nix.Eval as Eval
|
||||
import Nix.Exec (Lazy)
|
||||
import qualified Nix.Exec as Exec
|
||||
import Nix.Normal
|
||||
import Nix.Parser
|
||||
import Nix.Pretty
|
||||
import Nix.Scope
|
||||
import qualified Nix.Type.Env as Env
|
||||
import Nix.Type.Infer
|
||||
import Nix.Value
|
||||
|
||||
import qualified Data.HashMap.Lazy as M
|
||||
import qualified Data.Map as Map
|
||||
import Data.Monoid
|
||||
import qualified Data.Text.Lazy as L
|
||||
import qualified Data.Text.Lazy.IO as L
|
||||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.IO as Text
|
||||
|
||||
import Control.Monad.Identity
|
||||
import Control.Monad.State.Strict
|
||||
|
@ -43,17 +54,18 @@ import System.Console.Repline
|
|||
data TermEnv
|
||||
|
||||
data IState = IState
|
||||
{ tyctx :: Env.Env -- Type environment
|
||||
, tmctx :: TermEnv -- Value environment
|
||||
{ -- tyctx :: Env.Env -- Type environment
|
||||
-- ,
|
||||
tmctx :: TermEnv -- Value environment
|
||||
}
|
||||
|
||||
initState :: IState
|
||||
initState = IState Env.empty undefined
|
||||
initState = IState {-Env.empty-} undefined
|
||||
|
||||
type Repl a = HaskelineT (StateT IState IO) a
|
||||
hoistErr :: Show e => Either e a -> Repl a
|
||||
hoistErr (Right val) = return val
|
||||
hoistErr (Left err) = do
|
||||
hoistErr :: Result a -> Repl a
|
||||
hoistErr (Success val) = return val
|
||||
hoistErr (Failure err) = do
|
||||
liftIO $ print err
|
||||
abort
|
||||
|
||||
|
@ -61,42 +73,39 @@ hoistErr (Left err) = do
|
|||
-- Execution
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
exec :: Bool -> L.Text -> Repl ()
|
||||
exec :: Bool -> Text.Text -> Repl ()
|
||||
exec update source = do
|
||||
-- Get the current interpreter state
|
||||
st <- get
|
||||
|
||||
-- Parser ( returns AST )
|
||||
-- mod <- hoistErr $ parseModule "<stdin>" source
|
||||
expr <- hoistErr $ parseNixTextLoc source
|
||||
|
||||
-- Type Inference ( returns Typing Environment )
|
||||
-- tyctx' <- hoistErr $ inferTop (tyctx st) mod
|
||||
-- tyctx' <- hoistErr $ inferTop (tyctx st) expr
|
||||
|
||||
-- Create the new environment
|
||||
-- let st' = st { tmctx = foldl' evalDef (tmctx st) mod
|
||||
-- , tyctx = tyctx' <> tyctx st
|
||||
-- }
|
||||
let st' = st { tmctx = tmctx st -- foldl' evalDef (tmctx st) expr
|
||||
-- , tyctx = tyctx' <> tyctx st
|
||||
}
|
||||
|
||||
-- Update the interpreter state
|
||||
-- when update (put st')
|
||||
when update (put st')
|
||||
|
||||
-- If a value is entered, print it.
|
||||
-- case lookup "it" mod of
|
||||
-- Nothing -> return ()
|
||||
-- Just ex -> do
|
||||
-- let (val, _) = runEval (tmctx st') "it" ex
|
||||
-- showOutput (show val) st'
|
||||
|
||||
undefined
|
||||
|
||||
showOutput :: String -> IState -> Repl ()
|
||||
showOutput arg st =
|
||||
case Env.lookup "it" (tyctx st) of
|
||||
Just val -> liftIO $ putStrLn $ undefined -- ppsignature (arg, val)
|
||||
Nothing -> return ()
|
||||
val <- liftIO $ Exec.runLazyM $
|
||||
Nix.evalTopLevelExprGen
|
||||
-- jww (2018-04-12): Once the user is able to establish definitions
|
||||
-- in the repl, they should be passed here.
|
||||
(pushScope @(NThunk (Lazy IO)) M.empty
|
||||
. Eval.framedEvalExpr
|
||||
(Eval.eval @_ @(NValue (Lazy IO))
|
||||
@(NThunk (Lazy IO)) @(Lazy IO)))
|
||||
Nothing [] expr
|
||||
liftIO $ putStrLn $ printNix val
|
||||
|
||||
cmd :: String -> Repl ()
|
||||
cmd source = exec True (L.pack source)
|
||||
cmd source = exec True (Text.pack source)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Commands
|
||||
|
@ -112,21 +121,21 @@ browse _ = do
|
|||
-- :load command
|
||||
load :: [String] -> Repl ()
|
||||
load args = do
|
||||
contents <- liftIO $ L.readFile (unwords args)
|
||||
contents <- liftIO $ Text.readFile (unwords args)
|
||||
exec True contents
|
||||
|
||||
-- :type command
|
||||
typeof :: [String] -> Repl ()
|
||||
typeof args = do
|
||||
st <- get
|
||||
let arg = unwords args
|
||||
case Env.lookup (pack arg) (tyctx st) of
|
||||
Just val -> liftIO $ putStrLn $ undefined -- ppsignature (arg, val)
|
||||
Nothing -> exec False (L.pack arg)
|
||||
-- typeof :: [String] -> Repl ()
|
||||
-- typeof args = do
|
||||
-- st <- get
|
||||
-- let arg = unwords args
|
||||
-- case Env.lookup (pack arg) (tyctx st) of
|
||||
-- Just val -> liftIO $ putStrLn $ undefined -- ppsignature (arg, val)
|
||||
-- Nothing -> exec False (Text.pack arg)
|
||||
|
||||
-- :quit command
|
||||
quit :: a -> Repl ()
|
||||
quit _ = liftIO $ exitSuccess
|
||||
quit _ = liftIO exitSuccess
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Interactive Shell
|
||||
|
@ -143,16 +152,16 @@ defaultMatcher = [
|
|||
comp :: (Monad m, MonadState IState m) => WordCompleter m
|
||||
comp n = do
|
||||
let cmds = [":load", ":type", ":browse", ":quit"]
|
||||
Env.TypeEnv ctx <- gets tyctx
|
||||
let defs = map unpack $ Map.keys ctx
|
||||
return $ filter (isPrefixOf n) (cmds ++ defs)
|
||||
-- Env.TypeEnv ctx <- gets tyctx
|
||||
-- let defs = map unpack $ Map.keys ctx
|
||||
return $ filter (isPrefixOf n) (cmds {-++ defs-})
|
||||
|
||||
options :: [(String, [String] -> Repl ())]
|
||||
options = [
|
||||
("load" , load)
|
||||
, ("browse" , browse)
|
||||
, ("quit" , quit)
|
||||
, ("type" , Repl.typeof)
|
||||
-- , ("type" , Repl.typeof)
|
||||
]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -163,18 +172,18 @@ completer :: CompleterStyle (StateT IState IO)
|
|||
completer = Prefix (wordCompleter comp) defaultMatcher
|
||||
|
||||
shell :: Repl a -> IO ()
|
||||
shell pre = flip evalStateT initState
|
||||
$ evalRepl "Poly> " cmd options completer pre
|
||||
shell pre = flip evalStateT initState $
|
||||
evalRepl "hnix> " cmd options completer pre
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Toplevel
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
case args of
|
||||
[] -> shell (return ())
|
||||
[fname] -> shell (load [fname])
|
||||
["test", fname] -> shell (load [fname] >> browse [] >> quit ())
|
||||
_ -> putStrLn "invalid arguments"
|
||||
-- main :: IO ()
|
||||
-- main = do
|
||||
-- args <- getArgs
|
||||
-- case args of
|
||||
-- [] -> shell (return ())
|
||||
-- [fname] -> shell (load [fname])
|
||||
-- ["test", fname] -> shell (load [fname] >> browse [] >> quit ())
|
||||
-- _ -> putStrLn "invalid arguments"
|
||||
|
|
|
@ -68,6 +68,7 @@ executables:
|
|||
dependencies:
|
||||
- hnix
|
||||
- repline
|
||||
- megaparsec
|
||||
|
||||
tests:
|
||||
hnix-tests:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
|
||||
module Nix (eval, evalLoc, tracingEvalLoc, lint, runLintM) where
|
||||
module Nix where
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Monad.Catch
|
||||
|
@ -15,11 +15,9 @@ import qualified Data.HashMap.Lazy as M
|
|||
import qualified Data.Text as Text
|
||||
import Nix.Builtins
|
||||
import qualified Nix.Eval as Eval
|
||||
import Nix.Eval hiding (eval)
|
||||
import Nix.Exec
|
||||
import Nix.Expr.Types (NExpr)
|
||||
import Nix.Expr.Types.Annotated (NExprLoc)
|
||||
import Nix.Lint (lint, runLintM)
|
||||
import Nix.Normal
|
||||
import Nix.Scope
|
||||
import Nix.Thunk
|
||||
|
@ -58,7 +56,7 @@ eval mpath incls = runLazyM . evalTopLevelExpr mpath incls
|
|||
evalTopLevelExprLoc :: forall e m. MonadBuiltins e m
|
||||
=> Maybe FilePath -> [String] -> NExprLoc -> m (NValueNF m)
|
||||
evalTopLevelExprLoc = evalTopLevelExprGen $
|
||||
framedEvalExpr (Eval.eval @_ @(NValue m) @(NThunk m) @m)
|
||||
Eval.framedEvalExpr (Eval.eval @_ @(NValue m) @(NThunk m) @m)
|
||||
|
||||
evalLoc :: (MonadFix m, MonadThrow m, MonadCatch m, MonadIO m)
|
||||
=> Maybe FilePath -> [String] -> NExprLoc -> m (NValueNF (Lazy m))
|
||||
|
@ -70,6 +68,6 @@ tracingEvalLoc
|
|||
=> Maybe FilePath -> [String] -> NExprLoc -> m (NValueNF (Lazy m))
|
||||
tracingEvalLoc mpath incls expr =
|
||||
runLazyM . evalTopLevelExprGen id mpath incls
|
||||
=<< tracingEvalExpr @_ @(Lazy m) @_ @(NValue (Lazy m))
|
||||
=<< Eval.tracingEvalExpr @_ @(Lazy m) @_ @(NValue (Lazy m))
|
||||
(Eval.eval @_ @(NValue (Lazy m))
|
||||
@(NThunk (Lazy m)) @(Lazy m)) expr
|
||||
|
|
|
@ -21,6 +21,7 @@ data Options = Options
|
|||
, check :: Bool
|
||||
, readFrom :: Maybe FilePath
|
||||
, cache :: Bool
|
||||
, repl :: Bool
|
||||
, ignoreErrors :: Bool
|
||||
, expression :: Maybe Text
|
||||
, arg :: [(Text, Text)]
|
||||
|
@ -84,6 +85,9 @@ nixOptions = Options
|
|||
<*> switch
|
||||
( long "cache"
|
||||
<> help "Write out the parsed expression tree to a binary cache")
|
||||
<*> switch
|
||||
( long "repl"
|
||||
<> help "After performing any indicated actions, enter the REPL")
|
||||
<*> switch
|
||||
( long "ignore-errors"
|
||||
<> help "Continue parsing files, even if there are errors")
|
||||
|
|
|
@ -15,7 +15,7 @@ import qualified Data.Map as Map
|
|||
import qualified Data.Text as Text
|
||||
import qualified Data.Text.IO as Text
|
||||
import GHC.Exts
|
||||
import Nix
|
||||
import Nix.Lint
|
||||
import Nix.Options
|
||||
import Nix.Parser
|
||||
import Nix.Pretty
|
||||
|
|
Loading…
Reference in New Issue