0cb3946ee7
M main/Main.hs M main/Repl.hs M src/Nix/Builtins.hs M src/Nix/Convert.hs M src/Nix/Effects.hs M src/Nix/Effects/Basic.hs M src/Nix/Eval.hs M src/Nix/Exec.hs M src/Nix/Expr/Types.hs M src/Nix/Json.hs M src/Nix/Lint.hs M src/Nix/Normal.hs M src/Nix/Options/Parser.hs M src/Nix/Parser.hs M src/Nix/Scope.hs M src/Nix/String.hs M src/Nix/TH.hs M src/Nix/Thunk/Basic.hs M src/Nix/Utils.hs M src/Nix/Value.hs M src/Nix/Value/Equal.hs M src/Nix/XML.hs M tests/EvalTests.hs M tests/Main.hs M tests/NixLanguageTests.hs M tests/ParserTests.hs M tests/TestCommon.hs
96 lines
2.8 KiB
Haskell
96 lines
2.8 KiB
Haskell
{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
{-# LANGUAGE ConstraintKinds #-}
|
|
{-# LANGUAGE DeriveTraversable #-}
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
{-# LANGUAGE FunctionalDependencies #-}
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
{-# LANGUAGE TypeApplications #-}
|
|
|
|
module Nix.Scope where
|
|
|
|
import Control.Applicative
|
|
import Control.Monad.Reader
|
|
import qualified Data.HashMap.Lazy as M
|
|
import Data.Text ( Text )
|
|
import Lens.Family2
|
|
import Nix.Utils
|
|
|
|
newtype Scope a = Scope { getScope :: AttrSet a }
|
|
deriving (Functor, Foldable, Traversable, Eq)
|
|
|
|
instance Show (Scope a) where
|
|
show (Scope m) = show (M.keys m)
|
|
|
|
newScope :: AttrSet a -> Scope a
|
|
newScope = Scope
|
|
|
|
scopeLookup :: Text -> [Scope a] -> Maybe a
|
|
scopeLookup key = foldr go Nothing
|
|
where go (Scope m) rest = M.lookup key m <|> rest
|
|
|
|
data Scopes m a = Scopes
|
|
{ lexicalScopes :: [Scope a]
|
|
, dynamicScopes :: [m (Scope a)]
|
|
}
|
|
|
|
instance Show (Scopes m a) where
|
|
show (Scopes m a) =
|
|
"Scopes: " ++ show m ++ ", and " ++ show (length a) ++ " with-scopes"
|
|
|
|
instance Semigroup (Scopes m a) where
|
|
Scopes ls lw <> Scopes rs rw = Scopes (ls <> rs) (lw <> rw)
|
|
|
|
instance Monoid (Scopes m a) where
|
|
mempty = emptyScopes
|
|
mappend = (<>)
|
|
|
|
emptyScopes :: forall m a . Scopes m a
|
|
emptyScopes = Scopes [] []
|
|
|
|
class Scoped a m | m -> a where
|
|
currentScopes :: m (Scopes m a)
|
|
clearScopes :: m r -> m r
|
|
pushScopes :: Scopes m a -> m r -> m r
|
|
lookupVar :: Text -> m (Maybe a)
|
|
|
|
currentScopesReader
|
|
:: forall m a e . (MonadReader e m, Has e (Scopes m a)) => m (Scopes m a)
|
|
currentScopesReader = asks (view hasLens)
|
|
|
|
clearScopesReader
|
|
:: forall m a e r . (MonadReader e m, Has e (Scopes m a)) => m r -> m r
|
|
clearScopesReader = local (set hasLens (emptyScopes @m @a))
|
|
|
|
pushScope :: Scoped a m => AttrSet a -> m r -> m r
|
|
pushScope s = pushScopes (Scopes [Scope s] [])
|
|
|
|
pushWeakScope :: (Functor m, Scoped a m) => m (AttrSet a) -> m r -> m r
|
|
pushWeakScope s = pushScopes (Scopes [] [Scope <$> s])
|
|
|
|
pushScopesReader
|
|
:: (MonadReader e m, Has e (Scopes m a)) => Scopes m a -> m r -> m r
|
|
pushScopesReader s = local (over hasLens (s <>))
|
|
|
|
lookupVarReader
|
|
:: forall m a e . (MonadReader e m, Has e (Scopes m a)) => Text -> m (Maybe a)
|
|
lookupVarReader k = do
|
|
mres <- asks (scopeLookup k . lexicalScopes @m . view hasLens)
|
|
case mres of
|
|
Just sym -> pure $ Just sym
|
|
Nothing -> do
|
|
ws <- asks (dynamicScopes . view hasLens)
|
|
foldr
|
|
(\x rest -> do
|
|
mres' <- M.lookup k . getScope <$> x
|
|
case mres' of
|
|
Just sym -> pure $ Just sym
|
|
Nothing -> rest
|
|
)
|
|
(pure Nothing)
|
|
ws
|
|
|
|
withScopes :: Scoped a m => Scopes m a -> m r -> m r
|
|
withScopes scope = clearScopes . pushScopes scope
|