2018-04-02 07:49:12 +02:00
|
|
|
{-# LANGUAGE FlexibleContexts #-}
|
2018-04-02 23:41:42 +02:00
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
2018-04-01 19:33:43 +02:00
|
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
2018-04-02 23:41:42 +02:00
|
|
|
{-# LANGUAGE LambdaCase #-}
|
|
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
2018-04-02 07:49:12 +02:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2018-04-02 23:41:42 +02:00
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
2018-04-01 19:33:43 +02:00
|
|
|
|
2018-04-03 23:21:33 +02:00
|
|
|
module Nix (eval, evalLoc, tracingEvalLoc, lint, runLintM) where
|
2018-03-30 23:08:38 +02:00
|
|
|
|
2018-04-03 23:21:33 +02:00
|
|
|
import Control.Applicative
|
2018-04-02 23:41:42 +02:00
|
|
|
import Control.Monad
|
2018-04-01 19:33:43 +02:00
|
|
|
import Control.Monad.Fix
|
|
|
|
import Control.Monad.IO.Class
|
|
|
|
import Control.Monad.Reader (MonadReader)
|
|
|
|
import Control.Monad.Trans.Reader
|
2018-04-04 00:47:33 +02:00
|
|
|
import qualified Data.ByteString as BS
|
2018-03-31 23:43:08 +02:00
|
|
|
import qualified Data.HashMap.Lazy as M
|
2018-04-04 00:47:33 +02:00
|
|
|
import Data.IORef
|
2018-04-02 23:41:42 +02:00
|
|
|
import Data.Text (Text)
|
2018-03-30 23:08:38 +02:00
|
|
|
import Nix.Builtins
|
2018-04-03 23:21:33 +02:00
|
|
|
import qualified Nix.Eval as Eval
|
|
|
|
import Nix.Eval hiding (eval)
|
|
|
|
import Nix.Expr.Types (NExpr)
|
|
|
|
import Nix.Expr.Types.Annotated (NExprLoc)
|
|
|
|
import qualified Nix.Lint as Lint
|
|
|
|
import Nix.Lint hiding (lint)
|
2018-03-30 23:25:03 +02:00
|
|
|
import Nix.Monad
|
2018-03-30 23:08:38 +02:00
|
|
|
import Nix.Monad.Instance
|
2018-03-31 23:43:08 +02:00
|
|
|
import Nix.Scope
|
2018-04-04 00:47:33 +02:00
|
|
|
import Nix.Stack
|
|
|
|
import Nix.Thunk
|
2018-03-30 23:08:38 +02:00
|
|
|
import Nix.Utils
|
2018-04-04 02:15:54 +02:00
|
|
|
import System.IO.Unsafe
|
2018-03-30 23:08:38 +02:00
|
|
|
|
|
|
|
-- | Evaluate a nix expression in the default context
|
2018-03-31 23:43:08 +02:00
|
|
|
evalTopLevelExpr :: MonadBuiltins e m
|
2018-04-03 23:21:33 +02:00
|
|
|
=> NExpr -> m (NValueNF m)
|
|
|
|
evalTopLevelExpr expr = do
|
|
|
|
base <- baseEnv
|
|
|
|
normalForm =<< pushScopes base (Eval.evalExpr expr)
|
|
|
|
|
2018-04-04 02:15:54 +02:00
|
|
|
eval :: (MonadFix m, MonadIO m, MonadInterleave (Lazy m))
|
2018-04-03 23:21:33 +02:00
|
|
|
=> NExpr -> m (NValueNF (Lazy m))
|
|
|
|
eval = runLazyM . evalTopLevelExpr
|
|
|
|
|
|
|
|
-- | Evaluate a nix expression in the default context
|
|
|
|
evalTopLevelExprLoc :: MonadBuiltins e m
|
|
|
|
=> Maybe FilePath -> NExprLoc -> m (NValueNF m)
|
|
|
|
evalTopLevelExprLoc mpath expr = do
|
2018-03-30 23:55:30 +02:00
|
|
|
base <- baseEnv
|
2018-04-03 04:57:05 +02:00
|
|
|
(normalForm =<<) $ pushScopes base $ case mpath of
|
2018-04-03 23:21:33 +02:00
|
|
|
Nothing -> framedEvalExpr Eval.eval expr
|
2018-04-03 04:57:05 +02:00
|
|
|
Just path -> do
|
|
|
|
traceM $ "Setting __cur_file = " ++ show path
|
|
|
|
ref <- valueThunk $ NVLiteralPath path
|
|
|
|
pushScope (M.singleton "__cur_file" ref)
|
2018-04-03 23:21:33 +02:00
|
|
|
(framedEvalExpr Eval.eval expr)
|
2018-03-30 23:08:38 +02:00
|
|
|
|
2018-04-04 02:15:54 +02:00
|
|
|
evalLoc :: (MonadFix m, MonadIO m, MonadInterleave (Lazy m))
|
2018-04-03 23:21:33 +02:00
|
|
|
=> Maybe FilePath -> NExprLoc -> m (NValueNF (Lazy m))
|
|
|
|
evalLoc mpath = runLazyM . evalTopLevelExprLoc mpath
|
2018-03-31 08:00:06 +02:00
|
|
|
|
2018-04-04 02:15:54 +02:00
|
|
|
tracingEvalLoc
|
|
|
|
:: (MonadFix m, MonadIO m, Alternative m, MonadInterleave (Lazy m))
|
|
|
|
=> Maybe FilePath -> NExprLoc -> m (NValueNF (Lazy m))
|
2018-04-03 23:21:33 +02:00
|
|
|
tracingEvalLoc mpath expr = do
|
|
|
|
traced <- tracingEvalExpr Eval.eval expr
|
2018-04-03 04:57:05 +02:00
|
|
|
case mpath of
|
2018-03-30 23:55:30 +02:00
|
|
|
Nothing ->
|
2018-04-03 23:21:33 +02:00
|
|
|
runLazyM (normalForm =<< (`pushScopes` traced) =<< baseEnv)
|
2018-04-03 04:57:05 +02:00
|
|
|
Just path -> do
|
|
|
|
traceM $ "Setting __cur_file = " ++ show path
|
2018-04-03 23:21:33 +02:00
|
|
|
ref <- runLazyM (valueThunk $ NVLiteralPath path)
|
2018-04-03 04:57:05 +02:00
|
|
|
let m = M.singleton "__cur_file" ref
|
2018-04-03 23:21:33 +02:00
|
|
|
runLazyM (baseEnv >>= (`pushScopes` pushScope m traced)
|
2018-03-30 23:55:30 +02:00
|
|
|
>>= normalForm)
|
2018-03-30 23:08:38 +02:00
|
|
|
|
2018-04-01 19:33:43 +02:00
|
|
|
newtype Lint m a = Lint
|
2018-04-03 06:44:01 +02:00
|
|
|
{ runLint :: ReaderT (Context (Lint m) (SThunk (Lint m))) m a }
|
2018-04-01 19:33:43 +02:00
|
|
|
deriving (Functor, Applicative, Monad, MonadFix, MonadIO,
|
2018-04-03 06:44:01 +02:00
|
|
|
MonadReader (Context (Lint m) (SThunk (Lint m))))
|
2018-04-01 19:33:43 +02:00
|
|
|
|
2018-04-04 00:47:33 +02:00
|
|
|
instance MonadIO m => MonadVar (Lint m) where
|
|
|
|
type Var (Lint m) = IORef
|
|
|
|
|
|
|
|
newVar = liftIO . newIORef
|
|
|
|
readVar = liftIO . readIORef
|
|
|
|
writeVar = (liftIO .) . writeIORef
|
|
|
|
|
|
|
|
instance MonadIO m => MonadFile (Lint m) where
|
|
|
|
readFile = liftIO . BS.readFile
|
|
|
|
|
2018-04-04 02:15:54 +02:00
|
|
|
instance MonadInterleave (Lint IO) where
|
|
|
|
unsafeInterleave (Lint (ReaderT f)) = Lint $ ReaderT $ \e ->
|
|
|
|
liftIO $ unsafeInterleaveIO (f e)
|
|
|
|
|
2018-04-04 00:47:33 +02:00
|
|
|
instance MonadIO m =>
|
|
|
|
Eval.MonadExpr (SThunk (Lint m))
|
|
|
|
(IORef (NSymbolicF (NTypeF (Lint m) (SThunk (Lint m)))))
|
|
|
|
(Lint m) where
|
2018-04-02 23:41:42 +02:00
|
|
|
embedSet s = mkSymbolic [TSet (Just s)]
|
|
|
|
projectSet = unpackSymbolic >=> \case
|
|
|
|
NMany [TSet s] -> return s
|
|
|
|
_ -> return Nothing
|
|
|
|
|
|
|
|
type MText (Lint m) = Text
|
|
|
|
|
|
|
|
wrapText = return
|
|
|
|
unwrapText = return
|
|
|
|
|
|
|
|
embedText = const $ mkSymbolic [TStr]
|
|
|
|
projectText = const $ return Nothing
|
|
|
|
|
2018-04-03 23:21:33 +02:00
|
|
|
runLintM :: Lint m a -> m a
|
|
|
|
runLintM = flip runReaderT (Context emptyScopes []) . runLint
|
2018-04-01 19:33:43 +02:00
|
|
|
|
2018-04-03 06:44:01 +02:00
|
|
|
symbolicBaseEnv :: Monad m => m (Scopes m (SThunk m))
|
|
|
|
symbolicBaseEnv = return [] -- jww (2018-04-02): TODO
|
2018-04-01 19:33:43 +02:00
|
|
|
|
2018-04-04 02:15:54 +02:00
|
|
|
lint :: (MonadFix m, MonadIO m, MonadInterleave (Lint m))
|
|
|
|
=> NExpr -> m (Symbolic (Lint m))
|
2018-04-03 23:21:33 +02:00
|
|
|
lint expr = runLintM $ symbolicBaseEnv
|
|
|
|
>>= (`pushScopes` Lint.lintExpr expr)
|