hnix 0.14.0.8 → 0.15.0
raw patch · 63 files changed
+5833/−4398 lines, 63 filesdep +unix-compatdep −unixdep ~basedep ~hashablePVP ok
version bump matches the API change (PVP)
Dependencies added: unix-compat
Dependencies removed: unix
Dependency ranges changed: base, hashable
API changes (from Hackage documentation)
- Nix.Convert: Path :: FilePath -> Path
- Nix.Convert: [getPath] :: Path -> FilePath
- Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.FromValue a m (Nix.Value.NValue t f m)) => Nix.Convert.FromValue (Nix.Utils.AttrSet a) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
- Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.FromValue a m (Nix.Value.NValue t f m)) => Nix.Convert.FromValue (Nix.Utils.AttrSet a, Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
- Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.ToValue a m (Nix.Value.NValue t f m)) => Nix.Convert.ToValue (Nix.Utils.AttrSet a) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
- Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.ToValue a m (Nix.Value.NValue t f m)) => Nix.Convert.ToValue (Nix.Utils.AttrSet a, Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
- Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Value.Monad.MonadValue (Nix.Value.NValue t f m) m) => Nix.Convert.FromValue Nix.Convert.Path m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance GHC.Show.Show Nix.Convert.Path
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue (Nix.Utils.AttrSet (Nix.Value.NValue t f m)) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue (Nix.Utils.AttrSet (Nix.Value.NValue t f m), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue GHC.Integer.Type.Integer m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue (Nix.Utils.AttrSet (Nix.Value.NValue t f m)) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue (Nix.Utils.AttrSet (Nix.Value.NValue t f m), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue GHC.Integer.Type.Integer m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue Nix.Convert.Path m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
- Nix.Convert: newtype Path
- Nix.Effects: [unStorePath] :: StorePath -> FilePath
- Nix.Effects: makeAbsolutePath :: MonadEffects t f m => FilePath -> m FilePath
- Nix.Effects: type FilePathFilter m = FilePath -> m Bool
- Nix.Effects.Basic: defaultMakeAbsolutePath :: MonadNix e t f m => FilePath -> m FilePath
- Nix.Expr.Shorthands: infixl 1 @@
- Nix.Expr.Strings: removePlainEmpty :: [Antiquoted Text r] -> [Antiquoted Text r]
- Nix.Expr.Types: NNonRecursive :: NRecordType
- Nix.Expr.Types: NRecursive :: NRecordType
- Nix.Expr.Types: data NRecordType
- Nix.Expr.Types: instance Codec.Serialise.Class.Serialise Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Control.DeepSeq.NFData Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Data.Aeson.Types.FromJSON.FromJSON Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Data.Aeson.Types.ToJSON.ToJSON Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Data.Binary.Class.Binary Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Data.Data.Data Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance Data.Hashable.Class.Hashable Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Classes.Eq Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Classes.Ord Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Enum.Bounded Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Enum.Enum Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Generics.Generic Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Read.Read Nix.Expr.Types.NRecordType
- Nix.Expr.Types: instance GHC.Show.Show Nix.Expr.Types.NRecordType
- Nix.Expr.Types: type VarName = Text
- Nix.Expr.Types.Annotated: Ann :: ann -> a -> Ann ann a
- Nix.Expr.Types.Annotated: annToAnnF :: Ann ann (f (Fix (AnnF ann f))) -> Fix (AnnF ann f)
- Nix.Expr.Types.Annotated: data Ann ann a
- Nix.Expr.Types.Annotated: instance (Codec.Serialise.Class.Serialise ann, Codec.Serialise.Class.Serialise a) => Codec.Serialise.Class.Serialise (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (Control.DeepSeq.NFData ann, Control.DeepSeq.NFData a) => Control.DeepSeq.NFData (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (Data.Binary.Class.Binary ann, Data.Binary.Class.Binary a) => Data.Binary.Class.Binary (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (Data.Data.Data ann, Data.Data.Data a) => Data.Data.Data (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (Data.Hashable.Class.Hashable ann, Data.Hashable.Class.Hashable a) => Data.Hashable.Class.Hashable (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (GHC.Classes.Eq ann, GHC.Classes.Eq a) => GHC.Classes.Eq (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (GHC.Classes.Ord ann, GHC.Classes.Ord a) => GHC.Classes.Ord (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (GHC.Read.Read ann, GHC.Read.Read a) => GHC.Read.Read (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance (GHC.Show.Show ann, GHC.Show.Show a) => GHC.Show.Show (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance Control.DeepSeq.NFData ann => Control.DeepSeq.NFData1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance Data.Aeson.Types.FromJSON.FromJSON ann => Data.Aeson.Types.FromJSON.FromJSON1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance Data.Aeson.Types.FromJSON.FromJSON2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Aeson.Types.ToJSON.ToJSON ann => Data.Aeson.Types.ToJSON.ToJSON1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance Data.Aeson.Types.ToJSON.ToJSON2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Foldable.Foldable (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Eq2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Ord2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Read2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Show2 Nix.Expr.Types.Annotated.Ann
- Nix.Expr.Types.Annotated: instance Data.Hashable.Class.Hashable ann => Data.Hashable.Class.Hashable1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance Data.Traversable.Traversable (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Base.Functor (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Classes.Eq ann => Data.Functor.Classes.Eq1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Classes.Ord ann => Data.Functor.Classes.Ord1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Generics.Generic (Nix.Expr.Types.Annotated.Ann ann a)
- Nix.Expr.Types.Annotated: instance GHC.Generics.Generic1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Read.Read ann => Data.Functor.Classes.Read1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: instance GHC.Show.Show ann => Data.Functor.Classes.Show1 (Nix.Expr.Types.Annotated.Ann ann)
- Nix.Expr.Types.Annotated: nAbs :: Ann SrcSpan (Params NExprLoc) -> NExprLoc -> NExprLoc
- Nix.Expr.Types.Annotated: nApp :: NExprLoc -> NExprLoc -> NExprLoc
- Nix.Expr.Types.Annotated: nBinary :: Ann SrcSpan NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc
- Nix.Expr.Types.Annotated: nHasAttr :: NExprLoc -> Ann SrcSpan (NAttrPath NExprLoc) -> NExprLoc
- Nix.Expr.Types.Annotated: nNull :: NExprLoc
- Nix.Expr.Types.Annotated: nSelectLoc :: NExprLoc -> Ann SrcSpan (NAttrPath NExprLoc) -> Maybe NExprLoc -> NExprLoc
- Nix.Expr.Types.Annotated: nStr :: Ann SrcSpan (NString NExprLoc) -> NExprLoc
- Nix.Expr.Types.Annotated: nUnary :: Ann SrcSpan NUnaryOp -> NExprLoc -> NExprLoc
- Nix.Expr.Types.Annotated: pattern AnnE :: forall ann (f :: Type -> Type). ann -> f (Fix (AnnF ann f)) -> Fix (AnnF ann f)
- Nix.Expr.Types.Annotated: pattern AnnFP :: ann -> f a -> Compose (Ann ann) f a
- Nix.Expr.Types.Annotated: pattern NAbs_ :: SrcSpan -> Params r -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NAssert_ :: SrcSpan -> r -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NBinary_ :: SrcSpan -> NBinaryOp -> r -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NConstant_ :: SrcSpan -> NAtom -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NEnvPath_ :: SrcSpan -> FilePath -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NHasAttr_ :: SrcSpan -> r -> NAttrPath r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NIf_ :: SrcSpan -> r -> r -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NLet_ :: SrcSpan -> [Binding r] -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NList_ :: SrcSpan -> [r] -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NLiteralPath_ :: SrcSpan -> FilePath -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NSelect_ :: SrcSpan -> r -> NAttrPath r -> Maybe r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NSet_ :: SrcSpan -> NRecordType -> [Binding r] -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NStr_ :: SrcSpan -> NString r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NSym_ :: SrcSpan -> VarName -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NSynHole_ :: SrcSpan -> Text -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NUnary_ :: SrcSpan -> NUnaryOp -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: pattern NWith_ :: SrcSpan -> r -> r -> NExprLocF r
- Nix.Expr.Types.Annotated: stripAnn :: AnnF ann f r -> f r
- Nix.Frames: AllocationLimitExceeded :: AllocationLimitExceeded
- Nix.Frames: AssertionFailed :: String -> AssertionFailed
- Nix.Frames: BlockedIndefinitelyOnMVar :: BlockedIndefinitelyOnMVar
- Nix.Frames: BlockedIndefinitelyOnSTM :: BlockedIndefinitelyOnSTM
- Nix.Frames: CompactionFailed :: String -> CompactionFailed
- Nix.Frames: Deadlock :: Deadlock
- Nix.Frames: Denormal :: ArithException
- Nix.Frames: DivideByZero :: ArithException
- Nix.Frames: ErrorCallWithLocation :: String -> String -> ErrorCall
- Nix.Frames: Handler :: (e -> IO a) -> Handler a
- Nix.Frames: HeapOverflow :: AsyncException
- Nix.Frames: IndexOutOfBounds :: String -> ArrayException
- Nix.Frames: LossOfPrecision :: ArithException
- Nix.Frames: MaskedInterruptible :: MaskingState
- Nix.Frames: MaskedUninterruptible :: MaskingState
- Nix.Frames: NestedAtomically :: NestedAtomically
- Nix.Frames: NoMethodError :: String -> NoMethodError
- Nix.Frames: NonTermination :: NonTermination
- Nix.Frames: Overflow :: ArithException
- Nix.Frames: PatternMatchFail :: String -> PatternMatchFail
- Nix.Frames: RatioZeroDenominator :: ArithException
- Nix.Frames: RecConError :: String -> RecConError
- Nix.Frames: RecSelError :: String -> RecSelError
- Nix.Frames: RecUpdError :: String -> RecUpdError
- Nix.Frames: SomeAsyncException :: e -> SomeAsyncException
- Nix.Frames: SomeException :: e -> SomeException
- Nix.Frames: StackOverflow :: AsyncException
- Nix.Frames: ThreadKilled :: AsyncException
- Nix.Frames: TypeError :: String -> TypeError
- Nix.Frames: UndefinedElement :: String -> ArrayException
- Nix.Frames: Underflow :: ArithException
- Nix.Frames: Unmasked :: MaskingState
- Nix.Frames: UserInterrupt :: AsyncException
- Nix.Frames: allowInterrupt :: IO ()
- Nix.Frames: assert :: Bool -> a -> a
- Nix.Frames: asyncExceptionFromException :: Exception e => SomeException -> Maybe e
- Nix.Frames: asyncExceptionToException :: Exception e => e -> SomeException
- Nix.Frames: bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
- Nix.Frames: bracketOnError :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
- Nix.Frames: bracket_ :: IO a -> IO b -> IO c -> IO c
- Nix.Frames: catchJust :: Exception e => (e -> Maybe b) -> IO a -> (b -> IO a) -> IO a
- Nix.Frames: catches :: IO a -> [Handler a] -> IO a
- Nix.Frames: class (Typeable e, Show e) => Exception e
- Nix.Frames: data AllocationLimitExceeded
- Nix.Frames: data ArithException
- Nix.Frames: data ArrayException
- Nix.Frames: data AsyncException
- Nix.Frames: data BlockedIndefinitelyOnMVar
- Nix.Frames: data BlockedIndefinitelyOnSTM
- Nix.Frames: data Deadlock
- Nix.Frames: data ErrorCall
- Nix.Frames: data Handler a
- Nix.Frames: data IOException
- Nix.Frames: data MaskingState
- Nix.Frames: data NestedAtomically
- Nix.Frames: data NonTermination
- Nix.Frames: data SomeAsyncException
- Nix.Frames: data SomeException
- Nix.Frames: displayException :: Exception e => e -> String
- Nix.Frames: finally :: IO a -> IO b -> IO a
- Nix.Frames: fromException :: Exception e => SomeException -> Maybe e
- Nix.Frames: getMaskingState :: IO MaskingState
- Nix.Frames: handle :: Exception e => (e -> IO a) -> IO a -> IO a
- Nix.Frames: handleJust :: Exception e => (e -> Maybe b) -> (b -> IO a) -> IO a -> IO a
- Nix.Frames: interruptible :: IO a -> IO a
- Nix.Frames: ioError :: IOError -> IO a
- Nix.Frames: mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a
- Nix.Frames: mask :: ((forall a. () => IO a -> IO a) -> IO b) -> IO b
- Nix.Frames: mask_ :: IO a -> IO a
- Nix.Frames: newtype AssertionFailed
- Nix.Frames: newtype CompactionFailed
- Nix.Frames: newtype NoMethodError
- Nix.Frames: newtype PatternMatchFail
- Nix.Frames: newtype RecConError
- Nix.Frames: newtype RecSelError
- Nix.Frames: newtype RecUpdError
- Nix.Frames: newtype TypeError
- Nix.Frames: onException :: IO a -> IO b -> IO a
- Nix.Frames: pattern ErrorCall :: String -> ErrorCall
- Nix.Frames: throw :: forall (r :: RuntimeRep) (a :: TYPE r) e. Exception e => e -> a
- Nix.Frames: throwIO :: Exception e => e -> IO a
- Nix.Frames: throwTo :: Exception e => ThreadId -> e -> IO ()
- Nix.Frames: toException :: Exception e => e -> SomeException
- Nix.Frames: try :: Exception e => IO a -> IO (Either e a)
- Nix.Frames: tryJust :: Exception e => (e -> Maybe b) -> IO a -> IO (Either b a)
- Nix.Frames: uninterruptibleMask :: ((forall a. () => IO a -> IO a) -> IO b) -> IO b
- Nix.Frames: uninterruptibleMask_ :: IO a -> IO a
- Nix.Fresh: [unFreshIdT] :: FreshIdT i m a -> ReaderT (Ref m i) m a
- Nix.Lint: instance Nix.Convert.FromValue (Nix.Utils.AttrSet (Nix.Lint.Symbolic m), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Lint.Symbolic m)
- Nix.Lint: instance Nix.Convert.ToValue (Nix.Utils.AttrSet (Nix.Lint.Symbolic m), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) m (Nix.Lint.Symbolic m)
- Nix.Parser: nixToplevelForm :: Parser NExprLoc
- Nix.Parser: symbol :: Text -> Parser Text
- Nix.Reduce: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (GHC.Maybe.Maybe GHC.IO.FilePath, Nix.Scope.Scopes (Nix.Reduce.Reducer m) Nix.Expr.Types.Annotated.NExprLoc) (Nix.Reduce.Reducer m)
- Nix.Reduce: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap GHC.IO.FilePath Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) (Nix.Reduce.Reducer m)
- Nix.Render: instance (Nix.Utils.Fix1.MonadFix1T t m, Control.Monad.Fail.MonadFail (Nix.Utils.Fix1.Fix1T t m), Nix.Render.MonadFile m) => Nix.Render.MonadFile (Nix.Utils.Fix1.Fix1T t m)
- Nix.Scope: [getScope] :: Scope a -> AttrSet a
- Nix.Scope: newScope :: AttrSet a -> Scope a
- Nix.Standard: [_stdCited] :: StdCited m a -> Cited (StdThunk m) (StdCited m) m a
- Nix.Standard: [_stdThunk] :: StdThunk (m :: Type -> Type) -> StdCited m (NThunkF m (StdValue m))
- Nix.Standard: instance (Control.Monad.Fix.MonadFix m, Nix.Render.MonadFile m, Control.Monad.Catch.MonadCatch m, Nix.Effects.MonadEnv m, Nix.Effects.MonadPaths m, Nix.Effects.MonadExec m, Nix.Effects.MonadHttp m, Nix.Effects.MonadInstantiate m, Nix.Effects.MonadIntrospect m, GHC.Base.MonadPlus m, Nix.Effects.MonadPutStr m, Nix.Effects.MonadStore m, Control.Monad.Ref.MonadAtomicRef m, Data.Typeable.Internal.Typeable m, Nix.Scope.Scoped (Nix.Standard.StdValue m) m, Control.Monad.Reader.Class.MonadReader (Nix.Context.Context m (Nix.Standard.StdValue m)) m, Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap GHC.IO.FilePath Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) m, Nix.Value.MonadDataErrorContext (Nix.Standard.StdThunk m) (Nix.Standard.StdCited m) m, Nix.Thunk.MonadThunk (Nix.Standard.StdThunk m) m (Nix.Standard.StdValue m), Nix.Value.Monad.MonadValue (Nix.Standard.StdValue m) m) => Nix.Effects.MonadEffects (Nix.Standard.StdThunk m) (Nix.Standard.StdCited m) m
- Nix.Standard: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap GHC.IO.FilePath Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) (Nix.Standard.StandardTF r m)
- Nix.Standard: instance Nix.Thunk.MonadThunkId m => Nix.Thunk.MonadThunkId (Nix.Utils.Fix1.Fix1T Nix.Standard.StandardTF m)
- Nix.String: makeNixString :: Text -> HashSet StringContext -> NixString
- Nix.String: makeNixStringWithSingletonContext :: Text -> StringContext -> NixString
- Nix.String: makeNixStringWithoutContext :: Text -> NixString
- Nix.TH: instance Nix.TH.ToExpr GHC.Integer.Type.Integer
- Nix.Type.Assumption: [assumptions] :: Assumption -> [(Name, Type)]
- Nix.Type.Assumption: mergeAssumptions :: [Assumption] -> Assumption
- Nix.Type.Infer: instance Nix.Type.Infer.MonadInfer m => Nix.Convert.FromValue (Nix.Utils.AttrSet (Nix.Type.Infer.Judgment s), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) (Nix.Type.Infer.InferT s m) (Nix.Type.Infer.Judgment s)
- Nix.Type.Infer: instance Nix.Type.Infer.MonadInfer m => Nix.Convert.ToValue (Nix.Utils.AttrSet (Nix.Type.Infer.Judgment s), Nix.Utils.AttrSet Text.Megaparsec.Pos.SourcePos) (Nix.Type.Infer.InferT s m) (Nix.Type.Infer.Judgment s)
- Nix.Type.Type: type Name = Text
- Nix.Utils: (%~) :: Setter s t a b -> (a -> b) -> s -> t
- Nix.Utils: (&&~) :: Setter s t Bool Bool -> Bool -> s -> t
- Nix.Utils: (*~) :: Num a => Setter s t a a -> a -> s -> t
- Nix.Utils: (+~) :: Num a => Setter s t a a -> a -> s -> t
- Nix.Utils: (-~) :: Num a => Setter s t a a -> a -> s -> t
- Nix.Utils: (.~) :: Setter s t a b -> b -> s -> t
- Nix.Utils: (//~) :: Fractional a => Setter s t a a -> a -> s -> t
- Nix.Utils: (<>~) :: Monoid a => Setter s t a a -> a -> s -> t
- Nix.Utils: (^.) :: s -> FoldLike a s t a b -> a
- Nix.Utils: (^..) :: s -> Fold s t a b -> [a]
- Nix.Utils: (^?) :: s -> Fold s t a b -> Maybe a
- Nix.Utils: (||~) :: Setter s t Bool Bool -> Bool -> s -> t
- Nix.Utils: PathEntryPath :: NixPathEntryType
- Nix.Utils: PathEntryURI :: NixPathEntryType
- Nix.Utils: _unFix :: Functor f1 => (f2 (Fix f2) -> f1 (f3 (Fix f3))) -> Fix f2 -> f1 (Fix f3)
- Nix.Utils: adiM :: (Traversable t, Monad m) => Transform t (m a) -> AlgM t m a -> Fix t -> m a
- Nix.Utils: allOf :: Fold s t a b -> (a -> Bool) -> s -> Bool
- Nix.Utils: alterF :: (Eq k, Hashable k, Functor f) => (Maybe v -> f (Maybe v)) -> k -> HashMap k v -> f (HashMap k v)
- Nix.Utils: anyOf :: Fold s t a b -> (a -> Bool) -> s -> Bool
- Nix.Utils: cataP :: Functor f => (Fix f -> f a -> a) -> Fix f -> a
- Nix.Utils: cataPM :: (Traversable f, Monad m) => (Fix f -> f a -> m a) -> Fix f -> m a
- Nix.Utils: class (Traversable f, Applicative f) => Identical (f :: Type -> Type)
- Nix.Utils: class Functor f => Phantom (f :: Type -> Type)
- Nix.Utils: data Constant a (b :: k)
- Nix.Utils: data NixPathEntryType
- Nix.Utils: degrating :: Grate s t a b -> ((s -> a) -> b) -> t
- Nix.Utils: firstOf :: Fold s t a b -> s -> Maybe a
- Nix.Utils: fixToFree :: Functor f => Fix f -> Free f a
- Nix.Utils: folding :: Foldable f => (s -> f a) -> Fold s t a b
- Nix.Utils: freeToFix :: Functor f => (a -> Fix f) -> Free f a -> Fix f
- Nix.Utils: infixl 8 ^.
- Nix.Utils: infixr 4 %~
- Nix.Utils: instance GHC.Classes.Eq Nix.Utils.NixPathEntryType
- Nix.Utils: instance GHC.Show.Show Nix.Utils.NixPathEntryType
- Nix.Utils: lastOf :: Fold s t a b -> s -> Maybe a
- Nix.Utils: lengthOf :: Num r => Fold s t a b -> s -> r
- Nix.Utils: loeb :: Functor f => f (f a -> a) -> f a
- Nix.Utils: matching :: Traversal s t a b -> s -> Either t a
- Nix.Utils: nullOf :: Fold s t a b -> s -> Bool
- Nix.Utils: para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a
- Nix.Utils: paraM :: (Traversable f, Monad m) => (f (Fix f, a) -> m a) -> Fix f -> m a
- Nix.Utils: productOf :: Num a => Fold s t a b -> s -> a
- Nix.Utils: reset :: Resetter s t a b -> b -> s -> t
- Nix.Utils: review :: GrateLike (Constant () :: Type -> Type) s t a b -> b -> t
- Nix.Utils: set :: Setter s t a b -> b -> s -> t
- Nix.Utils: sumOf :: Num a => Fold s t a b -> s -> a
- Nix.Utils: to :: (s -> a) -> Getter s t a b
- Nix.Utils: toEncodingSorted :: Value -> Encoding
- Nix.Utils: toListOf :: Fold s t a b -> s -> [a]
- Nix.Utils: type AdapterLike (f :: Type -> Type) (g :: Type -> Type) s t a b = g a -> f b -> g s -> f t
- Nix.Utils: type AdapterLike' (f :: Type -> Type) (g :: Type -> Type) s a = g a -> f a -> g s -> f s
- Nix.Utils: type AlgM f m a = f a -> m a
- Nix.Utils: type AttrSet = HashMap Text
- Nix.Utils: type FoldLike r s t a b = LensLike Constant r :: Type -> Type s t a b
- Nix.Utils: type FoldLike' r s a = LensLike' Constant r :: Type -> Type s a
- Nix.Utils: type GrateLike (g :: Type -> Type) s t a b = g a -> b -> g s -> t
- Nix.Utils: type GrateLike' (g :: Type -> Type) s a = g a -> a -> g s -> s
- Nix.Utils: type LensLike (f :: Type -> Type) s t a b = a -> f b -> s -> f t
- Nix.Utils: under :: Resetter s t a b -> (a -> b) -> s -> t
- Nix.Utils: uriAwareSplit :: Text -> [(Text, NixPathEntryType)]
- Nix.Utils: views :: FoldLike r s t a b -> (a -> r) -> s -> r
- Nix.Utils: whenFree :: Monoid b => (f (Free f a) -> b) -> Free f a -> b
- Nix.Utils: whenPure :: Monoid b => (a -> b) -> Free f a -> b
- Nix.Utils: zipWithOf :: Grate s t a b -> (a -> a -> b) -> s -> s -> t
- Nix.Value: pattern NVSet :: forall (w :: Type -> Type) t (m :: Type -> Type) a. Comonad w => AttrSet (Free (NValue' t w m) a) -> AttrSet SourcePos -> Free (NValue' t w m) a
- Nix.Value: pattern NVPath :: forall (w :: Type -> Type) t (m :: Type -> Type) a. Comonad w => FilePath -> Free (NValue' t w m) a
- Nix.Value: pattern NVBuiltin :: forall (w :: Type -> Type) t m a. Comonad w => Text -> (NValue t w m -> m (Free (NValue' t w m) a)) -> Free (NValue' t w m) a
+ Nix.Builtins: instance GHC.Classes.Eq Nix.Builtins.NixPathEntryType
+ Nix.Builtins: instance GHC.Show.Show Nix.Builtins.NixPathEntryType
+ Nix.Convert: inHask :: forall a1 a2 v b m. (Monad m, FromValue a1 m v, ToValue a2 m b) => (a1 -> a2) -> v -> m b
+ Nix.Convert: inHaskM :: forall a1 a2 v b m. (Monad m, FromValue a1 m v, ToValue a2 m b) => (a1 -> m a2) -> v -> m b
+ Nix.Convert: inHaskMay :: forall a1 a2 v b m. (Monad m, FromValue a1 m v, ToValue a2 m b) => (Maybe a1 -> a2) -> v -> m b
+ Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.FromValue a m (Nix.Value.NValue t f m)) => Nix.Convert.FromValue (Nix.Expr.Types.AttrSet a) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
+ Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.FromValue a m (Nix.Value.NValue t f m)) => Nix.Convert.FromValue (Nix.Expr.Types.AttrSet a, Nix.Expr.Types.PositionSet) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
+ Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.ToValue a m (Nix.Value.NValue t f m)) => Nix.Convert.ToValue (Nix.Expr.Types.AttrSet a) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
+ Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Convert.ToValue a m (Nix.Value.NValue t f m)) => Nix.Convert.ToValue (Nix.Expr.Types.AttrSet a, Nix.Expr.Types.PositionSet) m (Nix.Convert.Deeper (Nix.Value.NValue' t f m (Nix.Value.NValue t f m)))
+ Nix.Convert: instance (Nix.Convert.Convertible e t f m, Nix.Value.Monad.MonadValue (Nix.Value.NValue t f m) m) => Nix.Convert.FromValue Nix.Utils.Path m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue (Nix.Expr.Types.AttrSet (Nix.Value.NValue t f m)) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue (Nix.Expr.Types.AttrSet (Nix.Value.NValue t f m), Nix.Expr.Types.PositionSet) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue Data.Text.Internal.Text m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.FromValue GHC.Num.Integer.Integer m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue (Nix.Expr.Types.AttrSet (Nix.Value.NValue t f m)) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue (Nix.Expr.Types.AttrSet (Nix.Value.NValue t f m), Nix.Expr.Types.PositionSet) m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue Data.Text.Internal.Text m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue GHC.Num.Integer.Integer m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: instance Nix.Convert.Convertible e t f m => Nix.Convert.ToValue Nix.Utils.Path m (Nix.Value.NValue' t f m (Nix.Value.NValue t f m))
+ Nix.Convert: traverseFromM :: (Applicative m, Traversable t, FromValue b m a) => t a -> m (Maybe (t b))
+ Nix.Convert: traverseToValue :: (Traversable t, Applicative f, ToValue a f b) => t a -> f (t b)
+ Nix.Effects: toAbsolutePath :: MonadEffects t f m => Path -> m Path
+ Nix.Effects: type PathFilter m = Path -> m Bool
+ Nix.Effects.Basic: defaultToAbsolutePath :: forall e t f m. MonadNix e t f m => Path -> m Path
+ Nix.Expr.Shorthands: (@.<|>) :: NExpr -> Text -> NExpr -> NExpr
+ Nix.Expr.Shorthands: emptyList :: NExpr
+ Nix.Expr.Shorthands: emptySet :: NExpr
+ Nix.Expr.Shorthands: getRefOrDefault :: Maybe NExpr -> NExpr -> Text -> NExpr
+ Nix.Expr.Shorthands: infix 1 $->
+ Nix.Expr.Shorthands: infix 3 $!=
+ Nix.Expr.Shorthands: infix 4 $>=
+ Nix.Expr.Shorthands: infix 9 @.<|>
+ Nix.Expr.Shorthands: infixl 5 $-
+ Nix.Expr.Shorthands: infixl 6 $/
+ Nix.Expr.Shorthands: infixl 8 @@
+ Nix.Expr.Shorthands: infixr 5 $//
+ Nix.Expr.Shorthands: infixr 7 $++
+ Nix.Expr.Shorthands: mkConst :: NAtom -> NExpr
+ Nix.Expr.Shorthands: mkGeneralParamSet :: Maybe Text -> [(Text, Maybe NExpr)] -> Bool -> Params NExpr
+ Nix.Expr.Shorthands: mkNamedParamSet :: Text -> [(Text, Maybe NExpr)] -> Params NExpr
+ Nix.Expr.Shorthands: mkNamedVariadicParamSet :: Text -> [(Text, Maybe NExpr)] -> Params NExpr
+ Nix.Expr.Shorthands: mkNeg :: NExpr -> NExpr
+ Nix.Expr.Shorthands: mkOp :: NUnaryOp -> NExpr -> NExpr
+ Nix.Expr.Shorthands: mkOp2 :: NBinaryOp -> NExpr -> NExpr -> NExpr
+ Nix.Expr.Shorthands: mkParamSet :: [(Text, Maybe NExpr)] -> Params NExpr
+ Nix.Expr.Shorthands: mkSet :: Recursivity -> [Binding NExpr] -> NExpr
+ Nix.Expr.Shorthands: mkVariadicParamSet :: [(Text, Maybe NExpr)] -> Params NExpr
+ Nix.Expr.Strings: removeEmptyPlains :: [Antiquoted Text r] -> [Antiquoted Text r]
+ Nix.Expr.Types: Closed :: Variadic
+ Nix.Expr.Types: NonRecursive :: Recursivity
+ Nix.Expr.Types: Recursive :: Recursivity
+ Nix.Expr.Types: VarName :: Text -> VarName
+ Nix.Expr.Types: Variadic :: Variadic
+ Nix.Expr.Types: data Recursivity
+ Nix.Expr.Types: data Variadic
+ Nix.Expr.Types: instance Codec.Serialise.Class.Serialise Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Codec.Serialise.Class.Serialise Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Codec.Serialise.Class.Serialise Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Control.DeepSeq.NFData Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Control.DeepSeq.NFData Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Control.DeepSeq.NFData Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.Aeson.Types.FromJSON.FromJSON Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Data.Aeson.Types.FromJSON.FromJSON Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Data.Aeson.Types.FromJSON.FromJSON Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.Aeson.Types.ToJSON.ToJSON Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Data.Aeson.Types.ToJSON.ToJSON Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Data.Aeson.Types.ToJSON.ToJSON Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.Binary.Class.Binary Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Data.Binary.Class.Binary Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Data.Binary.Class.Binary Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.Data.Data Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Data.Data.Data Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Data.Data.Data Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.Hashable.Class.Hashable Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance Data.Hashable.Class.Hashable Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance Data.Hashable.Class.Hashable Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Data.String.IsString Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Base.Monoid Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Base.Monoid Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Base.Semigroup Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Base.Semigroup Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Classes.Eq Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Classes.Eq Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Classes.Eq Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Classes.Ord Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Classes.Ord Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Classes.Ord Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Enum.Bounded Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Enum.Enum Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Generics.Generic Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Generics.Generic Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Generics.Generic Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Read.Read Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Read.Read Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Read.Read Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance GHC.Show.Show Nix.Expr.Types.Recursivity
+ Nix.Expr.Types: instance GHC.Show.Show Nix.Expr.Types.VarName
+ Nix.Expr.Types: instance GHC.Show.Show Nix.Expr.Types.Variadic
+ Nix.Expr.Types: instance Relude.String.Conversion.ToString Nix.Expr.Types.VarName
+ Nix.Expr.Types: newtype VarName
+ Nix.Expr.Types: stringParts :: NString r -> [Antiquoted Text r]
+ Nix.Expr.Types: type AttrSet = HashMap VarName
+ Nix.Expr.Types: type PositionSet = HashMap VarName SourcePos
+ Nix.Expr.Types.Annotated: AnnUnit :: ann -> expr -> AnnUnit ann expr
+ Nix.Expr.Types.Annotated: annNAbs :: AnnUnit SrcSpan (Params NExprLoc) -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: annNApp :: NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: annNBinary :: AnnUnit SrcSpan NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: annNHasAttr :: NExprLoc -> AnnUnit SrcSpan (NAttrPath NExprLoc) -> NExprLoc
+ Nix.Expr.Types.Annotated: annNNull :: NExprLoc
+ Nix.Expr.Types.Annotated: annNSelect :: Maybe NExprLoc -> NExprLoc -> AnnUnit SrcSpan (NAttrPath NExprLoc) -> NExprLoc
+ Nix.Expr.Types.Annotated: annNStr :: AnnUnit SrcSpan (NString NExprLoc) -> NExprLoc
+ Nix.Expr.Types.Annotated: annNUnary :: AnnUnit SrcSpan NUnaryOp -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: annUnitToAnn :: AnnUnit ann (f (Ann ann f)) -> Ann ann f
+ Nix.Expr.Types.Annotated: data AnnUnit ann expr
+ Nix.Expr.Types.Annotated: instance (Codec.Serialise.Class.Serialise ann, Codec.Serialise.Class.Serialise a) => Codec.Serialise.Class.Serialise (Nix.Expr.Types.Annotated.AnnUnit ann a)
+ Nix.Expr.Types.Annotated: instance (Control.DeepSeq.NFData ann, Control.DeepSeq.NFData expr) => Control.DeepSeq.NFData (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (Data.Binary.Class.Binary ann, Data.Binary.Class.Binary a) => Data.Binary.Class.Binary (Nix.Expr.Types.Annotated.AnnUnit ann a)
+ Nix.Expr.Types.Annotated: instance (Data.Data.Data ann, Data.Data.Data expr) => Data.Data.Data (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (Data.Hashable.Class.Hashable ann, Data.Hashable.Class.Hashable expr) => Data.Hashable.Class.Hashable (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (GHC.Classes.Eq ann, GHC.Classes.Eq expr) => GHC.Classes.Eq (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (GHC.Classes.Ord ann, GHC.Classes.Ord expr) => GHC.Classes.Ord (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (GHC.Read.Read ann, GHC.Read.Read expr) => GHC.Read.Read (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance (GHC.Show.Show ann, GHC.Show.Show expr) => GHC.Show.Show (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance Control.DeepSeq.NFData ann => Control.DeepSeq.NFData1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance Data.Aeson.Types.FromJSON.FromJSON ann => Data.Aeson.Types.FromJSON.FromJSON1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance Data.Aeson.Types.FromJSON.FromJSON2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Aeson.Types.ToJSON.ToJSON ann => Data.Aeson.Types.ToJSON.ToJSON1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance Data.Aeson.Types.ToJSON.ToJSON2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Foldable.Foldable (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Eq2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Ord2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Read2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Functor.Classes.Show2 Nix.Expr.Types.Annotated.AnnUnit
+ Nix.Expr.Types.Annotated: instance Data.Hashable.Class.Hashable ann => Data.Hashable.Class.Hashable1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance Data.Traversable.Traversable (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Base.Functor (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Classes.Eq ann => Data.Functor.Classes.Eq1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Classes.Ord ann => Data.Functor.Classes.Ord1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Generics.Generic (Nix.Expr.Types.Annotated.AnnUnit ann expr)
+ Nix.Expr.Types.Annotated: instance GHC.Generics.Generic1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Read.Read ann => Data.Functor.Classes.Read1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: instance GHC.Show.Show ann => Data.Functor.Classes.Show1 (Nix.Expr.Types.Annotated.AnnUnit ann)
+ Nix.Expr.Types.Annotated: pattern Ann :: forall ann (f :: Type -> Type). ann -> f (Ann ann f) -> Ann ann f
+ Nix.Expr.Types.Annotated: pattern AnnF :: ann -> f a -> Compose (AnnUnit ann) f a
+ Nix.Expr.Types.Annotated: pattern NAbsAnn :: SrcSpan -> Params NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NAbsAnnF :: SrcSpan -> Params r -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NAssertAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NAssertAnnF :: SrcSpan -> r -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NBinaryAnn :: SrcSpan -> NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NBinaryAnnF :: SrcSpan -> NBinaryOp -> r -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NConstantAnn :: SrcSpan -> NAtom -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NConstantAnnF :: SrcSpan -> NAtom -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NEnvPathAnn :: SrcSpan -> Path -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NEnvPathAnnF :: SrcSpan -> Path -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NHasAttrAnn :: SrcSpan -> NExprLoc -> NAttrPath NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NHasAttrAnnF :: SrcSpan -> r -> NAttrPath r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NIfAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NIfAnnF :: SrcSpan -> r -> r -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NLetAnn :: SrcSpan -> [Binding NExprLoc] -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NLetAnnF :: SrcSpan -> [Binding r] -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NListAnn :: SrcSpan -> [NExprLoc] -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NListAnnF :: SrcSpan -> [r] -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NLiteralPathAnn :: SrcSpan -> Path -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NLiteralPathAnnF :: SrcSpan -> Path -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NSelectAnn :: SrcSpan -> Maybe NExprLoc -> NExprLoc -> NAttrPath NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NSelectAnnF :: SrcSpan -> Maybe r -> r -> NAttrPath r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NSetAnn :: SrcSpan -> Recursivity -> [Binding NExprLoc] -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NSetAnnF :: SrcSpan -> Recursivity -> [Binding r] -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NStrAnn :: SrcSpan -> NString NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NStrAnnF :: SrcSpan -> NString r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NSymAnn :: SrcSpan -> VarName -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NSymAnnF :: SrcSpan -> VarName -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NSynHoleAnn :: SrcSpan -> VarName -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NSynHoleAnnF :: SrcSpan -> VarName -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NUnaryAnn :: SrcSpan -> NUnaryOp -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NUnaryAnnF :: SrcSpan -> NUnaryOp -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: pattern NWithAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc
+ Nix.Expr.Types.Annotated: pattern NWithAnnF :: SrcSpan -> r -> r -> NExprLocF r
+ Nix.Expr.Types.Annotated: stripAnnF :: AnnF ann f r -> f r
+ Nix.Expr.Types.Annotated: type Ann ann f = Fix (AnnF ann f)
+ Nix.Json: toEncodingSorted :: Value -> Encoding
+ Nix.Lint: instance Nix.Convert.FromValue (Nix.Expr.Types.AttrSet (Nix.Lint.Symbolic m), Nix.Expr.Types.PositionSet) m (Nix.Lint.Symbolic m)
+ Nix.Lint: instance Nix.Convert.ToValue (Nix.Expr.Types.AttrSet (Nix.Lint.Symbolic m), Nix.Expr.Types.PositionSet) m (Nix.Lint.Symbolic m)
+ Nix.Parser: nixExprAlgebra :: Parser NExprLoc
+ Nix.Pretty: prettyVarName :: VarName -> Doc ann
+ Nix.Reduce: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (GHC.Maybe.Maybe Nix.Utils.Path, Nix.Scope.Scopes (Nix.Reduce.Reducer m) Nix.Expr.Types.Annotated.NExprLoc) (Nix.Reduce.Reducer m)
+ Nix.Reduce: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap Nix.Utils.Path Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) (Nix.Reduce.Reducer m)
+ Nix.Render: instance (Nix.Utils.Fix1.MonadFix1T t m, Control.Monad.IO.Class.MonadIO (Nix.Utils.Fix1.Fix1T t m), Control.Monad.Fail.MonadFail (Nix.Utils.Fix1.Fix1T t m), Nix.Render.MonadFile m) => Nix.Render.MonadFile (Nix.Utils.Fix1.Fix1T t m)
+ Nix.Render.Frame: dumbRenderValue :: forall e t f m ann. (MonadReader e m, Has e Options, MonadFile m, MonadCitedThunks t f m) => NValue t f m -> m (Doc ann)
+ Nix.Scope: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Nix.Scope.Scope a)
+ Nix.Scope: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Nix.Scope.Scope a)
+ Nix.Scope: instance GHC.Base.Monoid (Nix.Scope.Scope a)
+ Nix.Scope: instance GHC.Base.Semigroup (Nix.Scope.Scope a)
+ Nix.Scope: instance GHC.Classes.Ord a => GHC.Classes.Ord (Nix.Scope.Scope a)
+ Nix.Scope: instance GHC.Generics.Generic (Nix.Scope.Scope a)
+ Nix.Scope: instance GHC.Read.Read a => GHC.Read.Read (Nix.Scope.Scope a)
+ Nix.Standard: instance (Control.Monad.Fix.MonadFix m, Nix.Render.MonadFile m, Control.Monad.Catch.MonadCatch m, Nix.Effects.MonadEnv m, Nix.Effects.MonadPaths m, Nix.Effects.MonadExec m, Nix.Effects.MonadHttp m, Nix.Effects.MonadInstantiate m, Nix.Effects.MonadIntrospect m, GHC.Base.MonadPlus m, Nix.Effects.MonadPutStr m, Nix.Effects.MonadStore m, Control.Monad.Ref.MonadAtomicRef m, Data.Typeable.Internal.Typeable m, Nix.Scope.Scoped (Nix.Standard.StdValue m) m, Control.Monad.Reader.Class.MonadReader (Nix.Context.Context m (Nix.Standard.StdValue m)) m, Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap Nix.Utils.Path Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) m, Nix.Value.MonadDataErrorContext (Nix.Standard.StdThunk m) (Nix.Standard.StdCited m) m, Nix.Thunk.MonadThunk (Nix.Standard.StdThunk m) m (Nix.Standard.StdValue m), Nix.Value.Monad.MonadValue (Nix.Standard.StdValue m) m) => Nix.Effects.MonadEffects (Nix.Standard.StdThunk m) (Nix.Standard.StdCited m) m
+ Nix.Standard: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.HashMap.Internal.HashMap Nix.Utils.Path Nix.Expr.Types.Annotated.NExprLoc, Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Text.Internal.Text) (Nix.Standard.StandardTF r m)
+ Nix.Standard: instance Nix.Thunk.MonadThunkId m => Nix.Thunk.MonadThunkId (Nix.Standard.StandardT m)
+ Nix.Standard: type CitedStdThunk m = Cited (StdThunk m) (StdCited m) m (NThunkF m (StdValue m))
+ Nix.String: mkNixString :: Text -> HashSet StringContext -> NixString
+ Nix.String: mkNixStringWithSingletonContext :: VarName -> StringContext -> NixString
+ Nix.String: mkNixStringWithoutContext :: Text -> NixString
+ Nix.TH: extQOnFreeVars :: (Typeable b, Typeable loc) => (Set VarName -> loc -> Maybe q) -> NExpr -> b -> Maybe q
+ Nix.TH: instance Nix.TH.ToExpr GHC.Num.Integer.Integer
+ Nix.TH: parseExpr :: MonadFail m => Text -> m NExpr
+ Nix.Type.Infer: instance GHC.Base.Monoid Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance GHC.Base.Semigroup Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance GHC.Classes.Eq Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance GHC.Classes.Ord Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance GHC.Enum.Enum Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance GHC.Num.Num Nix.Type.Infer.InferState
+ Nix.Type.Infer: instance Nix.Type.Infer.MonadInfer m => Nix.Convert.FromValue (Nix.Expr.Types.AttrSet (Nix.Type.Infer.Judgment s), Nix.Expr.Types.PositionSet) (Nix.Type.Infer.InferT s m) (Nix.Type.Infer.Judgment s)
+ Nix.Type.Infer: instance Nix.Type.Infer.MonadInfer m => Nix.Convert.ToValue (Nix.Expr.Types.AttrSet (Nix.Type.Infer.Judgment s), Nix.Expr.Types.PositionSet) (Nix.Type.Infer.InferT s m) (Nix.Type.Infer.Judgment s)
+ Nix.Utils: (</>) :: Path -> Path -> Path
+ Nix.Utils: Path :: FilePath -> Path
+ Nix.Utils: addExtension :: Path -> String -> Path
+ Nix.Utils: dropExtensions :: Path -> Path
+ Nix.Utils: infixr 5 </>
+ Nix.Utils: instance Codec.Serialise.Class.Serialise Nix.Utils.Path
+ Nix.Utils: instance Control.DeepSeq.NFData Nix.Utils.Path
+ Nix.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Nix.Utils.Path
+ Nix.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Nix.Utils.Path
+ Nix.Utils: instance Data.Binary.Class.Binary Nix.Utils.Path
+ Nix.Utils: instance Data.Data.Data Nix.Utils.Path
+ Nix.Utils: instance Data.Hashable.Class.Hashable Nix.Utils.Path
+ Nix.Utils: instance Data.String.IsString Nix.Utils.Path
+ Nix.Utils: instance GHC.Base.Monoid Nix.Utils.Path
+ Nix.Utils: instance GHC.Base.Semigroup Nix.Utils.Path
+ Nix.Utils: instance GHC.Classes.Eq Nix.Utils.Path
+ Nix.Utils: instance GHC.Classes.Ord Nix.Utils.Path
+ Nix.Utils: instance GHC.Generics.Generic Nix.Utils.Path
+ Nix.Utils: instance GHC.Read.Read Nix.Utils.Path
+ Nix.Utils: instance GHC.Show.Show Nix.Utils.Path
+ Nix.Utils: instance Relude.String.Conversion.ToText Nix.Utils.Path
+ Nix.Utils: isAbsolute :: Path -> Bool
+ Nix.Utils: joinPath :: [Path] -> Path
+ Nix.Utils: newtype Path
+ Nix.Utils: pass :: Applicative f => f ()
+ Nix.Utils: readFile :: Path -> IO Text
+ Nix.Utils: replaceExtension :: Path -> String -> Path
+ Nix.Utils: splitDirectories :: Path -> [Path]
+ Nix.Utils: takeBaseName :: Path -> String
+ Nix.Utils: takeDirectory :: Path -> Path
+ Nix.Utils: takeExtension :: Path -> String
+ Nix.Utils: takeExtensions :: Path -> String
+ Nix.Utils: takeFileName :: Path -> Path
+ Nix.Utils: traverseM :: (Applicative m, Applicative f, Traversable t) => (a -> m (f b)) -> t a -> m (f (t b))
+ Nix.Utils: type KeyMap = HashMap Text
+ Nix.Utils: whenJust :: Monoid b => (a -> b) -> Maybe a -> b
+ Nix.Utils: whenText :: a -> (Text -> a) -> Text -> a
+ Nix.Value: instance GHC.Base.Monoid Nix.Value.TStringContext
+ Nix.Value: instance GHC.Base.Semigroup Nix.Value.TStringContext
+ Nix.Value: pattern NVPath :: forall {w :: Type -> Type} {t} {m :: Type -> Type} {a}. Comonad w => Path -> Free (NValue' t w m) a
+ Nix.Value: pattern NVSet :: forall {w :: Type -> Type} {t} {m :: Type -> Type} {a}. Comonad w => PositionSet -> AttrSet (Free (NValue' t w m) a) -> Free (NValue' t w m) a
+ Nix.Value: pattern NVBuiltin :: forall {w :: Type -> Type} {t} {m} {a}. Comonad w => VarName -> (NValue t w m -> m (Free (NValue' t w m) a)) -> Free (NValue' t w m) a
+ Prelude: (!!?) :: [a] -> Int -> Maybe a
+ Prelude: ($!!) :: NFData a => (a -> b) -> a -> b
+ Prelude: ($!) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
+ Prelude: ($) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
+ Prelude: ($<) :: Contravariant f => f b -> b -> f a
+ Prelude: ($>) :: Functor f => f a -> b -> f b
+ Prelude: (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
+ Prelude: (&&) :: Bool -> Bool -> Bool
+ Prelude: (&&^) :: Monad m => m Bool -> m Bool -> m Bool
+ Prelude: (&) :: a -> (a -> b) -> b
+ Prelude: (*) :: Num a => a -> a -> a
+ Prelude: (**) :: Floating a => a -> a -> a
+ Prelude: (*>) :: Applicative f => f a -> f b -> f b
+ Prelude: (+) :: Num a => a -> a -> a
+ Prelude: (++) :: [a] -> [a] -> [a]
+ Prelude: (-) :: Num a => a -> a -> a
+ Prelude: (.) :: (b -> c) -> (a -> b) -> a -> c
+ Prelude: (/) :: Fractional a => a -> a -> a
+ Prelude: (/=) :: Eq a => a -> a -> Bool
+ Prelude: (:|) :: a -> [a] -> NonEmpty a
+ Prelude: (<$!>) :: Monad m => (a -> b) -> m a -> m b
+ Prelude: (<$) :: Functor f => a -> f b -> f a
+ Prelude: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ Prelude: (<&>) :: Functor f => f a -> (a -> b) -> f b
+ Prelude: (<) :: Ord a => a -> a -> Bool
+ Prelude: (<*) :: Applicative f => f a -> f b -> f a
+ Prelude: (<**>) :: Applicative f => f a -> f (a -> b) -> f b
+ Prelude: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
+ Prelude: (<<$>>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
+ Prelude: (<<<) :: forall {k} cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
+ Prelude: (<=) :: Ord a => a -> a -> Bool
+ Prelude: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Prelude: (<>) :: Semigroup a => a -> a -> a
+ Prelude: (<|>) :: Alternative f => f a -> f a -> f a
+ Prelude: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Prelude: (==) :: Eq a => a -> a -> Bool
+ Prelude: (>$$<) :: Contravariant f => f b -> (a -> b) -> f a
+ Prelude: (>$) :: Contravariant f => b -> f b -> f a
+ Prelude: (>$<) :: Contravariant f => (a -> b) -> f b -> f a
+ Prelude: (>) :: Ord a => a -> a -> Bool
+ Prelude: (>=) :: Ord a => a -> a -> Bool
+ Prelude: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
+ Prelude: (>>) :: Monad m => m a -> m b -> m b
+ Prelude: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Prelude: (>>>) :: forall {k} cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
+ Prelude: (?:) :: Maybe a -> a -> a
+ Prelude: (??) :: Functor f => f (a -> b) -> a -> f b
+ Prelude: (^) :: (Num a, Integral b) => a -> b -> a
+ Prelude: (^^) :: (Fractional a, Integral b) => a -> b -> a
+ Prelude: (||) :: Bool -> Bool -> Bool
+ Prelude: (||^) :: Monad m => m Bool -> m Bool -> m Bool
+ Prelude: -- | Type of a single element of the structure.
+ Prelude: All :: Bool -> All
+ Prelude: Alt :: f a -> Alt (f :: k -> Type) (a :: k)
+ Prelude: Any :: Bool -> Any
+ Prelude: Ap :: f a -> Ap (f :: k -> Type) (a :: k)
+ Prelude: AppendMode :: IOMode
+ Prelude: BlockBuffering :: Maybe Int -> BufferMode
+ Prelude: Bug :: SomeException -> CallStack -> Bug
+ Prelude: Comparison :: (a -> a -> Ordering) -> Comparison a
+ Prelude: Compose :: f (g a) -> Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1)
+ Prelude: Const :: a -> Const a (b :: k)
+ Prelude: D# :: Double# -> Double
+ Prelude: Down :: a -> Down a
+ Prelude: Dual :: a -> Dual a
+ Prelude: EQ :: Ordering
+ Prelude: Endo :: (a -> a) -> Endo a
+ Prelude: Equivalence :: (a -> a -> Bool) -> Equivalence a
+ Prelude: ExceptT :: m (Either e a) -> ExceptT e (m :: Type -> Type) a
+ Prelude: F# :: Float# -> Float
+ Prelude: False :: Bool
+ Prelude: First :: Maybe a -> First a
+ Prelude: GT :: Ordering
+ Prelude: Identity :: a -> Identity a
+ Prelude: Just :: a -> Maybe a
+ Prelude: LT :: Ordering
+ Prelude: Last :: Maybe a -> Last a
+ Prelude: Left :: a -> Either a b
+ Prelude: LineBuffering :: BufferMode
+ Prelude: MaybeT :: m (Maybe a) -> MaybeT (m :: Type -> Type) a
+ Prelude: NoBuffering :: BufferMode
+ Prelude: Nothing :: Maybe a
+ Prelude: Op :: (b -> a) -> Op a b
+ Prelude: Option :: Maybe a -> Option a
+ Prelude: Predicate :: (a -> Bool) -> Predicate a
+ Prelude: Product :: a -> Product a
+ Prelude: Proxy :: Proxy (t :: k)
+ Prelude: ReadMode :: IOMode
+ Prelude: ReadWriteMode :: IOMode
+ Prelude: ReaderT :: (r -> m a) -> ReaderT r (m :: Type -> Type) a
+ Prelude: Right :: b -> Either a b
+ Prelude: SomeException :: e -> SomeException
+ Prelude: SomeNat :: Proxy n -> SomeNat
+ Prelude: StateT :: (s -> m (a, s)) -> StateT s (m :: Type -> Type) a
+ Prelude: Sum :: a -> Sum a
+ Prelude: True :: Bool
+ Prelude: Undefined :: Undefined
+ Prelude: WriteMode :: IOMode
+ Prelude: ZipList :: [a] -> ZipList a
+ Prelude: [appEndo] :: Endo a -> a -> a
+ Prelude: [getAll] :: All -> Bool
+ Prelude: [getAlt] :: Alt (f :: k -> Type) (a :: k) -> f a
+ Prelude: [getAny] :: Any -> Bool
+ Prelude: [getAp] :: Ap (f :: k -> Type) (a :: k) -> f a
+ Prelude: [getComparison] :: Comparison a -> a -> a -> Ordering
+ Prelude: [getCompose] :: Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1) -> f (g a)
+ Prelude: [getConst] :: Const a (b :: k) -> a
+ Prelude: [getDown] :: Down a -> a
+ Prelude: [getDual] :: Dual a -> a
+ Prelude: [getEquivalence] :: Equivalence a -> a -> a -> Bool
+ Prelude: [getFirst] :: First a -> Maybe a
+ Prelude: [getLast] :: Last a -> Maybe a
+ Prelude: [getOp] :: Op a b -> b -> a
+ Prelude: [getOption] :: Option a -> Maybe a
+ Prelude: [getPredicate] :: Predicate a -> a -> Bool
+ Prelude: [getProduct] :: Product a -> a
+ Prelude: [getSum] :: Sum a -> a
+ Prelude: [getZipList] :: ZipList a -> [a]
+ Prelude: [runIdentity] :: Identity a -> a
+ Prelude: [runMaybeT] :: MaybeT (m :: Type -> Type) a -> m (Maybe a)
+ Prelude: [runReaderT] :: ReaderT r (m :: Type -> Type) a -> r -> m a
+ Prelude: [runStateT] :: StateT s (m :: Type -> Type) a -> s -> m (a, s)
+ Prelude: abs :: Num a => a -> a
+ Prelude: absurd :: Void -> a
+ Prelude: acos :: Floating a => a -> a
+ Prelude: acosh :: Floating a => a -> a
+ Prelude: all :: Foldable t => (a -> Bool) -> t a -> Bool
+ Prelude: allM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
+ Prelude: and :: Foldable t => t Bool -> Bool
+ Prelude: andM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
+ Prelude: any :: Foldable t => (a -> Bool) -> t a -> Bool
+ Prelude: anyM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
+ Prelude: appendFile :: MonadIO m => FilePath -> String -> m ()
+ Prelude: appendFileBS :: MonadIO m => FilePath -> ByteString -> m ()
+ Prelude: appendFileLBS :: MonadIO m => FilePath -> LByteString -> m ()
+ Prelude: appendFileLText :: MonadIO m => FilePath -> LText -> m ()
+ Prelude: appendFileText :: MonadIO m => FilePath -> Text -> m ()
+ Prelude: appliedTo :: Applicative f => f a -> f (a -> b) -> f b
+ Prelude: asTypeOf :: a -> a -> a
+ Prelude: asin :: Floating a => a -> a
+ Prelude: asinh :: Floating a => a -> a
+ Prelude: ask :: MonadReader r m => m r
+ Prelude: asks :: MonadReader r m => (r -> a) -> m a
+ Prelude: asum :: (Foldable t, Alternative f) => t (f a) -> f a
+ Prelude: asumMap :: forall b m f a. (Foldable f, Alternative m) => (a -> m b) -> f a -> m b
+ Prelude: atan :: Floating a => a -> a
+ Prelude: atan2 :: RealFloat a => a -> a -> a
+ Prelude: atanh :: Floating a => a -> a
+ Prelude: atomicModifyIORef :: MonadIO m => IORef a -> (a -> (a, b)) -> m b
+ Prelude: atomicModifyIORef' :: MonadIO m => IORef a -> (a -> (a, b)) -> m b
+ Prelude: atomicModifyIORef'_ :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Prelude: atomicModifyIORef_ :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Prelude: atomicWriteIORef :: MonadIO m => IORef a -> a -> m ()
+ Prelude: atomically :: MonadIO m => STM a -> m a
+ Prelude: biList :: Bifoldable t => t a a -> [a]
+ Prelude: biall :: Bifoldable t => (a -> Bool) -> (b -> Bool) -> t a b -> Bool
+ Prelude: biand :: Bifoldable t => t Bool Bool -> Bool
+ Prelude: biany :: Bifoldable t => (a -> Bool) -> (b -> Bool) -> t a b -> Bool
+ Prelude: biasum :: (Bifoldable t, Alternative f) => t (f a) (f a) -> f a
+ Prelude: bielem :: (Bifoldable t, Eq a) => a -> t a a -> Bool
+ Prelude: bifind :: Bifoldable t => (a -> Bool) -> t a a -> Maybe a
+ Prelude: bifold :: (Bifoldable p, Monoid m) => p m m -> m
+ Prelude: bifoldMap :: (Bifoldable p, Monoid m) => (a -> m) -> (b -> m) -> p a b -> m
+ Prelude: bifoldMapDefault :: (Bitraversable t, Monoid m) => (a -> m) -> (b -> m) -> t a b -> m
+ Prelude: bifoldl :: Bifoldable p => (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
+ Prelude: bifoldl' :: Bifoldable t => (a -> b -> a) -> (a -> c -> a) -> a -> t b c -> a
+ Prelude: bifoldlM :: (Bifoldable t, Monad m) => (a -> b -> m a) -> (a -> c -> m a) -> a -> t b c -> m a
+ Prelude: bifoldr :: Bifoldable p => (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c
+ Prelude: bifoldr' :: Bifoldable t => (a -> c -> c) -> (b -> c -> c) -> c -> t a b -> c
+ Prelude: bifoldrM :: (Bifoldable t, Monad m) => (a -> c -> m c) -> (b -> c -> m c) -> c -> t a b -> m c
+ Prelude: bifor :: (Bitraversable t, Applicative f) => t a b -> (a -> f c) -> (b -> f d) -> f (t c d)
+ Prelude: bifor_ :: (Bifoldable t, Applicative f) => t a b -> (a -> f c) -> (b -> f d) -> f ()
+ Prelude: bilength :: Bifoldable t => t a b -> Int
+ Prelude: bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
+ Prelude: bimapDefault :: Bitraversable t => (a -> b) -> (c -> d) -> t a c -> t b d
+ Prelude: binull :: Bifoldable t => t a b -> Bool
+ Prelude: bior :: Bifoldable t => t Bool Bool -> Bool
+ Prelude: bisequence :: (Bitraversable t, Applicative f) => t (f a) (f b) -> f (t a b)
+ Prelude: bisequence_ :: (Bifoldable t, Applicative f) => t (f a) (f b) -> f ()
+ Prelude: bitraverse :: (Bitraversable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f (t c d)
+ Prelude: bitraverse_ :: (Bifoldable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f ()
+ Prelude: bool :: a -> a -> Bool -> a
+ Prelude: boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
+ Prelude: boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
+ Prelude: break :: (a -> Bool) -> [a] -> ([a], [a])
+ Prelude: bug :: (HasCallStack, Exception e) => e -> a
+ Prelude: byteSwap16 :: Word16 -> Word16
+ Prelude: byteSwap32 :: Word32 -> Word32
+ Prelude: byteSwap64 :: Word64 -> Word64
+ Prelude: callStack :: HasCallStack => CallStack
+ Prelude: catMaybes :: [Maybe a] -> [a]
+ Prelude: catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a
+ Prelude: ceiling :: (RealFrac a, Integral b) => a -> b
+ Prelude: chainedTo :: Monad m => (a -> m b) -> m a -> m b
+ Prelude: chr :: Int -> Char
+ Prelude: class Applicative f => Alternative (f :: Type -> Type)
+ Prelude: class Functor f => Applicative (f :: Type -> Type)
+ Prelude: class Bifoldable (p :: Type -> Type -> Type)
+ Prelude: class Bifunctor (p :: Type -> Type -> Type)
+ Prelude: class (Bifunctor t, Bifoldable t) => Bitraversable (t :: Type -> Type -> Type)
+ Prelude: class Bounded a
+ Prelude: class a ~R# b => Coercible (a :: k) (b :: k)
+ Prelude: class Contravariant (f :: Type -> Type)
+ Prelude: class ConvertUtf8 a b
+ Prelude: class Enum a
+ Prelude: class Eq a
+ Prelude: class (Typeable e, Show e) => Exception e
+ Prelude: class Fractional a => Floating a
+ Prelude: class Foldable (t :: Type -> Type)
+ Prelude: class Num a => Fractional a
+ Prelude: class Functor (f :: Type -> Type)
+ Prelude: class Generic a
+ Prelude: class Hashable a
+ Prelude: class (Real a, Enum a) => Integral a
+ Prelude: class IsLabel (x :: Symbol) a
+ Prelude: class IsList l
+ Prelude: class IsString a
+ Prelude: class KnownNat (n :: Nat)
+ Prelude: class LazyStrict l s | l -> s, s -> l
+ Prelude: class Applicative m => Monad (m :: Type -> Type)
+ Prelude: class Monad m => MonadFail (m :: Type -> Type)
+ Prelude: class Monad m => MonadIO (m :: Type -> Type)
+ Prelude: class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type)
+ Prelude: class Monad m => MonadReader r (m :: Type -> Type) | m -> r
+ Prelude: class Monad m => MonadState s (m :: Type -> Type) | m -> s
+ Prelude: class MonadTrans (t :: Type -> Type -> Type -> Type)
+ Prelude: class Semigroup a => Monoid a
+ Prelude: class NFData a
+ Prelude: class Num a
+ Prelude: class One x where {
+ Prelude: class Eq a => Ord a
+ Prelude: class Read a
+ Prelude: class (Num a, Ord a) => Real a
+ Prelude: class (RealFrac a, Floating a) => RealFloat a
+ Prelude: class (Real a, Fractional a) => RealFrac a
+ Prelude: class Semigroup a
+ Prelude: class Show a
+ Prelude: class ToLText a
+ Prelude: class ToString a
+ Prelude: class ToText a
+ Prelude: class (Functor t, Foldable t) => Traversable (t :: Type -> Type)
+ Prelude: class Typeable (a :: k)
+ Prelude: coerce :: forall {k :: RuntimeRep} (a :: TYPE k) (b :: TYPE k). Coercible a b => a -> b
+ Prelude: compare :: Ord a => a -> a -> Ordering
+ Prelude: comparing :: Ord a => (b -> a) -> b -> b -> Ordering
+ Prelude: comparisonEquivalence :: Comparison a -> Equivalence a
+ Prelude: concat :: Foldable t => t [a] -> [a]
+ Prelude: concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
+ Prelude: const :: a -> b -> a
+ Prelude: contramap :: Contravariant f => (a' -> a) -> f a -> f a'
+ Prelude: cos :: Floating a => a -> a
+ Prelude: cosh :: Floating a => a -> a
+ Prelude: currentCallStack :: IO [String]
+ Prelude: curry :: ((a, b) -> c) -> a -> b -> c
+ Prelude: cycle :: [a] -> [a]
+ Prelude: cycle1 :: Semigroup m => m -> m
+ Prelude: data Bool
+ Prelude: data BufferMode
+ Prelude: data Bug
+ Prelude: data ByteString
+ Prelude: data CallStack
+ Prelude: data Char
+ Prelude: data Constraint
+ Prelude: data Double
+ Prelude: data Either a b
+ Prelude: data Float
+ Prelude: data Handle
+ Prelude: data HashMap k v
+ Prelude: data HashSet a
+ Prelude: data IO a
+ Prelude: data IOMode
+ Prelude: data IORef a
+ Prelude: data IdentityT (f :: k -> Type) (a :: k)
+ Prelude: data Int
+ Prelude: data Int16
+ Prelude: data Int32
+ Prelude: data Int64
+ Prelude: data Int8
+ Prelude: data IntMap a
+ Prelude: data IntSet
+ Prelude: data Integer
+ Prelude: data MVar a
+ Prelude: data Map k a
+ Prelude: data Maybe a
+ Prelude: data Nat
+ Prelude: data Natural
+ Prelude: data NonEmpty a
+ Prelude: data Ordering
+ Prelude: data Proxy (t :: k)
+ Prelude: data Ratio a
+ Prelude: data STM a
+ Prelude: data Seq a
+ Prelude: data Set a
+ Prelude: data ShortByteString
+ Prelude: data SomeException
+ Prelude: data SomeNat
+ Prelude: data TMVar a
+ Prelude: data TVar a
+ Prelude: data Text
+ Prelude: data Undefined
+ Prelude: data UnicodeException
+ Prelude: data Void
+ Prelude: data Word
+ Prelude: data Word16
+ Prelude: data Word32
+ Prelude: data Word64
+ Prelude: data Word8
+ Prelude: data WrappedMonoid m
+ Prelude: decodeFloat :: RealFloat a => a -> (Integer, Int)
+ Prelude: decodeUtf8 :: ConvertUtf8 a b => b -> a
+ Prelude: decodeUtf8' :: ByteString -> Either UnicodeException Text
+ Prelude: decodeUtf8Strict :: ConvertUtf8 a b => b -> Either UnicodeException a
+ Prelude: decodeUtf8With :: OnDecodeError -> ByteString -> Text
+ Prelude: deepseq :: NFData a => a -> b -> b
+ Prelude: defaultComparison :: Ord a => Comparison a
+ Prelude: defaultEquivalence :: Eq a => Equivalence a
+ Prelude: denominator :: Ratio a -> a
+ Prelude: die :: MonadIO m => String -> m a
+ Prelude: displayException :: Exception e => e -> String
+ Prelude: div :: Integral a => a -> a -> a
+ Prelude: divMod :: Integral a => a -> a -> (a, a)
+ Prelude: drop :: Int -> [a] -> [a]
+ Prelude: dropWhile :: (a -> Bool) -> [a] -> [a]
+ Prelude: either :: (a -> c) -> (b -> c) -> Either a b -> c
+ Prelude: elem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
+ Prelude: empty :: Alternative f => f a
+ Prelude: encodeFloat :: RealFloat a => Integer -> Int -> a
+ Prelude: encodeUtf8 :: ConvertUtf8 a b => a -> b
+ Prelude: enumFrom :: Enum a => a -> [a]
+ Prelude: enumFromThen :: Enum a => a -> a -> [a]
+ Prelude: enumFromThenTo :: Enum a => a -> a -> a -> [a]
+ Prelude: enumFromTo :: Enum a => a -> a -> [a]
+ Prelude: error :: forall (r :: RuntimeRep) (a :: TYPE r) t. (HasCallStack, IsText t) => t -> a
+ Prelude: etaReaderT :: forall r (m :: Type -> Type) a. ReaderT r m a -> ReaderT r m a
+ Prelude: evalState :: State s a -> s -> a
+ Prelude: evalStateT :: Monad m => StateT s m a -> s -> m a
+ Prelude: evaluateNF :: (NFData a, MonadIO m) => a -> m a
+ Prelude: evaluateNF_ :: (NFData a, MonadIO m) => a -> m ()
+ Prelude: evaluateWHNF :: MonadIO m => a -> m a
+ Prelude: evaluateWHNF_ :: MonadIO m => a -> m ()
+ Prelude: evaluatingState :: s -> State s a -> a
+ Prelude: evaluatingStateT :: Functor f => s -> StateT s f a -> f a
+ Prelude: even :: Integral a => a -> Bool
+ Prelude: exceptToMaybeT :: forall (m :: Type -> Type) e a. Functor m => ExceptT e m a -> MaybeT m a
+ Prelude: execState :: State s a -> s -> s
+ Prelude: execStateT :: Monad m => StateT s m a -> s -> m s
+ Prelude: executingState :: s -> State s a -> s
+ Prelude: executingStateT :: Functor f => s -> StateT s f a -> f s
+ Prelude: exitFailure :: MonadIO m => m a
+ Prelude: exitSuccess :: MonadIO m => m a
+ Prelude: exitWith :: MonadIO m => ExitCode -> m a
+ Prelude: exp :: Floating a => a -> a
+ Prelude: fail :: MonadFail m => String -> m a
+ Prelude: filter :: (a -> Bool) -> [a] -> [a]
+ Prelude: filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
+ Prelude: find :: Foldable t => (a -> Bool) -> t a -> Maybe a
+ Prelude: first :: Bifunctor p => (a -> b) -> p a c -> p b c
+ Prelude: fix :: (a -> a) -> a
+ Prelude: flap :: Functor f => f (a -> b) -> a -> f b
+ Prelude: flip :: (a -> b -> c) -> b -> a -> c
+ Prelude: flipfoldl' :: Foldable f => (a -> b -> b) -> b -> f a -> b
+ Prelude: floatDigits :: RealFloat a => a -> Int
+ Prelude: floatRadix :: RealFloat a => a -> Integer
+ Prelude: floatRange :: RealFloat a => a -> (Int, Int)
+ Prelude: floor :: (RealFrac a, Integral b) => a -> b
+ Prelude: fmap :: Functor f => (a -> b) -> f a -> f b
+ Prelude: fold :: (Foldable t, Monoid m) => t m -> m
+ Prelude: foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ Prelude: foldMap' :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ Prelude: foldMapA :: (Semigroup b, Monoid b, Applicative m, Foldable f) => (a -> m b) -> f a -> m b
+ Prelude: foldMapM :: (Monoid b, Monad m, Foldable f) => (a -> m b) -> f a -> m b
+ Prelude: foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ Prelude: foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
+ Prelude: foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
+ Prelude: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
+ Prelude: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
+ Prelude: for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
+ Prelude: forever :: Applicative f => f a -> f b
+ Prelude: fromEnum :: Enum a => a -> Int
+ Prelude: fromException :: Exception e => SomeException -> Maybe e
+ Prelude: fromInteger :: Num a => Integer -> a
+ Prelude: fromIntegral :: (Integral a, Num b) => a -> b
+ Prelude: fromLabel :: IsLabel x a => a
+ Prelude: fromLazy :: LazyStrict l s => l -> s
+ Prelude: fromLeft :: a -> Either a b -> a
+ Prelude: fromList :: IsList l => [Item l] -> l
+ Prelude: fromListN :: IsList l => Int -> [Item l] -> l
+ Prelude: fromMaybe :: a -> Maybe a -> a
+ Prelude: fromRational :: Fractional a => Rational -> a
+ Prelude: fromRight :: b -> Either a b -> b
+ Prelude: fromShort :: ShortByteString -> ByteString
+ Prelude: fromStrict :: LazyStrict l s => s -> l
+ Prelude: fromString :: IsString a => String -> a
+ Prelude: fst :: (a, b) -> a
+ Prelude: gcd :: Integral a => a -> a -> a
+ Prelude: genericDrop :: Integral i => i -> [a] -> [a]
+ Prelude: genericLength :: Num i => [a] -> i
+ Prelude: genericReplicate :: Integral i => i -> a -> [a]
+ Prelude: genericSplitAt :: Integral i => i -> [a] -> ([a], [a])
+ Prelude: genericTake :: Integral i => i -> [a] -> [a]
+ Prelude: get :: MonadState s m => m s
+ Prelude: getArgs :: MonadIO m => m [String]
+ Prelude: getCallStack :: CallStack -> [([Char], SrcLoc)]
+ Prelude: getLine :: MonadIO m => m Text
+ Prelude: getStackTrace :: IO (Maybe [Location])
+ Prelude: gets :: MonadState s m => (s -> a) -> m a
+ Prelude: group :: Eq a => [a] -> [[a]]
+ Prelude: guard :: Alternative f => Bool -> f ()
+ Prelude: guardM :: MonadPlus m => m Bool -> m ()
+ Prelude: guarded :: Alternative f => (a -> Bool) -> a -> f a
+ Prelude: hFlush :: MonadIO m => Handle -> m ()
+ Prelude: hGetBuffering :: MonadIO m => Handle -> m BufferMode
+ Prelude: hIsEOF :: MonadIO m => Handle -> m Bool
+ Prelude: hSetBuffering :: MonadIO m => Handle -> BufferMode -> m ()
+ Prelude: hashNub :: (Eq a, Hashable a) => [a] -> [a]
+ Prelude: hashWithSalt :: Hashable a => Int -> a -> Int
+ Prelude: head :: IsNonEmpty f a a "head" => f a -> a
+ Prelude: hoistEither :: forall (m :: Type -> Type) e a. Applicative m => Either e a -> ExceptT e m a
+ Prelude: hoistMaybe :: forall (m :: Type -> Type) a. Applicative m => Maybe a -> MaybeT m a
+ Prelude: id :: a -> a
+ Prelude: identity :: a -> a
+ Prelude: ifM :: Monad m => m Bool -> m a -> m a -> m a
+ Prelude: infinitely :: Applicative f => f a -> f Void
+ Prelude: infix 4 >=
+ Prelude: infix 9 !!?
+ Prelude: infixl 0 `on`
+ Prelude: infixl 1 <&>
+ Prelude: infixl 3 <|>
+ Prelude: infixl 4 <<$>>
+ Prelude: infixl 6 `xor`
+ Prelude: infixl 7 *
+ Prelude: infixr 0 ?:
+ Prelude: infixr 1 =<<
+ Prelude: infixr 2 ||
+ Prelude: infixr 3 &&
+ Prelude: infixr 5 :|
+ Prelude: infixr 6 <>
+ Prelude: infixr 8 ^
+ Prelude: infixr 9 `Compose`
+ Prelude: init :: IsNonEmpty f a [a] "init" => f a -> [a]
+ Prelude: inits :: [a] -> [[a]]
+ Prelude: intNub :: [Int] -> [Int]
+ Prelude: intNubOn :: (a -> Int) -> [a] -> [a]
+ Prelude: integerToBounded :: (Integral a, Bounded a) => Integer -> Maybe a
+ Prelude: integerToNatural :: Integer -> Maybe Natural
+ Prelude: intercalate :: [a] -> [[a]] -> [a]
+ Prelude: intersperse :: a -> [a] -> [a]
+ Prelude: inverseMap :: (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
+ Prelude: isDenormalized :: RealFloat a => a -> Bool
+ Prelude: isEmptyTMVar :: TMVar a -> STM Bool
+ Prelude: isIEEE :: RealFloat a => a -> Bool
+ Prelude: isInfinite :: RealFloat a => a -> Bool
+ Prelude: isJust :: Maybe a -> Bool
+ Prelude: isLeft :: Either a b -> Bool
+ Prelude: isNaN :: RealFloat a => a -> Bool
+ Prelude: isNegativeZero :: RealFloat a => a -> Bool
+ Prelude: isNothing :: Maybe a -> Bool
+ Prelude: isPrefixOf :: Eq a => [a] -> [a] -> Bool
+ Prelude: isRight :: Either a b -> Bool
+ Prelude: iterate :: (a -> a) -> a -> [a]
+ Prelude: join :: Monad m => m (m a) -> m a
+ Prelude: last :: IsNonEmpty f a a "last" => f a -> a
+ Prelude: lcm :: Integral a => a -> a -> a
+ Prelude: leftToMaybe :: Either l r -> Maybe l
+ Prelude: lefts :: [Either a b] -> [a]
+ Prelude: length :: Foldable t => t a -> Int
+ Prelude: lenientDecode :: OnDecodeError
+ Prelude: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Prelude: liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
+ Prelude: liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
+ Prelude: liftIO :: MonadIO m => IO a -> m a
+ Prelude: lines :: IsText t "lines" => t -> [t]
+ Prelude: listToMaybe :: [a] -> Maybe a
+ Prelude: local :: MonadReader r m => (r -> r) -> m a -> m a
+ Prelude: logBase :: Floating a => a -> a -> a
+ Prelude: lookupEnv :: MonadIO m => String -> m (Maybe String)
+ Prelude: many :: Alternative f => f a -> f [a]
+ Prelude: map :: (a -> b) -> [a] -> [b]
+ Prelude: mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Prelude: mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Prelude: mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Prelude: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Prelude: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Prelude: mapMaybe :: (a -> Maybe b) -> [a] -> [b]
+ Prelude: mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
+ Prelude: mappend :: Monoid a => a -> a -> a
+ Prelude: max :: Ord a => a -> a -> a
+ Prelude: maxBound :: Bounded a => a
+ Prelude: maxInt :: Int
+ Prelude: maybe :: b -> (a -> b) -> Maybe a -> b
+ Prelude: maybeAt :: Int -> [a] -> Maybe a
+ Prelude: maybeToExceptT :: forall (m :: Type -> Type) e a. Functor m => e -> MaybeT m a -> ExceptT e m a
+ Prelude: maybeToLeft :: r -> Maybe l -> Either l r
+ Prelude: maybeToList :: Maybe a -> [a]
+ Prelude: maybeToMonoid :: Monoid m => Maybe m -> m
+ Prelude: maybeToRight :: l -> Maybe r -> Either l r
+ Prelude: mconcat :: Monoid a => [a] -> a
+ Prelude: mempty :: Monoid a => a
+ Prelude: memptyIfFalse :: Monoid m => Bool -> m -> m
+ Prelude: memptyIfTrue :: Monoid m => Bool -> m -> m
+ Prelude: mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+ Prelude: min :: Ord a => a -> a -> a
+ Prelude: minBound :: Bounded a => a
+ Prelude: minInt :: Int
+ Prelude: mkWeakTMVar :: TMVar a -> IO () -> IO (Weak (TMVar a))
+ Prelude: mod :: Integral a => a -> a -> a
+ Prelude: modify :: MonadState s m => (s -> s) -> m ()
+ Prelude: modify' :: MonadState s m => (s -> s) -> m ()
+ Prelude: modifyIORef :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Prelude: modifyIORef' :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Prelude: modifyTVar' :: TVar a -> (a -> a) -> STM ()
+ Prelude: mplus :: MonadPlus m => m a -> m a -> m a
+ Prelude: mtimesDefault :: (Integral b, Monoid a) => b -> a -> a
+ Prelude: mzero :: MonadPlus m => m a
+ Prelude: natVal :: forall (n :: Nat) proxy. KnownNat n => proxy n -> Natural
+ Prelude: negate :: Num a => a -> a
+ Prelude: newEmptyMVar :: MonadIO m => m (MVar a)
+ Prelude: newEmptyTMVar :: STM (TMVar a)
+ Prelude: newEmptyTMVarIO :: MonadIO m => m (TMVar a)
+ Prelude: newIORef :: MonadIO m => a -> m (IORef a)
+ Prelude: newMVar :: MonadIO m => a -> m (MVar a)
+ Prelude: newTMVar :: a -> STM (TMVar a)
+ Prelude: newTMVarIO :: MonadIO m => a -> m (TMVar a)
+ Prelude: newTVar :: a -> STM (TVar a)
+ Prelude: newTVarIO :: MonadIO m => a -> m (TVar a)
+ Prelude: newtype All
+ Prelude: newtype Alt (f :: k -> Type) (a :: k)
+ Prelude: newtype Any
+ Prelude: newtype Ap (f :: k -> Type) (a :: k)
+ Prelude: newtype Comparison a
+ Prelude: newtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1)
+ Prelude: newtype Const a (b :: k)
+ Prelude: newtype Down a
+ Prelude: newtype Dual a
+ Prelude: newtype Endo a
+ Prelude: newtype Equivalence a
+ Prelude: newtype ExceptT e (m :: Type -> Type) a
+ Prelude: newtype First a
+ Prelude: newtype Identity a
+ Prelude: newtype Last a
+ Prelude: newtype MaybeT (m :: Type -> Type) a
+ Prelude: newtype Op a b
+ Prelude: newtype Option a
+ Prelude: newtype Predicate a
+ Prelude: newtype Product a
+ Prelude: newtype ReaderT r (m :: Type -> Type) a
+ Prelude: newtype StateT s (m :: Type -> Type) a
+ Prelude: newtype Sum a
+ Prelude: newtype ZipList a
+ Prelude: nonEmpty :: [a] -> Maybe (NonEmpty a)
+ Prelude: not :: Bool -> Bool
+ Prelude: notElem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
+ Prelude: null :: Foldable t => t a -> Bool
+ Prelude: numerator :: Ratio a -> a
+ Prelude: odd :: Integral a => a -> Bool
+ Prelude: on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
+ Prelude: one :: One x => OneItem x -> x
+ Prelude: optional :: Alternative f => f a -> f (Maybe a)
+ Prelude: or :: Foldable t => t Bool -> Bool
+ Prelude: orM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
+ Prelude: ord :: Char -> Int
+ Prelude: ordNub :: Ord a => [a] -> [a]
+ Prelude: ordNubOn :: Ord b => (a -> b) -> [a] -> [a]
+ Prelude: otherwise :: Bool
+ Prelude: partitionEithers :: [Either a b] -> ([a], [b])
+ Prelude: partitionWith :: (a -> Either b c) -> [a] -> ([b], [c])
+ Prelude: pattern Exc :: Exception e => e -> SomeException
+ Prelude: permutations :: [a] -> [[a]]
+ Prelude: phantom :: (Functor f, Contravariant f) => f a -> f b
+ Prelude: pi :: Floating a => a
+ Prelude: pred :: Enum a => a -> a
+ Prelude: prettyCallStack :: CallStack -> String
+ Prelude: prettySrcLoc :: SrcLoc -> String
+ Prelude: print :: forall a m. (MonadIO m, Show a) => a -> m ()
+ Prelude: product :: forall a f. (Foldable f, Num a) => f a -> a
+ Prelude: properFraction :: (RealFrac a, Integral b) => a -> (b, a)
+ Prelude: pure :: Applicative f => a -> f a
+ Prelude: put :: MonadState s m => s -> m ()
+ Prelude: putBS :: MonadIO m => ByteString -> m ()
+ Prelude: putBSLn :: MonadIO m => ByteString -> m ()
+ Prelude: putLBS :: MonadIO m => LByteString -> m ()
+ Prelude: putLBSLn :: MonadIO m => LByteString -> m ()
+ Prelude: putLText :: MonadIO m => LText -> m ()
+ Prelude: putLTextLn :: MonadIO m => LText -> m ()
+ Prelude: putMVar :: MonadIO m => MVar a -> a -> m ()
+ Prelude: putStr :: MonadIO m => String -> m ()
+ Prelude: putStrLn :: MonadIO m => String -> m ()
+ Prelude: putTMVar :: TMVar a -> a -> STM ()
+ Prelude: putText :: MonadIO m => Text -> m ()
+ Prelude: putTextLn :: MonadIO m => Text -> m ()
+ Prelude: quot :: Integral a => a -> a -> a
+ Prelude: quotRem :: Integral a => a -> a -> (a, a)
+ Prelude: readEither :: Read a => String -> Either Text a
+ Prelude: readFile' :: MonadIO m => FilePath -> m String
+ Prelude: readFileBS :: MonadIO m => FilePath -> m ByteString
+ Prelude: readFileLBS :: MonadIO m => FilePath -> m LByteString
+ Prelude: readFileLText :: MonadIO m => FilePath -> m LText
+ Prelude: readFileText :: MonadIO m => FilePath -> m Text
+ Prelude: readIORef :: MonadIO m => IORef a -> m a
+ Prelude: readMVar :: MonadIO m => MVar a -> m a
+ Prelude: readMaybe :: Read a => String -> Maybe a
+ Prelude: readTMVar :: TMVar a -> STM a
+ Prelude: readTVar :: TVar a -> STM a
+ Prelude: readTVarIO :: MonadIO m => TVar a -> m a
+ Prelude: reader :: MonadReader r m => (r -> a) -> m a
+ Prelude: reads :: Read a => ReadS a
+ Prelude: realToFrac :: (Real a, Fractional b) => a -> b
+ Prelude: recip :: Fractional a => a -> a
+ Prelude: rem :: Integral a => a -> a -> a
+ Prelude: repeat :: a -> [a]
+ Prelude: replicate :: Int -> a -> [a]
+ Prelude: replicateM :: Applicative m => Int -> m a -> m [a]
+ Prelude: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Prelude: return :: Monad m => a -> m a
+ Prelude: reverse :: [a] -> [a]
+ Prelude: rightToMaybe :: Either l r -> Maybe r
+ Prelude: rights :: [Either a b] -> [b]
+ Prelude: rnf :: NFData a => a -> ()
+ Prelude: round :: (RealFrac a, Integral b) => a -> b
+ Prelude: runExceptT :: ExceptT e m a -> m (Either e a)
+ Prelude: runReader :: Reader r a -> r -> a
+ Prelude: runState :: State s a -> s -> (a, s)
+ Prelude: scanl :: (b -> a -> b) -> b -> [a] -> [b]
+ Prelude: scanl' :: (b -> a -> b) -> b -> [a] -> [b]
+ Prelude: scanl1 :: (a -> a -> a) -> [a] -> [a]
+ Prelude: scanr :: (a -> b -> b) -> b -> [a] -> [b]
+ Prelude: scanr1 :: (a -> a -> a) -> [a] -> [a]
+ Prelude: sconcat :: Semigroup a => NonEmpty a -> a
+ Prelude: second :: Bifunctor p => (b -> c) -> p a b -> p a c
+ Prelude: seq :: forall {r :: RuntimeRep} a (b :: TYPE r). a -> b -> b
+ Prelude: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Prelude: sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
+ Prelude: sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f ()
+ Prelude: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Prelude: show :: forall b a. (Show a, IsString b) => a -> b
+ Prelude: showStackTrace :: IO (Maybe String)
+ Prelude: signum :: Num a => a -> a
+ Prelude: sin :: Floating a => a -> a
+ Prelude: sinh :: Floating a => a -> a
+ Prelude: snd :: (a, b) -> b
+ Prelude: some :: Alternative f => f a -> f [a]
+ Prelude: someNatVal :: Natural -> SomeNat
+ Prelude: sort :: Ord a => [a] -> [a]
+ Prelude: sortBy :: (a -> a -> Ordering) -> [a] -> [a]
+ Prelude: sortNub :: Ord a => [a] -> [a]
+ Prelude: sortOn :: Ord b => (a -> b) -> [a] -> [a]
+ Prelude: sortWith :: Ord b => (a -> b) -> [a] -> [a]
+ Prelude: span :: (a -> Bool) -> [a] -> ([a], [a])
+ Prelude: splitAt :: Int -> [a] -> ([a], [a])
+ Prelude: sqrt :: Floating a => a -> a
+ Prelude: state :: MonadState s m => (s -> (a, s)) -> m a
+ Prelude: stderr :: Handle
+ Prelude: stdin :: Handle
+ Prelude: stdout :: Handle
+ Prelude: stimes :: (Semigroup a, Integral b) => b -> a -> a
+ Prelude: stimesIdempotent :: Integral b => b -> a -> a
+ Prelude: stimesIdempotentMonoid :: (Integral b, Monoid a) => b -> a -> a
+ Prelude: stimesMonoid :: (Integral b, Monoid a) => b -> a -> a
+ Prelude: strictDecode :: OnDecodeError
+ Prelude: subsequences :: [a] -> [[a]]
+ Prelude: subtract :: Num a => a -> a -> a
+ Prelude: succ :: Enum a => a -> a
+ Prelude: sum :: forall a f. (Foldable f, Num a) => f a -> a
+ Prelude: swap :: (a, b) -> (b, a)
+ Prelude: swapMVar :: MonadIO m => MVar a -> a -> m a
+ Prelude: swapTMVar :: TMVar a -> a -> STM a
+ Prelude: tail :: IsNonEmpty f a [a] "tail" => f a -> [a]
+ Prelude: tails :: [a] -> [[a]]
+ Prelude: take :: Int -> [a] -> [a]
+ Prelude: takeMVar :: MonadIO m => MVar a -> m a
+ Prelude: takeTMVar :: TMVar a -> STM a
+ Prelude: takeWhile :: (a -> Bool) -> [a] -> [a]
+ Prelude: tan :: Floating a => a -> a
+ Prelude: tanh :: Floating a => a -> a
+ Prelude: throwSTM :: Exception e => e -> STM a
+ Prelude: toEnum :: Enum a => Int -> a
+ Prelude: toException :: Exception e => e -> SomeException
+ Prelude: toInteger :: Integral a => a -> Integer
+ Prelude: toIntegralSized :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b
+ Prelude: toLText :: ToLText a => a -> LText
+ Prelude: toLazy :: LazyStrict l s => s -> l
+ Prelude: toList :: Foldable t => t a -> [a]
+ Prelude: toRational :: Real a => a -> Rational
+ Prelude: toShort :: ByteString -> ShortByteString
+ Prelude: toStrict :: LazyStrict l s => l -> s
+ Prelude: toString :: ToString a => a -> String
+ Prelude: toText :: ToText a => a -> Text
+ Prelude: traceId :: String -> String
+ Prelude: traceShow :: Show a => a -> b -> b
+ Prelude: traceShowId :: Show a => a -> a
+ Prelude: traceShowM :: (Show a, Applicative f) => a -> f ()
+ Prelude: traceShowWith :: Show b => (a -> b) -> a -> a
+ Prelude: transpose :: [[a]] -> [[a]]
+ Prelude: traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
+ Prelude: traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
+ Prelude: truncate :: (RealFrac a, Integral b) => a -> b
+ Prelude: tryPutMVar :: MonadIO m => MVar a -> a -> m Bool
+ Prelude: tryPutTMVar :: TMVar a -> a -> STM Bool
+ Prelude: tryReadMVar :: MonadIO m => MVar a -> m (Maybe a)
+ Prelude: tryReadTMVar :: TMVar a -> STM (Maybe a)
+ Prelude: tryTakeMVar :: MonadIO m => MVar a -> m (Maybe a)
+ Prelude: tryTakeTMVar :: TMVar a -> STM (Maybe a)
+ Prelude: type FilePath = String
+ Prelude: type HasCallStack = ?callStack :: CallStack
+ Prelude: type LByteString = ByteString
+ Prelude: type LText = Text
+ Prelude: type OnDecodeError = OnError Word8 Char
+ Prelude: type OnError a b = String -> Maybe a -> Maybe b
+ Prelude: type Rational = Ratio Integer
+ Prelude: type Reader r = ReaderT r Identity
+ Prelude: type State s = StateT s Identity
+ Prelude: type String = [Char]
+ Prelude: type Type = Type
+ Prelude: type family OneItem x;
+ Prelude: uncons :: [a] -> Maybe (a, [a])
+ Prelude: uncurry :: (a -> b -> c) -> (a, b) -> c
+ Prelude: undefined :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a
+ Prelude: unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
+ Prelude: universe :: (Bounded a, Enum a) => [a]
+ Prelude: universeNonEmpty :: (Bounded a, Enum a) => NonEmpty a
+ Prelude: unless :: Applicative f => Bool -> f () -> f ()
+ Prelude: unlessM :: Monad m => m Bool -> m () -> m ()
+ Prelude: unlines :: IsText t "unlines" => [t] -> t
+ Prelude: unstableNub :: (Eq a, Hashable a) => [a] -> [a]
+ Prelude: unwords :: IsText t "unwords" => [t] -> t
+ Prelude: unzip :: [(a, b)] -> ([a], [b])
+ Prelude: unzip3 :: [(a, b, c)] -> ([a], [b], [c])
+ Prelude: usingReader :: r -> Reader r a -> a
+ Prelude: usingReaderT :: r -> ReaderT r m a -> m a
+ Prelude: usingState :: s -> State s a -> (a, s)
+ Prelude: usingStateT :: s -> StateT s m a -> m (a, s)
+ Prelude: vacuous :: Functor f => f Void -> f a
+ Prelude: viaNonEmpty :: (NonEmpty a -> b) -> [a] -> Maybe b
+ Prelude: void :: Functor f => f a -> f ()
+ Prelude: when :: Applicative f => Bool -> f () -> f ()
+ Prelude: whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()
+ Prelude: whenLeft :: Applicative f => a -> Either l r -> (l -> f a) -> f a
+ Prelude: whenLeftM :: Monad m => a -> m (Either l r) -> (l -> m a) -> m a
+ Prelude: whenLeftM_ :: Monad m => m (Either l r) -> (l -> m ()) -> m ()
+ Prelude: whenLeft_ :: Applicative f => Either l r -> (l -> f ()) -> f ()
+ Prelude: whenM :: Monad m => m Bool -> m () -> m ()
+ Prelude: whenNotNull :: Applicative f => [a] -> (NonEmpty a -> f ()) -> f ()
+ Prelude: whenNotNullM :: Monad m => m [a] -> (NonEmpty a -> m ()) -> m ()
+ Prelude: whenNothingM :: Monad m => m (Maybe a) -> m a -> m a
+ Prelude: whenNothingM_ :: Monad m => m (Maybe a) -> m () -> m ()
+ Prelude: whenNothing_ :: Applicative f => Maybe a -> f () -> f ()
+ Prelude: whenRight :: Applicative f => a -> Either l r -> (r -> f a) -> f a
+ Prelude: whenRightM :: Monad m => a -> m (Either l r) -> (r -> m a) -> m a
+ Prelude: whenRightM_ :: Monad m => m (Either l r) -> (r -> m ()) -> m ()
+ Prelude: whenRight_ :: Applicative f => Either l r -> (r -> f ()) -> f ()
+ Prelude: withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
+ Prelude: withFrozenCallStack :: HasCallStack => (HasCallStack => a) -> a
+ Prelude: withReader :: (r' -> r) -> Reader r a -> Reader r' a
+ Prelude: withReaderT :: forall r' r (m :: Type -> Type) a. (r' -> r) -> ReaderT r m a -> ReaderT r' m a
+ Prelude: withState :: (s -> s) -> State s a -> State s a
+ Prelude: words :: IsText t "words" => t -> [t]
+ Prelude: writeFile :: MonadIO m => FilePath -> String -> m ()
+ Prelude: writeFileBS :: MonadIO m => FilePath -> ByteString -> m ()
+ Prelude: writeFileLBS :: MonadIO m => FilePath -> LByteString -> m ()
+ Prelude: writeFileLText :: MonadIO m => FilePath -> LText -> m ()
+ Prelude: writeFileText :: MonadIO m => FilePath -> Text -> m ()
+ Prelude: writeIORef :: MonadIO m => IORef a -> a -> m ()
+ Prelude: writeTVar :: TVar a -> a -> STM ()
+ Prelude: xor :: Bits a => a -> a -> a
+ Prelude: zip :: [a] -> [b] -> [(a, b)]
+ Prelude: zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
+ Prelude: zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
+ Prelude: zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Prelude: zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
+ Prelude: }
- Nix: evaluateExpression :: (MonadNix e t f m, Has e Options) => Maybe FilePath -> (Maybe FilePath -> NExprLoc -> m (NValue t f m)) -> (NValue t f m -> m a) -> NExprLoc -> m a
+ Nix: evaluateExpression :: (MonadNix e t f m, Has e Options) => Maybe Path -> (Maybe Path -> NExprLoc -> m (NValue t f m)) -> (NValue t f m -> m a) -> NExprLoc -> m a
- Nix: nixEvalExpr :: (MonadNix e t f m, Has e Options) => Maybe FilePath -> NExpr -> m (NValue t f m)
+ Nix: nixEvalExpr :: (MonadNix e t f m, Has e Options) => Maybe Path -> NExpr -> m (NValue t f m)
- Nix: nixEvalExprLoc :: forall e t f m. (MonadNix e t f m, Has e Options) => Maybe FilePath -> NExprLoc -> m (NValue t f m)
+ Nix: nixEvalExprLoc :: forall e t f m. (MonadNix e t f m, Has e Options) => Maybe Path -> NExprLoc -> m (NValue t f m)
- Nix: nixTracingEvalExprLoc :: (MonadNix e t f m, Has e Options, MonadIO m, Alternative m) => Maybe FilePath -> NExprLoc -> m (NValue t f m)
+ Nix: nixTracingEvalExprLoc :: (MonadNix e t f m, Has e Options, MonadIO m, Alternative m) => Maybe Path -> NExprLoc -> m (NValue t f m)
- Nix: withNixContext :: forall e t f m r. (MonadNix e t f m, Has e Options) => Maybe FilePath -> m r -> m r
+ Nix: withNixContext :: forall e t f m r. (MonadNix e t f m, Has e Options) => Maybe Path -> m r -> m r
- Nix.Builtins: builtins :: (MonadNix e t f m, Scoped (NValue t f m) m) => m (Scopes m (NValue t f m))
+ Nix.Builtins: builtins :: forall e t f m. (MonadNix e t f m, Scoped (NValue t f m) m) => m (Scopes m (NValue t f m))
- Nix.Builtins: withNixContext :: forall e t f m r. (MonadNix e t f m, Has e Options) => Maybe FilePath -> m r -> m r
+ Nix.Builtins: withNixContext :: forall e t f m r. (MonadNix e t f m, Has e Options) => Maybe Path -> m r -> m r
- Nix.Cache: readCache :: FilePath -> IO NExprLoc
+ Nix.Cache: readCache :: Path -> IO NExprLoc
- Nix.Cache: writeCache :: FilePath -> NExprLoc -> IO ()
+ Nix.Cache: writeCache :: Path -> NExprLoc -> IO ()
- Nix.Cited: cited :: forall f t a (m :: Type -> Type) v. Functor f => (t -> f a) -> NCited m v t -> f (NCited m v a)
+ Nix.Cited: cited :: forall {f} {t} {a} {m :: Type -> Type} {v}. Functor f => (t -> f a) -> NCited m v t -> f (NCited m v a)
- Nix.Cited: lexicalScope :: forall f (m1 :: Type -> Type) v (m2 :: Type -> Type). Functor f => (Scopes m1 v -> f (Scopes m2 v)) -> Provenance m1 v -> f (Provenance m2 v)
+ Nix.Cited: lexicalScope :: forall {f} {m1 :: Type -> Type} {v} {m2 :: Type -> Type}. Functor f => (Scopes m1 v -> f (Scopes m2 v)) -> Provenance m1 v -> f (Provenance m2 v)
- Nix.Cited: originExpr :: forall f v (m :: Type -> Type). Functor f => (NExprLocF (Maybe v) -> f (NExprLocF (Maybe v))) -> Provenance m v -> f (Provenance m v)
+ Nix.Cited: originExpr :: forall {f} {v} {m :: Type -> Type}. Functor f => (NExprLocF (Maybe v) -> f (NExprLocF (Maybe v))) -> Provenance m v -> f (Provenance m v)
- Nix.Cited: provenance :: forall f (m1 :: Type -> Type) v1 (m2 :: Type -> Type) v2 a. Functor f => ([Provenance m1 v1] -> f [Provenance m2 v2]) -> NCited m1 v1 a -> f (NCited m2 v2 a)
+ Nix.Cited: provenance :: forall {f} {m1 :: Type -> Type} {v1} {m2 :: Type -> Type} {v2} {a}. Functor f => ([Provenance m1 v1] -> f [Provenance m2 v2]) -> NCited m1 v1 a -> f (NCited m2 v2 a)
- Nix.Effects: StorePath :: FilePath -> StorePath
+ Nix.Effects: StorePath :: Path -> StorePath
- Nix.Effects: addPath :: (Framed e m, MonadStore m) => FilePath -> m StorePath
+ Nix.Effects: addPath :: (Framed e m, MonadStore m) => Path -> m StorePath
- Nix.Effects: addToStore :: (MonadStore m, MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> FilePath -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)
+ Nix.Effects: addToStore :: (MonadStore m, MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> Path -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)
- Nix.Effects: class Monad m => MonadPutStr m
+ Nix.Effects: class (Monad m, MonadIO m) => MonadPutStr m
- Nix.Effects: findEnvPath :: MonadEffects t f m => String -> m FilePath
+ Nix.Effects: findEnvPath :: MonadEffects t f m => String -> m Path
- Nix.Effects: findPath :: MonadEffects t f m => [NValue t f m] -> FilePath -> m FilePath
+ Nix.Effects: findPath :: MonadEffects t f m => [NValue t f m] -> Path -> m Path
- Nix.Effects: getDataDir :: (MonadPaths m, MonadTrans t, MonadPaths m', m ~ t m') => m FilePath
+ Nix.Effects: getDataDir :: (MonadPaths m, MonadTrans t, MonadPaths m', m ~ t m') => m Path
- Nix.Effects: importPath :: MonadEffects t f m => FilePath -> m (NValue t f m)
+ Nix.Effects: importPath :: MonadEffects t f m => Path -> m (NValue t f m)
- Nix.Effects: pathToDefaultNix :: MonadEffects t f m => FilePath -> m FilePath
+ Nix.Effects: pathToDefaultNix :: MonadEffects t f m => Path -> m Path
- Nix.Effects: toFile_ :: (Framed e m, MonadStore m) => FilePath -> String -> m StorePath
+ Nix.Effects: toFile_ :: (Framed e m, MonadStore m) => Path -> Text -> m StorePath
- Nix.Effects.Basic: (<///>) :: FilePath -> FilePath -> FilePath
+ Nix.Effects.Basic: (<///>) :: Path -> Path -> Path
- Nix.Effects.Basic: defaultFindEnvPath :: MonadNix e t f m => String -> m FilePath
+ Nix.Effects.Basic: defaultFindEnvPath :: MonadNix e t f m => String -> m Path
- Nix.Effects.Basic: defaultFindPath :: MonadNix e t f m => [NValue t f m] -> FilePath -> m FilePath
+ Nix.Effects.Basic: defaultFindPath :: MonadNix e t f m => [NValue t f m] -> Path -> m Path
- Nix.Effects.Basic: defaultImportPath :: (MonadNix e t f m, MonadState (HashMap FilePath NExprLoc, b) m) => FilePath -> m (NValue t f m)
+ Nix.Effects.Basic: defaultImportPath :: (MonadNix e t f m, MonadState (HashMap Path NExprLoc, b) m) => Path -> m (NValue t f m)
- Nix.Effects.Basic: defaultPathToDefaultNix :: MonadNix e t f m => FilePath -> m FilePath
+ Nix.Effects.Basic: defaultPathToDefaultNix :: MonadNix e t f m => Path -> m Path
- Nix.Effects.Basic: expandHomePath :: MonadFile m => FilePath -> m FilePath
+ Nix.Effects.Basic: expandHomePath :: MonadFile m => Path -> m Path
- Nix.Effects.Basic: findEnvPathM :: forall e t f m. MonadNix e t f m => FilePath -> m FilePath
+ Nix.Effects.Basic: findEnvPathM :: forall e t f m. MonadNix e t f m => Path -> m Path
- Nix.Effects.Basic: findPathBy :: forall e t f m. MonadNix e t f m => (FilePath -> m (Maybe FilePath)) -> [NValue t f m] -> FilePath -> m FilePath
+ Nix.Effects.Basic: findPathBy :: forall e t f m. MonadNix e t f m => (Path -> m (Maybe Path)) -> [NValue t f m] -> Path -> m Path
- Nix.Effects.Basic: findPathM :: forall e t f m. MonadNix e t f m => [NValue t f m] -> FilePath -> m FilePath
+ Nix.Effects.Basic: findPathM :: forall e t f m. MonadNix e t f m => [NValue t f m] -> Path -> m Path
- Nix.Effects.Basic: pathToDefaultNixFile :: MonadFile m => FilePath -> m FilePath
+ Nix.Effects.Basic: pathToDefaultNixFile :: MonadFile m => Path -> m Path
- Nix.Effects.Basic: removeDotDotIndirections :: FilePath -> FilePath
+ Nix.Effects.Basic: removeDotDotIndirections :: Path -> Path
- Nix.Effects.Derivation: defaultDerivationStrict :: forall e t f m b. (MonadNix e t f m, MonadState (b, AttrSet Text) m) => NValue t f m -> m (NValue t f m)
+ Nix.Effects.Derivation: defaultDerivationStrict :: forall e t f m b. (MonadNix e t f m, MonadState (b, KeyMap Text) m) => NValue t f m -> m (NValue t f m)
- Nix.Eval: attrMissing :: MonadEval v m => NonEmpty Text -> Maybe v -> m v
+ Nix.Eval: attrMissing :: MonadEval v m => NonEmpty VarName -> Maybe v -> m v
- Nix.Eval: attrSetAlter :: forall v m. MonadNixEval v m => [Text] -> SourcePos -> AttrSet (m v) -> AttrSet SourcePos -> m v -> m (AttrSet (m v), AttrSet SourcePos)
+ Nix.Eval: attrSetAlter :: forall v m. MonadNixEval v m => [VarName] -> SourcePos -> AttrSet (m v) -> PositionSet -> m v -> m (AttrSet (m v), PositionSet)
- Nix.Eval: evalBinds :: forall v m. MonadNixEval v m => Bool -> [Binding (m v)] -> m (AttrSet v, AttrSet SourcePos)
+ Nix.Eval: evalBinds :: forall v m. MonadNixEval v m => Bool -> [Binding (m v)] -> m (AttrSet v, PositionSet)
- Nix.Eval: evalEnvPath :: MonadEval v m => FilePath -> m v
+ Nix.Eval: evalEnvPath :: MonadEval v m => Path -> m v
- Nix.Eval: evalGetterKeyName :: forall v m. (MonadEval v m, FromValue NixString m v) => NKeyName (m v) -> m Text
+ Nix.Eval: evalGetterKeyName :: forall v m. (MonadEval v m, FromValue NixString m v) => NKeyName (m v) -> m VarName
- Nix.Eval: evalLiteralPath :: MonadEval v m => FilePath -> m v
+ Nix.Eval: evalLiteralPath :: MonadEval v m => Path -> m v
- Nix.Eval: evalSelect :: forall v m. MonadNixEval v m => m v -> NAttrPath (m v) -> m (Either (v, NonEmpty Text) (m v))
+ Nix.Eval: evalSelect :: forall v m. MonadNixEval v m => m v -> NAttrPath (m v) -> m (Either (v, NonEmpty VarName) (m v))
- Nix.Eval: evalSetterKeyName :: (MonadEval v m, FromValue NixString m v) => NKeyName (m v) -> m (Maybe Text)
+ Nix.Eval: evalSetterKeyName :: (MonadEval v m, FromValue NixString m v) => NKeyName (m v) -> m (Maybe VarName)
- Nix.Eval: evaledSym :: MonadEval v m => Text -> v -> m v
+ Nix.Eval: evaledSym :: MonadEval v m => VarName -> v -> m v
- Nix.Eval: freeVariable :: MonadEval v m => Text -> m v
+ Nix.Eval: freeVariable :: MonadEval v m => VarName -> m v
- Nix.Eval: synHole :: MonadEval v m => Text -> m v
+ Nix.Eval: synHole :: MonadEval v m => VarName -> m v
- Nix.Eval: type MonadNixEval v m = (MonadEval v m, Scoped v m, MonadValue v m, MonadFix m, ToValue Bool m v, ToValue [v] m v, FromValue NixString m v, ToValue (AttrSet v, AttrSet SourcePos) m v, FromValue (AttrSet v, AttrSet SourcePos) m v)
+ Nix.Eval: type MonadNixEval v m = (MonadEval v m, Scoped v m, MonadValue v m, MonadFix m, ToValue Bool m v, ToValue [v] m v, FromValue NixString m v, ToValue (AttrSet v, PositionSet) m v, FromValue (AttrSet v, PositionSet) m v)
- Nix.Exec: nvBuiltinP :: MonadCited t f m => Provenance m (NValue t f m) -> Text -> (NValue t f m -> m (NValue t f m)) -> NValue t f m
+ Nix.Exec: nvBuiltinP :: MonadCited t f m => Provenance m (NValue t f m) -> VarName -> (NValue t f m -> m (NValue t f m)) -> NValue t f m
- Nix.Exec: nvPathP :: MonadCited t f m => Provenance m (NValue t f m) -> FilePath -> NValue t f m
+ Nix.Exec: nvPathP :: MonadCited t f m => Provenance m (NValue t f m) -> Path -> NValue t f m
- Nix.Exec: nvSetP :: MonadCited t f m => Provenance m (NValue t f m) -> AttrSet SourcePos -> AttrSet (NValue t f m) -> NValue t f m
+ Nix.Exec: nvSetP :: MonadCited t f m => Provenance m (NValue t f m) -> PositionSet -> AttrSet (NValue t f m) -> NValue t f m
- Nix.Expr.Shorthands: infixl 2 @.
+ Nix.Expr.Shorthands: infixl 2 $||
- Nix.Expr.Shorthands: inherit :: [NKeyName e] -> SourcePos -> Binding e
+ Nix.Expr.Shorthands: inherit :: [VarName] -> Binding e
- Nix.Expr.Shorthands: inheritFrom :: e -> [NKeyName e] -> SourcePos -> Binding e
+ Nix.Expr.Shorthands: inheritFrom :: e -> [VarName] -> Binding e
- Nix.Expr.Types: Inherit :: !Maybe r -> ![NKeyName r] -> !SourcePos -> Binding r
+ Nix.Expr.Types: Inherit :: !Maybe r -> ![VarName] -> !SourcePos -> Binding r
- Nix.Expr.Types: NEnvPath :: !FilePath -> NExprF r
+ Nix.Expr.Types: NEnvPath :: !Path -> NExprF r
- Nix.Expr.Types: NLiteralPath :: !FilePath -> NExprF r
+ Nix.Expr.Types: NLiteralPath :: !Path -> NExprF r
- Nix.Expr.Types: NSelect :: !r -> !NAttrPath r -> !Maybe r -> NExprF r
+ Nix.Expr.Types: NSelect :: !Maybe r -> !r -> !NAttrPath r -> NExprF r
- Nix.Expr.Types: NSet :: !NRecordType -> ![Binding r] -> NExprF r
+ Nix.Expr.Types: NSet :: !Recursivity -> ![Binding r] -> NExprF r
- Nix.Expr.Types: ParamSet :: !ParamSet r -> !Bool -> !Maybe VarName -> Params r
+ Nix.Expr.Types: ParamSet :: !Maybe VarName -> !Variadic -> !ParamSet r -> Params r
- Nix.Expr.Types: _Inherit :: Applicative f => ((Maybe r, [NKeyName r], SourcePos) -> f (Maybe r, [NKeyName r], SourcePos)) -> Binding r -> f (Binding r)
+ Nix.Expr.Types: _Inherit :: Applicative f => ((Maybe r, [VarName], SourcePos) -> f (Maybe r, [VarName], SourcePos)) -> Binding r -> f (Binding r)
- Nix.Expr.Types: _NEnvPath :: Applicative f => (FilePath -> f FilePath) -> NExprF r -> f (NExprF r)
+ Nix.Expr.Types: _NEnvPath :: Applicative f => (Path -> f Path) -> NExprF r -> f (NExprF r)
- Nix.Expr.Types: _NLiteralPath :: Applicative f => (FilePath -> f FilePath) -> NExprF r -> f (NExprF r)
+ Nix.Expr.Types: _NLiteralPath :: Applicative f => (Path -> f Path) -> NExprF r -> f (NExprF r)
- Nix.Expr.Types: _NSelect :: Applicative f => ((r, NAttrPath r, Maybe r) -> f (r, NAttrPath r, Maybe r)) -> NExprF r -> f (NExprF r)
+ Nix.Expr.Types: _NSelect :: Applicative f => ((Maybe r, r, NAttrPath r) -> f (Maybe r, r, NAttrPath r)) -> NExprF r -> f (NExprF r)
- Nix.Expr.Types: _NSet :: Applicative f => ((NRecordType, [Binding r]) -> f (NRecordType, [Binding r])) -> NExprF r -> f (NExprF r)
+ Nix.Expr.Types: _NSet :: Applicative f => ((Recursivity, [Binding r]) -> f (Recursivity, [Binding r])) -> NExprF r -> f (NExprF r)
- Nix.Expr.Types: _ParamSet :: Applicative f => ((ParamSet r1, Bool, Maybe VarName) -> f (ParamSet r2, Bool, Maybe VarName)) -> Params r1 -> f (Params r2)
+ Nix.Expr.Types: _ParamSet :: Applicative f => ((Maybe VarName, Variadic, ParamSet r1) -> f (Maybe VarName, Variadic, ParamSet r2)) -> Params r1 -> f (Params r2)
- Nix.Expr.Types: ekey :: NExprAnn ann g => NonEmpty Text -> SourcePos -> Lens' (Fix g) (Maybe (Fix g))
+ Nix.Expr.Types: ekey :: forall ann g. NExprAnn ann g => NonEmpty VarName -> SourcePos -> Lens' (Fix g) (Maybe (Fix g))
- Nix.Expr.Types: hashAt :: VarName -> Lens' (AttrSet v) (Maybe v)
+ Nix.Expr.Types: hashAt :: Functor f => VarName -> (Maybe v -> f (Maybe v)) -> AttrSet v -> f (AttrSet v)
- Nix.Expr.Types.Annotated: [annotated] :: Ann ann a -> a
+ Nix.Expr.Types.Annotated: [annotated] :: AnnUnit ann expr -> expr
- Nix.Expr.Types.Annotated: [annotation] :: Ann ann a -> ann
+ Nix.Expr.Types.Annotated: [annotation] :: AnnUnit ann expr -> ann
- Nix.Expr.Types.Annotated: stripAnnotation :: Functor f => Fix (AnnF ann f) -> Fix f
+ Nix.Expr.Types.Annotated: stripAnnotation :: Functor f => Ann ann f -> Fix f
- Nix.Expr.Types.Annotated: type AnnF ann f = Compose (Ann ann) f
+ Nix.Expr.Types.Annotated: type AnnF ann f = Compose (AnnUnit ann) f
- Nix.Frames: [HRefl] :: forall k1 (a :: k1). a :~~: a
+ Nix.Frames: [HRefl] :: forall {k1} (a :: k1). a :~~: a
- Nix.Frames: [Refl] :: forall k (a :: k). a :~: a
+ Nix.Frames: [Refl] :: forall {k} (a :: k). a :~: a
- Nix.Frames: eqT :: forall k (a :: k) (b :: k). (Typeable a, Typeable b) => Maybe (a :~: b)
+ Nix.Frames: eqT :: forall {k} (a :: k) (b :: k). (Typeable a, Typeable b) => Maybe (a :~: b)
- Nix.Frames: gcast :: forall k (a :: k) (b :: k) c. (Typeable a, Typeable b) => c a -> Maybe (c b)
+ Nix.Frames: gcast :: forall {k} (a :: k) (b :: k) c. (Typeable a, Typeable b) => c a -> Maybe (c b)
- Nix.Frames: gcast1 :: forall k1 k2 c (t :: k2 -> k1) (t' :: k2 -> k1) (a :: k2). (Typeable t, Typeable t') => c (t a) -> Maybe (c (t' a))
+ Nix.Frames: gcast1 :: forall {k1} {k2} c (t :: k2 -> k1) (t' :: k2 -> k1) (a :: k2). (Typeable t, Typeable t') => c (t a) -> Maybe (c (t' a))
- Nix.Frames: gcast2 :: forall k1 k2 k3 c (t :: k2 -> k3 -> k1) (t' :: k2 -> k3 -> k1) (a :: k2) (b :: k3). (Typeable t, Typeable t') => c (t a b) -> Maybe (c (t' a b))
+ Nix.Frames: gcast2 :: forall {k1} {k2} {k3} c (t :: k2 -> k3 -> k1) (t' :: k2 -> k3 -> k1) (a :: k2) (b :: k3). (Typeable t, Typeable t') => c (t a b) -> Maybe (c (t' a b))
- Nix.Frames: typeRep :: forall k proxy (a :: k). Typeable a => proxy a -> TypeRep
+ Nix.Frames: typeRep :: forall {k} proxy (a :: k). Typeable a => proxy a -> TypeRep
- Nix.Lint: TSet :: Maybe (HashMap Text r) -> NTypeF (m :: Type -> Type) r
+ Nix.Lint: TSet :: Maybe (AttrSet r) -> NTypeF (m :: Type -> Type) r
- Nix.Options: Options :: Verbosity -> Bool -> Bool -> Bool -> Bool -> Maybe FilePath -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe FilePath -> Bool -> Bool -> Bool -> Bool -> Maybe Text -> [FilePath] -> Bool -> Maybe FilePath -> Bool -> Bool -> Bool -> Maybe Text -> [(Text, Text)] -> [(Text, Text)] -> Maybe FilePath -> UTCTime -> [FilePath] -> Options
+ Nix.Options: Options :: Verbosity -> Bool -> Bool -> Bool -> Bool -> Maybe Path -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe Path -> Bool -> Bool -> Bool -> Bool -> Maybe Text -> [Path] -> Bool -> Maybe Path -> Bool -> Bool -> Bool -> Maybe Text -> [(Text, Text)] -> [(Text, Text)] -> Maybe Path -> UTCTime -> [Path] -> Options
- Nix.Options: [filePaths] :: Options -> [FilePath]
+ Nix.Options: [filePaths] :: Options -> [Path]
- Nix.Options: [findFile] :: Options -> Maybe FilePath
+ Nix.Options: [findFile] :: Options -> Maybe Path
- Nix.Options: [fromFile] :: Options -> Maybe FilePath
+ Nix.Options: [fromFile] :: Options -> Maybe Path
- Nix.Options: [include] :: Options -> [FilePath]
+ Nix.Options: [include] :: Options -> [Path]
- Nix.Options: [readFrom] :: Options -> Maybe FilePath
+ Nix.Options: [readFrom] :: Options -> Maybe Path
- Nix.Options: [reduce] :: Options -> Maybe FilePath
+ Nix.Options: [reduce] :: Options -> Maybe Path
- Nix.Parser: nixSelector :: Parser (Ann SrcSpan (NAttrPath NExprLoc))
+ Nix.Parser: nixSelector :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc))
- Nix.Parser: parseFromFileEx :: MonadFile m => Parser a -> FilePath -> m (Result a)
+ Nix.Parser: parseFromFileEx :: MonadFile m => Parser a -> Path -> m (Result a)
- Nix.Parser: parseNixFile :: MonadFile m => FilePath -> m (Result NExpr)
+ Nix.Parser: parseNixFile :: MonadFile m => Path -> m (Result NExpr)
- Nix.Parser: parseNixFileLoc :: MonadFile m => FilePath -> m (Result NExprLoc)
+ Nix.Parser: parseNixFileLoc :: MonadFile m => Path -> m (Result NExprLoc)
- Nix.Parser: reservedNames :: HashSet Text
+ Nix.Parser: reservedNames :: HashSet VarName
- Nix.Pretty: prettyParamSet :: ParamSet (NixDoc ann) -> Bool -> Doc ann
+ Nix.Pretty: prettyParamSet :: Variadic -> ParamSet (NixDoc ann) -> Doc ann
- Nix.Pretty: printNix :: forall t f m. MonadDataContext f m => NValue t f m -> String
+ Nix.Pretty: printNix :: forall t f m. MonadDataContext f m => NValue t f m -> Text
- Nix.Reduce: reduceExpr :: (MonadIO m, MonadFail m) => Maybe FilePath -> NExprLoc -> m NExprLoc
+ Nix.Reduce: reduceExpr :: (MonadIO m, MonadFail m) => Maybe Path -> NExprLoc -> m NExprLoc
- Nix.Reduce: reducingEvalExpr :: (Framed e m, Has e Options, Exception r, MonadCatch m, MonadIO m) => (NExprLocF (m a) -> m a) -> Maybe FilePath -> NExprLoc -> m (NExprLoc, Either r a)
+ Nix.Reduce: reducingEvalExpr :: (Framed e m, Has e Options, Exception r, MonadCatch m, MonadIO m) => (NExprLocF (m a) -> m a) -> Maybe Path -> NExprLoc -> m (NExprLoc, Either r a)
- Nix.Render: canonicalizePath :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m FilePath
+ Nix.Render: canonicalizePath :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m Path
- Nix.Render: class MonadFail m => MonadFile m
+ Nix.Render: class (MonadFail m, MonadIO m) => MonadFile m
- Nix.Render: doesDirectoryExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool
+ Nix.Render: doesDirectoryExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool
- Nix.Render: doesFileExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool
+ Nix.Render: doesFileExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool
- Nix.Render: doesPathExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool
+ Nix.Render: doesPathExist :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool
- Nix.Render: errorContext :: FilePath -> Pos -> Pos -> Pos -> Pos -> Doc a
+ Nix.Render: errorContext :: Path -> Pos -> Pos -> Pos -> Pos -> Doc a
- Nix.Render: getCurrentDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => m FilePath
+ Nix.Render: getCurrentDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => m Path
- Nix.Render: getHomeDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => m FilePath
+ Nix.Render: getHomeDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => m Path
- Nix.Render: getSymbolicLinkStatus :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m FileStatus
+ Nix.Render: getSymbolicLinkStatus :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m FileStatus
- Nix.Render: listDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m [FilePath]
+ Nix.Render: listDirectory :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => Path -> m [Path]
- Nix.Render: readFile :: (MonadFile m, MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m ByteString
+ Nix.Render: readFile :: (MonadFile m, MonadTrans t, MonadIO m', MonadFile m', m ~ t m') => Path -> m Text
- Nix.Render: sourceContext :: MonadFile m => FilePath -> Pos -> Pos -> Pos -> Pos -> Doc a -> m (Doc a)
+ Nix.Render: sourceContext :: MonadFile m => Path -> Pos -> Pos -> Pos -> Pos -> Doc a -> m (Doc a)
- Nix.Render.Frame: renderEvalFrame :: (MonadReader e m, Has e Options, MonadFile m) => NixLevel -> EvalFrame m v -> m [Doc ann]
+ Nix.Render.Frame: renderEvalFrame :: forall e m v ann. (MonadReader e m, Has e Options, MonadFile m) => NixLevel -> EvalFrame m v -> m [Doc ann]
- Nix.Scope: emptyScopes :: forall m a. Scopes m a
+ Nix.Scope: emptyScopes :: Scopes m a
- Nix.Scope: lookupVar :: Scoped a m => Text -> m (Maybe a)
+ Nix.Scope: lookupVar :: Scoped a m => VarName -> m (Maybe a)
- Nix.Scope: lookupVarReader :: forall m a e. (MonadReader e m, Has e (Scopes m a)) => Text -> m (Maybe a)
+ Nix.Scope: lookupVarReader :: forall m a e. (MonadReader e m, Has e (Scopes m a)) => VarName -> m (Maybe a)
- Nix.Scope: pushScope :: Scoped a m => AttrSet a -> m r -> m r
+ Nix.Scope: pushScope :: Scoped a m => Scope a -> m r -> m r
- Nix.Scope: pushWeakScope :: (Functor m, Scoped a m) => m (AttrSet a) -> m r -> m r
+ Nix.Scope: pushWeakScope :: (Functor m, Scoped a m) => m (Scope a) -> m r -> m r
- Nix.Scope: scopeLookup :: Text -> [Scope a] -> Maybe a
+ Nix.Scope: scopeLookup :: VarName -> [Scope a] -> Maybe a
- Nix.Standard: StandardTF :: ReaderT (Context r (StdValue r)) (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m) a -> StandardTF r m a
+ Nix.Standard: StandardTF :: ReaderT (Context r (StdValue r)) (StateT (HashMap Path NExprLoc, HashMap Text Text) m) a -> StandardTF r m a
- Nix.Standard: StdThunk :: StdCited m (NThunkF m (StdValue m)) -> StdThunk (m :: Type -> Type)
+ Nix.Standard: StdThunk :: StdCited m (NThunkF m (StdValue m)) -> StdThunk m
- Nix.Standard: mkStandardT :: ReaderT (Context (StandardT m) (StdValue (StandardT m))) (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m) a -> StandardT m a
+ Nix.Standard: mkStandardT :: ReaderT (Context (StandardT m) (StdValue (StandardT m))) (StateT (HashMap Path NExprLoc, HashMap Text Text) m) a -> StandardT m a
- Nix.Standard: newtype StdThunk (m :: Type -> Type)
+ Nix.Standard: newtype StdThunk m
- Nix.Standard: runStandardT :: StandardT m a -> ReaderT (Context (StandardT m) (StdValue (StandardT m))) (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m) a
+ Nix.Standard: runStandardT :: StandardT m a -> ReaderT (Context (StandardT m) (StdValue (StandardT m))) (StateT (HashMap Path NExprLoc, HashMap Text Text) m) a
- Nix.String: StringContext :: !Text -> !ContextFlavor -> StringContext
+ Nix.String: StringContext :: !VarName -> !ContextFlavor -> StringContext
- Nix.String: [scPath] :: StringContext -> !Text
+ Nix.String: [scPath] :: StringContext -> !VarName
- Nix.Type.Assumption: Assumption :: [(Name, Type)] -> Assumption
+ Nix.Type.Assumption: Assumption :: [(VarName, Type)] -> Assumption
- Nix.Type.Assumption: extend :: Assumption -> (Name, Type) -> Assumption
+ Nix.Type.Assumption: extend :: Assumption -> (VarName, Type) -> Assumption
- Nix.Type.Assumption: keys :: Assumption -> [Name]
+ Nix.Type.Assumption: keys :: Assumption -> [VarName]
- Nix.Type.Assumption: lookup :: Name -> Assumption -> [Type]
+ Nix.Type.Assumption: lookup :: VarName -> Assumption -> [Type]
- Nix.Type.Assumption: remove :: Assumption -> Name -> Assumption
+ Nix.Type.Assumption: remove :: Assumption -> VarName -> Assumption
- Nix.Type.Assumption: singleton :: Name -> Type -> Assumption
+ Nix.Type.Assumption: singleton :: VarName -> Type -> Assumption
- Nix.Type.Env: TypeEnv :: Map Name [Scheme] -> Env
+ Nix.Type.Env: TypeEnv :: Map VarName [Scheme] -> Env
- Nix.Type.Env: extend :: Env -> (Name, [Scheme]) -> Env
+ Nix.Type.Env: extend :: Env -> (VarName, [Scheme]) -> Env
- Nix.Type.Env: extends :: Env -> [(Name, [Scheme])] -> Env
+ Nix.Type.Env: extends :: Env -> [(VarName, [Scheme])] -> Env
- Nix.Type.Env: fromList :: [(Name, [Scheme])] -> Env
+ Nix.Type.Env: fromList :: [(VarName, [Scheme])] -> Env
- Nix.Type.Env: keys :: Env -> [Name]
+ Nix.Type.Env: keys :: Env -> [VarName]
- Nix.Type.Env: lookup :: Name -> Env -> Maybe [Scheme]
+ Nix.Type.Env: lookup :: VarName -> Env -> Maybe [Scheme]
- Nix.Type.Env: remove :: Env -> Name -> Env
+ Nix.Type.Env: remove :: Env -> VarName -> Env
- Nix.Type.Env: singleton :: Name -> Scheme -> Env
+ Nix.Type.Env: singleton :: VarName -> Scheme -> Env
- Nix.Type.Env: toList :: Env -> [(Name, [Scheme])]
+ Nix.Type.Env: toList :: Env -> [(VarName, [Scheme])]
- Nix.Type.Infer: UnboundVariables :: [Text] -> TypeError
+ Nix.Type.Infer: UnboundVariables :: [VarName] -> TypeError
- Nix.Type.Infer: inferTop :: Env -> [(Text, NExpr)] -> Either InferError Env
+ Nix.Type.Infer: inferTop :: Env -> [(VarName, NExpr)] -> Either InferError Env
- Nix.Type.Type: TSet :: Bool -> AttrSet Type -> Type
+ Nix.Type.Type: TSet :: Variadic -> AttrSet Type -> Type
- Nix.Type.Type: typeFun :: [Type] -> Type
+ Nix.Type.Type: typeFun :: NonEmpty Type -> Type
- Nix.Value: NVBuiltinF :: Text -> (p -> m r) -> NValueF p m r
+ Nix.Value: NVBuiltinF :: VarName -> (p -> m r) -> NValueF p m r
- Nix.Value: NVPathF :: FilePath -> NValueF p m r
+ Nix.Value: NVPathF :: Path -> NValueF p m r
- Nix.Value: NVSetF :: AttrSet r -> AttrSet SourcePos -> NValueF p m r
+ Nix.Value: NVSetF :: PositionSet -> AttrSet r -> NValueF p m r
- Nix.Value: _NVBuiltinF :: Applicative f => ((Text, p -> m r) -> f (Text, p -> m r)) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVBuiltinF :: Applicative f => ((VarName, p -> m r) -> f (VarName, p -> m r)) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: _NVConstantF :: forall f p (m :: Type -> Type) r. Applicative f => (NAtom -> f NAtom) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVConstantF :: forall {f} {p} {m :: Type -> Type} {r}. Applicative f => (NAtom -> f NAtom) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: _NVListF :: forall f r p (m :: Type -> Type). Applicative f => ([r] -> f [r]) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVListF :: forall {f} {r} {p} {m :: Type -> Type}. Applicative f => ([r] -> f [r]) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: _NVPathF :: forall f p (m :: Type -> Type) r. Applicative f => (FilePath -> f FilePath) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVPathF :: forall {f} {p} {m :: Type -> Type} {r}. Applicative f => (Path -> f Path) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: _NVSetF :: forall f r p (m :: Type -> Type). Applicative f => ((AttrSet r, AttrSet SourcePos) -> f (AttrSet r, AttrSet SourcePos)) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVSetF :: forall {f} {r} {p} {m :: Type -> Type}. Applicative f => ((PositionSet, AttrSet r) -> f (PositionSet, AttrSet r)) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: _NVStrF :: forall f p (m :: Type -> Type) r. Applicative f => (NixString -> f NixString) -> NValueF p m r -> f (NValueF p m r)
+ Nix.Value: _NVStrF :: forall {f} {p} {m :: Type -> Type} {r}. Applicative f => (NixString -> f NixString) -> NValueF p m r -> f (NValueF p m r)
- Nix.Value: builtin :: forall m f t. (MonadThunk t m (NValue t f m), MonadDataContext f m) => Text -> (NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
+ Nix.Value: builtin :: forall m f t. (MonadThunk t m (NValue t f m), MonadDataContext f m) => VarName -> (NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
- Nix.Value: builtin2 :: (MonadThunk t m (NValue t f m), MonadDataContext f m) => Text -> (NValue t f m -> NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
+ Nix.Value: builtin2 :: (MonadThunk t m (NValue t f m), MonadDataContext f m) => VarName -> (NValue t f m -> NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
- Nix.Value: builtin3 :: (MonadThunk t m (NValue t f m), MonadDataContext f m) => Text -> (NValue t f m -> NValue t f m -> NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
+ Nix.Value: builtin3 :: (MonadThunk t m (NValue t f m), MonadDataContext f m) => VarName -> (NValue t f m -> NValue t f m -> NValue t f m -> m (NValue t f m)) -> m (NValue t f m)
- Nix.Value: nValue :: forall f1 f2 t1 (m1 :: Type -> Type) a1 f3 t2 (m2 :: Type -> Type) a2. Functor f1 => (f2 (NValueF (NValue t1 f2 m1) m1 a1) -> f1 (f3 (NValueF (NValue t2 f3 m2) m2 a2))) -> NValue' t1 f2 m1 a1 -> f1 (NValue' t2 f3 m2 a2)
+ Nix.Value: nValue :: forall {f1} {f2} {t1} {m1 :: Type -> Type} {a1} {f3} {t2} {m2 :: Type -> Type} {a2}. Functor f1 => (f2 (NValueF (NValue t1 f2 m1) m1 a1) -> f1 (f3 (NValueF (NValue t2 f3 m2) m2 a2))) -> NValue' t1 f2 m1 a1 -> f1 (NValue' t2 f3 m2 a2)
- Nix.Value: nvBuiltin :: (Applicative f, Functor m) => Text -> (NValue t f m -> m (NValue t f m)) -> NValue t f m
+ Nix.Value: nvBuiltin :: (Applicative f, Functor m) => VarName -> (NValue t f m -> m (NValue t f m)) -> NValue t f m
- Nix.Value: nvBuiltin' :: (Applicative f, Functor m) => Text -> (NValue t f m -> m r) -> NValue' t f m r
+ Nix.Value: nvBuiltin' :: (Applicative f, Functor m) => VarName -> (NValue t f m -> m r) -> NValue' t f m r
- Nix.Value: nvPath :: Applicative f => FilePath -> NValue t f m
+ Nix.Value: nvPath :: Applicative f => Path -> NValue t f m
- Nix.Value: nvPath' :: Applicative f => FilePath -> NValue' t f m r
+ Nix.Value: nvPath' :: Applicative f => Path -> NValue' t f m r
- Nix.Value: nvSet :: Applicative f => AttrSet SourcePos -> AttrSet (NValue t f m) -> NValue t f m
+ Nix.Value: nvSet :: Applicative f => PositionSet -> AttrSet (NValue t f m) -> NValue t f m
- Nix.Value: nvSet' :: Applicative f => AttrSet SourcePos -> AttrSet r -> NValue' t f m r
+ Nix.Value: nvSet' :: Applicative f => PositionSet -> AttrSet r -> NValue' t f m r
- Nix.Value: pattern NVConstant :: forall (w :: Type -> Type) t (m :: Type -> Type) a. Comonad w => NAtom -> Free (NValue' t w m) a
+ Nix.Value: pattern NVConstant :: forall {w :: Type -> Type} {t} {m :: Type -> Type} {a}. Comonad w => NAtom -> Free (NValue' t w m) a
- Nix.Value: pattern NVThunk :: forall f a. a -> Free f a
+ Nix.Value: pattern NVThunk :: forall {f} {a}. a -> Free f a
- Nix.Value: pattern NVStr :: forall (w :: Type -> Type) t (m :: Type -> Type) a. Comonad w => NixString -> Free (NValue' t w m) a
+ Nix.Value: pattern NVStr :: forall {w :: Type -> Type} {t} {m :: Type -> Type} {a}. Comonad w => NixString -> Free (NValue' t w m) a
- Nix.Value: pattern NVClosure :: forall (w :: Type -> Type) t m a. Comonad w => Params () -> (NValue t w m -> m (Free (NValue' t w m) a)) -> Free (NValue' t w m) a
+ Nix.Value: pattern NVClosure :: forall {w :: Type -> Type} {t} {m} {a}. Comonad w => Params () -> (NValue t w m -> m (Free (NValue' t w m) a)) -> Free (NValue' t w m) a
- Nix.Value: pattern NVList :: forall (w :: Type -> Type) t (m :: Type -> Type) a. Comonad w => [Free (NValue' t w m) a] -> Free (NValue' t w m) a
+ Nix.Value: pattern NVList :: forall {w :: Type -> Type} {t} {m :: Type -> Type} {a}. Comonad w => [Free (NValue' t w m) a] -> Free (NValue' t w m) a
- Nix.Value: pattern NVList' :: forall w t m a. Comonad w => [a] -> NValue' t w m a
+ Nix.Value: pattern NVList' :: forall {w} {t} {m} {a}. Comonad w => [a] -> NValue' t w m a
Files
- ChangeLog.md +44/−1
- benchmarks/Main.hs +1/−1
- benchmarks/ParserBench.hs +2/−2
- hnix.cabal +16/−10
- main/Main.hs +119/−91
- main/Repl.hs +96/−80
- src/Nix.hs +20/−19
- src/Nix/Atoms.hs +3/−2
- src/Nix/Builtins.hs +306/−280
- src/Nix/Cache.hs +6/−6
- src/Nix/Cited.hs +3/−3
- src/Nix/Cited/Basic.hs +9/−13
- src/Nix/Context.hs +1/−1
- src/Nix/Convert.hs +95/−64
- src/Nix/Effects.hs +44/−50
- src/Nix/Effects/Basic.hs +139/−133
- src/Nix/Effects/Derivation.hs +48/−43
- src/Nix/Eval.hs +194/−188
- src/Nix/Exec.hs +75/−64
- src/Nix/Expr/Shorthands.hs +344/−148
- src/Nix/Expr/Strings.hs +9/−9
- src/Nix/Expr/Types.hs +178/−130
- src/Nix/Expr/Types/Annotated.hs +173/−119
- src/Nix/Frames.hs +7/−18
- src/Nix/Fresh.hs +7/−7
- src/Nix/Fresh/Basic.hs +3/−4
- src/Nix/Json.hs +27/−12
- src/Nix/Lint.hs +149/−120
- src/Nix/Normal.hs +10/−13
- src/Nix/Options.hs +9/−7
- src/Nix/Options/Parser.hs +3/−3
- src/Nix/Parser.hs +920/−773
- src/Nix/Pretty.hs +105/−94
- src/Nix/Reduce.hs +157/−151
- src/Nix/Render.hs +72/−71
- src/Nix/Render/Frame.hs +107/−95
- src/Nix/Scope.hs +25/−22
- src/Nix/Standard.hs +64/−41
- src/Nix/String.hs +20/−16
- src/Nix/String/Coerce.hs +11/−14
- src/Nix/TH.hs +66/−49
- src/Nix/Thunk.hs +3/−3
- src/Nix/Thunk/Basic.hs +3/−6
- src/Nix/Type/Assumption.hs +26/−26
- src/Nix/Type/Env.hs +21/−20
- src/Nix/Type/Infer.hs +220/−220
- src/Nix/Type/Type.hs +15/−19
- src/Nix/Unused.hs +82/−0
- src/Nix/Utils.hs +186/−136
- src/Nix/Utils/Fix1.hs +10/−6
- src/Nix/Value.hs +71/−80
- src/Nix/Value/Equal.hs +22/−25
- src/Nix/Var.hs +4/−5
- src/Nix/XML.hs +39/−46
- src/Prelude.hs +20/−0
- tests/EvalTests.hs +399/−258
- tests/Main.hs +28/−27
- tests/NixLanguageTests.hs +150/−98
- tests/ParserTests.hs +662/−317
- tests/PrettyParseTests.hs +118/−91
- tests/PrettyTests.hs +32/−13
- tests/ReduceExprTests.hs +4/−5
- tests/TestCommon.hs +31/−30
ChangeLog.md view
@@ -1,7 +1,50 @@ # ChangeLog -## [(diff)](https://github.com/haskell-nix/hnix/compare/0.13.1...0.14.0#files_bucket) 0.14.0+## [(diff)](https://github.com/haskell-nix/hnix/compare/0.14.0...0.15.0#files_bucket) 0.15.0++For support refere to: https://github.com/haskell-nix/hnix/issues/984++Partial log (for now):++* Breaking:++ * `Nix.Expr.Shorthands`:+ * `inherit{,From}`:+ * dropped second(/third) argument as irrelevant ([report](https://github.com/haskell-nix/hnix/issues/326))+ * bindings to inherit changed type from complex `[NKeyName]` (which is for static & dynamic keys) to `[VarName]` (`VarName` is newtype of `Text`).+ * So examples of use now are: `inherit ["a", "b"]`, `inheritFrom (var "a") ["b", "c"]`+ * `mkAssert`: fixed ([report](https://github.com/haskell-nix/hnix/issues/969)).+ * fx presedence between the operators:+ + ```haskell+ (@@), (@.), (@./), ($==), ($!=), ($<), ($<=), ($>), ($>=), ($&&), ($||), ($->), ($//), ($+), ($-), ($*), ($/), ($++), (==>)+ ```+ + Now these shorthands can be used without sectioning & so represent the Nix expressions one to one.+ + ```haskell+ nix = " a/b // c/def // <g> < def/d"+ hask = mkRelPath "a/b" $// mkRelPath "c/def" $// mkEnvPath "g" $< mkRelPath "def/d"+ ```++* Additional+ * `Nix.Expr.Shorthands`:+ * added:+ * `emptySet`+ * `emptyList`+ * `mkOp{,2}`+ * `mk{,Named,Variadic,General}ParamSet`+ * `mkNeg` - number negation.+ * `@.<|>` for Nix language `s.x or y` expession.+ * entered deprecation:+ * `mkOper{,2}` bacame `mkOp{,2}`.+ * `mkBinop` became `mkOp2`.+ * `mkParaset` supeceeded by `mk{,Named{,Variadic},Variadic,General}ParamSet`.+ * fixed:+ * `mkAssert` was creating `with`, now properly creates `assert`.++## [(diff)](https://github.com/haskell-nix/hnix/compare/0.13.1...0.14.0#files_bucket) 0.14.0 (2021-07-08) * GHC 9.0 support.
benchmarks/Main.hs view
@@ -5,4 +5,4 @@ import qualified ParserBench main :: IO ()-main = defaultMain [ParserBench.benchmarks]+main = defaultMain $ one ParserBench.benchmarks
benchmarks/ParserBench.hs view
@@ -4,8 +4,8 @@ import Criterion -benchFile :: FilePath -> Benchmark-benchFile = bench <*> whnfIO . parseNixFile . ("data/" <>)+benchFile :: Path -> Benchmark+benchFile = bench . coerce <*> whnfIO . parseNixFile . ("data/" <>) benchmarks :: Benchmark benchmarks = bgroup
hnix.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: hnix-version: 0.14.0.8+version: 0.15.0 synopsis: Haskell implementation of the Nix language description: Haskell implementation of the Nix language. category: System, Data, Nix@@ -341,7 +341,9 @@ library exposed-modules:+ Prelude Nix+ Nix.Utils Nix.Atoms Nix.Builtins Nix.Cache@@ -383,7 +385,6 @@ Nix.Type.Env Nix.Type.Infer Nix.Type.Type- Nix.Utils Nix.Utils.Fix1 Nix.Value Nix.Value.Equal@@ -392,13 +393,13 @@ Nix.XML other-modules: Paths_hnix+ Nix.Unused autogen-modules: Paths_hnix hs-source-dirs: src mixins: base hiding (Prelude)- , relude (Relude as Prelude) , relude ghc-options: -Wall@@ -406,7 +407,7 @@ build-depends: aeson >= 1.4.2 && < 1.6 || >= 2.0 && < 2.1 , array >= 0.4 && < 0.6- , base >= 4.12 && < 4.16+ , base >= 4.12 && < 5 , base16-bytestring >= 0.1.1 && < 1.1 , binary >= 0.8.5 && < 0.9 , bytestring >= 0.10.8 && < 0.12@@ -421,7 +422,7 @@ , filepath >= 1.4.2 && < 1.5 , free >= 5.1 && < 5.2 , gitrev >= 1.1.0 && < 1.4- , hashable >= 1.2.5 && < 1.5+ , hashable >= 1.2.5 && < 1.4 , hashing >= 0.1.0 && < 0.2 , hnix-store-core >= 0.5.0 && < 0.6 , hnix-store-remote >= 0.5.0 && < 0.6@@ -463,7 +464,7 @@ , time >= 1.8.0 && < 1.9 || >= 1.9.3 && < 1.10 , transformers >= 0.5.5 && < 0.6 , transformers-base >= 0.4.5 && < 0.5- , unix >= 2.7.2 && < 2.8+ , unix-compat >= 0.4.3 && < 0.6 , unordered-containers >= 0.2.9 && < 0.3 , vector >= 0.12.0 && < 0.13 , xml >= 1.3.14 && < 1.4@@ -477,6 +478,7 @@ , DeriveLift , FlexibleContexts , FlexibleInstances+ , ScopedTypeVariables , StandaloneDeriving , TypeApplications , TypeSynonymInstances@@ -485,6 +487,7 @@ , TupleSections , LambdaCase , BangPatterns+ , ViewPatterns if flag(optimize) default-extensions: ApplicativeDo@@ -531,7 +534,6 @@ , time mixins: base hiding (Prelude)- , relude (Relude as Prelude) , relude default-extensions: OverloadedStrings@@ -543,6 +545,7 @@ , DeriveLift , FlexibleContexts , FlexibleInstances+ , ScopedTypeVariables , StandaloneDeriving , TypeApplications , TypeSynonymInstances@@ -551,6 +554,7 @@ , TupleSections , LambdaCase , BangPatterns+ , ViewPatterns if flag(optimize) default-extensions: ApplicativeDo@@ -577,7 +581,6 @@ TestCommon mixins: base hiding (Prelude)- , relude (Relude as Prelude) , relude hs-source-dirs: tests@@ -610,7 +613,7 @@ , serialise , template-haskell , time- , unix+ , unix-compat default-extensions: OverloadedStrings , DeriveGeneric@@ -621,6 +624,7 @@ , DeriveLift , FlexibleContexts , FlexibleInstances+ , ScopedTypeVariables , StandaloneDeriving , TypeApplications , TypeSynonymInstances@@ -629,6 +633,7 @@ , TupleSections , LambdaCase , BangPatterns+ , ViewPatterns if flag(optimize) default-extensions: ApplicativeDo@@ -647,7 +652,6 @@ benchmarks mixins: base hiding (Prelude)- , relude (Relude as Prelude) , relude ghc-options: -Wall@@ -673,6 +677,7 @@ , DeriveLift , FlexibleContexts , FlexibleInstances+ , ScopedTypeVariables , StandaloneDeriving , TypeApplications , TypeSynonymInstances@@ -681,6 +686,7 @@ , TupleSections , LambdaCase , BangPatterns+ , ViewPatterns if flag(optimize) default-extensions: ApplicativeDo
main/Main.hs view
@@ -1,29 +1,24 @@-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE RecordWildCards #-}+{-# language MultiWayIf #-}+{-# language TypeFamilies #-}+{-# language RecordWildCards #-} module Main ( main ) where -import Nix.Utils+import Relude as Prelude ( force ) import Control.Comonad ( extract )-import qualified Control.DeepSeq as Deep-import qualified Control.Exception as Exc+import qualified Control.Exception as Exception import GHC.Err ( errorWithoutStackTrace ) import Control.Monad.Free import Control.Monad.Ref ( MonadRef(readRef) ) import Control.Monad.Catch-import System.IO ( hPutStrLn, getContents )+import System.IO ( hPutStrLn ) import qualified Data.HashMap.Lazy as M import qualified Data.Map as Map-import Data.Maybe ( fromJust )-import qualified Data.String as String import Data.Time import qualified Data.Text.IO as Text-import Nix+import Text.Show.Pretty ( ppShow )+import Nix hiding ( force ) import Nix.Convert-import qualified Nix.Eval as Eval import Nix.Fresh.Basic import Nix.Json import Nix.Options.Parser@@ -35,11 +30,9 @@ import Nix.Value.Monad import Options.Applicative hiding ( ParserResult(..) ) import Prettyprinter hiding ( list )-import Prettyprinter.Render.Text+import Prettyprinter.Render.Text ( renderIO ) import qualified Repl-import System.FilePath-import qualified Text.Show.Pretty as PS-import Nix.Utils.Fix1 ( Fix1T )+import Nix.Eval main :: IO () main =@@ -50,45 +43,66 @@ main' opts main' :: Options -> IO ()-main' (opts@Options{..}) = runWithBasicEffectsIO opts execContentsFilesOrRepl+main' opts@Options{..} = runWithBasicEffectsIO opts execContentsFilesOrRepl where+ -- 2021-07-15: NOTE: This logic should be weaved stronger through CLI options logic (OptParse-Applicative code)+ -- As this logic is not stated in the CLI documentation, for example. So user has no knowledge of these.+ execContentsFilesOrRepl :: StandardT (StdIdT IO) () execContentsFilesOrRepl =- firstJust- -- The `--read` option: load expression from a serialized file.- [ readFrom <&> \path -> do- let file = addExtension (dropExtension path) "nixc"- process (Just file) =<< liftIO (readCache path)+ fromMaybe+ loadFromCliFilePathList+ ( loadBinaryCacheFile <|>+ loadLiteralExpression <|>+ loadExpressionFromFile+ )+ where+ -- | The base case: read expressions from the last CLI directive (@[FILE]@) listed on the command line.+ loadFromCliFilePathList =+ case filePaths of+ [] -> runRepl+ ["-"] -> readExpressionFromStdin+ _paths -> processSeveralFiles (coerce _paths)+ where+ -- | Fall back to running the REPL+ runRepl = withEmptyNixContext Repl.main - -- The `--expr` option: read expression from the argument string- , expression <&> processText+ readExpressionFromStdin =+ do+ expr <- liftIO Text.getContents+ processExpr expr - -- The `--file` argument: read expressions from the files listed in the argument file- , fromFile <&> \x ->- -- We can start use Text as in the base case, requires changing FilePath -> Text- traverse_ processFile . String.lines =<< liftIO- (case x of- "-" -> getContents- fp -> readFile fp- )- ]- `orElse`- -- The base case: read expressions from the files listed on the command line- case filePaths of- -- With no files, fall back to running the REPL- [] -> withNixContext mempty Repl.main- ["-"] -> processText =<< liftIO Text.getContents- _paths -> traverse_ processFile _paths+ processSeveralFiles :: [Path] -> StandardT (StdIdT IO) ()+ processSeveralFiles = traverse_ processFile+ where+ processFile path = handleResult (pure path) =<< parseNixFileLoc path - firstJust :: [Maybe a] -> Maybe a- firstJust = asum+ -- | The `--read` option: load expression from a serialized file.+ loadBinaryCacheFile =+ (\ (binaryCacheFile :: Path) ->+ do+ let file = replaceExtension binaryCacheFile "nixc"+ processCLIOptions (Just file) =<< liftIO (readCache binaryCacheFile)+ ) <$> readFrom - orElse :: Maybe a -> a -> a- orElse = flip fromMaybe+ -- | The `--expr` option: read expression from the argument string+ loadLiteralExpression = processExpr <$> expression - processText text = handleResult Nothing $ parseNixTextLoc text+ -- | The `--file` argument: read expressions from the files listed in the argument file+ loadExpressionFromFile =+ -- We can start use Text as in the base case, requires changing Path -> Text+ -- But that is a gradual process:+ -- https://github.com/haskell-nix/hnix/issues/912+ (processSeveralFiles . (coerce . toString <$>) . lines <=< liftIO) .+ (\case+ "-" -> Text.getContents+ _fp -> readFile _fp+ ) <$> fromFile - processFile path = handleResult (Just path) =<< parseNixFileLoc path+ processExpr text = handleResult Nothing $ parseNixTextLoc text + withEmptyNixContext = withNixContext mempty++ -- 2021-07-15: NOTE: @handleResult@ & @process@ - have atrocious size & compexity, they need to be decomposed & refactored. handleResult mpath = either (\ err ->@@ -103,18 +117,18 @@ do when check $ do- expr' <- liftIO (reduceExpr mpath expr)+ expr' <- liftIO $ reduceExpr mpath expr either- (\ err -> errorWithoutStackTrace $ "Type error: " <> PS.ppShow err)- (\ ty -> liftIO $ putStrLn $ "Type of expression: " <> PS.ppShow- (fromJust $ Map.lookup "it" (coerce ty :: Map Text [Scheme]))+ (\ err -> errorWithoutStackTrace $ "Type error: " <> ppShow err)+ (\ ty -> liftIO $ putStrLn $ "Type of expression: " <>+ ppShow (maybeToMonoid $ Map.lookup @VarName @[Scheme] "it" $ coerce ty) )- (HM.inferTop mempty [("it", stripAnnotation expr')])+ (HM.inferTop mempty (one ("it", stripAnnotation expr'))) -- liftIO $ putStrLn $ runST $ -- runLintM opts . renderSymbolic =<< lint opts expr - catch (process mpath expr) $+ catch (processCLIOptions mpath expr) $ \case NixException frames -> errorWithoutStackTrace . show =<<@@ -124,30 +138,32 @@ frames when repl $- withNixContext mempty $+ withEmptyNixContext $ bool Repl.main (do- val <- Nix.nixEvalExprLoc mpath expr+ val <- nixEvalExprLoc (coerce mpath) expr Repl.main' $ pure val ) evaluate ) - process mpath expr+ -- 2021-07-15: NOTE: Logic of CLI Option processing is scattered over several functions, needs to be consolicated.+ processCLIOptions :: Maybe Path -> NExprLoc -> StandardT (StdIdT IO) ()+ processCLIOptions mpath expr | evaluate = if- | tracing -> evaluateExpression mpath Nix.nixTracingEvalExprLoc printer expr- | Just path <- reduce -> evaluateExpression mpath (reduction path) printer expr- | not (null arg && null argstr) -> evaluateExpression mpath Nix.nixEvalExprLoc printer expr- | otherwise -> processResult printer =<< Nix.nixEvalExprLoc mpath expr- | xml = fail "Rendering expression trees to XML is not yet implemented"- | json = fail "Rendering expression trees to JSON is not implemented"- | verbose >= DebugInfo = liftIO $ putStr $ PS.ppShow $ stripAnnotation expr- | cache , Just path <- mpath = liftIO $ writeCache (addExtension (dropExtension path) "nixc") expr- | parseOnly = void $ liftIO $ Exc.evaluate $ Deep.force expr+ | tracing -> evaluateExprWithEvaluator nixTracingEvalExprLoc expr+ | Just path <- reduce -> evaluateExprWithEvaluator (reduction path . coerce) expr+ | null arg || null argstr -> evaluateExprWithEvaluator nixEvalExprLoc expr+ | otherwise -> processResult printer <=< nixEvalExprLoc (coerce mpath) $ expr+ | xml = fail "Rendering expression trees to XML is not yet implemented"+ | json = fail "Rendering expression trees to JSON is not implemented"+ | verbose >= DebugInfo = liftIO . putStr . ppShow . stripAnnotation $ expr+ | cache , Just path <- mpath = liftIO . writeCache (replaceExtension path "nixc") $ expr+ | parseOnly = void . liftIO . Exception.evaluate . force $ expr | otherwise =- liftIO $+ liftIO . renderIO stdout . layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4)@@ -155,19 +171,31 @@ . stripAnnotation $ expr where+ evaluateExprWithEvaluator evaluator = evaluateExpression (coerce mpath) evaluator printer+ printer | finder = findAttrs <=< fromValue @(AttrSet (StdValue (StandardT (StdIdT IO))))- | xml = liftIO . Text.putStrLn . stringIgnoreContext . toXML <=< normalForm- -- 2021-05-27: NOTE: With naive fix of the #941- -- This is overall a naive printer implementation, as options should interact/respect one another.- -- A nice question: "Should respect one another to what degree?": Go full combinator way, for which- -- old Nix CLI is nototrious for (and that would mean to reimplement the old Nix CLI),- -- OR: https://github.com/haskell-nix/hnix/issues/172 and have some sane standart/default behaviour for (most) keys.- | json = liftIO . Text.putStrLn . stringIgnoreContext <=< nvalueToJSONNixString <=< normalForm- | strict = liftIO . print . prettyNValue <=< normalForm- | values = liftIO . print . prettyNValueProv <=< removeEffects- | otherwise = liftIO . print . prettyNValue <=< removeEffects+ | otherwise = printer' where+ printer'+ | xml = go (stringIgnoreContext . toXML) normalForm+ -- 2021-05-27: NOTE: With naive fix of the #941+ -- This is overall a naive printer implementation, as options should interact/respect one another.+ -- A nice question: "Should respect one another to what degree?": Go full combinator way, for which+ -- old Nix CLI is nototrious for (and that would mean to reimplement the old Nix CLI),+ -- OR: https://github.com/haskell-nix/hnix/issues/172 and have some sane standart/default behaviour for (most) keys.+ | json = go (stringIgnoreContext . mempty . nvalueToJSONNixString) normalForm+ | strict = go (show . prettyNValue) normalForm+ | values = go (show . prettyNValueProv) removeEffects+ | otherwise = go (show . prettyNValue) removeEffects+ where+ go+ :: (b -> Text)+ -> (a -> StandardT (StdIdT IO) b)+ -> a+ -> StandardT (StdIdT IO) ()+ go g f = liftIO . Text.putStrLn . g <=< f+ findAttrs :: AttrSet (StdValue (StandardT (StdIdT IO))) -> StandardT (StdIdT IO) ()@@ -200,7 +228,7 @@ (pure . pure . Free) nv )- (sortWith fst $ M.toList s)+ (sortWith fst $ M.toList $ M.mapKeys coerce s) traverse_ (\ (k, mv) -> do@@ -212,10 +240,10 @@ liftIO $ Text.putStrLn path when descend $ maybe- pass+ stub (\case- NVSet s' _ -> go (path <> ".") s'- _ -> pass+ NVSet _ s' -> go (path <> ".") s'+ _ -> stub ) mv )@@ -239,10 +267,10 @@ _ -> (True , True ) forceEntry- :: MonadValue a (Fix1T StandardTF (StdIdT IO))+ :: MonadValue a (StandardT (StdIdT IO)) => Text -> a- -> Fix1T StandardTF (StdIdT IO) (Maybe a)+ -> StandardT (StdIdT IO) (Maybe a) forceEntry k v = catch (pure <$> demand v)@@ -259,24 +287,24 @@ pure Nothing ) - reduction path mp x =+ reduction path mpathToContext annExpr = do eres <-- Nix.withNixContext- mp- (Nix.reducingEvalExpr- Eval.evalContent- mp- x+ withNixContext+ mpathToContext+ (reducingEvalExpr+ evalContent+ mpathToContext+ annExpr ) handleReduced path eres handleReduced :: (MonadThrow m, MonadIO m)- => FilePath+ => Path -> (NExprLoc, Either SomeException (NValue t f m)) -> m (NValue t f m)- handleReduced path (expr', eres) =+ handleReduced (coerce -> path) (expr', eres) = do liftIO $ do
main/Repl.hs view
@@ -7,22 +7,19 @@ directory for more details. -} -{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language MultiWayIf #-} module Repl ( main , main' ) where -import Nix hiding ( exec- , try- )+import Prelude hiding ( state )+import Nix hiding ( exec ) import Nix.Scope-import Nix.Utils import Nix.Value.Monad ( demand ) -import qualified Data.HashMap.Lazy+import qualified Data.HashMap.Lazy as M import Data.Char ( isSpace ) import Data.List ( dropWhileEnd ) import qualified Data.Text as Text@@ -71,7 +68,7 @@ evalStateT (evalRepl banner- (cmd . toText)+ (cmd . fromString) options (pure commandPrefix) (pure "paste")@@ -99,28 +96,28 @@ rcFile = do- f <- liftIO $ Text.readFile ".hnixrc" `catch` handleMissing+ f <- liftIO $ readFile ".hnixrc" `catch` handleMissing traverse_ (\case (prefixedCommand : xs) | Text.head prefixedCommand == commandPrefix -> do let- arguments = Text.unwords xs+ arguments = unwords xs command = Text.tail prefixedCommand optMatcher command options arguments- x -> cmd $ Text.unwords x+ x -> cmd $ unwords x )- (Text.words <$> lines f)+ (words <$> lines f) handleMissing e- | Error.isDoesNotExistError e = pure ""- | otherwise = throwIO e+ | Error.isDoesNotExistError e = pure mempty+ | otherwise = throwM e -- Replicated and slightly adjusted `optMatcher` from `System.Console.Repline` -- which doesn't export it.- -- * @MonadIO m@ instead of @MonadHaskeline m@- -- * @putStrLn@ instead of @outputStrLn@+ -- * @MonadIO m@ instead of @MonadHaskeline m@+ -- * @putStrLn@ instead of @outputStrLn@ optMatcher :: MonadIO m => Text -> Console.Options m@@ -128,16 +125,16 @@ -> m () optMatcher s [] _ = liftIO $ Text.putStrLn $ "No such command :" <> s optMatcher s ((x, m) : xs) args- | s `Text.isPrefixOf` toText x = m $ toString args+ | s `Text.isPrefixOf` fromString x = m $ toString args | otherwise = optMatcher s xs args -- * Types data IState t f m = IState- { replIt :: Maybe NExprLoc -- ^ Last expression entered- , replCtx :: AttrSet (NValue t f m) -- ^ Value environment- , replCfg :: ReplConfig -- ^ REPL configuration+ { replIt :: Maybe NExprLoc -- ^ Last expression entered+ , replCtx :: Scope (NValue t f m) -- ^ Scope. Value environment.+ , replCfg :: ReplConfig -- ^ REPL configuration } deriving (Eq, Show) data ReplConfig = ReplConfig@@ -159,14 +156,17 @@ builtins <- evalText "builtins" - opts :: Nix.Options <- asks (view hasLens)+ let+ scope = coerce $+ M.fromList $+ ("builtins", builtins) : fmap ("input",) (maybeToList mIni) + opts :: Nix.Options <- asks $ view hasLens+ pure $ IState Nothing- (Data.HashMap.Lazy.fromList $- ("builtins", builtins) : fmap ("input",) (maybeToList mIni)- )+ scope defReplConfig { cfgStrict = strict opts , cfgValues = values opts@@ -192,9 +192,9 @@ -> Repl e t f m (Maybe (NValue t f m)) exec update source = do -- Get the current interpreter state- st <- get+ state <- get - when (cfgDebug $ replCfg st) $ liftIO $ print st+ when (cfgDebug $ replCfg state) $ liftIO $ print state -- Parser ( returns AST as `NExprLoc` ) case parseExprOrBinding source of@@ -211,7 +211,7 @@ -- let tyctx' = inferTop mempty [("repl", stripAnnotation expr)] -- liftIO $ print tyctx' - mVal <- lift $ lift $ try $ pushScope (replCtx st) (evalExprLoc expr)+ mVal <- lift $ lift $ try $ pushScope (replCtx state) (evalExprLoc expr) either (\ (NixException frames) -> do@@ -221,12 +221,12 @@ -- Update the interpreter state when (update && isBinding) $ do -- Set `replIt` to last entered expression- put st { replIt = pure expr }+ put state { replIt = pure expr } -- If the result value is a set, update our context with it case val of- NVSet xs _ -> put st { replCtx = xs <> replCtx st }- _ -> pass+ NVSet _ (coerce -> scope) -> put state { replCtx = scope <> replCtx state }+ _ -> stub pure $ pure val )@@ -248,7 +248,7 @@ (parseNixTextLoc i) toAttrSet i =- "{" <> i <> bool ";" mempty (Text.isSuffixOf ";" i) <> "}"+ "{" <> i <> whenFalse ";" (Text.isSuffixOf ";" i) <> "}" cmd :: (MonadNix e t f m, MonadIO m)@@ -258,7 +258,7 @@ do mVal <- exec True source maybe- pass+ stub printValue mVal @@ -267,11 +267,15 @@ -> Repl e t f m () printValue val = do cfg <- replCfg <$> get+ let+ g :: MonadIO m => Doc ann0 -> m ()+ g = liftIO . print+ lift $ lift $ (if- | cfgStrict cfg -> liftIO . print . prettyNValue <=< normalForm- | cfgValues cfg -> liftIO . print . prettyNValueProv <=< removeEffects- | otherwise -> liftIO . print . prettyNValue <=< removeEffects+ | cfgStrict cfg -> g . prettyNValue <=< normalForm+ | cfgValues cfg -> g . prettyNValueProv <=< removeEffects+ | otherwise -> g . prettyNValue <=< removeEffects ) val @@ -281,26 +285,31 @@ browse :: (MonadNix e t f m, MonadIO m) => Text -> Repl e t f m ()-browse _ = do- st <- get- for_ (Data.HashMap.Lazy.toList $ replCtx st) $ \(k, v) -> do- liftIO $ Text.putStr $ k <> " = "- printValue v+browse _ =+ do+ state <- get+ traverse_+ (\(k, v) ->+ do+ liftIO $ Text.putStr $ coerce k <> " = "+ printValue v+ )+ (M.toList $ coerce $ replCtx state) -- | @:load@ command load :: (MonadNix e t f m, MonadIO m) -- This one does I String -> O String pretty fast, it is ugly to double marshall here.- => String+ => Path -> Repl e t f m ()-load args =+load path = do- contents <- liftIO $- Text.readFile $- trim args+ contents <- liftIO $ readFile $+ trim path void $ exec True contents where- trim = dropWhileEnd isSpace . dropWhile isSpace+ trim :: Path -> Path+ trim = coerce . dropWhileEnd isSpace . dropWhile isSpace . coerce -- | @:type@ command typeof@@ -308,12 +317,12 @@ => Text -> Repl e t f m () typeof args = do- st <- get+ state <- get mVal <- maybe (exec False line) (pure . pure)- (Data.HashMap.Lazy.lookup line (replCtx st))+ (M.lookup (coerce line) (coerce $ replCtx state)) traverse_ printValueType mVal @@ -332,12 +341,14 @@ -- | @:set@ command setConfig :: (MonadNix e t f m, MonadIO m) => Text -> Repl e t f m () setConfig args =- case Text.words args of- [] -> liftIO $ Text.putStrLn "No option to set specified"- (x:_xs) ->+ list+ (liftIO $ Text.putStrLn "No option to set specified")+ (\ (x:_xs) -> case filter ((==x) . helpSetOptionName) helpSetOptions of [opt] -> modify (\s -> s { replCfg = helpSetOptionFunction opt (replCfg s) }) _ -> liftIO $ Text.putStrLn "No such option"+ )+ $ words args -- * Interactive Shell@@ -345,8 +356,7 @@ -- | Prefix tab completer defaultMatcher :: MonadIO m => [(String, CompletionFunc m)] defaultMatcher =- [ (":load", Console.fileCompleter)- ]+ one (":load", Console.fileCompleter) completion :: (MonadNix e t f m, MonadIO m)@@ -381,9 +391,9 @@ listFiles word -- Attributes of sets in REPL context- | var : subFields <- Text.split (== '.') (toText word) , not $ null subFields =+ | var : subFields <- Text.split (== '.') (fromString word) , not $ null subFields = do- s <- get+ state <- get maybe stub (\ binding ->@@ -396,18 +406,24 @@ candidates ) )- (Data.HashMap.Lazy.lookup var (replCtx s))+ (M.lookup (coerce var) $ coerce $ replCtx state) -- Builtins, context variables | otherwise = do- s <- get- let contextKeys = Data.HashMap.Lazy.keys (replCtx s)- (Just (NVSet builtins _)) = Data.HashMap.Lazy.lookup "builtins" (replCtx s)- shortBuiltins = Data.HashMap.Lazy.keys builtins+ state <- get+ let+ scopeHashMap :: HashMap VarName (NValue t f m)+ scopeHashMap = coerce $ replCtx state+ contextKeys :: [VarName]+ contextKeys = M.keys scopeHashMap+ builtins :: AttrSet (NValue t f m)+ (Just (NVSet _ builtins)) = M.lookup "builtins" scopeHashMap+ shortBuiltins :: [VarName]+ shortBuiltins = M.keys builtins pure $ listCompletion $ toString <$>- ["__includes"]+ one "__includes" <> contextKeys <> shortBuiltins @@ -423,7 +439,7 @@ -> m [Text] algebraicComplete subFields val = let- keys = fmap ("." <>) . Data.HashMap.Lazy.keys+ keys = fmap ("." <>) . M.keys withMap m = case subFields of@@ -437,10 +453,10 @@ (("." <> f) <>) . algebraicComplete fs <=< demand )- (Data.HashMap.Lazy.lookup f m)+ (M.lookup (coerce f) m) in case val of- NVSet xs _ -> withMap xs+ NVSet _ xs -> withMap (M.mapKeys coerce xs) _ -> stub -- | HelpOption inspired by Dhall Repl@@ -458,44 +474,44 @@ helpOptions = [ HelpOption "help"- ""+ mempty "Print help text"- (help helpOptions . toText)+ (help helpOptions . fromString) , HelpOption "paste"- ""+ mempty "Enter multi-line mode" (error "Unreachable") , HelpOption "load" "FILENAME" "Load .nix file into scope"- load+ (load . fromString) , HelpOption "browse"- ""+ mempty "Browse bindings in interpreter context"- (browse . toText)+ (browse . fromString) , HelpOption "type" "EXPRESSION" "Evaluate expression or binding from context and print the type of the result value"- (typeof . toText)+ (typeof . fromString) , HelpOption "quit"- ""+ mempty "Quit interpreter" quit , HelpOption "set"- ""+ mempty ("Set REPL option" <> Prettyprinter.line <> "Available options:" <> Prettyprinter.line <> renderSetOptions helpSetOptions )- (setConfig . toText)+ (setConfig . fromString) ] -- | Options for :set@@ -510,32 +526,32 @@ helpSetOptions = [ HelpSetOption "strict"- ""+ mempty "Enable strict evaluation of REPL expressions" (\x -> x { cfgStrict = True}) , HelpSetOption "lazy"- ""+ mempty "Disable strict evaluation of REPL expressions" (\x -> x { cfgStrict = False}) , HelpSetOption "values"- ""+ mempty "Enable printing of value provenance information" (\x -> x { cfgValues = True}) , HelpSetOption "novalues"- ""+ mempty "Disable printing of value provenance information" (\x -> x { cfgValues = False}) , HelpSetOption "debug"- ""+ mempty "Enable printing of REPL debug information" (\x -> x { cfgDebug = True}) , HelpSetOption "nodebug"- ""+ mempty "Disable REPL debugging" (\x -> x { cfgDebug = False}) ]
src/Nix.hs view
@@ -1,10 +1,10 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-} module Nix ( module Nix.Cache , module Nix.Exec- , module Nix.Expr+ , module Nix.Expr.Types+ , module Nix.Expr.Shorthands+ , module Nix.Expr.Types.Annotated , module Nix.Frames , module Nix.Render.Frame , module Nix.Normal@@ -35,7 +35,9 @@ import Nix.Cache import qualified Nix.Eval as Eval import Nix.Exec-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Shorthands+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.String import Nix.Normal@@ -45,7 +47,6 @@ import Nix.Reduce import Nix.Render.Frame import Nix.Thunk-import Nix.Utils import Nix.Value import Nix.Value.Monad import Nix.XML@@ -57,7 +58,7 @@ :: (MonadNix e t f m, Has e Options, Functor g) => Transform g (m a) -> Alg g (m a)- -> Maybe FilePath+ -> Maybe Path -> Fix g -> m a nixEval transform alg mpath = withNixContext mpath . adi transform alg@@ -65,7 +66,7 @@ -- | Evaluate a nix expression in the default context nixEvalExpr :: (MonadNix e t f m, Has e Options)- => Maybe FilePath+ => Maybe Path -> NExpr -> m (NValue t f m) nixEvalExpr = nixEval id Eval.eval@@ -74,7 +75,7 @@ nixEvalExprLoc :: forall e t f m . (MonadNix e t f m, Has e Options)- => Maybe FilePath+ => Maybe Path -> NExprLoc -> m (NValue t f m) nixEvalExprLoc =@@ -89,22 +90,22 @@ -- context. nixTracingEvalExprLoc :: (MonadNix e t f m, Has e Options, MonadIO m, Alternative m)- => Maybe FilePath+ => Maybe Path -> NExprLoc -> m (NValue t f m) nixTracingEvalExprLoc mpath = withNixContext mpath . evalExprLoc evaluateExpression :: (MonadNix e t f m, Has e Options)- => Maybe FilePath- -> (Maybe FilePath -> NExprLoc -> m (NValue t f m))+ => Maybe Path+ -> (Maybe Path -> NExprLoc -> m (NValue t f m)) -> (NValue t f m -> m a) -> NExprLoc -> m a evaluateExpression mpath evaluator handler expr = do opts :: Options <- asks $ view hasLens- args <-+ (coerce -> args) <- (traverse . traverse) eval' $ (second parseArg <$> arg opts)@@ -137,23 +138,23 @@ opts :: Options <- asks $ view hasLens maybe (h val)- (\ (Text.splitOn "." -> keys) -> processKeys keys val)+ (\ (coerce . Text.splitOn "." -> keys) -> processKeys keys val) (attr opts) where- processKeys :: [Text] -> NValue t f m -> m a+ processKeys :: [VarName] -> NValue t f m -> m a processKeys kys v = list (h v)- (\ (k : ks) ->+ (\ ((k : ks) :: [VarName]) -> do v' <- demand v case (k, v') of- (Text.decimal -> Right (n,""), NVList xs) -> processKeys ks $ xs !! n- (_, NVSet xs _) ->+ (Text.decimal . coerce -> Right (n,""), NVList xs) -> processKeys ks $ xs !! n+ (_, NVSet _ xs) -> maybe- (errorWithoutStackTrace $ toString $ "Set does not contain key '" <> k <> "'")+ (errorWithoutStackTrace $ "Set does not contain key ''" <> show k <> "''.") (processKeys ks) (M.lookup k xs)- (_, _) -> errorWithoutStackTrace $ toString $ "Expected a set or list for selector '" <> k <> "', but got: " <> show v+ (_, _) -> errorWithoutStackTrace $ "Expected a set or list for selector '" <> show k <> "', but got: " <> show v ) kys
src/Nix/Atoms.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}+{-# language CPP #-}+{-# language DeriveAnyClass #-} module Nix.Atoms where @@ -11,6 +11,7 @@ import Data.Aeson.Types ( FromJSON , ToJSON )+-- 2021-08-01: NOTE: Check the order efficience of NAtom constructors. -- | Atoms are values that evaluate to themselves. -- In other words - this is a constructors that are literals in Nix.
src/Nix/Builtins.hs view
@@ -1,20 +1,17 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE PackageImports #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@+{-# language CPP #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language FunctionalDependencies #-}+{-# language KindSignatures #-}+{-# language MonoLocalBinds #-}+{-# language MultiWayIf #-}+{-# language PartialTypeSignatures #-}+{-# language QuasiQuotes #-}+{-# language TemplateHaskell #-}+{-# language UndecidableInstances #-}+{-# language PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@ -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -fno-warn-name-shadowing #-} -- | Code that implements Nix builtins. Lists the functions that are built into the Nix expression evaluator. Some built-ins (aka `derivation`), are always in the scope, so they can be accessed by the name. To keap the namespace clean, most built-ins are inside the `builtins` scope - a set that contains all what is a built-in. module Nix.Builtins@@ -24,8 +21,7 @@ where -import Prelude hiding ( traceM )-import Nix.Utils+import GHC.Exception ( ErrorCall(ErrorCall) ) import Control.Comonad ( Comonad ) import Control.Monad ( foldM ) import Control.Monad.Catch ( MonadCatch(catch) )@@ -53,9 +49,9 @@ import Data.Scientific import qualified Data.Set as S import qualified Data.Text as Text-import qualified Data.Text.Lazy as LazyText+import Data.Text.Read ( decimal ) import qualified Data.Text.Lazy.Builder as Builder-import Data.These ( fromThese )+import Data.These ( fromThese, These ) import qualified Data.Time.Clock.POSIX as Time import qualified Data.Vector as V import NeatInterpolation ( text )@@ -65,7 +61,6 @@ import Nix.Effects.Basic ( fetchTarball ) import Nix.Exec import Nix.Expr.Types-import Nix.Expr.Types.Annotated import qualified Nix.Eval as Eval import Nix.Frames import Nix.Json@@ -81,11 +76,11 @@ import Nix.Value.Monad import Nix.XML import System.Nix.Base32 as Base32-import System.FilePath-import System.Posix.Files ( isRegularFile+import System.PosixCompat.Files ( isRegularFile , isDirectory , isSymbolicLink )+import qualified Text.Show import Text.Regex.TDFA ( Regex , makeRegex , matchOnceText@@ -101,13 +96,13 @@ -- ** Nix Builtins Haskell type level -newtype Prim m a = Prim { runPrim :: m a }+newtype Prim m a = Prim (m a) data BuiltinType = Normal | TopLevel data Builtin v = Builtin { _kind :: BuiltinType- , mapping :: (Text, v)+ , mapping :: (VarName, v) } -- *** @class ToBuiltin@ and its instances@@ -121,7 +116,7 @@ , ToValue a m (NValue t f m) ) => ToBuiltin t f m (Prim m a) where- toBuiltin _ p = toValue =<< runPrim p+ toBuiltin _ p = toValue @a @m =<< coerce p instance ( MonadNix e t f m@@ -130,7 +125,7 @@ ) => ToBuiltin t f m (a -> b) where toBuiltin name f =- pure $ nvBuiltin name $ toBuiltin name . f <=< fromValue . Deeper+ pure $ nvBuiltin (coerce name) $ toBuiltin name . f <=< fromValue . Deeper -- *** @WValue@ closure wrapper to have @Ord@ @@ -174,11 +169,28 @@ -> NValue t f m mkNVBool = nvConstant . NBool +data NixPathEntryType+ = PathEntryPath+ | PathEntryURI+ deriving (Show, Eq)++-- | @NIX_PATH@ is colon-separated, but can also contain URLs, which have a colon+-- (i.e. @https://...@)+uriAwareSplit :: Text -> [(Text, NixPathEntryType)]+uriAwareSplit txt =+ case Text.break (== ':') txt of+ (e1, e2)+ | Text.null e2 -> one (e1, PathEntryPath)+ | "://" `Text.isPrefixOf` e2 ->+ let ((suffix, _) : path) = uriAwareSplit (Text.drop 3 e2) in+ (e1 <> "://" <> suffix, PathEntryURI) : path+ | otherwise -> (e1, PathEntryPath) : uriAwareSplit (Text.drop 1 e2)+ foldNixPath :: forall e t f m r . MonadNix e t f m => r- -> (FilePath -> Maybe Text -> NixPathEntryType -> r -> m r)+ -> (Path -> Maybe Text -> NixPathEntryType -> r -> m r) -> m r foldNixPath z f = do@@ -193,36 +205,36 @@ dataDir <- maybe getDataDir- (pure . toString)+ (pure . coerce . toString) mDataDir foldrM go z $ (fromInclude . stringIgnoreContext <$> dirs)- <> maybe- mempty- uriAwareSplit- mPath- <> [ fromInclude $ "nix=" <> toText dataDir <> "/nix/corepkgs" ]+ <> uriAwareSplit `whenJust` mPath+ <> one (fromInclude $ "nix=" <> fromString (coerce dataDir) <> "/nix/corepkgs") where - fromInclude x = (x, ) $- bool- PathEntryPath- PathEntryURI- ("://" `Text.isInfixOf` x)+ fromInclude :: Text -> (Text, NixPathEntryType)+ fromInclude x =+ (x, ) $+ bool+ PathEntryPath+ PathEntryURI+ ("://" `Text.isInfixOf` x) + go :: (Text, NixPathEntryType) -> r -> m r go (x, ty) rest = case Text.splitOn "=" x of- [p] -> f (toString p) mempty ty rest- [n, p] -> f (toString p) (pure n) ty rest+ [p] -> f (coerce $ toString p) mempty ty rest+ [n, p] -> f (coerce $ toString p) (pure n) ty rest _ -> throwError $ ErrorCall $ "Unexpected entry in NIX_PATH: " <> show x -attrsetGet :: MonadNix e t f m => Text -> AttrSet (NValue t f m) -> m (NValue t f m)+attrsetGet :: MonadNix e t f m => VarName -> AttrSet (NValue t f m) -> m (NValue t f m) attrsetGet k s = maybe- (throwError $ ErrorCall $ "Attribute '" <> toString k <> "' required")+ (throwError $ ErrorCall $ toString @Text $ "Attribute '" <> coerce k <> "' required") pure (M.lookup k s) @@ -230,77 +242,82 @@ = VersionComponentPre -- ^ The string "pre" | VersionComponentString !Text -- ^ A string other than "pre" | VersionComponentNumber !Integer -- ^ A number- deriving (Show, Read, Eq, Ord)--versionComponentToString :: VersionComponent -> Text-versionComponentToString =- \case- VersionComponentPre -> "pre"- VersionComponentString s -> s- VersionComponentNumber n -> show n+ deriving (Read, Eq, Ord) --- | Based on https://github.com/NixOS/nix/blob/4ee4fda521137fed6af0446948b3877e0c5db803/src/libexpr/names.cc#L44-versionComponentSeparators :: String-versionComponentSeparators = ".-"+instance Show VersionComponent where+ show =+ \case+ VersionComponentPre -> "pre"+ VersionComponentString s -> show s+ VersionComponentNumber n -> show n splitVersion :: Text -> [VersionComponent] splitVersion s =- case Text.uncons s of- Nothing -> mempty- Just (h, t)+ whenJust+ (\ (x, xs) -> if+ | isRight eDigitsPart ->+ either+ (\ e -> error $ "splitVersion: did hit impossible: '" <> toText e <> "' while parsing '" <> s <> "'.")+ (\ res ->+ one (VersionComponentNumber $ fst res)+ <> splitVersion (snd res)+ )+ eDigitsPart - | h `elem` versionComponentSeparators -> splitVersion t+ | x `elem` separators -> splitVersion xs - | isDigit h ->- let (digits, rest) = Text.span isDigit s- in- VersionComponentNumber- (fromMaybe (error $ "splitVersion: couldn't parse " <> show digits) $ readMaybe $ toString digits) : splitVersion rest+ | otherwise -> one charsPart <> splitVersion rest2+ )+ (Text.uncons s)+ where+ -- | Based on https://github.com/NixOS/nix/blob/4ee4fda521137fed6af0446948b3877e0c5db803/src/libexpr/names.cc#L44+ separators :: String+ separators = ".-" - | otherwise ->- let- (chars, rest) =- Text.span- (\c -> not $ isDigit c || c `elem` versionComponentSeparators)- s- thisComponent =- case chars of- "pre" -> VersionComponentPre- x -> VersionComponentString x- in- thisComponent : splitVersion rest+ eDigitsPart :: Either String (Integer, Text)+ eDigitsPart = decimal @Integer $ s + (charsSpan, rest2) =+ Text.span+ (\c -> not $ isDigit c || c `elem` separators)+ s++ charsPart :: VersionComponent+ charsPart =+ case charsSpan of+ "pre" -> VersionComponentPre+ xs' -> VersionComponentString xs'++ compareVersions :: Text -> Text -> Ordering compareVersions s1 s2 =- mconcat $- alignWith- f- (splitVersion s1)- (splitVersion s2)+ fold $ (alignWith cmp `on` splitVersion) s1 s2 where- z = VersionComponentString ""- f = uncurry compare . fromThese z z+ cmp :: These VersionComponent VersionComponent -> Ordering+ cmp = uncurry compare . join fromThese (VersionComponentString mempty) splitDrvName :: Text -> (Text, Text) splitDrvName s =- let- sep = "-"- pieces = Text.splitOn sep s- isFirstVersionPiece p =- case Text.uncons p of- Just (h, _) -> isDigit h- _ -> False- -- Like 'break', but always puts the first item into the first result- -- list- breakAfterFirstItem :: (a -> Bool) -> [a] -> ([a], [a])- breakAfterFirstItem f =- list- (mempty, mempty)- (\ (h : t) -> let (a, b) = break f t in (h : a, b))- (namePieces, versionPieces) =- breakAfterFirstItem isFirstVersionPiece pieces- in- (Text.intercalate sep namePieces, Text.intercalate sep versionPieces)+ both (Text.intercalate sep) (namePieces, versionPieces)+ where+ sep = "-"+ pieces :: [Text]+ pieces = Text.splitOn sep s+ isFirstVersionPiece :: Text -> Bool+ isFirstVersionPiece p =+ maybe+ False+ (isDigit . fst)+ (Text.uncons p)+ -- Like 'break', but always puts the first item into the first result+ -- list+ breakAfterFirstItem :: (a -> Bool) -> [a] -> ([a], [a])+ breakAfterFirstItem f =+ list+ mempty+ (\ (h : t) -> let (a, b) = break f t in (h : a, b))+ (namePieces, versionPieces) =+ breakAfterFirstItem isFirstVersionPiece pieces splitMatches :: forall e t f m@@ -309,7 +326,7 @@ -> [[(ByteString, (Int, Int))]] -> ByteString -> [NValue t f m]-splitMatches _ [] haystack = [thunkStr haystack]+splitMatches _ [] haystack = one $ thunkStr haystack splitMatches _ ([] : _) _ = fail "Fail in splitMatches: this should never happen!" splitMatches numDropped (((_, (start, len)) : captures) : mts) haystack =@@ -319,7 +336,9 @@ where relStart = max 0 start - numDropped (before, rest) = B.splitAt relStart haystack+ caps :: NValue t f m caps = nvList (f <$> captures)+ f :: (ByteString, (Int, b)) -> NValue t f m f (a, (s, _)) = bool nvNull@@ -334,23 +353,18 @@ . (MonadNix e t f m, FromValue a m (NValue t f m)) => NValue t f m -> m (NValue t f m)-hasKind nv =- do- v <- fromValueMay nv-- toValue $- case v of- Just (_ :: a) -> True- _ -> False+hasKind =+ inHaskMay+ (isJust @a) -absolutePathFromValue :: MonadNix e t f m => NValue t f m -> m FilePath+absolutePathFromValue :: MonadNix e t f m => NValue t f m -> m Path absolutePathFromValue = \case NVStr ns -> do let- path = toString $ stringIgnoreContext ns+ path = coerce . toString $ stringIgnoreContext ns unless (isAbsolute path) $ throwError $ ErrorCall $ "string " <> show path <> " doesn't represent an absolute path" pure path@@ -368,7 +382,7 @@ instance Convertible e t f m => ToValue FileType m (NValue t f m) where toValue =- toValue . makeNixStringWithoutContext .+ toValue . mkNixStringWithoutContext . \case FileTypeRegular -> "regular" :: Text FileTypeDirectory -> "directory"@@ -411,29 +425,26 @@ [|| expr ||] ) -nixPathNix :: MonadNix e t f m => m (NValue t f m)+nixPathNix :: forall e t f m . MonadNix e t f m => m (NValue t f m) nixPathNix = fmap nvList- (foldNixPath mempty $- \p mn ty rest ->- pure $- pure- (nvSet- mempty- (M.fromList- [case ty of- PathEntryPath -> ("path", nvPath p)- PathEntryURI -> ( "uri", mkNvStr p)+ $ foldNixPath mempty $+ \p mn ty rest ->+ pure $+ pure+ (nvSet+ mempty+ (M.fromList+ [case ty of+ PathEntryPath -> ("path", nvPath p)+ PathEntryURI -> ( "uri", nvStrWithoutContext $ fromString $ coerce p) - , ( "prefix", mkNvStr $ toString $ fromMaybe "" mn)- ]+ , ( "prefix", nvStrWithoutContext $ maybeToMonoid mn)+ ]+ ) )- )- <> rest- )- where- mkNvStr = nvStrWithoutContext . toText+ <> rest toStringNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) toStringNix = toValue <=< coerceToString callFunc DontCopyToStore CoerceAny@@ -446,13 +457,13 @@ -> m (NValue t f m) hasAttrNix x y = do- key <- fromStringNoContext =<< fromValue x- (aset, _) <- fromValue @(AttrSet (NValue t f m), AttrSet SourcePos) y+ (coerce -> key) <- fromStringNoContext =<< fromValue x+ (aset, _) <- fromValue @(AttrSet (NValue t f m), PositionSet) y toValue $ M.member key aset hasContextNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m)-hasContextNix = toValue . stringHasContext <=< fromValue+hasContextNix = inHask stringHasContext getAttrNix :: forall e t f m@@ -462,8 +473,8 @@ -> m (NValue t f m) getAttrNix x y = do- key <- fromStringNoContext =<< fromValue x- (aset, _) <- fromValue @(AttrSet (NValue t f m), AttrSet SourcePos) y+ (coerce -> key) <- fromStringNoContext =<< fromValue x+ (aset, _) <- fromValue @(AttrSet (NValue t f m), PositionSet) y attrsetGet key aset @@ -479,18 +490,18 @@ y <- demand nvY case (x, y) of- (NVStr ns, NVSet _ apos) ->+ (NVStr ns, NVSet apos _) -> maybe (pure nvNull) toValue- (M.lookup (stringIgnoreContext ns) apos)+ (M.lookup @VarName (coerce $ stringIgnoreContext ns) apos) _xy -> throwError $ ErrorCall $ "Invalid types for builtins.unsafeGetAttrPosNix: " <> show _xy -- This function is a bit special in that it doesn't care about the contents -- of the list. lengthNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m)-lengthNix = toValue . (length :: [NValue t f m] -> Int) <=< fromValue+lengthNix = inHask (length :: [NValue t f m] -> Int) addNix :: MonadNix e t f m@@ -587,7 +598,7 @@ headNix = maybe (throwError $ ErrorCall "builtins.head: empty list")- (pure)+ pure . viaNonEmpty head <=< fromValue @[NValue t f m] tailNix :: forall e t f m. MonadNix e t f m => NValue t f m -> m (NValue t f m)@@ -603,7 +614,7 @@ version <- fromStringNoContext =<< fromValue v pure $ nvList $- nvStrWithoutContext . versionComponentToString <$>+ nvStrWithoutContext . show <$> splitVersion version compareVersionsNix@@ -639,7 +650,7 @@ toValue @(AttrSet (NValue t f m)) $ M.fromList- [ ( "name" :: Text+ [ ( "name" :: VarName , mkNVStr name ) , ( "version"@@ -671,7 +682,7 @@ mkMatch t = bool (toValue ()) -- Shorthand for Null- (toValue $ makeNixStringWithoutContext t)+ (toValue $ mkNixStringWithoutContext t) (not $ Text.null t) case matchOnceText re s of@@ -682,8 +693,8 @@ traverse mkMatch (case submatches of- [] -> []- [a] -> [a]+ [] -> mempty+ [a] -> one a _:xs -> xs -- return only the matched groups, drop the full string ) _ -> pure nvNull@@ -726,8 +737,10 @@ attrNamesNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m) attrNamesNix =- (fmap (coerce :: CoerceDeeperToNValue t f m) . toValue . fmap makeNixStringWithoutContext . sort . M.keys)- <=< fromValue @(AttrSet (NValue t f m))+ coersion . inHask @(AttrSet (NValue t f m))+ (fmap (mkNixStringWithoutContext . coerce) . sort . M.keys)+ where+ coersion = fmap (coerce :: CoerceDeeperToNValue t f m) attrValuesNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m)@@ -737,7 +750,7 @@ toValue $ snd <$> sortOn- (fst @Text @(NValue t f m))+ (fst @VarName @(NValue t f m)) (M.toList attrs) mapNix@@ -747,13 +760,13 @@ -> NValue t f m -> m (NValue t f m) mapNix f =- toValue <=<- traverse- (defer @(NValue t f m)+ inHaskM @[NValue t f m]+ (traverse+ (defer . withFrame Debug (ErrorCall "While applying f in map:\n") . callFunc f )- <=< fromValue @[NValue t f m]+ ) mapAttrsNix :: forall e t f m@@ -770,7 +783,7 @@ applyFunToKeyVal (key, val) = do- runFunForKey <- callFunc f $ nvStrWithoutContext key+ runFunForKey <- callFunc f $ nvStrWithoutContext (coerce key) callFunc runFunForKey val newVals <-@@ -787,10 +800,11 @@ -> NValue t f m -> m (NValue t f m) filterNix f =- toValue <=<- filterM- (fromValue <=< callFunc f)- <=< fromValue+ inHaskM+ (filterM fh)+ where+ fh :: NValue t f m -> m Bool+ fh = fromValue <=< callFunc f catAttrsNix :: forall e t f m@@ -805,7 +819,7 @@ nvList . catMaybes <$> traverse- (fmap (M.lookup n) . fromValue <=< demand)+ (fmap (M.lookup @VarName $ coerce n) . fromValue <=< demand) l baseNameOfNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m)@@ -815,7 +829,7 @@ pure $ nvStr $ modifyNixContents- (toText . takeFileName . toString)+ (fromString . coerce takeFileName . toString) ns bitAndNix@@ -829,7 +843,7 @@ a <- fromValue @Integer x b <- fromValue @Integer y - toValue (a .&. b)+ toValue $ a .&. b bitOrNix :: forall e t f m@@ -842,7 +856,7 @@ a <- fromValue @Integer x b <- fromValue @Integer y - toValue (a .|. b)+ toValue $ a .|. b bitXorNix :: forall e t f m@@ -855,7 +869,7 @@ a <- fromValue @Integer x b <- fromValue @Integer y - toValue (a `xor` b)+ toValue $ a `xor` b builtinsBuiltinNix :: forall e t f m@@ -869,16 +883,15 @@ dir <- demand nvdir case dir of- NVStr ns -> pure $ nvStr $ modifyNixContents (toText . takeDirectory . toString) ns+ NVStr ns -> pure $ nvStr $ modifyNixContents (fromString . coerce takeDirectory . toString) ns NVPath path -> pure $ nvPath $ takeDirectory path v -> throwError $ ErrorCall $ "dirOf: expected string or path, got " <> show v -- jww (2018-04-28): This should only be a string argument, and not coerced? unsafeDiscardStringContextNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m)-unsafeDiscardStringContextNix mnv = do- ns <- fromValue mnv- toValue $ makeNixStringWithoutContext $ stringIgnoreContext ns+unsafeDiscardStringContextNix =+ inHask (mkNixStringWithoutContext . stringIgnoreContext) -- | Evaluate `a` to WHNF to collect its topmost effect. seqNix@@ -902,15 +915,18 @@ => NValue t f m -> NValue t f m -> m (NValue t f m)-elemNix x = toValue <=< anyMNix (valueEqM x) <=< fromValue+elemNix x = inHaskM (anyMNix $ valueEqM x) where anyMNix :: Monad m => (a -> m Bool) -> [a] -> m Bool- anyMNix _ [] = pure False- anyMNix p (x : xs) =- bool- (anyMNix p xs)- (pure True)- =<< p x+ anyMNix p =+ list+ (pure False)+ (\ (x : xss) ->+ bool+ (anyMNix p xss)+ (pure True)+ =<< p x+ ) elemAtNix :: MonadNix e t f m@@ -954,33 +970,32 @@ do ss <- fromValue @[NValue t f m] =<< demand startSet op <- demand operator+ let+ go+ :: Set (WValue t f m)+ -> [NValue t f m]+ -> m (Set (WValue t f m), [NValue t f m])+ go ks [] = pure (ks, mempty)+ go ks (t : ts) =+ do+ v <- demand t+ k <- demand =<< attrsetGet "key" =<< fromValue @(AttrSet (NValue t f m)) v - toValue @[NValue t f m] =<< snd <$> go op mempty ss- where- go- :: NValue t f m- -> Set (WValue t f m)- -> [NValue t f m]- -> m (Set (WValue t f m), [NValue t f m])- go _ ks [] = pure (ks, mempty)- go op ks (t : ts) =- do- v <- demand t- k <- demand =<< attrsetGet "key" =<< fromValue @(AttrSet (NValue t f m)) v+ bool+ (do+ checkComparable k $+ list+ k+ (\ (WValue j:_) -> j)+ (S.toList ks) - bool- (do- ys <- fromValue @[NValue t f m] =<< callFunc op v- checkComparable k- (case S.toList ks of- [] -> k- WValue j : _ -> j- )- (t :) <<$>> go op (S.insert (WValue k) ks) (ts <> ys)- )- (go op ks ts)- (S.member (WValue k) ks)+ (<<$>>) (v :) . go (S.insert (WValue k) ks) . (<>) ts =<< fromValue @[NValue t f m] =<< callFunc op v+ )+ (go ks ts)+ (S.member (WValue k) ks) + toValue @[NValue t f m] =<< snd <$> go mempty ss+ -- | Takes: -- 1. List of strings to match. -- 2. List of strings to replace corresponding match occurance. (arg 1 & 2 lists matched by index)@@ -1021,7 +1036,7 @@ maybePrefixMatch :: Maybe (Text, NixString, Text) maybePrefixMatch = formMatchReplaceTailInfo <$> find ((`Text.isPrefixOf` input) . fst) fromKeysToValsMap where- formMatchReplaceTailInfo = (\(m, r) -> (m, r, Text.drop (Text.length m) input))+ formMatchReplaceTailInfo (m, r) = (m, r, Text.drop (Text.length m) input) fromKeysToValsMap = zip (stringIgnoreContext <$> fromKeys) toVals @@ -1034,7 +1049,7 @@ -- 2021-02-18: NOTE: rly?: toStrict . toLazyText -- Maybe `text-builder`, `text-show`?- finish ctx output = makeNixString (LazyText.toStrict $ Builder.toLazyText output) ctx+ finish ctx output = mkNixString (toStrict $ Builder.toLazyText output) ctx replace (key, replacementNS, unprocessedInput) = replaceWithNixBug unprocessedInput updatedOutput @@ -1080,11 +1095,12 @@ -> m (NValue t f m) removeAttrsNix set v = do- (m, p) <- fromValue @(AttrSet (NValue t f m), AttrSet SourcePos) set+ (m, p) <- fromValue @(AttrSet (NValue t f m), PositionSet) set (nsToRemove :: [NixString]) <- fromValue $ Deeper v- toRemove <- traverse fromStringNoContext nsToRemove+ (coerce -> toRemove) <- traverse fromStringNoContext nsToRemove toValue (go m toRemove, go p toRemove) where+ go :: forall k v . (Eq k, Hashable k) => HashMap k v -> [k] -> HashMap k v go = foldl' (flip M.delete) intersectAttrsNix@@ -1095,8 +1111,8 @@ -> m (NValue t f m) intersectAttrsNix set1 set2 = do- (s1, p1) <- fromValue @(AttrSet (NValue t f m), AttrSet SourcePos) set1- (s2, p2) <- fromValue @(AttrSet (NValue t f m), AttrSet SourcePos) set2+ (s1, p1) <- fromValue @(AttrSet (NValue t f m), PositionSet) set1+ (s2, p2) <- fromValue @(AttrSet (NValue t f m), PositionSet) set2 pure $ nvSet (p2 `M.intersection` p1) (s2 `M.intersection` s1) @@ -1110,7 +1126,7 @@ toValue @(AttrSet (NValue t f m)) $ mkNVBool <$> case p of Param name -> one (name, False)- ParamSet s _ _ -> isJust <$> M.fromList s+ ParamSet _ _ pset -> isJust <$> M.fromList pset _v -> throwError $ ErrorCall $ "builtins.functionArgs: expected function, got " <> show _v toFileNix@@ -1123,18 +1139,18 @@ name' <- fromStringNoContext =<< fromValue name s' <- fromValue s mres <-- (toFile_ `on` toString)- name'+ toFile_+ (coerce $ toString name') (stringIgnoreContext s') let- t = toText $ unStorePath mres- sc = StringContext t DirectPath+ storepath = coerce (fromString @Text) mres+ sc = StringContext storepath DirectPath - toValue $ makeNixStringWithSingletonContext t sc+ toValue $ mkNixStringWithSingletonContext storepath sc toPathNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m)-toPathNix = toValue @Path <=< fromValue @Path+toPathNix = inHask @Path id pathExistsNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) pathExistsNix nvpath =@@ -1143,7 +1159,7 @@ toValue =<< case path of NVPath p -> doesPathExist p- NVStr ns -> doesPathExist $ toString $ stringIgnoreContext ns+ NVStr ns -> doesPathExist $ coerce $ toString $ stringIgnoreContext ns _v -> throwError $ ErrorCall $ "builtins.pathExists: expected path, got " <> show _v isAttrsNix@@ -1258,8 +1274,8 @@ -> m (NValue t f m) scopedImportNix asetArg pathArg = do- s <- fromValue @(AttrSet (NValue t f m)) asetArg- (Path p) <- fromValue pathArg+ (coerce -> scope) <- fromValue @(AttrSet (NValue t f m)) asetArg+ p <- fromValue pathArg path <- pathToDefaultNix @t @f @m p path' <-@@ -1270,7 +1286,7 @@ ) (\ res -> do- (Path p') <- fromValue =<< demand res+ p' <- fromValue @Path =<< demand res traceM $ "Current file being evaluated is: " <> show p' pure $ takeDirectory p' </> path@@ -1279,36 +1295,34 @@ clearScopes @(NValue t f m) $ withNixContext (pure path')- $ pushScope s+ $ pushScope scope $ importPath @t @f @m path' getEnvNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) getEnvNix v =- do- s <- fromStringNoContext =<< fromValue v- mres <- getEnvVar s-- toValue $ makeNixStringWithoutContext $- fromMaybe mempty mres+ (toValue . mkNixStringWithoutContext . maybeToMonoid) =<< getEnvVar =<< fromStringNoContext =<< fromValue v sortNix- :: MonadNix e t f m+ :: forall e t f m+ . MonadNix e t f m => NValue t f m -> NValue t f m -> m (NValue t f m)-sortNix comp = toValue <=< sortByM (cmp comp) <=< fromValue+sortNix comp =+ inHaskM (sortByM cmp) where- cmp f a b =- do- isLessThan <- (`callFunc` b) =<< callFunc f a- bool- (do- isGreaterThan <- (`callFunc` a) =<< callFunc f b- fromValue isGreaterThan <&>- bool EQ GT- )- (pure LT)- =<< fromValue isLessThan+ cmp :: NValue t f m -> NValue t f m -> m Ordering+ cmp a b =+ bool+ (fmap+ (bool EQ GT)+ (compare b a)+ )+ (pure LT)+ =<< compare a b+ where+ compare :: NValue t f m -> NValue t f m -> m Bool+ compare a2 a1 = fromValue =<< (`callFunc` a1) =<< callFunc comp a2 lessThanNix :: MonadNix e t f m@@ -1343,10 +1357,11 @@ -> NValue t f m -> m (NValue t f m) concatWith f =- toValue . concat <=<- traverse- (fromValue @[NValue t f m] <=< f)- <=< fromValue @[NValue t f m]+ toValue .+ concat <=<+ traverse+ (fromValue @[NValue t f m] <=< f)+ <=< fromValue @[NValue t f m] -- | Nix function of Haskell: -- > concat :: [[a]] -> [a]@@ -1377,7 +1392,7 @@ (\ nvattrset -> do a <- fromValue @(AttrSet (NValue t f m)) =<< demand nvattrset- name <- fromStringNoContext =<< fromValue =<< demand =<< attrsetGet "name" a+ (coerce -> name) <- fromStringNoContext =<< fromValue =<< demand =<< attrsetGet "name" a val <- attrsetGet "value" a pure (name, val)@@ -1413,17 +1428,17 @@ mkHash s = hash $ encodeUtf8 s -placeHolderNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m)+placeHolderNix :: forall t f m e . MonadNix e t f m => NValue t f m -> m (NValue t f m) placeHolderNix p = do t <- fromStringNoContext =<< fromValue p h <-- runPrim $- (hashStringNix `on` makeNixStringWithoutContext)+ coerce @(Prim m NixString) @(m NixString) $+ (hashStringNix `on` mkNixStringWithoutContext) "sha256" ("nix-output:" <> t) toValue- $ makeNixStringWithoutContext+ $ mkNixStringWithoutContext $ Text.cons '/' $ Base32.encode -- Please, stop Text -> Bytestring here after migration to Text@@ -1440,7 +1455,7 @@ bytes :: NixString -> ByteString bytes = encodeUtf8 . body - body h = stringIgnoreContext h+ body = stringIgnoreContext readFileNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) readFileNix = toValue <=< Nix.Render.readFile <=< absolutePathFromValue <=< demand@@ -1459,7 +1474,7 @@ case (aset, filePath) of (NVList x, NVStr ns) -> do- mres <- findPath @t @f @m x $ toString $ stringIgnoreContext ns+ mres <- findPath @t @f @m x $ coerce $ toString $ stringIgnoreContext ns pure $ nvPath mres @@ -1475,6 +1490,7 @@ items <- listDirectory path let+ detectFileTypes :: Path -> m (VarName, FileType) detectFileTypes item = do s <- getSymbolicLinkStatus $ path </> item@@ -1486,7 +1502,7 @@ | isSymbolicLink s -> FileTypeSymlink | otherwise -> FileTypeUnknown - pure (toText item, t)+ pure (coerce @Text @VarName $ toText item, t) -- function indeed binds filepaths as keys (VarNames) in Nix attrset. itemsWithTypes <- traverse@@ -1563,7 +1579,7 @@ NVBuiltin _ _ -> "lambda" _ -> error "Pattern synonyms obscure complete patterns" - toValue $ makeNixStringWithoutContext detectType+ toValue $ mkNixStringWithoutContext detectType tryEvalNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m)@@ -1623,7 +1639,7 @@ :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m) fetchurlNix = (\case- NVSet s _ -> go (M.lookup "sha256" s) =<< demand =<< attrsetGet "url" s+ NVSet _ s -> go (M.lookup "sha256" s) =<< demand =<< attrsetGet "url" s v@NVStr{} -> go Nothing v v -> throwError $ ErrorCall $ "builtins.fetchurl: Expected URI or set, got " <> show v ) <=< demand@@ -1697,7 +1713,7 @@ case v' of (NVStr ns) -> do let context = getNixLikeContext $ toNixLikeContext $ getContext ns- valued :: AttrSet (NValue t f m) <- sequenceA $ toValue <$> context+ valued :: AttrSet (NValue t f m) <- traverseToValue context pure $ nvSet mempty valued x -> throwError $ ErrorCall $ "Invalid type for builtins.getContext: " <> show x @@ -1713,7 +1729,7 @@ y <- demand ty case (x, y) of- (NVStr ns, NVSet attrs _) ->+ (NVStr ns, NVSet _ attrs) -> do newContextValues <- traverse getPathNOuts attrs @@ -1727,7 +1743,7 @@ x <- demand tx case x of- NVSet attrs _ ->+ NVSet _ attrs-> do -- TODO: Fail for unexpected keys. @@ -1759,7 +1775,7 @@ _x -> throwError $ ErrorCall $ "Invalid types for context value in builtins.appendContext: " <> show _x addContext ns newContextValues =- makeNixString+ mkNixString (stringIgnoreContext ns) (fromNixLikeContext $ NixLikeContext $@@ -1772,18 +1788,18 @@ ) ) +nixVersionNix :: MonadNix e t f m => m (NValue t f m)+nixVersionNix = toValue $ mkNixStringWithoutContext "2.3" +langVersionNix :: MonadNix e t f m => m (NValue t f m)+langVersionNix = toValue (5 :: Int)+ -- ** @builtinsList@ builtinsList :: forall e t f m . MonadNix e t f m => m [Builtin (NValue t f m)]-builtinsList = sequence- [ do- version <- toValue (makeNixStringWithoutContext "2.3")- pure $ Builtin Normal ("nixVersion", version)- , do- version <- toValue (5 :: Int)- pure $ Builtin Normal ("langVersion", version)-+builtinsList = sequenceA+ [ add0 Normal "nixVersion" nixVersionNix+ , add0 Normal "langVersion" langVersionNix , add TopLevel "abort" throwNix -- for now , add2 Normal "add" addNix , add2 Normal "addErrorContext" addErrorContextNix@@ -1888,42 +1904,46 @@ , add Normal "valueSize" getRecursiveSizeNix ] where++ arity0 :: a -> Prim m a+ arity0 = Prim . pure+ arity1 :: (a -> b) -> (a -> Prim m b)- arity1 f = Prim . pure . f+ arity1 g = arity0 . g arity2 :: (a -> b -> c) -> (a -> b -> Prim m c)- arity2 f = ((Prim . pure) .) . f+ arity2 f = arity1 . f - mkBuiltin :: BuiltinType -> Text -> m (NValue t f m) -> m (Builtin (NValue t f m))+ mkBuiltin :: BuiltinType -> VarName -> m (NValue t f m) -> m (Builtin (NValue t f m)) mkBuiltin t n v = wrap t n <$> mkThunk n v where- wrap :: BuiltinType -> Text -> v -> Builtin v+ wrap :: BuiltinType -> VarName -> v -> Builtin v wrap t n f = Builtin t (n, f) - mkThunk :: Text -> m (NValue t f m) -> m (NValue t f m)+ mkThunk :: VarName -> m (NValue t f m) -> m (NValue t f m) mkThunk n = defer . withFrame Info (ErrorCall $ "While calling builtin " <> toString n <> "\n") hAdd- :: ( Text+ :: ( VarName -> fun -> m (NValue t f m) ) -> BuiltinType- -> Text+ -> VarName -> fun -> m (Builtin (NValue t f m)) hAdd f t n v = mkBuiltin t n $ f n v add0 :: BuiltinType- -> Text+ -> VarName -> m (NValue t f m) -> m (Builtin (NValue t f m)) add0 = hAdd (\ _ x -> x) add :: BuiltinType- -> Text+ -> VarName -> ( NValue t f m -> m (NValue t f m) )@@ -1932,7 +1952,7 @@ add2 :: BuiltinType- -> Text+ -> VarName -> ( NValue t f m -> NValue t f m -> m (NValue t f m)@@ -1942,7 +1962,7 @@ add3 :: BuiltinType- -> Text+ -> VarName -> ( NValue t f m -> NValue t f m -> NValue t f m@@ -1954,10 +1974,10 @@ add' :: ToBuiltin t f m a => BuiltinType- -> Text+ -> VarName -> a -> m (Builtin (NValue t f m))- add' = hAdd toBuiltin+ add' = hAdd (toBuiltin . coerce) -- * Exported@@ -1966,7 +1986,7 @@ withNixContext :: forall e t f m r . (MonadNix e t f m, Has e Options)- => Maybe FilePath+ => Maybe Path -> m r -> m r withNixContext mpath action =@@ -1977,7 +1997,7 @@ i = nvList $ nvStrWithoutContext . toText <$> include opts pushScope- (one ("__includes", i))+ (coerce $ M.fromList $ one ("__includes", i)) (pushScopes base $ maybe@@ -1986,29 +2006,35 @@ do traceM $ "Setting __cur_file = " <> show path let ref = nvPath path- pushScope (one ("__cur_file", ref)) act+ pushScope (coerce $ M.fromList $ one ("__cur_file", ref)) act ) mpath action ) builtins- :: ( MonadNix e t f m+ :: forall e t f m+ . ( MonadNix e t f m , Scoped (NValue t f m) m ) => m (Scopes m (NValue t f m)) builtins = do ref <- defer $ nvSet mempty <$> buildMap- lst <- ([("builtins", ref)] <>) <$> topLevelBuiltins- pushScope (M.fromList lst) currentScopes+ lst <- (one ("builtins", ref) <>) <$> topLevelBuiltins+ pushScope (coerce (M.fromList lst)) currentScopes where- buildMap = fmap (M.fromList . fmap mapping) builtinsList+ buildMap :: m (HashMap VarName (NValue t f m))+ buildMap = M.fromList . (mapping <$>) <$> builtinsList++ topLevelBuiltins :: m [(VarName, NValue t f m)] topLevelBuiltins = mapping <<$>> fullBuiltinsList + fullBuiltinsList :: m [Builtin (NValue t f m)] fullBuiltinsList = nameBuiltins <<$>> builtinsList where+ nameBuiltins :: Builtin v -> Builtin v nameBuiltins b@(Builtin TopLevel _) = b nameBuiltins (Builtin Normal nB) =- Builtin TopLevel $ first ("__" <>) nB+ Builtin TopLevel $ first (coerce @Text . ("__" <>) . coerce @VarName) nB
src/Nix/Cache.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE CPP #-}+{-# language CPP #-} -- | Reading and writing Nix cache files module Nix.Cache where -import qualified Data.ByteString.Lazy as BS+import qualified Data.ByteString.Lazy as BSL import Nix.Expr.Types.Annotated #if defined (__linux__)@@ -17,7 +17,7 @@ #endif import qualified Codec.Serialise as S -readCache :: FilePath -> IO NExprLoc+readCache :: Path -> IO NExprLoc readCache path = do #if USE_COMPACT eres <- C.unsafeReadCompact path@@ -26,17 +26,17 @@ (\ expr -> pure $ C.getCompact expr) eres #else- eres <- S.deserialiseOrFail <$> BS.readFile path+ eres <- S.deserialiseOrFail <$> BSL.readFile (coerce path) either (\ err -> fail $ "Error reading cache file: " <> show err) pure eres #endif -writeCache :: FilePath -> NExprLoc -> IO ()+writeCache :: Path -> NExprLoc -> IO () writeCache path expr = #ifdef USE_COMPACT C.writeCompact path =<< C.compact expr #else- BS.writeFile path (S.serialise expr)+ BSL.writeFile (coerce path) (S.serialise expr) #endif
src/Nix/Cited.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE TemplateHaskell #-}+{-# language DeriveAnyClass #-}+{-# language TemplateHaskell #-} -{-# OPTIONS_GHC -Wno-missing-signatures #-}+{-# options_ghc -Wno-missing-signatures #-} module Nix.Cited where
src/Nix/Cited/Basic.hs view
@@ -1,12 +1,9 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE PatternSynonyms #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language UndecidableInstances #-}+{-# language PatternSynonyms #-} module Nix.Cited.Basic where -import Prelude hiding ( force ) import Control.Comonad ( Comonad ) import Control.Comonad.Env ( ComonadEnv ) import Control.Monad.Catch hiding ( catchJust )@@ -14,11 +11,10 @@ import Nix.Eval as Eval ( EvalFrame(EvaluatingExpr,ForcingExpr) ) import Nix.Exec-import Nix.Expr+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Options import Nix.Thunk-import Nix.Utils import Nix.Value @@ -94,11 +90,11 @@ -- Gather the current evaluation context at the time of thunk -- creation, and record it along with the thunk. let- go (fromException -> Just (EvaluatingExpr scope (AnnE s e))) =- let e' = AnnFP s (Nothing <$ e) in- [Provenance scope e']+ go :: SomeException -> [Provenance m (NValue u f m)]+ go (fromException -> Just (EvaluatingExpr scope (Ann s e))) =+ one $ Provenance scope $ AnnF s (Nothing <$ e) go _ = mempty- ps = concatMap (go . frame) frames+ ps = foldMap (go . frame) frames cite ps t )@@ -182,6 +178,6 @@ displayProvenance = list id- (\ (Provenance scope e@(AnnFP s _) : _) ->+ (\ (Provenance scope e@(AnnF s _) : _) -> withFrame Info $ ForcingExpr scope $ wrapExprLoc s e )
src/Nix/Context.hs view
@@ -7,8 +7,8 @@ import Nix.Expr.Types.Annotated ( SrcSpan , nullSpan )-import Nix.Utils ( Has(..) ) +-- 2021-07-18: NOTE: It should be Options -> Scopes -> Frames -> Source(span) data Context m t = Context { scopes :: Scopes m t , source :: SrcSpan
src/Nix/Convert.hs view
@@ -1,11 +1,10 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language IncoherentInstances #-}+{-# language TypeFamilies #-}+{-# language UndecidableInstances #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -fno-warn-name-shadowing #-} -- | Although there are a lot of instances in this file, really it's just a -- combinatorial explosion of the following combinations:@@ -16,7 +15,6 @@ module Nix.Convert where -import Prelude hiding ( force ) import Control.Monad.Free import qualified Data.HashMap.Lazy as M import Nix.Atoms@@ -28,7 +26,6 @@ import Nix.Value import Nix.Value.Monad import Nix.Thunk ( MonadThunk(force) )-import Nix.Utils newtype Deeper a = Deeper a deriving (Typeable, Functor, Foldable, Traversable)@@ -50,13 +47,39 @@ -} +type Convertible e t f m+ = (Framed e m, MonadDataErrorContext t f m, MonadThunk t m (NValue t f m))++-- | Transform Nix -> Hask. Run function. Convert Hask -> Nix.+inHask :: forall a1 a2 v b m . (Monad m, FromValue a1 m v, ToValue a2 m b) => (a1 -> a2) -> v -> m b+inHask f = toValue . f <=< fromValue++inHaskM :: forall a1 a2 v b m . (Monad m, FromValue a1 m v, ToValue a2 m b) => (a1 -> m a2) -> v -> m b+inHaskM f = toValue <=< f <=< fromValue++-- | Maybe transform Nix -> Hask. Run function. Convert Hask -> Nix.+inHaskMay :: forall a1 a2 v b m . (Monad m, FromValue a1 m v, ToValue a2 m b) => (Maybe a1 -> a2) -> v -> m b+inHaskMay f = toValue . f <=< fromValueMay++ -- * FromValue class FromValue a m v where fromValue :: v -> m a fromValueMay :: v -> m (Maybe a) +traverseFromM+ :: ( Applicative m+ , Traversable t+ , FromValue b m a+ )+ => t a+ -> m (Maybe (t b))+traverseFromM = traverseM fromValueMay +traverseToValue :: ((Traversable t, Applicative f, ToValue a f b) => t a -> f (t b))+traverseToValue = traverse toValue+ -- Please, hide these helper function from export, to be sure they get optimized away. fromMayToValue :: forall t f m a e@@ -67,12 +90,10 @@ -> NValue' t f m (NValue t f m) -> m a fromMayToValue t v =- do- v' <- fromValueMay v- maybe- (throwError $ Expectation @t @f @m t (Free v))- pure- v'+ maybe+ (throwError $ Expectation @t @f @m t (Free v))+ pure+ =<< fromValueMay v fromMayToDeeperValue :: forall t f m a e m1@@ -83,15 +104,10 @@ -> Deeper (NValue' t f m (NValue t f m)) -> m (m1 a) fromMayToDeeperValue t v =- do- v' <- fromValueMay v- maybe- (throwError $ Expectation @t @f @m t $ Free $ (coerce :: CoerceDeeperToNValue' t f m) v)- pure- v'--type Convertible e t f m- = (Framed e m, MonadDataErrorContext t f m, MonadThunk t m (NValue t f m))+ maybe+ (throwError $ Expectation @t @f @m t $ Free $ (coerce :: CoerceDeeperToNValue' t f m) v)+ pure+ =<< fromValueMay v instance ( Convertible e t f m , MonadValue (NValue t f m) m@@ -135,7 +151,7 @@ fromValueMay = pure . \case- NVConstant' NNull -> pass+ NVConstant' NNull -> stub _ -> mempty fromValue = fromMayToValue TNull@@ -195,17 +211,18 @@ \case NVStr' ns -> pure $ pure ns NVPath' p ->- fmap- (pure . (\s -> makeNixStringWithSingletonContext s (StringContext s DirectPath)) . toText . unStorePath)- (addPath p)- NVSet' s _ ->+ (\path -> pure $ mkNixStringWithSingletonContext path (StringContext path DirectPath)) . fromString . coerce <$>+ addPath p+ NVSet' _ s -> maybe stub fromValueMay (M.lookup "outPath" s) _ -> stub - fromValue = fromMayToValue $ TString NoContext+ -- 2021-07-18: NOTE: There may be cases where conversion wrongly marks the content to have a context.+ -- See: https://github.com/haskell-nix/hnix/pull/958#issuecomment-881949183 thread.+ fromValue = fromMayToValue $ TString HasContext instance Convertible e t f m => FromValue ByteString m (NValue' t f m (NValue t f m)) where@@ -213,15 +230,22 @@ fromValueMay = pure . \case- NVStr' ns -> encodeUtf8 <$> getStringNoContext ns+ NVStr' ns -> encodeUtf8 <$> getStringNoContext ns _ -> mempty - fromValue = fromMayToValue $ TString NoContext+ fromValue = fromMayToValue $ TString mempty +instance Convertible e t f m+ => FromValue Text m (NValue' t f m (NValue t f m)) where -newtype Path = Path { getPath :: FilePath }- deriving Show+ fromValueMay =+ pure .+ \case+ NVStr' ns -> getStringNoContext ns+ _ -> mempty + fromValue = fromMayToValue $ TString mempty+ instance ( Convertible e t f m , MonadValue (NValue t f m) m )@@ -229,14 +253,14 @@ fromValueMay = \case- NVPath' p -> pure $ pure $ Path p- NVStr' ns -> pure $ Path . toString <$> getStringNoContext ns- NVSet' s _ ->+ NVPath' p -> pure $ pure $ coerce p+ NVStr' ns -> pure $ coerce . toString <$> getStringNoContext ns+ NVSet' _ s -> maybe- (pure Nothing)+ stub (fromValueMay @Path) (M.lookup "outPath" s)- _ -> pure Nothing+ _ -> stub fromValue = fromMayToValue TPath @@ -257,7 +281,7 @@ => FromValue [a] m (Deeper (NValue' t f m (NValue t f m))) where fromValueMay = \case- Deeper (NVList' l) -> sequence <$> traverse fromValueMay l+ Deeper (NVList' l) -> traverseFromM l _ -> stub @@ -269,7 +293,7 @@ fromValueMay = pure . \case- NVSet' s _ -> pure s+ NVSet' _ s -> pure s _ -> mempty fromValue = fromMayToValue TSet@@ -281,19 +305,19 @@ fromValueMay = \case- Deeper (NVSet' s _) -> sequence <$> traverse fromValueMay s+ Deeper (NVSet' _ s) -> traverseFromM s _ -> stub fromValue = fromMayToDeeperValue TSet instance Convertible e t f m- => FromValue (AttrSet (NValue t f m), AttrSet SourcePos) m+ => FromValue (AttrSet (NValue t f m), PositionSet) m (NValue' t f m (NValue t f m)) where fromValueMay = pure . \case- NVSet' s p -> pure (s, p)+ NVSet' p s -> pure (s, p) _ -> mempty fromValue = fromMayToValue TSet@@ -301,12 +325,12 @@ instance ( Convertible e t f m , FromValue a m (NValue t f m) )- => FromValue (AttrSet a, AttrSet SourcePos) m+ => FromValue (AttrSet a, PositionSet) m (Deeper (NValue' t f m (NValue t f m))) where fromValueMay = \case- Deeper (NVSet' s p) -> fmap (, p) . sequence <$> traverse fromValueMay s+ Deeper (NVSet' p s) -> (, p) <<$>> traverseFromM s _ -> stub fromValue = fromMayToDeeperValue TSet@@ -325,13 +349,15 @@ class ToValue a m v where toValue :: a -> m v -instance (Convertible e t f m, ToValue a m (NValue' t f m (NValue t f m)))+instance (Convertible e t f m+ , ToValue a m (NValue' t f m (NValue t f m))+ ) => ToValue a m (NValue t f m) where toValue v = Free <$> toValue v instance ( Convertible e t f m- , ToValue a m (Deeper (NValue' t f m (NValue t f m)))- )+ , ToValue a m (Deeper (NValue' t f m (NValue t f m)))+ ) => ToValue a m (Deeper (NValue t f m)) where toValue v = Free <<$>> toValue v @@ -361,24 +387,27 @@ instance Convertible e t f m => ToValue ByteString m (NValue' t f m (NValue t f m)) where- toValue = pure . nvStr' . makeNixStringWithoutContext . decodeUtf8+ toValue = pure . nvStr' . mkNixStringWithoutContext . decodeUtf8 instance Convertible e t f m+ => ToValue Text m (NValue' t f m (NValue t f m)) where+ toValue = pure . nvStr' . mkNixStringWithoutContext++instance Convertible e t f m => ToValue Path m (NValue' t f m (NValue t f m)) where- toValue = pure . nvPath' . getPath+ toValue = pure . nvPath' . coerce instance Convertible e t f m => ToValue StorePath m (NValue' t f m (NValue t f m)) where- toValue = toValue . Path . unStorePath+ toValue = toValue @Path . coerce -instance ( Convertible e t f m- )+instance Convertible e t f m => ToValue SourcePos m (NValue' t f m (NValue t f m)) where toValue (SourcePos f l c) = do- f' <- toValue $ makeNixStringWithoutContext $ toText f+ f' <- toValue $ mkNixStringWithoutContext $ fromString f l' <- toValue $ unPos l c' <- toValue $ unPos c- let pos = M.fromList [("file" :: Text, f'), ("line", l'), ("column", c')]+ let pos = M.fromList [("file" :: VarName, f'), ("line", l'), ("column", c')] pure $ nvSet' mempty pos -- | With 'ToValue', we can always act recursively@@ -386,9 +415,11 @@ => ToValue [NValue t f m] m (NValue' t f m (NValue t f m)) where toValue = pure . nvList' -instance (Convertible e t f m, ToValue a m (NValue t f m))+instance (Convertible e t f m+ , ToValue a m (NValue t f m)+ ) => ToValue [a] m (Deeper (NValue' t f m (NValue t f m))) where- toValue l = Deeper . nvList' <$> traverse toValue l+ toValue l = Deeper . nvList' <$> traverseToValue l instance Convertible e t f m => ToValue (AttrSet (NValue t f m)) m (NValue' t f m (NValue t f m)) where@@ -398,20 +429,20 @@ => ToValue (AttrSet a) m (Deeper (NValue' t f m (NValue t f m))) where toValue s = liftA2 (\ v s -> Deeper $ nvSet' s v)- (traverse toValue s)+ (traverseToValue s) stub instance Convertible e t f m- => ToValue (AttrSet (NValue t f m), AttrSet SourcePos) m+ => ToValue (AttrSet (NValue t f m), PositionSet) m (NValue' t f m (NValue t f m)) where toValue (s, p) = pure $ nvSet' p s instance (Convertible e t f m, ToValue a m (NValue t f m))- => ToValue (AttrSet a, AttrSet SourcePos) m+ => ToValue (AttrSet a, PositionSet) m (Deeper (NValue' t f m (NValue t f m))) where toValue (s, p) = liftA2 (\ v s -> Deeper $ nvSet' s v)- (traverse toValue s)+ (traverseToValue s) (pure p) instance Convertible e t f m@@ -427,9 +458,9 @@ allOutputs <- g nlcvAllOutputs outputs <- do let- outputs = makeNixStringWithoutContext <$> nlcvOutputs nlcv+ outputs = mkNixStringWithoutContext <$> nlcvOutputs nlcv - ts :: [NValue t f m] <- traverse toValue outputs+ ts :: [NValue t f m] <- traverseToValue outputs list (pure Nothing) (fmap pure . toValue)
src/Nix/Effects.hs view
@@ -1,24 +1,21 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@+{-# language AllowAmbiguousTypes #-}+{-# language CPP #-}+{-# language DefaultSignatures #-}+{-# language TypeFamilies #-}+{-# language DataKinds #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language UndecidableInstances #-}+{-# language PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@ -{-# OPTIONS_GHC -Wno-orphans #-}+{-# options_ghc -Wno-orphans #-} module Nix.Effects where -import Prelude hiding ( traceM- , putStr- , putStrLn+import Prelude hiding ( putStrLn , print )-import qualified Prelude-import Nix.Utils+import GHC.Exception ( ErrorCall(ErrorCall) ) import qualified Data.HashSet as HS import qualified Data.Text as Text import Network.HTTP.Client hiding ( path, Proxy )@@ -26,15 +23,13 @@ import Network.HTTP.Types import qualified "cryptonite" Crypto.Hash as Hash import Nix.Utils.Fix1-import Nix.Expr+import Nix.Expr.Types.Annotated import Nix.Frames hiding ( Proxy ) import Nix.Parser import Nix.Render import Nix.Value import qualified Paths_hnix import System.Exit-import qualified System.Environment as Env-import System.FilePath ( takeFileName ) import qualified System.Info import System.Process @@ -42,7 +37,7 @@ import qualified System.Nix.StorePath as Store -- | A path into the nix store-newtype StorePath = StorePath { unStorePath :: FilePath }+newtype StorePath = StorePath Path -- All of the following type classes defer to the underlying 'm'.@@ -62,16 +57,15 @@ ) => MonadEffects t f m where - -- | Determine the absolute path of relative path in the current context- makeAbsolutePath :: FilePath -> m FilePath- findEnvPath :: String -> m FilePath+ -- | Determine the absolute path in the current context.+ toAbsolutePath :: Path -> m Path+ findEnvPath :: String -> m Path - -- | Having an explicit list of sets corresponding to the NIX_PATH- -- and a file path try to find an existing path- findPath :: [NValue t f m] -> FilePath -> m FilePath+ -- | Having an explicit list of sets corresponding to the @NIX_PATH@ and a file path try to find an existing path.+ findPath :: [NValue t f m] -> Path -> m Path - importPath :: FilePath -> m (NValue t f m)- pathToDefaultNix :: FilePath -> m FilePath+ importPath :: Path -> m (NValue t f m)+ pathToDefaultNix :: Path -> m Path derivationStrict :: NValue t f m -> m (NValue t f m) @@ -108,7 +102,7 @@ #ifdef MIN_VERSION_ghc_datasize recursiveSize #else- \_ -> pure 0+ const $ pure 0 #endif deriving@@ -140,9 +134,9 @@ exec' = \case [] -> pure $ Left $ ErrorCall "exec: missing program" (prog : args) -> do- (exitCode, out, _) <- liftIO $ readProcessWithExitCode (toString prog) (toString <$> args) ""+ (exitCode, out, _) <- liftIO $ readProcessWithExitCode (toString prog) (toString <$> args) mempty let- t = Text.strip $ toText out+ t = Text.strip $ fromString out emsg = "program[" <> prog <> "] args=" <> show args case exitCode of ExitSuccess ->@@ -191,7 +185,7 @@ readProcessWithExitCode "nix-instantiate" ["--eval", "--expr", toString expr]- ""+ mempty pure $ case exitCode of@@ -199,7 +193,7 @@ either (\ e -> Left $ ErrorCall $ "Error parsing output of nix-instantiate: " <> show e) pure- (parseNixTextLoc $ toText out)+ (parseNixTextLoc $ fromString out) status -> Left $ ErrorCall $ "nix-instantiate failed: " <> show status <> ": " <> err deriving@@ -235,12 +229,12 @@ -- ** Instances instance MonadEnv IO where- getEnvVar = (<<$>>) toText . Env.lookupEnv . toString+ getEnvVar = (<<$>>) fromString . lookupEnv . toString - getCurrentSystemOS = pure $ toText System.Info.os+ getCurrentSystemOS = pure $ fromString System.Info.os -- Invert the conversion done by GHC_CONVERT_CPU in GHC's aclocal.m4- getCurrentSystemArch = pure $ toText $ case System.Info.arch of+ getCurrentSystemArch = pure $ fromString $ case System.Info.arch of "i386" -> "i686" arch -> arch @@ -260,15 +254,15 @@ class Monad m => MonadPaths m where- getDataDir :: m FilePath- default getDataDir :: (MonadTrans t, MonadPaths m', m ~ t m') => m FilePath+ getDataDir :: m Path+ default getDataDir :: (MonadTrans t, MonadPaths m', m ~ t m') => m Path getDataDir = lift getDataDir -- ** Instances instance MonadPaths IO where- getDataDir = Paths_hnix.getDataDir+ getDataDir = coerce Paths_hnix.getDataDir deriving instance@@ -328,7 +322,7 @@ -- * @class MonadPutStr m@ class- Monad m+ (Monad m, MonadIO m) => MonadPutStr m where --TODO: Should this be used *only* when the Nix to be evaluated invokes a@@ -336,7 +330,7 @@ -- 2021-04-01: Due to trace operation here, leaving it as String. putStr :: String -> m () default putStr :: (MonadTrans t, MonadPutStr m', m ~ t m') => String -> m ()- putStr = lift . putStr+ putStr = lift . Prelude.putStr -- ** Instances@@ -358,7 +352,7 @@ -- ** Functions putStrLn :: MonadPutStr m => String -> m ()-putStrLn = putStr . (<> "\n")+putStrLn = Nix.Effects.putStr . (<> "\n") print :: (MonadPutStr m, Show a) => a -> m () print = putStrLn . show@@ -370,7 +364,7 @@ type RecursiveFlag = Bool type RepairFlag = Bool type StorePathName = Text-type FilePathFilter m = FilePath -> m Bool+type PathFilter m = Path -> m Bool type StorePathSet = HS.HashSet StorePath -- ** @class MonadStore m@@@ -382,8 +376,8 @@ -- | Copy the contents of a local path to the store. The resulting store -- path is returned. Note: This does not support yet support the expected -- `filter` function that allows excluding some files.- addToStore :: StorePathName -> FilePath -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)- default addToStore :: (MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> FilePath -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)+ addToStore :: StorePathName -> Path -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)+ default addToStore :: (MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> Path -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath) addToStore a b c d = lift $ addToStore a b c d -- | Like addToStore, but the contents written to the output path is a@@ -403,10 +397,10 @@ (\ pathName -> do -- TODO: redesign the filter parameter- res <- Store.Remote.runStore $ Store.Remote.addToStore @Hash.SHA256 pathName path recursive (const False) repair+ res <- Store.Remote.runStore $ Store.Remote.addToStore @Hash.SHA256 pathName (coerce path) recursive (const False) repair either Left -- err- (pure . StorePath . decodeUtf8 . Store.storePathToRawFilePath) -- store path+ (pure . StorePath . coerce . decodeUtf8 @FilePath @ByteString . Store.storePathToRawFilePath) -- store path <$> parseStoreResult "addToStore" res ) (Store.makeStorePathName name)@@ -416,7 +410,7 @@ res <- Store.Remote.runStore $ Store.Remote.addTextToStore name text references repair either Left -- err- (pure . StorePath . decodeUtf8 . Store.storePathToRawFilePath) -- path+ (pure . StorePath . coerce . decodeUtf8 @FilePath @ByteString . Store.storePathToRawFilePath) -- path <$> parseStoreResult "addTextToStore" res @@ -438,12 +432,12 @@ pure =<< addTextToStore' a b c d -addPath :: (Framed e m, MonadStore m) => FilePath -> m StorePath+addPath :: (Framed e m, MonadStore m) => Path -> m StorePath addPath p = either throwError pure- =<< addToStore (toText $ takeFileName p) p True False+ =<< addToStore (fromString $ coerce takeFileName p) p True False -toFile_ :: (Framed e m, MonadStore m) => FilePath -> String -> m StorePath-toFile_ p contents = addTextToStore (toText p) (toText contents) mempty False+toFile_ :: (Framed e m, MonadStore m) => Path -> Text -> m StorePath+toFile_ p contents = addTextToStore (toText p) contents mempty False
src/Nix/Effects/Basic.hs view
@@ -1,27 +1,24 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-}+{-# language CPP #-} module Nix.Effects.Basic where -import Prelude hiding ( traceM- , head+import Prelude hiding ( head ) import Relude.Unsafe ( head )-import Nix.Utils+import GHC.Exception ( ErrorCall(ErrorCall) ) import Control.Monad ( foldM ) import qualified Data.HashMap.Lazy as M import Data.List.Split ( splitOn ) import qualified Data.Text as Text import Prettyprinter ( fillSep )-import System.FilePath import Nix.Convert import Nix.Effects import Nix.Exec ( MonadNix , evalExprLoc , nixInstantiateExpr )-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Parser import Nix.Render@@ -34,137 +31,134 @@ import GHC.DataSize #endif -defaultMakeAbsolutePath :: MonadNix e t f m => FilePath -> m FilePath-defaultMakeAbsolutePath origPath = do- origPathExpanded <- expandHomePath origPath- absPath <-- bool- (do- cwd <- do- mres <- lookupVar "__cur_file"- maybe- getCurrentDirectory- (- (\case- NVPath s -> pure $ takeDirectory s- val -> throwError $ ErrorCall $ "when resolving relative path, __cur_file is in scope, but is not a path; it is: " <> show val- ) <=< demand++++defaultToAbsolutePath :: forall e t f m . MonadNix e t f m => Path -> m Path+defaultToAbsolutePath origPath =+ do+ origPathExpanded <- expandHomePath origPath+ fmap+ removeDotDotIndirections+ . canonicalizePath+ =<< bool+ (fmap+ (<///> origPathExpanded)+ $ maybe+ getCurrentDirectory+ ( (\case+ NVPath s -> pure $ takeDirectory s+ val -> throwError $ ErrorCall $ "when resolving relative path, __cur_file is in scope, but is not a path; it is: " <> show val+ ) <=< demand+ )+ =<< lookupVar "__cur_file" )- mres- pure $ cwd <///> origPathExpanded- )- (pure origPathExpanded)- (isAbsolute origPathExpanded)- removeDotDotIndirections <$> canonicalizePath absPath+ (pure origPathExpanded)+ (isAbsolute origPathExpanded) -expandHomePath :: MonadFile m => FilePath -> m FilePath-expandHomePath ('~' : xs) = (<> xs) <$> getHomeDirectory+expandHomePath :: MonadFile m => Path -> m Path+expandHomePath (coerce -> ('~' : xs)) = (<> coerce xs) <$> getHomeDirectory expandHomePath p = pure p -- | Incorrectly normalize paths by rewriting patterns like @a/b/..@ to @a@. -- This is incorrect on POSIX systems, because if @b@ is a symlink, its -- parent may be a different directory from @a@. See the discussion at -- https://hackage.haskell.org/package/directory-1.3.1.5/docs/System-Directory.html#v:canonicalizePath-removeDotDotIndirections :: FilePath -> FilePath-removeDotDotIndirections = intercalate "/" . go mempty . splitOn "/"+removeDotDotIndirections :: Path -> Path+removeDotDotIndirections = coerce . intercalate "/" . go mempty . splitOn "/" . coerce where go s [] = reverse s go (_ : s) (".." : rest) = go s rest go s (this : rest) = go (this : s) rest infixr 9 <///>-(<///>) :: FilePath -> FilePath -> FilePath-x <///> y | isAbsolute y || "." `isPrefixOf` y = x </> y- | otherwise = joinByLargestOverlap x y+(<///>) :: Path -> Path -> Path+x <///> y+ | isAbsolute y || "." `isPrefixOf` coerce y = x </> y+ | otherwise = joinByLargestOverlap x y where+ joinByLargestOverlap :: Path -> Path -> Path joinByLargestOverlap (splitDirectories -> xs) (splitDirectories -> ys) = joinPath $ head [ xs <> drop (length tx) ys | tx <- tails xs, tx `elem` inits ys ] -defaultFindEnvPath :: MonadNix e t f m => String -> m FilePath-defaultFindEnvPath = findEnvPathM--findEnvPathM :: forall e t f m . MonadNix e t f m => FilePath -> m FilePath-findEnvPathM name = do- mres <- lookupVar "__nixPath"+defaultFindEnvPath :: MonadNix e t f m => String -> m Path+defaultFindEnvPath = findEnvPathM . coerce +findEnvPathM :: forall e t f m . MonadNix e t f m => Path -> m Path+findEnvPathM name = maybe (fail "impossible")- (- (\ nv ->- do- (l :: [NValue t f m]) <- fromValue nv- findPathBy nixFilePath l name- ) <=< demand+ (\ v ->+ do+ l <- fromValue @[NValue t f m] =<< demand v+ findPathBy nixFilePath l name )- mres+ =<< lookupVar "__nixPath" where- nixFilePath :: MonadEffects t f m => FilePath -> m (Maybe FilePath)- nixFilePath path = do- absPath <- makeAbsolutePath @t @f path- isDir <- doesDirectoryExist absPath- absFile <-- bool- (pure absPath)- (makeAbsolutePath @t @f $ absPath </> "default.nix")- isDir- exists <- doesFileExist absFile- pure $- bool- mempty- (pure absFile)- exists+ nixFilePath :: MonadEffects t f m => Path -> m (Maybe Path)+ nixFilePath path =+ do+ absPath <- toAbsolutePath @t @f path+ isDir <- doesDirectoryExist absPath+ absFile <-+ bool+ (pure absPath)+ (toAbsolutePath @t @f $ absPath </> "default.nix")+ isDir + (pure absFile `whenTrue`) <$> doesFileExist absFile+ findPathBy :: forall e t f m . MonadNix e t f m- => (FilePath -> m (Maybe FilePath))+ => (Path -> m (Maybe Path)) -> [NValue t f m]- -> FilePath- -> m FilePath-findPathBy finder ls name = do- mpath <- foldM go mempty ls+ -> Path+ -> m Path+findPathBy finder ls name = maybe- (throwError $ ErrorCall $ "file '" <> name <> "' was not found in the Nix search path (add it's using $NIX_PATH or -I)")+ (throwError $ ErrorCall $ "file ''" <> coerce name <> "'' was not found in the Nix search path (add it's using $NIX_PATH or -I)") pure- mpath+ =<< foldM fun mempty ls where- go :: Maybe FilePath -> NValue t f m -> m (Maybe FilePath)- go mp =+ fun+ :: MonadNix e t f m+ => Maybe Path+ -> NValue t f m+ -> m (Maybe Path)+ fun = maybe (\ nv -> do- (s :: HashMap Text (NValue t f m)) <- fromValue =<< demand nv+ (s :: HashMap VarName (NValue t f m)) <- fromValue =<< demand nv p <- resolvePath s- nvpath <- demand p- (Path path) <- fromValue nvpath+ path <- fromValue =<< demand p maybe (tryPath path mempty) (\ nv' -> do- mns <- fromValueMay =<< demand nv'+ mns <- fromValueMay @NixString =<< demand nv' tryPath path $- case mns of- Just (nsPfx :: NixString) ->+ whenJust+ (\ nsPfx -> let pfx = stringIgnoreContext nsPfx in- bool- mempty- (pure (toString pfx))- (not $ Text.null pfx)- _ -> mempty+ pure $ coerce $ toString pfx `whenFalse` Text.null pfx+ )+ mns ) (M.lookup "prefix" s) ) (const . pure . pure)- mp - tryPath :: FilePath -> Maybe FilePath -> m (Maybe FilePath)+ tryPath :: Path -> Maybe Path -> m (Maybe Path) tryPath p (Just n) | n' : ns <- splitDirectories name, n == n' = finder $ p <///> joinPath ns tryPath p _ = finder $ p <///> name + resolvePath :: HashMap VarName (NValue t f m) -> m (NValue t f m) resolvePath s = maybe (maybe@@ -176,22 +170,29 @@ (M.lookup "path" s) fetchTarball- :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m)+ :: forall e t f m+ . MonadNix e t f m+ => NValue t f m+ -> m (NValue t f m) fetchTarball = \case- NVSet s _ ->+ NVSet _ s -> maybe (throwError $ ErrorCall "builtins.fetchTarball: Missing url attribute")- (go (M.lookup "sha256" s) <=< demand)+ (fetchFromString (M.lookup "sha256" s) <=< demand) (M.lookup "url" s)- v@NVStr{} -> go Nothing v+ v@NVStr{} -> fetchFromString Nothing v v -> throwError $ ErrorCall $ "builtins.fetchTarball: Expected URI or set, got " <> show v <=< demand where- go :: Maybe (NValue t f m) -> NValue t f m -> m (NValue t f m)- go msha = \case- NVStr ns -> fetch (stringIgnoreContext ns) msha- v -> throwError $ ErrorCall $ "builtins.fetchTarball: Expected URI or string, got " <> show v+ fetchFromString+ :: Maybe (NValue t f m)+ -> NValue t f m+ -> m (NValue t f m)+ fetchFromString msha =+ \case+ NVStr ns -> fetch (stringIgnoreContext ns) msha+ v -> throwError $ ErrorCall $ "builtins.fetchTarball: Expected URI or string, got " <> show v {- jww (2018-04-11): This should be written using pipes in another module fetch :: Text -> Maybe (NThunk m) -> m (NValue t f m)@@ -206,68 +207,73 @@ -} fetch :: Text -> Maybe (NValue t f m) -> m (NValue t f m)- fetch uri Nothing =- nixInstantiateExpr $ "builtins.fetchTarball \"" <> uri <> "\""- fetch url (Just t) =- (\nv -> do- nsSha <- fromValue nv+ fetch uri =+ maybe+ (nixInstantiateExpr $+ "builtins.fetchTarball \"" <> uri <> "\""+ )+ (\ v ->+ do+ nsSha <- fromValue =<< demand v - let sha = stringIgnoreContext nsSha+ let sha = stringIgnoreContext nsSha - nixInstantiateExpr- $ "builtins.fetchTarball { " <> "url = \"" <> url <> "\"; " <> "sha256 = \"" <> sha <> "\"; }"- ) =<< demand t+ nixInstantiateExpr $+ "builtins.fetchTarball { " <> "url = \"" <> uri <> "\"; " <> "sha256 = \"" <> sha <> "\"; }"+ ) -defaultFindPath :: MonadNix e t f m => [NValue t f m] -> FilePath -> m FilePath+defaultFindPath :: MonadNix e t f m => [NValue t f m] -> Path -> m Path defaultFindPath = findPathM findPathM :: forall e t f m . MonadNix e t f m => [NValue t f m]- -> FilePath- -> m FilePath+ -> Path+ -> m Path findPathM = findPathBy existingPath where- existingPath :: MonadEffects t f m => FilePath -> m (Maybe FilePath)+ existingPath :: MonadEffects t f m => Path -> m (Maybe Path) existingPath path = do- apath <- makeAbsolutePath @t @f path+ apath <- toAbsolutePath @t @f path doesExist <- doesPathExist apath pure $ pure apath `whenTrue` doesExist defaultImportPath- :: (MonadNix e t f m, MonadState (HashMap FilePath NExprLoc, b) m)- => FilePath+ :: (MonadNix e t f m, MonadState (HashMap Path NExprLoc, b) m)+ => Path -> m (NValue t f m)-defaultImportPath path = do- traceM $ "Importing file " <> path- withFrame Info (ErrorCall $ "While importing file " <> show path) $ do- imports <- gets fst- evalExprLoc =<<- maybe- (do- eres <- parseNixFileLoc path- either- (\ err -> throwError $ ErrorCall . show $ fillSep ["Parse during import failed:", err])- (\ expr ->- do- modify (first (M.insert path expr))- pure expr+defaultImportPath path =+ do+ traceM $ "Importing file " <> coerce path+ withFrame+ Info+ (ErrorCall $ "While importing file " <> show path)+ $ evalExprLoc =<<+ (maybe+ (either+ (\ err -> throwError $ ErrorCall . show $ fillSep ["Parse during import failed:", err])+ (\ expr ->+ do+ modify $ first $ M.insert path expr+ pure expr+ )+ =<< parseNixFileLoc path )- eres- )- pure -- return expr- (M.lookup path imports)+ pure -- return expr+ . M.lookup path+ ) =<< gets fst -defaultPathToDefaultNix :: MonadNix e t f m => FilePath -> m FilePath+defaultPathToDefaultNix :: MonadNix e t f m => Path -> m Path defaultPathToDefaultNix = pathToDefaultNixFile -- Given a path, determine the nix file to load-pathToDefaultNixFile :: MonadFile m => FilePath -> m FilePath-pathToDefaultNixFile p = do- isDir <- doesDirectoryExist p- pure $ p </> "default.nix" `whenTrue` isDir+pathToDefaultNixFile :: MonadFile m => Path -> m Path+pathToDefaultNixFile p =+ do+ isDir <- doesDirectoryExist p+ pure $ p </> "default.nix" `whenTrue` isDir defaultTraceEffect :: MonadPutStr m => String -> m () defaultTraceEffect = Nix.Effects.putStrLn
src/Nix/Effects/Derivation.hs view
@@ -1,12 +1,12 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@+{-# language DataKinds #-}+{-# language NamedFieldPuns #-}+{-# language RecordWildCards #-}+{-# language PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@ module Nix.Effects.Derivation ( defaultDerivationStrict ) where -import Nix.Utils+import Prelude hiding ( readFile )+import GHC.Exception ( ErrorCall(ErrorCall) ) import Data.Char ( isAscii , isAlphaNum )@@ -24,6 +24,7 @@ import qualified "cryptonite" Crypto.Hash as Hash -- 2021-07-05: Attrocity of Haskell hashing situation, in HNix we ended-up with 2 hash package dependencies @{hashing, cryptonite}@ import Nix.Atoms+import Nix.Expr.Types hiding ( Recursive ) import Nix.Convert import Nix.Effects import Nix.Exec ( MonadNix@@ -40,9 +41,9 @@ import qualified System.Nix.ReadonlyStore as Store import qualified System.Nix.Hash as Store import qualified System.Nix.StorePath as Store-import Prelude hiding (readFile) +-- 2021-07-17: NOTE: Derivation consists of @"keys"@ @"vals"@ (of text), so underlining type boundary currently stops here. data Derivation = Derivation { name :: Text , outputs :: Map Text Text@@ -75,11 +76,11 @@ let (inputSrcs, inputDrvs) = inputs references <- Set.fromList <$> traverse parsePath (Set.toList $ inputSrcs <> Set.fromList (Map.keys inputDrvs)) path <- addTextToStore (Text.append name ".drv") (unparseDrv drv) (S.fromList $ Set.toList references) False- parsePath $ toText $ unStorePath path+ parsePath $ fromString $ coerce path -- | Traverse the graph of inputDrvs to replace fixed output derivations with their fixed output hash. -- this avoids propagating changes to their .drv when the output hash stays the same.-hashDerivationModulo :: (MonadNix e t f m, MonadState (b, AttrSet Text) m) => Derivation -> m (Hash.Digest Hash.SHA256)+hashDerivationModulo :: (MonadNix e t f m, MonadState (b, KeyMap Text) m) => Derivation -> m (Hash.Digest Hash.SHA256) hashDerivationModulo Derivation { mFixed = Just (Store.SomeDigest (digest :: Hash.Digest hashType))@@ -91,7 +92,7 @@ Hash.hash @ByteString @Hash.SHA256 $ encodeUtf8 $ "fixed:out"- <> (if hashMode == Recursive then ":r" else "")+ <> (if hashMode == Recursive then ":r" else mempty) <> ":" <> (Store.algoName @hashType) <> ":" <> Store.encodeDigestWith Store.Base16 digest <> ":" <> path@@ -110,7 +111,7 @@ (\(path, outs) -> maybe (do- drv' <- readDerivation $ toString path+ drv' <- readDerivation $ coerce $ toString path hash <- Store.encodeDigestWith Store.Base16 <$> hashDerivationModulo drv' pure (hash, outs) )@@ -144,7 +145,7 @@ ] where produceOutputInfo (outputName, outputPath) =- let prefix = if hashMode == Recursive then "r:" else "" in+ let prefix = if hashMode == Recursive then "r:" else mempty in parens $ (s <$>) $ ([outputName, outputPath] <>) $ maybe [mempty, mempty]@@ -168,13 +169,13 @@ escape '\t' = "\\t" escape c = one c -readDerivation :: (Framed e m, MonadFile m) => FilePath -> m Derivation+readDerivation :: (Framed e m, MonadFile m) => Path -> m Derivation readDerivation path = do- content <- decodeUtf8 <$> readFile path+ content <- readFile path either (\ err -> throwError $ ErrorCall $ "Failed to parse " <> show path <> ":\n" <> show err) pure- (parse derivationParser path content)+ (parse derivationParser (coerce path) content) derivationParser :: Parsec () Text Derivation derivationParser = do@@ -199,13 +200,13 @@ let outputs = Map.fromList $ (\(a, b, _, _) -> (a, b)) <$> fullOutputs let (mFixed, hashMode) = parseFixed fullOutputs- let name = "" -- FIXME (extract from file path ?)- let useJson = ["__json"] == Map.keys env+ let name = mempty -- FIXME (extract from file path ?)+ let useJson = one "__json" == Map.keys env pure $ Derivation {inputs = (inputSrcs, inputDrvs), ..} where s :: Parsec () Text Text- s = fmap toText $ string "\"" *> manyTill (escaped <|> regular) (string "\"")+ s = fmap fromString $ string "\"" *> manyTill (escaped <|> regular) (string "\"") escaped = char '\\' *> ( '\n' <$ string "n" <|> '\r' <$ string "r"@@ -218,12 +219,13 @@ string o *> sepBy p (string ",") <* string c parens :: Parsec () Text a -> Parsec () Text [a]- parens p = wrap "(" ")" p- serializeList p = wrap "[" "]" p+ parens = wrap "(" ")"+ serializeList :: Parsec () Text a -> Parsec () Text [a]+ serializeList = wrap "[" "]" parseFixed :: [(Text, Text, Text, Text)] -> (Maybe Store.SomeNamedDigest, HashMode) parseFixed fullOutputs = case fullOutputs of- [("out", _path, rht, hash)] | rht /= "" && hash /= "" ->+ [("out", _path, rht, hash)] | rht /= mempty && hash /= mempty -> let (hashType, hashMode) = case Text.splitOn ":" rht of ["r", ht] -> (ht, Recursive)@@ -238,9 +240,9 @@ _ -> (Nothing, Flat) -defaultDerivationStrict :: forall e t f m b. (MonadNix e t f m, MonadState (b, AttrSet Text) m) => NValue t f m -> m (NValue t f m)+defaultDerivationStrict :: forall e t f m b. (MonadNix e t f m, MonadState (b, KeyMap Text) m) => NValue t f m -> m (NValue t f m) defaultDerivationStrict val = do- s <- fromValue @(AttrSet (NValue t f m)) val+ s <- M.mapKeys coerce <$> fromValue @(AttrSet (NValue t f m)) val (drv, ctx) <- runWithStringContextT' $ buildDerivationWithContext s drvName <- makeStorePathName $ name drv let@@ -266,47 +268,50 @@ ifNotJsonModEnv (\ baseEnv -> foldl'- (\m k -> Map.insert k "" m)+ (\m k -> Map.insert k mempty m) baseEnv (Map.keys $ outputs drv) ) }- outputs' <- sequence $ Map.mapWithKey (\o _ -> makeOutputPath o hash drvName) $ outputs drv+ outputs' <- sequenceA $ Map.mapWithKey (\o _ -> makeOutputPath o hash drvName) $ outputs drv pure $ drv { inputs , outputs = outputs'- , env = ifNotJsonModEnv $ (outputs' <>)+ , env = ifNotJsonModEnv (outputs' <>) } - drvPath <- pathToText <$> writeDerivation drv'+ (coerce @Text @VarName -> drvPath) <- pathToText <$> writeDerivation drv' -- Memoize here, as it may be our last chance in case of readonly stores. drvHash <- Store.encodeDigestWith Store.Base16 <$> hashDerivationModulo drv'- modify $ second $ MS.insert drvPath drvHash+ modify $ second $ MS.insert (coerce drvPath) drvHash let outputsWithContext = Map.mapWithKey- (\out path -> makeNixStringWithSingletonContext path $ StringContext drvPath $ DerivationOutput out)+ (\out (coerce -> path) -> mkNixStringWithSingletonContext path $ StringContext drvPath $ DerivationOutput out) (outputs drv')- drvPathWithContext = makeNixStringWithSingletonContext drvPath $ StringContext drvPath AllOutputs+ drvPathWithContext = mkNixStringWithSingletonContext drvPath $ StringContext drvPath AllOutputs attrSet = nvStr <$> M.fromList (("drvPath", drvPathWithContext) : Map.toList outputsWithContext) -- TODO: Add location information for all the entries. -- here --v- pure $ nvSet mempty attrSet+ pure $ nvSet mempty (M.mapKeys coerce attrSet) where pathToText = decodeUtf8 . Store.storePathToRawFilePath makeOutputPath o h n = do- name <- makeStorePathName $ Store.unStorePathName n <> if o == "out" then "" else "-" <> o+ name <- makeStorePathName $ Store.unStorePathName n <> if o == "out" then mempty else "-" <> o pure $ pathToText $ Store.makeStorePath "/nix/store" ("output:" <> encodeUtf8 o) h name - toStorePaths ctx = foldl (flip addToInputs) (mempty, mempty) ctx+ toStorePaths :: HashSet StringContext -> (Set Text, Map Text [Text])+ toStorePaths = foldl (flip addToInputs) mempty++ addToInputs :: Bifunctor p => StringContext -> p (Set Text) (Map Text [Text]) -> p (Set Text) (Map Text [Text]) addToInputs (StringContext path kind) = case kind of- DirectPath -> first (Set.insert path)- DerivationOutput o -> second (Map.insertWith (<>) path [o])+ DirectPath -> first (Set.insert (coerce path))+ DerivationOutput o -> second (Map.insertWith (<>) (coerce path) $ one o) AllOutputs -> -- TODO: recursive lookup. See prim_derivationStrict -- XXX: When is this really used ?@@ -316,7 +321,7 @@ -- | Build a derivation in a context collecting string contexts. -- This is complex from a typing standpoint, but it allows to perform the -- full computation without worrying too much about all the string's contexts.-buildDerivationWithContext :: forall e t f m. (MonadNix e t f m) => AttrSet (NValue t f m) -> WithStringContextT m Derivation+buildDerivationWithContext :: forall e t f m. (MonadNix e t f m) => KeyMap (NValue t f m) -> WithStringContextT m Derivation buildDerivationWithContext drvAttrs = do -- Parse name first, so we can add an informative frame drvName <- getAttr "name" $ assertDrvStoreName <=< extractNixString@@ -330,13 +335,13 @@ platform <- getAttr "system" $ assertNonNull <=< extractNoCtx mHash <- getAttrOr "outputHash" mempty $ (pure . pure) <=< extractNoCtx hashMode <- getAttrOr "outputHashMode" Flat $ parseHashMode <=< extractNoCtx- outputs <- getAttrOr "outputs" ["out"] $ traverse (extractNoCtx <=< fromValue')+ outputs <- getAttrOr "outputs" (one "out") $ traverse (extractNoCtx <=< fromValue') mFixedOutput <- maybe (pure Nothing) (\ hash -> do- when (outputs /= ["out"]) $ lift $ throwError $ ErrorCall "Multiple outputs are not supported for fixed-output derivations"+ when (outputs /= one "out") $ lift $ throwError $ ErrorCall "Multiple outputs are not supported for fixed-output derivations" hashType <- getAttr "outputHashAlgo" extractNoCtx digest <- lift $ either (throwError . ErrorCall) pure $ Store.mkNamedDigest hashType hash pure $ pure digest)@@ -362,7 +367,7 @@ env <- if useJson then do- jsonString :: NixString <- lift $ nvalueToJSONNixString $ nvSet mempty $+ jsonString :: NixString <- lift $ nvalueToJSONNixString $ nvSet mempty $ M.mapKeys coerce $ deleteKeys [ "args", "__ignoreNulls", "__structuredAttrs" ] attrs rawString :: Text <- extractNixString jsonString pure $ one ("__json", rawString)@@ -374,7 +379,7 @@ , name = drvName , outputs = Map.fromList $ (, mempty) <$> outputs , mFixed = mFixedOutput- , inputs = (mempty, mempty) -- stub for now+ , inputs = mempty -- stub for now } where @@ -386,7 +391,7 @@ withFrame' :: (Framed e m, Exception s) => NixLevel -> s -> WithStringContextT m a -> WithStringContextT m a withFrame' level f = join . lift . withFrame level f . pure - -- shortcuts to get the (forced) value of an AttrSet field+ -- shortcuts to get the (forced) value of an KeyMap field getAttrOr' :: forall v a. (MonadNix e t f m, FromValue v m (NValue' t f m (NValue t f m))) => Text -> m a -> (v -> WithStringContextT m a) -> WithStringContextT m a@@ -395,7 +400,7 @@ Just v -> withFrame' Info (ErrorCall $ "While evaluating attribute '" <> show n <> "'") $ f =<< fromValue' v - getAttrOr n d f = getAttrOr' n (pure d) f+ getAttrOr n = getAttrOr' n . pure getAttr n = getAttrOr' n (throwError $ ErrorCall $ "Required attribute '" <> show n <> "' not found.") @@ -431,6 +436,6 @@ -- Other helpers - deleteKeys :: [Text] -> AttrSet a -> AttrSet a+ deleteKeys :: [Text] -> KeyMap a -> KeyMap a deleteKeys keys attrSet = foldl' (flip M.delete) attrSet keys
src/Nix/Eval.hs view
@@ -1,38 +1,39 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language RankNTypes #-} module Nix.Eval where +import Relude.Extra ( set ) import Control.Monad ( foldM ) import Control.Monad.Fix ( MonadFix )+import GHC.Exception ( ErrorCall(ErrorCall) ) import Data.Semialign.Indexed ( ialignWith ) import qualified Data.HashMap.Lazy as M import Data.List ( partition ) import Data.These ( These(..) ) import Nix.Atoms import Nix.Convert-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Expr.Strings ( runAntiquoted ) import Nix.Frames import Nix.String import Nix.Scope-import Nix.Utils import Nix.Value.Monad class (Show v, Monad m) => MonadEval v m where- freeVariable :: Text -> m v- synHole :: Text -> m v- attrMissing :: NonEmpty Text -> Maybe v -> m v- evaledSym :: Text -> v -> m v+ freeVariable :: VarName -> m v+ synHole :: VarName -> m v+ attrMissing :: NonEmpty VarName -> Maybe v -> m v+ evaledSym :: VarName -> v -> m v evalCurPos :: m v evalConstant :: NAtom -> m v evalString :: NString (m v) -> m v- evalLiteralPath :: FilePath -> m v- evalEnvPath :: FilePath -> m v+ evalLiteralPath :: Path -> m v+ evalEnvPath :: Path -> m v evalUnary :: NUnaryOp -> v -> m v evalBinary :: NBinaryOp -> v -> m v -> m v -- ^ The second argument is an action because operators such as boolean &&@@ -60,9 +61,9 @@ evalListElem :: [m v] -> Int -> m v -> m v evalList :: [v] -> m v evalSetElem :: AttrSet (m v) -> Text -> m v -> m v- evalSet :: AttrSet v -> AttrSet SourcePos -> m v+ evalSet :: AttrSet v -> PositionSet -> m v evalRecSetElem :: AttrSet (m v) -> Text -> m v -> m v- evalRecSet :: AttrSet v -> AttrSet SourcePos -> m v+ evalRecSet :: AttrSet v -> PositionSet -> m v evalLetElem :: Text -> m v -> m v evalLet :: m v -> m v -}@@ -76,8 +77,8 @@ , ToValue Bool m v , ToValue [v] m v , FromValue NixString m v- , ToValue (AttrSet v, AttrSet SourcePos) m v- , FromValue (AttrSet v, AttrSet SourcePos) m v+ , ToValue (AttrSet v, PositionSet) m v+ , FromValue (AttrSet v, PositionSet) m v ) data EvalFrame m v@@ -129,12 +130,12 @@ lav <- larg evalBinary op lav rarg -eval (NSelect aset attr alt ) =+eval (NSelect alt aset attr) = do let useAltOrReportMissing (s, ks) = fromMaybe (attrMissing ks $ pure s) alt eAttr <- evalSelect aset attr- either useAltOrReportMissing id eAttr+ either useAltOrReportMissing id (coerce eAttr) eval (NHasAttr aset attr) = do@@ -144,23 +145,17 @@ eval (NList l ) = do scope <- currentScopes- lst <- traverse (defer @v @m . withScopes @v scope) l- toValue lst--eval (NSet NNonRecursive binds) =- do- attrSet <- evalBinds False $ desugarBinds (eval . NSet NNonRecursive) binds- toValue attrSet+ toValue =<< traverse (defer @v @m . withScopes @v scope) l -eval (NSet NRecursive binds) =+eval (NSet r binds) = do- attrSet <- evalBinds True $ desugarBinds (eval . NSet NNonRecursive) binds+ attrSet <- evalBinds (r == Recursive) $ desugarBinds (eval . NSet mempty) binds toValue attrSet eval (NLet binds body ) = do (attrSet, _) <- evalBinds True binds- pushScope attrSet body+ pushScope (coerce attrSet) body eval (NIf cond t f ) = do@@ -179,78 +174,97 @@ -- needs to be used when evaluating the body and default arguments, hence we -- defer here so the present scope is restored when the parameters and body -- are forced during application.- scope <- currentScopes :: m (Scopes m v)+ curScope <- currentScopes let- withScope = withScopes scope- withScopeInform = withScope . inform+ withCurScope = withScopes curScope - evalAbs- params- (\arg k ->- withScope $+ fun :: m v -> (AttrSet (m v) -> m v -> m r) -> m r+ fun arg k =+ withCurScope $ do- args <- buildArgument params arg+ (coerce -> newScopeToAdd) <- buildArgument params arg pushScope- args $+ newScopeToAdd $ k- (withScopeInform <$> args)+ (coerce $ withCurScope . inform <$> newScopeToAdd) body- ) + evalAbs+ params+ fun+ eval (NSynHole name) = synHole name -- | If you know that the 'scope' action will result in an 'AttrSet v', then -- this implementation may be used as an implementation for 'evalWith'. evalWithAttrSet :: forall v m . MonadNixEval v m => m v -> m v -> m v evalWithAttrSet aset body = do- scope <- currentScopes :: m (Scopes m v)+ scopes <- currentScopes :: m (Scopes m v) -- The scope is deliberately wrapped in a thunk here, since it is demanded -- each time a name is looked up within the weak scope, and we want to be -- sure the action it evaluates is to force a thunk, so its value is only -- computed once.- deferredAset <- defer $ withScopes scope aset- let attrSet = fst <$> (fromValue @(AttrSet v, AttrSet SourcePos) =<< demand deferredAset)+ deferredAset <- defer $ withScopes scopes aset+ let weakscope = coerce . fst <$> (fromValue @(AttrSet v, PositionSet) =<< demand deferredAset) - pushWeakScope attrSet body+ pushWeakScope weakscope body attrSetAlter :: forall v m . MonadNixEval v m- => [Text]+ => [VarName] -> SourcePos -> AttrSet (m v)- -> AttrSet SourcePos+ -> PositionSet -> m v- -> m (AttrSet (m v), AttrSet SourcePos)-attrSetAlter [] _ _ _ _ = evalError @v $ ErrorCall "invalid selector with no components"-attrSetAlter (k : ks) pos m p val =- bool- go- (maybe- (recurse mempty mempty)- (\x ->- do- (st, sp) <- fromValue @(AttrSet v, AttrSet SourcePos) =<< x- recurse (demand <$> st) sp- )- (M.lookup k m)- )- (not $ null ks)+ -> m (AttrSet (m v), PositionSet)+attrSetAlter ks' pos m' p' val =+ swap <$> go p' m' ks' where- go = pure (M.insert k val m, M.insert k pos p)-- recurse st sp =- (\(st', _) ->- (M.insert- k- (toValue @(AttrSet v, AttrSet SourcePos) =<< (, mempty) <$> sequence st')- m- , M.insert k pos p+ -- This `go` does traverse in disquise. Notice how it traverses `ks`.+ go+ :: PositionSet+ -> AttrSet (m v)+ -> [VarName]+ -> m (PositionSet, AttrSet (m v))+ go _ _ [] = evalError @v $ ErrorCall "invalid selector with no components"+ go p m (k : ks) =+ bool+ (pure $ insertVal val)+ (maybe+ (recurse mempty mempty)+ (\x ->+ do+ -- 2021-10-12: NOTE: swapping sourcewide into (PositionSet, AttrSet) would optimize code and remove this `swap`+ (swap -> (sp, st)) <- fromValue @(AttrSet v, PositionSet) =<< x+ recurse sp $ demand <$> st+ )+ ((`M.lookup` m) k) )- ) <$> attrSetAlter ks pos st sp val+ (not $ null ks)+ where+ insertVal :: m v -> (PositionSet, AttrSet (m v))+ insertVal v =+ ( insertPos+ , insertV v+ )+ where+ insertV v' = M.insert k v' m+ insertPos = M.insert k pos p + recurse+ :: PositionSet+ -> AttrSet (m v)+ -> m ( PositionSet+ , AttrSet (m v)+ )+ recurse p'' m'' =+ fmap+ (insertVal . (=<<) (toValue @(AttrSet v, PositionSet)) . fmap (,mempty) . sequenceA . snd)+ (go p'' m'' ks)+ desugarBinds :: forall r . ([Binding r] -> r) -> [Binding r] -> [Binding r]-desugarBinds embed binds = evalState (traverse (go <=< collect) binds) mempty+desugarBinds embed binds = evalState (traverse (findBinding <=< collect) binds) mempty where collect :: Binding r@@ -261,76 +275,79 @@ do m <- get put $- M.insert- x- (maybe- (p, [bindValAt p])- (\ (q, v) -> (q, bindValAt q : v))- (M.lookup x m)+ join+ (M.insert+ x+ . maybe+ (p, one $ bindValAt p)+ (\ (sp, bnd) -> (sp, one (bindValAt sp) <> bnd))+ . M.lookup x ) m pure $ Left x where- bindValAt pos = NamedVar (y :| ys) val pos+ bindValAt = NamedVar (y :| ys) val collect x = pure $ pure x - go+ findBinding :: Either VarName (Binding r) -> State (HashMap VarName (SourcePos, [Binding r])) (Binding r)- go =+ findBinding = either- (\ x -> do- maybeValue <- gets $ M.lookup x+ (\ x -> maybe (error $ "No binding " <> show x)- (\ (p, v) -> pure $ NamedVar (StaticKey x :| mempty) (embed v) p)- maybeValue+ (\ (p, v) -> pure $ NamedVar (one $ StaticKey x) (embed v) p)+ =<< gets (M.lookup x) ) pure evalBinds :: forall v m . MonadNixEval v m+-- 2021-07-19: NOTE: Recutsivity data type => Bool -> [Binding (m v)]- -> m (AttrSet v, AttrSet SourcePos)-evalBinds recursive binds =+-- 2021-07-19: NOTE: AttrSet is a Scope+ -> m (AttrSet v, PositionSet)+evalBinds isRecursive binds = do scope <- currentScopes :: m (Scopes m v) - buildResult scope . concat =<< traverse (applyBindToAdt scope) (moveOverridesLast binds)+ buildResult scope . fold =<< (`traverse` moveOverridesLast binds) (applyBindToAdt scope) where buildResult :: Scopes m v- -> [([Text], SourcePos, m v)]- -> m (AttrSet v, AttrSet SourcePos)- buildResult scope bindings =+ -> [([VarName], SourcePos, m v)]+ -> m (AttrSet v, PositionSet)+ buildResult scopes bindings = do- (s, p) <- foldM insert (mempty, mempty) bindings+ (coerce -> scope, p) <- foldM insert mempty bindings res <- bool- (traverse mkThunk s)- (loebM $ encapsulate <$> s)- recursive+ (traverse mkThunk)+ (loebM . fmap encapsulate)+ isRecursive+ scope - pure (res, p)+ pure (coerce res, p) where insert (m, p) (path, pos, value) = attrSetAlter path pos m p value - mkThunk = defer . withScopes scope+ mkThunk = defer . withScopes scopes encapsulate f attrs = mkThunk $ pushScope attrs f - applyBindToAdt :: Scopes m v -> Binding (m v) -> m [([Text], SourcePos, m v)]+ applyBindToAdt :: Scopes m v -> Binding (m v) -> m [([VarName], SourcePos, m v)] applyBindToAdt _ (NamedVar (StaticKey "__overrides" :| []) finalValue pos) = do (o', p') <- fromValue =<< finalValue -- jww (2018-05-09): What to do with the key position here? pure $ (\ (k, v) ->- ( [k]+ ( one k , fromMaybe pos $ M.lookup k p' , demand v )@@ -341,19 +358,19 @@ -- When there are no path segments, e.g. `${null} = 5;`, we don't -- bind anything ([], _, _) -> mempty- result -> [result]+ result -> one result ) <$> processAttrSetKeys pathExpr where- processAttrSetKeys :: NAttrPath (m v) -> m ([Text], SourcePos, m v)+ processAttrSetKeys :: NAttrPath (m v) -> m ([VarName], SourcePos, m v) processAttrSetKeys (h :| t) = maybe -- Empty attrset - return a stub.- (pure ( mempty, nullPos, toValue @(AttrSet v, AttrSet SourcePos) (mempty, mempty)) )+ (pure (mempty, nullPos, toValue @(AttrSet v, PositionSet) mempty) ) (\ k -> list -- No more keys in the attrset - return the result- (pure ( [k], pos, finalValue ) )+ (pure ( one k, pos, finalValue ) ) -- There are unprocessed keys in attrset - recurse appending the results (\ (x : xs) -> do@@ -364,37 +381,28 @@ ) =<< evalSetterKeyName h - applyBindToAdt scope (Inherit ms names pos) =- catMaybes <$>- traverse- processScope- names+ applyBindToAdt scopes (Inherit ms names pos) =+ pure $ processScope <$> names where processScope- :: NKeyName (m v)- -> m (Maybe ([Text], SourcePos, m v))- processScope nkeyname =- (\ mkey ->- do- key <- mkey- pure- ([key]- , pos- , maybe- (attrMissing (key :| mempty) Nothing)- demand- =<< maybe- (withScopes scope $ lookupVar key)- (\ s ->- do- (attrset, _) <- fromValue @(AttrSet v, AttrSet SourcePos) =<< s+ :: VarName+ -> ([VarName], SourcePos, m v)+ processScope var =+ ( one var+ , pos+ , maybe+ (attrMissing (one var) Nothing)+ demand+ =<< maybe+ (withScopes scopes $ lookupVar var)+ (\ s ->+ do+ (coerce -> scope, _) <- fromValue @(AttrSet v, PositionSet) =<< s - clearScopes @v $ pushScope attrset $ lookupVar key- )- ms- )- ) <$>- evalSetterKeyName nkeyname+ clearScopes $ pushScope @v scope $ lookupVar var+ )+ ms+ ) moveOverridesLast = uncurry (<>) . partition (\case@@ -407,30 +415,33 @@ . MonadNixEval v m => m v -> NAttrPath (m v)- -> m (Either (v, NonEmpty Text) (m v))+ -> m (Either (v, NonEmpty VarName) (m v)) evalSelect aset attr = do s <- aset path <- traverse evalGetterKeyName attr - extract s path+ extract path s where- extract x path@(k :| ks) =- do- x' <- fromValueMay x-- case x' of- Nothing -> pure $ Left (x, path)- Just (s :: AttrSet v, p :: AttrSet SourcePos)- | Just t <- M.lookup k s ->- do- list- (pure . pure)- (\ (y : ys) -> ((`extract` (y :| ys)) =<<))- ks- $ demand t- | otherwise -> Left . (, path) <$> toValue (s, p)+ extract :: NonEmpty VarName -> v -> m (Either (v, NonEmpty VarName) (m v))+ extract path@(k :| ks) x =+ maybe+ left+ (maybe+ left+ (list+ (pure . pure)+ (\ (y : ys) -> (extract (y :| ys) =<<))+ ks+ . demand+ )+ . M.lookup k . fst+ )+ =<< fromValueMay @(AttrSet v, PositionSet) x+ where+ left :: m (Either (v, NonEmpty VarName) b)+ left = pure $ Left (x, path) -- | Evaluate a component of an attribute path in a context where we are -- *retrieving* a value@@ -438,7 +449,7 @@ :: forall v m . (MonadEval v m, FromValue NixString m v) => NKeyName (m v)- -> m Text+ -> m VarName evalGetterKeyName = maybe (evalError @v $ ErrorCall "value is null while a string was expected")@@ -450,33 +461,29 @@ evalSetterKeyName :: (MonadEval v m, FromValue NixString m v) => NKeyName (m v)- -> m (Maybe Text)+ -> m (Maybe VarName) evalSetterKeyName = \case StaticKey k -> pure $ pure k DynamicKey k ->- maybe- mempty- (pure . stringIgnoreContext)- <$> runAntiquoted "\n" assembleString (fromValueMay =<<) k+ (coerce . stringIgnoreContext) <<$>>+ runAntiquoted "\n" assembleString (fromValueMay =<<) k assembleString :: forall v m . (MonadEval v m, FromValue NixString m v) => NString (m v) -> m (Maybe NixString)-assembleString =- fromParts .- \case- Indented _ parts -> parts- DoubleQuoted parts -> parts+assembleString = fromParts . stringParts where- fromParts xs = (mconcat <$>) . sequence <$> traverse go xs+ fromParts :: [Antiquoted Text (m v)] -> m (Maybe NixString)+ fromParts xs = fold <<$>> traverseM fun xs - go =+ fun :: Antiquoted Text (m v) -> m (Maybe NixString)+ fun = runAntiquoted "\n"- (pure . pure . makeNixStringWithoutContext)+ (pure . pure . mkNixStringWithoutContext) (fromValueMay =<<) buildArgument@@ -484,43 +491,42 @@ buildArgument params arg = do scope <- currentScopes :: m (Scopes m v)- let argThunk = defer $ withScopes scope arg+ let+ argThunk = defer $ withScopes scope arg case params of- Param name -> M.singleton name <$> argThunk- ParamSet s isVariadic m ->+ Param name -> one . (name,) <$> argThunk+ ParamSet mname variadic pset -> do- (args, _) <- fromValue @(AttrSet v, AttrSet SourcePos) =<< arg+ (args, _) <- fromValue @(AttrSet v, PositionSet) =<< arg let inject = maybe id- (\ n -> M.insert n $ const argThunk) -- why insert into const?- m- loebM- (inject $- M.mapMaybe- id- (ialignWith- (assemble scope isVariadic)+ (`M.insert` const argThunk) -- why insert into const? Thunk value getting magic point?+ mname+ loebM $+ inject $+ M.mapMaybe+ id+ $ ialignWith+ (assemble scope variadic) args- $ M.fromList s- )- )+ $ M.fromList pset where assemble :: Scopes m v- -> Bool- -> Text+ -> Variadic+ -> VarName -> These v (Maybe (m v)) -> Maybe (AttrSet v -> m v)- assemble scope isVariadic k =- \case- That Nothing -> pure $ const $ evalError @v $ ErrorCall $ "Missing value for parameter: " <> show k- That (Just f) -> pure $ \args -> defer $ withScopes scope $ pushScope args f- This _- | isVariadic -> Nothing- | otherwise -> pure $ const $ evalError @v $ ErrorCall $ "Unexpected parameter: " <> show k- These x _ -> pure $ const $ pure x+ assemble _ Variadic _ (This _) = Nothing+ assemble scope _ k t =+ pure $+ case t of+ That Nothing -> const $ evalError @v $ ErrorCall $ "Missing value for parameter: ''" <> show k+ That (Just f) -> coerce $ defer . withScopes scope . (`pushScope` f)+ This _ -> const $ evalError @v $ ErrorCall $ "Unexpected parameter: " <> show k+ These x _ -> const $ pure x -- | Add source positions to @NExprLoc@. --@@ -533,7 +539,7 @@ -- > -> NExprLoc -> m a addSourcePositions :: (MonadReader e m, Has e SrcSpan) => Transform NExprLocF (m a)-addSourcePositions f (v@(AnnE ann _) :: NExprLoc) =+addSourcePositions f (v@(Ann ann _) :: NExprLoc) = local (set hasLens ann) $ f v addStackFrames@@ -571,4 +577,4 @@ :: MonadNixEval v m => AnnF ann NExprF (m v) -> m v-evalContent = eval . stripAnn+evalContent = eval . stripAnnF
src/Nix/Exec.hs view
@@ -1,14 +1,13 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language AllowAmbiguousTypes #-}+{-# language CPP #-}+{-# language ConstraintKinds #-}+{-# language PartialTypeSignatures #-}+{-# language RankNTypes #-}+{-# language TypeFamilies #-}+{-# language UndecidableInstances #-} -{-# OPTIONS_GHC -Wno-orphans #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -Wno-orphans #-}+{-# options_ghc -fno-warn-name-shadowing #-} module Nix.Exec where@@ -17,7 +16,7 @@ , putStrLn , print )-+import GHC.Exception ( ErrorCall(ErrorCall) ) import Control.Monad.Catch hiding ( catchJust ) import Control.Monad.Fix import Data.Fix@@ -29,7 +28,8 @@ import Nix.Convert import Nix.Effects import Nix.Eval as Eval-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Options import Nix.Pretty@@ -38,7 +38,6 @@ import Nix.String import Nix.String.Coerce import Nix.Thunk-import Nix.Utils import Nix.Value import Nix.Value.Equal import Nix.Value.Monad@@ -72,7 +71,7 @@ nvPathP :: MonadCited t f m => Provenance m (NValue t f m)- -> FilePath+ -> Path -> NValue t f m nvPathP p x = addProvenance p $ nvPath x @@ -86,7 +85,7 @@ nvSetP :: MonadCited t f m => Provenance m (NValue t f m)- -> AttrSet SourcePos+ -> PositionSet -> AttrSet (NValue t f m) -> NValue t f m nvSetP p x s = addProvenance p $ nvSet x s@@ -102,7 +101,7 @@ nvBuiltinP :: MonadCited t f m => Provenance m (NValue t f m)- -> Text+ -> VarName -> (NValue t f m -> m (NValue t f m)) -> NValue t f m nvBuiltinP p name f = addProvenance p $ nvBuiltin name f@@ -140,21 +139,21 @@ currentPos = asks $ view hasLens wrapExprLoc :: SrcSpan -> NExprLocF r -> NExprLoc-wrapExprLoc span x = Fix $ Fix (NSym_ span "<?>") <$ x+wrapExprLoc span x = Fix $ NSymAnn span "<?>" <$ x {-# inline wrapExprLoc #-} -- 2021-01-07: NOTE: This instance belongs to be beside MonadEval type class. -- Currently instance is stuck in orphanage between the requirements to be MonadEval, aka Eval stage, and emposed requirement to be MonadNix (Execution stage). MonadNix constraint tries to put the cart before horse and seems superflous, since Eval in Nix also needs and can throw exceptions. It is between `nverr` and `evalError`. instance MonadNix e t f m => MonadEval (NValue t f m) m where freeVariable var =- nverr @e @t @f $ ErrorCall $ "Undefined variable '" <> toString var <> "'"+ nverr @e @t @f $ ErrorCall $ toString @Text $ "Undefined variable '" <> coerce var <> "'" synHole name = do span <- currentPos scope <- currentScopes evalError @(NValue t f m) $ SynHole $ SynHoleInfo- { _synHoleInfo_expr = Fix $ NSynHole_ span name+ { _synHoleInfo_expr = NSynHoleAnn span name , _synHoleInfo_scope = scope } @@ -168,13 +167,13 @@ ) ms where- attr = Text.intercalate "." $ NE.toList ks+ attr = Text.intercalate "." $ NE.toList $ coerce ks evalCurPos = do scope <- currentScopes span@(SrcSpan delta _) <- currentPos addProvenance @_ @_ @(NValue t f m)- (Provenance scope $ NSym_ span "__curPos") <$>+ (Provenance scope $ NSymAnnF span (coerce @Text "__curPos")) <$> toValue delta evaledSym name val = do@@ -182,13 +181,13 @@ span <- currentPos pure $ addProvenance @_ @_ @(NValue t f m)- (Provenance scope $ NSym_ span name)+ (Provenance scope $ NSymAnnF span name) val evalConstant c = do scope <- currentScopes span <- currentPos- pure $ nvConstantP (Provenance scope $ NConstant_ span c) c+ pure $ join (nvConstantP . Provenance scope . NConstantAnnF span) c evalString = maybe@@ -198,10 +197,11 @@ scope <- currentScopes span <- currentPos pure $- nvStrP- (Provenance- scope- (NStr_ span $ DoubleQuoted [Plain $ stringIgnoreContext ns])+ join+ (nvStrP+ . Provenance+ scope+ . NStrAnnF span . DoubleQuoted . one . Plain . stringIgnoreContext ) ns )@@ -210,14 +210,24 @@ evalLiteralPath p = do scope <- currentScopes span <- currentPos- nvPathP (Provenance scope $ NLiteralPath_ span p) <$>- makeAbsolutePath @t @f @m p+ let+ evalPath :: Path -> m (NValue t f m)+ evalPath p1 =+ fmap+ (g p1)+ (f p1)+ where+ g :: Path -> Path -> NValue t f m+ g = nvPathP . Provenance scope . NLiteralPathAnnF span+ f :: Path -> m Path+ f = toAbsolutePath @t @f @m+ evalPath p evalEnvPath p = do scope <- currentScopes span <- currentPos- nvPathP (Provenance scope $ NEnvPath_ span p) <$>- findEnvPath @t @f @m p+ nvPathP (Provenance scope $ NEnvPathAnnF span p) <$>+ findEnvPath @t @f @m (coerce p) evalUnary op arg = do scope <- currentScopes@@ -232,24 +242,24 @@ evalWith c b = do scope <- currentScopes span <- currentPos- let f = join $ addProvenance . Provenance scope . NWith_ span Nothing . pure+ let f = join $ addProvenance . Provenance scope . NWithAnnF span Nothing . pure f <$> evalWithAttrSet c b - evalIf c t f = do+ evalIf c tVal fVal = do scope <- currentScopes span <- currentPos- b <- fromValue c+ bl <- fromValue c let- fun x y z = addProvenance (Provenance scope $ NIf_ span (pure c) x y) z+ fun x y = addProvenance (Provenance scope $ NIfAnnF span (pure c) x y) -- Note: join acts as \ f x -> f x x- false = join (fun Nothing . pure) <$> f- true = join (flip fun Nothing . pure) <$> t+ falseVal = join (fun Nothing . pure) <$> fVal+ trueVal = join (flip fun Nothing . pure) <$> tVal bool- false- true- b+ falseVal+ trueVal+ bl evalAssert c body = do@@ -259,25 +269,26 @@ (nverr $ Assertion span c) (do scope <- currentScopes- let f = join (addProvenance . Provenance scope . NAssert_ span (pure c) . pure)- f <$> body+ join (addProvenance . Provenance scope . NAssertAnnF span (pure c) . pure) <$> body ) b evalApp f x = do scope <- currentScopes span <- currentPos- addProvenance (Provenance scope $ NBinary_ span NApp (pure f) Nothing) <$>+ addProvenance (Provenance scope $ NBinaryAnnF span NApp (pure f) Nothing) <$> (callFunc f =<< defer x) evalAbs p k = do+ let+ fk = flip k scope <- currentScopes span <- currentPos pure $ nvClosureP- (Provenance scope $ NAbs_ span (Nothing <$ p) Nothing)+ (Provenance scope $ NAbsAnnF span (Nothing <$ p) Nothing) (void p)- (\arg -> snd <$> k (pure arg) (\_ b -> ((), ) <$> b))+ $ fmap snd . fk (const $ fmap ((), )) . pure evalError = throwError @@ -299,8 +310,8 @@ NVBuiltin name f -> do span <- currentPos- withFrame Info ((Calling @m @(NValue t f m)) name span) $ f arg -- Is this cool?- (NVSet m _) | Just f <- M.lookup "__functor" m ->+ withFrame Info ((Calling @m @(NValue t f m)) (coerce name) span) $ f arg -- Is this cool?+ (NVSet _ m) | Just f <- M.lookup "__functor" m -> (`callFunc` arg) =<< (`callFunc` fun') =<< demand f _x -> throwError $ ErrorCall $ "Attempt to call non-function: " <> show _x @@ -311,7 +322,7 @@ -> NUnaryOp -> NValue t f m -> m (NValue t f m)-execUnaryOp scope span op arg = do+execUnaryOp scope span op arg = case arg of NVConstant c -> case (op, c) of@@ -323,7 +334,7 @@ _x -> throwError $ ErrorCall $ "argument to unary operator must evaluate to an atomic type: " <> show _x where- unaryOp = pure . nvConstantP (Provenance scope $ NUnary_ span op $ pure arg)+ unaryOp = pure . nvConstantP (Provenance scope $ NUnaryAnnF span op $ pure arg) execBinaryOp :: forall e t f m@@ -351,6 +362,7 @@ where + helperEq :: (Bool -> Bool) -> m (NValue t f m) helperEq flag = do rval <- rarg@@ -375,7 +387,7 @@ toBoolOp r b = pure $ nvConstantP- (Provenance scope $ NBinary_ span op (pure lval) r)+ (Provenance scope $ NBinaryAnnF span op (pure lval) r) (NBool b) execBinaryOpForced@@ -403,9 +415,9 @@ NUpdate -> case (lval, rval) of- (NVSet ls lp, NVSet rs rp) -> pure $ nvSetP prov (rp <> lp) (rs <> ls)- (NVSet ls lp, NVConstant NNull) -> pure $ nvSetP prov lp ls- (NVConstant NNull, NVSet rs rp) -> pure $ nvSetP prov rp rs+ (NVSet lp ls, NVSet rp rs) -> pure $ nvSetP prov (rp <> lp) (rs <> ls)+ (NVSet lp ls, NVConstant NNull) -> pure $ nvSetP prov lp ls+ (NVConstant NNull, NVSet rp rs) -> pure $ nvSetP prov rp rs _ -> unsupportedTypes NPlus ->@@ -421,10 +433,10 @@ (throwError $ ErrorCall "A string that refers to a store path cannot be appended to a path.") -- data/nix/src/libexpr/eval.cc:1412 (\ rs2 -> nvPathP prov <$>- makeAbsolutePath @t @f (ls <> toString rs2)+ toAbsolutePath @t @f (ls <> coerce (toString rs2)) ) (getStringNoContext rs)- (NVPath ls, NVPath rs) -> nvPathP prov <$> makeAbsolutePath @t @f (ls <> rs)+ (NVPath ls, NVPath rs) -> nvPathP prov <$> toAbsolutePath @t @f (ls <> rs) (ls@NVSet{}, NVStr rs) -> (\ls2 -> nvStrP prov (ls2 <> rs)) <$>@@ -443,7 +455,7 @@ where prov :: Provenance m (NValue t f m)- prov = Provenance scope $ NBinary_ span op (pure lval) (pure rval)+ prov = Provenance scope $ NBinaryAnnF span op (pure lval) (pure rval) toBool = pure . nvConstantP prov . NBool compare :: (forall a. Ord a => a -> a -> Bool) -> m (NValue t f m)@@ -452,8 +464,8 @@ (NVStr l, NVStr r) -> toBool $ l `op` r _ -> unsupportedTypes - toInt = pure . nvConstantP prov . NInt- toFloat = pure . nvConstantP prov . NFloat+ nvInt = pure . nvConstantP prov . NInt+ nvFloat = pure . nvConstantP prov . NFloat numBinOp :: (forall a. Num a => a -> a -> a) -> m (NValue t f m) numBinOp op = numBinOp' op op@@ -462,13 +474,12 @@ :: (Integer -> Integer -> Integer) -> (Float -> Float -> Float) -> m (NValue t f m)- numBinOp' intOp floatOp = case (lval, rval) of (NVConstant l, NVConstant r) -> case (l, r) of- (NInt li, NInt ri) -> toInt $ li `intOp` ri- (NInt li, NFloat rf) -> toFloat $ fromInteger li `floatOp` rf- (NFloat lf, NInt ri) -> toFloat $ lf `floatOp` fromInteger ri- (NFloat lf, NFloat rf) -> toFloat $ lf `floatOp` rf+ (NInt li, NInt ri) -> nvInt $ li `intOp` ri+ (NInt li, NFloat rf) -> nvFloat $ fromInteger li `floatOp` rf+ (NFloat lf, NInt ri) -> nvFloat $ lf `floatOp` fromInteger ri+ (NFloat lf, NFloat rf) -> nvFloat $ lf `floatOp` rf _ -> unsupportedTypes _ -> unsupportedTypes @@ -502,7 +513,7 @@ depth <- ask guard $ depth < 2000 local succ $ do- v'@(AnnFP span x) <- sequence v+ v'@(AnnF span x) <- sequenceA v pure $ do opts :: Options <- asks $ view hasLens let
src/Nix/Expr/Shorthands.hs view
@@ -1,251 +1,447 @@ -- | A bunch of shorthands for making nix expressions. ----- Functions with an @F@ suffix return a more general type without the outer--- 'Fix' wrapper.+-- Functions with an @F@ suffix return a more general type (base functor @F a@) without the outer+-- 'Fix' wrapper that creates @a@. module Nix.Expr.Shorthands where import Data.Fix import Nix.Atoms import Nix.Expr.Types-import Text.Megaparsec.Pos ( SourcePos ) --- | Make an integer literal expression.-mkInt :: Integer -> NExpr-mkInt = Fix . mkIntF+-- * Basic expression builders +-- | Put @NAtom@ as expression+mkConst :: NAtom -> NExpr+mkConst = Fix . NConstant -mkIntF :: Integer -> NExprF a-mkIntF = NConstant . NInt+-- | Put null.+mkNull :: NExpr+mkNull = Fix mkNullF --- | Make an floating point literal expression.+-- | Put boolean.+mkBool :: Bool -> NExpr+mkBool = Fix . mkBoolF++-- | Put integer.+mkInt :: Integer -> NExpr+mkInt = Fix . mkIntF++-- | Put floating point number. mkFloat :: Float -> NExpr mkFloat = Fix . mkFloatF -mkFloatF :: Float -> NExprF a-mkFloatF = NConstant . NFloat---- | Make a regular (double-quoted) string.+-- | Put a regular (double-quoted) string. mkStr :: Text -> NExpr-mkStr = Fix . NStr . DoubleQuoted . \case- "" -> mempty- x -> [Plain x]+mkStr = Fix . NStr . DoubleQuoted .+ whenText+ mempty+ (one . Plain) --- | Make an indented string.+-- | Put an indented string. mkIndentedStr :: Int -> Text -> NExpr-mkIndentedStr w = Fix . NStr . Indented w . \case- "" -> mempty- x -> [Plain x]+mkIndentedStr w = Fix . NStr . Indented w .+ whenText+ mempty+ (one . Plain) --- | Make a path. Use 'True' if the path should be read from the--- environment, else 'False'.+-- | Put a path. Use @True@ if the path should be read from the environment, else use @False@. mkPath :: Bool -> FilePath -> NExpr mkPath b = Fix . mkPathF b -mkPathF :: Bool -> FilePath -> NExprF a-mkPathF False = NLiteralPath-mkPathF True = NEnvPath---- | Make a path expression which pulls from the NIX_PATH env variable.+-- | Put a path expression which pulls from the @NIX_PATH@ @env@ variable. mkEnvPath :: FilePath -> NExpr mkEnvPath = Fix . mkEnvPathF -mkEnvPathF :: FilePath -> NExprF a-mkEnvPathF = mkPathF True---- | Make a path expression which references a relative path.+-- | Put a path which references a relative path. mkRelPath :: FilePath -> NExpr mkRelPath = Fix . mkRelPathF -mkRelPathF :: FilePath -> NExprF a-mkRelPathF = mkPathF False---- | Make a variable (symbol)+-- | Put a variable (symbol). mkSym :: Text -> NExpr mkSym = Fix . mkSymF -mkSymF :: Text -> NExprF a-mkSymF = NSym-+-- | Put syntactic hole. mkSynHole :: Text -> NExpr mkSynHole = Fix . mkSynHoleF -mkSynHoleF :: Text -> NExprF a-mkSynHoleF = NSynHole- mkSelector :: Text -> NAttrPath NExpr-mkSelector = (:| mempty) . StaticKey+mkSelector = one . StaticKey . coerce -mkBool :: Bool -> NExpr-mkBool = Fix . mkBoolF+-- | Put an unary operator.+-- @since 0.15.0+mkOp :: NUnaryOp -> NExpr -> NExpr+mkOp op = Fix . NUnary op -mkBoolF :: Bool -> NExprF a-mkBoolF = NConstant . NBool+-- | Logical negation: @not@.+mkNot :: NExpr -> NExpr+mkNot = mkOp NNot -mkNull :: NExpr-mkNull = Fix mkNullF+-- | Number negation: @-@.+--+-- Negation in the language works with integers and floating point.+-- @since 0.15.0+mkNeg :: NExpr -> NExpr+mkNeg = mkOp NNeg -mkNullF :: NExprF a-mkNullF = NConstant NNull+-- | Put a binary operator.+-- @since 0.15.0+mkOp2 :: NBinaryOp -> NExpr -> NExpr -> NExpr+mkOp2 op a = Fix . NBinary op a -mkOper :: NUnaryOp -> NExpr -> NExpr-mkOper op = Fix . NUnary op+-- | > { x }+-- @since 0.15.0+mkParamSet :: [(Text, Maybe NExpr)] -> Params NExpr+mkParamSet pset = mkGeneralParamSet Nothing pset False -mkOper2 :: NBinaryOp -> NExpr -> NExpr -> NExpr-mkOper2 op a = Fix . NBinary op a+-- | > { x, ... }+-- @since 0.15.0+mkVariadicParamSet :: [(Text, Maybe NExpr)] -> Params NExpr+mkVariadicParamSet pset = mkGeneralParamSet Nothing pset True -mkParamset :: [(Text, Maybe NExpr)] -> Bool -> Params NExpr-mkParamset params variadic = ParamSet params variadic mempty+-- | > s@{ x }+-- @since 0.15.0+mkNamedParamSet :: Text -> [(Text, Maybe NExpr)] -> Params NExpr+mkNamedParamSet name pset = mkGeneralParamSet (pure name) pset False +-- | > s@{ x, ... }+-- @since 0.15.0+mkNamedVariadicParamSet :: Text -> [(Text, Maybe NExpr)] -> Params NExpr+mkNamedVariadicParamSet name params = mkGeneralParamSet (pure name) params True++-- | Args:+--+-- 1. Maybe name:+--+-- > Nothing -> {}+-- > Just "s" -> s@{}+--+-- 2. key:expr pairs+--+-- 3. Is variadic or not:+--+-- > True -> {...}+-- > False -> {}+-- @since 0.15.0+mkGeneralParamSet :: Maybe Text -> [(Text, Maybe NExpr)] -> Bool -> Params NExpr+mkGeneralParamSet mname params variadic = ParamSet (coerce mname) (Variadic `whenTrue` variadic) (coerce params)++-- | > rec { .. } mkRecSet :: [Binding NExpr] -> NExpr-mkRecSet = Fix . NSet NRecursive+mkRecSet = mkSet Recursive +-- | Put a non-recursive set.+--+-- > { .. } mkNonRecSet :: [Binding NExpr] -> NExpr-mkNonRecSet = Fix . NSet NNonRecursive+mkNonRecSet = mkSet mempty -mkLets :: [Binding NExpr] -> NExpr -> NExpr-mkLets bindings = Fix . NLet bindings+-- | General set builder function.+mkSet :: Recursivity -> [Binding NExpr] -> NExpr+mkSet r = Fix . NSet r +-- | Empty set.+--+-- Monoid. Use @//@ operation (shorthand $//) to extend the set.+-- @since 0.15.0+emptySet :: NExpr+emptySet = mkNonRecSet mempty++-- | Put a list. mkList :: [NExpr] -> NExpr mkList = Fix . NList +-- @since 0.15.0+emptyList :: NExpr+emptyList = mkList mempty++-- | Wrap in a @let@.+--+-- (Evaluate the second argument after introducing the bindings.)+--+-- +------------------------+-----------------++-- | Haskell | Nix |+-- +========================+=================++-- | @mkLets bindings expr@ | @let bindings;@ |+-- | | @in expr@ |+-- +------------------------+-----------------++mkLets :: [Binding NExpr] -> NExpr -> NExpr+mkLets bindings = Fix . NLet bindings++-- | Create a @whith@:+-- 1st expr - what to bring into the scope.+-- 2nd - expression that recieves the scope extention.+--+-- +--------------------+-------------------++-- | Haskell | Nix |+-- +====================+===================++-- | @mkWith body main@ | @with body; expr@ |+-- +--------------------+-------------------+ mkWith :: NExpr -> NExpr -> NExpr mkWith e = Fix . NWith e +-- | Create an @assert@:+-- 1st expr - asserting itself, must return @true@.+-- 2nd - main expression to evaluated after assertion.+--+-- +-----------------------+----------------------++-- | Haskell | Nix |+-- +=======================+======================++-- | @mkAssert check eval@ | @assert check; eval@ |+-- +-----------------------+----------------------+ mkAssert :: NExpr -> NExpr -> NExpr-mkAssert e = Fix . NWith e+mkAssert e = Fix . NAssert e +-- | Put:+--+-- > if expr1+-- > then expr2+-- > else expr3 mkIf :: NExpr -> NExpr -> NExpr -> NExpr mkIf e1 e2 = Fix . NIf e1 e2 +-- | Lambda function, analog of Haskell's @\\ x -> x@:+--+-- +-----------------------+-----------++-- | Haskell | Nix |+-- +=======================+===========++-- | @ mkFunction x expr @ | @x: expr@ |+-- +-----------------------+-----------+ mkFunction :: Params NExpr -> NExpr -> NExpr mkFunction params = Fix . NAbs params -{--mkDot :: NExpr -> Text -> NExpr-mkDot e key = mkDots e [key]+-- | General dot-reference with optional alternative if the jey does not exist.+-- @since 0.15.0+getRefOrDefault :: Maybe NExpr -> NExpr -> Text -> NExpr+getRefOrDefault alt obj = Fix . NSelect alt obj . mkSelector --- | Create a dotted expression using only text.-mkDots :: NExpr -> [Text] -> NExpr-mkDots e [] = e-mkDots (Fix (NSelect e keys' x)) keys =- -- Special case: if the expression in the first argument is already- -- a dotted expression, just extend it.- Fix (NSelect e (keys' <> fmap (`StaticKey` Nothing) keys) x)-mkDots e keys = Fix $ NSelect e (fmap (`StaticKey` Nothing) keys) Nothing--}+-- ** Base functor builders for basic expressions builders *sic --- | An `inherit` clause without an expression to pull from.-inherit :: [NKeyName e] -> SourcePos -> Binding e-inherit = Inherit Nothing+-- | Unfixed @mkNull@.+mkNullF :: NExprF a+mkNullF = NConstant NNull +-- | Unfixed @mkBool@.+mkBoolF :: Bool -> NExprF a+mkBoolF = NConstant . NBool++-- | Unfixed @mkInt@.+mkIntF :: Integer -> NExprF a+mkIntF = NConstant . NInt++-- | Unfixed @mkFloat@.+mkFloatF :: Float -> NExprF a+mkFloatF = NConstant . NFloat++-- | Unfixed @mkPath@.+mkPathF :: Bool -> FilePath -> NExprF a+mkPathF False = NLiteralPath . coerce+mkPathF True = NEnvPath . coerce++-- | Unfixed @mkEnvPath@.+mkEnvPathF :: FilePath -> NExprF a+mkEnvPathF = mkPathF True++-- | Unfixed @mkRelPath@.+mkRelPathF :: FilePath -> NExprF a+mkRelPathF = mkPathF False++-- | Unfixed @mkSym@.+mkSymF :: Text -> NExprF a+mkSymF = NSym . coerce++-- | Unfixed @mkSynHole@.+mkSynHoleF :: Text -> NExprF a+mkSynHoleF = NSynHole . coerce+++-- * Other+-- (org this better/make a better name for section(s))+ -- | An `inherit` clause with an expression to pull from.-inheritFrom :: e -> [NKeyName e] -> SourcePos -> Binding e-inheritFrom expr = Inherit (pure expr)+--+-- +------------------------+--------------------+------------++-- | Hask | Nix | pseudocode |+-- +========================+====================+============++-- | @inheritFrom x [a, b]@ | @inherit (x) a b;@ | @a = x.a;@ |+-- | | | @b = x.b;@ |+-- +------------------------+--------------------+------------++inheritFrom :: e -> [VarName] -> Binding e+inheritFrom expr ks = Inherit (pure expr) ks nullPos --- | Shorthand for producing a binding of a name to an expression: @=-bindTo :: Text -> NExpr -> Binding NExpr-bindTo name x = NamedVar (mkSelector name) x nullPos+-- | An `inherit` clause without an expression to pull from.+--+-- +----------------------+----------------+------------------++-- | Hask | Nix | pseudocode |+-- +======================+================+==================++-- | @inheritFrom [a, b]@ | @inherit a b;@ | @a = outside.a;@ |+-- | | | @b = outside.b;@ |+-- +----------------------+----------------+------------------++inherit :: [VarName] -> Binding e+inherit ks = Inherit Nothing ks nullPos --- | Infix version of @bindTo@: @=@+-- | Nix @=@ (bind operator). ($=) :: Text -> NExpr -> Binding NExpr ($=) = bindTo- infixr 2 $= +-- | Shorthand for producing a binding of a name to an expression: Nix's @=@.+bindTo :: Text -> NExpr -> Binding NExpr+bindTo name x = NamedVar (mkSelector name) x nullPos+ -- | Append a list of bindings to a set or let expression.--- For example, adding `[a = 1, b = 2]` to `let c = 3; in 4` produces--- `let a = 1; b = 2; c = 3; in 4`.+-- For example:+-- adding `[a = 1, b = 2]`+-- to `let c = 3; in 4`+-- produces `let a = 1; b = 2; c = 3; in 4`. appendBindings :: [Binding NExpr] -> NExpr -> NExpr-appendBindings newBindings (Fix e) = case e of- NLet bindings e' -> Fix $ NLet (bindings <> newBindings) e'- NSet recur bindings -> Fix $ NSet recur (bindings <> newBindings)- _ -> error "Can only append bindings to a set or a let"+appendBindings newBindings (Fix e) =+ case e of+ NLet bindings e' -> mkLets (bindings <> newBindings) e'+ NSet recur bindings -> Fix $ NSet recur (bindings <> newBindings)+ _ -> error "Can only append bindings to a set or a let" --- | Applies a transformation to the body of a nix function.+-- | Applies a transformation to the body of a Nix function. modifyFunctionBody :: (NExpr -> NExpr) -> NExpr -> NExpr-modifyFunctionBody f (Fix (NAbs params body)) = Fix $ NAbs params $ f body+modifyFunctionBody transform (Fix (NAbs params body)) = mkFunction params $ transform body modifyFunctionBody _ _ = error "Not a function" --- | A let statement with multiple assignments.+-- | A @let@ statement with multiple assignments. letsE :: [(Text, NExpr)] -> NExpr -> NExpr-letsE pairs = Fix . NLet (uncurry bindTo <$> pairs)+letsE pairs = mkLets $ uncurry ($=) <$> pairs -- | Wrapper for a single-variable @let@. letE :: Text -> NExpr -> NExpr -> NExpr-letE varName varExpr = letsE [(varName, varExpr)]+letE varName varExpr = letsE $ one (varName, varExpr) --- | Make an attribute set (non-recursive).+-- | Make a non-recursive attribute set. attrsE :: [(Text, NExpr)] -> NExpr-attrsE pairs = Fix $ NSet NNonRecursive $ uncurry bindTo <$> pairs+attrsE pairs = mkNonRecSet $ uncurry ($=) <$> pairs --- | Make an attribute set (recursive).+-- | Make a recursive attribute set. recAttrsE :: [(Text, NExpr)] -> NExpr-recAttrsE pairs = Fix $ NSet NRecursive $ uncurry bindTo <$> pairs+recAttrsE pairs = mkRecSet $ uncurry ($=) <$> pairs --- | Logical negation.-mkNot :: NExpr -> NExpr-mkNot = Fix . NUnary NNot --- -- | Dot-reference into an attribute set.--- (!.) :: NExpr -> Text -> NExpr--- (!.) = mkDot--- infixl 8 !.- -- * Nix binary operators --- | Nix binary operator builder.-mkBinop :: NBinaryOp -> NExpr -> NExpr -> NExpr-mkBinop op e1 e2 = Fix $ NBinary op e1 e2- (@@), ($==), ($!=), ($<), ($<=), ($>), ($>=), ($&&), ($||), ($->), ($//), ($+), ($-), ($*), ($/), ($++) :: NExpr -> NExpr -> NExpr+-- 2021-07-10: NOTE: Probably the presedence of some operators is still needs to be tweaked.++-- | Dot-reference into an attribute set: @attrSet.k@+(@.) :: NExpr -> Text -> NExpr+(@.) = getRefOrDefault Nothing+infix 9 @.++-- | Dot-reference into an attribute set with alternative if the key does not exist.+--+-- > s.x or y+-- @since 0.15.0+(@.<|>) :: NExpr -> Text -> NExpr -> NExpr+(@.<|>) obj name alt = getRefOrDefault (pure alt ) obj name+infix 9 @.<|>+ -- | Function application (@' '@ in @f x@)-(@@) = mkBinop NApp-infixl 1 @@--- | Equality: @==@-($==) = mkBinop NEq--- | Inequality: @!=@-($!=) = mkBinop NNEq--- | Less than: @<@-($<) = mkBinop NLt--- | Less than OR equal: @<=@-($<=) = mkBinop NLte+(@@) = mkOp2 NApp+infixl 8 @@++-- | List concatenation: @++@+($++) = mkOp2 NConcat+infixr 7 $++++-- | Multiplication: @*@+($*) = mkOp2 NMult+infixl 6 $*++-- | Division: @/@+($/) = mkOp2 NDiv+infixl 6 $/++-- | Addition: @+@+($+) = mkOp2 NPlus+infixl 5 $+++-- | Subtraction: @-@+($-) = mkOp2 NMinus+infixl 5 $-++-- | Extend/override the left attr set, with the right one: @//@+($//) = mkOp2 NUpdate+infixr 5 $//+ -- | Greater than: @>@-($>) = mkBinop NGt+($>) = mkOp2 NGt+infix 4 $>+ -- | Greater than OR equal: @>=@-($>=) = mkBinop NGte+infix 4 $>=+($>=) = mkOp2 NGte++-- | Less than OR equal: @<=@+($<=) = mkOp2 NLte+infix 4 $<=++-- | Less than: @<@+($<) = mkOp2 NLt+infix 4 $<++-- | Equality: @==@+($==) = mkOp2 NEq+infix 3 $==++-- | Inequality: @!=@+($!=) = mkOp2 NNEq+infix 3 $!=+ -- | AND: @&&@-($&&) = mkBinop NAnd+($&&) = mkOp2 NAnd+infixl 2 $&&+ -- | OR: @||@-($||) = mkBinop NOr--- | Logical implication: @->@-($->) = mkBinop NImpl--- | Extend/override the left attr set, with the right one: @//@-($//) = mkBinop NUpdate--- | Addition: @+@-($+) = mkBinop NPlus--- | Subtraction: @-@-($-) = mkBinop NMinus--- | Multiplication: @*@-($*) = mkBinop NMult--- | Division: @/@-($/) = mkBinop NDiv--- | List concatenation: @++@-($++) = mkBinop NConcat+($||) = mkOp2 NOr+infixl 2 $|| +-- | Logical implication: @->@+($->) = mkOp2 NImpl+infix 1 $-> --- | Lambda function.--- > x ==> x---Haskell:--- > \\ x -> x---Nix:--- > x: x+-- | Lambda function, analog of Haskell's @\\ x -> x@:+--+-- +---------------+-----------++-- | Haskell | Nix |+-- +===============+===========++-- | @x ==> expr @ | @x: expr@ |+-- +---------------+-----------+ (==>) :: Params NExpr -> NExpr -> NExpr (==>) = mkFunction infixr 1 ==> --- | Dot-reference into an attribute set: @attrSet.k@-(@.) :: NExpr -> Text -> NExpr-(@.) obj name = Fix $ NSelect obj (StaticKey name :| mempty) Nothing-infixl 2 @.++-- * Under deprecation++-- NOTE: Remove after 2023-07+-- | __@Deprecated@__: Please, use `mkOp`+-- Put an unary operator.+mkOper :: NUnaryOp -> NExpr -> NExpr+mkOper op = Fix . NUnary op++-- NOTE: Remove after 2023-07+-- | __@Deprecated@__: Please, use `mkOp2`+-- | Put a binary operator.+mkOper2 :: NBinaryOp -> NExpr -> NExpr -> NExpr+mkOper2 op a = Fix . NBinary op a++-- NOTE: Remove after 2023-07+-- | __@Deprecated@__: Please, use `mkOp2`+-- | Nix binary operator builder.+mkBinop :: NBinaryOp -> NExpr -> NExpr -> NExpr+mkBinop = mkOp2++-- NOTE: Remove after 2023-07+-- | __@Deprecated@__: Please, use:+-- * `mkParamSet` is for closed sets;+-- * `mkVariadicSet` is for variadic;+-- * `mkGeneralParamSet` a general constructor.+mkParamset :: [(Text, Maybe NExpr)] -> Bool -> Params NExpr+mkParamset params variadic = ParamSet Nothing (Variadic `whenTrue` variadic) (coerce params)
src/Nix/Expr/Strings.hs view
@@ -2,7 +2,6 @@ -- | Functions for manipulating nix strings. module Nix.Expr.Strings where -import Nix.Utils import Relude.Unsafe as Unsafe -- Please, switch things to NonEmpty import Data.List ( dropWhileEnd@@ -10,7 +9,7 @@ , lookup ) import qualified Data.Text as T-import Nix.Expr+import Nix.Expr.Types -- | Merge adjacent @Plain@ values with @<>@. mergePlain :: [Antiquoted Text r] -> [Antiquoted Text r]@@ -22,8 +21,8 @@ -- | Remove 'Plain' values equal to 'mempty', as they don't have any -- informational content.-removePlainEmpty :: [Antiquoted Text r] -> [Antiquoted Text r]-removePlainEmpty = filter f where+removeEmptyPlains :: [Antiquoted Text r] -> [Antiquoted Text r]+removeEmptyPlains = filter f where f (Plain x) = x /= mempty f _ = True @@ -42,17 +41,18 @@ -- | Split a stream representing a string with antiquotes on line breaks. splitLines :: [Antiquoted Text r] -> [[Antiquoted Text r]] splitLines = uncurry (flip (:)) . go where- go (Plain t : xs) = (Plain l :) <$> foldr f (go xs) ls where+ go (Plain t : xs) = (Plain l :) <$> foldr f (go xs) ls+ where (l : ls) = T.split (== '\n') t f prefix (finished, current) = ((Plain prefix : current) : finished, mempty) go (Antiquoted a : xs) = (Antiquoted a :) <$> go xs go (EscapedNewline : xs) = (EscapedNewline :) <$> go xs- go [] = (mempty, mempty)+ go [] = mempty -- | Join a stream of strings containing antiquotes again. This is the inverse -- of 'splitLines'. unsplitLines :: [[Antiquoted Text r]] -> [Antiquoted Text r]-unsplitLines = intercalate [Plain "\n"]+unsplitLines = intercalate $ one $ Plain "\n" -- | Form an indented string by stripping spaces equal to the minimal indent. stripIndent :: [Antiquoted Text r] -> NString r@@ -60,7 +60,7 @@ stripIndent xs = Indented minIndent- (removePlainEmpty $+ (removeEmptyPlains $ mergePlain $ (snd <$>) $ dropWhileEnd@@ -111,7 +111,7 @@ [('\n', 'n'), ('\r', 'r'), ('\t', 't'), ('\\', '\\'), ('$', '$'), ('"', '"')] fromEscapeCode :: Char -> Maybe Char-fromEscapeCode = (`lookup` fmap swap escapeCodes)+fromEscapeCode = (`lookup` (swap <$> escapeCodes)) toEscapeCode :: Char -> Maybe Char toEscapeCode = (`lookup` escapeCodes)
src/Nix/Expr/Types.hs view
@@ -1,40 +1,38 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}+{-# language ConstraintKinds #-}+{-# language CPP #-}+{-# language DeriveAnyClass #-}+{-# language FunctionalDependencies #-}+{-# language RankNTypes #-}+{-# language TemplateHaskell #-}+{-# language TypeFamilies #-} -{-# OPTIONS_GHC -Wno-orphans #-}-{-# OPTIONS_GHC -Wno-missing-signatures #-}+{-# options_ghc -Wno-orphans #-}+{-# options_ghc -Wno-missing-signatures #-} -- | The Nix expression type and supporting types. ----- For a brief introduction of the Nix expression language, see--- <https://nixos.org/nix/manual/#ch-expression-language>.+-- [Brief introduction of the Nix expression language.](https://nixos.org/nix/manual/#ch-expression-language) -- -- This module is a beginning of a deep embedding (term) of a Nix language into Haskell.--- Shallow/deep embedding brief:--- <https://web.archive.org/web/20201112031804/https://alessandrovermeulen.me/2013/07/13/the-difference-between-shallow-and-deep-embedding/>+-- [Brief on shallow & deep embedding.](https://web.archive.org/web/20201112031804/https://alessandrovermeulen.me/2013/07/13/the-difference-between-shallow-and-deep-embedding/) ----- (additiona info for dev): Big use of TemplateHaskell in the module requires proper (top-down) organization of declarations+-- (additiona info for dev): Big use of TemplateHaskell in the module requires proper (top-down) organization of declarations. module Nix.Expr.Types where import qualified Codec.Serialise as Serialise import Codec.Serialise ( Serialise )-import Control.DeepSeq+import Control.DeepSeq ( NFData1(..) ) import Data.Aeson-import Data.Aeson.TH import qualified Data.Binary as Binary import Data.Binary ( Binary ) import Data.Data-import Data.Fix+import Data.Fix ( Fix(Fix) ) import Data.Functor.Classes import Data.Hashable.Lifted+import qualified Data.HashMap.Lazy as MapL import qualified Data.List.NonEmpty as NE import qualified Text.Show-import Data.Traversable+import Data.Traversable ( fmapDefault, foldMapDefault ) import GHC.Generics import qualified Language.Haskell.TH.Syntax as TH import Lens.Family2@@ -44,22 +42,31 @@ , mkPos , unPos )-import Text.Show.Deriving-import Text.Read.Deriving-import Data.Eq.Deriving-import Data.Ord.Deriving+import Text.Show.Deriving ( deriveShow1, deriveShow2 )+import Text.Read.Deriving ( deriveRead1, deriveRead2 )+import Data.Eq.Deriving ( deriveEq1 , deriveEq2 )+import Data.Ord.Deriving ( deriveOrd1 , deriveOrd2 )+import Data.Aeson.TH ( deriveJSON2 ) import qualified Type.Reflection as Reflection-import Type.Reflection ( eqTypeRep ) import Nix.Atoms-import Nix.Utils #if !MIN_VERSION_text(1,2,4) -- NOTE: Remove package @th-lift-instances@ removing this-import Instances.TH.Lift () -- importing Lift Text fo GHC 8.6+import Instances.TH.Lift () -- importing Lift Text for GHC 8.6 #endif --- * Utilitary: orphan instances+-- * utils +-- | Holds file positionng information for abstrations.+-- A type synonym for @HashMap VarName SourcePos@.+type PositionSet = HashMap VarName SourcePos++-- 2021-07-16: NOTE: Should replace @ParamSet@ List+-- | > Hashmap VarName -- type synonym+type AttrSet = HashMap VarName++-- ** orphan instances+ -- Placed here because TH inference depends on declaration sequence. -- Upstreaming so far was not pursued.@@ -102,24 +109,53 @@ parseJSON = fmap mkPos . parseJSON instance FromJSON SourcePos - -- * Components of Nix expressions -- NExpr is a composition of--- * direct reuse of the Haskell types (list, FilePath, Text)+-- * direct reuse of the Haskell types (list, Path, Text) -- * NAtom -- * Types in this section -- * Fixpoint nature -type VarName = Text+-- ** newtype VarName +newtype VarName = VarName Text+ deriving+ ( Eq, Ord, Generic+ , Typeable, Data, NFData, Serialise, Binary, ToJSON, FromJSON+ , Show, Read, Hashable+ ) --- ** @Params@+instance IsString VarName where+ fromString = coerce . fromString @Text +instance ToString VarName where+ toString = toString @Text . coerce++-- ** data Params++-- *** utils+ -- This uses an association list because nix XML serialization preserves the -- order of the param set. type ParamSet r = [(VarName, Maybe r)] +data Variadic = Closed | Variadic+ deriving+ ( Eq, Ord, Generic+ , Typeable, Data, NFData, Serialise, Binary, ToJSON, FromJSON+ , Show, Read, Hashable+ )++instance Semigroup Variadic where+ (<>) Closed Closed = Closed+ (<>) _ _ = Variadic++instance Monoid Variadic where+ mempty = Closed++-- *** data Params+ -- | @Params@ represents all the ways the formal parameters to a -- function can be represented. data Params r@@ -127,20 +163,18 @@ -- ^ For functions with a single named argument, such as @x: x + 1@. -- -- > Param "x" ~ x- | ParamSet !(ParamSet r) !Bool !(Maybe VarName)- -- 2021-05-15: NOTE: Seems like we should flip the ParamSet, so partial application kicks in for Bool?- -- 2021-05-15: NOTE: '...' variadic property probably needs a Bool synonym.+ | ParamSet !(Maybe VarName) !Variadic !(ParamSet r) -- ^ Explicit parameters (argument must be a set). Might specify a name to -- bind to the set in the function body. The bool indicates whether it is -- variadic or not. --- -- > ParamSet [("x",Nothing)] False Nothing ~ { x }- -- > ParamSet [("x",pure y)] True (pure "s") ~ s@{ x ? y, ... }+ -- > ParamSet Nothing False [("x",Nothing)] ~ { x }+ -- > ParamSet (pure "s") True [("x", pure y)] ~ s@{ x ? y, ... } deriving ( Eq, Ord, Generic, Generic1 , Typeable, Data, NFData, NFData1, Serialise, Binary, ToJSON, ToJSON1, FromJSON, FromJSON1 , Functor, Foldable, Traversable- , Show, Hashable+ , Show, Hashable, Hashable1 ) instance IsString (Params r) where@@ -151,14 +185,12 @@ $(deriveEq1 ''Params) $(deriveOrd1 ''Params) -deriving instance Hashable1 Params---- *** Lens traversals+-- *** lens traversals $(makeTraversals ''Params) --- ** @Antiquoted@+-- ** data Antiquoted -- | 'Antiquoted' represents an expression that is either -- antiquoted (surrounded by ${...}) or plain (not antiquoted).@@ -178,7 +210,7 @@ , Typeable, Data, NFData, NFData1, Serialise, Binary , ToJSON, ToJSON1, FromJSON, FromJSON1 , Functor, Foldable, Traversable- , Show, Read, Hashable+ , Show, Read, Hashable, Hashable1 ) instance Hashable2 Antiquoted where@@ -196,26 +228,25 @@ $(deriveOrd2 ''Antiquoted) $(deriveJSON2 defaultOptions ''Antiquoted) -deriving instance Hashable v => Hashable1 (Antiquoted v) --- *** Lens traversals+-- *** lens traversals $(makeTraversals ''Antiquoted) --- ** @NString@+-- ** data NString -- | An 'NString' is a list of things that are either a plain string -- or an antiquoted expression. After the antiquotes have been evaluated, -- the final string is constructed by concatenating all the parts. data NString r = DoubleQuoted ![Antiquoted Text r]- -- ^ Strings wrapped with double-quotes (") can contain literal newline+ -- ^ Strings wrapped with double-quotes (__@"@__) can contain literal newline -- characters, but the newlines are preserved and no indentation is stripped. -- -- > DoubleQuoted [Plain "x",Antiquoted y] ~ "x${y}" | Indented !Int ![Antiquoted Text r]- -- ^ Strings wrapped with two single quotes ('') can contain newlines, and+ -- ^ Strings wrapped with two single quotes (__@''@__) can contain newlines, and -- their indentation will be stripped, but the amount stripped is -- remembered. --@@ -230,27 +261,25 @@ ( Eq, Ord, Generic, Generic1 , Typeable, Data, NFData, NFData1, Serialise, Binary, ToJSON, ToJSON1, FromJSON, FromJSON1 , Functor, Foldable, Traversable- , Show, Read, Hashable+ , Show, Read, Hashable, Hashable1 ) -- | For the the 'IsString' instance, we use a plain doublequoted string. instance IsString (NString r) where fromString "" = DoubleQuoted mempty- fromString string = DoubleQuoted [Plain $ toText string]+ fromString string = DoubleQuoted [Plain $ fromString string] $(deriveShow1 ''NString) $(deriveRead1 ''NString) $(deriveEq1 ''NString) $(deriveOrd1 ''NString) -deriving instance Hashable1 NString---- *** Lens traversals+-- *** lens traversals $(makeTraversals ''NString) --- ** @NKeyName@+-- ** data NKeyName -- | A 'KeyName' is something that can appear on the left side of an -- equals sign. For example, @a@ is a 'KeyName' in @{ a = 3; }@, @let a = 3;@@ -318,11 +347,12 @@ -- occurs not only as last argument in @Antiquoted (NString r) r@ instance Show1 NKeyName where liftShowsPrec sp sl p = \case- DynamicKey a -> showsUnaryWith- (liftShowsPrec2 (liftShowsPrec sp sl) (liftShowList sp sl) sp sl)- "DynamicKey"- p- a+ DynamicKey a ->+ showsUnaryWith+ (liftShowsPrec2 (liftShowsPrec sp sl) (liftShowList sp sl) sp sl)+ "DynamicKey"+ p+ a StaticKey t -> showsUnaryWith Text.Show.showsPrec "StaticKey" p t -- Deriving this instance automatically is not possible because @r@@@ -344,12 +374,12 @@ DynamicKey EscapedNewline -> pure $ DynamicKey EscapedNewline StaticKey key -> pure $ StaticKey key --- *** Lens traversals+-- *** lens traversals $(makeTraversals ''NKeyName) --- ** @NAttrPath@+-- ** type NAttrPath -- | A selector (for example in a @let@ or an attribute set) is made up -- of strung-together key names.@@ -358,7 +388,7 @@ type NAttrPath r = NonEmpty (NKeyName r) --- ** @Binding@+-- ** data Binding #if !MIN_VERSION_hashable(1,3,1) -- Required by Hashable Binding deriving. There was none of this Hashable instance before mentioned version, remove this in year >2022@@ -371,7 +401,7 @@ -- ^ An explicit naming. -- -- > NamedVar (StaticKey "x" :| [StaticKey "y"]) z SourcePos{} ~ x.y = z;- | Inherit !(Maybe r) ![NKeyName r] !SourcePos+ | Inherit !(Maybe r) ![VarName] !SourcePos -- ^ Inheriting an attribute (binding) into the attribute set from the other scope (attribute set). No denoted scope means to inherit from the closest outside scope. -- -- +---------------------------------------------------------------+--------------------+-----------------------+@@ -391,7 +421,7 @@ ( Eq, Ord, Generic, Generic1 , Typeable, Data, NFData, NFData1, Serialise, Binary, ToJSON, FromJSON , Functor, Foldable, Traversable- , Show, Hashable+ , Show, Hashable, Hashable1 ) $(deriveShow1 ''Binding)@@ -399,29 +429,33 @@ $(deriveOrd1 ''Binding) --x $(deriveJSON1 defaultOptions ''Binding) -deriving instance Hashable1 Binding---- *** Lens traversals+-- *** lens traversals $(makeTraversals ''Binding) --- ** @NRecordType@+-- ** data Recursivity --- | 'NRecordType' distinguishes between recursive and non-recursive attribute+-- | Distinguishes between recursive and non-recursive. Mainly for attribute -- sets.-data NRecordType- = NNonRecursive -- ^ > { ... }- | NRecursive -- ^ > rec { ... }+data Recursivity+ = NonRecursive -- ^ > { ... }+ | Recursive -- ^ > rec { ... } deriving ( Eq, Ord, Enum, Bounded, Generic , Typeable, Data, NFData, Serialise, Binary, ToJSON, FromJSON , Show, Read, Hashable ) +instance Semigroup Recursivity where+ (<>) NonRecursive NonRecursive = NonRecursive+ (<>) _ _ = Recursive --- ** @NUnaryOp@+instance Monoid Recursivity where+ mempty = NonRecursive +-- ** data NUnaryOp+ -- | There are two unary operations: logical not and integer negation. data NUnaryOp = NNeg -- ^ @-@@@ -432,12 +466,12 @@ , Show, Read, Hashable ) --- *** Lens traversals+-- *** lens traversals $(makeTraversals ''NUnaryOp) --- ** @NBinaryOp@+-- ** data NBinaryOp -- | Binary operators expressible in the nix language. data NBinaryOp@@ -465,12 +499,12 @@ , Show, Read, Hashable ) --- *** Lens traversals+-- *** lens traversals $(makeTraversals ''NBinaryOp) --- ** @NExprF@ - Nix expressions, base functor+-- * data NExprF - Nix expressions, base functor -- | The main Nix expression type. As it is polimophic, has a functor, -- which allows to traverse expressions and map functions over them.@@ -490,19 +524,19 @@ -- ^ A list literal. -- -- > NList [x,y] ~ [ x y ]- | NSet !NRecordType ![Binding r]+ | NSet !Recursivity ![Binding r] -- ^ An attribute set literal --- -- > NSet NRecursive [NamedVar x y _] ~ rec { x = y; }- -- > NSet NNonRecursive [Inherit Nothing [x] _] ~ { inherit x; }- | NLiteralPath !FilePath+ -- > NSet Recursive [NamedVar x y _] ~ rec { x = y; }+ -- > NSet NonRecursive [Inherit Nothing [x] _] ~ { inherit x; }+ | NLiteralPath !Path -- ^ A path expression, which is evaluated to a store path. The path here -- can be relative, in which case it's evaluated relative to the file in -- which it appears. -- -- > NLiteralPath "/x" ~ /x -- > NLiteralPath "x/y" ~ x/y- | NEnvPath !FilePath+ | NEnvPath !Path -- ^ A path which refers to something in the Nix search path (the NIX_PATH -- environment variable. For example, @<nixpkgs/pkgs>@. --@@ -517,14 +551,12 @@ -- -- > NBinary NPlus x y ~ x + y -- > NBinary NApp f x ~ f x- | NSelect !r !(NAttrPath r) !(Maybe r)- -- 2021-05-15: NOTE: Default value should be first argument to leverage partial application.- -- Cascading change diff is not that big.+ | NSelect !(Maybe r) !r !(NAttrPath r) -- ^ Dot-reference into an attribute set, optionally providing an -- alternative if the key doesn't exist. --- -- > NSelect s (x :| []) Nothing ~ s.x- -- > NSelect s (x :| []) (pure y) ~ s.x or y+ -- > NSelect Nothing s (x :| []) ~ s.x+ -- > NSelect (pure y) s (x :| []) ~ s.x or y | NHasAttr !r !(NAttrPath r) -- ^ Ask if a set contains a given attribute path. --@@ -549,7 +581,7 @@ -- -- > NWith x y ~ with x; y | NAssert !r !r- -- ^ Assert that the first returns @true@ before evaluating the second.+ -- ^ Checks that the first argument is a predicate that is @true@ before evaluating the second argument. -- -- > NAssert x y ~ assert x; y | NSynHole !VarName@@ -562,7 +594,7 @@ ( Eq, Ord, Generic, Generic1 , Typeable, Data, NFData, NFData1, Serialise, Binary, ToJSON, FromJSON , Functor, Foldable, Traversable- , Show, Hashable+ , Show, Hashable, Hashable1 ) @@ -571,14 +603,12 @@ $(deriveOrd1 ''NExprF) --x $(deriveJSON1 defaultOptions ''NExprF) -deriving instance Hashable1 NExprF---- *** Lens traversals+-- ** lens traversals $(makeTraversals ''NExprF) --- *** @NExpr@+-- ** type NExpr -- | The monomorphic expression type is a fixed point of the polymorphic one. type NExpr = Fix NExprF@@ -600,13 +630,13 @@ -- Reflection is a key strategy in metaprogramming. -- <https://en.wikipedia.org/wiki/Reflective_programming> HRefl <-- eqTypeRep+ Reflection.eqTypeRep (Reflection.typeRep @Text) (Reflection.typeOf b ) pure [| $(TH.lift b) |] ) #if MIN_VERSION_template_haskell(2,17,0)- liftTyped = TH.liftTyped+ liftTyped = TH.unsafeCodeCoerce . TH.lift #elif MIN_VERSION_template_haskell(2,16,0) liftTyped = TH.unsafeTExpCoerce . TH.lift #endif@@ -624,31 +654,47 @@ #else hashAt :: VarName -> Lens' (AttrSet v) (Maybe v) #endif-hashAt = flip alterF+hashAt = alterF+ where+ alterF+ :: (Functor f)+ => VarName+ -> (Maybe v -> f (Maybe v))+ -> AttrSet v+ -> f (AttrSet v)+ alterF (coerce -> k) f m =+ maybe+ (MapL.delete k m)+ (\ v -> MapL.insert k v m)+ <$> f (MapL.lookup k m) -- | Get the name out of the parameter (there might be none). paramName :: Params r -> Maybe VarName-paramName (Param n ) = pure n-paramName (ParamSet _ _ n) = n+paramName (Param name ) = pure name+paramName (ParamSet mname _ _) = mname +stringParts :: NString r -> [Antiquoted Text r]+stringParts (DoubleQuoted parts) = parts+stringParts (Indented _ parts) = parts+ stripPositionInfo :: NExpr -> NExpr stripPositionInfo = transport phi where transport f (Fix x) = Fix $ transport f <$> f x - phi (NSet recur binds) = NSet recur $ go <$> binds- phi (NLet binds body) = NLet (go <$> binds) body+ phi (NSet recur binds) = NSet recur $ erasePositions <$> binds+ phi (NLet binds body) = NLet (erasePositions <$> binds) body phi x = x - go (NamedVar path r _pos) = NamedVar path r nullPos- go (Inherit ms names _pos) = Inherit ms names nullPos+ erasePositions (NamedVar path r _pos) = NamedVar path r nullPos+ erasePositions (Inherit ms names _pos) = Inherit ms names nullPos nullPos :: SourcePos nullPos = on (SourcePos "<string>") mkPos 1 1 -- * Dead code --- ** @class NExprAnn@+-- ** class NExprAnn class NExprAnn ann g | g -> ann where fromNExpr :: g r -> (NExprF r, ann)@@ -657,37 +703,39 @@ -- ** Other ekey- :: NExprAnn ann g- => NonEmpty Text+ :: forall ann g+ . NExprAnn ann g+ => NonEmpty VarName -> SourcePos -> Lens' (Fix g) (Maybe (Fix g))-ekey keys pos f e@(Fix x) | (NSet NNonRecursive xs, ann) <- fromNExpr x =- case go xs of- ((v, [] ) : _) -> fromMaybe e <$> f (pure v)- ((v, r : rest) : _) -> ekey (r :| rest) pos f v+ekey keys pos f e@(Fix x)+ | (NSet NonRecursive xs, ann) <- fromNExpr x =+ let+ vals :: [(Fix g, [VarName])]+ vals =+ do+ let keys' = NE.toList keys+ (ks, rest) <- zip (inits keys') (tails keys')+ list+ mempty+ (\ (j : js) ->+ do+ NamedVar ns v _p <- xs+ guard $ (j : js) == (NE.toList ns ^.. traverse . _StaticKey)+ pure (v, rest)+ )+ ks+ in+ case vals of+ ((v, [] ) : _) -> fromMaybe e <$> f (pure v)+ ((v, r : rest) : _) -> ekey (r :| rest) pos f v - _ ->- maybe- e- (\ v ->- let entry = NamedVar (StaticKey <$> keys) v pos in- Fix $ toNExpr ( NSet NNonRecursive $ [entry] <> xs, ann )- )- <$>- f Nothing- where- go xs =- do- let keys' = NE.toList keys- (ks, rest) <- zip (inits keys') (tails keys')- list- mempty- (\ (j : js) ->- do- NamedVar ns v _p <- xs- guard $ (j : js) == (NE.toList ns ^.. traverse . _StaticKey)- pure (v, rest)+ _ ->+ maybe+ e+ (\ v ->+ let entry = NamedVar (StaticKey <$> keys) v pos in+ Fix $ toNExpr ( NSet mempty $ one entry <> xs, ann ) )- ks-+ <$> f Nothing ekey _ _ f e = fromMaybe e <$> f Nothing
src/Nix/Expr/Types/Annotated.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TemplateHaskell #-}+{-# language CPP #-}+{-# language DeriveAnyClass #-}+{-# language KindSignatures #-}+{-# language PatternSynonyms #-}+{-# language RankNTypes #-}+{-# language TemplateHaskell #-} -- | The source location annotated nix expression type and supporting types. --@@ -26,7 +26,8 @@ import Data.Data import Data.Eq.Deriving import Data.Fix ( Fix(..)- , unfoldFix )+ , unfoldFix+ ) import Data.Functor.Compose import Data.Hashable.Lifted import Data.Ord.Deriving@@ -44,18 +45,18 @@ -- | Demarcation of a chunk in a source file. data SrcSpan = SrcSpan- { spanBegin :: SourcePos- , spanEnd :: SourcePos- }- deriving (Ord, Eq, Generic, Typeable, Data, Show, NFData, Hashable)+ { spanBegin :: SourcePos+ , spanEnd :: SourcePos+ }+ deriving (Ord, Eq, Generic, Typeable, Data, Show, NFData, Hashable) -- ** Instances instance Semigroup SrcSpan where s1 <> s2 = SrcSpan- ((min `on` spanBegin) s1 s2)- ((max `on` spanEnd ) s1 s2)+ (on min spanBegin s1 s2)+ (on max spanEnd s1 s2) instance Binary SrcSpan instance ToJSON SrcSpan@@ -65,70 +66,78 @@ -- * data type @Ann@ +-- 2021-08-02: NOTE: Annotation needs to be after what is annotated. -- | A type constructor applied to a type along with an annotation -- -- Intended to be used with 'Fix':--- @type MyType = Fix (Compose (Ann Annotation) F)@-data Ann ann a = Ann- { annotation :: ann- , annotated :: a- }- deriving (Ord, Eq, Data, Generic, Generic1, Typeable, Functor, Foldable,- Traversable, Read, Show, NFData, Hashable)+-- @type MyType = Fix (Compose (AnnUnit Annotation) F)@+data AnnUnit ann expr = AnnUnit+ { annotation :: ann+ , annotated :: expr+ }+ deriving+ ( Eq, Ord, Data, Typeable, Hashable+ , Generic, Generic1, NFData+ , Functor, Foldable, Traversable+ , Show, Read+ ) -type AnnF ann f = Compose (Ann ann) f+type AnnF ann f = Compose (AnnUnit ann) f --- | Pattern: @(Compose (Ann _ _))@.-pattern AnnFP+-- | Pattern: @(Compose (AnnUnit _ _))@.+pattern AnnF :: ann -> f a- -> Compose (Ann ann) f a-pattern AnnFP ann f = Compose (Ann ann f)-{-# complete AnnFP #-}+ -> Compose (AnnUnit ann) f a+pattern AnnF ann f = Compose (AnnUnit ann f)+{-# complete AnnF #-} --- | Pattern: @Fix (Compose (Ann _ _))@.++type Ann ann f = Fix (AnnF ann f)++-- | Pattern: @Fix (Compose (AnnUnit _ _))@. -- Fix composes units of (annotations & the annotated) into one object. -- Giving annotated expression.-pattern AnnE+pattern Ann :: forall ann (f :: Type -> Type) . ann- -> f (Fix (AnnF ann f))- -> Fix (AnnF ann f)-pattern AnnE ann a = Fix (AnnFP ann a)-{-# complete AnnE #-}+ -> f (Ann ann f)+ -> Ann ann f+pattern Ann ann a = Fix (AnnF ann a)+{-# complete Ann #-} -annToAnnF :: Ann ann (f (Fix (AnnF ann f))) -> Fix (AnnF ann f)-annToAnnF (Ann ann a) = AnnE ann a+annUnitToAnn :: AnnUnit ann (f (Ann ann f)) -> Ann ann f+annUnitToAnn (AnnUnit ann a) = Ann ann a -- ** Instances -instance Hashable ann => Hashable1 (Ann ann)+instance Hashable ann => Hashable1 (AnnUnit ann) -instance NFData ann => NFData1 (Ann ann)+instance NFData ann => NFData1 (AnnUnit ann) -instance (Binary ann, Binary a) => Binary (Ann ann a)+instance (Binary ann, Binary a) => Binary (AnnUnit ann a) -$(deriveEq1 ''Ann)-$(deriveEq2 ''Ann)-$(deriveOrd1 ''Ann)-$(deriveOrd2 ''Ann)-$(deriveRead1 ''Ann)-$(deriveRead2 ''Ann)-$(deriveShow1 ''Ann)-$(deriveShow2 ''Ann)-$(deriveJSON1 defaultOptions ''Ann)-$(deriveJSON2 defaultOptions ''Ann)+$(deriveEq1 ''AnnUnit)+$(deriveEq2 ''AnnUnit)+$(deriveOrd1 ''AnnUnit)+$(deriveOrd2 ''AnnUnit)+$(deriveRead1 ''AnnUnit)+$(deriveRead2 ''AnnUnit)+$(deriveShow1 ''AnnUnit)+$(deriveShow2 ''AnnUnit)+$(deriveJSON1 defaultOptions ''AnnUnit)+$(deriveJSON2 defaultOptions ''AnnUnit) -instance (Serialise ann, Serialise a) => Serialise (Ann ann a)+instance (Serialise ann, Serialise a) => Serialise (AnnUnit ann a) -- ** @NExprLoc{,F}@ - annotated Nix expression type NExprLocF = AnnF SrcSpan NExprF instance Serialise r => Serialise (NExprLocF r) where- encode (AnnFP ann a) = encode ann <> encode a+ encode (AnnF ann a) = encode ann <> encode a decode =- liftA2 AnnFP+ liftA2 AnnF decode decode @@ -143,105 +152,150 @@ -- * Other -stripAnnotation :: Functor f => Fix (AnnF ann f) -> Fix f-stripAnnotation = unfoldFix (stripAnn . unFix)+stripAnnF :: AnnF ann f r -> f r+stripAnnF = annotated . getCompose -stripAnn :: AnnF ann f r -> f r-stripAnn = annotated . getCompose+stripAnnotation :: Functor f => Ann ann f -> Fix f+stripAnnotation = unfoldFix (stripAnnF . unFix) -nUnary :: Ann SrcSpan NUnaryOp -> NExprLoc -> NExprLoc-nUnary (Ann s1 u) e1@(AnnE s2 _) = AnnE (s1 <> s2) $ NUnary u e1-{-# inline nUnary #-}+annNUnary :: AnnUnit SrcSpan NUnaryOp -> NExprLoc -> NExprLoc+annNUnary (AnnUnit s1 u) e1@(Ann s2 _) = NUnaryAnn (s1 <> s2) u e1+{-# inline annNUnary #-} -nBinary :: Ann SrcSpan NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc-nBinary (Ann s1 b) e1@(AnnE s2 _) e2@(AnnE s3 _) =- AnnE (s1 <> s2 <> s3) $ NBinary b e1 e2+annNBinary :: AnnUnit SrcSpan NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc+annNBinary (AnnUnit s1 b) e1@(Ann s2 _) e2@(Ann s3 _) = NBinaryAnn (s1 <> s2 <> s3) b e1 e2 -nSelectLoc- :: NExprLoc -> Ann SrcSpan (NAttrPath NExprLoc) -> Maybe NExprLoc -> NExprLoc-nSelectLoc e1@(AnnE s1 _) (Ann s2 ats) =- -- 2021-05-16: NOTE: This could been rewritten into function application of @(s3, pure e2)@- -- if @SrcSpan@ was Monoid, which requires @SorcePos@ to be a Monoid, and upstream code prevents it.- -- Question upstream: https://github.com/mrkkrp/megaparsec/issues/450- maybe- ( AnnE s1s2 $ NSelect e1 ats Nothing)- (\ e2@(AnnE s3 _) -> AnnE (s1s2 <> s3) $ NSelect e1 ats $ pure e2)- where- s1s2 = s1 <> s2+annNSelect+ :: Maybe NExprLoc -> NExprLoc -> AnnUnit SrcSpan (NAttrPath NExprLoc) -> NExprLoc+annNSelect Nothing e2@(Ann s2 _) (AnnUnit s1 ats) = NSelectAnn ( s2 <> s1) Nothing e2 ats+annNSelect (Just e3@(Ann s3 _)) e2@(Ann s2 _) (AnnUnit s1 ats) = NSelectAnn (s3 <> s2 <> s1) (pure e3) e2 ats -nHasAttr :: NExprLoc -> Ann SrcSpan (NAttrPath NExprLoc) -> NExprLoc-nHasAttr e1@(AnnE s1 _) (Ann s2 ats) = AnnE (s1 <> s2) $ NHasAttr e1 ats+annNHasAttr :: NExprLoc -> AnnUnit SrcSpan (NAttrPath NExprLoc) -> NExprLoc+annNHasAttr e1@(Ann s1 _) (AnnUnit s2 ats) = NHasAttrAnn (s1 <> s2) e1 ats -nApp :: NExprLoc -> NExprLoc -> NExprLoc-nApp e1@(AnnE s1 _) e2@(AnnE s2 _) = AnnE (s1 <> s2) $ NBinary NApp e1 e2+annNApp :: NExprLoc -> NExprLoc -> NExprLoc+annNApp e1@(Ann s1 _) e2@(Ann s2 _) = NBinaryAnn (s1 <> s2) NApp e1 e2 -nAbs :: Ann SrcSpan (Params NExprLoc) -> NExprLoc -> NExprLoc-nAbs (Ann s1 ps) e1@(AnnE s2 _) = AnnE (s1 <> s2) $ NAbs ps e1+annNAbs :: AnnUnit SrcSpan (Params NExprLoc) -> NExprLoc -> NExprLoc+annNAbs (AnnUnit s1 ps) e1@(Ann s2 _) = NAbsAnn (s1 <> s2) ps e1 -nStr :: Ann SrcSpan (NString NExprLoc) -> NExprLoc-nStr (Ann s1 s) = AnnE s1 $ NStr s+annNStr :: AnnUnit SrcSpan (NString NExprLoc) -> NExprLoc+annNStr (AnnUnit s1 s) = NStrAnn s1 s deltaInfo :: SourcePos -> (Text, Int, Int)-deltaInfo (SourcePos fp l c) = (toText fp, unPos l, unPos c)+deltaInfo (SourcePos fp l c) = (fromString fp, unPos l, unPos c) -nNull :: NExprLoc-nNull = AnnE nullSpan $ NConstant NNull-{-# inline nNull #-}+annNNull :: NExprLoc+annNNull = NConstantAnn nullSpan NNull+{-# inline annNNull #-} nullSpan :: SrcSpan nullSpan = SrcSpan nullPos nullPos {-# inline nullSpan #-} --- | Pattern systems for matching on NExprLocF constructions.+-- | Pattern systems for matching on @NExprLocF@ constructions. -pattern NConstant_ :: SrcSpan -> NAtom -> NExprLocF r-pattern NConstant_ ann x = AnnFP ann (NConstant x)+pattern NConstantAnnF :: SrcSpan -> NAtom -> NExprLocF r+pattern NConstantAnnF ann x = AnnF ann (NConstant x) -pattern NStr_ :: SrcSpan -> NString r -> NExprLocF r-pattern NStr_ ann x = AnnFP ann (NStr x)+pattern NStrAnnF :: SrcSpan -> NString r -> NExprLocF r+pattern NStrAnnF ann x = AnnF ann (NStr x) -pattern NSym_ :: SrcSpan -> VarName -> NExprLocF r-pattern NSym_ ann x = AnnFP ann (NSym x)+pattern NSymAnnF :: SrcSpan -> VarName -> NExprLocF r+pattern NSymAnnF ann x = AnnF ann (NSym x) -pattern NList_ :: SrcSpan -> [r] -> NExprLocF r-pattern NList_ ann x = AnnFP ann (NList x)+pattern NListAnnF :: SrcSpan -> [r] -> NExprLocF r+pattern NListAnnF ann x = AnnF ann (NList x) -pattern NSet_ :: SrcSpan -> NRecordType -> [Binding r] -> NExprLocF r-pattern NSet_ ann recur x = AnnFP ann (NSet recur x)+pattern NSetAnnF :: SrcSpan -> Recursivity -> [Binding r] -> NExprLocF r+pattern NSetAnnF ann rec x = AnnF ann (NSet rec x) -pattern NLiteralPath_ :: SrcSpan -> FilePath -> NExprLocF r-pattern NLiteralPath_ ann x = AnnFP ann (NLiteralPath x)+pattern NLiteralPathAnnF :: SrcSpan -> Path -> NExprLocF r+pattern NLiteralPathAnnF ann x = AnnF ann (NLiteralPath x) -pattern NEnvPath_ :: SrcSpan -> FilePath -> NExprLocF r-pattern NEnvPath_ ann x = AnnFP ann (NEnvPath x)+pattern NEnvPathAnnF :: SrcSpan -> Path -> NExprLocF r+pattern NEnvPathAnnF ann x = AnnF ann (NEnvPath x) -pattern NUnary_ :: SrcSpan -> NUnaryOp -> r -> NExprLocF r-pattern NUnary_ ann op x = AnnFP ann (NUnary op x)+pattern NUnaryAnnF :: SrcSpan -> NUnaryOp -> r -> NExprLocF r+pattern NUnaryAnnF ann op x = AnnF ann (NUnary op x) -pattern NBinary_ :: SrcSpan -> NBinaryOp -> r -> r -> NExprLocF r-pattern NBinary_ ann op x y = AnnFP ann (NBinary op x y)+pattern NBinaryAnnF :: SrcSpan -> NBinaryOp -> r -> r -> NExprLocF r+pattern NBinaryAnnF ann op x y = AnnF ann (NBinary op x y) -pattern NSelect_ :: SrcSpan -> r -> NAttrPath r -> Maybe r -> NExprLocF r-pattern NSelect_ ann x p v = AnnFP ann (NSelect x p v)+pattern NSelectAnnF :: SrcSpan -> Maybe r -> r -> NAttrPath r -> NExprLocF r+pattern NSelectAnnF ann v x p = AnnF ann (NSelect v x p) -pattern NHasAttr_ :: SrcSpan -> r -> NAttrPath r -> NExprLocF r-pattern NHasAttr_ ann x p = AnnFP ann (NHasAttr x p)+pattern NHasAttrAnnF :: SrcSpan -> r -> NAttrPath r -> NExprLocF r+pattern NHasAttrAnnF ann x p = AnnF ann (NHasAttr x p) -pattern NAbs_ :: SrcSpan -> Params r-> r -> NExprLocF r-pattern NAbs_ ann x b = AnnFP ann (NAbs x b)+pattern NAbsAnnF :: SrcSpan -> Params r-> r -> NExprLocF r+pattern NAbsAnnF ann x b = AnnF ann (NAbs x b) -pattern NLet_ :: SrcSpan -> [Binding r] -> r -> NExprLocF r-pattern NLet_ ann x b = AnnFP ann (NLet x b)+pattern NLetAnnF :: SrcSpan -> [Binding r] -> r -> NExprLocF r+pattern NLetAnnF ann x b = AnnF ann (NLet x b) -pattern NIf_ :: SrcSpan -> r -> r -> r -> NExprLocF r-pattern NIf_ ann c t e = AnnFP ann (NIf c t e)+pattern NIfAnnF :: SrcSpan -> r -> r -> r -> NExprLocF r+pattern NIfAnnF ann c t e = AnnF ann (NIf c t e) -pattern NWith_ :: SrcSpan -> r -> r -> NExprLocF r-pattern NWith_ ann x y = AnnFP ann (NWith x y)+pattern NWithAnnF :: SrcSpan -> r -> r -> NExprLocF r+pattern NWithAnnF ann x y = AnnF ann (NWith x y) -pattern NAssert_ :: SrcSpan -> r -> r -> NExprLocF r-pattern NAssert_ ann x y = AnnFP ann (NAssert x y)+pattern NAssertAnnF :: SrcSpan -> r -> r -> NExprLocF r+pattern NAssertAnnF ann x y = AnnF ann (NAssert x y) -pattern NSynHole_ :: SrcSpan -> Text -> NExprLocF r-pattern NSynHole_ ann x = AnnFP ann (NSynHole x)-{-# complete NConstant_, NStr_, NSym_, NList_, NSet_, NLiteralPath_, NEnvPath_, NUnary_, NBinary_, NSelect_, NHasAttr_, NAbs_, NLet_, NIf_, NWith_, NAssert_, NSynHole_ #-}+pattern NSynHoleAnnF :: SrcSpan -> VarName -> NExprLocF r+pattern NSynHoleAnnF ann x = AnnF ann (NSynHole x)+{-# complete NConstantAnnF, NStrAnnF, NSymAnnF, NListAnnF, NSetAnnF, NLiteralPathAnnF, NEnvPathAnnF, NUnaryAnnF, NBinaryAnnF, NSelectAnnF, NHasAttrAnnF, NAbsAnnF, NLetAnnF, NIfAnnF, NWithAnnF, NAssertAnnF, NSynHoleAnnF #-}+++pattern NConstantAnn :: SrcSpan -> NAtom -> NExprLoc+pattern NConstantAnn ann x = Ann ann (NConstant x)++pattern NStrAnn :: SrcSpan -> NString NExprLoc -> NExprLoc+pattern NStrAnn ann x = Ann ann (NStr x)++pattern NSymAnn :: SrcSpan -> VarName -> NExprLoc+pattern NSymAnn ann x = Ann ann (NSym x)++pattern NListAnn :: SrcSpan -> [NExprLoc] -> NExprLoc+pattern NListAnn ann x = Ann ann (NList x)++pattern NSetAnn :: SrcSpan -> Recursivity -> [Binding NExprLoc] -> NExprLoc+pattern NSetAnn ann rec x = Ann ann (NSet rec x)++pattern NLiteralPathAnn :: SrcSpan -> Path -> NExprLoc+pattern NLiteralPathAnn ann x = Ann ann (NLiteralPath x)++pattern NEnvPathAnn :: SrcSpan -> Path -> NExprLoc+pattern NEnvPathAnn ann x = Ann ann (NEnvPath x)++pattern NUnaryAnn :: SrcSpan -> NUnaryOp -> NExprLoc -> NExprLoc+pattern NUnaryAnn ann op x = Ann ann (NUnary op x)++pattern NBinaryAnn :: SrcSpan -> NBinaryOp -> NExprLoc -> NExprLoc -> NExprLoc+pattern NBinaryAnn ann op x y = Ann ann (NBinary op x y)++pattern NSelectAnn :: SrcSpan -> Maybe NExprLoc -> NExprLoc -> NAttrPath NExprLoc -> NExprLoc+pattern NSelectAnn ann v x p = Ann ann (NSelect v x p)++pattern NHasAttrAnn :: SrcSpan -> NExprLoc -> NAttrPath NExprLoc -> NExprLoc+pattern NHasAttrAnn ann x p = Ann ann (NHasAttr x p)++pattern NAbsAnn :: SrcSpan -> Params NExprLoc -> NExprLoc -> NExprLoc+pattern NAbsAnn ann x b = Ann ann (NAbs x b)++pattern NLetAnn :: SrcSpan -> [Binding NExprLoc] -> NExprLoc -> NExprLoc+pattern NLetAnn ann x b = Ann ann (NLet x b)++pattern NIfAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc -> NExprLoc+pattern NIfAnn ann c t e = Ann ann (NIf c t e)++pattern NWithAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc+pattern NWithAnn ann x y = Ann ann (NWith x y)++pattern NAssertAnn :: SrcSpan -> NExprLoc -> NExprLoc -> NExprLoc+pattern NAssertAnn ann x y = Ann ann (NAssert x y)++pattern NSynHoleAnn :: SrcSpan -> VarName -> NExprLoc+pattern NSynHoleAnn ann x = Ann ann (NSynHole x)+{-# complete NConstantAnn, NStrAnn, NSymAnn, NListAnn, NSetAnn, NLiteralPathAnn, NEnvPathAnn, NUnaryAnn, NBinaryAnn, NSelectAnn, NHasAttrAnn, NAbsAnn, NLetAnn, NIfAnn, NWithAnn, NAssertAnn, NSynHoleAnn #-}
src/Nix/Frames.hs view
@@ -1,6 +1,5 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language ConstraintKinds #-}+{-# language ExistentialQuantification #-} -- | Definitions of Frames. Frames are messages that gather and ship themself with a context related to the message. For example - the message about some exception would also gather, keep and bring with it the tracing information. module Nix.Frames@@ -12,30 +11,20 @@ , withFrame , throwError , module Data.Typeable- , module Control.Exception ) where -import Prelude hiding ( traceM ) import Data.Typeable hiding ( typeOf ) import Control.Monad.Catch ( MonadThrow(..) )-import Control.Exception hiding ( catch- , evaluate- ) import qualified Text.Show-import Nix.Utils ( Has(..)- , view- , over- , traceM- ) data NixLevel = Fatal | Error | Warning | Info | Debug- deriving (Ord, Eq, Bounded, Enum, Show)+ deriving (Ord, Eq, Bounded, Enum, Show) data NixFrame = NixFrame- { frameLevel :: NixLevel- , frame :: SomeException- }+ { frameLevel :: NixLevel+ , frame :: SomeException+ } instance Show NixFrame where show (NixFrame level f) =@@ -46,7 +35,7 @@ type Framed e m = (MonadReader e m, Has e Frames, MonadThrow m) newtype NixException = NixException Frames- deriving Show+ deriving Show instance Exception NixException
src/Nix/Fresh.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language CPP #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language TypeFamilies #-}+{-# language UndecidableInstances #-} -{-# OPTIONS_GHC -Wno-orphans #-}+{-# options_ghc -Wno-orphans #-} module Nix.Fresh where@@ -21,7 +21,7 @@ import Nix.Thunk -- 2021-06-02: NOTE: Remove singleton newtype accessor in favour of free coerce-newtype FreshIdT i m a = FreshIdT { unFreshIdT :: ReaderT (Ref m i) m a }+newtype FreshIdT i m a = FreshIdT (ReaderT (Ref m i) m a) deriving ( Functor , Applicative@@ -60,4 +60,4 @@ atomicModifyRef v (\i -> (succ i, i)) runFreshIdT :: Functor m => Ref m i -> FreshIdT i m a -> m a-runFreshIdT i m = runReaderT (unFreshIdT m) i+runFreshIdT i m = runReaderT (coerce m) i
src/Nix/Fresh/Basic.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language CPP #-} -{-# OPTIONS_GHC -Wno-orphans #-}+{-# options_ghc -Wno-orphans #-} module Nix.Fresh.Basic where@@ -29,7 +28,7 @@ instance (MonadEffects t f m, MonadDataContext f m) => MonadEffects t f (StdIdT m) where- makeAbsolutePath = lift . makeAbsolutePath @t @f @m+ toAbsolutePath = lift . toAbsolutePath @t @f @m findEnvPath = lift . findEnvPath @t @f @m findPath vs path = do i <- FreshIdT ask
src/Nix/Json.hs view
@@ -4,30 +4,44 @@ import qualified Data.Aeson as A import qualified Data.Aeson.Encoding as A-import qualified Data.HashMap.Lazy as HM-import qualified Data.Text.Lazy.Encoding as TL+import qualified Data.Vector as V+import qualified Data.HashMap.Strict as HM #if MIN_VERSION_aeson(2,0,0) import qualified Data.Aeson.Key as AKM import qualified Data.Aeson.KeyMap as AKM-#else-import Nix.Expr.Types #endif-import qualified Data.Vector as V import Nix.Atoms import Nix.Effects import Nix.Exec import Nix.Frames import Nix.String-import Nix.Utils import Nix.Value import Nix.Value.Monad+import Nix.Expr.Types +-- This was moved from Utils.+toEncodingSorted :: A.Value -> A.Encoding+toEncodingSorted = \case+ A.Object m ->+ A.pairs+ . fold+ . ((\(k, v) -> A.pair k $ toEncodingSorted v) <$>)+ . sortWith fst $+#if MIN_VERSION_aeson(2,0,0)+ AKM.toList+#else+ HM.toList+#endif+ m+ A.Array l -> A.list toEncodingSorted $ V.toList l+ v -> A.toEncoding v+ nvalueToJSONNixString :: MonadNix e t f m => NValue t f m -> m NixString nvalueToJSONNixString = runWithStringContextT . fmap- ( toStrict- . TL.decodeUtf8+ ( decodeUtf8+ -- This is completely not optimal, but seems we do not have better encoding analog (except for @unsafe*@), Aeson gatekeeps through this. . A.encodingToLazyByteString . toEncodingSorted )@@ -42,7 +56,7 @@ NVConstant NNull -> pure A.Null NVStr ns -> A.toJSON <$> extractNixString ns NVList l -> A.Array . V.fromList <$> traverse intoJson l- NVSet m _ ->+ NVSet _ m -> maybe (A.Object <$> traverse intoJson kmap) intoJson@@ -50,17 +64,18 @@ where #if MIN_VERSION_aeson(2,0,0) lkup = AKM.lookup- kmap = AKM.fromHashMap (HM.mapKeys (AKM.fromText . coerce) m)+ kmap = AKM.fromHashMap $ HM.mapKeys (AKM.fromText . coerce) m #else lkup = HM.lookup kmap = HM.mapKeys (coerce @VarName @Text) m #endif NVPath p -> do- fp <- lift $ unStorePath <$> addPath p- addSingletonStringContext $ StringContext (toText fp) DirectPath+ fp <- lift $ coerce <$> addPath p+ addSingletonStringContext $ StringContext (fromString fp) DirectPath pure $ A.toJSON fp v -> lift $ throwError $ CoercionToJson v where+ intoJson :: MonadNix e t f m => NValue t f m -> WithStringContextT m A.Value intoJson nv = join $ lift $ nvalueToJSON <$> demand nv
src/Nix/Lint.hs view
@@ -1,21 +1,19 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language ConstraintKinds #-}+{-# language CPP #-}+{-# language DataKinds #-}+{-# language GADTs #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language TypeFamilies #-}+{-# language UndecidableInstances #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_GHC -Wno-missing-methods #-}+{-# options_ghc -fno-warn-name-shadowing #-}+{-# options_ghc -Wno-missing-methods #-} module Nix.Lint where -import Prelude hiding ( head- , force- )-import Nix.Utils+import Relude.Unsafe as Unsafe ( head )+import Control.Exception ( throw )+import GHC.Exception ( ErrorCall(ErrorCall) ) import Control.Monad ( foldM ) import Control.Monad.Catch import Control.Monad.Fix@@ -23,7 +21,7 @@ import Control.Monad.ST import qualified Data.HashMap.Lazy as M -- Plese, use NonEmpty-import Data.List+import Data.List ( intersect ) import qualified Data.List.NonEmpty as NE import qualified Data.Text as Text import qualified Text.Show@@ -32,7 +30,8 @@ import Nix.Convert import Nix.Eval ( MonadEval(..) ) import qualified Nix.Eval as Eval-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Fresh import Nix.String@@ -53,7 +52,7 @@ = TConstant [TAtom] | TStr | TList r- | TSet (Maybe (HashMap Text r))+ | TSet (Maybe (AttrSet r)) | TClosure (Params ()) | TPath | TBuiltin Text (Symbolic m -> m r)@@ -103,7 +102,7 @@ :: MonadAtomicRef m => [NTypeF m (Symbolic m)] -> m (Symbolic m)-mkSymbolic xs = packSymbolic (NMany xs)+mkSymbolic = packSymbolic . NMany packSymbolic :: MonadAtomicRef m@@ -129,31 +128,50 @@ symerr = evalError @(Symbolic m) . ErrorCall . toString renderSymbolic :: MonadLint e m => Symbolic m -> m Text-renderSymbolic = unpackSymbolic >=> \case- NAny -> pure "<any>"- NMany xs -> fmap (Text.intercalate ", ") $ forM xs $ \case- TConstant ys -> fmap (Text.intercalate ", ") $ forM ys $ pure . \case- TInt -> "int"- TFloat -> "float"- TBool -> "bool"- TNull -> "null"- TStr -> pure "string"- TList r -> do- x <- renderSymbolic =<< demand r- pure $ "[" <> x <> "]"- TSet Nothing -> pure "<any set>"- TSet (Just s) -> do- x <- traverse (renderSymbolic <=< demand) s- pure $ "{" <> show x <> "}"- f@(TClosure p) -> do- (args, sym) <- do- f' <- mkSymbolic [f]- lintApp (NAbs (void p) ()) f' everyPossible- args' <- traverse renderSymbolic args- sym' <- renderSymbolic sym- pure $ "(" <> show args' <> " -> " <> sym' <> ")"- TPath -> pure "path"- TBuiltin _n _f -> pure "<builtin function>"+renderSymbolic =+ (\case+ NAny -> pure "<any>"+ NMany xs ->+ Text.intercalate ", " <$>+ traverse+ (\case+ TConstant ys ->+ pure $+ Text.intercalate ", "+ (fmap+ (\case+ TInt -> "int"+ TFloat -> "float"+ TBool -> "bool"+ TNull -> "null"+ )+ ys+ )+ TStr -> pure "string"+ TList r ->+ fmap brackets $ renderSymbolic =<< demand r+ TSet Nothing -> pure "<any set>"+ TSet (Just s) ->+ braces . show <$> traverse (renderSymbolic <=< demand) s+ f@(TClosure p) ->+ do+ (args, sym) <-+ do+ f' <- mkSymbolic $ one f+ lintApp (NAbs p mempty) f' everyPossible+ args' <- traverse renderSymbolic args+ sym' <- renderSymbolic sym+ pure $ parens $ show args' <> " -> " <> sym'+ TPath -> pure "path"+ TBuiltin _n _f -> pure "<builtin function>"+ )+ xs+ ) <=< unpackSymbolic+ where+ between a b c = a <> b <> c+ parens = between "(" ")"+ brackets = between "[" "]"+ braces = between "{" "}" -- This function is order and uniqueness preserving (of types). merge@@ -171,20 +189,19 @@ -> m [NTypeF m (Symbolic m)] go [] _ = stub go _ [] = stub- go (x : xs) (y : ys) = case (x, y) of- (TStr , TStr ) -> (TStr :) <$> go xs ys- (TPath, TPath) -> (TPath :) <$> go xs ys+ go xxs@(x : xs) yys@(y : ys) = case (x, y) of+ (TStr , TStr ) -> (one TStr <>) <$> rest+ (TPath, TPath) -> (one TPath <>) <$> rest (TConstant ls, TConstant rs) ->- (TConstant (ls `intersect` rs) :) <$> go xs ys+ (one (TConstant (ls `intersect` rs)) <>) <$> rest (TList l, TList r) ->- (\l' ->- (\r' -> do- m <- defer $ unify context l' r'- (TList m :) <$> go xs ys- ) =<< demand r- ) =<< demand l- (TSet x , TSet Nothing ) -> (TSet x :) <$> go xs ys- (TSet Nothing , TSet x ) -> (TSet x :) <$> go xs ys+ do+ l' <- demand l+ r' <- demand r+ m <- defer $ unify context l' r'+ (one (TList m) <>) <$> rest+ (TSet x , TSet Nothing ) -> (one (TSet x) <>) <$> rest+ (TSet Nothing , TSet x ) -> (one (TSet x) <>) <$> rest (TSet (Just l), TSet (Just r)) -> do m <- sequenceA $ M.intersectionWith (\ i j ->@@ -199,23 +216,26 @@ id ((TSet (pure m) :) <$>) (not $ M.null m)- (go xs ys)+ rest (TClosure{}, TClosure{}) -> throwError $ ErrorCall "Cannot unify functions" (TBuiltin _ _, TBuiltin _ _) -> throwError $ ErrorCall "Cannot unify builtin functions"- _ | compareTypes x y == LT -> go xs (y : ys)- | compareTypes x y == GT -> go (x : xs) ys+ _ | compareTypes x y == LT -> go xs yys+ | compareTypes x y == GT -> go xxs ys | otherwise -> error "impossible"+ where+ rest :: m [NTypeF m (Symbolic m)]+ rest = go xs ys {- mergeFunctions pl nl fl pr fr xs ys = do m <- sequenceA $ M.intersectionWith (\i j -> i >>= \i' -> j >>= \j' -> case (i', j') of- (Nothing, Nothing) -> pure $ pure Nothing- (_, Nothing) -> pure Nothing- (Nothing, _) -> pure Nothing+ (Nothing, Nothing) -> stub+ (_, Nothing) -> stub+ (Nothing, _) -> stub (Just i'', Just j'') -> pure . pure <$> unify context i'' j'') (pure <$> pl) (pure <$> pr)@@ -254,7 +274,7 @@ writeRef y (NMany m) packSymbolic (NMany m) )- (do+ ( -- x' <- renderSymbolic (Symbolic x) -- y' <- renderSymbolic (Symbolic y) throwError $ ErrorCall "Cannot unify "@@ -273,9 +293,9 @@ instance FromValue NixString m (Symbolic m) where -instance FromValue (AttrSet (Symbolic m), AttrSet SourcePos) m (Symbolic m) where+instance FromValue (AttrSet (Symbolic m), PositionSet) m (Symbolic m) where -instance ToValue (AttrSet (Symbolic m), AttrSet SourcePos) m (Symbolic m) where+instance ToValue (AttrSet (Symbolic m), PositionSet) m (Symbolic m) where instance (MonadThunkId m, MonadAtomicRef m, MonadCatch m) => MonadValue (Symbolic m) m where@@ -297,7 +317,7 @@ instance MonadLint e m => MonadEval (Symbolic m) m where- freeVariable var = symerr $ "Undefined variable '" <> var <> "'"+ freeVariable var = symerr $ "Undefined variable '" <> coerce var <> "'" attrMissing ks ms = evalError @(Symbolic m) $ ErrorCall $ toString $@@ -306,30 +326,30 @@ (\ s -> "Could not look up attribute " <> attr <> " in " <> show s) ms where- attr = Text.intercalate "." (NE.toList ks)+ attr = Text.intercalate "." $ NE.toList $ coerce ks evalCurPos = do- f <- mkSymbolic [TPath]- l <- mkSymbolic [TConstant [TInt]]- c <- mkSymbolic [TConstant [TInt]]- mkSymbolic [TSet (pure (M.fromList [("file", f), ("line", l), ("col", c)]))]+ f <- mkSymbolic $ one TPath+ l <- mkSymbolic $ one $ TConstant $ one TInt+ c <- mkSymbolic $ one $ TConstant $ one TInt+ mkSymbolic $ one $ TSet (pure (M.fromList [("file", f), ("line", l), ("col", c)])) - evalConstant c = mkSymbolic [go c]+ evalConstant c = mkSymbolic $ one $ fun c where- go =+ fun = \case NURI _ -> TStr- NInt _ -> TConstant [TInt]- NFloat _ -> TConstant [TFloat]- NBool _ -> TConstant [TBool]- NNull -> TConstant [TNull]+ NInt _ -> TConstant $ one TInt+ NFloat _ -> TConstant $ one TFloat+ NBool _ -> TConstant $ one TBool+ NNull -> TConstant $ one TNull - evalString = const $ mkSymbolic [TStr]- evalLiteralPath = const $ mkSymbolic [TPath]- evalEnvPath = const $ mkSymbolic [TPath]+ evalString = const $ mkSymbolic $ one TStr+ evalLiteralPath = const $ mkSymbolic $ one TPath+ evalEnvPath = const $ mkSymbolic $ one TPath evalUnary op arg =- unify (void (NUnary op arg)) arg =<< mkSymbolic [TConstant [TInt, TBool]]+ unify (void (NUnary op arg)) arg =<< mkSymbolic (one (TConstant [TInt, TBool])) evalBinary = lintBinaryOp @@ -343,7 +363,7 @@ pushWeakScope (case s of- NMany [TSet (Just s')] -> pure s'+ NMany [TSet (Just (coerce -> scope))] -> pure scope NMany [TSet Nothing] -> error "NYI: with unknown" _ -> throwError $ ErrorCall "scope must be a set in with statement" )@@ -355,18 +375,18 @@ f' <- f let e = NIf cond t' f' - _ <- unify (void e) cond =<< mkSymbolic [TConstant [TBool]]+ _ <- unify (void e) cond =<< mkSymbolic (one $ TConstant $ one TBool) unify (void e) t' f' evalAssert cond body = do body' <- body let e = NAssert cond body'- _ <- unify (void e) cond =<< mkSymbolic [TConstant [TBool]]+ _ <- unify (void e) cond =<< mkSymbolic (one $ TConstant $ one TBool) pure body' evalApp = (fmap snd .) . lintApp (NBinary NApp () ())- evalAbs params _ = mkSymbolic [TClosure (void params)]+ evalAbs params _ = mkSymbolic (one $ TClosure $ void params) evalError = throwError @@ -389,36 +409,41 @@ NEq -> [TConstant [TInt, TBool, TNull], TStr, TList y] NNEq -> [TConstant [TInt, TBool, TNull], TStr, TList y] - NLt -> [TConstant [TInt, TBool, TNull]]- NLte -> [TConstant [TInt, TBool, TNull]]- NGt -> [TConstant [TInt, TBool, TNull]]- NGte -> [TConstant [TInt, TBool, TNull]]+ NLt -> one $ TConstant [TInt, TBool, TNull]+ NLte -> one $ TConstant [TInt, TBool, TNull]+ NGt -> one $ TConstant [TInt, TBool, TNull]+ NGte -> one $ TConstant [TInt, TBool, TNull] - NAnd -> [TConstant [TBool]]- NOr -> [TConstant [TBool]]- NImpl -> [TConstant [TBool]]+ NAnd -> one $ TConstant $ one TBool+ NOr -> one $ TConstant $ one TBool+ NImpl -> one $ TConstant $ one TBool -- jww (2018-04-01): NYI: Allow Path + Str- NPlus -> [TConstant [TInt], TStr, TPath]- NMinus -> [TConstant [TInt]]- NMult -> [TConstant [TInt]]- NDiv -> [TConstant [TInt]]+ NPlus -> [TConstant $ one TInt, TStr, TPath]+ NMinus -> one $ TConstant $ one TInt+ NMult -> one $ TConstant $ one TInt+ NDiv -> one $ TConstant $ one TInt - NUpdate -> [TSet mempty]+ NUpdate -> one $ TSet mempty - NConcat -> [TList y]+ NConcat -> one $ TList y #if __GLASGOW_HASKELL__ < 900 _ -> fail "Should not be possible" -- symerr or this fun signature should be changed to work in type scope #endif+++ where check lsym rsym xs = do- let e = NBinary op lsym rsym+ let+ e = NBinary op lsym rsym+ unifyE = unify (void e) m <- mkSymbolic xs- _ <- unify (void e) lsym m- _ <- unify (void e) rsym m- unify (void e) lsym rsym+ _ <- unifyE lsym m+ _ <- unifyE rsym m+ unifyE lsym rsym infixl 1 `lintApp` lintApp@@ -428,25 +453,29 @@ -> Symbolic m -> m (Symbolic m) -> m (HashMap VarName (Symbolic m), Symbolic m)-lintApp context fun arg = unpackSymbolic fun >>= \case- NAny ->- throwError $ ErrorCall "Cannot apply something not known to be a function"- NMany xs -> do- (args, ys) <- fmap unzip $ forM xs $ \case- TClosure _params -> arg >>= unpackSymbolic >>= \case- NAny -> do- error "NYI"+lintApp context fun arg =+ (\case+ NAny ->+ throwError $ ErrorCall "Cannot apply something not known to be a function"+ NMany xs -> do+ (args, ys) <- fmap unzip $ forM xs $ \case+ TClosure _params ->+ (\case+ NAny -> do+ error "NYI" - NMany [TSet (Just _)] -> do- error "NYI"+ NMany [TSet (Just _)] -> do+ error "NYI" - NMany _ -> throwError $ ErrorCall "NYI: lintApp NMany not set"- TBuiltin _ _f -> throwError $ ErrorCall "NYI: lintApp builtin"- TSet _m -> throwError $ ErrorCall "NYI: lintApp Set"- _x -> throwError $ ErrorCall "Attempt to call non-function"+ NMany _ -> throwError $ ErrorCall "NYI: lintApp NMany not set"+ ) =<< unpackSymbolic =<< arg+ TBuiltin _ _f -> throwError $ ErrorCall "NYI: lintApp builtin"+ TSet _m -> throwError $ ErrorCall "NYI: lintApp Set"+ _x -> throwError $ ErrorCall "Attempt to call non-function" - y <- everyPossible- (head args, ) <$> foldM (unify context) y ys+ y <- everyPossible+ (Unsafe.head args, ) <$> foldM (unify context) y ys+ ) =<< unpackSymbolic fun newtype Lint s a = Lint { runLint :: ReaderT (Context (Lint s) (Symbolic (Lint s))) (FreshIdT Int (ST s)) a }@@ -462,10 +491,10 @@ ) instance MonadThrow (Lint s) where- throwM e = Lint $ ReaderT $ \_ -> throw e+ throwM e = Lint $ ReaderT $ const (throw e) instance MonadCatch (Lint s) where- catch _m _h = Lint $ ReaderT $ \_ -> fail "Cannot catch in 'Lint s'"+ catch _m _h = Lint $ ReaderT $ const (fail "Cannot catch in 'Lint s'") runLintM :: Options -> Lint s a -> ST s a runLintM opts action = do@@ -475,7 +504,7 @@ symbolicBaseEnv :: Monad m => m (Scopes m (Symbolic m))-symbolicBaseEnv = pure mempty+symbolicBaseEnv = stub lint :: Options -> NExprLoc -> ST s (Symbolic (Lint s)) lint opts expr =
src/Nix/Normal.hs view
@@ -1,18 +1,15 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE RankNTypes #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language DataKinds #-}+{-# language GADTs #-}+{-# language TypeFamilies #-}+{-# language RankNTypes #-} -- | Code for normalization (reduction into a normal form) of Nix expressions. -- Nix language allows recursion, so some expressions do not converge. -- And so do not converge into a normal form. module Nix.Normal where -import Prelude hiding ( force )-import Nix.Utils import Control.Monad.Free ( Free(..) ) import Data.Set ( member , insert@@ -23,7 +20,7 @@ import Nix.Value newtype NormalLoop t f m = NormalLoop (NValue t f m)- deriving Show+ deriving Show instance MonadDataErrorContext t f m => Exception (NormalLoop t f m) @@ -158,10 +155,10 @@ (\_ t -> Free $ NValue' $- foldr- (addProvenance1 @m @(NValue t f m))+ foldl'+ (flip $ addProvenance1 @m @(NValue t f m)) cyc- (reverse $ citations @m @(NValue t f m) t)+ (citations @m @(NValue t f m) t) ) Free where
src/Nix/Options.hs view
@@ -1,40 +1,42 @@-{-# LANGUAGE StrictData #-}+{-# language StrictData #-} -- | Definitions & defaults for the CLI options module Nix.Options where import Data.Time +-- 2021-07-15: NOTE: What these are? They need to be documented.+-- Also need better names. Foe example, Maybes & lists names need to show their type in the name. data Options = Options { verbose :: Verbosity , tracing :: Bool , thunks :: Bool , values :: Bool , showScopes :: Bool- , reduce :: Maybe FilePath+ , reduce :: Maybe Path , reduceSets :: Bool , reduceLists :: Bool , parse :: Bool , parseOnly :: Bool , finder :: Bool- , findFile :: Maybe FilePath+ , findFile :: Maybe Path , strict :: Bool , evaluate :: Bool , json :: Bool , xml :: Bool , attr :: Maybe Text- , include :: [FilePath]+ , include :: [Path] , check :: Bool- , readFrom :: Maybe FilePath+ , readFrom :: Maybe Path , cache :: Bool , repl :: Bool , ignoreErrors :: Bool , expression :: Maybe Text , arg :: [(Text, Text)] , argstr :: [(Text, Text)]- , fromFile :: Maybe FilePath+ , fromFile :: Maybe Path , currentTime :: UTCTime- , filePaths :: [FilePath]+ , filePaths :: [Path] } deriving Show
src/Nix/Options/Parser.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell #-}+{-# language TemplateHaskell #-} -- | Code that configures presentation parser for the CLI options module Nix.Options.Parser where@@ -212,7 +212,7 @@ debugVersionOpt :: Parser (a -> a) debugVersionOpt = infoOption- ( concat+ ( fold [ "Version: ", showVersion version , "\nCommit: ", $(gitHash) , "\n date: ", $(gitCommitDate)@@ -227,4 +227,4 @@ nixOptionsInfo current = info (helper <*> versionOpt <*> nixOptions current)- (fullDesc <> progDesc "" <> header "hnix")+ (fullDesc <> progDesc mempty <> header "hnix")
src/Nix/Parser.hs view
@@ -1,773 +1,920 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}--{-# OPTIONS_GHC -fno-warn-name-shadowing #-}---- | Main module for parsing Nix expressions.-module Nix.Parser- ( parseNixFile- , parseNixFileLoc- , parseNixText- , parseNixTextLoc- , parseFromFileEx- , Parser- , parseFromText- , Result- , reservedNames- , OperatorInfo(..)- , NSpecialOp(..)- , NAssoc(..)- , NOperatorDef- , getUnaryOperator- , getBinaryOperator- , getSpecialOperator- , nixToplevelForm- , nixExpr- , nixSet- , nixBinders- , nixSelector- , nixSym- , nixPath- , nixString- , nixUri- , nixSearchPath- , nixFloat- , nixInt- , nixBool- , nixNull- , symbol- , whiteSpace- )-where--import Prelude hiding ( some- , many- , readFile- )-import Data.Foldable ( foldr1 )--import Control.Monad ( msum )-import Control.Monad.Combinators.Expr ( makeExprParser- , Operator( Postfix- , InfixN- , InfixR- , Prefix- , InfixL- )- )-import Data.Char ( isAlpha- , isDigit- , isSpace- )-import Data.Data ( Data(..) )-import Data.Fix ( Fix(..) )-import qualified Data.HashSet as HashSet-import qualified Data.Map as Map-import Data.Text ( cons )-import Nix.Expr hiding ( ($>) )-import Nix.Expr.Strings ( escapeCodes- , stripIndent- , mergePlain- , removePlainEmpty- )-import Nix.Render ( MonadFile(readFile) )-import Prettyprinter ( Doc- , pretty- )--- `parser-combinators` ships performance enhanced & MonadPlus-aware combinators.--- For example `smome` and `many` impoted here.-import Text.Megaparsec hiding ( State )-import Text.Megaparsec.Char ( space1- , string- , letterChar- , char- )-import qualified Text.Megaparsec.Char.Lexer as Lexer---- | Different to @isAlphaNum@-isAlphanumeric :: Char -> Bool-isAlphanumeric x = isAlpha x || isDigit x-{-# inline isAlphanumeric #-}--infixl 3 <+>-(<+>) :: MonadPlus m => m a -> m a -> m a-(<+>) = mplus-------------------------------------------------------------------------------------nixExpr :: Parser NExprLoc-nixExpr =- makeExprParser- nixTerm $- snd <<$>>- nixOperators nixSelector--antiStart :: Parser Text-antiStart = symbol "${" <?> "${"--nixAntiquoted :: Parser a -> Parser (Antiquoted a NExprLoc)-nixAntiquoted p =- Antiquoted <$>- (antiStart *> nixToplevelForm <* symbol "}")- <+> Plain <$>- p- <?> "anti-quotation"--selDot :: Parser ()-selDot = try (symbol "." *> notFollowedBy nixPath) <?> "."--nixSelect :: Parser NExprLoc -> Parser NExprLoc-nixSelect term =- do- res <-- liftA2 build- term- (optional $- liftA2 (,)- (selDot *> nixSelector)- (optional $ reserved "or" *> nixTerm)- )- continues <- optional $ lookAhead selDot-- maybe- id- (const nixSelect)- continues- (pure res)- where- build- :: NExprLoc- -> Maybe ( Ann SrcSpan (NAttrPath NExprLoc)- , Maybe NExprLoc- )- -> NExprLoc- build t mexpr =- maybe- id- (\ expr t -> (uncurry $ nSelectLoc t) expr)- mexpr- t--nixSelector :: Parser (Ann SrcSpan (NAttrPath NExprLoc))-nixSelector =- annotateLocation $- do- (x : xs) <- keyName `sepBy1` selDot- pure $ x :| xs--nixTerm :: Parser NExprLoc-nixTerm = do- c <- try $ lookAhead $ satisfy $ \x ->- pathChar x || (`elem` ("({[</\"'^" :: String)) x- case c of- '(' -> nixSelect nixParens- '{' -> nixSelect nixSet- '[' -> nixList- '<' -> nixSearchPath- '/' -> nixPath- '"' -> nixString- '\'' -> nixString- '^' -> nixSynHole- _ ->- msum- $ [ nixSelect nixSet | c == 'r' ]- <> [ nixPath | pathChar c ]- <> if isDigit c- then [ nixFloat, nixInt ]- else- [ nixUri | isAlpha c ]- <> [ nixBool | c == 't' || c == 'f' ]- <> [ nixNull | c == 'n' ]- <> [ nixSelect nixSym ]--nixToplevelForm :: Parser NExprLoc-nixToplevelForm = keywords <+> nixLambda <+> nixExpr- where- keywords = nixLet <+> nixIf <+> nixAssert <+> nixWith--nixSym :: Parser NExprLoc-nixSym = annotateLocation1 $ mkSymF <$> identifier--nixSynHole :: Parser NExprLoc-nixSynHole = annotateLocation1 $ mkSynHoleF <$> (char '^' *> identifier)--nixInt :: Parser NExprLoc-nixInt = annotateLocation1 (mkIntF <$> integer <?> "integer")--nixFloat :: Parser NExprLoc-nixFloat =- annotateLocation1 (try (mkFloatF . realToFrac <$> float) <?> "float")--nixBool :: Parser NExprLoc-nixBool =- annotateLocation1 (bool "true" True <+> bool "false" False) <?> "bool"- where- bool str b = mkBoolF b <$ reserved str--nixNull :: Parser NExprLoc-nixNull = annotateLocation1 (mkNullF <$ reserved "null" <?> "null")---- | 'nixTopLevelForm' returns an expression annotated with a source position,--- however this position doesn't include the parsed parentheses, so remove the--- "inner" location annotateion and annotate again, including the parentheses.-nixParens :: Parser NExprLoc-nixParens = annotateLocation1 (parens (stripAnn . unFix <$> nixToplevelForm) <?> "parens")--nixList :: Parser NExprLoc-nixList = annotateLocation1 (brackets (NList <$> many nixTerm) <?> "list")--pathChar :: Char -> Bool-pathChar x =- isAlphanumeric x || (`elem` ("._-+~" :: String)) x--slash :: Parser Char-slash =- try- ( char '/'- <* notFollowedBy (satisfy (\x -> x == '/' || x == '*' || isSpace x))- )- <?> "slash"---- | A path surrounded by angle brackets, indicating that it should be--- looked up in the NIX_PATH environment variable at evaluation.-nixSearchPath :: Parser NExprLoc-nixSearchPath =- annotateLocation1- (mkPathF True <$>- try (char '<' *> many (satisfy pathChar <+> slash) <* symbol ">")- <?> "spath"- )--pathStr :: Parser FilePath-pathStr =- lexeme $- liftA2 (<>)- (many $ satisfy pathChar)- (concat <$>- some- (liftA2 (:)- slash- (some $ satisfy pathChar)- )- )--nixPath :: Parser NExprLoc-nixPath = annotateLocation1 (try (mkPathF False <$> pathStr) <?> "path")--nixLet :: Parser NExprLoc-nixLet = annotateLocation1- (reserved "let" *> (letBody <+> letBinders) <?> "let block")- where- letBinders =- liftA2 NLet- nixBinders- (reserved "in" *> nixToplevelForm)- -- Let expressions `let {..., body = ...}' are just desugared- -- into `(rec {..., body = ...}).body'.- letBody = (\x -> NSelect x (StaticKey "body" :| mempty) Nothing) <$> aset- aset = annotateLocation1 $ NSet NRecursive <$> braces nixBinders--nixIf :: Parser NExprLoc-nixIf = annotateLocation1- (liftA3 NIf- (reserved "if" *> nixExpr )- (reserved "then" *> nixToplevelForm)- (reserved "else" *> nixToplevelForm)- <?> "if"- )--nixAssert :: Parser NExprLoc-nixAssert = annotateLocation1- (liftA2 NAssert- (reserved "assert" *> nixToplevelForm)- (semi *> nixToplevelForm)- <?> "assert"- )--nixWith :: Parser NExprLoc-nixWith = annotateLocation1- (liftA2 NWith- (reserved "with" *> nixToplevelForm)- (semi *> nixToplevelForm)- <?> "with"- )--nixLambda :: Parser NExprLoc-nixLambda =- liftA2 nAbs- (annotateLocation $ try argExpr)- nixToplevelForm--nixString :: Parser NExprLoc-nixString = nStr <$> annotateLocation nixString'--nixUri :: Parser NExprLoc-nixUri = lexeme $ annotateLocation1 $ try $ do- start <- letterChar- protocol <- many $- satisfy $- \ x ->- isAlphanumeric x- || (`elem` ("+-." :: String)) x- _ <- string ":"- address <-- some $- satisfy $- \ x ->- isAlphanumeric x- || (`elem` ("%/?:@&=+$,-_.!~*'" :: String)) x- pure $ NStr $ DoubleQuoted- [Plain $ toText $ start : protocol ++ ':' : address]--nixString' :: Parser (NString NExprLoc)-nixString' = lexeme (doubleQuoted <+> indented <?> "string")- where- doubleQuoted :: Parser (NString NExprLoc)- doubleQuoted =- DoubleQuoted- . removePlainEmpty- . mergePlain <$>- ( doubleQ- *> many (stringChar doubleQ (void $ char '\\') doubleEscape)- <* doubleQ- )- <?> "double quoted string"-- doubleQ = void $ char '"'- doubleEscape = Plain . one <$> (char '\\' *> escapeCode)-- indented :: Parser (NString NExprLoc)- indented =- stripIndent <$>- (indentedQ- *> many (stringChar indentedQ indentedQ indentedEscape)- <* indentedQ- )- <?> "indented string"-- indentedQ = void (string "''" <?> "\"''\"")- indentedEscape =- try $- do- indentedQ- (Plain <$> ("''" <$ char '\'' <+> "$" <$ char '$')) <+>- do- _ <- char '\\'- c <- escapeCode-- pure $- bool- EscapedNewline- (Plain $ one c)- (c /= '\n')-- stringChar end escStart esc =- Antiquoted <$>- (antiStart *> nixToplevelForm <* char '}')- <+> Plain . one <$>- char '$' <+> esc <+> Plain . toText <$>- some plainChar- where- plainChar =- notFollowedBy (end <+> void (char '$') <+> escStart) *> anySingle-- escapeCode =- msum- [ c <$ char e | (c, e) <- escapeCodes ]- <+> anySingle---- | Gets all of the arguments for a function.-argExpr :: Parser (Params NExprLoc)-argExpr =- msum- [ atLeft- , onlyname- , atRight- ]- <* symbol ":"- where- -- An argument not in curly braces. There's some potential ambiguity- -- in the case of, for example `x:y`. Is it a lambda function `x: y`, or- -- a URI `x:y`? Nix syntax says it's the latter. So we need to fail if- -- there's a valid URI parse here.- onlyname =- msum- [ nixUri *> unexpected (Label ('v' :| "alid uri"))- , Param <$> identifier- ]-- -- Parameters named by an identifier on the left (`args @ {x, y}`)- atLeft =- try $- do- name <- identifier <* symbol "@"- (params, variadic) <- params- pure $ ParamSet params variadic $ pure name-- -- Parameters named by an identifier on the right, or none (`{x, y} @ args`)- atRight =- do- (params, variadic) <- params- name <- optional $ symbol "@" *> identifier- pure $ ParamSet params variadic name-- -- Return the parameters set.- params = braces getParams-- -- Collects the parameters within curly braces. Returns the parameters and- -- a boolean indicating if the parameters are variadic.- getParams :: Parser ([(Text, Maybe NExprLoc)], Bool)- getParams = go mempty- where- -- Attempt to parse `...`. If this succeeds, stop and return True.- -- Otherwise, attempt to parse an argument, optionally with a- -- default. If this fails, then return what has been accumulated- -- so far.- go acc = ((acc, True) <$ symbol "...") <+> getMore- where- getMore =- -- Could be nothing, in which just return what we have so far.- option (acc, False) $- do- -- Get an argument name and an optional default.- pair <-- liftA2 (,)- identifier- (optional $ question *> nixToplevelForm)-- let args = acc <> [pair]-- -- Either return this, or attempt to get a comma and restart.- option (args, False) $ comma *> go args--nixBinders :: Parser [Binding NExprLoc]-nixBinders = (inherit <+> namedVar) `endBy` semi where- inherit =- do- -- We can't use 'reserved' here because it would consume the whitespace- -- after the keyword, which is not exactly the semantics of C++ Nix.- try $ string "inherit" *> lookAhead (void (satisfy reservedEnd))- p <- getSourcePos- x <- whiteSpace *> optional scope- liftA2 (Inherit x)- (many keyName)- (pure p)- <?> "inherited binding"- namedVar =- do- p <- getSourcePos- liftA3 NamedVar- (annotated <$> nixSelector)- (equals *> nixToplevelForm)- (pure p)- <?> "variable binding"- scope = nixParens <?> "inherit scope"--keyName :: Parser (NKeyName NExprLoc)-keyName = dynamicKey <+> staticKey- where- staticKey = StaticKey <$> identifier- dynamicKey = DynamicKey <$> nixAntiquoted nixString'--nixSet :: Parser NExprLoc-nixSet = annotateLocation1 ((isRec <*> braces nixBinders) <?> "set")- where- isRec = (reserved "rec" $> NSet NRecursive <?> "recursive set") <+> pure (NSet NNonRecursive)--parseNixFile :: MonadFile m => FilePath -> m (Result NExpr)-parseNixFile =- parseFromFileEx $ stripAnnotation <$> (whiteSpace *> nixToplevelForm <* eof)--parseNixFileLoc :: MonadFile m => FilePath -> m (Result NExprLoc)-parseNixFileLoc = parseFromFileEx (whiteSpace *> nixToplevelForm <* eof)--parseNixText :: Text -> Result NExpr-parseNixText =- parseFromText $ stripAnnotation <$> (whiteSpace *> nixToplevelForm <* eof)--parseNixTextLoc :: Text -> Result NExprLoc-parseNixTextLoc = parseFromText (whiteSpace *> nixToplevelForm <* eof)--{- Parser.Library -}--skipLineComment' :: Tokens Text -> Parser ()-skipLineComment' prefix =- string prefix *> void (takeWhileP (pure "character") (\x -> x /= '\n' && x /= '\r'))--whiteSpace :: Parser ()-whiteSpace = do- put =<< getSourcePos- Lexer.space space1 lineCmnt blockCmnt- where- lineCmnt = skipLineComment' "#"- blockCmnt = Lexer.skipBlockComment "/*" "*/"--lexeme :: Parser a -> Parser a-lexeme p = p <* whiteSpace--symbol :: Text -> Parser Text-symbol = lexeme . string--reservedEnd :: Char -> Bool-reservedEnd x =- isSpace x || (`elem` ("{([})];:.\"'," :: String)) x-{-# inline reservedEnd #-}--reserved :: Text -> Parser ()-reserved n =- lexeme $ try $ string n *> lookAhead (void (satisfy reservedEnd) <|> eof)--identifier :: Parser Text-identifier = lexeme $ try $ do- ident <-- liftA2 cons- (satisfy (\x -> isAlpha x || x == '_'))- (takeWhileP mempty identLetter)- guard $ not $ ident `HashSet.member` reservedNames- pure ident- where- identLetter x = isAlphanumeric x || x == '_' || x == '\'' || x == '-'---- We restrict the type of 'parens' and 'brackets' here because if they were to--- take a @Parser NExprLoc@ argument they would parse additional text which--- wouldn't be captured in the source location annotation.------ Braces and angles in hnix don't enclose a single expression so this type--- restriction would not be useful.-parens :: Parser (NExprF f) -> Parser (NExprF f)-parens = between (symbol "(") (symbol ")")-braces :: ParsecT Void Text (State SourcePos) a -> ParsecT Void Text (State SourcePos) a-braces = between (symbol "{") (symbol "}")--- angles = between (symbol "<") (symbol ">")-brackets :: Parser (NExprF f) -> Parser (NExprF f)-brackets = between (symbol "[") (symbol "]")-semi :: Parser Text-semi = symbol ";"-comma :: Parser Text-comma = symbol ","--- colon = symbol ":"--- dot = symbol "."-equals :: Parser Text-equals = symbol "="-question :: Parser Text-question = symbol "?"--integer :: Parser Integer-integer = lexeme Lexer.decimal--float :: Parser Double-float = lexeme Lexer.float--reservedNames :: HashSet Text-reservedNames =- HashSet.fromList- ["let", "in", "if", "then", "else", "assert", "with", "rec", "inherit"]--type Parser = ParsecT Void Text (State SourcePos)--type Result a = Either (Doc Void) a--parseFromFileEx :: MonadFile m => Parser a -> FilePath -> m (Result a)-parseFromFileEx parser file =- do- input <- decodeUtf8 <$> readFile file-- pure $- either- (Left . pretty . errorBundlePretty)- pure- $ (`evalState` initialPos file) $ runParserT parser file input--parseFromText :: Parser a -> Text -> Result a-parseFromText parser input =- let stub = "<string>" in- either- (Left . pretty . errorBundlePretty)- pure- $ (`evalState` initialPos stub) $ (`runParserT` stub) parser input--{- Parser.Operators -}--data NSpecialOp = NHasAttrOp | NSelectOp- deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)--data NAssoc = NAssocNone | NAssocLeft | NAssocRight- deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)--data NOperatorDef- = NUnaryDef Text NUnaryOp- | NBinaryDef Text NBinaryOp NAssoc- | NSpecialDef Text NSpecialOp NAssoc- deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)--annotateLocation :: Parser a -> Parser (Ann SrcSpan a)-annotateLocation p =- do- begin <- getSourcePos- res <- p- end <- get -- The state set before the last whitespace-- pure $ Ann (SrcSpan begin end) res--annotateLocation1 :: Parser (NExprF NExprLoc) -> Parser NExprLoc-annotateLocation1 = fmap annToAnnF . annotateLocation--manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a)-manyUnaryOp f = foldr1 (.) <$> some f--operator :: Text -> Parser Text-operator op =- case op of- "-" -> tuneLexer "-" '>'- "/" -> tuneLexer "/" '/'- "<" -> tuneLexer "<" '='- ">" -> tuneLexer ">" '='- n -> symbol n- where- tuneLexer opchar nonextchar =- lexeme . try $ string opchar <* notFollowedBy (char nonextchar)--opWithLoc :: Text -> o -> (Ann SrcSpan o -> a) -> Parser a-opWithLoc name op f =- do- Ann ann _ <-- annotateLocation $- {- dbg (toString name) $ -}- operator name-- pure $ f $ Ann ann op--binaryN :: Text -> NBinaryOp -> (NOperatorDef, Operator (ParsecT Void Text (State SourcePos)) NExprLoc)-binaryN name op =- (NBinaryDef name op NAssocNone, InfixN $ opWithLoc name op nBinary)-binaryL :: Text -> NBinaryOp -> (NOperatorDef, Operator (ParsecT Void Text (State SourcePos)) NExprLoc)-binaryL name op =- (NBinaryDef name op NAssocLeft, InfixL $ opWithLoc name op nBinary)-binaryR :: Text -> NBinaryOp -> (NOperatorDef, Operator (ParsecT Void Text (State SourcePos)) NExprLoc)-binaryR name op =- (NBinaryDef name op NAssocRight, InfixR $ opWithLoc name op nBinary)-prefix :: Text -> NUnaryOp -> (NOperatorDef, Operator (ParsecT Void Text (State SourcePos)) NExprLoc)-prefix name op =- (NUnaryDef name op, Prefix $ manyUnaryOp $ opWithLoc name op nUnary)--- postfix name op = (NUnaryDef name op,--- Postfix (opWithLoc name op nUnary))--nixOperators- :: Parser (Ann SrcSpan (NAttrPath NExprLoc))- -> [[(NOperatorDef, Operator Parser NExprLoc)]]-nixOperators selector =- [ -- This is not parsed here, even though technically it's part of the- -- expression table. The problem is that in some cases, such as list- -- membership, it's also a term. And since terms are effectively the- -- highest precedence entities parsed by the expression parser, it ends up- -- working out that we parse them as a kind of "meta-term".-- -- {- 1 -} [ (NSpecialDef "." NSelectOp NAssocLeft,- -- Postfix $ do- -- sel <- seldot *> selector- -- mor <- optional (reserved "or" *> term)- -- pure $ \x -> nSelectLoc x sel mor) ]-- {- 2 -}- [ ( NBinaryDef " " NApp NAssocLeft- ,- -- Thanks to Brent Yorgey for showing me this trick!- InfixL $ nApp <$ symbol ""- )- ]- , {- 3 -}- [ prefix "-" NNeg ]- , {- 4 -}- [ ( NSpecialDef "?" NHasAttrOp NAssocLeft- , Postfix $ symbol "?" *> (flip nHasAttr <$> selector)- )- ]- , {- 5 -}- [ binaryR "++" NConcat ]- , {- 6 -}- [ binaryL "*" NMult- , binaryL "/" NDiv- ]- , {- 7 -}- [ binaryL "+" NPlus- , binaryL "-" NMinus- ]- , {- 8 -}- [ prefix "!" NNot ]- , {- 9 -}- [ binaryR "//" NUpdate ]- , {- 10 -}- [ binaryL "<" NLt- , binaryL ">" NGt- , binaryL "<=" NLte- , binaryL ">=" NGte- ]- , {- 11 -}- [ binaryN "==" NEq- , binaryN "!=" NNEq- ]- , {- 12 -}- [ binaryL "&&" NAnd ]- , {- 13 -}- [ binaryL "||" NOr ]- , {- 14 -}- [ binaryR "->" NImpl ]- ]--data OperatorInfo = OperatorInfo- { precedence :: Int- , associativity :: NAssoc- , operatorName :: Text- } deriving (Eq, Ord, Generic, Typeable, Data, Show)--getUnaryOperator :: NUnaryOp -> OperatorInfo-getUnaryOperator = (m Map.!)- where- m =- Map.fromList $- concat $- zipWith- buildEntry- [1 ..]- (nixOperators $ fail "unused")-- buildEntry i =- concatMap $- \case- (NUnaryDef name op, _) -> [(op, OperatorInfo i NAssocNone name)]- _ -> mempty--getBinaryOperator :: NBinaryOp -> OperatorInfo-getBinaryOperator = (m Map.!)- where- m =- Map.fromList $- concat $- zipWith- buildEntry- [1 ..]- (nixOperators $ fail "unused")-- buildEntry i =- concatMap $- \case- (NBinaryDef name op assoc, _) -> [(op, OperatorInfo i assoc name)]- _ -> mempty--getSpecialOperator :: NSpecialOp -> OperatorInfo-getSpecialOperator NSelectOp = OperatorInfo 1 NAssocLeft "."-getSpecialOperator o = m Map.! o- where- m =- Map.fromList $- concat $- zipWith- buildEntry- [1 ..]- (nixOperators $ fail "unused")-- buildEntry i =- concatMap $- \case- (NSpecialDef name op assoc, _) -> [(op, OperatorInfo i assoc name)]- _ -> mempty+{-# language CPP #-}+{-# language DeriveAnyClass #-}++{-# options_ghc -fno-warn-name-shadowing #-}++-- | Main module for parsing Nix expressions.+module Nix.Parser+ ( parseNixFile+ , parseNixFileLoc+ , parseNixText+ , parseNixTextLoc+ , parseFromFileEx+ , Parser+ , parseFromText+ , Result+ , reservedNames+ , OperatorInfo(..)+ , NSpecialOp(..)+ , NAssoc(..)+ , NOperatorDef+ , getUnaryOperator+ , getBinaryOperator+ , getSpecialOperator+ , nixExpr+ , nixExprAlgebra+ , nixSet+ , nixBinders+ , nixSelector+ , nixSym+ , nixPath+ , nixString+ , nixUri+ , nixSearchPath+ , nixFloat+ , nixInt+ , nixBool+ , nixNull+ , whiteSpace+ )+where++import Prelude hiding ( (<|>)+ , some+ , many+ )+import Data.Foldable ( foldr1 )++import Control.Monad ( msum )+import Control.Monad.Combinators.Expr ( makeExprParser+ , Operator( Postfix+ , InfixN+ , InfixR+ , Prefix+ , InfixL+ )+ )+import Data.Char ( isAlpha+ , isDigit+ , isSpace+ )+import Data.Data ( Data(..) )+import Data.Fix ( Fix(..) )+import qualified Data.HashSet as HashSet+import qualified Data.Map as Map+import qualified Data.Text as Text+import Nix.Expr.Types+import Nix.Expr.Shorthands hiding ( ($>) )+import Nix.Expr.Types.Annotated+import Nix.Expr.Strings ( escapeCodes+ , stripIndent+ , mergePlain+ , removeEmptyPlains+ )+import Nix.Render ( MonadFile() )+import Prettyprinter ( Doc+ , pretty+ )+-- `parser-combinators` ships performance enhanced & MonadPlus-aware combinators.+-- For example `some` and `many` impoted here.+import Text.Megaparsec hiding ( (<|>)+ , State+ )+import Text.Megaparsec.Char ( space1+ , letterChar+ , char+ )+import qualified Text.Megaparsec.Char.Lexer as Lexer+++type Parser = ParsecT Void Text (State SourcePos)++-- * Utils++-- | Different to @isAlphaNum@+isAlphanumeric :: Char -> Bool+isAlphanumeric x = isAlpha x || isDigit x+{-# inline isAlphanumeric #-}++-- | @<|>@ with additional preservation of @MonadPlus@ constraint.+infixl 3 <|>+(<|>) :: MonadPlus m => m a -> m a -> m a+(<|>) = mplus++-- ** Annotated++annotateLocation1 :: Parser a -> Parser (AnnUnit SrcSpan a)+annotateLocation1 p =+ do+ begin <- getSourcePos+ res <- p+ end <- get -- The state set before the last whitespace++ pure $ AnnUnit (SrcSpan begin end) res++annotateLocation :: Parser (NExprF NExprLoc) -> Parser NExprLoc+annotateLocation = (annUnitToAnn <$>) . annotateLocation1++annotateNamedLocation :: String -> Parser (NExprF NExprLoc) -> Parser NExprLoc+annotateNamedLocation name = annotateLocation . label name+++-- ** Grammar++reservedNames :: HashSet VarName+reservedNames =+ HashSet.fromList+ ["let", "in", "if", "then", "else", "assert", "with", "rec", "inherit"]++reservedEnd :: Char -> Bool+reservedEnd x =+ isSpace x || (`elem` ("{([})];:.\"'," :: String)) x+{-# inline reservedEnd #-}++reserved :: Text -> Parser ()+reserved n =+ lexeme $ try $ chunk n *> lookAhead (void (satisfy reservedEnd) <|> eof)++exprAfterP :: Parser a -> Parser NExprLoc+exprAfterP p = p *> nixExpr++exprAfterSymbol :: Char -> Parser NExprLoc+exprAfterSymbol p = exprAfterP $ symbol p++exprAfterReservedWord :: Text -> Parser NExprLoc+exprAfterReservedWord word = exprAfterP $ reserved word++-- | A literal copy of @megaparsec@ one but with addition of the @\r@ for Windows EOL case (@\r\n@).+-- Overall, parser should simply @\r\n -> \n@.+skipLineComment' :: Tokens Text -> Parser ()+skipLineComment' prefix =+ chunk prefix *> void (takeWhileP (pure "character") $ \x -> x /= '\n' && x /= '\r')++whiteSpace :: Parser ()+whiteSpace =+ do+ put =<< getSourcePos+ Lexer.space space1 lineCmnt blockCmnt+ where+ lineCmnt = skipLineComment' "#"+ blockCmnt = Lexer.skipBlockComment "/*" "*/"++-- | Lexeme is a unit of the language.+-- Convention is that after lexeme an arbitrary amount of empty entities (space, comments, line breaks) are allowed.+-- This lexeme definition just skips over superflous @megaparsec: lexeme@ abstraction.+lexeme :: Parser a -> Parser a+lexeme p = p <* whiteSpace++symbol :: Char -> Parser Char+symbol = lexeme . char++symbols :: Text -> Parser Text+symbols = lexeme . chunk++-- We restrict the type of 'parens' and 'brackets' here because if they were to+-- take a @Parser NExprLoc@ argument they would parse additional text which+-- wouldn't be captured in the source location annotation.+--+-- Braces and angles in hnix don't enclose a single expression so this type+-- restriction would not be useful.+parens :: Parser (NExprF f) -> Parser (NExprF f)+parens = on between symbol '(' ')'++braces :: Parser a -> Parser a+braces = on between symbol '{' '}'++brackets :: Parser (NExprF f) -> Parser (NExprF f)+brackets = on between symbol '[' ']'++antiquotedIsHungryForTrailingSpaces :: Bool -> Parser (Antiquoted v NExprLoc)+antiquotedIsHungryForTrailingSpaces hungry = Antiquoted <$> (antiStart *> nixExpr <* antiEnd)+ where+ antiStart :: Parser Text+ antiStart = label "${" $ symbols "${"++ antiEnd :: Parser Char+ antiEnd = label "}" $+ bool+ id+ lexeme+ hungry+ (char '}')++antiquotedLexeme :: Parser (Antiquoted v NExprLoc)+antiquotedLexeme = antiquotedIsHungryForTrailingSpaces True++antiquoted :: Parser (Antiquoted v NExprLoc)+antiquoted = antiquotedIsHungryForTrailingSpaces False++---------------------------------------------------------------------------------++-- * Parser parts++-- ** Constrants++nixNull :: Parser NExprLoc+nixNull =+ annotateNamedLocation "null" $+ mkNullF <$ reserved "null"++nixBool :: Parser NExprLoc+nixBool =+ annotateNamedLocation "bool" $+ on (<|>) lmkBool (True, "true") (False, "false")+ where+ lmkBool (b, txt) = mkBoolF b <$ reserved txt++integer :: Parser Integer+integer = lexeme Lexer.decimal++nixInt :: Parser NExprLoc+nixInt =+ annotateNamedLocation "integer" $+ mkIntF <$> integer++float :: Parser Double+float = lexeme Lexer.float++nixFloat :: Parser NExprLoc+nixFloat =+ annotateNamedLocation "float" $+ try $+ mkFloatF . realToFrac <$> float++nixUri :: Parser NExprLoc+nixUri =+ lexeme $+ annotateLocation $+ try $+ do+ start <- letterChar+ protocol <-+ takeWhileP mempty $+ \ x ->+ isAlphanumeric x+ || (`elem` ("+-." :: String)) x+ _ <- single ':'+ address <-+ takeWhile1P mempty $+ \ x ->+ isAlphanumeric x+ || (`elem` ("%/?:@&=+$,-_.!~*'" :: String)) x+ pure . NStr . DoubleQuoted . one . Plain $ start `Text.cons` protocol <> ":" <> address+++-- ** Strings++nixAntiquoted :: Parser a -> Parser (Antiquoted a NExprLoc)+nixAntiquoted p =+ label "anti-quotation" $+ antiquotedLexeme+ <|> Plain <$> p++nixString' :: Parser (NString NExprLoc)+nixString' = label "string" $ lexeme $ doubleQuoted <|> indented+ where+ doubleQuoted :: Parser (NString NExprLoc)+ doubleQuoted =+ label "double quoted string" $+ DoubleQuoted . removeEmptyPlains . mergePlain <$>+ inQuotationMarks (many $ stringChar quotationMark (void $ char '\\') doubleEscape)+ where+ inQuotationMarks :: Parser a -> Parser a+ inQuotationMarks expr = quotationMark *> expr <* quotationMark++ quotationMark :: Parser ()+ quotationMark = void $ char '"'++ doubleEscape :: Parser (Antiquoted Text r)+ doubleEscape = Plain . one <$> (char '\\' *> escapeCode)++ indented :: Parser (NString NExprLoc)+ indented =+ label "indented string" $+ stripIndent <$>+ inIndentedQuotation (many $ join stringChar indentedQuotationMark indentedEscape)+ where+ indentedEscape :: Parser (Antiquoted Text r)+ indentedEscape =+ try $+ do+ indentedQuotationMark+ (Plain <$> ("''" <$ char '\'' <|> "$" <$ char '$'))+ <|>+ do+ _ <- char '\\'+ c <- escapeCode++ pure $+ bool+ EscapedNewline+ (Plain $ one c)+ (c /= '\n')++ inIndentedQuotation :: Parser a -> Parser a+ inIndentedQuotation expr = indentedQuotationMark *> expr <* indentedQuotationMark++ indentedQuotationMark :: Parser ()+ indentedQuotationMark = label "\"''\"" . void $ chunk "''"++ stringChar+ :: Parser ()+ -> Parser ()+ -> Parser (Antiquoted Text NExprLoc)+ -> Parser (Antiquoted Text NExprLoc)+ stringChar end escStart esc =+ antiquoted+ <|> Plain . one <$> char '$'+ <|> esc+ <|> Plain . fromString <$> some plainChar+ where+ plainChar :: Parser Char+ plainChar =+ notFollowedBy (end <|> void (char '$') <|> escStart) *> anySingle++ escapeCode :: Parser Char+ escapeCode =+ msum+ [ c <$ char e | (c, e) <- escapeCodes ]+ <|> anySingle++nixString :: Parser NExprLoc+nixString = annNStr <$> annotateLocation1 nixString'+++-- ** Names (variables aka symbols)++identifier :: Parser VarName+identifier =+ lexeme $+ try $+ do+ (coerce -> iD) <-+ liftA2 Text.cons+ (satisfy (\x -> isAlpha x || x == '_'))+ (takeWhileP mempty identLetter)+ guard $ not $ iD `HashSet.member` reservedNames+ pure iD+ where+ identLetter x = isAlphanumeric x || x == '_' || x == '\'' || x == '-'++nixSym :: Parser NExprLoc+nixSym = annotateLocation $ mkSymF <$> coerce identifier+++-- ** ( ) parens++-- | 'nixExpr' returns an expression annotated with a source position,+-- however this position doesn't include the parsed parentheses, so remove the+-- "inner" location annotateion and annotate again, including the parentheses.+nixParens :: Parser NExprLoc+nixParens =+ annotateNamedLocation "parens" $+ parens $ stripAnnF . unFix <$> nixExpr+++-- ** [ ] list++nixList :: Parser NExprLoc+nixList =+ annotateNamedLocation "list" $+ brackets $ NList <$> many nixTerm+++-- ** { } set++nixBinders :: Parser [Binding NExprLoc]+nixBinders = (inherit <|> namedVar) `endBy` symbol ';' where+ inherit =+ do+ -- We can't use 'reserved' here because it would consume the whitespace+ -- after the keyword, which is not exactly the semantics of C++ Nix.+ try $ chunk "inherit" *> lookAhead (void $ satisfy reservedEnd)+ p <- getSourcePos+ x <- whiteSpace *> optional scope+ label "inherited binding" $+ liftA2 (Inherit x)+ (many identifier)+ (pure p)+ namedVar =+ do+ p <- getSourcePos+ label "variable binding" $+ liftA3 NamedVar+ (annotated <$> nixSelector)+ (exprAfterSymbol '=')+ (pure p)+ scope = label "inherit scope" nixParens++nixSet :: Parser NExprLoc+nixSet =+ annotateNamedLocation "set" $+ isRec <*> braces nixBinders+ where+ isRec =+ label "recursive set" (reserved "rec" $> NSet Recursive)+ <|> pure (NSet mempty)++-- ** /x/y/z literal Path++pathChar :: Char -> Bool+pathChar x =+ isAlphanumeric x || (`elem` ("._-+~" :: String)) x++slash :: Parser Char+slash =+ label "slash " $+ try $+ char '/' <* notFollowedBy (satisfy $ \x -> x == '/' || x == '*' || isSpace x)++pathStr :: Parser Path+pathStr =+ lexeme $ coerce . toString <$>+ liftA2 (<>)+ (takeWhileP mempty pathChar)+ (Text.concat <$>+ some+ (liftA2 Text.cons+ slash+ (takeWhile1P mempty pathChar)+ )+ )++nixPath :: Parser NExprLoc+nixPath =+ annotateNamedLocation "path" $+ try $ mkPathF False <$> coerce pathStr+++-- ** <<x>> environment path++-- | A path surrounded by angle brackets, indicating that it should be+-- looked up in the NIX_PATH environment variable at evaluation.+nixSearchPath :: Parser NExprLoc+nixSearchPath =+ annotateNamedLocation "spath" $+ mkPathF True <$> try (lexeme $ char '<' *> many (satisfy pathChar <|> slash) <* char '>')+++-- ** Operators++data NSpecialOp = NHasAttrOp | NSelectOp+ deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)++data NAssoc = NAssocNone | NAssocLeft | NAssocRight+ deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)++data NOperatorDef+ = NUnaryDef NUnaryOp Text+ | NBinaryDef NAssoc NBinaryOp Text+ | NSpecialDef NAssoc NSpecialOp Text+ deriving (Eq, Ord, Generic, Typeable, Data, Show, NFData)++manyUnaryOp :: MonadPlus f => f (a -> a) -> f (a -> a)+manyUnaryOp f = foldr1 (.) <$> some f++operator :: Text -> Parser Text+operator op =+ case op of+ c@"-" -> c `without` '>'+ c@"/" -> c `without` '/'+ c@"<" -> c `without` '='+ c@">" -> c `without` '='+ n -> symbols n+ where+ without :: Text -> Char -> Parser Text+ without opChar noNextChar =+ lexeme . try $ chunk opChar <* notFollowedBy (char noNextChar)++opWithLoc :: (AnnUnit SrcSpan o -> a) -> o -> Text -> Parser a+opWithLoc f op name =+ do+ AnnUnit ann _ <-+ annotateLocation1 $+ operator name++ pure . f $ AnnUnit ann op++binary+ :: NAssoc+ -> (Parser (NExprLoc -> NExprLoc -> NExprLoc) -> b)+ -> NBinaryOp+ -> Text+ -> (NOperatorDef, b)+binary assoc fixity op name =+ (NBinaryDef assoc op name, fixity $ opWithLoc annNBinary op name)++binaryN, binaryL, binaryR :: NBinaryOp -> Text -> (NOperatorDef, Operator Parser NExprLoc)+binaryN =+ binary NAssocNone InfixN+binaryL =+ binary NAssocLeft InfixL+binaryR =+ binary NAssocRight InfixR++prefix :: NUnaryOp -> Text -> (NOperatorDef, Operator Parser NExprLoc)+prefix op name =+ (NUnaryDef op name, Prefix $ manyUnaryOp $ opWithLoc annNUnary op name)+-- postfix name op = (NUnaryDef name op,+-- Postfix (opWithLoc name op annNUnary))++nixOperators+ :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc))+ -> [[ ( NOperatorDef+ , Operator Parser NExprLoc+ )+ ]]+nixOperators selector =+ [ -- This is not parsed here, even though technically it's part of the+ -- expression table. The problem is that in some cases, such as list+ -- membership, it's also a term. And since terms are effectively the+ -- highest precedence entities parsed by the expression parser, it ends up+ -- working out that we parse them as a kind of "meta-term".++ -- {- 1 -}+ -- [ ( NSpecialDef "." NSelectOp NAssocLeft+ -- , Postfix $+ -- do+ -- sel <- seldot *> selector+ -- mor <- optional (reserved "or" *> term)+ -- pure $ \x -> annNSelect x sel mor)+ -- ]++ {- 2 -}+ one+ ( NBinaryDef NAssocLeft NApp " "+ ,+ -- Thanks to Brent Yorgey for showing me this trick!+ InfixL $ annNApp <$ symbols mempty+ )+ , {- 3 -}+ one $ prefix NNeg "-"+ , {- 4 -}+ one+ ( NSpecialDef NAssocLeft NHasAttrOp "?"+ , Postfix $ symbol '?' *> (flip annNHasAttr <$> selector)+ )+ , {- 5 -}+ one $ binaryR NConcat "++"+ , {- 6 -}+ [ binaryL NMult "*"+ , binaryL NDiv "/"+ ]+ , {- 7 -}+ [ binaryL NPlus "+"+ , binaryL NMinus "-"+ ]+ , {- 8 -}+ one $ prefix NNot "!"+ , {- 9 -}+ one $ binaryR NUpdate "//"+ , {- 10 -}+ [ binaryL NLt "<"+ , binaryL NGt ">"+ , binaryL NLte "<="+ , binaryL NGte ">="+ ]+ , {- 11 -}+ [ binaryN NEq "=="+ , binaryN NNEq "!="+ ]+ , {- 12 -}+ one $ binaryL NAnd "&&"+ , {- 13 -}+ one $ binaryL NOr "||"+ , {- 14 -}+ one $ binaryR NImpl "->"+ ]++-- 2021-08-10: NOTE:+-- All this is a sidecar:+-- * This type+-- * detectPrecedence+-- * getUnaryOperation+-- * getBinaryOperation+-- * getSpecialOperation+-- can reduced in favour of adding precedence field into @NOperatorDef@.+-- details: https://github.com/haskell-nix/hnix/issues/982+data OperatorInfo = OperatorInfo+ { precedence :: Int+ , associativity :: NAssoc+ , operatorName :: Text+ } deriving (Eq, Ord, Generic, Typeable, Data, Show)++detectPrecedence+ :: Ord a+ => ( Int+ -> (NOperatorDef, Operator Parser NExprLoc)+ -> [(a, OperatorInfo)]+ )+ -> a+ -> OperatorInfo+detectPrecedence spec = (mapOfOpWithPrecedence Map.!)+ where+ mapOfOpWithPrecedence =+ Map.fromList $+ fold $+ zipWith+ (foldMap . spec)+ [1 ..]+ l+ where+ l :: [[(NOperatorDef, Operator Parser NExprLoc)]]+ l = nixOperators $ fail "unused"++getUnaryOperator :: NUnaryOp -> OperatorInfo+getUnaryOperator = detectPrecedence spec+ where+ spec :: Int -> (NOperatorDef, b) -> [(NUnaryOp, OperatorInfo)]+ spec i =+ \case+ (NUnaryDef op name, _) -> one (op, OperatorInfo i NAssocNone name)+ _ -> mempty++getBinaryOperator :: NBinaryOp -> OperatorInfo+getBinaryOperator = detectPrecedence spec+ where+ spec :: Int -> (NOperatorDef, b) -> [(NBinaryOp, OperatorInfo)]+ spec i =+ \case+ (NBinaryDef assoc op name, _) -> one (op, OperatorInfo i assoc name)+ _ -> mempty++getSpecialOperator :: NSpecialOp -> OperatorInfo+getSpecialOperator NSelectOp = OperatorInfo 1 NAssocLeft "."+getSpecialOperator o = detectPrecedence spec o+ where+ spec :: Int -> (NOperatorDef, b) -> [(NSpecialOp, OperatorInfo)]+ spec i =+ \case+ (NSpecialDef assoc op name, _) -> one (op, OperatorInfo i assoc name)+ _ -> mempty++-- ** x: y lambda function++-- | Gets all of the arguments for a function.+argExpr :: Parser (Params NExprLoc)+argExpr =+ msum+ [ atLeft+ , onlyname+ , atRight+ ]+ <* symbol ':'+ where+ -- An argument not in curly braces. There's some potential ambiguity+ -- in the case of, for example `x:y`. Is it a lambda function `x: y`, or+ -- a URI `x:y`? Nix syntax says it's the latter. So we need to fail if+ -- there's a valid URI parse here.+ onlyname =+ msum+ [ nixUri *> unexpected (Label $ fromList "valid uri" )+ , Param <$> identifier+ ]++ -- Parameters named by an identifier on the left (`args @ {x, y}`)+ atLeft =+ try $+ do+ name <- identifier <* symbol '@'+ (pset, variadic) <- params+ pure $ ParamSet (pure name) variadic pset++ -- Parameters named by an identifier on the right, or none (`{x, y} @ args`)+ atRight =+ do+ (pset, variadic) <- params+ name <- optional $ symbol '@' *> identifier+ pure $ ParamSet name variadic pset++ -- Return the parameters set.+ params = braces getParams++ -- Collects the parameters within curly braces. Returns the parameters and+ -- an flag indication if the parameters are variadic.+ getParams = go mempty+ where+ -- Attempt to parse `...`. If this succeeds, stop and return True.+ -- Otherwise, attempt to parse an argument, optionally with a+ -- default. If this fails, then return what has been accumulated+ -- so far.+ go acc = ((acc, Variadic) <$ symbols "...") <|> getMore+ where+ getMore :: Parser ([(VarName, Maybe NExprLoc)], Variadic)+ getMore =+ -- Could be nothing, in which just return what we have so far.+ option (acc, mempty) $+ do+ -- Get an argument name and an optional default.+ pair <-+ liftA2 (,)+ identifier+ (optional $ exprAfterSymbol '?')++ let args = acc <> one pair++ -- Either return this, or attempt to get a comma and restart.+ option (args, mempty) $ symbol ',' *> go args++nixLambda :: Parser NExprLoc+nixLambda =+ liftA2 annNAbs+ (annotateLocation1 $ try argExpr)+ nixExpr+++-- ** let expression++nixLet :: Parser NExprLoc+nixLet =+ annotateNamedLocation "let block" $+ reserved "let" *> (letBody <|> letBinders)+ where+ letBinders =+ liftA2 NLet+ nixBinders+ (exprAfterReservedWord "in")+ -- Let expressions `let {..., body = ...}' are just desugared+ -- into `(rec {..., body = ...}).body'.+ letBody = (\x -> NSelect Nothing x (one $ StaticKey "body")) <$> aset+ aset = annotateLocation $ NSet Recursive <$> braces nixBinders++-- ** if then else++nixIf :: Parser NExprLoc+nixIf =+ annotateNamedLocation "if" $+ liftA3 NIf+ (reserved "if" *> nixExprAlgebra)+ (exprAfterReservedWord "then")+ (exprAfterReservedWord "else")++-- ** with++nixWith :: Parser NExprLoc+nixWith =+ annotateNamedLocation "with" $+ liftA2 NWith+ (exprAfterReservedWord "with")+ (exprAfterSymbol ';' )+++-- ** assert++nixAssert :: Parser NExprLoc+nixAssert =+ annotateNamedLocation "assert" $+ liftA2 NAssert+ (exprAfterReservedWord "assert")+ (exprAfterSymbol ';' )++-- ** . - reference (selector) into attr++selDot :: Parser ()+selDot = label "." $ try (symbol '.' *> notFollowedBy nixPath)++keyName :: Parser (NKeyName NExprLoc)+keyName = dynamicKey <|> staticKey+ where+ staticKey = StaticKey <$> identifier+ dynamicKey = DynamicKey <$> nixAntiquoted nixString'++nixSelector :: Parser (AnnUnit SrcSpan (NAttrPath NExprLoc))+nixSelector =+ annotateLocation1 $+ do+ (x : xs) <- keyName `sepBy1` selDot+ pure $ x :| xs++nixSelect :: Parser NExprLoc -> Parser NExprLoc+nixSelect term =+ do+ res <-+ liftA2 build+ term+ (optional $+ liftA2 (,)+ (selDot *> nixSelector)+ (optional $ reserved "or" *> nixTerm)+ )+ continues <- optional $ lookAhead selDot++ maybe+ id+ (const nixSelect)+ continues+ (pure res)+ where+ build+ :: NExprLoc+ -> Maybe+ ( AnnUnit SrcSpan (NAttrPath NExprLoc)+ , Maybe NExprLoc+ )+ -> NExprLoc+ build t =+ maybe+ t+ (\ (a, m) -> (`annNSelect` t) m a)+++-- ** _ - syntax hole++nixSynHole :: Parser NExprLoc+nixSynHole = annotateLocation $ mkSynHoleF <$> coerce (char '^' *> identifier)+++-- ** Expr & its constituents (Language term, expr algebra)++nixTerm :: Parser NExprLoc+nixTerm =+ do+ c <- try . lookAhead . satisfy $+ \x -> (`elem` ("({[</\"'^" :: String)) x || pathChar x+ case c of+ '(' -> nixSelect nixParens+ '{' -> nixSelect nixSet+ '[' -> nixList+ '<' -> nixSearchPath+ '/' -> nixPath+ '"' -> nixString+ '\'' -> nixString+ '^' -> nixSynHole+ _ ->+ msum+ $ [ nixSelect nixSet | c == 'r' ]+ <> [ nixPath | pathChar c ]+ <> if isDigit c+ then [ nixFloat, nixInt ]+ else+ [ nixUri | isAlpha c ]+ <> [ nixBool | c == 't' || c == 'f' ]+ <> [ nixNull | c == 'n' ]+ <> one (nixSelect nixSym)++-- | Nix expression algebra parser.+-- "Expression algebra" is to explain @megaparsec@ use of the term "Expression" (parser for language algebraic coperators without any statements (without @let@ etc.)), which is essentially an algebra inside the language.+nixExprAlgebra :: Parser NExprLoc+nixExprAlgebra =+ makeExprParser+ nixTerm+ (snd <<$>>+ nixOperators nixSelector+ )++nixExpr :: Parser NExprLoc+nixExpr = keywords <|> nixLambda <|> nixExprAlgebra+ where+ keywords = nixLet <|> nixIf <|> nixAssert <|> nixWith+++-- * Parse++type Result a = Either (Doc Void) a++parseFromFileEx :: MonadFile m => Parser a -> Path -> m (Result a)+parseFromFileEx parser file =+ do+ input <- liftIO $ readFile file++ pure $+ either+ (Left . pretty . errorBundlePretty)+ pure+ $ (`evalState` initialPos (coerce file)) $ runParserT parser (coerce file) input++parseFromText :: Parser a -> Text -> Result a+parseFromText parser input =+ let stub = "<string>" in+ either+ (Left . pretty . errorBundlePretty)+ pure+ $ (`evalState` initialPos stub) $ (`runParserT` stub) parser input++fullContent :: Parser NExprLoc+fullContent = whiteSpace *> nixExpr <* eof++parseNixFile' :: MonadFile m => (Parser NExprLoc -> Parser a) -> Path -> m (Result a)+parseNixFile' f =+ parseFromFileEx $ f fullContent++parseNixFile :: MonadFile m => Path -> m (Result NExpr)+parseNixFile =+ parseNixFile' (stripAnnotation <$>)++parseNixFileLoc :: MonadFile m => Path -> m (Result NExprLoc)+parseNixFileLoc =+ parseNixFile' id++parseNixText' :: (Parser NExprLoc -> Parser a) -> Text -> Result a+parseNixText' f =+ parseFromText $ f fullContent++parseNixText :: Text -> Result NExpr+parseNixText =+ parseNixText' (stripAnnotation <$>)++parseNixTextLoc :: Text -> Result NExprLoc+parseNixTextLoc =+ parseNixText' id+
src/Nix/Pretty.hs view
@@ -1,14 +1,12 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-}+{-# language CPP #-}+{-# language AllowAmbiguousTypes #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -fno-warn-name-shadowing #-} module Nix.Pretty where import Prelude hiding ( toList, group )-import Nix.Utils import Control.Monad.Free ( Free(Free) ) import Data.Fix ( Fix(..) , foldFix )@@ -23,7 +21,8 @@ import Prettyprinter hiding ( list ) import Nix.Atoms import Nix.Cited-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Expr.Strings import Nix.Normal import Nix.Parser@@ -101,80 +100,90 @@ (wasPath sub) prettyString :: NString (NixDoc ann) -> Doc ann-prettyString (DoubleQuoted parts) = "\"" <> (mconcat . fmap prettyPart $ parts) <> "\""+prettyString (DoubleQuoted parts) = "\"" <> foldMap prettyPart parts <> "\"" where -- It serializes Text -> String, because the helper code is done for String, -- please, can someone break that code.- prettyPart (Plain t) = pretty . concatMap escape . toString $ t+ prettyPart (Plain t) = pretty . foldMap escape . toString $ t prettyPart EscapedNewline = "''\\n" prettyPart (Antiquoted r) = "${" <> withoutParens r <> "}" escape '"' = "\\\"" escape x = maybe- [x]- (('\\' :) . (: mempty))+ (one x)+ (('\\' :) . one) (toEscapeCode x) prettyString (Indented _ parts) = group $ nest 2 $ vcat ["''", content, "''"] where content = vsep . fmap prettyLine . stripLastIfEmpty . splitLines $ parts- stripLastIfEmpty = reverse . f . reverse where- f ([Plain t] : xs) | Text.null (strip t) = xs- f xs = xs+ stripLastIfEmpty :: [[Antiquoted Text r]] -> [[Antiquoted Text r]]+ stripLastIfEmpty = filter flt+ where+ flt :: [Antiquoted Text r] -> Bool+ flt [Plain t] | Text.null (strip t) = False+ flt _ = True+ prettyLine = hcat . fmap prettyPart prettyPart (Plain t) = pretty . replace "${" "''${" . replace "''" "'''" $ t prettyPart EscapedNewline = "\\n" prettyPart (Antiquoted r) = "${" <> withoutParens r <> "}" +prettyVarName :: VarName -> Doc ann+prettyVarName = pretty @Text . coerce+ prettyParams :: Params (NixDoc ann) -> Doc ann-prettyParams (Param n ) = pretty n-prettyParams (ParamSet s v mname) = prettyParamSet s v <>- maybe- mempty- (\ name ->- bool- mempty- ("@" <> pretty name)- (not (Text.null name))- )- mname+prettyParams (Param n ) = prettyVarName n+prettyParams (ParamSet mname variadic pset) =+ prettyParamSet variadic pset <>+ toDoc `whenJust` mname+ where+ toDoc :: VarName -> Doc ann+ toDoc (coerce -> name) =+ ("@" <> pretty name) `whenFalse` Text.null name -prettyParamSet :: ParamSet (NixDoc ann) -> Bool -> Doc ann-prettyParamSet args var =+prettyParamSet :: Variadic -> ParamSet (NixDoc ann) -> Doc ann+prettyParamSet variadic args = encloseSep "{ " (align " }") sep- (fmap prettySetArg args <> prettyVariadic)+ (fmap prettySetArg args <> one "..." `whenTrue` (variadic == Variadic)) where prettySetArg (n, maybeDef) = maybe- (pretty n)- (\x -> pretty n <> " ? " <> withoutParens x)+ varName+ (\x -> varName <> " ? " <> withoutParens x) maybeDef- prettyVariadic = [ "..." | var ]+ where+ varName = prettyVarName n sep = align ", " prettyBind :: Binding (NixDoc ann) -> Doc ann prettyBind (NamedVar n v _p) = prettySelector n <> " = " <> withoutParens v <> ";" prettyBind (Inherit s ns _p) =- "inherit " <> scope <> align (fillSep $ prettyKeyName <$> ns) <> ";"+ "inherit " <> scope <> align (fillSep $ prettyVarName <$> ns) <> ";" where scope =- maybe- mempty- ((<> " ") . parens . withoutParens)- s+ ((<> " ") . parens . withoutParens) `whenJust` s prettyKeyName :: NKeyName (NixDoc ann) -> Doc ann-prettyKeyName (StaticKey "") = "\"\""-prettyKeyName (StaticKey key) | HashSet.member key reservedNames = "\"" <> pretty key <> "\""-prettyKeyName (StaticKey key) = pretty key+prettyKeyName (StaticKey key) =+ bool+ "\"\""+ (bool+ varName+ ("\"" <> varName <> "\"")+ (HashSet.member key reservedNames)+ )+ (not $ Text.null $ coerce key)+ where+ varName = prettyVarName key prettyKeyName (DynamicKey key) = runAntiquoted- (DoubleQuoted [Plain "\n"])+ (DoubleQuoted $ one $ Plain "\n") prettyString (\ x -> "${" <> withoutParens x <> "}") key@@ -183,7 +192,7 @@ prettySelector = hcat . punctuate "." . fmap prettyKeyName . NE.toList prettyAtom :: NAtom -> NixDoc ann-prettyAtom atom = simpleExpr $ pretty $ atomText atom+prettyAtom = simpleExpr . pretty . atomText prettyNix :: NExpr -> Doc ann prettyNix = withoutParens . foldFix exprFNixDoc@@ -195,16 +204,16 @@ -> Doc ann prettyOriginExpr = withoutParens . go where- go = exprFNixDoc . stripAnn . fmap render-- render :: Maybe (NValue t f m) -> NixDoc ann- render Nothing = simpleExpr "_"- render (Just (Free (reverse . citations @m -> p:_))) = go (_originExpr p)- render _ = simpleExpr "?"- -- render (Just (NValue (citations -> ps))) =- -- simpleExpr $ foldr ((\x y -> vsep [x, y]) . parens . indent 2 . withoutParens- -- . go . originExpr)- -- mempty (reverse ps)+ go = exprFNixDoc . stripAnnF . fmap render+ where+ render :: Maybe (NValue t f m) -> NixDoc ann+ render Nothing = simpleExpr "_"+ render (Just (Free (reverse . citations @m -> p:_))) = go (_originExpr p)+ render _ = simpleExpr "?"+ -- render (Just (NValue (citations -> ps))) =+ -- simpleExpr $ foldr ((\x y -> vsep [x, y]) . parens . indent 2 . withoutParens+ -- . go . originExpr)+ -- mempty (reverse ps) exprFNixDoc :: NExprF (NixDoc ann) -> NixDoc ann exprFNixDoc = \case@@ -212,9 +221,9 @@ NStr str -> simpleExpr $ prettyString str NList xs -> prettyContainer "[" (wrapParens appOpNonAssoc) "]" xs- NSet NNonRecursive xs ->+ NSet NonRecursive xs -> prettyContainer "{" prettyBind "}" xs- NSet NRecursive xs ->+ NSet Recursive xs -> prettyContainer "rec {" prettyBind "}" xs NAbs args body -> leastPrecedence $@@ -229,23 +238,26 @@ mkNixDoc opInfo $ hsep- [ wrapParens (f NAssocLeft) r1+ [ f NAssocLeft r1 , pretty $ operatorName opInfo- , wrapParens (f NAssocRight) r2+ , f NAssocRight r2 ] where opInfo = getBinaryOperator op+ f :: NAssoc -> NixDoc ann1 -> Doc ann1 f x =- bool- opInfo- (opInfo { associativity = NAssocNone })- (associativity opInfo /= x)+ wrapParens+ $ bool+ opInfo+ (opInfo { associativity = NAssocNone })+ (associativity opInfo /= x) NUnary op r1 -> mkNixDoc- opInfo- (pretty (operatorName opInfo) <> wrapParens opInfo r1)- where opInfo = getUnaryOperator op- NSelect r' attr o ->+ opInfo $+ pretty (operatorName opInfo) <> wrapParens opInfo r1+ where+ opInfo = getUnaryOperator op+ NSelect o r' attr -> maybe (mkNixDoc selectOp) (const leastPrecedence)@@ -254,16 +266,13 @@ where r = mkNixDoc selectOp (wrapParens appOpNonAssoc r') ordoc =- maybe- mempty- ((" or " <>) . wrapParens appOpNonAssoc)- o+ ((" or " <>) . wrapParens appOpNonAssoc) `whenJust` o NHasAttr r attr -> mkNixDoc hasAttrOp (wrapParens hasAttrOp r <> " ? " <> prettySelector attr)- NEnvPath p -> simpleExpr $ pretty ("<" <> p <> ">")+ NEnvPath p -> simpleExpr $ pretty @String $ "<" <> coerce p <> ">" NLiteralPath p -> pathExpr $- pretty $+ pretty @FilePath $ coerce $ case p of "./" -> "./." "../" -> "../."@@ -272,8 +281,8 @@ bool ("./" <> _txt) _txt- (any (`isPrefixOf` _txt) ["/", "~/", "./", "../"])- NSym name -> simpleExpr $ pretty name+ (any (`isPrefixOf` coerce _txt) ["/", "~/", "./", "../"])+ NSym name -> simpleExpr $ prettyVarName name NLet binds body -> leastPrecedence $ group $@@ -295,12 +304,12 @@ prettyAddScope "with " scope body NAssert cond body -> prettyAddScope "assert " cond body- NSynHole name -> simpleExpr $ pretty ("^" <> name)+ NSynHole name -> simpleExpr $ pretty @Text ("^" <> coerce name) where prettyContainer h f t c = list (simpleExpr (h <> t))- (const $ simpleExpr $ group $ nest 2 $ vsep $ [h] <> (f <$> c) <> [t])+ (const $ simpleExpr $ group $ nest 2 $ vsep $ one h <> (f <$> c) <> one t) c prettyAddScope h c b =@@ -316,15 +325,15 @@ phi :: NValue' t f m NExpr -> NExprF NExpr phi (NVConstant' a ) = NConstant a- phi (NVStr' ns ) = NStr $ DoubleQuoted [Plain (stringIgnoreContext ns)]+ phi (NVStr' ns ) = NStr $ DoubleQuoted $ one $ Plain $ stringIgnoreContext ns phi (NVList' l ) = NList l- phi (NVSet' s p) = NSet NNonRecursive- [ NamedVar (StaticKey k :| mempty) v (fromMaybe nullPos (M.lookup k p))+ phi (NVSet' p s) = NSet mempty+ [ NamedVar (one $ StaticKey k) v (fromMaybe nullPos $ (`M.lookup` p) k) | (k, v) <- toList s ] phi (NVClosure' _ _) = NSym "<closure>" phi (NVPath' p ) = NLiteralPath p- phi (NVBuiltin' name _) = NSym $ "builtins." <> name+ phi (NVBuiltin' name _) = NSym $ coerce ((mappend @Text) "builtins.") name prettyNValue :: forall t f m ann . MonadDataContext f m => NValue t f m -> Doc ann@@ -346,7 +355,7 @@ fillSep [ prettyNVal , indent 2 $- "(" <> mconcat ("from: " : (prettyOriginExpr . _originExpr <$> ps)) <> ")"+ "(" <> fold (one "from: " <> (prettyOriginExpr . _originExpr <$> ps)) <> ")" ] ) (citations @m @(NValue t f m) v)@@ -370,34 +379,36 @@ fillSep [ v' , indent 2 $- "(" <> mconcat ( "thunk from: " : (prettyOriginExpr . _originExpr <$> ps)) <> ")"+ "(" <> fold (one "thunk from: " <> (prettyOriginExpr . _originExpr <$> ps)) <> ")" ] -- | This function is used only by the testing code.-printNix :: forall t f m . MonadDataContext f m => NValue t f m -> String+printNix :: forall t f m . MonadDataContext f m => NValue t f m -> Text printNix = iterNValueByDiscardWith thk phi where- thk = toString thunkStubText+ thk = thunkStubText - phi :: NValue' t f m String -> String- phi (NVConstant' a ) = toString $ atomText a+ phi :: NValue' t f m Text -> Text+ phi (NVConstant' a ) = atomText a phi (NVStr' ns) = show $ stringIgnoreContext ns- phi (NVList' l ) = toString $ "[ " <> unwords (fmap toText l) <> " ]"- phi (NVSet' s _) =+ phi (NVList' l ) = "[ " <> unwords l <> " ]"+ phi (NVSet' _ s) = "{ " <>- concat- [ check (toString k) <> " = " <> v <> "; "- | (k, v) <- sort $ toList s+ fold+ [ check k <> " = " <> v <> "; "+ | (coerce -> k, v) <- sort $ toList s ] <> "}" where- check :: [Char] -> [Char]+ check :: Text -> Text check v = fromMaybe v- (fmap (surround . show) (readMaybe v :: Maybe Int)- <|> fmap (surround . show) (readMaybe v :: Maybe Float)- )- where surround s = "\"" <> s <> "\""+ (tryRead @Int <|> tryRead @Float)+ where+ surround s = "\"" <> s <> "\""++ tryRead :: forall a . (Read a, Show a) => Maybe Text+ tryRead = fmap (surround . show) (readMaybe (toString v) :: Maybe a) phi NVClosure'{} = "<<lambda>>"- phi (NVPath' fp ) = fp- phi (NVBuiltin' name _) = toString $ "<<builtin " <> name <> ">>"+ phi (NVPath' fp ) = fromString $ coerce fp+ phi (NVBuiltin' name _) = "<<builtin " <> coerce name <> ">>"
src/Nix/Reduce.hs view
@@ -1,13 +1,11 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}+{-# language CPP #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language PartialTypeSignatures #-}+{-# language TypeFamilies #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -fno-warn-name-shadowing #-} -- | This module provides a "reducing" expression evaluator, which reduces@@ -42,7 +40,8 @@ import qualified Text.Show import Nix.Atoms import Nix.Effects.Basic ( pathToDefaultNixFile )-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Options ( Options , reduceSets@@ -50,18 +49,16 @@ ) import Nix.Parser import Nix.Scope-import Nix.Utils import System.Directory-import System.FilePath newtype Reducer m a = Reducer { runReducer :: ReaderT- ( Maybe FilePath+ ( Maybe Path , Scopes (Reducer m) NExprLoc ) ( StateT- ( HashMap FilePath NExprLoc+ ( HashMap Path NExprLoc , HashMap Text Text ) m@@ -71,8 +68,8 @@ deriving ( Functor, Applicative, Alternative , Monad, MonadPlus, MonadFix, MonadIO, MonadFail- , MonadReader (Maybe FilePath, Scopes (Reducer m) NExprLoc)- , MonadState (HashMap FilePath NExprLoc, HashMap Text Text)+ , MonadReader (Maybe Path, Scopes (Reducer m) NExprLoc)+ , MonadState (HashMap Path NExprLoc, HashMap Text Text) ) staticImport@@ -80,59 +77,62 @@ . ( MonadIO m , Scoped NExprLoc m , MonadFail m- , MonadReader (Maybe FilePath, Scopes m NExprLoc) m- , MonadState (HashMap FilePath NExprLoc, HashMap Text Text) m+ , MonadReader (Maybe Path, Scopes m NExprLoc) m+ , MonadState (HashMap Path NExprLoc, HashMap Text Text) m ) => SrcSpan- -> FilePath+ -> Path -> m NExprLoc-staticImport pann path = do- mfile <- asks fst- path <- liftIO $ pathToDefaultNixFile path- path' <- liftIO $ pathToDefaultNixFile =<< canonicalizePath- (maybe id ((</>) . takeDirectory) mfile path)+staticImport pann path =+ do+ mfile <- asks fst+ path' <- liftIO $ pathToDefaultNixFile path+ path'' <- liftIO $ pathToDefaultNixFile =<< coerce canonicalizePath+ (maybe id ((</>) . takeDirectory) mfile path') - imports <- gets fst- maybe- (go path')- pure- (HM.lookup path' imports)- where- go path = do- liftIO $ putStrLn $ "Importing file " <> path+ let+ importIt :: m NExprLoc+ importIt = do+ liftIO $ putStrLn $ "Importing file " <> coerce path'' - eres <- liftIO $ parseNixFileLoc path- either- (\ err -> fail $ "Parse failed: " <> show err)- (\ x -> do- let- pos = SourcePos "Reduce.hs" (mkPos 1) (mkPos 1)- span = SrcSpan pos pos- cur =- NamedVar- (StaticKey "__cur_file" :| mempty)- (Fix (NLiteralPath_ pann path))- pos- x' = Fix $ NLet_ span [cur] x- modify $ first $ HM.insert path x'- local- (const (pure path, mempty)) $- do- x'' <- foldFix reduce x'- modify $ first $ HM.insert path x''- pure x''- )- eres+ eres <- liftIO $ parseNixFileLoc path''+ either+ (\ err -> fail $ "Parse failed: " <> show err)+ (\ x -> do+ let+ pos = join (SourcePos "Reduce.hs") $ mkPos 1+ span = join SrcSpan pos+ cur =+ NamedVar+ (one $ StaticKey "__cur_file")+ (NLiteralPathAnn pann path'')+ pos+ x' = NLetAnn span (one cur) x+ modify $ first $ HM.insert path'' x'+ local+ (const (pure path'', mempty)) $+ do+ x'' <- foldFix reduce x'+ modify $ first $ HM.insert path'' x''+ pure x''+ )+ eres + imports <- gets fst+ maybe+ importIt+ pure+ (HM.lookup path'' imports)+ -- gatherNames :: NExprLoc -> HashSet VarName -- gatherNames = foldFix $ \case--- NSym_ _ var -> S.singleton var--- Compose (Ann _ x) -> fold x+-- NSymAnnF _ var -> S.singleton var+-- AnnF _ x -> fold x reduceExpr- :: (MonadIO m, MonadFail m) => Maybe FilePath -> NExprLoc -> m NExprLoc+ :: (MonadIO m, MonadFail m) => Maybe Path -> NExprLoc -> m NExprLoc reduceExpr mpath expr =- (`evalStateT` (mempty, mempty))+ (`evalStateT` mempty) . (`runReaderT` (mpath, mempty)) . runReducer $ foldFix reduce expr@@ -142,26 +142,26 @@ . ( MonadIO m , Scoped NExprLoc m , MonadFail m- , MonadReader (Maybe FilePath, Scopes m NExprLoc) m- , MonadState (HashMap FilePath NExprLoc, HashMap Text Text) m+ , MonadReader (Maybe Path, Scopes m NExprLoc) m+ , MonadState (HashMap Path NExprLoc, HashMap Text Text) m ) => NExprLocF (m NExprLoc) -> m NExprLoc -- | Reduce the variable to its value if defined. -- Leave it as it is otherwise.-reduce (NSym_ ann var) =- fromMaybe (Fix (NSym_ ann var)) <$> lookupVar var+reduce (NSymAnnF ann var) =+ fromMaybe (NSymAnn ann var) <$> lookupVar var -- | Reduce binary and integer negation.-reduce (NUnary_ uann op arg) =+reduce (NUnaryAnnF uann op arg) = do x <- arg- pure $ Fix $+ pure $ case (op, x) of- (NNeg, Fix (NConstant_ cann (NInt n))) -> NConstant_ cann $ NInt $ negate n- (NNot, Fix (NConstant_ cann (NBool b))) -> NConstant_ cann $ NBool $ not b- _ -> NUnary_ uann op x+ (NNeg, NConstantAnn cann (NInt n)) -> NConstantAnn cann $ NInt $ negate n+ (NNot, NConstantAnn cann (NBool b)) -> NConstantAnn cann $ NBool $ not b+ _ -> NUnaryAnn uann op x -- | Reduce function applications. --@@ -169,32 +169,32 @@ -- -- * Reduce a lambda function by adding its name to the local -- scope and recursively reducing its body.-reduce (NBinary_ bann NApp fun arg) = fun >>= \case- f@(Fix (NSym_ _ "import")) ->+reduce (NBinaryAnnF bann NApp fun arg) = fun >>= \case+ f@(NSymAnn _ "import") -> (\case- -- Fix (NEnvPath_ pann origPath) -> staticImport pann origPath- Fix (NLiteralPath_ pann origPath) -> staticImport pann origPath- v -> pure $ Fix $ NBinary_ bann NApp f v+ -- NEnvPathAnn pann origPath -> staticImport pann origPath+ NLiteralPathAnn pann origPath -> staticImport pann origPath+ v -> pure $ NBinaryAnn bann NApp f v ) =<< arg - Fix (NAbs_ _ (Param name) body) ->+ NAbsAnn _ (Param name) body -> do x <- arg pushScope- (HM.singleton name x)+ (coerce $ HM.singleton name x) (foldFix reduce body) - f -> Fix . NBinary_ bann NApp f <$> arg+ f -> NBinaryAnn bann NApp f <$> arg -- | Reduce an integer addition to its result.-reduce (NBinary_ bann op larg rarg) =+reduce (NBinaryAnnF bann op larg rarg) = do lval <- larg rval <- rarg- pure $ Fix $+ pure $ case (op, lval, rval) of- (NPlus, Fix (NConstant_ ann (NInt x)), Fix (NConstant_ _ (NInt y))) -> NConstant_ ann $ NInt $ x + y- _ -> NBinary_ bann op lval rval+ (NPlus, NConstantAnn ann (NInt x), NConstantAnn _ (NInt y)) -> NConstantAnn ann $ NInt $ x + y+ _ -> NBinaryAnn bann op lval rval -- | Reduce a select on a Set by substituting the set to the selected value. --@@ -203,13 +203,13 @@ -- 1. The selected expr is indeed a set. -- 2. The selection AttrPath is a list of StaticKeys. -- 3. The selected AttrPath exists in the set.-reduce base@(NSelect_ _ _ attrs _)+reduce base@(NSelectAnnF _ _ _ attrs) | sAttrPath $ NE.toList attrs = do- (NSelect_ _ aset attrs _) <- sequence base+ (NSelectAnnF _ _ aset attrs) <- sequenceA base inspectSet (unFix aset) attrs | otherwise = sId where- sId = Fix <$> sequence base+ sId = reduceLayer base -- The selection AttrPath is composed of StaticKeys. sAttrPath (StaticKey _ : xs) = sAttrPath xs sAttrPath [] = True@@ -220,7 +220,7 @@ n@(NamedVar (a' :| _) _ _) | a' == a -> pure n _ -> findBind xs attrs -- Follow the attrpath recursively in sets.- inspectSet (NSet_ _ NNonRecursive binds) attrs = case findBind binds attrs of+ inspectSet (NSetAnnF _ NonRecursive binds) attrs = case findBind binds attrs of Just (NamedVar _ e _) -> case NE.uncons attrs of (_, Just attrs) -> inspectSet (unFix e) attrs _ -> pure e@@ -231,49 +231,52 @@ -- | Reduce a set by inlining its binds outside of the set -- if none of the binds inherit the super set.-reduce e@(NSet_ ann NNonRecursive binds) =- do- let- usesInherit =- any- (\case- Inherit{} -> True- _ -> False- )- binds-- bool- (Fix <$> sequence e)- (clearScopes @NExprLoc $ Fix . NSet_ ann NNonRecursive <$> traverse sequence binds)+reduce e@(NSetAnnF ann r binds) =+ bool+ -- Encountering a 'rec set' construction eliminates any hope of inlining+ -- definitions.+ mExprLoc+ (bool+ (reduceLayer e)+ mExprLoc usesInherit+ )+ (r == NonRecursive)+ where+ mExprLoc :: m NExprLoc+ mExprLoc =+ clearScopes @NExprLoc $ NSetAnn ann r <$> traverse sequenceA binds --- Encountering a 'rec set' construction eliminates any hope of inlining--- definitions.-reduce (NSet_ ann NRecursive binds) =- clearScopes @NExprLoc $ Fix . NSet_ ann NRecursive <$> traverse sequence binds+ usesInherit =+ any+ (\case+ Inherit{} -> True+ _ -> False+ )+ binds -- Encountering a 'with' construction eliminates any hope of inlining -- definitions.-reduce (NWith_ ann scope body) =- clearScopes @NExprLoc $ Fix <$> liftA2 (NWith_ ann) scope body+reduce (NWithAnnF ann scope body) =+ clearScopes @NExprLoc $ liftA2 (NWithAnn ann) scope body -- | Reduce a let binds section by pushing lambdas, -- constants and strings to the body scope.-reduce (NLet_ ann binds body) =+reduce (NLetAnnF ann binds body) = do- binds' <- traverse sequence binds+ binds' <- traverse sequenceA binds body' <-- (`pushScope` body) . HM.fromList . catMaybes =<<+ (`pushScope` body) . coerce . HM.fromList . catMaybes =<< traverse (\case NamedVar (StaticKey name :| []) def _pos -> let defcase = \case- d@(Fix NAbs_ {}) -> pure (name, d)- d@(Fix NConstant_{}) -> pure (name, d)- d@(Fix NStr_ {}) -> pure (name, d)- _ -> Nothing+ d@NAbsAnn {} -> pure (name, d)+ d@NConstantAnn{} -> pure (name, d)+ d@NStrAnn {} -> pure (name, d)+ _ -> Nothing in defcase <$> def @@ -282,11 +285,11 @@ binds -- let names = gatherNames body'- -- binds' <- traverse sequence binds <&> \b -> flip filter b $ \case+ -- binds' <- traverse sequenceA binds <&> \b -> flip filter b $ \case -- NamedVar (StaticKey name _ :| []) _ -> -- name `S.member` names -- _ -> True- pure $ Fix $ NLet_ ann binds' body'+ pure $ NLetAnn ann binds' body' -- where -- go m [] = pure m -- go m (x:xs) = case x of@@ -297,34 +300,37 @@ -- | Reduce an if to the relevant path if -- the condition is a boolean constant.-reduce e@(NIf_ _ b t f) =+reduce e@(NIfAnnF _ b t f) = (\case- Fix (NConstant_ _ (NBool b')) -> if b' then t else f- _ -> Fix <$> sequence e+ NConstantAnn _ (NBool b') -> bool f t b'+ _ -> reduceLayer e ) =<< b -- | Reduce an assert atom to its encapsulated -- symbol if the assertion is a boolean constant.-reduce e@(NAssert_ _ b body) =+reduce e@(NAssertAnnF _ b body) = (\case- Fix (NConstant_ _ (NBool b')) | b' -> body- _ -> Fix <$> sequence e+ NConstantAnn _ (NBool True) -> body+ _ -> reduceLayer e ) =<< b -reduce (NAbs_ ann params body) = do- params' <- sequence params+reduce (NAbsAnnF ann params body) = do+ params' <- sequenceA params -- Make sure that variable definitions in scope do not override function -- arguments. let- args =+ scope = coerce $ case params' of- Param name -> HM.singleton name $ Fix $ NSym_ ann name- ParamSet pset _ _ ->- HM.fromList $ (\(k, _) -> (k, Fix $ NSym_ ann k)) <$> pset- Fix . NAbs_ ann params' <$> pushScope args body+ Param name -> one (name, NSymAnn ann name)+ ParamSet _ _ pset ->+ HM.fromList $ (\(k, _) -> (k, NSymAnn ann k)) <$> pset+ NAbsAnn ann params' <$> pushScope scope body -reduce v = Fix <$> sequence v+reduce v = reduceLayer v +reduceLayer :: (Traversable f1, Applicative f2) => f1 (f2 (Fix f1)) -> f2 (Fix f1)+reduceLayer v = Fix <$> sequenceA v+ -- newtype FlaggedF f r = FlaggedF { flagged :: (IORef Bool, f r) } newtype FlaggedF f r = FlaggedF (IORef Bool, f r) deriving (Functor, Foldable, Traversable)@@ -337,7 +343,7 @@ flagExprLoc :: (MonadIO n, Traversable f) => Fix f -> n (Flagged f) flagExprLoc = foldFixM $ \x -> do flag <- liftIO $ newIORef False- pure $ Fix $ FlaggedF (flag, x)+ pure $ coerce (flag, x) -- stripFlags :: Functor f => Flagged f -> Fix f -- stripFlags = foldFix $ Fix . snd . flagged@@ -348,7 +354,7 @@ \(FlaggedF (b, Compose x)) -> bool Nothing- (Fix . Compose <$> traverse prune x)+ (annUnitToAnn <$> traverse prune x) <$> liftIO (readIORef b) where prune :: NExprF (Maybe NExprLoc) -> Maybe (NExprF NExprLoc)@@ -360,30 +366,30 @@ NList l -> pure $ NList $ bool- (fromMaybe nNull <$>)+ (fromMaybe annNNull <$>) catMaybes (reduceLists opts) -- Reduce list members that aren't used; breaks if elemAt is used l NSet recur binds -> pure $ NSet recur $ bool- (fromMaybe nNull <<$>>)- (mapMaybe sequence)+ (fromMaybe annNNull <<$>>)+ (mapMaybe sequenceA) (reduceSets opts) -- Reduce set members that aren't used; breaks if hasAttr is used binds - NLet binds (Just body@(AnnE _ x)) ->+ NLet binds (Just body@(Ann _ x)) -> pure $ list x (`NLet` body) (mapMaybe pruneBinding binds) - NSelect (Just aset) attr alt ->- pure $ NSelect aset (pruneKeyName <$> attr) $ join alt+ NSelect alt (Just aset) attr ->+ pure $ NSelect (join alt) aset $ pruneKeyName <$> attr -- These are the only short-circuiting binary operators- NBinary NAnd (Just (AnnE _ larg)) _ -> pure larg- NBinary NOr (Just (AnnE _ larg)) _ -> pure larg+ NBinary NAnd (Just (Ann _ larg)) _ -> pure larg+ NBinary NOr (Just (Ann _ larg)) _ -> pure larg -- If the function was never called, it means its argument was in a -- thunk that was forced elsewhere.@@ -393,22 +399,22 @@ -- invalid is that we're trying to emit what will reproduce whatever -- fail the user encountered, which means providing all aspects of -- the evaluation path they ultimately followed.- NBinary op Nothing (Just rarg) -> pure $ NBinary op nNull rarg- NBinary op (Just larg) Nothing -> pure $ NBinary op larg nNull+ NBinary op Nothing (Just rarg) -> pure $ NBinary op annNNull rarg+ NBinary op (Just larg) Nothing -> pure $ NBinary op larg annNNull -- If the scope of a with was never referenced, it's not needed- NWith Nothing (Just (AnnE _ body)) -> pure body+ NWith Nothing (Just (Ann _ body)) -> pure body NAssert Nothing _ -> fail "How can an assert be used, but its condition not?"- NAssert _ (Just (AnnE _ body)) -> pure body- NAssert (Just cond) _ -> pure $ NAssert cond nNull+ NAssert _ (Just (Ann _ body)) -> pure body+ NAssert (Just cond) _ -> pure $ NAssert cond annNNull NIf Nothing _ _ -> fail "How can an if be used, but its condition not?" - NIf _ Nothing (Just (AnnE _ f)) -> pure f- NIf _ (Just (AnnE _ t)) Nothing -> pure t+ NIf _ Nothing (Just (Ann _ f)) -> pure f+ NIf _ (Just (Ann _ t)) Nothing -> pure t - x -> sequence x+ x -> sequenceA x pruneString :: NString (Maybe NExprLoc) -> NString NExprLoc pruneString (DoubleQuoted xs) = DoubleQuoted $ mapMaybe pruneAntiquotedText xs@@ -436,28 +442,28 @@ pruneParams :: Params (Maybe NExprLoc) -> Params NExprLoc pruneParams (Param n) = Param n- pruneParams (ParamSet xs b n) =- ParamSet (reduceOrPassMode <$> xs) b n+ pruneParams (ParamSet mname variadic pset) =+ ParamSet mname variadic (reduceOrPassMode <$> pset) where reduceOrPassMode = second $ bool fmap- ((pure .) . maybe nNull)+ ((pure .) . maybe annNNull) (reduceSets opts) -- Reduce set members that aren't used; breaks if hasAttr is used- (fromMaybe nNull)+ (fromMaybe annNNull) pruneBinding :: Binding (Maybe NExprLoc) -> Maybe (Binding NExprLoc) pruneBinding (NamedVar _ Nothing _ ) = Nothing pruneBinding (NamedVar xs (Just x) pos) = pure $ NamedVar (pruneKeyName <$> xs) x pos pruneBinding (Inherit _ [] _ ) = Nothing pruneBinding (Inherit (join -> Nothing) _ _ ) = Nothing- pruneBinding (Inherit (join -> m) xs pos) = pure $ Inherit m (pruneKeyName <$> xs) pos+ pruneBinding (Inherit (join -> m) xs pos) = pure $ Inherit m xs pos reducingEvalExpr :: (Framed e m, Has e Options, Exception r, MonadCatch m, MonadIO m) => (NExprLocF (m a) -> m a)- -> Maybe FilePath+ -> Maybe Path -> NExprLoc -> m (NExprLoc, Either r a) reducingEvalExpr eval mpath expr =@@ -467,7 +473,7 @@ pure <$> foldFix (addEvalFlags eval) expr' opts :: Options <- asks $ view hasLens expr'' <- pruneTree opts expr'- pure (fromMaybe nNull expr'', eres)+ pure (fromMaybe annNNull expr'', eres) where addEvalFlags k (FlaggedF (b, x)) = liftIO (writeIORef b True) *> k x
src/Nix/Render.hs view
@@ -1,103 +1,100 @@-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE MultiWayIf #-}+{-# language UndecidableInstances #-}+{-# language CPP #-}+{-# language ConstraintKinds #-}+{-# language DefaultSignatures #-}+{-# language GADTs #-}+{-# language TypeFamilies #-}+{-# language TypeOperators #-}+{-# language MultiWayIf #-} module Nix.Render where -import Prelude hiding ( readFile )--import qualified Data.ByteString as BS import qualified Data.Set as Set import Nix.Utils.Fix1 ( Fix1T- , MonadFix1T )+ , MonadFix1T+ ) import Nix.Expr.Types.Annotated import Prettyprinter import qualified System.Directory as S-import qualified System.Posix.Files as S+import qualified System.PosixCompat.Files as S import Text.Megaparsec.Error import Text.Megaparsec.Pos+import qualified Data.Text as Text -class MonadFail m => MonadFile m where- readFile :: FilePath -> m ByteString- default readFile :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m ByteString- readFile = lift . readFile- listDirectory :: FilePath -> m [FilePath]- default listDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m [FilePath]+class (MonadFail m, MonadIO m) => MonadFile m where+ readFile :: Path -> m Text+ default readFile :: (MonadTrans t, MonadIO m', MonadFile m', m ~ t m') => Path -> m Text+ readFile = liftIO . Prelude.readFile+ listDirectory :: Path -> m [Path]+ default listDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m [Path] listDirectory = lift . listDirectory- getCurrentDirectory :: m FilePath- default getCurrentDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => m FilePath+ getCurrentDirectory :: m Path+ default getCurrentDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => m Path getCurrentDirectory = lift getCurrentDirectory- canonicalizePath :: FilePath -> m FilePath- default canonicalizePath :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m FilePath+ canonicalizePath :: Path -> m Path+ default canonicalizePath :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m Path canonicalizePath = lift . canonicalizePath- getHomeDirectory :: m FilePath- default getHomeDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => m FilePath+ getHomeDirectory :: m Path+ default getHomeDirectory :: (MonadTrans t, MonadFile m', m ~ t m') => m Path getHomeDirectory = lift getHomeDirectory- doesPathExist :: FilePath -> m Bool- default doesPathExist :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool+ doesPathExist :: Path -> m Bool+ default doesPathExist :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool doesPathExist = lift . doesPathExist- doesFileExist :: FilePath -> m Bool- default doesFileExist :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool+ doesFileExist :: Path -> m Bool+ default doesFileExist :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool doesFileExist = lift . doesFileExist- doesDirectoryExist :: FilePath -> m Bool- default doesDirectoryExist :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m Bool+ doesDirectoryExist :: Path -> m Bool+ default doesDirectoryExist :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m Bool doesDirectoryExist = lift . doesDirectoryExist- getSymbolicLinkStatus :: FilePath -> m S.FileStatus- default getSymbolicLinkStatus :: (MonadTrans t, MonadFile m', m ~ t m') => FilePath -> m S.FileStatus+ getSymbolicLinkStatus :: Path -> m S.FileStatus+ default getSymbolicLinkStatus :: (MonadTrans t, MonadFile m', m ~ t m') => Path -> m S.FileStatus getSymbolicLinkStatus = lift . getSymbolicLinkStatus instance MonadFile IO where- readFile = BS.readFile- listDirectory = S.listDirectory- getCurrentDirectory = S.getCurrentDirectory- canonicalizePath = S.canonicalizePath- getHomeDirectory = S.getHomeDirectory- doesPathExist = S.doesPathExist- doesFileExist = S.doesFileExist- doesDirectoryExist = S.doesDirectoryExist- getSymbolicLinkStatus = S.getSymbolicLinkStatus+ readFile = Prelude.readFile+ listDirectory = coerce S.listDirectory+ getCurrentDirectory = coerce S.getCurrentDirectory+ canonicalizePath = coerce S.canonicalizePath+ getHomeDirectory = coerce S.getHomeDirectory+ doesPathExist = coerce S.doesPathExist+ doesFileExist = coerce S.doesFileExist+ doesDirectoryExist = coerce S.doesDirectoryExist+ getSymbolicLinkStatus = coerce S.getSymbolicLinkStatus -instance (MonadFix1T t m, MonadFail (Fix1T t m), MonadFile m) => MonadFile (Fix1T t m)+instance (MonadFix1T t m, MonadIO (Fix1T t m), MonadFail (Fix1T t m), MonadFile m) => MonadFile (Fix1T t m) posAndMsg :: SourcePos -> Doc a -> ParseError s Void posAndMsg (SourcePos _ lineNo _) msg = FancyError (unPos lineNo)- (Set.fromList [ErrorFail (show msg) :: ErrorFancy Void])+ (Set.fromList $ one (ErrorFail (show msg) :: ErrorFancy Void)) renderLocation :: MonadFile m => SrcSpan -> Doc a -> m (Doc a)-renderLocation (SrcSpan (SourcePos file begLine begCol) (SourcePos file' endLine endCol)) msg- | file == file' && file == "<string>" && begLine == endLine- = pure $ "In raw input string at position " <> pretty (unPos begCol)+renderLocation (SrcSpan (SourcePos (coerce -> file) begLine begCol) (SourcePos (coerce -> file') endLine endCol)) msg+ | file == file' && file == "<string>" && begLine == endLine =+ pure $ "In raw input string at position " <> pretty (unPos begCol) - | file /= "<string>" && file == file'- = do- exist <- doesFileExist file- if exist- then do+ | file /= "<string>" && file == file' =+ bool+ (pure msg)+ (do txt <- sourceContext file begLine begCol endLine endCol msg pure $ vsep [ "In file " <> errorContext file begLine begCol endLine endCol <> ":" , txt ]- else pure msg+ )+ =<< doesFileExist file renderLocation (SrcSpan beg end) msg = fail $ "Don't know how to render range from " <> show beg <>" to " <> show end <>" for fail: " <> show msg -errorContext :: FilePath -> Pos -> Pos -> Pos -> Pos -> Doc a-errorContext path bl bc _el _ec =+errorContext :: Path -> Pos -> Pos -> Pos -> Pos -> Doc a+errorContext (coerce @Path @FilePath -> path) bl bc _el _ec = pretty path <> ":" <> pretty (unPos bl) <> ":" <> pretty (unPos bc) sourceContext- :: MonadFile m => FilePath -> Pos -> Pos -> Pos -> Pos -> Doc a -> m (Doc a)+ :: MonadFile m => Path -> Pos -> Pos -> Pos -> Pos -> Doc a -> m (Doc a) sourceContext path (unPos -> begLine) (unPos -> _begCol) (unPos -> endLine) (unPos -> _endCol) msg = do let beg' = max 1 $ begLine - 3@@ -107,31 +104,35 @@ . take (end' - beg') . drop (pred beg') . lines- . decodeUtf8- <$> readFile path+ <$> Nix.Render.readFile path let- longest = length $ show @String (beg' + (length ls) - 1)+ longest = Text.length $ show $ beg' + length ls - 1+ pad :: Int -> Text pad n = let+ ns :: Text ns = show n- nsp = replicate (longest - length ns) ' ' <> ns+ nsp = Text.replicate (longest - Text.length ns) " " <> ns in if | n == begLine && n == endLine -> "==> " <> nsp <> " | " | n >= begLine && n <= endLine -> " > " <> nsp <> " | " | otherwise -> " " <> nsp <> " | " composeLine n l =- [pretty (pad n) <> l]- ++ [ pretty- $ replicate (length (pad n) - 3) ' '- <> "| "- <> replicate (_begCol - 1) ' '- <> replicate (_endCol - _begCol) '^'- | begLine == endLine && n == endLine ]+ one (pretty (pad n) <> l)+ <> whenTrue+ (one $+ pretty $+ Text.replicate (Text.length (pad n) - 3) " "+ <> "|"+ <> Text.replicate (_begCol + 1) " "+ <> Text.replicate (_endCol - _begCol) "^"+ )+ (begLine == endLine && n == endLine) -- XXX: Consider inserting the message here when it is small enough. -- ATM some messages are so huge that they take prevalence over the source listing. -- ++ [ indent (length $ pad n) msg | n == endLine ] - ls' = concat $ zipWith composeLine [beg' ..] ls+ ls' = fold $ zipWith composeLine [beg' ..] ls - pure $ vsep $ ls' ++ [ indent (length $ pad begLine) msg ]+ pure $ vsep $ ls' <> one (indent (Text.length $ pad begLine) msg)
src/Nix/Render/Frame.hs view
@@ -1,21 +1,21 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}+{-# language CPP #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language MultiWayIf #-}+{-# language GADTs #-}+{-# language TypeFamilies #-} -- | Code for rendering/representation of the messages packaged with their context (Frames). module Nix.Render.Frame where import Prelude hiding ( Comparison )-import Nix.Utils+import GHC.Exception ( ErrorCall ) import Data.Fix ( Fix(..) )-import Nix.Eval+import Nix.Eval hiding ( addMetaInfo ) import Nix.Exec-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Frames import Nix.Normal import Nix.Options@@ -39,37 +39,39 @@ => Frames -> m (Doc ann) renderFrames [] = stub-renderFrames (x : xs) = do- opts :: Options <- asks (view hasLens)- frames <- if- | verbose opts <= ErrorsOnly -> renderFrame @v @t @f x- | verbose opts <= Informational -> do- f <- renderFrame @v @t @f x- pure $ concatMap go (reverse xs) <> f- | otherwise -> concat <$> traverse (renderFrame @v @t @f) (reverse (x : xs))- pure $- list- mempty- vsep- frames+renderFrames xss@(x : xs) =+ do+ opts :: Options <- asks $ view hasLens+ let+ verbosity :: Verbosity+ verbosity = verbose opts+ renderedFrames <- if+ | verbosity <= ErrorsOnly -> render1 x+ -- 2021-10-22: NOTE: List reverse is completely conterproductive. `reverse` of list famously neest to traverse the whole list to take the last element+ | verbosity <= Informational -> (foldMap renderPosition (reverse xs) <>) <$> render1 x+ | otherwise -> foldMapM render1 (reverse xss)+ pure $ list mempty vsep renderedFrames where- go :: NixFrame -> [Doc ann]- go f =- maybe- mempty- (\ pos -> ["While evaluating at " <> pretty (sourcePosPretty pos) <> colon])- (framePos @v @m f)+ render1 :: NixFrame -> m [Doc ann1]+ render1 = renderFrame @v @t @f + renderPosition :: NixFrame -> [Doc ann]+ renderPosition =+ whenJust+ (\ pos -> one ("While evaluating at " <> pretty (sourcePosPretty pos) <> colon))+ . framePos @v @m+ framePos :: forall v (m :: Type -> Type) . (Typeable m, Typeable v) => NixFrame -> Maybe SourcePos-framePos (NixFrame _ f)- | Just (e :: EvalFrame m v) <- fromException f = case e of- EvaluatingExpr _ (AnnE (SrcSpan beg _) _) -> pure beg+framePos (NixFrame _ f) =+ (\case+ EvaluatingExpr _ (Ann (SrcSpan beg _) _) -> pure beg _ -> Nothing- | otherwise = Nothing+ )+ =<< fromException @(EvalFrame m v) f renderFrame :: forall v t f e m ann@@ -87,55 +89,57 @@ | Just (e :: ValueFrame t f m ) <- fromException f = renderValueFrame level e | Just (e :: NormalLoop t f m ) <- fromException f = renderNormalLoop level e | Just (e :: ExecFrame t f m ) <- fromException f = renderExecFrame level e- | Just (e :: ErrorCall ) <- fromException f = pure [pretty (Text.show e)]- | Just (e :: SynHoleInfo m v) <- fromException f = pure [pretty (Text.show e)]+ | Just (e :: ErrorCall ) <- fromException f = pure $ one $ pretty (Text.show e)+ | Just (e :: SynHoleInfo m v) <- fromException f = pure $ one $ pretty (Text.show e) | otherwise = fail $ "Unrecognized frame: " <> show f wrapExpr :: NExprF r -> NExpr wrapExpr x = Fix (Fix (NSym "<?>") <$ x) renderEvalFrame- :: (MonadReader e m, Has e Options, MonadFile m)+ :: forall e m v ann+ . (MonadReader e m, Has e Options, MonadFile m) => NixLevel -> EvalFrame m v -> m [Doc ann] renderEvalFrame level f = do opts :: Options <- asks (view hasLens)+ let+ addMetaInfo :: ([Doc ann] -> [Doc ann]) -> SrcSpan -> Doc ann -> m [Doc ann]+ addMetaInfo trans loc = fmap (trans . one) . renderLocation loc+ case f of- EvaluatingExpr scope e@(AnnE ann _) ->- do- let- scopeInfo =- bool- mempty- [pretty $ Text.show scope]- (showScopes opts)- fmap- (\x -> scopeInfo <> [x])- $ renderLocation ann =<<- renderExpr level "While evaluating" "Expression" e+ EvaluatingExpr scope e@(Ann loc _) ->+ addMetaInfo+ (scopeInfo <>)+ loc+ =<< renderExpr level "While evaluating" "Expression" e+ where+ scopeInfo :: [Doc ann]+ scopeInfo =+ one (pretty $ Text.show scope) `whenTrue` showScopes opts - ForcingExpr _scope e@(AnnE ann _) | thunks opts ->- fmap- (: mempty)- $ renderLocation ann =<<- renderExpr level "While forcing thunk from" "Forcing thunk" e+ ForcingExpr _scope e@(Ann loc _) | thunks opts ->+ addMetaInfo+ id+ loc+ =<< renderExpr level "While forcing thunk from" "Forcing thunk" e - Calling name ann ->- fmap- (: mempty)- $ renderLocation ann $- "While calling builtins." <> pretty name+ Calling name loc ->+ addMetaInfo+ id+ loc+ $ "While calling builtins." <> pretty name SynHole synfo ->- sequence $- let e@(AnnE ann _) = _synHoleInfo_expr synfo in-- [ renderLocation ann =<<+ sequenceA+ [ renderLocation loc =<< renderExpr level "While evaluating" "Syntactic Hole" e , pure $ pretty $ Text.show $ _synHoleInfo_scope synfo ]+ where+ e@(Ann loc _) = _synHoleInfo_expr synfo ForcingExpr _ _ -> stub @@ -147,18 +151,28 @@ -> Text -> NExprLoc -> m (Doc ann)-renderExpr _level longLabel shortLabel e@(AnnE _ x) = do+renderExpr _level longLabel shortLabel e@(Ann _ x) = do opts :: Options <- asks (view hasLens)- let rendered- | verbose opts >= DebugInfo =- pretty (PS.ppShow (stripAnnotation e))- | verbose opts >= Chatty = prettyNix (stripAnnotation e)- | otherwise = prettyNix (Fix (Fix (NSym "<?>") <$ x))+ let+ lvl :: Verbosity+ lvl = verbose opts++ expr :: NExpr+ expr = stripAnnotation e++ concise = prettyNix $ Fix $ Fix (NSym "<?>") <$ x++ chatty =+ bool+ (pretty $ PS.ppShow expr)+ (prettyNix expr)+ (lvl == Chatty)+ pure $ bool- (pretty shortLabel <> fillSep [": ", rendered])- (vsep [pretty (longLabel <> ":\n>>>>>>>>"), indent 2 rendered, "<<<<<<<<"])- (verbose opts >= Chatty)+ (pretty shortLabel <> fillSep [": ", concise])+ (vsep [pretty (longLabel <> ":\n>>>>>>>>"), indent 2 chatty, "<<<<<<<<"])+ (lvl >= Chatty) renderValueFrame :: forall e t f m ann@@ -166,7 +180,7 @@ => NixLevel -> ValueFrame t f m -> m [Doc ann]-renderValueFrame level = fmap (: mempty) . \case+renderValueFrame level = fmap one . \case ForcingThunk _t -> pure "ForcingThunk" -- jww (2019-03-18): NYI ConcerningValue _v -> pure "ConcerningValue" Comparison _ _ -> pure "Comparing"@@ -175,22 +189,23 @@ Multiplication _ _ -> pure "Multiplying" Coercion x y -> pure- $ mconcat [desc, pretty (describeValue x), " to ", pretty (describeValue y)]+ $ fold [desc, pretty (describeValue x), " to ", pretty (describeValue y)] where desc = bool- "While coercing "- "Cannot coerce "- (level <= Error)+ "While coercing "+ "Cannot coerce "+ (level <= Error) CoercionToJson v ->- ("CoercionToJson " <>) <$> renderValue level "" "" v+ ("CoercionToJson " <>) <$> dumbRenderValue v CoercionFromJson _j -> pure "CoercionFromJson" Expectation t v ->- (msg <>) <$> renderValue @_ @t @f @m level "" "" v+ (msg <>) <$> dumbRenderValue v where msg = "Expected " <> pretty (describeValue t) <> ", but saw " +-- 2021-10-28: NOTE: notice it ignores `level`, `longlabel` & `shortlabel`, to underline that `dumbRenderValue` synonym was created renderValue :: forall e t f m ann . (MonadReader e m, Has e Options, MonadFile m, MonadCitedThunks t f m)@@ -207,37 +222,34 @@ (values opts) <$> removeEffects v +dumbRenderValue+ :: forall e t f m ann+ . (MonadReader e m, Has e Options, MonadFile m, MonadCitedThunks t f m)+ => (NValue t f m -> m (Doc ann))+dumbRenderValue = renderValue Info mempty mempty+ renderExecFrame :: (MonadReader e m, Has e Options, MonadFile m, MonadCitedThunks t f m) => NixLevel -> ExecFrame t f m -> m [Doc ann]-renderExecFrame level =- \case- Assertion ann v ->- fmap- (: mempty)- (do- d <- renderValue level "" "" v- renderLocation ann $ fillSep ["Assertion failed:", d]- )+renderExecFrame _level (Assertion ann v) =+ fmap+ one+ $ renderLocation ann . fillSep . on (<>) one "Assertion failed:" =<< dumbRenderValue v renderThunkLoop :: (MonadReader e m, Has e Options, MonadFile m, Show (ThunkId m)) => NixLevel -> ThunkLoop -> m [Doc ann]-renderThunkLoop _level = pure . (: mempty) . \case- ThunkLoop n -> pretty $ "Infinite recursion in thunk " <> n+renderThunkLoop _level (ThunkLoop n) =+ pure . one . pretty $ "Infinite recursion in thunk " <> n renderNormalLoop :: (MonadReader e m, Has e Options, MonadFile m, MonadCitedThunks t f m) => NixLevel -> NormalLoop t f m -> m [Doc ann]-renderNormalLoop level =- fmap- (: mempty)- . \case- NormalLoop v ->- ("Infinite recursion during normalization forcing " <>) <$> renderValue level "" "" v+renderNormalLoop _level (NormalLoop v) =+ one . ("Infinite recursion during normalization forcing " <>) <$> dumbRenderValue v
src/Nix/Scope.hs view
@@ -1,26 +1,29 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language FunctionalDependencies #-}+{-# language GeneralizedNewtypeDeriving #-} module Nix.Scope where import qualified Data.HashMap.Lazy as M import qualified Text.Show import Lens.Family2-import Nix.Utils+import Nix.Expr.Types -newtype Scope a = Scope { getScope :: AttrSet a }- deriving (Functor, Foldable, Traversable, Eq)+-- 2021-07-19: NOTE: Scopes can gain from sequentiality, HashMap (aka AttrSet) may not be proper to it.+newtype Scope a = Scope (AttrSet a)+ deriving+ ( Eq, Ord, Generic+ , Typeable, NFData+ , Read, Hashable+ , Semigroup, Monoid+ , Functor, Foldable, Traversable+ ) 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 :: VarName -> [Scope a] -> Maybe a scopeLookup key = foldr go Nothing where go@@ -45,14 +48,14 @@ instance Monoid (Scopes m a) where mempty = emptyScopes -emptyScopes :: forall m a . Scopes m a+emptyScopes :: Scopes m a emptyScopes = Scopes mempty mempty 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)+ lookupVar :: VarName -> m (Maybe a) currentScopesReader :: forall m a e@@ -73,19 +76,19 @@ pushScope :: Scoped a m- => AttrSet a+ => Scope a -> m r -> m r-pushScope s = pushScopes $ Scopes [Scope s] mempty+pushScope scope = pushScopes $ Scopes (one scope) mempty pushWeakScope :: ( Functor m , Scoped a m )- => m (AttrSet a)+ => m (Scope a) -> m r -> m r-pushWeakScope s = pushScopes $ Scopes mempty [Scope <$> s]+pushWeakScope scope = pushScopes $ Scopes mempty $ one scope pushScopesReader :: ( MonadReader e m@@ -101,7 +104,7 @@ . ( MonadReader e m , Has e (Scopes m a) )- => Text+ => VarName -> m (Maybe a) lookupVarReader k = do@@ -112,9 +115,9 @@ ws <- asks $ dynamicScopes . view hasLens foldr- (\ x rest ->+ (\ weakscope rest -> do- mres' <- M.lookup k . getScope <$> x+ mres' <- M.lookup k . coerce @(Scope a) <$> weakscope maybe rest@@ -132,4 +135,4 @@ => Scopes m a -> m r -> m r-withScopes scope = clearScopes . pushScopes scope+withScopes scopes = clearScopes . pushScopes scopes
src/Nix/Standard.hs view
@@ -1,15 +1,13 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language TypeFamilies #-}+{-# language CPP #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language UndecidableInstances #-} -{-# OPTIONS_GHC -Wno-orphans #-}+{-# options_ghc -Wno-orphans #-} module Nix.Standard where -import Prelude hiding ( force ) import Control.Comonad ( Comonad ) import Control.Comonad.Env ( ComonadEnv ) import Control.Monad.Catch ( MonadThrow@@ -19,7 +17,7 @@ #if !MIN_VERSION_base(4,13,0) import Control.Monad.Fail ( MonadFail ) #endif-import Control.Monad.Free ( Free(Pure, Free) )+import Control.Monad.Free ( Free(Free) ) import Control.Monad.Reader ( MonadFix ) import Control.Monad.Ref ( MonadRef(newRef) , MonadAtomicRef@@ -39,7 +37,6 @@ import Nix.Scope import Nix.Thunk import Nix.Thunk.Basic-import Nix.Utils ( free ) import Nix.Utils.Fix1 ( Fix1T(Fix1T) ) import Nix.Value import Nix.Value.Monad@@ -47,7 +44,7 @@ newtype StdCited m a = StdCited- { _stdCited :: Cited (StdThunk m) (StdCited m) m a }+ (Cited (StdThunk m) (StdCited m) m a) deriving ( Generic , Typeable@@ -59,13 +56,18 @@ , ComonadEnv [Provenance m (StdValue m)] ) -newtype StdThunk (m :: Type -> Type) =+newtype StdThunk m = StdThunk- { _stdThunk :: StdCited m (NThunkF m (StdValue m)) }+ (StdCited m (NThunkF m (StdValue m))) type StdValue' m = NValue' (StdThunk m) (StdCited m) m (StdValue m) type StdValue m = NValue (StdThunk m) (StdCited m) m +-- | Type alias:+--+-- > Cited (StdThunk m) (StdCited m) m (NThunkF m (StdValue m))+type CitedStdThunk m = Cited (StdThunk m) (StdCited m) m (NThunkF m (StdValue m))+ instance Show (StdThunk m) where show _ = toString thunkStubText @@ -100,13 +102,13 @@ , Typeable m , Scoped (StdValue m) m , MonadReader (Context m (StdValue m)) m- , MonadState (HashMap FilePath NExprLoc, HashMap Text Text) m+ , MonadState (HashMap Path NExprLoc, HashMap Text Text) m , MonadDataErrorContext (StdThunk m) (StdCited m) m , MonadThunk (StdThunk m) m (StdValue m) , MonadValue (StdValue m) m ) => MonadEffects (StdThunk m) (StdCited m) m where- makeAbsolutePath = defaultMakeAbsolutePath+ toAbsolutePath = defaultToAbsolutePath findEnvPath = defaultFindEnvPath findPath = defaultFindPath importPath = defaultImportPath@@ -114,6 +116,10 @@ derivationStrict = defaultDerivationStrict traceEffect = defaultTraceEffect +-- 2021-07-24:+-- This instance currently is to satisfy @MonadThunk@ requirements for @normalForm@ function.+-- As it is seen from the instance - it does superficial type class jump.+-- It is just a type boundary for thunking. instance ( Typeable m , MonadThunkId m@@ -126,34 +132,39 @@ thunkId :: StdThunk m -> ThunkId m- thunkId = thunkId . _stdCited . _stdThunk+ thunkId = thunkId @(CitedStdThunk m) . coerce {-# inline thunkId #-} thunk :: m (StdValue m) -> m (StdThunk m)- thunk = fmap (StdThunk . StdCited) . thunk+ thunk = fmap coerce . thunk @(CitedStdThunk m)+ {-# inline thunk #-} query :: m (StdValue m) -> StdThunk m -> m (StdValue m)- query b = query b . _stdCited . _stdThunk+ query b = query @(CitedStdThunk m) b . coerce+ {-# inline query #-} force :: StdThunk m -> m (StdValue m)- force = force . _stdCited . _stdThunk+ force = force @(CitedStdThunk m) . coerce+ {-# inline force #-} forceEff :: StdThunk m -> m (StdValue m)- forceEff = forceEff . _stdCited . _stdThunk+ forceEff = forceEff @(CitedStdThunk m) . coerce+ {-# inline forceEff #-} further :: StdThunk m -> m (StdThunk m)- further = fmap (StdThunk . StdCited) . further . _stdCited . _stdThunk+ further = fmap coerce . further @(CitedStdThunk m) . coerce+ {-# inline further #-} -- * @instance MonadThunkF@ (Kleisli functor HOFs)@@ -175,7 +186,7 @@ -> m r -> StdThunk m -> m r- queryF k b = queryF k b . _stdCited . _stdThunk+ queryF k b = queryF @(CitedStdThunk m) k b . coerce forceF :: ( StdValue m@@ -183,7 +194,7 @@ ) -> StdThunk m -> m r- forceF k = forceF k . _stdCited . _stdThunk+ forceF k = forceF @(CitedStdThunk m) k . coerce forceEffF :: ( StdValue m@@ -191,7 +202,7 @@ ) -> StdThunk m -> m r- forceEffF k = forceEffF k . _stdCited . _stdThunk+ forceEffF k = forceEffF @(CitedStdThunk m) k . coerce furtherF :: ( m (StdValue m)@@ -199,7 +210,7 @@ ) -> StdThunk m -> m (StdThunk m)- furtherF k = fmap (StdThunk . StdCited) . furtherF k . _stdCited . _stdThunk+ furtherF k = fmap coerce . furtherF @(CitedStdThunk m) k . coerce -- * @instance MonadValue (StdValue m) m@@@ -216,22 +227,29 @@ defer :: m (StdValue m) -> m (StdValue m)- defer = fmap pure . thunk+ defer = fmap (pure . coerce) . thunk @(CitedStdThunk m) demand :: StdValue m -> m (StdValue m)- demand v =- free- (demand <=< force)- (const $ pure v)- v+ demand = go -- lock to ensure no type class jumps.+ where+ go :: StdValue m -> m (StdValue m)+ go =+ free+ (go <=< force @(CitedStdThunk m) . coerce)+ (pure . Free) inform :: StdValue m -> m (StdValue m)- inform (Pure t) = Pure <$> further t- inform (Free v) = Free <$> bindNValue' id inform v+ inform = go -- lock to ensure no type class jumps.+ where+ go :: StdValue m -> m (StdValue m)+ go =+ free+ ((pure . coerce <$>) . (further @(CitedStdThunk m) . coerce))+ ((Free <$>) . bindNValue' id go) -- * @instance MonadValueF (StdValue m) m@@@ -271,8 +289,12 @@ -- withFrame Debug (ForcingThunk @t @f @m) . withFrame Debug frame newtype StandardTF r m a- = StandardTF (ReaderT (Context r (StdValue r))- (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m) a)+ = StandardTF+ (ReaderT+ (Context r (StdValue r))+ (StateT (HashMap Path NExprLoc, HashMap Text Text) m)+ a+ ) deriving ( Functor , Applicative@@ -286,7 +308,7 @@ , MonadThrow , MonadMask , MonadReader (Context r (StdValue r))- , MonadState (HashMap FilePath NExprLoc, HashMap Text Text)+ , MonadState (HashMap Path NExprLoc, HashMap Text Text) ) instance MonadTrans (StandardTF r) where@@ -314,27 +336,28 @@ instance MonadTrans (Fix1T StandardTF) where lift = Fix1T . lift+ {-# inline lift #-} instance MonadThunkId m- => MonadThunkId (Fix1T StandardTF m) where+ => MonadThunkId (StandardT m) where - type ThunkId (Fix1T StandardTF m) = ThunkId m+ type ThunkId (StandardT m) = ThunkId m mkStandardT :: ReaderT (Context (StandardT m) (StdValue (StandardT m)))- (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m)+ (StateT (HashMap Path NExprLoc, HashMap Text Text) m) a -> StandardT m a-mkStandardT = Fix1T . StandardTF+mkStandardT = coerce runStandardT :: StandardT m a -> ReaderT (Context (StandardT m) (StdValue (StandardT m)))- (StateT (HashMap FilePath NExprLoc, HashMap Text Text) m)+ (StateT (HashMap Path NExprLoc, HashMap Text Text) m) a-runStandardT (Fix1T (StandardTF m)) = m+runStandardT = coerce runWithBasicEffects :: (MonadIO m, MonadAtomicRef m)
src/Nix/String.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# language GeneralizedNewtypeDeriving #-} module Nix.String ( NixString , getContext- , makeNixString+ , mkNixString , StringContext(..) , ContextFlavor(..) , NixLikeContext(..)@@ -14,8 +14,8 @@ , intercalateNixString , getStringNoContext , stringIgnoreContext- , makeNixStringWithoutContext- , makeNixStringWithSingletonContext+ , mkNixStringWithoutContext+ , mkNixStringWithSingletonContext , modifyNixContents , WithStringContext , WithStringContextT(..)@@ -32,21 +32,24 @@ -import Nix.Utils import Control.Monad.Writer ( WriterT(..), MonadWriter(tell)) import qualified Data.HashMap.Lazy as M import qualified Data.HashSet as S import qualified Data.Text as Text+import Nix.Expr.Types ( VarName(..)+ , AttrSet+ ) -- * Types -- ** Context +-- 2021-07-18: NOTE: it should be ContextFlavor -> Varname. -- | A Nix 'StringContext' ... data StringContext = StringContext- { scPath :: !Text+ { scPath :: !VarName , scFlavor :: !ContextFlavor } deriving (Eq, Ord, Show, Generic)@@ -101,6 +104,7 @@ -- ** NixString +-- 2021-07-18: NOTE: It should be Context -> Contents. data NixString = NixString { nsContents :: !Text@@ -122,17 +126,17 @@ -- ** Makers -- | Constructs NixString without a context-makeNixStringWithoutContext :: Text -> NixString-makeNixStringWithoutContext = (`NixString` mempty)+mkNixStringWithoutContext :: Text -> NixString+mkNixStringWithoutContext = (`NixString` mempty) -- | Create NixString using a singleton context-makeNixStringWithSingletonContext- :: Text -> StringContext -> NixString-makeNixStringWithSingletonContext s c = NixString s $ one c+mkNixStringWithSingletonContext+ :: VarName -> StringContext -> NixString+mkNixStringWithSingletonContext s c = NixString (coerce @VarName @Text s) $ one c -- | Create NixString from a Text and context-makeNixString :: Text -> S.HashSet StringContext -> NixString-makeNixString = NixString+mkNixString :: Text -> S.HashSet StringContext -> NixString+mkNixString = NixString -- ** Checkers@@ -172,7 +176,7 @@ -- this really should be 2 args, then with @toStringContexts path@ laziness it would tail recurse. -- for now tuple dissected internaly with laziness preservation.-toStringContexts :: (Text, NixLikeContextValue) -> [StringContext]+toStringContexts :: (VarName, NixLikeContextValue) -> [StringContext] toStringContexts ~(path, nlcv) = go nlcv where@@ -190,13 +194,13 @@ mkCtxFor = StringContext path mkLstCtxFor t c = mkCtxFor t : go c -toNixLikeContextValue :: StringContext -> (Text, NixLikeContextValue)+toNixLikeContextValue :: StringContext -> (VarName, NixLikeContextValue) toNixLikeContextValue sc = ( scPath sc , case scFlavor sc of DirectPath -> NixLikeContextValue True False mempty AllOutputs -> NixLikeContextValue False True mempty- DerivationOutput t -> NixLikeContextValue False False [t]+ DerivationOutput t -> NixLikeContextValue False False $ one t ) toNixLikeContext :: S.HashSet StringContext -> NixLikeContext
src/Nix/String/Coerce.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE CPP #-}+{-# language CPP #-} module Nix.String.Coerce where import Control.Monad.Catch ( MonadThrow )+import GHC.Exception ( ErrorCall(ErrorCall) ) import qualified Data.HashMap.Lazy as M import Nix.Atoms import Nix.Effects@@ -58,11 +59,7 @@ case x' of -- TODO Return a singleton for "" and "1" NVConstant (NBool b) ->- castToNixString $- bool- ""- "1"- b+ castToNixString $ "1" `whenTrue` b NVConstant (NInt n) -> castToNixString $ show n@@ -70,10 +67,10 @@ castToNixString $ show n NVConstant NNull ->- castToNixString ""+ castToNixString mempty -- NVConstant: NAtom (NURI Text) is not matched NVList l ->- nixStringUnwords <$> traverse (go <=< demand) l+ nixStringUnwords <$> traverse go l v -> coerceStringy v coerceStringy x' =@@ -81,11 +78,11 @@ NVStr ns -> pure ns NVPath p -> bool- (castToNixString . toText)+ (castToNixString . fromString . coerce) (fmap storePathToNixString . addPath) (ctsm == CopyToStore) p- v@(NVSet s _) ->+ v@(NVSet _ s) -> maybe (maybe (err v)@@ -106,15 +103,15 @@ v -> err v err v = throwError $ ErrorCall $ "Expected a string, but saw: " <> show v- castToNixString = pure . makeNixStringWithoutContext+ castToNixString = pure . mkNixStringWithoutContext - nixStringUnwords = intercalateNixString $ makeNixStringWithoutContext " "+ nixStringUnwords = intercalateNixString $ mkNixStringWithoutContext " " storePathToNixString :: StorePath -> NixString storePathToNixString sp =- makeNixStringWithSingletonContext+ mkNixStringWithSingletonContext t (StringContext t DirectPath) where- t = toText $ unStorePath sp+ t = fromString $ coerce sp
src/Nix/TH.hs view
@@ -1,92 +1,113 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-}+{-# language QuasiQuotes #-}+{-# language TemplateHaskell #-} -{-# OPTIONS_GHC -Wno-missing-fields #-}+{-# options_ghc -Wno-missing-fields #-}+{-# options_ghc -Wno-name-shadowing #-} module Nix.TH where -import Data.Fix ( Fix(..) )+import Data.Fix ( Fix(unFix) ) import Data.Generics.Aliases ( extQ ) import qualified Data.Set as Set import Language.Haskell.TH import qualified Language.Haskell.TH.Syntax as TH import Language.Haskell.TH.Quote import Nix.Atoms-import Nix.Expr+import Nix.Expr.Types+import Nix.Expr.Types.Annotated import Nix.Parser quoteExprExp :: String -> ExpQ-quoteExprExp s = do- expr <-- either- (fail . show)- pure- (parseNixText $ toText s)- dataToExpQ- (const Nothing `extQ` metaExp (freeVars expr) `extQ` (pure . (TH.lift :: Text -> Q Exp)))- expr+quoteExprExp s =+ do+ expr <- parseExpr $ fromString s+ dataToExpQ+ (extQOnFreeVars metaExp expr `extQ` (pure . (TH.lift :: Text -> Q Exp)))+ expr quoteExprPat :: String -> PatQ-quoteExprPat s = do- expr <-- either- (fail . show)- pure- (parseNixText $ toText s)- dataToPatQ- (const Nothing `extQ` metaPat (freeVars expr))- expr+quoteExprPat s =+ do+ expr <- parseExpr $ fromString s+ dataToPatQ+ (extQOnFreeVars metaPat expr)+ expr +-- | Helper function.+extQOnFreeVars+ :: ( Typeable b+ , Typeable loc+ )+ => ( Set VarName+ -> loc+ -> Maybe q+ )+ -> NExpr+ -> b+ -> Maybe q+extQOnFreeVars f = extQ (const Nothing) . f . freeVars++parseExpr :: (MonadFail m) => Text -> m NExpr+parseExpr =+ either+ (fail . show)+ pure+ . parseNixText+ freeVars :: NExpr -> Set VarName freeVars e = case unFix e of (NConstant _ ) -> mempty (NStr string ) -> mapFreeVars string (NSym var ) -> one var (NList list ) -> mapFreeVars list- (NSet NNonRecursive bindings) -> bindFreeVars bindings- (NSet NRecursive bindings) -> Set.difference (bindFreeVars bindings) (bindDefs bindings)+ (NSet NonRecursive bindings) -> bindFreeVars bindings+ (NSet Recursive bindings) -> diffBetween bindFreeVars bindDefs bindings (NLiteralPath _ ) -> mempty (NEnvPath _ ) -> mempty (NUnary _ expr ) -> freeVars expr- (NBinary _ left right ) -> ((<>) `on` freeVars) left right- (NSelect expr path orExpr) ->+ (NBinary _ left right ) -> collectFreeVars left right+ (NSelect orExpr expr path) -> Set.unions [ freeVars expr , pathFree path- , maybe mempty freeVars orExpr+ , freeVars `whenJust` orExpr ] (NHasAttr expr path) -> freeVars expr <> pathFree path (NAbs (Param varname) expr) -> Set.delete varname (freeVars expr)- (NAbs (ParamSet set _ varname) expr) ->+ (NAbs (ParamSet varname _ pset) expr) -> -- Include all free variables from the expression and the default arguments freeVars expr <> -- But remove the argument name if existing, and all arguments in the parameter set Set.difference- (Set.unions $ freeVars <$> mapMaybe snd set)+ (Set.unions $ freeVars <$> mapMaybe snd pset) (Set.difference- (maybe mempty one varname)- (Set.fromList $ fst <$> set)+ (one `whenJust` varname)+ (Set.fromList $ fst <$> pset) ) (NLet bindings expr ) -> freeVars expr <>- Set.difference- (bindFreeVars bindings)- (bindDefs bindings)+ diffBetween bindFreeVars bindDefs bindings (NIf cond th el ) -> Set.unions $ freeVars <$> [cond, th, el] -- Evaluation is needed to find out whether x is a "real" free variable in `with y; x`, we just include it -- This also makes sense because its value can be overridden by `x: with y; x`- (NWith set expr ) -> ((<>) `on` freeVars) set expr- (NAssert assertion expr ) -> ((<>) `on` freeVars) assertion expr+ (NWith set expr ) -> collectFreeVars set expr+ (NAssert assertion expr ) -> collectFreeVars assertion expr (NSynHole _ ) -> mempty where + diffBetween :: (a -> Set VarName) -> (a -> Set VarName) -> a -> Set VarName+ diffBetween g f b = Set.difference (g b) (f b)++ collectFreeVars :: NExpr -> NExpr -> Set VarName+ collectFreeVars = (<>) `on` freeVars+ bindDefs :: Foldable t => t (Binding NExpr) -> Set VarName bindDefs = foldMap bind1Def where bind1Def :: Binding r -> Set VarName bind1Def (Inherit Nothing _ _) = mempty- bind1Def (Inherit (Just _ ) keys _) = Set.fromList $ mapMaybe staticKey keys+ bind1Def (Inherit (Just _ ) keys _) = Set.fromList keys bind1Def (NamedVar (StaticKey varname :| _) _ _) = one varname bind1Def (NamedVar (DynamicKey _ :| _) _ _) = mempty @@ -94,14 +115,10 @@ bindFreeVars = foldMap bind1Free where bind1Free :: Binding NExpr -> Set VarName- bind1Free (Inherit Nothing keys _) = Set.fromList $ mapMaybe staticKey keys+ bind1Free (Inherit Nothing keys _) = Set.fromList keys bind1Free (Inherit (Just scope) _ _) = freeVars scope bind1Free (NamedVar path expr _) = pathFree path <> freeVars expr - staticKey :: NKeyName r -> Maybe VarName- staticKey (StaticKey varname) = pure varname- staticKey (DynamicKey _ ) = mempty- pathFree :: NAttrPath NExpr -> Set VarName pathFree = foldMap mapFreeVars @@ -116,24 +133,24 @@ toExpr = id instance ToExpr VarName where- toExpr = Fix . NSym_ nullSpan+ toExpr = NSymAnn nullSpan instance ToExpr Int where- toExpr = Fix . NConstant_ nullSpan . NInt . fromIntegral+ toExpr = NConstantAnn nullSpan . NInt . fromIntegral instance ToExpr Integer where- toExpr = Fix . NConstant_ nullSpan . NInt+ toExpr = NConstantAnn nullSpan . NInt instance ToExpr Float where- toExpr = Fix . NConstant_ nullSpan . NFloat+ toExpr = NConstantAnn nullSpan . NFloat metaExp :: Set VarName -> NExprLoc -> Maybe ExpQ-metaExp fvs (Fix (NSym_ _ x)) | x `Set.member` fvs =+metaExp fvs (NSymAnn _ x) | x `Set.member` fvs = pure [| toExpr $(varE (mkName $ toString x)) |] metaExp _ _ = Nothing metaPat :: Set VarName -> NExprLoc -> Maybe PatQ-metaPat fvs (Fix (NSym_ _ x)) | x `Set.member` fvs =+metaPat fvs (NSymAnn _ x) | x `Set.member` fvs = pure $ varP $ mkName $ toString x metaPat _ _ = Nothing
src/Nix/Thunk.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE TypeFamilies #-}+{-# language DefaultSignatures #-}+{-# language FunctionalDependencies #-}+{-# language TypeFamilies #-} module Nix.Thunk where
src/Nix/Thunk/Basic.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}+{-# language ConstraintKinds #-}+{-# language UndecidableInstances #-}+{-# options_ghc -Wno-unused-do-bind #-} module Nix.Thunk.Basic@@ -11,8 +10,6 @@ , MonadBasicThunk ) where -import Prelude hiding ( force )-import Relude.Extra ( dup ) import Control.Monad.Ref ( MonadRef(Ref, newRef, readRef, writeRef) , MonadAtomicRef(atomicModifyRef) )
src/Nix/Type/Assumption.hs view
@@ -1,6 +1,6 @@ -- | Basing on the Nix (Hindley–Milner) type system (that provides decidable type inference): -- gathering assumptions (inference evidence) about polymorphic types.-{-# LANGUAGE TypeFamilies #-}+{-# language TypeFamilies #-} module Nix.Type.Assumption ( Assumption(..) , empty@@ -9,7 +9,6 @@ , extend , keys , merge- , mergeAssumptions , singleton ) where@@ -18,9 +17,10 @@ , empty ) +import Nix.Expr.Types import Nix.Type.Type -newtype Assumption = Assumption { assumptions :: [(Name, Type)] }+newtype Assumption = Assumption [(VarName, Type)] deriving (Eq, Show) -- We pretend that Assumptions can be inconsistent (nonunique keys),@@ -33,40 +33,40 @@ mempty = empty instance One Assumption where- type OneItem Assumption = (Name, Type)- one (x, y) = Assumption [(x, y)]+ type OneItem Assumption = (VarName, Type)+ one vt = Assumption $ one vt empty :: Assumption empty = Assumption mempty -extend :: Assumption -> (Name, Type) -> Assumption-extend (Assumption a) (x, s) =- Assumption $- (x, s) : a+extend :: Assumption -> (VarName, Type) -> Assumption+extend a vt =+ one (coerce vt) <> a -remove :: Assumption -> Name -> Assumption-remove (Assumption a) var =- Assumption $+remove :: Assumption -> VarName -> Assumption+remove a var =+ coerce+ rmVar+ a+ where+ rmVar :: [(VarName, Type)] -> [(VarName, Type)]+ rmVar = filter- (\(n, _) -> n /= var)- a+ ((/=) var . fst) -lookup :: Name -> Assumption -> [Type]-lookup key (Assumption a) =+lookup :: VarName -> Assumption -> [Type]+lookup key a = snd <$> filter- (\(n, _) -> n == key)- a+ ((==) key . fst)+ (coerce a) merge :: Assumption -> Assumption -> Assumption-merge (Assumption a) (Assumption b) =- Assumption $ a <> b--mergeAssumptions :: [Assumption] -> Assumption-mergeAssumptions = foldl' (<>) mempty+merge =+ coerce ((<>) @[(VarName, Type)]) -singleton :: Name -> Type -> Assumption-singleton x y = Assumption [(x, y)]+singleton :: VarName -> Type -> Assumption+singleton = curry one -keys :: Assumption -> [Name]+keys :: Assumption -> [VarName] keys (Assumption a) = fst <$> a
src/Nix/Type/Env.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeFamilies #-}+{-# language TypeFamilies #-} module Nix.Type.Env ( Env(..) , empty@@ -20,6 +20,7 @@ , fromList ) +import Nix.Expr.Types import Nix.Type.Type import qualified Data.Map as Map@@ -27,7 +28,7 @@ -- * Typing Environment -newtype Env = TypeEnv (Map.Map Name [Scheme])+newtype Env = TypeEnv (Map VarName [Scheme]) deriving (Eq, Show) instance Semigroup Env where@@ -39,42 +40,42 @@ mempty = empty instance One Env where- type OneItem Env = (Name, Scheme)- one = uncurry singleton+ type OneItem Env = (VarName, Scheme)+ one (x, y) = TypeEnv $ one (x, one y) empty :: Env empty = TypeEnv mempty -extend :: Env -> (Name, [Scheme]) -> Env-extend env (x, s) = TypeEnv $ Map.insert x s $ coerce env+extend :: Env -> (VarName, [Scheme]) -> Env+extend env (x, s) = coerce (Map.insert x s) env -remove :: Env -> Name -> Env-remove (TypeEnv env) var = TypeEnv $ Map.delete var env+remove :: Env -> VarName -> Env+remove env var = TypeEnv $ Map.delete var $ coerce env -extends :: Env -> [(Name, [Scheme])] -> Env-extends env xs = TypeEnv $ Map.fromList xs <> coerce env+extends :: Env -> [(VarName, [Scheme])] -> Env+extends env xs = fromList xs <> coerce env -lookup :: Name -> Env -> Maybe [Scheme]-lookup key (TypeEnv tys) = Map.lookup key tys+lookup :: VarName -> Env -> Maybe [Scheme]+lookup key tys = Map.lookup key $ coerce tys merge :: Env -> Env -> Env-merge (TypeEnv a) (TypeEnv b) = TypeEnv $ a <> b+merge a b = TypeEnv $ coerce a <> coerce b mergeRight :: Env -> Env -> Env-mergeRight (TypeEnv a) (TypeEnv b) = TypeEnv $ b <> a+mergeRight = flip merge mergeEnvs :: [Env] -> Env mergeEnvs = foldl' (<>) mempty -singleton :: Name -> Scheme -> Env-singleton x y = TypeEnv $ one (x, [y])+singleton :: VarName -> Scheme -> Env+singleton = curry one -keys :: Env -> [Name]+keys :: Env -> [VarName] keys (TypeEnv env) = Map.keys env -fromList :: [(Name, [Scheme])] -> Env-fromList xs = TypeEnv $ Map.fromList xs+fromList :: [(VarName, [Scheme])] -> Env+fromList xs = coerce $ Map.fromList xs -toList :: Env -> [(Name, [Scheme])]+toList :: Env -> [(VarName, [Scheme])] toList (TypeEnv env) = Map.toList env
src/Nix/Type/Infer.hs view
@@ -1,14 +1,13 @@-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}+{-# language MultiWayIf #-}+{-# language CPP #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language ExistentialQuantification #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language RankNTypes #-}+{-# language TypeFamilies #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-}+{-# options_ghc -Wno-name-shadowing #-} module Nix.Type.Infer ( Constraint(..)@@ -22,12 +21,11 @@ import Control.Monad.Catch ( MonadThrow(..) , MonadCatch(..) )-import Control.Monad.Except ( MonadError(..) )+import Control.Monad.Except ( MonadError(throwError,catchError) ) import Prelude hiding ( Type , TVar , Constraint )-import Nix.Utils import Control.Monad.Logic hiding ( fail ) import Control.Monad.Reader ( MonadFix ) import Control.Monad.Ref ( MonadAtomicRef(..)@@ -37,7 +35,6 @@ , runST ) import Data.Fix ( foldFix )-import Data.Foldable ( foldrM ) import qualified Data.HashMap.Lazy as M import Data.List ( delete , intersect@@ -56,13 +53,10 @@ , evalWithAttrSet ) import Nix.Expr.Types-import Nix.Expr.Types.Annotated import Nix.Fresh import Nix.String import Nix.Scope-import Nix.Type.Assumption hiding ( assumptions- , extend- )+import Nix.Type.Assumption hiding ( extend ) import qualified Nix.Type.Assumption as Assumption ( remove , lookup@@ -80,14 +74,14 @@ ord = zip (ordNub $ fv body)- (TV . toText <$> letters)+ (TV . fromString <$> letters) - fv (TVar a ) = [a]- fv (a :~> b ) = fv a <> fv b+ fv (TVar a ) = one a+ fv (a :~> b ) = on (<>) fv a b fv (TCon _ ) = mempty- fv (TSet _ a) = concatMap fv $ M.elems a- fv (TList a ) = concatMap fv a- fv (TMany ts) = concatMap fv ts+ fv (TSet _ a) = foldMap fv $ M.elems a+ fv (TList a ) = foldMap fv a+ fv (TMany ts) = foldMap fv ts normtype (a :~> b ) = normtype a :~> normtype b normtype (TCon a ) = TCon a@@ -109,6 +103,7 @@ closeOver :: Type -> Scheme closeOver = normalizeScheme . generalize mempty +-- When `[]` becomes `NonEmpty` - function becomes just `all` -- | Check if all elements are of the same type. allSameType :: [Type] -> Bool allSameType = allSame@@ -122,7 +117,7 @@ data TypeError = UnificationFail Type Type | InfiniteType TVar Type- | UnboundVariables [Text]+ | UnboundVariables [VarName] | Ambigious [Constraint] | UnificationMismatch [Type] [Type] deriving (Eq, Show, Ord)@@ -135,7 +130,7 @@ | forall s. Exception s => EvaluationError s typeError :: MonadError InferError m => TypeError -> m ()-typeError err = throwError $ TypeInferenceErrors [err]+typeError err = throwError $ TypeInferenceErrors $ one err -- ** Instances @@ -143,20 +138,27 @@ instance Exception InferError instance Semigroup InferError where- x <> _ = x+ (<>) = const instance Monoid InferError where mempty = TypeInferenceAborted- mappend = (<>) -- * @InferState@: inference state --- | Inference state-newtype InferState = InferState { count :: Int }+-- | Inference state (stage).+newtype InferState = InferState Int+ deriving+ (Eq, Num, Enum, Ord) +instance Semigroup InferState where+ (<>) = (+)++instance Monoid InferState where+ mempty = 0+ -- | Initial inference state initInfer :: InferState-initInfer = InferState { count = 0 }+initInfer = InferState 0 letters :: [String] letters =@@ -170,18 +172,19 @@ freshTVar = do s <- get- put s { count = count s + 1 }- pure $ TV $ toText $ letters !! count s+ put $ succ s+ pure $ TV $ fromString $ letters !! coerce s fresh :: MonadState InferState m => m Type fresh = TVar <$> freshTVar +intoFresh :: (Traversable t, MonadState InferState f) => t a -> f (t Type)+intoFresh =+ traverse (const fresh)+ instantiate :: MonadState InferState m => Scheme -> m Type instantiate (Forall as t) =- do- as' <- traverse (const fresh) as- let s = Subst $ Map.fromList $ zip as as'- pure $ apply s t+ fmap ((`apply` t) . coerce . Map.fromList . zip as) (intoFresh as) -- * @Constraint@ data type @@ -199,9 +202,9 @@ -- | Compose substitutions compose :: Subst -> Subst -> Subst-Subst s1 `compose` Subst s2 =- Subst $- apply (Subst s1) <$>+compose a@(Subst s2) (Subst s1) =+ coerce $ --+ apply a <$> (s2 <> s1) -- * class @Substitutable@@@ -214,15 +217,14 @@ instance Substitutable TVar where apply (Subst s) a = tv where- t = TVar a- (TVar tv) = Map.findWithDefault t a s+ (TVar tv) = Map.findWithDefault (TVar a) a s instance Substitutable Type where apply _ ( TCon a ) = TCon a apply s ( TSet b a ) = TSet b $ apply s <$> a apply s ( TList a ) = TList $ apply s <$> a apply (Subst s) t@(TVar a ) = Map.findWithDefault t a s- apply s ( t1 :~> t2) = apply s t1 :~> apply s t2+ apply s ( t1 :~> t2) = ((:~>) `on` apply s) t1 t2 apply s ( TMany ts ) = TMany $ apply s <$> ts instance Substitutable Scheme where@@ -231,10 +233,7 @@ s' = Subst $ foldr Map.delete s as instance Substitutable Constraint where- apply s (EqConst t1 t2) =- EqConst- (apply s t1)- (apply s t2)+ apply s (EqConst t1 t2) = on EqConst (apply s) t1 t2 apply s (ExpInstConst t sc) = ExpInstConst (apply s t)@@ -252,7 +251,7 @@ apply = Set.map . apply --- * data type @Judgement@+-- * data type @Judgment@ data Judgment s = Judgment@@ -262,16 +261,22 @@ } deriving Show +inferred :: Type -> Judgment s+inferred = Judgment mempty mempty+ -- * @InferT@: inference monad +type InferTInternals s m a =+ ReaderT+ (Set.Set TVar, Scopes (InferT s m) (Judgment s))+ (StateT InferState (ExceptT InferError m))+ a+ -- | Inference monad newtype InferT s m a = InferT { getInfer ::- ReaderT- (Set.Set TVar, Scopes (InferT s m) (Judgment s))- (StateT InferState (ExceptT InferError m))- a+ InferTInternals s m a } deriving ( Functor@@ -286,8 +291,11 @@ , MonadError InferError ) -extendMSet :: Monad m => TVar -> InferT s m a -> InferT s m a-extendMSet x = InferT . local (first $ Set.insert x) . getInfer+extendMSet :: forall s m a . Monad m => TVar -> InferT s m a -> InferT s m a+extendMSet x = coerce putSetElementM+ where+ putSetElementM :: InferTInternals s m a -> InferTInternals s m a+ putSetElementM = local (first . Set.insert $ x) -- ** Instances @@ -335,58 +343,48 @@ instance MonadInfer m => FromValue ( AttrSet (Judgment s)- , AttrSet SourcePos+ , PositionSet ) (InferT s m) (Judgment s) where fromValueMay (Judgment _ _ (TSet _ xs)) = do- let sing _ = Judgment mempty mempty+ let sing = const inferred pure $ pure (M.mapWithKey sing xs, mempty) fromValueMay _ = stub fromValue = pure .- fromMaybe- (mempty, mempty)+ maybeToMonoid <=< fromValueMay -instance MonadInfer m- => ToValue (AttrSet (Judgment s), AttrSet SourcePos)- (InferT s m) (Judgment s) where- toValue (xs, _) =- liftA3- Judgment- (foldrM go mempty xs)- (fun concat typeConstraints)- (fun (TSet True) inferredType )+foldInitializedWith :: (Traversable t, Applicative f) => (t c -> c) -> (b -> c) -> (a -> f b) -> t a -> f c+foldInitializedWith fld getter init =+ -- maybe here is some law?+ fmap fld . traverse (fmap getter . init)++toJudgment :: forall t m s . (Traversable t, Monad m) => (t Type -> Type) -> t (Judgment s) -> InferT s m (Judgment s)+toJudgment c xs =+ liftA3 Judgment+ (foldWith fold assumptions )+ (foldWith fold typeConstraints)+ (foldWith c inferredType ) where- go x rest =- do- x' <- demand x- pure $ assumptions x' <> rest+ foldWith :: ((t a -> a) -> (Judgment s -> a) -> InferT s m a)+ foldWith g f = uncurry (foldInitializedWith g f) tpl - fun :: (AttrSet b -> b1) -> (Judgment s -> b) -> InferT s m b1- fun g f =- g <$> traverse ((f <$>) . demand) xs+ tpl :: (Judgment s -> InferT s m (Judgment s), t (Judgment s))+ tpl = (demand, xs) -instance MonadInfer m => ToValue [Judgment s] (InferT s m) (Judgment s) where- toValue xs =- liftA3- Judgment- (foldrM go mempty xs)- (fun concat typeConstraints)- (fun TList inferredType )- where- go x rest =- do- x' <- demand x- pure $ assumptions x' <> rest+instance MonadInfer m+ => ToValue (AttrSet (Judgment s), PositionSet)+ (InferT s m) (Judgment s) where+ toValue :: (AttrSet (Judgment s), PositionSet) -> InferT s m (Judgment s)+ toValue (xs, _) = toJudgment (TSet Variadic) xs -- why variadic? Probably `Closed` (`mempty`)? - fun :: ([b] -> b1) -> (Judgment s -> b) -> InferT s m b1- fun g f =- g <$> traverse ((f <$>) . demand) xs+instance MonadInfer m => ToValue [Judgment s] (InferT s m) (Judgment s) where+ toValue = toJudgment TList instance MonadInfer m => ToValue Bool (InferT s m) (Judgment s) where- toValue _ = pure $ Judgment mempty mempty typeBool+ toValue _ = pure $ inferred typeBool instance Monad m@@ -424,7 +422,7 @@ -> InferT s m r) -> Judgment s -> InferT s m r- demandF f a = f a+ demandF f = f informF :: ( InferT s m (Judgment s)@@ -455,84 +453,84 @@ f =<< Judgment mempty mempty <$> fresh -} +polymorphicVar :: MonadInfer m => VarName -> InferT s m (Judgment s)+polymorphicVar var =+ fmap+ (join ((`Judgment` mempty) . curry one var))+ fresh++constInfer :: Applicative f => Type -> b -> f (Judgment s)+constInfer x = const $ pure $ inferred x+ instance MonadInfer m => MonadEval (Judgment s) (InferT s m) where- freeVariable var = do- tv <- fresh- pure $ Judgment (one (var, tv)) mempty tv+ freeVariable = polymorphicVar - synHole var = do- tv <- fresh- pure $ Judgment (one (var, tv)) mempty tv+ synHole = polymorphicVar -- If we fail to look up an attribute, we just don't know the type.- attrMissing _ _ = Judgment mempty mempty <$> fresh+ attrMissing _ _ = inferred <$> fresh evaledSym _ = pure evalCurPos = pure $- Judgment- mempty- mempty- (TSet False $+ inferred $+ TSet mempty $ M.fromList [ ("file", typePath) , ("line", typeInt ) , ("col" , typeInt ) ]- ) - evalConstant c = pure $ Judgment mempty mempty $ go c+ evalConstant c = pure $ inferred $ fun c where- go = \case+ fun = \case NURI _ -> typeString NInt _ -> typeInt NFloat _ -> typeFloat NBool _ -> typeBool NNull -> typeNull - evalString = const $ pure $ Judgment mempty mempty typeString- evalLiteralPath = const $ pure $ Judgment mempty mempty typePath- evalEnvPath = const $ pure $ Judgment mempty mempty typePath+ evalString = constInfer typeString+ evalLiteralPath = constInfer typePath+ evalEnvPath = constInfer typePath - evalUnary op (Judgment as1 cs1 t1) = do- tv <- fresh- pure $- Judgment- as1- (cs1 <> unops (t1 :~> tv) op)- tv+ evalUnary op (Judgment as1 cs1 t1) =+ fmap+ (join+ $ Judgment+ as1+ . (cs1 <>) . (`unops` op) . (t1 :~>)+ )+ fresh evalBinary op (Judgment as1 cs1 t1) e2 = do Judgment as2 cs2 t2 <- e2- tv <- fresh- pure $- Judgment- (as1 <> as2)- ( cs1 <>- cs2 <>- binops- (t1 :~> t2 :~> tv)- op- )- tv+ fmap+ (join+ $ Judgment+ (as1 <> as2)+ . (\ cs3 -> cs1 <> cs2 <> cs3) . (`binops` op) . (\ t3 -> t1 :~> t2 :~> t3)+ )+ fresh evalWith = Eval.evalWithAttrSet evalIf (Judgment as1 cs1 t1) t f = do Judgment as2 cs2 t2 <- t Judgment as3 cs3 t3 <- f- pure $ Judgment- (as1 <> as2 <> as3)- (cs1 <> cs2 <> cs3 <> [EqConst t1 typeBool, EqConst t2 t3])- t2+ pure $+ Judgment+ (as1 <> as2 <> as3)+ (cs1 <> cs2 <> cs3 <> [EqConst t1 typeBool, EqConst t2 t3])+ t2 evalAssert (Judgment as1 cs1 t1) body = do Judgment as2 cs2 t2 <- body pure $ Judgment (as1 <> as2)- (cs1 <> cs2 <> [EqConst t1 typeBool])+ (cs1 <> cs2 <> one (EqConst t1 typeBool)) t2 evalApp (Judgment as1 cs1 t1) e2 = do@@ -541,7 +539,7 @@ pure $ Judgment (as1 <> as2)- (cs1 <> cs2 <> [EqConst t1 (t2 :~> tv)])+ (cs1 <> cs2 <> one (EqConst t1 (t2 :~> tv))) tv evalAbs (Param x) k = do@@ -565,27 +563,19 @@ (cs <> [ EqConst t' tv | t' <- Assumption.lookup x as ]) (tv :~> t) - evalAbs (ParamSet ps variadic _mname) k = do- js <-- concat <$>- traverse- (\(name, _) ->- do- tv <- fresh- pure [(name, tv)]- )- ps+ evalAbs (ParamSet _mname variadic pset) k = do+ js <- foldInitializedWith fold one intoFresh pset let f (as1, t1) (k, t) = (as1 <> one (k, t), M.insert k t t1)- (env, tys) = foldl' f (mempty, mempty) js- arg = pure $ Judgment env mempty $ TSet True tys+ (env, tys) = foldl' f mempty js+ arg = pure $ Judgment env mempty $ TSet Variadic tys call = k arg $ \args b -> (args, ) <$> b names = fst <$> js (args, Judgment as cs t) <- foldr (\(_, TVar a) -> extendMSet a) call js - ty <- TSet variadic <$> traverse (inferredType <$>) args+ ty <- foldInitializedWith (TSet variadic) inferredType id args pure $ Judgment@@ -651,7 +641,7 @@ runInfer' = runExceptT . (`evalStateT` initInfer)- . (`runReaderT` (mempty, mempty))+ . (`runReaderT` mempty) . getInfer runInfer :: (forall s . InferT s (FreshIdT Int (ST s)) a) -> Either InferError a@@ -667,6 +657,7 @@ do Judgment as cs t <- infer ex let+ unbounds :: Set VarName unbounds = (Set.difference `on` Set.fromList) (Assumption.keys as )@@ -683,30 +674,32 @@ , s <- ss , t <- Assumption.lookup x as ]- eres = (`evalState` inferState) $ runSolver $- do- subst <- solve $ cs <> cs'- pure (subst, subst `apply` t)+ evalResult =+ (`evalState` inferState) . runSolver $ second (`apply` t) . join (,) <$> solve (cs <> cs') either (throwError . TypeInferenceErrors) pure- eres+ evalResult -- | Solve for the toplevel type of an expression in a given environment inferExpr :: Env -> NExpr -> Either InferError [Scheme] inferExpr env ex =- (\ (subst, ty) -> closeOver $ subst `apply` ty) <<$>>- runInfer (inferType env ex)+ closeOver . uncurry apply <<$>> runInfer (inferType env ex) unops :: Type -> NUnaryOp -> [Constraint] unops u1 op =- [ EqConst u1- (case op of- NNot -> typeFun [typeBool , typeBool ]- NNeg -> TMany [typeFun [typeInt, typeInt], typeFun [typeFloat, typeFloat]]- )- ]+ one $+ EqConst u1 $+ case op of+ NNot -> mkUnaryConstr typeBool+ NNeg -> TMany $ mkUnaryConstr <$> [typeInt, typeFloat]+ where+ mkUnaryConstr :: Type -> Type+ mkUnaryConstr = typeFun . mk2same+ where+ mk2same :: a -> NonEmpty a+ mk2same a = a :| one a binops :: Type -> NBinaryOp -> [Constraint] binops u1 op =@@ -724,47 +717,55 @@ where - gate = eqCnst [typeBool, typeBool, typeBool]- concatenation = eqCnst [typeList, typeList, typeList]+ mk3 :: a -> a -> a -> NonEmpty a+ mk3 a b c = a :| [b, c] - eqCnst l = [EqConst u1 $ typeFun l]+ mk3same :: a -> NonEmpty a+ mk3same a = a :| [a, a] + allConst :: Type -> [Constraint]+ allConst = one . EqConst u1 . typeFun . mk3same++ gate = allConst typeBool+ concatenation = allConst typeList++ eqConstrMtx :: [NonEmpty Type] -> [Constraint]+ eqConstrMtx = one . EqConst u1 . TMany . fmap typeFun+ inequality =- eqCnstMtx- [ [typeInt , typeInt , typeBool]- , [typeFloat, typeFloat, typeBool]- , [typeInt , typeFloat, typeBool]- , [typeFloat, typeInt , typeBool]+ eqConstrMtx+ [ mk3 typeInt typeInt typeBool+ , mk3 typeFloat typeFloat typeBool+ , mk3 typeInt typeFloat typeBool+ , mk3 typeFloat typeInt typeBool ] arithmetic =- eqCnstMtx- [ [typeInt , typeInt , typeInt ]- , [typeFloat, typeFloat, typeFloat]- , [typeInt , typeFloat, typeFloat]- , [typeFloat, typeInt , typeFloat]+ eqConstrMtx+ [ mk3same typeInt+ , mk3same typeFloat+ , mk3 typeInt typeFloat typeFloat+ , mk3 typeFloat typeInt typeFloat ] rUnion =- eqCnstMtx- [ [typeSet , typeSet , typeSet]- , [typeSet , typeNull, typeSet]- , [typeNull, typeSet , typeSet]+ eqConstrMtx+ [ mk3same typeSet+ , mk3 typeSet typeNull typeSet+ , mk3 typeNull typeSet typeSet ] addition =- eqCnstMtx- [ [typeInt , typeInt , typeInt ]- , [typeFloat , typeFloat , typeFloat ]- , [typeInt , typeFloat , typeFloat ]- , [typeFloat , typeInt , typeFloat ]- , [typeString, typeString, typeString]- , [typePath , typePath , typePath ]- , [typeString, typeString, typePath ]+ eqConstrMtx+ [ mk3same typeInt+ , mk3same typeFloat+ , mk3 typeInt typeFloat typeFloat+ , mk3 typeFloat typeInt typeFloat+ , mk3same typeString+ , mk3same typePath+ , mk3 typeString typeString typePath ] - eqCnstMtx mtx = [EqConst u1 $ TMany $ typeFun <$> mtx]- liftInfer :: Monad m => m a -> InferT s m a liftInfer = InferT . lift . lift . lift @@ -773,13 +774,11 @@ infer :: MonadInfer m => NExpr -> InferT s m (Judgment s) infer = foldFix Eval.eval -inferTop :: Env -> [(Text, NExpr)] -> Either InferError Env+inferTop :: Env -> [(VarName, NExpr)] -> Either InferError Env inferTop env [] = pure env inferTop env ((name, ex) : xs) =- either- Left- (\ ty -> inferTop (extend env (name, ty)) xs)- (inferExpr env ex)+ (\ ty -> inferTop (extend env (name, ty)) xs)+ =<< inferExpr env ex -- * Other @@ -787,13 +786,15 @@ deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadLogic, MonadState [TypeError]) -runSolver :: Monad m => Solver m a -> m (Either [TypeError] [a])-runSolver (Solver s) = do- res <- runStateT (observeAllT s) mempty- pure $- case res of- (x : xs, _ ) -> pure (x : xs)- (_ , es) -> Left (ordNub es)+runSolver :: forall m a . Monad m => Solver m a -> m (Either [TypeError] [a])+runSolver (Solver s) =+ uncurry report <$> runStateT (observeAllT s) mempty+ where+ report :: [a] -> [TypeError] -> Either [TypeError] [a]+ report xs e =+ if null xs+ then Left (ordNub e)+ else pure xs -- ** Instances @@ -827,13 +828,9 @@ -- Putting a statement that lists of different lengths containing various types would not -- be unified. unifies t1@(TList _ ) t2@(TList _ ) = throwError $ UnificationFail t1 t2-unifies ( TSet True _) ( TSet True _) = stub-unifies (TSet False b) (TSet True s)- | M.keys b `intersect` M.keys s == M.keys s = stub-unifies (TSet True s) (TSet False b)- | M.keys b `intersect` M.keys s == M.keys b = stub-unifies (TSet False s) (TSet False b)- | null (M.keys b \\ M.keys s) = stub+unifies (TSet Variadic _) (TSet Variadic _) = stub+unifies (TSet Closed s) (TSet Closed b) | null (M.keys b \\ M.keys s) = stub+unifies (TSet _ a) (TSet _ b) | (M.keys a `intersect` M.keys b) == M.keys b = stub unifies (t1 :~> t2) (t3 :~> t4) = unifyMany [t1, t2] [t3, t4] unifies (TMany t1s) t2 = considering t1s >>- (`unifies` t2) unifies t1 (TMany t2s) = considering t2s >>- unifies t1@@ -844,17 +841,15 @@ unifyMany (t1 : ts1) (t2 : ts2) = do su1 <- unifies t1 t2 su2 <-- unifyMany- (apply su1 ts1)- (apply su1 ts2)- pure $ su2 `compose` su1+ (unifyMany `on` apply su1) ts1 ts2+ pure $ compose su1 su2 unifyMany t1 t2 = throwError $ UnificationMismatch t1 t2 nextSolvable :: [Constraint] -> (Constraint, [Constraint])-nextSolvable xs = fromJust $ find solvable $ takeFirstOnes xs+nextSolvable = fromJust . find solvable . pickFirstOne where- takeFirstOnes :: Eq a => [a] -> [(a, [a])]- takeFirstOnes xs = [ (x, ys) | x <- xs, let ys = delete x xs ]+ pickFirstOne :: Eq a => [a] -> [(a, [a])]+ pickFirstOne xs = [ (x, ys) | x <- xs, let ys = delete x xs ] solvable :: (Constraint, [Constraint]) -> Bool solvable (EqConst{} , _) = True@@ -862,18 +857,23 @@ solvable (ImpInstConst _t1 ms t2, cs) = Set.null $ (ms `Set.difference` ftv t2) `Set.intersection` atv cs -solve :: MonadState InferState m => [Constraint] -> Solver m Subst+solve :: forall m . MonadState InferState m => [Constraint] -> Solver m Subst solve [] = stub solve cs = solve' $ nextSolvable cs where- solve' (EqConst t1 t2, cs) =- unifies t1 t2 >>-- \su1 -> solve (apply su1 cs) >>-- \su2 -> pure $ su2 `compose` su1- solve' (ImpInstConst t1 ms t2, cs) = solve (ExpInstConst t1 (generalize ms t2) : cs)+ solve' (ExpInstConst t s, cs) =+ do+ s' <- lift $ instantiate s+ solve (EqConst t s' : cs)+ solve' (EqConst t1 t2, cs) =+ (\ su1 ->+ (pure . compose su1) -<< solve ((`apply` cs) su1)+ ) -<<+ unifies t1 t2 - solve' (ExpInstConst t s, cs) = do- s' <- lift $ instantiate s- solve (EqConst t s' : cs)+infixr 1 -<<+-- | @LogicT@ fair conjunction, since library has only @>>-@+(-<<) :: Monad m => (a -> Solver m b) -> Solver m a -> Solver m b+(-<<) = flip (>>-)
src/Nix/Type/Type.hs view
@@ -3,11 +3,8 @@ -- Therefore -> from this the type inference follows. module Nix.Type.Type where -import Prelude hiding ( Type, TVar )-import Data.Foldable ( foldr1 )-import Nix.Utils ( AttrSet )--type Name = Text+import Prelude hiding (Type, TVar)+import Nix.Expr.Types -- | Hindrey-Milner type interface @@ -19,7 +16,7 @@ data Type = TVar TVar -- ^ Type variable in the Nix type system. | TCon Text -- ^ Concrete (non-polymorphic, constant) type in the Nix type system.- | TSet Bool (AttrSet Type) -- ^ Heterogeneous map in the Nix type system. @True@ -> variadic.+ | TSet Variadic (AttrSet Type) -- ^ Heterogeneous map in the Nix type system. @True@ -> variadic. | TList [Type] -- ^ Heterogeneous list in the Nix type system. | (:~>) Type Type -- ^ Type arrow (@Type -> Type@) in the Nix type system. | TMany [Type] -- ^ Variant type (term). Since relating to Nix type system, more precicely -@@ -34,22 +31,21 @@ data Scheme = Forall [TVar] Type -- ^ @Forall [TVar] Type@: the Nix type system @forall vars. type@. deriving (Show, Eq, Ord) +-- | Concrete types in the Nix type system.+typeNull, typeBool, typeInt, typeFloat, typeString, typePath :: Type+typeNull = TCon "null"+typeBool = TCon "boolean"+typeInt = TCon "integer"+typeFloat = TCon "float"+typeString = TCon "string"+typePath = TCon "path"+ -- This models a set that unifies with any other set. typeSet :: Type-typeSet = TSet True mempty+typeSet = TSet mempty mempty typeList :: Type typeList = TList mempty -typeFun :: [Type] -> Type--- Please, replace with safe analog to `foldr1`-typeFun = foldr1 (:~>)---- | Concrete types in the Nix type system.-typeInt, typeFloat, typeBool, typeString, typePath, typeNull :: Type-typeInt = TCon "integer"-typeFloat = TCon "float"-typeBool = TCon "boolean"-typeString = TCon "string"-typePath = TCon "path"-typeNull = TCon "null"+typeFun :: NonEmpty Type -> Type+typeFun (head_ :| tail_) = foldr (:~>) head_ tail_
+ src/Nix/Unused.hs view
@@ -0,0 +1,82 @@+{-# language FunctionalDependencies #-}+{-# language TemplateHaskell #-}++{-# options_ghc -Wno-missing-signatures #-}++-- | This module holds unused code.+-- So, if someone wants something - look here, use it & move to appropriate place.+module Nix.Unused+ where++import Control.Monad.Free ( Free(..) )+import Data.Fix ( Fix(..) )+import Lens.Family2.TH ( makeLensesBy )++-- * From "Nix.Utils"++-- | > type AlgM f m a = f a -> m a+type AlgM f m a = f a -> m a++whenFree :: (Monoid b)+ => (f (Free f a) -> b) -> Free f a -> b+whenFree =+ free+ mempty+{-# inline whenFree #-}++whenPure :: (Monoid b)+ => (a -> b) -> Free f a -> b+whenPure f =+ free+ f+ mempty+{-# inline whenPure #-}++-- | Replace:+-- @Pure a -> a@+-- @Free -> Fix@+freeToFix :: Functor f => (a -> Fix f) -> Free f a -> Fix f+freeToFix f = go+ where+ go =+ free+ f+ $ Fix . (go <$>)++-- | Replace:+-- @a -> Pure a@+-- @Fix -> Free@+fixToFree :: Functor f => Fix f -> Free f a+fixToFree = Free . go+ where+ go (Fix f) = Free . go <$> f+++loeb :: Functor f => f (f a -> a) -> f a+loeb x = go+ where+ go = ($ go) <$> x++adiM+ :: ( Traversable t+ , Monad m+ )+ => Transform t (m a)+ -> AlgM t m a+ -> Fix t+ -> m a+adiM g f = g $ f <=< traverse (adiM g f) . unFix++para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a+para f = f . fmap (id &&& para f) . unFix++paraM :: (Traversable f, Monad m) => (f (Fix f, a) -> m a) -> Fix f -> m a+paraM f = f <=< traverse (\x -> (x, ) <$> paraM f x) . unFix++cataP :: Functor f => (Fix f -> f a -> a) -> Fix f -> a+cataP f x = f x . fmap (cataP f) . unFix $ x++cataPM :: (Traversable f, Monad m) => (Fix f -> f a -> m a) -> Fix f -> m a+cataPM f x = f x <=< traverse (cataPM f) . unFix $ x++$(makeLensesBy (\n -> pure $ "_" <> n) ''Fix)
src/Nix/Utils.hs view
@@ -1,56 +1,168 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}+{-# language NoImplicitPrelude #-}+{-# language CPP #-}+{-# language GeneralizedNewtypeDeriving #-} -{-# OPTIONS_GHC -Wno-missing-signatures #-}+-- | This is a module of custom "Prelude" code.+-- It is for import for projects other then @HNix@.+-- For @HNix@ - this module gets reexported by "Prelude", so for @HNix@ please fix-up pass-through there.+module Nix.Utils+ ( KeyMap+ , TransformF+ , Transform+ , Alg -module Nix.Utils (module Nix.Utils, module X) where+ , Path(..)+ , isAbsolute+ , (</>)+ , joinPath+ , splitDirectories+ , takeDirectory+ , takeFileName+ , takeBaseName+ , takeExtension+ , takeExtensions+ , addExtension+ , dropExtensions+ , replaceExtension + , Has(..)+ , trace+ , traceM+ , stub+ , pass+ , whenTrue+ , whenFalse+ , list+ , whenText+ , free+ , whenJust+ , dup+ , mapPair+ , both+ , readFile+ , traverseM+ , lifted+ , loebM+ , adi+ , module X+ )+ where++import Relude hiding ( pass+ , force+ , readFile+ , whenJust+ , whenNothing+ , trace+ , traceM+ )++import Data.Binary ( Binary )+import Data.Data ( Data )+import Codec.Serialise ( Serialise ) import Control.Monad.Fix ( MonadFix(..) ) import Control.Monad.Free ( Free(..) ) import Control.Monad.Trans.Control ( MonadTransControl(..) ) import qualified Data.Aeson as A-import qualified Data.Aeson.Encoding as A-#if MIN_VERSION_aeson(2,0,0)-import qualified Data.Aeson.KeyMap as AKM-#else-import qualified Data.HashMap.Strict as HM-#endif import Data.Fix ( Fix(..) )-import qualified Data.HashMap.Lazy as M import qualified Data.Text as Text-import qualified Data.Vector as V-import Lens.Family2 as X hiding ((&))+import qualified Data.Text.IO as Text+import Lens.Family2 as X+ ( view+ , over+ , LensLike'+ , Lens'+ ) import Lens.Family2.Stock ( _1 , _2 )-import Lens.Family2.TH ( makeLensesBy )+import qualified System.FilePath as FilePath #if ENABLE_TRACING-import Debug.Trace as X+import qualified Relude.Debug as X #else -- Well, since it is currently CPP intermingled with Debug.Trace, required to use String here. trace :: String -> a -> a trace = const id {-# inline trace #-} traceM :: Monad m => String -> m ()-traceM = const pass+traceM = const stub {-# inline traceM #-} #endif -$(makeLensesBy (\n -> pure $ "_" <> n) ''Fix)+-- | To have explicit type boundary between FilePath & String.+newtype Path = Path FilePath+ deriving+ ( Eq, Ord, Generic+ , Typeable, Data, NFData, Serialise, Binary, A.ToJSON, A.FromJSON+ , Show, Read, Hashable+ , Semigroup, Monoid+ ) +instance ToText Path where+ toText = toText @String . coerce++instance IsString Path where+ fromString = coerce++-- This set of @Path@ funcs is to control system filepath types & typesafety and to easy migrate from FilePath to anything suitable (like @path@ or so).++-- | @isAbsolute@ specialized to @Path@.+isAbsolute :: Path -> Bool+isAbsolute = coerce FilePath.isAbsolute++-- | @(</>)@ specialized to @Path@+(</>) :: Path -> Path -> Path+(</>) = coerce (FilePath.</>)+infixr 5 </>++-- | @joinPath@ specialized to @Path@+joinPath :: [Path] -> Path+joinPath = coerce FilePath.joinPath++-- | @splitDirectories@ specialized to @Path@+splitDirectories :: Path -> [Path]+splitDirectories = coerce FilePath.splitDirectories++-- | @takeDirectory@ specialized to @Path@+takeDirectory :: Path -> Path+takeDirectory = coerce FilePath.takeDirectory++-- | @takeFileName@ specialized to @Path@+takeFileName :: Path -> Path+takeFileName = coerce FilePath.takeFileName++-- | @takeBaseName@ specialized to @Path@+takeBaseName :: Path -> String+takeBaseName = coerce FilePath.takeBaseName++-- | @takeExtension@ specialized to @Path@+takeExtension :: Path -> String+takeExtension = coerce FilePath.takeExtensions++-- | @takeExtensions@ specialized to @Path@+takeExtensions :: Path -> String+takeExtensions = coerce FilePath.takeExtensions++addExtension :: Path -> String -> Path+addExtension = coerce FilePath.addExtension++-- | @dropExtensions@ specialized to @Path@+dropExtensions :: Path -> Path+dropExtensions = coerce FilePath.dropExtensions++-- | @replaceExtension@ specialized to @Path@+replaceExtension :: Path -> String -> Path+replaceExtension = coerce FilePath.replaceExtension++ -- | > Hashmap Text -- type synonym-type AttrSet = HashMap Text+type KeyMap = HashMap Text -- | F-algebra defines how to reduce the fixed-point of a functor to a value. -- > type Alg f a = f a -> a type Alg f a = f a -> a --- | > type AlgM f m a = f a -> m a-type AlgM f m a = f a -> m a- -- | Do according transformation. -- -- It is a transformation of a recursion scheme.@@ -63,28 +175,25 @@ -- You got me, it is a natural transformation. type TransformF f a = (f -> a) -> f -> a -loeb :: Functor f => f (f a -> a) -> f a-loeb x = go- where- go = ($ go) <$> x+class Has a b where+ hasLens :: Lens' a b +instance Has a a where+ hasLens f = f++instance Has (a, b) a where+ hasLens = _1++instance Has (a, b) b where+ hasLens = _2+ loebM :: (MonadFix m, Traversable t) => t (t a -> m a) -> m (t a) -- Sectioning here insures optimization happening. loebM f = mfix $ \a -> (`traverse` f) ($ a) {-# inline loebM #-} -para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a-para f = f . fmap (id &&& para f) . unFix--paraM :: (Traversable f, Monad m) => (f (Fix f, a) -> m a) -> Fix f -> m a-paraM f = f <=< traverse (\x -> (x, ) <$> paraM f x) . unFix--cataP :: Functor f => (Fix f -> f a -> a) -> Fix f -> a-cataP f x = f x . fmap (cataP f) . unFix $ x--cataPM :: (Traversable f, Monad m) => (Fix f -> f a -> m a) -> Fix f -> m a-cataPM f x = f x <=< traverse (cataPM f) . unFix $ x-+-- 2021-08-21: NOTE: Someone needs to put in normal words, what this does.+-- This function is pretty spefic & used only once, in "Nix.Normal". lifted :: (MonadTransControl u, Monad (u m), Monad m) => ((a -> m (StT u b)) -> m (StT u b))@@ -95,29 +204,12 @@ lftd <- liftWith (\run -> f (run . k)) restoreT $ pure lftd --- | Replace:--- @Pure a -> a@--- @Free -> Fix@-freeToFix :: Functor f => (a -> Fix f) -> Free f a -> Fix f-freeToFix f = go- where- go =- free- f- $ Fix . (go <$>)---- | Replace:--- @a -> Pure a@--- @Fix -> Free@-fixToFree :: Functor f => Fix f -> Free f a-fixToFree = Free . go- where- go (Fix f) = Free . go <$> f- -- | adi is Abstracting Definitional Interpreters: -- -- https://arxiv.org/abs/1707.04755 --+-- All ADI does is interleaves every layer of evaluation by inserting intermitten layers between them, in that way the evaluation can be extended/embelished in any way wanted. Look at its use to see great examples.+-- -- Essentially, it does for evaluation what recursion schemes do for -- representation: allows threading layers through existing structure, only -- in this case through behavior.@@ -129,72 +221,7 @@ -> a adi g f = g $ f . (adi g f <$>) . unFix -adiM- :: ( Traversable t- , Monad m- )- => Transform t (m a)- -> AlgM t m a- -> Fix t- -> m a-adiM g f = g $ f <=< traverse (adiM g f) . unFix --class Has a b where- hasLens :: Lens' a b--instance Has a a where- hasLens f = f--instance Has (a, b) a where- hasLens = _1--instance Has (a, b) b where- hasLens = _2--toEncodingSorted :: A.Value -> A.Encoding-toEncodingSorted = \case- A.Object m ->- A.pairs- . mconcat- . ((\(k, v) -> A.pair k $ toEncodingSorted v) <$>)- . sortWith fst $-#if MIN_VERSION_aeson(2,0,0)- AKM.toList-#else- HM.toList-#endif- m- A.Array l -> A.list toEncodingSorted $ V.toList l- v -> A.toEncoding v--data NixPathEntryType = PathEntryPath | PathEntryURI deriving (Show, Eq)---- | @NIX_PATH@ is colon-separated, but can also contain URLs, which have a colon--- (i.e. @https://...@)-uriAwareSplit :: Text -> [(Text, NixPathEntryType)]-uriAwareSplit txt =- case Text.break (== ':') txt of- (e1, e2)- | Text.null e2 -> [(e1, PathEntryPath)]- | "://" `Text.isPrefixOf` e2 ->- let ((suffix, _) : path) = uriAwareSplit (Text.drop 3 e2) in- (e1 <> "://" <> suffix, PathEntryURI) : path- | otherwise -> (e1, PathEntryPath) : uriAwareSplit (Text.drop 1 e2)--alterF- :: (Eq k, Hashable k, Functor f)- => (Maybe v -> f (Maybe v))- -> k- -> HashMap k v- -> f (HashMap k v)-alterF f k m =- maybe- (M.delete k m)- (\ v -> M.insert k v m)- <$> f (M.lookup k m)-- -- | Analog for @bool@ or @maybe@, for list-like cons structures. list :: Foldable t@@ -206,6 +233,14 @@ (null l) {-# inline list #-} +whenText+ :: a -> (Text -> a) -> Text -> a+whenText e f t =+ bool+ (f t)+ e+ (Text.null t)+ -- | Lambda analog of @maybe@ or @either@ for Free monad. free :: (a -> b) -> (f (Free f a) -> b) -> Free f a -> b free fP fF fr =@@ -230,20 +265,15 @@ mempty {-# inline whenFalse #-} -whenFree :: (Monoid b)- => (f (Free f a) -> b) -> Free f a -> b-whenFree =- free- mempty-{-# inline whenFree #-}--whenPure :: (Monoid b)- => (a -> b) -> Free f a -> b-whenPure f =- free- f+whenJust+ :: Monoid b+ => (a -> b)+ -> Maybe a+ -> b+whenJust =+ maybe mempty-{-# inline whenPure #-}+{-# inline whenJust #-} -- | Apply a single function to both components of a pair.@@ -271,3 +301,23 @@ stub :: (Applicative f, Monoid a) => f a stub = pure mempty {-# inline stub #-}++-- | Alias for @stub@, since @Relude@ has more specialized @pure ()@.+pass :: (Applicative f) => f ()+pass = stub+{-# inline pass #-}++readFile :: Path -> IO Text+readFile = Text.readFile . coerce++traverseM+ :: ( Applicative m+ , Applicative f+ , Traversable t+ )+ => ( a+ -> m (f b)+ )+ -> t a+ -> m (f (t b))+traverseM f x = sequenceA <$> traverse f x
src/Nix/Utils/Fix1.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE UndecidableInstances #-}+{-# language TypeFamilies #-}+{-# language ConstraintKinds #-}+{-# language CPP #-}+{-# language GeneralizedNewtypeDeriving #-}+{-# language PolyKinds #-}+{-# language UndecidableInstances #-} module Nix.Utils.Fix1 where @@ -87,8 +87,11 @@ type Ref (Fix1T t m) = Ref m newRef = lift . newRef+ {-# inline newRef #-} readRef = lift . readRef+ {-# inline readRef #-} writeRef r = lift . writeRef r+ {-# inline writeRef #-} instance@@ -98,6 +101,7 @@ => MonadAtomicRef (Fix1T t m) where atomicModifyRef r = lift . atomicModifyRef r+ {-# inline atomicModifyRef #-} {-
src/Nix/Value.hs view
@@ -1,22 +1,18 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}+{-# language CPP #-}+{-# language DeriveAnyClass #-}+{-# language KindSignatures #-}+{-# language ConstraintKinds #-}+{-# language PatternSynonyms #-}+{-# language RankNTypes #-}+{-# language TemplateHaskell #-} -{-# OPTIONS_GHC -Wno-missing-signatures #-}-{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}+{-# options_ghc -Wno-missing-signatures #-}+{-# options_ghc -Wno-missing-pattern-synonym-signatures #-} -- | The core of the type system, Nix language values module Nix.Value where -import Prelude hiding ( force )-import Nix.Utils import Control.Comonad ( Comonad , extract )@@ -36,13 +32,12 @@ , showString , showParen )-import Lens.Family2.Stock ( _1 )+import Lens.Family2.Stock ( _2 ) import Lens.Family2.TH ( makeTraversals , makeLenses ) import Nix.Atoms import Nix.Expr.Types-import Nix.Expr.Types.Annotated import Nix.String import Nix.Thunk @@ -118,14 +113,13 @@ -- | A string has a value and a context, which can be used to record what a -- string has been build from | NVStrF NixString- | NVPathF FilePath+ | NVPathF Path | NVListF [r]- -- 2021-05-22: NOTE: Please flip this and dependent functions.- -- Quite frequently actions/processing happens with values- -- (for example - forcing of values & recreation of the monad),- -- but SourcePos does not change then- -- That would be good to flip all 'AttrSet.* AttrSet SourcePos'- | NVSetF (AttrSet r) (AttrSet SourcePos)+ | NVSetF PositionSet (AttrSet r)+ -- ^+ -- Quite frequently actions/processing happens with values+ -- (for example - forcing of values & recreation of the monad),+ -- but @SourcePos@ does not change then. | NVClosureF (Params ()) (p -> m r) -- ^ A function is a closed set of parameters representing the "call -- signature", used at application time to check the type of arguments@@ -138,7 +132,7 @@ -- Note that 'm r' is being used here because effectively a function -- and its set of default arguments is "never fully evaluated". This -- enforces in the type that it must be re-evaluated for each call.- | NVBuiltinF Text (p -> m r)+ | NVBuiltinF VarName (p -> m r) -- ^ A builtin function is itself already in normal form. Also, it may -- or may not choose to evaluate its argument in the production of a -- result.@@ -151,8 +145,8 @@ liftEq _ (NVConstantF x) (NVConstantF y) = x == y liftEq _ (NVStrF x) (NVStrF y) = x == y liftEq eq (NVListF x) (NVListF y) = liftEq eq x y- liftEq eq (NVSetF x _ ) (NVSetF y _ ) = liftEq eq x y- liftEq _ (NVPathF x ) (NVPathF y ) = x == y+ liftEq eq (NVSetF _ x) (NVSetF _ y) = liftEq eq x y+ liftEq _ (NVPathF x) (NVPathF y) = x == y liftEq _ _ _ = False @@ -166,7 +160,7 @@ (NVConstantF atom ) -> showsCon1 "NVConstant" atom (NVStrF ns ) -> showsCon1 "NVStr" (stringIgnoreContext ns) (NVListF lst ) -> showsCon1 "NVList" lst- (NVSetF attrs _ ) -> showsCon1 "NVSet" attrs+ (NVSetF _ attrs) -> showsCon1 "NVSet" attrs (NVClosureF params _ ) -> showsCon1 "NVClosure" params (NVPathF path ) -> showsCon1 "NVPath" path (NVBuiltinF name _ ) -> showsCon1 "NVBuiltin" name@@ -185,7 +179,7 @@ NVStrF _ -> mempty NVPathF _ -> mempty NVListF l -> foldMap f l- NVSetF s _ -> foldMap f s+ NVSetF _ s -> foldMap f s NVClosureF _ _ -> mempty NVBuiltinF _ _ -> mempty @@ -203,11 +197,7 @@ NVStrF s -> pure $ NVStrF s NVPathF p -> pure $ NVPathF p NVListF l -> NVListF <$> sequenceA l- NVSetF s p ->- liftA2- NVSetF- (sequenceA s)- (pure p)+ NVSetF p s -> NVSetF p <$> sequenceA s NVClosureF p g -> pure $ NVClosureF p (transform <=< g) NVBuiltinF s g -> pure $ NVBuiltinF s (transform <=< g) @@ -226,11 +216,7 @@ NVStrF s -> pure $ NVStrF s NVPathF p -> pure $ NVPathF p NVListF l -> NVListF <$> traverse f l- NVSetF s p ->- liftA2- NVSetF- (traverse f s)- (pure p)+ NVSetF p s -> NVSetF p <$> traverse f s NVClosureF p g -> pure $ NVClosureF p (transform . f <=< g) NVBuiltinF s g -> pure $ NVBuiltinF s (transform . f <=< g) @@ -268,13 +254,13 @@ -- , NVStrF s -- , NVPathF p -- , NVListF l- -- , NVSetF s p+ -- , NVSetF p s -- ] NVConstantF a -> NVConstantF a NVStrF s -> NVStrF s NVPathF p -> NVPathF p NVListF l -> NVListF l- NVSetF s p -> NVSetF s p+ NVSetF p s -> NVSetF p s NVBuiltinF s g -> NVBuiltinF s (lft . g) NVClosureF p g -> NVClosureF p (lft . g) {-# inline hoistNValueF #-}@@ -303,7 +289,7 @@ NVStr' ns -> showsUnaryWith showsPrec "NVStrF" p (stringIgnoreContext ns) NVList' lst -> showsUnaryWith (liftShowsPrec sp sl) "NVListF" p lst- NVSet' attrs _ -> showsUnaryWith (liftShowsPrec sp sl) "NVSetF" p attrs+ NVSet' _ attrs -> showsUnaryWith (liftShowsPrec sp sl) "NVSetF" p attrs NVPath' path -> showsUnaryWith showsPrec "NVPathF" p path NVClosure' c _ -> showsUnaryWith showsPrec "NVClosureF" p c NVBuiltin' name _ -> showsUnaryWith showsPrec "NVBuiltinF" p name@@ -330,7 +316,7 @@ NVStrF s -> NVStrF s NVPathF p -> NVPathF p NVListF l -> NVListF l- NVSetF s p -> NVSetF s p+ NVSetF p s -> NVSetF p s NVClosureF p g -> NVClosureF p (g . f) NVBuiltinF s g -> NVBuiltinF s (g . f) @@ -429,11 +415,11 @@ nvStr' = NValue' . pure . NVStrF --- | Haskell @FilePath@ to the Nix path,+-- | Haskell @Path@ to the Nix path, nvPath' :: Applicative f- => FilePath+ => Path -> NValue' t f m r-nvPath' = NValue' . pure . NVPathF+nvPath' = NValue' . pure . NVPathF . coerce -- | Haskell @[]@ to the Nix @[]@,@@ -445,10 +431,11 @@ -- | Haskell key-value to the Nix key-value, nvSet' :: Applicative f- => AttrSet SourcePos+ => PositionSet -> AttrSet r -> NValue' t f m r-nvSet' x s = NValue' $ pure $ NVSetF s x+-- 2021-07-16: NOTE: that the arguments are flipped.+nvSet' p s = NValue' $ pure $ NVSetF p s -- | Haskell closure to the Nix closure,@@ -463,7 +450,7 @@ -- | Haskell functions to the Nix functions! nvBuiltin' :: (Applicative f, Functor m)- => Text+ => VarName -> (NValue t f m -> m r) -> NValue' t f m r nvBuiltin' name f = NValue' $ pure $ NVBuiltinF name f@@ -485,10 +472,10 @@ pattern NVStr' ns <- NValue' (extract -> NVStrF ns) pattern NVPath' x <- NValue' (extract -> NVPathF x) pattern NVList' l <- NValue' (extract -> NVListF l)-pattern NVSet' s x <- NValue' (extract -> NVSetF s x)+pattern NVSet' p s <- NValue' (extract -> NVSetF p s) pattern NVClosure' x f <- NValue' (extract -> NVClosureF x f) pattern NVBuiltin' name f <- NValue' (extract -> NVBuiltinF name f)-{-# COMPLETE NVConstant', NVStr', NVPath', NVList', NVSet', NVClosure', NVBuiltin' #-}+{-# complete NVConstant', NVStr', NVPath', NVList', NVSet', NVClosure', NVBuiltin' #-} -- * @__NValue__@: Nix language values@@ -610,12 +597,12 @@ nvStrWithoutContext :: Applicative f => Text -> NValue t f m-nvStrWithoutContext = nvStr . makeNixStringWithoutContext+nvStrWithoutContext = nvStr . mkNixStringWithoutContext -- | Life of a Haskell FilePath to the life of a Nix path nvPath :: Applicative f- => FilePath+ => Path -> NValue t f m nvPath = Free . nvPath' @@ -627,11 +614,10 @@ nvSet :: Applicative f- => AttrSet SourcePos+ => PositionSet -> AttrSet (NValue t f m) -> NValue t f m-nvSet x s = Free $ nvSet' x s-+nvSet p s = Free $ nvSet' p s nvClosure :: (Applicative f, Functor m) => Params ()@@ -643,7 +629,7 @@ nvBuiltin :: (Applicative f, Functor m)- => Text+ => VarName -> (NValue t f m -> m (NValue t f m) )@@ -654,7 +640,7 @@ builtin :: forall m f t . (MonadThunk t m (NValue t f m), MonadDataContext f m)- => Text+ => VarName -> ( NValue t f m -> m (NValue t f m) )@@ -664,7 +650,7 @@ builtin2 :: (MonadThunk t m (NValue t f m), MonadDataContext f m)- => Text+ => VarName -> ( NValue t f m -> NValue t f m -> m (NValue t f m)@@ -675,7 +661,7 @@ builtin3 :: (MonadThunk t m (NValue t f m), MonadDataContext f m)- => Text+ => VarName -> ( NValue t f m -> NValue t f m -> NValue t f m@@ -689,7 +675,7 @@ pattern NVThunk t <- Pure t pattern NVValue v <- Free v-{-# COMPLETE NVThunk, NVValue #-}+{-# complete NVThunk, NVValue #-} pattern NVConstant x <- Free (NVConstant' x) pattern NVStr ns <- Free (NVStr' ns) pattern NVPath x <- Free (NVPath' x)@@ -697,29 +683,37 @@ pattern NVSet s x <- Free (NVSet' s x) pattern NVClosure x f <- Free (NVClosure' x f) pattern NVBuiltin name f <- Free (NVBuiltin' name f)-{-# COMPLETE NVThunk, NVConstant, NVStr, NVPath, NVList, NVSet, NVClosure, NVBuiltin #-}+{-# complete NVThunk, NVConstant, NVStr, NVPath, NVList, NVSet, NVClosure, NVBuiltin #-} -- * @TStringContext@ data TStringContext = NoContext | HasContext- deriving Show+ deriving Show +instance Semigroup TStringContext where+ (<>) NoContext NoContext = NoContext+ (<>) _ _ = HasContext+++instance Monoid TStringContext where+ mempty = NoContext+ -- * @ValueType@ data ValueType- = TInt- | TFloat- | TBool- | TNull- | TString TStringContext- | TList- | TSet- | TClosure- | TPath- | TBuiltin- deriving Show+ = TInt+ | TFloat+ | TBool+ | TNull+ | TString TStringContext+ | TList+ | TSet+ | TClosure+ | TPath+ | TBuiltin+ deriving Show -- | Determine type of a value@@ -728,17 +722,14 @@ \case NVConstantF a -> case a of- NURI _ -> TString NoContext+ NURI _ -> TString mempty NInt _ -> TInt NFloat _ -> TFloat NBool _ -> TBool NNull -> TNull NVStrF ns -> TString $- bool- NoContext- HasContext- (stringHasContext ns)+ HasContext `whenTrue` stringHasContext ns NVListF{} -> TList NVSetF{} -> TSet NVClosureF{} -> TClosure@@ -754,8 +745,8 @@ TFloat -> "a float" TBool -> "a boolean" TNull -> "a null"- TString NoContext -> "a string"- TString HasContext -> "a string with context"+ TString NoContext -> "a string with no context"+ TString HasContext -> "a string" TList -> "a list" TSet -> "an attr set" TClosure -> "a function"@@ -822,4 +813,4 @@ :: (Traversable f, Applicative g) => VarName -> LensLike' g (NValue' t f m a) (Maybe a)-key k = nValue . traverse . _NVSetF . _1 . hashAt k+key k = nValue . traverse . _NVSetF . _2 . hashAt k
src/Nix/Value/Equal.hs view
@@ -1,17 +1,12 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-}+{-# language TypeFamilies #-} -{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}+{-# options_ghc -Wno-missing-pattern-synonym-signatures #-} module Nix.Value.Equal where -import Prelude hiding ( Comparison- , force- )-import Nix.Utils+import Prelude hiding ( Comparison ) import Control.Comonad ( Comonad(extract)) import Control.Monad.Free ( Free(Pure,Free) ) import Control.Monad.Trans.Except ( throwE )@@ -25,6 +20,7 @@ import Nix.String import Nix.Thunk import Nix.Value+import Nix.Expr.Types ( AttrSet ) checkComparable :: ( Framed e m@@ -35,12 +31,12 @@ -> m () checkComparable x y = case (x, y) of- (NVConstant (NFloat _), NVConstant (NInt _)) -> pass- (NVConstant (NInt _), NVConstant (NFloat _)) -> pass- (NVConstant (NInt _), NVConstant (NInt _)) -> pass- (NVConstant (NFloat _), NVConstant (NFloat _)) -> pass- (NVStr _ , NVStr _ ) -> pass- (NVPath _ , NVPath _ ) -> pass+ (NVConstant (NFloat _), NVConstant (NInt _)) -> stub+ (NVConstant (NInt _), NVConstant (NFloat _)) -> stub+ (NVConstant (NInt _), NVConstant (NInt _)) -> stub+ (NVConstant (NFloat _), NVConstant (NFloat _)) -> stub+ (NVStr _ , NVStr _ ) -> stub+ (NVPath _ , NVPath _ ) -> stub _ -> throwError $ Comparison x y -- | Checks whether two containers are equal, using the given item equality@@ -79,15 +75,16 @@ isDerivationM f m = maybe (pure False)- (\ t ->- maybe- -- We should probably really make sure the context is empty here- -- but the C++ implementation ignores it.- False- ((==) "derivation" . stringIgnoreContext)- <$> f t- )+ p (HashMap.Lazy.lookup "type" m)+ where+ p t =+ maybe+ -- We should probably really make sure the context is empty here+ -- but the C++ implementation ignores it.+ False+ ((==) "derivation" . stringIgnoreContext)+ <$> f t isDerivation :: Monad m@@ -119,7 +116,7 @@ (NVConstantF lc , NVConstantF rc ) -> pure $ lc == rc (NVStrF ls , NVStrF rs ) -> pure $ (\ i -> i ls == i rs) stringIgnoreContext (NVListF ls , NVListF rs ) -> alignEqM eq ls rs- (NVSetF lm _ , NVSetF rm _ ) -> attrsEq lm rm+ (NVSetF _ lm , NVSetF _ rm ) -> attrsEq lm rm (NVPathF lp , NVPathF rp ) -> pure $ lp == rp _ -> pure False
src/Nix/Var.hs view
@@ -1,9 +1,8 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language AllowAmbiguousTypes #-}+{-# language ConstraintKinds #-} -{-# OPTIONS_GHC -Wno-orphans #-}-{-# OPTIONS_GHC -Wno-unused-top-binds #-}+{-# options_ghc -Wno-orphans #-}+{-# options_ghc -Wno-unused-top-binds #-} module Nix.Var () where
src/Nix/XML.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ScopedTypeVariables #-} module Nix.XML ( toXML )@@ -21,13 +20,14 @@ where cyc = pure $ mkEVal "string" "<expr>" + pp :: Element -> Text pp e = heading- <> toText+ <> fromString (ppElement $ mkE "expr"- [Elem e]+ (one $ Elem e) ) <> "\n" where@@ -38,80 +38,73 @@ NVConstant' a -> pure $ case a of- NURI t -> mkEVal "string" $ toString t+ NURI t -> mkEVal "string" t NInt n -> mkEVal "int" $ show n NFloat f -> mkEVal "float" $ show f NBool b -> mkEVal "bool" $ if b then "true" else "false" NNull -> mkE "null" mempty NVStr' str ->- mkEVal "string" . toString <$> extractNixString str+ mkEVal "string" <$> extractNixString str NVList' l ->- do- els <- sequence l- pure $- mkE- "list"- (Elem <$> els)+ mkE "list" . fmap Elem <$> sequenceA l - NVSet' s _ ->- do- kvs <- sequence s- pure $- mkE- "attrs"- ((\ (k, v) ->- Elem $- Element- (unqual "attr")- [Attr (unqual "name") (toString k)]- [Elem v]- Nothing- ) <$>- sortWith fst (M.toList kvs)- )+ NVSet' _ s ->+ mkE+ "attrs"+ . fmap+ mkElem'+ . sortWith fst . M.toList+ <$> sequenceA s+ where+ mkElem' :: (VarName, Element) -> Content+ mkElem' (k, v) =+ Elem $+ Element+ (unqual "attr")+ (one $ Attr (unqual "name") $ toString k)+ (one $ Elem v)+ Nothing NVClosure' p _ -> pure $ mkE "function" (paramsXML p)- NVPath' fp -> pure $ mkEVal "path" fp- NVBuiltin' name _ -> pure $ mkEName "function" $ toString name+ NVPath' fp -> pure $ mkEVal "path" $ fromString $ coerce fp+ NVBuiltin' name _ -> pure $ mkEName "function" name -mkE :: String -> [Content] -> Element-mkE n c =+mkE :: Text -> [Content] -> Element+mkE (toString -> n) c = Element (unqual n) mempty c Nothing -mkElem :: String -> String -> String -> Element-mkElem n a v =+mkElem :: Text -> Text -> Text -> Element+mkElem (toString -> n) (toString -> a) (toString -> v) = Element (unqual n)- [Attr (unqual a) v]+ (one $ Attr (unqual a) v) mempty Nothing -mkEVal :: String -> String -> Element+mkEVal :: Text -> Text -> Element mkEVal = (`mkElem` "value") -mkEName :: String -> String -> Element-mkEName = (`mkElem` "name")+mkEName :: Text -> VarName -> Element+mkEName x (coerce -> y) = (`mkElem` "name") x y paramsXML :: Params r -> [Content]-paramsXML (Param name) = [Elem $ mkEName "varpat" (toString name)]-paramsXML (ParamSet s b mname) =- [Elem $ Element (unqual "attrspat") (battr <> nattr) (paramSetXML s) Nothing]+paramsXML (Param name) = one $ Elem $ mkEName "varpat" name+paramsXML (ParamSet mname variadic pset) =+ one $ Elem $ Element (unqual "attrspat") (battr <> nattr) (paramSetXML pset) Nothing where- battr = [ Attr (unqual "ellipsis") "1" | b ]+ battr =+ one (Attr (unqual "ellipsis") "1") `whenTrue` (variadic == Variadic) nattr =- maybe- mempty- ((: mempty) . Attr (unqual "name") . toString)- mname+ (one . Attr (unqual "name") . toString) `whenJust` mname paramSetXML :: ParamSet r -> [Content]-paramSetXML = fmap (\(k, _) -> Elem $ mkEName "attr" (toString k))+paramSetXML = fmap (Elem . mkEName "attr" . fst)
+ src/Prelude.hs view
@@ -0,0 +1,20 @@+-- | This is a @Prelude@, but, please, do not put things in here,+-- put them into "Nix.Utils". This module is a pass-through-multiplexer,+-- between our custom code ("Nix.Utils") that shadows over the outside prelude that is in use ("Relude")+-- "Prelude" module has a problem of being imported & used by other projects.+-- "Nix.Utils" as a module with a regular name does not have that problem.+module Prelude+ ( module Nix.Utils+ , module Relude+ ) where++import Nix.Utils+import Relude hiding ( pass+ , force+ , readFile+ , whenJust+ , whenNothing+ , trace+ , traceM+ )+
tests/EvalTests.hs view
@@ -1,13 +1,11 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}+{-# language QuasiQuotes #-}+{-# language TemplateHaskell #-} -{-# OPTIONS_GHC -Wno-missing-signatures #-}+{-# options_ghc -Wno-missing-signatures #-} module EvalTests (tests, genEvalCompareTests) where -import Prelude hiding (lookupEnv) import Control.Monad.Catch import Data.List ((\\)) import qualified Data.Set as S@@ -17,136 +15,189 @@ import Nix.Standard import Nix.TH import Nix.Value.Equal-import Nix.Utils import qualified System.Directory as D-import System.Environment (lookupEnv)-import System.FilePath import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.TH import TestCommon case_basic_sum =- constantEqualText "2" "1 + 1"+ constantEqualText+ "2"+ "1 + 1" case_basic_div =- constantEqualText "3" "builtins.div 6 2"+ constantEqualText+ "3"+ "builtins.div 6 2" -case_zero_div = do- assertNixEvalThrows "builtins.div 1 0"- assertNixEvalThrows "builtins.div 1.0 0"- assertNixEvalThrows "builtins.div 1 0.0"- assertNixEvalThrows "builtins.div 1.0 0.0"+case_zero_div =+ traverse_ assertNixEvalThrows+ [ "builtins.div 1 0"+ , "builtins.div 1.0 0"+ , "builtins.div 1 0.0"+ , "builtins.div 1.0 0.0"+ ] -case_bit_ops = do- -- mic92 (2018-08-20): change to constantEqualText,- -- when hnix's nix fork supports bitAnd/bitOr/bitXor- constantEqualText' "0" "builtins.bitAnd 1 0"- constantEqualText' "1" "builtins.bitOr 1 1"- constantEqualText' "3" "builtins.bitXor 1 2"+case_bit_ops =+ traverse_ (uncurry constantEqualText)+ [ ("0", "builtins.bitAnd 1 0")+ , ("1", "builtins.bitOr 1 1")+ , ("3", "builtins.bitXor 1 2")+ ] case_basic_function =- constantEqualText "2" "(a: a) 2"+ constantEqualText+ "2"+ "(a: a) 2" case_set_attr =- constantEqualText "2" "{ a = 2; }.a"+ constantEqualText+ "2"+ "{ a = 2; }.a" case_function_set_arg =- constantEqualText "2" "({ a }: 2) { a = 1; }"+ constantEqualText+ "2"+ "({ a }: 2) { a = 1; }" case_function_set_two_arg =- constantEqualText "2" "({ a, b ? 3 }: b - a) { a = 1; }"+ constantEqualText+ "2"+ "({ a, b ? 3 }: b - a) { a = 1; }" case_function_set_two_arg_default_scope =- constantEqualText "2" "({ x ? 1, y ? x * 3 }: y - x) {}"+ constantEqualText+ "2"+ "({ x ? 1, y ? x * 3 }: y - x) {}" case_function_default_env =- constantEqualText "2" "let default = 2; in ({ a ? default }: a) {}"+ constantEqualText+ "2"+ "let default = 2; in ({ a ? default }: a) {}" case_function_definition_uses_environment =- constantEqualText "3" "let f = (let a=1; in x: x+a); in f 2"+ constantEqualText+ "3"+ "let f = (let a=1; in x: x+a); in f 2" case_function_atpattern =- -- jww (2018-05-09): This should be constantEqualText- constantEqualText' "2" "(({a}@attrs:attrs) {a=2;}).a"+ -- jww (2018-05-09): This should be constantEqualText+ constantEqualText'+ "2"+ "(({a}@attrs:attrs) {a=2;}).a" case_function_ellipsis =- -- jww (2018-05-09): This should be constantEqualText- constantEqualText' "2" "(({a, ...}@attrs:attrs) {a=0; b=2;}).b"+ -- jww (2018-05-09): This should be constantEqualText+ constantEqualText'+ "2"+ "(({a, ...}@attrs:attrs) {a=0; b=2;}).b" case_function_default_value_not_in_atpattern =- constantEqualText "false" "({a ? 2}@attrs: attrs ? a) {}"+ constantEqualText+ "false"+ "({a ? 2}@attrs: attrs ? a) {}" case_function_arg_shadowing =- constantEqualText "6" "(y: y: x: x: x + y) 1 2 3 4"+ constantEqualText+ "6"+ "(y: y: x: x: x + y) 1 2 3 4" case_function_recursive_args =- constantEqualText "2" "({ x ? 1, y ? x * 3}: y - x) {}"+ constantEqualText+ "2"+ "({ x ? 1, y ? x * 3}: y - x) {}" case_function_recursive_sets =- constantEqualText "[ [ 6 4 100 ] 4 ]" [text|- let x = rec {+ constantEqualText+ "[ [ 6 4 100 ] 4 ]"+ [text|+ let x = rec { - y = 2;- z = { w = 4; };- v = rec {- u = 6;- t = [ u z.w s ];- };+ y = 2;+ z = { w = 4; };+ v = rec {+ u = 6;+ t = [ u z.w s ];+ }; - }; s = 100; in [ x.v.t x.z.w ]+ }; s = 100; in [ x.v.t x.z.w ] |] case_nested_with =- constantEqualText "2" "with { x = 1; }; with { x = 2; }; x"+ constantEqualText+ "2"+ "with { x = 1; }; with { x = 2; }; x" case_with_strictness =- constantEqualText "5" "let x = with x; with { a = 5; }; a; in x"+ constantEqualText+ "5"+ "let x = with x; with { a = 5; }; a; in x" case_match_failure_null =- constantEqualText "null" "builtins.match \"ab\" \"abc\""+ constantEqualText+ "null"+ "builtins.match \"ab\" \"abc\"" case_find_file_success_no_prefix =- constantEqualText "./tests/files/findFile.nix"- "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] \"findFile.nix\""+ constantEqualText+ "./tests/files/findFile.nix"+ "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] \"findFile.nix\"" case_find_file_success_with_prefix =- constantEqualText "./tests/files/findFile.nix"- "builtins.findFile [{ path=\"./tests/files\"; prefix=\"nix\"; }] \"nix/findFile.nix\""+ constantEqualText+ "./tests/files/findFile.nix"+ "builtins.findFile [{ path=\"./tests/files\"; prefix=\"nix\"; }] \"nix/findFile.nix\"" case_find_file_success_folder =- constantEqualText "./tests/files"- "builtins.findFile [{ path=\"./tests\"; prefix=\"\"; }] \"files\""+ constantEqualText+ "./tests/files"+ "builtins.findFile [{ path=\"./tests\"; prefix=\"\"; }] \"files\"" case_find_file_failure_not_found =- assertNixEvalThrows "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] \"not_found.nix\""+ assertNixEvalThrows+ "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] \"not_found.nix\"" case_find_file_failure_invalid_arg_1 =- assertNixEvalThrows "builtins.findFile 1 \"files\""+ assertNixEvalThrows+ "builtins.findFile 1 \"files\"" case_find_file_failure_invalid_arg_2 =- assertNixEvalThrows "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] 2"+ assertNixEvalThrows+ "builtins.findFile [{ path=\"./tests/files\"; prefix=\"\"; }] 2" case_find_file_failure_invalid_arg_no_path =- assertNixEvalThrows "builtins.findFile [{ prefix=\"\"; }] \"files\""+ assertNixEvalThrows+ "builtins.findFile [{ prefix=\"\"; }] \"files\"" case_infinite_recursion =- assertNixEvalThrows "let foo = a: bar a; bar = a: foo a; in foo 3"+ assertNixEvalThrows+ "let foo = a: bar a; bar = a: foo a; in foo 3" case_nested_let =- constantEqualText "3" "let a = 3; x.x = 2; in a"+ constantEqualText+ "3"+ "let a = 3; x.x = 2; in a" case_nested_nested_let =- constantEqualText "3" "let a = 3; x.x = let b = a; in b; c = x.x; in c"+ constantEqualText+ "3"+ "let a = 3; x.x = let b = a; in b; c = x.x; in c" case_inherit_in_rec_set =- constantEqualText "1" "let x = 1; in (rec { inherit x; }).x"+ constantEqualText+ "1"+ "let x = 1; in (rec { inherit x; }).x" case_lang_version =- constantEqualText "5" "builtins.langVersion"+ constantEqualText+ "5"+ "builtins.langVersion" case_rec_set_attr_path_simpl =- constantEqualText "123" [text|+ constantEqualText+ "123"+ [text| let x = rec { foo.number = 123; foo.function = y: foo.number;@@ -154,7 +205,9 @@ |] case_inherit_from_set_has_no_scope =- constantEqualText' "false" [text|+ constantEqualText'+ "false"+ [text| (builtins.tryEval ( let x = 1; y = { z = 2; };@@ -163,7 +216,7 @@ |] -- github/orblivion (2018-08-05): Adding these failing tests so we fix this feature-+-- -- case_overrides = -- constantEqualText' "2" [text| -- let@@ -190,171 +243,198 @@ -- }.__overrides.a) -- |] -case_unsafegetattrpos1 =- constantEqualText "[ 5 14 ]" [text|- let e = 1;- f = 1;- t = {};- s = {- inherit t e f;- a = 1;- "b" = 2;- c.d = 3;- };- p = builtins.unsafeGetAttrPos "e" s; in- [ p.line p.column ]- |]+case_unsafegetattrpos =+ traverse_ (uncurry constantEqualText)+ [ ( "[ 5 14 ]"+ , [text|+ let e = 1;+ f = 1;+ t = {};+ s = {+ inherit t e f;+ a = 1;+ "b" = 2;+ c.d = 3;+ };+ p = builtins.unsafeGetAttrPos "e" s; in+ [ p.line p.column ]+ |]+ )+ , ( "[ 5 14 ]"+ , [text|+ let e = 1;+ f = 1;+ t = {};+ s = {+ inherit t e f;+ a = 1;+ "b" = 2;+ c.d = 3;+ };+ p = builtins.unsafeGetAttrPos "f" s; in+ [ p.line p.column ]+ |]+ )+ , ( "[ 6 7 ]"+ , [text|+ let e = 1;+ f = 1;+ t = {};+ s = {+ inherit t e f;+ a = 1;+ "b" = 2;+ c.d = 3;+ };+ p = builtins.unsafeGetAttrPos "a" s; in+ [ p.line p.column ]+ |]+ )+ , ( "[ 7 7 ]"+ , [text|+ let e = 1;+ f = 1;+ t = {};+ s = {+ inherit t e f;+ a = 1;+ "b" = 2;+ c.d = 3;+ };+ p = builtins.unsafeGetAttrPos "b" s; in+ [ p.line p.column ]+ |]+ )+ -- jww (2018-05-09): These two are failing but they shouldn't be+ --+ -- , ( "[ 7 13 ]"+ -- , [text|+ -- let e = 1;+ -- f = 1;+ -- t = {};+ -- s = {+ -- inherit t e f;+ -- a = 1;+ -- "b" = 2;+ -- c.d = 3;+ -- };+ -- p = builtins.unsafeGetAttrPos "c.d" s; in+ -- [ p.line p.column ]+ -- |]+ -- ) -case_unsafegetattrpos2 =- constantEqualText "[ 5 14 ]" [text|- let e = 1;- f = 1;- t = {};- s = {- inherit t e f;- a = 1;- "b" = 2;- c.d = 3;- };- p = builtins.unsafeGetAttrPos "f" s; in- [ p.line p.column ]- |]+ -- , ( "[ 7 13 ]"+ -- , [text|+ -- let e = 1;+ -- f = 1;+ -- t = {};+ -- s = {+ -- inherit t e f;+ -- a = 1;+ -- "b" = 2;+ -- c.d = 3;+ -- };+ -- p = builtins.unsafeGetAttrPos "d" s; in+ -- [ p.line p.column ]+ -- |]+ -- )+ ] -case_unsafegetattrpos3 =- constantEqualText "[ 6 7 ]" [text|- let e = 1;- f = 1;- t = {};- s = {- inherit t e f;- a = 1;- "b" = 2;- c.d = 3;- };- p = builtins.unsafeGetAttrPos "a" s; in- [ p.line p.column ]+case_fixed_points =+ constantEqualText+ [text|+ [+ {+ foobar = "foobar";+ foo = "foo";+ bar = "bar";+ }+ {+ foobar = "foo + bar";+ foo = "foo + ";+ bar = "bar";+ }+ ] |]--case_unsafegetattrpos4 =- constantEqualText "[ 7 7 ]" [text|- let e = 1;- f = 1;- t = {};- s = {- inherit t e f;- a = 1;- "b" = 2;- c.d = 3;- };- p = builtins.unsafeGetAttrPos "b" s; in- [ p.line p.column ]+ [text|+ let+ fix = f: let x = f x; in x;+ extends = f: rattrs: self:+ let super = rattrs self; in super // f self super;+ f = self: { foo = "foo";+ bar = "bar";+ foobar = self.foo + self.bar; };+ g = self: super: { foo = super.foo + " + "; };+ in [ (fix f) (fix (extends g f)) ] |] --- jww (2018-05-09): These two are failing but they shouldn't be---- case_unsafegetattrpos5 =--- constantEqualText "[ 7 13 ]" [text|--- let e = 1;--- f = 1;--- t = {};--- s = {--- inherit t e f;--- a = 1;--- "b" = 2;--- c.d = 3;--- };--- p = builtins.unsafeGetAttrPos "c.d" s; in--- [ p.line p.column ]--- |]---- case_unsafegetattrpos6 =--- constantEqualText "[ 7 13 ]" [text|--- let e = 1;--- f = 1;--- t = {};--- s = {--- inherit t e f;--- a = 1;--- "b" = 2;--- c.d = 3;--- };--- p = builtins.unsafeGetAttrPos "d" s; in--- [ p.line p.column ]--- |]--case_fixed_points =- constantEqualText [text|[- {- foobar = "foobar";- foo = "foo";- bar = "bar";- }- {- foobar = "foo + bar";- foo = "foo + ";- bar = "bar";- }-]|] [text|- let- fix = f: let x = f x; in x;- extends = f: rattrs: self:- let super = rattrs self; in super // f self super;- f = self: { foo = "foo";- bar = "bar";- foobar = self.foo + self.bar; };- g = self: super: { foo = super.foo + " + "; };- in [ (fix f) (fix (extends g f)) ]-|]- case_fixed_points_and_fold =- constantEqualText [text|[ {} {} ]|] [text|-let- extends = f: rattrs: self:- let super = rattrs self; in super // f self super;- flip = f: a: b: f b a;- toFixFold = builtins.foldl' (flip extends) (self: {}) ([(self: super: {})]);- toFix = extends (self: super: {}) (self: {});- fix = f: let x = f x; in x;-in [ (fix toFixFold) (fix toFix) ]-|]+ constantEqualText+ [text|+ [ {} {} ]+ |]+ [text|+ let+ extends = f: rattrs: self:+ let super = rattrs self; in super // f self super;+ flip = f: a: b: f b a;+ toFixFold = builtins.foldl' (flip extends) (self: {}) ([(self: super: {})]);+ toFix = extends (self: super: {}) (self: {});+ fix = f: let x = f x; in x;+ in [ (fix toFixFold) (fix toFix) ]+ |] case_fixed_points_attrsets =- constantEqualText "{ x = { y = { z = 100; }; z = { y = 100; }; }; }" [text|+ constantEqualText+ "{ x = { y = { z = 100; }; z = { y = 100; }; }; }"+ [text| let fix = f: let x = f x; in x; f = self: { x.z.y = 100; x.y.z = self.x.z.y; }; in fix f |] --- case_function_equals1 =--- constantEqualText "true" "{f = x: x;} == {f = x: x;}"---- case_function_equals2 =--- constantEqualText "true" "[(x: x)] == [(x: x)]"--case_function_equals3 =- constantEqualText "false" "(let a = (x: x); in a == a)"--case_function_equals4 =- constantEqualText "true" "(let a = {f = x: x;}; in a == a)"--case_function_equals5 =- constantEqualText "true" "(let a = [(x: x)]; in a == a)"+case_function_equals =+ traverse_ (uncurry constantEqualText)+ [ -- ( "true"+ -- , "{f = x: x;} == {f = x: x;}"+ -- )+ -- ( "true"+ -- , "[(x: x)] == [(x: x)]"+ -- )+ ( "false"+ , "(let a = (x: x); in a == a)"+ )+ , ( "true"+ , "(let a = {f = x: x;}; in a == a)"+ )+ , ( "true"+ , "(let a = [(x: x)]; in a == a)"+ )+ , ( "false"+ , "builtins.pathExists \"/var/empty/invalid-directory\""+ )+ ] case_directory_pathexists =- constantEqualText "false" "builtins.pathExists \"/var/empty/invalid-directory\""+ constantEqualText+ "false"+ "builtins.pathExists \"/var/empty/invalid-directory\"" -- jww (2018-05-02): This constantly changes!--- case_placeholder =--- constantEqualText--- "\"/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9\""--- "builtins.placeholder \"out\""+case_placeholder =+ constantEqualText+ "\"/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9\""+ "builtins.placeholder \"out\"" case_rec_path_attr =- constantEqualText "10"- "let src = 10; x = rec { passthru.src = src; }; in x.passthru.src"+ constantEqualText+ "10"+ "let src = 10; x = rec { passthru.src = src; }; in x.passthru.src" case_mapattrs_builtin =- constantEqualText' "{ a = \"afoo\"; b = \"bbar\"; }" [text|+ constantEqualText'+ "{ a = \"afoo\"; b = \"bbar\"; }"+ [text| (builtins.mapAttrs (x: y: x + y) { a = "foo"; b = "bar";@@ -363,10 +443,18 @@ -- Regression test for #373 case_regression_373 :: Assertion-case_regression_373 = do- freeVarsEqual "{ inherit a; }" ["a"]- freeVarsEqual "rec {inherit a; }" ["a"]- freeVarsEqual "let inherit a; in { }" ["a"]+case_regression_373 =+ traverse_ (uncurry freeVarsEqual)+ [ ( "{ inherit a; }"+ , one "a"+ )+ , ("rec {inherit a; }"+ , one "a"+ )+ , ( "let inherit a; in { }"+ , one "a"+ )+ ] case_expression_split = constantEqualText@@ -374,91 +462,145 @@ "(x: builtins.deepSeq x x) (builtins.split \"(a)b\" \"abc\")" case_empty_string_equal_null_is_false =- constantEqualText "false" "\"\" == null"+ constantEqualText+ "false"+ "\"\" == null" case_null_equal_empty_string_is_false =- constantEqualText "false" "null == \"\""+ constantEqualText+ "false"+ "null == \"\"" case_empty_string_not_equal_null_is_true =- constantEqualText "true" "\"\" != null"+ constantEqualText+ "true"+ "\"\" != null" case_null_equal_not_empty_string_is_true =- constantEqualText "true" "null != \"\""+ constantEqualText+ "true"+ "null != \"\"" case_list_nested_bottom_diverges =- assertNixEvalThrows "let nested = [(let x = x; in x)]; in nested == nested"+ assertNixEvalThrows+ "let nested = [(let x = x; in x)]; in nested == nested" case_attrset_nested_bottom_diverges =- assertNixEvalThrows "let nested = { y = (let x = x; in x); }; in nested == nested"+ assertNixEvalThrows+ "let nested = { y = (let x = x; in x); }; in nested == nested" case_list_list_nested_bottom_equal =- constantEqualText "true" "let nested = [[(let x = x; in x)]]; in nested == nested"+ constantEqualText+ "true"+ "let nested = [[(let x = x; in x)]]; in nested == nested" case_list_attrset_nested_bottom_equal =- constantEqualText "true" "let nested = [{ y = (let x = x; in x); }]; in nested == nested"+ constantEqualText+ "true"+ "let nested = [{ y = (let x = x; in x); }]; in nested == nested" case_list_function_nested_bottom_equal =- constantEqualText "true" "let nested = [(_: let x = x; in x)]; in nested == nested"+ constantEqualText+ "true"+ "let nested = [(_: let x = x; in x)]; in nested == nested" case_attrset_list_nested_bottom_equal =- constantEqualText "true" "let nested = { y = [(let x = x; in x)];}; in nested == nested"+ constantEqualText+ "true"+ "let nested = { y = [(let x = x; in x)];}; in nested == nested" case_attrset_attrset_nested_bottom_equal =- constantEqualText "true" "let nested = { y = { y = (let x = x; in x); }; }; in nested == nested"+ constantEqualText+ "true"+ "let nested = { y = { y = (let x = x; in x); }; }; in nested == nested" case_attrset_function_nested_bottom_equal =- constantEqualText "true" "let nested = { y = _: (let x = x; in x); }; in nested == nested"+ constantEqualText+ "true"+ "let nested = { y = _: (let x = x; in x); }; in nested == nested" -- Regression test for #527 case_add_string_thunk_left =- constantEqualText [text|"cygwin"|] [text|builtins.head ["cyg"] + "win"|]+ constantEqualText+ [text|+ "cygwin"+ |]+ [text|+ builtins.head ["cyg"] + "win"+ |] case_add_string_thunk_right =- constantEqualText [text|"cygwin"|] [text|"cyg" + builtins.head ["win"]|]+ constantEqualText+ [text|+ "cygwin"+ |]+ [text|+ "cyg" + builtins.head ["win"]+ |] case_add_int_thunk_left =- constantEqualText "3" "builtins.head [1] + 2"+ constantEqualText+ "3"+ "builtins.head [1] + 2" case_add_int_thunk_right =- constantEqualText "3" "1 + builtins.head [2]"+ constantEqualText+ "3"+ "1 + builtins.head [2]" case_concat_thunk_left =- constantEqualText "[1 2 3]" "builtins.tail [0 1 2] ++ [3]"+ constantEqualText+ "[1 2 3]"+ "builtins.tail [0 1 2] ++ [3]" case_concat_thunk_rigth =- constantEqualText "[1 2 3]" "[1] ++ builtins.tail [1 2 3]"+ constantEqualText+ "[1 2 3]"+ "[1] ++ builtins.tail [1 2 3]" --------------------------------------------------------------------------------- tests :: TestTree tests = $testGroupGenerator -genEvalCompareTests = do- td <- D.listDirectory testDir+genEvalCompareTests =+ do+ (coerce -> files :: [Path]) <- D.listDirectory $ coerce testDir - let unmaskedFiles = filter ((==".nix") . takeExtension) td- let files = unmaskedFiles \\ maskedFiles+ let+ unmaskedFiles :: [Path]+ unmaskedFiles = filter ((== ".nix") . takeExtension) files - pure $ testGroup "Eval comparison tests" $ fmap (mkTestCase testDir) files+ testFiles :: [Path]+ testFiles = unmaskedFiles \\ maskedFiles++ pure $ testGroup "Eval comparison tests" $ fmap (mkTestCase testDir) testFiles where- mkTestCase td f = testCase f $ assertEvalFileMatchesNix (td </> f)+ mkTestCase :: Path -> Path -> TestTree+ mkTestCase dir f = testCase (coerce f :: TestName) $ assertEvalFileMatchesNix $ dir </> f constantEqual :: NExprLoc -> NExprLoc -> Assertion-constantEqual expected actual = do+constantEqual expected actual =+ do time <- getCurrentTime let opts = defaultOptions time -- putStrLn =<< lint (stripAnnotation a)- (eq, expectedNF, actualNF) <- runWithBasicEffectsIO opts $ do- expectedNF <- normalForm =<< nixEvalExprLoc mempty expected- actualNF <- normalForm =<< nixEvalExprLoc mempty actual- eq <- valueEqM expectedNF actualNF- pure (eq, expectedNF, actualNF)- let message =- "Inequal normal forms:\n"- <> "Expected: " <> printNix expectedNF <> "\n"- <> "Actual: " <> printNix actualNF- assertBool message eq+ (eq, expectedNF, actualNF) <-+ runWithBasicEffectsIO opts $+ do+ expectedNF <- getNormForm expected+ actualNF <- getNormForm actual+ eq <- valueEqM expectedNF actualNF+ pure (eq, expectedNF, actualNF)+ let+ message =+ "Inequal normal forms:\n"+ <> "Expected: " <> printNix expectedNF <> "\n"+ <> "Actual: " <> printNix actualNF+ assertBool (toString message) eq+ where+ getNormForm = normalForm <=< nixEvalExprLoc mempty constantEqualText' :: Text -> Text -> Assertion constantEqualText' expected actual =@@ -467,11 +609,11 @@ constantEqual expected' actual' constantEqualText :: Text -> Text -> Assertion-constantEqualText expected actual = do- constantEqualText' expected actual- mres <- liftIO $ lookupEnv "ALL_TESTS" <|> lookupEnv "MATCHING_TESTS"- when (isJust mres) $- assertEvalMatchesNix actual+constantEqualText expected actual =+ do+ constantEqualText' expected actual+ mres <- liftIO $ on (<|>) lookupEnv "ALL_TESTS" "MATCHING_TESTS"+ whenJust (const $ assertEvalMatchesNix actual) mres assertNixEvalThrows :: Text -> Assertion assertNixEvalThrows a =@@ -497,11 +639,10 @@ Right a' = parseNixText a xs' = S.fromList xs free' = freeVars a'- assertEqual "" xs' free'+ assertEqual mempty xs' free' -maskedFiles :: [FilePath]-maskedFiles =- [ "builtins.fetchurl-01.nix" ]+maskedFiles :: [Path]+maskedFiles = one "builtins.fetchurl-01.nix" -testDir :: FilePath+testDir :: Path testDir = "tests/eval-compare"
tests/Main.hs view
@@ -1,8 +1,8 @@-{-# LANGUAGE QuasiQuotes #-}+{-# language QuasiQuotes #-} module Main where -import Prelude hiding (lookupEnv)+import Relude (force) import Relude.Unsafe (read) import qualified Control.Exception as Exc import GHC.Err (errorWithoutStackTrace)@@ -25,9 +25,9 @@ import qualified ReduceExprTests import qualified PrettyParseTests import System.Directory-import System.Environment (setEnv, lookupEnv)-import System.FilePath.Glob-import System.Posix.Files+import System.Environment (setEnv)+import System.FilePath.Glob (compile, globDir1)+import System.PosixCompat.Files import Test.Tasty import Test.Tasty.HUnit @@ -43,9 +43,9 @@ ensureNixpkgsCanParse :: Assertion ensureNixpkgsCanParse = consider "default.nix" (parseNixFile "default.nix") $ \case- Fix (NAbs (ParamSet params _ _) _) -> do- let rev = getString "rev" params- sha256 = getString "sha256" params+ Fix (NAbs (ParamSet _ _ pset) _) -> do+ let rev = getString "rev" pset+ sha256 = getString "sha256" pset consider "fetchTarball expression" (pure $ parseNixTextLoc [text| builtins.fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";@@ -64,26 +64,27 @@ when (null files) $ errorWithoutStackTrace $ "Directory " <> show dir <> " does not have any files"- for_ files $ \file -> do+ for_ files $ \file -> unless ("azure-cli/default.nix" `isSuffixOf` file || "os-specific/linux/udisks/2-default.nix" `isSuffixOf` file) $ do -- Parse and deepseq the resulting expression tree, to ensure the -- parser is fully executed.- _ <- consider file (parseNixFileLoc file) $ Exc.evaluate . force- pass+ _ <- consider (coerce file) (parseNixFileLoc (coerce file)) $ Exc.evaluate . force+ stub v -> fail $ "Unexpected parse from default.nix: " <> show v where- getExpr k m = let Just (Just r) = lookup k m in r+ getExpr k m =+ let Just (Just r) = lookup k m in+ r getString k m =- let Fix (NStr (DoubleQuoted [Plain str])) = getExpr k m in str+ let Fix (NStr (DoubleQuoted [Plain str])) = getExpr k m in+ str consider path action k =- do- x <- action- either- (\ err -> errorWithoutStackTrace $ "Parsing " <> path <> " failed: " <> show err)- k- x+ either+ (\ err -> errorWithoutStackTrace $ "Parsing " <> coerce @Path path <> " failed: " <> show err)+ k+ =<< action main :: IO () main = do@@ -94,18 +95,18 @@ prettyTestsEnv <- lookupEnv "PRETTY_TESTS" pwd <- getCurrentDirectory- setEnv "NIX_REMOTE" (pwd <> "/real-store")- setEnv "NIX_DATA_DIR" (pwd <> "/data")+ setEnv "NIX_REMOTE" $ pwd <> "/real-store"+ setEnv "NIX_DATA_DIR" $ pwd <> "/data" defaultMain $ testGroup "hnix" $ [ ParserTests.tests , EvalTests.tests , PrettyTests.tests- , ReduceExprTests.tests] <>- [ PrettyParseTests.tests- (fromIntegral (read (fromMaybe "0" prettyTestsEnv) :: Int)) ] <>- [ evalComparisonTests ] <>- [ testCase "Nix language tests present" ensureLangTestsPresent+ , ReduceExprTests.tests+ , PrettyParseTests.tests $ fromIntegral $ read @Int $ fromMaybe "0" prettyTestsEnv+ , evalComparisonTests+ , testCase "Nix language tests present" ensureLangTestsPresent , nixLanguageTests ] <> [ testCase "Nixpkgs parses without errors" ensureNixpkgsCanParse- | isJust nixpkgsTestsEnv ]+ | isJust nixpkgsTestsEnv+ ]
tests/NixLanguageTests.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ScopedTypeVariables #-} module NixLanguageTests (genTests) where @@ -11,7 +10,6 @@ import qualified Data.Set as Set import qualified Data.String as String import qualified Data.Text as Text-import qualified Data.Text.IO as Text import Data.Time import GHC.Exts import Nix.Lint@@ -22,8 +20,7 @@ import Nix.String import Nix.XML import qualified Options.Applicative as Opts-import System.Environment-import System.FilePath+import System.Environment ( setEnv ) import System.FilePath.Glob ( compile , globDir1 )@@ -61,118 +58,173 @@ newFailingTests = Set.fromList [ "eval-okay-hash" , "eval-okay-hashfile"- , "eval-okay-path"+ , "eval-okay-path" -- #128 , "eval-okay-types" , "eval-okay-fromTOML"- , "eval-okay-context-introspection" ] +-- | Upstream tests that test cases that HNix disaded as a misfeature that is used so rarely+-- that it more effective to fix it & lint it out of existance.+deprecatedRareNixQuirkTests :: Set String+deprecatedRareNixQuirkTests = Set.fromList $+ one+ -- A rare quirk of Nix that is proper to fix&enforce then to support (see git commit history)+ "eval-okay-strings-as-attrs-names"+ genTests :: IO TestTree-genTests = do- testFiles <-- sort- -- jww (2018-05-07): Temporarily disable this test until #128 is fixed.- . filter ((`Set.notMember` newFailingTests) . takeBaseName)- . filter ((/= ".xml") . takeExtension)- <$> globDir1 (compile "*-*-*.*") "data/nix/tests/lang"- let testsByName = groupBy (takeFileName . dropExtensions) testFiles- let testsByType = groupBy testType (Map.toList testsByName)- let testGroups = fmap mkTestGroup (Map.toList testsByType)- pure $ localOption (mkTimeout 2000000) $ testGroup- "Nix (upstream) language tests"- testGroups+genTests =+ do+ testFiles <- getTestFiles+ let+ testsGroupedByName :: Map Path [Path]+ testsGroupedByName = groupBy (takeFileName . dropExtensions) testFiles++ testsGroupedByTypeThenName :: Map [String] [(Path, [Path])]+ testsGroupedByTypeThenName = groupBy testType $ Map.toList testsGroupedByName++ testTree :: [TestTree]+ testTree = mkTestGroup <$> Map.toList testsGroupedByTypeThenName++ pure $+ localOption+ (mkTimeout 2000000)+ $ testGroup+ "Nix (upstream) language tests"+ testTree where- testType (fullpath, _files) = take 2 $ splitOn "-" $ takeFileName fullpath- mkTestGroup (kind, tests) =- testGroup (String.unwords kind) $ fmap (mkTestCase kind) tests- mkTestCase kind (basename, files) = testCase (takeFileName basename) $ do- time <- liftIO getCurrentTime- let opts = defaultOptions time- case kind of- ["parse", "okay"] -> assertParse opts $ the files- ["parse", "fail"] -> assertParseFail opts $ the files- ["eval" , "okay"] -> assertEval opts files- ["eval" , "fail"] -> assertEvalFail $ the files- _ -> fail $ "Unexpected: " <> show kind -assertParse :: Options -> FilePath -> Assertion+ getTestFiles :: IO [Path]+ getTestFiles = sortTestFiles <$> collectTestFiles+ where+ collectTestFiles :: IO [Path]+ collectTestFiles = coerce (globDir1 (compile "*-*-*.*") nixTestDir)++ sortTestFiles :: [Path] -> [Path]+ sortTestFiles =+ sort+ -- Disabling the not yet done tests cases.+ . filter withoutDisabledTests+ . filter withoutXml+ where+ withoutDisabledTests :: Path -> Bool+ withoutDisabledTests = (`Set.notMember` (newFailingTests `Set.union` deprecatedRareNixQuirkTests)) . takeBaseName++ withoutXml :: Path -> Bool+ withoutXml = (/= ".xml") . takeExtension++ testType :: (Path, b) -> [String]+ testType (fullpath, _files) = coerce (take 2 . splitOn "-") $ takeFileName fullpath++ mkTestGroup :: ([String], [(Path, [Path])]) -> TestTree+ mkTestGroup (tType, tests) =+ testGroup (String.unwords tType) $ mkTestCase <$> tests+ where+ mkTestCase :: (Path, [Path]) -> TestTree+ mkTestCase (basename, files) =+ testCase+ (coerce $ takeFileName basename)+ $ do+ time <- liftIO getCurrentTime+ let opts = defaultOptions time+ case tType of+ ["parse", "okay"] -> assertParse opts $ the files+ ["parse", "fail"] -> assertParseFail opts $ the files+ ["eval" , "okay"] -> assertEval opts files+ ["eval" , "fail"] -> assertEvalFail $ the files+ _ -> fail $ "Unexpected: " <> show tType+++assertParse :: Options -> Path -> Assertion assertParse _opts file =- do- x <- parseNixFileLoc file- either- (\ err -> assertFailure $ "Failed to parse " <> file <> ":\n" <> show err)- (const pass) -- pure $! runST $ void $ lint opts expr- x+ either+ (\ err -> assertFailure $ "Failed to parse " <> coerce file <> ":\n" <> show err)+ (const stub) -- pure $! runST $ void $ lint opts expr+ =<< parseNixFileLoc file -assertParseFail :: Options -> FilePath -> Assertion-assertParseFail opts file = do- eres <- parseNixFileLoc file- (`catch` \(_ :: SomeException) -> pass)- (either- (const pass)+assertParseFail :: Options -> Path -> Assertion+assertParseFail opts file =+ (`catch` \(_ :: SomeException) -> stub) $+ either+ (const stub) (\ expr -> do _ <- pure $! runST $ void $ lint opts expr- assertFailure $ "Unexpected success parsing `" <> file <> ":\nParsed value: " <> show expr+ assertFailure $ "Unexpected success parsing `" <> coerce file <> ":\nParsed value: " <> show expr )- eres- )+ =<< parseNixFileLoc file -assertLangOk :: Options -> FilePath -> Assertion-assertLangOk opts file = do- actual <- printNix <$> hnixEvalFile opts (file <> ".nix")- expected <- Text.readFile $ file <> ".exp"- assertEqual "" expected $ toText (actual <> "\n")+assertLangOk :: Options -> Path -> Assertion+assertLangOk opts fileBaseName =+ do+ actual <- printNix <$> hnixEvalFile opts (addNixExt fileBaseName)+ expected <- read fileBaseName ".exp"+ assertEqual mempty expected (actual <> "\n") -assertLangOkXml :: Options -> FilePath -> Assertion-assertLangOkXml opts file = do- actual <- stringIgnoreContext . toXML <$> hnixEvalFile- opts- (file <> ".nix")- expected <- Text.readFile $ file <> ".exp.xml"- assertEqual "" expected actual+assertLangOkXml :: Options -> Path -> Assertion+assertLangOkXml opts fileBaseName =+ do+ actual <- stringIgnoreContext . toXML <$> hnixEvalFile opts (addNixExt fileBaseName)+ expected <- read fileBaseName ".exp.xml"+ assertEqual mempty expected actual -assertEval :: Options -> [FilePath] -> Assertion-assertEval _opts files = do- time <- liftIO getCurrentTime- let opts = defaultOptions time- case delete ".nix" $ sort $ fmap takeExtensions files of- [] -> () <$ hnixEvalFile opts (name <> ".nix")- [".exp" ] -> assertLangOk opts name- [".exp.xml" ] -> assertLangOkXml opts name- [".exp.disabled"] -> pass- [".exp-disabled"] -> pass- [".exp", ".flags"] -> do- liftIO $ setEnv "NIX_PATH" "lang/dir4:lang/dir5"- flags <- Text.readFile (name <> ".flags")- let flags' | Text.last flags == '\n' = Text.init flags- | otherwise = flags- case- Opts.execParserPure- Opts.defaultPrefs- (nixOptionsInfo time)- (fixup (fmap toString (Text.splitOn " " flags')))- of- Opts.Failure err -> errorWithoutStackTrace $ "Error parsing flags from " <> name <> ".flags: " <> show err- Opts.Success opts' -> assertLangOk opts' name- Opts.CompletionInvoked _ -> fail "unused"- _ -> assertFailure $ "Unknown test type " <> show files+assertEval :: Options -> [Path] -> Assertion+assertEval _opts files =+ do+ time <- liftIO getCurrentTime+ let opts = defaultOptions time+ case delete ".nix" $ sort $ fromString @Text . takeExtensions <$> files of+ [] -> void $ hnixEvalFile opts (addNixExt name)+ [".exp" ] -> assertLangOk opts name+ [".exp.xml" ] -> assertLangOkXml opts name+ [".exp.disabled" ] -> stub+ [".exp-disabled" ] -> stub+ [".exp", ".flags"] ->+ do+ liftIO $ setEnv "NIX_PATH" "lang/dir4:lang/dir5"+ flags <- read name ".flags"+ let+ flags' :: Text+ flags' =+ bool+ id+ Text.init+ (Text.last flags == '\n')+ flags+ case runParserGetResult time flags' of+ Opts.Failure err -> errorWithoutStackTrace $ "Error parsing flags from " <> coerce name <> ".flags: " <> show err+ Opts.CompletionInvoked _ -> fail "unused"+ Opts.Success opts' -> assertLangOk opts' name+ _ -> assertFailure $ "Unknown test type " <> show files where- name =- "data/nix/tests/lang/" <> the (fmap (takeFileName . dropExtensions) files)+ runParserGetResult :: UTCTime -> Text -> Opts.ParserResult Options+ runParserGetResult time flags' =+ Opts.execParserPure+ Opts.defaultPrefs+ (nixOptionsInfo time)+ (fmap toString $ fixup $ Text.splitOn " " flags') - fixup ("--arg" : x : y : rest) = "--arg" : (x <> "=" <> y) : fixup rest+ name :: Path+ name = coerce nixTestDir <> the (takeFileName . dropExtensions <$> files)++ fixup :: [Text] -> [Text]+ fixup ("--arg" : x : y : rest) = "--arg" : (x <> "=" <> y) : fixup rest fixup ("--argstr" : x : y : rest) = "--argstr" : (x <> "=" <> y) : fixup rest- fixup (x : rest) = x : fixup rest+ fixup (x : rest) = x : fixup rest fixup [] = mempty -assertEvalFail :: FilePath -> Assertion-assertEvalFail file = (`catch` (\(_ :: SomeException) -> pass)) $ do- time <- liftIO getCurrentTime- evalResult <- printNix <$> hnixEvalFile (defaultOptions time) file- evalResult `seq`- assertFailure $- file- <> " should not evaluate.\nThe evaluation result was `"- <> evalResult- <> "`."+assertEvalFail :: Path -> Assertion+assertEvalFail file =+ (`catch` (\(_ :: SomeException) -> stub)) $+ do+ time <- liftIO getCurrentTime+ evalResult <- printNix <$> hnixEvalFile (defaultOptions time) file+ evalResult `seq` assertFailure $ "File: ''" <> coerce file <> "'' should not evaluate.\nThe evaluation result was `" <> toString evalResult <> "`."++nixTestDir :: FilePath+nixTestDir = "data/nix/tests/lang/"++addNixExt :: Path -> Path+addNixExt path = addExtension path ".nix"++read :: Path -> String -> IO Text+read path ext = readFile $ addExtension path ext
tests/ParserTests.hs view
@@ -1,13 +1,16 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RankNTypes #-}+{-# language QuasiQuotes #-}+{-# language TemplateHaskell #-}+{-# language RankNTypes #-}+{-# language ExtendedDefaultRules #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_GHC -Wno-missing-signatures #-}+{-# options_ghc -fno-warn-name-shadowing #-}+{-# options_ghc -Wno-missing-signatures #-}+{-# options_ghc -Wno-type-defaults #-} module ParserTests (tests) where +import Prelude hiding (($<)) import Data.Fix import NeatInterpolation (text) import Nix.Atoms@@ -19,314 +22,523 @@ import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.TH+import Prettyprinter.Render.String (renderString)+import Prettyprinter.Util (reflow) -case_constant_int = assertParseText "234" $ mkInt 234+default (NixLang) -case_constant_bool = do- assertParseText "true" $ mkBool True- assertParseText "false" $ mkBool False+-- * Tests -case_constant_bool_respects_attributes = do- assertParseText "true-foo" $ mkSym "true-foo"- assertParseText "false-bar" $ mkSym "false-bar" -case_constant_path = do- assertParseText "./." $ mkPath False "./."- assertParseText "./+-_/cdef/09ad+-" $ mkPath False "./+-_/cdef/09ad+-"- assertParseText "/abc" $ mkPath False "/abc"- assertParseText "../abc" $ mkPath False "../abc"- assertParseText "<abc>" $ mkPath True "abc"- assertParseText "<../cdef>" $ mkPath True "../cdef"- assertParseText "a//b" $ mkOper2 NUpdate (mkSym "a") (mkSym "b")- assertParseText "rec+def/cdef" $ mkPath False "rec+def/cdef"- assertParseText "a/b//c/def//<g> < def/d" $ mkOper2 NLt- (mkOper2 NUpdate (mkPath False "a/b") $ mkOper2 NUpdate- (mkPath False "c/def") (mkPath True "g"))- (mkPath False "def/d")- assertParseText "a'b/c" $ Fix $ NBinary NApp (mkSym "a'b") (mkPath False "/c")- assertParseText "a/b" $ mkPath False "a/b"- assertParseText "4/2" $ mkPath False "4/2"- assertParseFail "."- assertParseFail ".."- assertParseFail "/"- assertParseFail "a/"- assertParseFail "a/def/"- assertParseFail "~"- assertParseFail "~/"- assertParseText "~/a" $ mkPath False "~/a"- assertParseText "~/a/b" $ mkPath False "~/a/b"+-- ** Literals -case_constant_uri = do- assertParseText "a:a" $ mkStr "a:a"- assertParseText "http://foo.bar" $ mkStr "http://foo.bar"- assertParseText "a+de+.adA+-:%%%ads%5asdk&/" $ mkStr "a+de+.adA+-:%%%ads%5asdk&/"- assertParseText "rec+def:c" $ mkStr "rec+def:c"- assertParseText "f.foo:bar" $ mkStr "f.foo:bar"- assertParseFail "http://foo${\"bar\"}"- assertParseFail ":bcdef"- assertParseFail "a%20:asda"- assertParseFail ".:adasd"- assertParseFail "+:acdcd"+case_constant_int =+ checks+ ( mkInt 234+ , "234"+ ) -case_simple_set = do- assertParseText "{ a = 23; b = 4; }" $ Fix $ NSet NNonRecursive- [ NamedVar (mkSelector "a") (mkInt 23) nullPos- , NamedVar (mkSelector "b") (mkInt 4) nullPos- ]- assertParseFail "{ a = 23 }"+case_constant_bool =+ checks+ ( mkBool True+ , "true"+ )+ ( mkBool False+ , "false"+ ) -case_set_inherit = do- assertParseText "{ e = 3; inherit a b; }" $ Fix $ NSet NNonRecursive- [ NamedVar (mkSelector "e") (mkInt 3) nullPos- , Inherit Nothing (StaticKey <$> ["a", "b"]) nullPos- ]- assertParseText "{ inherit; }" $ Fix $ NSet NNonRecursive [ Inherit Nothing mempty nullPos ]+case_constant_bool_respects_attributes =+ invariantVals+ "true-foo"+ "false-bar" -case_set_scoped_inherit = assertParseText "{ inherit (a) b c; e = 4; inherit(a)b c; }" $ Fix $ NSet NNonRecursive- [ Inherit (pure (mkSym "a")) (StaticKey <$> ["b", "c"]) nullPos- , NamedVar (mkSelector "e") (mkInt 4) nullPos- , Inherit (pure (mkSym "a")) (StaticKey <$> ["b", "c"]) nullPos- ]+case_constant_path_invariants =+ knownAs (staysInvariantUnder (mkRelPath . toString))+ "./."+ "./+-_/cdef/09ad+-"+ "/abc"+ "../abc"+ "~/a"+ "~/a/b"+ "a/b"+ "4/2"+ "rec+def/cdef" -case_set_rec = assertParseText "rec { a = 3; b = a; }" $ Fix $ NSet NRecursive- [ NamedVar (mkSelector "a") (mkInt 3) nullPos- , NamedVar (mkSelector "b") (mkSym "a") nullPos- ]+case_constant_path =+ checks+ ( var "a'b" @@ mkRelPath "/c"+ , "a'b/c"+ )+ ( mkRelPath "a/b" $// mkRelPath "c/def" $// mkEnvPath "g" $< mkRelPath "def/d"+ , "a/b//c/def//<g> < def/d"+ )+ ( mkEnvPath "abc"+ , "<abc>"+ )+ ( mkEnvPath "../cdef"+ , "<../cdef>"+ )+ ( var "a" $// var "b"+ , "a//b"+ ) -case_set_complex_keynames = do- assertParseText "{ \"\" = null; }" $ Fix $ NSet NNonRecursive- [ NamedVar (DynamicKey (Plain (DoubleQuoted mempty)) :| mempty) mkNull nullPos ]- assertParseText "{ a.b = 3; a.c = 4; }" $ Fix $ NSet NNonRecursive- [ NamedVar (StaticKey "a" :| [StaticKey "b"]) (mkInt 3) nullPos- , NamedVar (StaticKey "a" :| [StaticKey "c"]) (mkInt 4) nullPos- ]- assertParseText "{ ${let a = \"b\"; in a} = 4; }" $ Fix $ NSet NNonRecursive- [ NamedVar (DynamicKey (Antiquoted letExpr) :| mempty) (mkInt 4) nullPos ]- assertParseText "{ \"a${let a = \"b\"; in a}c\".e = 4; }" $ Fix $ NSet NNonRecursive- [ NamedVar (DynamicKey (Plain str) :| [StaticKey "e"]) (mkInt 4) nullPos ]+case_constant_path_syntax_mistakes =+ mistakes+ "."+ ".."+ "/"+ "a/"+ "a/def/"+ "~"+ "~/"++case_constant_uri =+ knownAs (staysInvariantUnder mkStr)+ "a:a"+ "http://foo.bar"+ "a+de+.adA+-:%%%ads%5asdk&/"+ "rec+def:c"+ "f.foo:bar"+++case_constant_uri_syntax_mistakes =+ mistakes+ "http://foo${\"bar\"}"+ ":bcdef"+ "a%20:asda"+ ".:adasd"+ "+:acdcd"+++-- *** Special chars in vals++case_identifier_special_chars =+ invariantVals+ "_a"+ "a_b"+ "a'b"+ "a''b"+ "a-b"+ "a--b"+ "a12a"++case_identifier_special_chars_syntax_mistakes =+ mistakes+ ".a"+ "'a"++-- ** Sets++-- *** Non-recursive sets++case_simple_set =+ checks+ ( mkNonRecSet+ [ "a" $= mkInt 23+ , "b" $= mkInt 4+ ]+ , "{ a = 23; b = 4; }"+ )++case_simple_set_syntax_mistakes =+ mistakes+ "{ a = 23 }"++case_set_complex_keynames =+ checks+ ( mkNonRecSet $+ one (NamedVar (one (DynamicKey (Plain (DoubleQuoted mempty)))) mkNull nullPos)+ , "{ \"\" = null; }"+ )+ ( mkNonRecSet+ [ NamedVar (StaticKey "a" :| one (StaticKey "b")) (mkInt 3) nullPos+ , NamedVar (StaticKey "a" :| one (StaticKey "c")) (mkInt 4) nullPos+ ]+ , "{ a.b = 3; a.c = 4; }"+ )+ ( mkNonRecSet $+ one (NamedVar (one (DynamicKey (Antiquoted letExpr))) (mkInt 4) nullPos)+ , "{ ${let a = \"b\"; in a} = 4; }"+ )+ ( mkNonRecSet $+ one (NamedVar (DynamicKey (Plain str) :| one (StaticKey "e")) (mkInt 4) nullPos)+ , "{ \"a${let a = \"b\"; in a}c\".e = 4; }"+ ) where- letExpr = Fix $ NLet [NamedVar (mkSelector "a") (mkStr "b") nullPos] (mkSym "a")+ letExpr = mkLets (one ("a" $= mkStr "b")) (var "a") str = DoubleQuoted [Plain "a", Antiquoted letExpr, Plain "c"] -case_set_inherit_direct = assertParseText "{ inherit ({a = 3;}); }" $ Fix $ NSet NNonRecursive- [ Inherit (pure $ Fix $ NSet NNonRecursive [NamedVar (mkSelector "a") (mkInt 3) nullPos]) mempty nullPos- ] -case_inherit_selector = do- assertParseText "{ inherit \"a\"; }" $ Fix $ NSet NNonRecursive- [Inherit Nothing [DynamicKey (Plain (DoubleQuoted [Plain "a"]))] nullPos]- assertParseFail "{ inherit a.x; }"+-- *** Recursivity in sets -case_int_list = assertParseText "[1 2 3]" $ Fix $ NList- [ mkInt i | i <- [1,2,3] ]+case_set_rec =+ checks+ ( mkRecSet+ [ "a" $= mkInt 3+ , "b" $= var "a"+ ]+ , "rec { a = 3; b = a; }"+ ) -case_int_null_list = assertParseText "[1 2 3 null 4]" $ Fix (NList (fmap (Fix . NConstant) [NInt 1, NInt 2, NInt 3, NNull, NInt 4])) -case_mixed_list = do- assertParseText "[{a = 3;}.a (if true then null else false) null false 4 [] c.d or null]" $ Fix $ NList- [ Fix (NSelect (Fix (NSet NNonRecursive [NamedVar (mkSelector "a") (mkInt 3) nullPos]))- (mkSelector "a") Nothing)- , Fix (NIf (mkBool True) mkNull (mkBool False))- , mkNull, mkBool False, mkInt 4, Fix (NList mempty)- , Fix (NSelect (mkSym "c") (mkSelector "d") (pure mkNull))- ]- assertParseFail "[if true then null else null]"- assertParseFail "[a ? b]"- assertParseFail "[a : a]"- assertParseFail "[${\"test\")]"+-- *** Inheritance -case_simple_lambda = assertParseText "a: a" $ Fix $ NAbs (Param "a") (mkSym "a")+case_set_inherit =+ checks+ ( mkNonRecSet+ [ "e" $= mkInt 3+ , inherit ["a", "b"]+ ]+ , "{ e = 3; inherit a b; }"+ )+ ( mkNonRecSet $ one $ inherit mempty+ , "{ inherit; }"+ ) -case_lambda_or_uri = do- assertParseText "a :b" $ Fix $ NAbs (Param "a") (mkSym "b")- assertParseText "a c:def" $ Fix $ NBinary NApp (mkSym "a") (mkStr "c:def")- assertParseText "c:def: c" $ Fix $ NBinary NApp (mkStr "c:def:") (mkSym "c")- assertParseText "a:{}" $ Fix $ NAbs (Param "a") $ Fix $ NSet NNonRecursive mempty- assertParseText "a:[a]" $ Fix $ NAbs (Param "a") $ Fix $ NList [mkSym "a"]- assertParseFail "def:"+case_set_scoped_inherit =+ checks+ ( mkNonRecSet $+ (\ x -> [x, "e" $= mkInt 4, x]) $+ inheritFrom (var "a") ["b", "c"]+ , "{ inherit (a) b c; e = 4; inherit(a)b c; }"+ ) -case_lambda_pattern = do- assertParseText "{b, c ? 1}: b" $- Fix $ NAbs (fixed args mempty) (mkSym "b")- assertParseText "{ b ? x: x }: b" $- Fix $ NAbs (fixed args2 mempty) (mkSym "b")- assertParseText "a@{b,c ? 1}: b" $- Fix $ NAbs (fixed args (pure "a")) (mkSym "b")- assertParseText "{b,c?1}@a: c" $- Fix $ NAbs (fixed args (pure "a")) (mkSym "c")- assertParseText "{b,c?1,...}@a: c" $- Fix $ NAbs (variadic vargs (pure "a")) (mkSym "c")- assertParseText "{...}: 1" $- Fix $ NAbs (variadic mempty mempty) (mkInt 1)- assertParseFail "a@b: a"- assertParseFail "{a}@{b}: a"+case_set_inherit_direct =+ checks+ ( mkNonRecSet $ one (inheritFrom (mkNonRecSet $ one ("a" $= mkInt 3)) mempty)+ , "{ inherit ({a = 3;}); }"+ )++case_inherit_selector_syntax_mistakes =+ mistakes+ "{ inherit a.x; }"+ -- A rare quirk of Nix that is proper to fix then to support (see git commit history)+ -- (old parser test result was):+ -- mkNonRecSet [inherit [DynamicKey (Plain (DoubleQuoted [Plain "a"]))]],+ "{ inherit \"a\"; }"+++-- ** Lists++case_int_list =+ checks+ ( mkList $ mkInt <$> [1,2,3]+ , "[1 2 3]"+ )++case_int_null_list =+ checks+ ( mkList (mkConst <$> [NInt 1, NInt 2, NInt 3, NNull, NInt 4])+ , "[1 2 3 null 4]"+ )++case_mixed_list =+ checks+ ( mkList+ [ mkNonRecSet (one $ "a" $= mkInt 3) @. "a"+ , mkIf (mkBool True) mkNull (mkBool False)+ , mkNull+ , mkBool False+ , mkInt 4+ , emptyList+ , (@.<|>) (var "c") "d" mkNull+ ]+ , "[{a = 3;}.a (if true then null else false) null false 4 [] c.d or null]"+ )++case_mixed_list_syntax_mistakes =+ mistakes+ "[if true then null else null]"+ "[a ? b]"+ "[a : a]"+ "[${\"test\")]"+++-- ** Lambdas++case_simple_lambda =+ checks+ ( mkFunction (Param "a") (var "a")+ , "a: a"+ )++case_lambda_or_uri =+ checks+ ( mkFunction (Param "a") $ var "b"+ , "a :b"+ )+ ( var "a" @@ mkStr "c:def"+ , "a c:def"+ )+ ( mkStr "c:def:" @@ var "c"+ , "c:def: c"+ )+ ( mkFunction (Param "a") emptySet+ , "a:{}"+ )+ ( mkFunction (Param "a") $ mkList $ one $ var "a"+ , "a:[a]"+ )++case_lambda_or_uri_syntax_mistakes =+ mistakes+ "def:"++case_lambda_pattern =+ checks+ ( mkFunction (mkParamSet args) $ var "b"+ , "{b, c ? 1}: b"+ -- Fix (NAbs (ParamSet [("b",Nothing),("c",Just (Fix (NConstant (NInt 1))))] False Nothing) (Fix (NSym "b")))+ )+ ( mkFunction (mkParamSet args2) $ var "b"+ , "{ b ? x: x }: b"+ )+ ( mkFunction (mkNamedParamSet "a" args) $ var "b"+ , "a@{b,c ? 1}: b"+ )+ ( mkFunction (mkNamedParamSet "a" args) $ var "c"+ , "{b,c?1}@a: c"+ )+ ( mkFunction (mkNamedVariadicParamSet "a" vargs) $ var "c"+ , "{b,c?1,...}@a: c"+ )+ ( mkFunction (mkVariadicParamSet mempty) $ mkInt 1+ , "{...}: 1"+ ) where- fixed args = ParamSet args False- variadic args = ParamSet args True- args = [("b", Nothing), ("c", pure $ mkInt 1)]+ args = [("b", Nothing), ("c", pure $ mkInt 1)] vargs = [("b", Nothing), ("c", pure $ mkInt 1)]- args2 = [("b", pure lam)]- lam = Fix $ NAbs (Param "x") (mkSym "x")+ args2 = one ("b", pure lam)+ lam = mkFunction (Param "x") $ var "x" -case_lambda_app_int = assertParseText "(a: a) 3" $ Fix (NBinary NApp lam int) where- int = mkInt 3- lam = Fix (NAbs (Param "a") asym)- asym = mkSym "a"+case_lambda_pattern_syntax_mistakes =+ mistakes+ "a@b: a"+ "{a}@{b}: a" -case_simple_let = do- assertParseText "let a = 4; in a" $ Fix (NLet binds $ mkSym "a")- assertParseFail "let a = 4 in a"- where- binds = [NamedVar (mkSelector "a") (mkInt 4) nullPos]+case_lambda_app_int =+ checks+ ( mkFunction (Param "a") (var "a") @@ mkInt 3+ , "(a: a) 3"+ ) -case_let_body = assertParseText "let { body = 1; }" letBody- where- letBody = Fix $ NSelect aset (mkSelector "body") Nothing- aset = Fix $ NSet NRecursive [NamedVar (mkSelector "body") (mkInt 1) nullPos] -case_nested_let = do- assertParseText "let a = 4; in let b = 5; in a" $ Fix $ NLet- [NamedVar (mkSelector "a") (mkInt 4) nullPos]- (Fix $ NLet [NamedVar (mkSelector "b") (mkInt 5) nullPos] $ mkSym "a")- assertParseFail "let a = 4; let b = 3; in b"+-- ** Let -case_let_scoped_inherit = do- assertParseText "let a = null; inherit (b) c; in c" $ Fix $ NLet- [ NamedVar (mkSelector "a") mkNull nullPos- , Inherit (pure $ mkSym "b") [StaticKey "c"] nullPos ]- (mkSym "c")- assertParseFail "let inherit (b) c in c"+case_simple_let =+ checks+ ( mkLets (one $ "a" $= mkInt 4) $ var "a"+ , "let a = 4; in a"+ ) -case_if = do- assertParseText "if true then true else false" $- Fix $ NIf (mkBool True) (mkBool True) (mkBool False)- assertParseFail "if true then false"- assertParseFail "else"- assertParseFail "if true then false else"- assertParseFail "if true then false else false else"- assertParseFail "1 + 2 then"+case_simple_let_syntax_mistakes =+ mistakes+ "let a = 4 in a" -case_identifier_special_chars = do- assertParseText "_a" $ mkSym "_a"- assertParseText "a_b" $ mkSym "a_b"- assertParseText "a'b" $ mkSym "a'b"- assertParseText "a''b" $ mkSym "a''b"- assertParseText "a-b" $ mkSym "a-b"- assertParseText "a--b" $ mkSym "a--b"- assertParseText "a12a" $ mkSym "a12a"- assertParseFail ".a"- assertParseFail "'a"+case_let_body =+ checks+ ( mkRecSet (one $ "body" $= mkInt 1) @. "body"+ , "let { body = 1; }"+ ) -case_identifier_keyword_prefix = do- assertParseText "true-name" $ mkSym "true-name"- assertParseText "trueName" $ mkSym "trueName"- assertParseText "null-name" $ mkSym "null-name"- assertParseText "nullName" $ mkSym "nullName"- assertParseText "[ null-name ]" $ mkList [ mkSym "null-name" ]+case_nested_let =+ checks+ ( mkLets (one $ "a" $= mkInt 4) $+ mkLets (one $ "b" $= mkInt 5) $ var "a"+ , "let a = 4; in let b = 5; in a"+ ) -makeTextParseTest str = assertParseText ("\"" <> str <> "\"") $ mkStr str+case_nested_let_syntax_mistakes =+ mistakes+ "let a = 4; let b = 3; in b" -case_simple_string = traverse_ makeTextParseTest ["abcdef", "a", "A", " a a ", ""]+case_let_scoped_inherit =+ checks+ ( mkLets+ [ "a" $= mkNull+ , inheritFrom (var "b") $ one "c"+ ]+ $ var "c"+ , "let a = null; inherit (b) c; in c"+ ) -case_string_dollar = traverse_ makeTextParseTest ["a$b", "a$$b", "$cdef", "gh$i"]+case_let_scoped_inherit_syntax_mistakes =+ mistakes+ "let inherit (b) c in c" -case_string_escape = do- assertParseText "\"\\$\\n\\t\\r\\\\\"" $ mkStr "$\n\t\r\\"- assertParseText "\" \\\" \\' \"" $ mkStr " \" ' " -case_string_antiquote = do- assertParseText "\"abc${ if true then \"def\" else \"abc\" } g\"" $- Fix $ NStr $ DoubleQuoted- [ Plain "abc"- , Antiquoted $ Fix $ NIf (mkBool True) (mkStr "def") (mkStr "abc")- , Plain " g"- ]- assertParseText "\"\\${a}\"" $ mkStr "${a}"- assertParseFail "\"a"- assertParseFail "${true}"- assertParseFail "\"${true\""+-- ** If -case_select = do- assertParseText "a . e .di. f" $ Fix $ NSelect (mkSym "a")- (StaticKey "e" :| [StaticKey "di", StaticKey "f"])- Nothing- assertParseText "a.e . d or null" $ Fix $ NSelect (mkSym "a")- (StaticKey "e" :| [StaticKey "d"])- (pure mkNull)- assertParseText "{}.\"\"or null" $ Fix $ NSelect (Fix (NSet NNonRecursive mempty))- (DynamicKey (Plain (DoubleQuoted mempty)) :| mempty) (pure mkNull)- assertParseText "{ a = [1]; }.a or [2] ++ [3]" $ Fix $ NBinary NConcat- (Fix (NSelect- (Fix (NSet NNonRecursive [NamedVar (StaticKey "a" :| mempty)- (Fix (NList [Fix (NConstant (NInt 1))]))- nullPos]))- (StaticKey "a" :| mempty)- (pure (Fix (NList [Fix (NConstant (NInt 2))])))))- (Fix (NList [Fix (NConstant (NInt 3))]))+case_if =+ checks+ ( mkIf (mkBool True) (mkBool True) (mkBool False)+ , "if true then true else false"+ ) -case_select_path = do- assertParseText "f ./." $ Fix $ NBinary NApp (mkSym "f") (mkPath False "./.")- assertParseText "f.b ../a" $ Fix $ NBinary NApp select (mkPath False "../a")- assertParseText "{}./def" $ Fix $ NBinary NApp (Fix (NSet NNonRecursive mempty)) (mkPath False "./def")- assertParseText "{}.\"\"./def" $ Fix $ NBinary NApp- (Fix $ NSelect (Fix (NSet NNonRecursive mempty)) (DynamicKey (Plain (DoubleQuoted mempty)) :| mempty) Nothing)- (mkPath False "./def")- where select = Fix $ NSelect (mkSym "f") (mkSelector "b") Nothing+case_if_syntax_mistakes =+ mistakes+ "if true then false"+ "else"+ "if true then false else"+ "if true then false else false else"+ "1 + 2 then" -case_select_keyword = do- assertParseText "{ false = \"foo\"; }" $ Fix $ NSet NNonRecursive [NamedVar (mkSelector "false") (mkStr "foo") nullPos] -case_fun_app = do- assertParseText "f a b" $ Fix $ NBinary NApp (Fix $ NBinary NApp (mkSym "f") (mkSym "a")) (mkSym "b")- assertParseText "f a.x or null" $ Fix $ NBinary NApp (mkSym "f") $ Fix $- NSelect (mkSym "a") (mkSelector "x") (pure mkNull)- assertParseFail "f if true then null else null"+-- ** Literal expressions in vals -case_indented_string = do- assertParseText "''a''" $ mkIndentedStr 0 "a"- assertParseText "''\n foo\n bar''" $ mkIndentedStr 2 "foo\nbar"- assertParseText "'' ''" $ mkIndentedStr 0 ""- assertParseText "'''''''" $ mkIndentedStr 0 "''"- assertParseText "'' ${null}\n a${null}''" $ Fix $ NStr $ Indented 3- [ Antiquoted mkNull- , Plain "\na"- , Antiquoted mkNull- ]- assertParseFail "'''''"- assertParseFail "'' '"+case_identifier_keyword_prefix_invariants =+ invariantVals+ "true-name"+ "trueName"+ "null-name"+ "nullName" -case_indented_string_escape = assertParseText- "'' ''\\n ''\\t ''\\\\ ''${ \\ \\n ' ''' ''" $- mkIndentedStr 1 "\n \t \\ ${ \\ \\n ' '' "+case_identifier_keyword_prefix =+ checks+ ( mkList $ one $ var "null-name"+ , "[ null-name ]"+ ) -case_operator_fun_app = do- assertParseText "a ++ b" $ mkOper2 NConcat (mkSym "a") (mkSym "b")- assertParseText "a ++ f b" $ mkOper2 NConcat (mkSym "a") $ Fix $ NBinary NApp- (mkSym "f") (mkSym "b") -case_operators = do- assertParseText "1 + 2 - 3" $ mkOper2 NMinus- (mkOper2 NPlus (mkInt 1) (mkInt 2)) (mkInt 3)- assertParseFail "1 + if true then 1 else 2"- assertParseText "1 + (if true then 2 else 3)" $ mkOper2 NPlus (mkInt 1) $ Fix $ NIf- (mkBool True) (mkInt 2) (mkInt 3)- assertParseText "{ a = 3; } // rec { b = 4; }" $ mkOper2 NUpdate- (Fix $ NSet NNonRecursive [NamedVar (mkSelector "a") (mkInt 3) nullPos])- (Fix $ NSet NRecursive [NamedVar (mkSelector "b") (mkInt 4) nullPos])- assertParseText "--a" $ mkOper NNeg $ mkOper NNeg $ mkSym "a"- assertParseText "a - b - c" $ mkOper2 NMinus- (mkOper2 NMinus (mkSym "a") (mkSym "b")) $- mkSym "c"- assertParseText "foo<bar" $ mkOper2 NLt (mkSym "foo") (mkSym "bar")- assertParseFail "+ 3"- assertParseFail "foo +"+-- ** Strings -case_comments =- do- Right expected <- parseNixFile "data/let.nix"- assertParseFile "let-comments-multiline.nix" expected- assertParseFile "let-comments.nix" expected+invariantString str =+ checks+ ( mkStr str+ , "\"" <> str <> "\""+ ) +case_simple_string =+ knownAs invariantString+ "abcdef"+ "a"+ "A"+ " a a "+ ""++case_string_dollar =+ knownAs invariantString+ "a$b"+ "a$$b"+ "$cdef"+ "gh$i"++case_string_escape =+ checks+ ( mkStr "$\n\t\r\\"+ , "\"\\$\\n\\t\\r\\\\\""+ )+ ( mkStr " \" ' "+ , "\" \\\" \\' \""+ )++case_string_antiquote =+ checks+ ( Fix $ NStr $ DoubleQuoted+ [ Plain "abc"+ , Antiquoted $ mkIf (mkBool True) (mkStr "def") (mkStr "abc")+ , Plain " g"+ ]+ , "\"abc${ if true then \"def\" else \"abc\" } g\""+ )+ ( mkStr "${a}"+ , "\"\\${a}\""+ )++case_string_antiquote_syntax_mistakes =+ mistakes+ "\"a"+ "${true}"+ "\"${true\""+++-- *** Indented string++case_indented_string =+ checks+ ( mkIndentedStr 0 "a"+ , "''a''"+ )+ ( mkIndentedStr 2 "foo\nbar"+ , "''\n foo\n bar''"+ )+ ( mkIndentedStr 0 mempty+ , "'' ''"+ )+ ( mkIndentedStr 0 "''"+ , "'''''''"+ )+ ( Fix $ NStr $ Indented 3+ [ Antiquoted mkNull+ , Plain "\na"+ , Antiquoted mkNull+ ]+ , "'' ${null}\n a${null}''"+ )++case_indented_string_syntax_mistakes =+ mistakes+ "'''''"+ "'' '"++case_indented_string_escape =+ checks+ ( mkIndentedStr 1 "\n \t \\ ${ \\ \\n ' '' "+ , "'' ''\\n ''\\t ''\\\\ ''${ \\ \\n ' ''' ''"+ )++-- ** Selection++case_select =+ checks+ ( Fix $ NSelect Nothing (var "a") (StaticKey "e" :| [StaticKey "di", StaticKey "f"])+ , "a . e .di. f"+ )+ ( Fix $ NSelect (pure mkNull) (var "a")+ (StaticKey "e" :| one (StaticKey "d"))+ , "a.e . d or null"+ )+ ( Fix $ NSelect (pure mkNull) emptySet+ (one $ DynamicKey (Plain $ DoubleQuoted mempty))+ , "{}.\"\"or null"+ )+ ( Fix $ NBinary NConcat+ ((@.<|>)+ (mkNonRecSet $+ one $+ NamedVar+ (mkSelector "a")+ (mkList $ one $ mkInt 1)+ nullPos+ )+ "a"+ (mkList $ one $ mkInt 2)+ )+ (mkList $ one $ mkInt 3)+ , "{ a = [1]; }.a or [2] ++ [3]"+ )++case_select_path =+ checks+ ( var "f" @@ mkRelPath "./."+ , "f ./."+ )+ ( var "f" @. "b" @@ mkRelPath "../a"+ , "f.b ../a"+ )+ ( emptySet @@ mkRelPath "./def"+ , "{}./def"+ )+ ( Fix (NSelect Nothing emptySet $ one $ DynamicKey $ Plain $ DoubleQuoted mempty) @@ mkRelPath "./def"+ , "{}.\"\"./def"+ )++case_select_keyword =+ checks+ ( mkNonRecSet $ one $ "false" $= mkStr "foo"+ , "{ false = \"foo\"; }"+ )+ case_select_or_precedence = assertParsePrint [text|let matchDef = def: matcher:@@ -357,39 +569,101 @@ in (matcher.case or null).foo (v.case); in null|] +-- ** Function application++case_fun_app =+ checks+ ( var "f" @@ var "a" @@ var "b"+ , "f a b"+ )+ ( var "f" @@ (@.<|>) (var "a") "x" mkNull+ , "f a.x or null"+ )++case_fun_app_syntax_mistakes =+ mistakes+ "f if true then null else null"+++-- ** Operators++case_operator_fun_app =+ checks+ ( var "a" $++ var "b"+ , "a ++ b"+ )+ ( var "a" $++ var "f" @@ var "b"+ , "a ++ f b"+ )++case_operators =+ checks+ ( mkInt 1 $+ mkInt 2 $- mkInt 3+ , "1 + 2 - 3"+ )+ ( mkInt 1 $+ mkIf (mkBool True) (mkInt 2) (mkInt 3)+ , "1 + (if true then 2 else 3)"+ )+ ( mkNonRecSet (one $ "a" $= mkInt 3) $// mkRecSet (one $ "b" $= mkInt 4)+ , "{ a = 3; } // rec { b = 4; }"+ )+ ( mkNeg $ mkNeg $ var "a"+ , "--a"+ )+ ( var "a" $- var "b" $- var "c"+ , "a - b - c"+ )+ ( var "foo" $< var "bar"+ , "foo<bar"+ )++case_operators_syntax_mistakes =+ mistakes+ "+ 3"+ "foo +"+ "1 + if true then 1 else 2"+++-- ** Comments++case_comments =+ do+ Right expected <- parseNixFile "data/let.nix"+ assertParseFile "let-comments-multiline.nix" expected+ assertParseFile "let-comments.nix" expected+++-- ** Location+ case_simpleLoc = let- mkSPos l c = SourcePos "<string>" (mkPos l) (mkPos c)- mkSpan l1 c1 l2 c2 = SrcSpan (mkSPos l1 c1) (mkSPos l2 c2)+ mkSPos = on (SourcePos "<string>") mkPos+ mkSpan = on SrcSpan (uncurry mkSPos) in assertParseTextLoc [text|let foo = bar baz "qux"; in foo |]- (Fix- (NLet_- (mkSpan 1 1 4 7)- [ NamedVar- (StaticKey "foo" :| [])- (Fix- (NBinary_- (mkSpan 2 7 3 15)- NApp- (Fix- (NBinary_ (mkSpan 2 7 3 9)- NApp- (Fix (NSym_ (mkSpan 2 7 2 10) "bar"))- (Fix (NSym_ (mkSpan 3 6 3 9) "baz"))- )- )- (Fix (NStr_ (mkSpan 3 10 3 15) (DoubleQuoted [Plain "qux"])))- )+ (NLetAnn+ (mkSpan (1, 1) (4, 7))+ (one $+ NamedVar+ (one $ StaticKey "foo")+ (NBinaryAnn+ (mkSpan (2, 7) (3, 15))+ NApp+ (NBinaryAnn+ (mkSpan (2, 7) (3, 9))+ NApp+ (NSymAnn (mkSpan (2, 7) (2, 10)) "bar")+ (NSymAnn (mkSpan (3, 6) (3, 9 )) "baz") )- (mkSPos 2 1)- ]- (Fix (NSym_ (mkSpan 4 4 4 7) "foo"))+ (NStrAnn (mkSpan (3, 10) (3, 15)) $ DoubleQuoted $ one $ Plain "qux")+ )+ (mkSPos 2 1) )+ (NSymAnn (mkSpan (4, 4) (4, 7)) "foo") ) @@ -398,12 +672,42 @@ --------------------------------------------------------------------------------- -assertParseText :: Text -> NExpr -> Assertion-assertParseText str expected =+-- * Helpers++var = mkSym++invariantVal = staysInvariantUnder var++staysInvariantUnder :: (NixLang -> ExpectedHask) -> NixLang -> Assertion+staysInvariantUnder f v =+ (<=>) (f v) v++type NixLang = Text+type ExpectedHask = NExpr++(<=>) :: ExpectedHask -> NixLang -> Assertion+(<=>) = assertParseText++throwParseError :: forall ann . Text -> Text -> Doc ann -> Assertion+throwParseError entity expr err =+ assertFailure $+ renderString $+ layoutSmart Prettyprinter.defaultLayoutOptions $+ nest 2 $+ vsep+ [ mempty+ , "Unexpected fail parsing " <> reflow entity <> ":"+ , nest 2 $ vsep+ [ "Expression:"+ , reflow expr+ , "Error: " <> nest 2 err+ ]+ ]++assertParseText :: ExpectedHask -> NixLang -> Assertion+assertParseText expected str = either- (\ err ->- assertFailure $ toString $ "Unexpected fail parsing `" <> str <> "':\n" <> show err- )+ (throwParseError "expression" str) (assertEqual ("When parsing " <> toString str) (stripPositionInfo expected)@@ -411,39 +715,35 @@ ) (parseNixText str) -assertParseTextLoc :: Text -> NExprLoc -> Assertion+assertParseTextLoc :: NixLang -> NExprLoc -> Assertion assertParseTextLoc str expected = either- (\ err ->- assertFailure $ toString $ "Unexpected fail parsing `" <> str <> "':\n" <> show err- )+ (throwParseError "expression" str) (assertEqual ("When parsing " <> toString str) expected ) (parseNixTextLoc str) -assertParseFile :: FilePath -> NExpr -> Assertion+assertParseFile :: Path -> NExpr -> Assertion assertParseFile file expected = do- res <- parseNixFile $ "data/" <> file- either- (\ err ->- assertFailure $ "Unexpected fail parsing data file `" <> file <> "':\n" <> show err- )- (assertEqual- ("Parsing data file " <> file)- (stripPositionInfo expected)- . stripPositionInfo- )- res+ res <- parseNixFile $ "data/" <> file+ either+ (throwParseError "data file" $ toText file)+ (assertEqual+ ("Parsing data file " <> coerce file)+ (stripPositionInfo expected)+ . stripPositionInfo+ )+ res -assertParseFail :: Text -> Assertion+assertParseFail :: NixLang -> Assertion assertParseFail str = either- (const pass)+ (const stub) (\ r ->- assertFailure $ toString $ "Unexpected success parsing `" <> str <> ":\nParsed value: " <> show r+ assertFailure $ toString $ "\nUnexpected success parsing string ''" <> str <> "'':\n''Parsed value: ''" <> show r <> "''." ) (parseNixText str) @@ -456,8 +756,53 @@ Right expr = parseNixTextLoc src result = renderStrict- . layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4)+ . layoutPretty defaultLayoutOptions . prettyNix . stripAnnotation $ expr- in assertEqual "" expect result+ in+ assertEqual mempty expect result+++-----++-- | This class constructs functions that accept variacic number of argumets.+-- Every argument is an assertion.+-- So now the new assertions can be added just by adding it to a block of according assertions.+class VariadicAssertions t where+ checkListPairs' :: ((ExpectedHask, NixLang) -> Assertion) -> [(ExpectedHask, NixLang)] -> t++instance VariadicAssertions (IO a) where+ checkListPairs' f acc =+ do+ traverse_ f acc+ pure $ error "never would be reached, cuz `I'm lazy`."++instance (VariadicAssertions a) => VariadicAssertions ((ExpectedHask, NixLang) -> a) where+ checkListPairs' f acc x = checkListPairs' f (acc <> one x)++checks :: (VariadicAssertions a) => a+checks = checkListPairs' (uncurry assertParseText) []+++class VariadicArgs t where+ checkList' :: (NixLang -> Assertion) -> [NixLang] -> t++instance VariadicArgs (IO a) where+ checkList' f acc =+ do+ traverse_ f acc+ pure $ error "never would be reached, cuz `I'm lazy`."++instance (VariadicArgs a) => VariadicArgs (NixLang -> a) where+ checkList' f acc x = checkList' f (acc <> one x)++knownAs :: (VariadicArgs a) => (NixLang -> Assertion) -> a+knownAs f = checkList' f []++mistakes :: (VariadicArgs a) => a+mistakes = knownAs assertParseFail++invariantVals :: (VariadicArgs a) => a+invariantVals = knownAs invariantVal+
tests/PrettyParseTests.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE NoMonomorphismRestriction #-}+{-# language DataKinds #-}+{-# language MonoLocalBinds #-}+{-# language NoMonomorphismRestriction #-} @@ -18,7 +18,6 @@ import Nix.Expr import Nix.Parser import Nix.Pretty-import Nix.Utils import Prettyprinter import Test.Tasty import Test.Tasty.Hedgehog@@ -29,23 +28,26 @@ asciiString = Gen.list (Range.linear 1 15) Gen.lower asciiText :: Gen Text-asciiText = toText <$> asciiString+asciiText = fromString <$> asciiString +asciiVarName :: Gen VarName+asciiVarName = coerce <$> asciiText+ -- Might want to replace this instance with a constant value genPos :: Gen Pos genPos = mkPos <$> Gen.int (Range.linear 1 256) genSourcePos :: Gen SourcePos genSourcePos =- liftA3- SourcePos- asciiString- genPos+ join (liftA3+ SourcePos+ asciiString+ ) genPos genKeyName :: Gen (NKeyName NExpr) genKeyName =- Gen.choice [DynamicKey <$> genAntiquoted genString, StaticKey <$> asciiText]+ Gen.choice [DynamicKey <$> genAntiquoted genString, StaticKey <$> asciiVarName] genAntiquoted :: Gen a -> Gen (Antiquoted a NExpr) genAntiquoted gen =@@ -53,51 +55,53 @@ genBinding :: Gen (Binding NExpr) genBinding = Gen.choice- [ liftA3- NamedVar+ [ liftA3 NamedVar genAttrPath genExpr genSourcePos- , liftA3- Inherit+ , liftA3 Inherit (Gen.maybe genExpr)- (Gen.list (Range.linear 0 5) genKeyName)+ (Gen.list (Range.linear 0 5) asciiVarName) genSourcePos ] genString :: Gen (NString NExpr) genString = Gen.choice- [ DoubleQuoted <$> Gen.list (Range.linear 0 5) (genAntiquoted asciiText)- , liftA2- Indented- (Gen.int (Range.linear 0 10))- (Gen.list- (Range.linear 0 5)- (genAntiquoted asciiText)- )+ [ DoubleQuoted <$> genLines+ , liftA2 Indented+ (Gen.int $ Range.linear 0 10)+ genLines ]+ where+ genLines =+ Gen.list+ (Range.linear 0 5)+ (genAntiquoted asciiText) genAttrPath :: Gen (NAttrPath NExpr) genAttrPath =- liftA2- (:|)+ liftA2 (:|) genKeyName $ Gen.list (Range.linear 0 4) genKeyName genParams :: Gen (Params NExpr) genParams = Gen.choice- [ Param <$> asciiText- , liftA3- ParamSet- (Gen.list (Range.linear 0 10) (liftA2 (,) asciiText $ Gen.maybe genExpr))+ [ Param <$> asciiVarName+ , liftA3 (mkGeneralParamSet . pure)+ (Gen.choice [stub, asciiText])+ (Gen.list (Range.linear 0 10) $+ liftA2 (,)+ asciiText+ (Gen.maybe genExpr)+ ) Gen.bool- (Gen.choice [stub, pure <$> asciiText]) ] + genAtom :: Gen NAtom genAtom = Gen.choice- [ NInt <$> Gen.integral (Range.linear 0 1000)- , NFloat <$> Gen.float (Range.linearFrac 0.0 1000.0)+ [ NInt <$> Gen.integral (Range.linear 0 1000 )+ , NFloat <$> Gen.float (Range.linearFrac 0.0 1000.0) , NBool <$> Gen.bool , pure NNull ]@@ -106,48 +110,65 @@ -- list Arbitrary instance which makes the generator terminate. The -- distribution is not scientifically chosen. genExpr :: Gen NExpr-genExpr = Gen.sized $ \(Size n) -> Fix <$> if n < 2- then Gen.choice [genConstant, genStr, genSym, genLiteralPath, genEnvPath]- else Gen.frequency- [ (1 , genConstant)- , (1 , genSym)- , (4 , Gen.resize (Size (n `div` 3)) genIf)- , (10, genRecSet)- , (20, genSet)- , (5 , genList)- , (2 , genUnary)- , (2, Gen.resize (Size (n `div` 3)) genBinary)- , (3, Gen.resize (Size (n `div` 3)) genSelect)- , (20, Gen.resize (Size (n `div` 2)) genAbs)- , (2, Gen.resize (Size (n `div` 2)) genHasAttr)- , (10, Gen.resize (Size (n `div` 2)) genLet)- , (10, Gen.resize (Size (n `div` 2)) genWith)- , (1, Gen.resize (Size (n `div` 2)) genAssert)- ]+genExpr =+ Gen.sized genCurbed where- genConstant = NConstant <$> genAtom- genStr = NStr <$> genString- genSym = NSym <$> asciiText- genList = NList <$> fairList genExpr- genSet = NSet NNonRecursive <$> fairList genBinding- genRecSet = NSet NRecursive <$> fairList genBinding- genLiteralPath = NLiteralPath . ("./" <>) <$> asciiString- genEnvPath = NEnvPath <$> asciiString- genUnary = liftA2 NUnary Gen.enumBounded genExpr- genBinary = liftA3 NBinary Gen.enumBounded genExpr genExpr- genSelect = liftA3 NSelect genExpr genAttrPath (Gen.maybe genExpr)- genHasAttr = liftA2 NHasAttr genExpr genAttrPath- genAbs = liftA2 NAbs genParams genExpr- genLet = liftA2 NLet (fairList genBinding) genExpr- genIf = liftA3 NIf genExpr genExpr genExpr- genWith = liftA2 NWith genExpr genExpr- genAssert = liftA2 NAssert genExpr genExpr+ genCurbed (coerce -> n) =+ Fix <$>+ bool+ small+ big+ (n >= 2)+ where + genConstant = NConstant <$> genAtom+ genStr = NStr <$> genString+ genSym = NSym <$> asciiVarName+ genLiteralPath = NLiteralPath . ("./" <>) . coerce <$> asciiString+ genEnvPath = NEnvPath . coerce <$> asciiString++ small = Gen.choice [genConstant, genStr, genSym, genLiteralPath, genEnvPath]++ big =+ let+ sizeDivBy i = Size $ n `div` i+ resizeDivBy i = Gen.resize (sizeDivBy i)+ in+ Gen.frequency+ [ (1 , genConstant)+ , (1 , genSym)+ , (2 , genUnary)+ , (5 , genList)+ , (20, genSet)+ , (10, genRecSet)+ , (1 , resizeDivBy 2 genAssert)+ , (4 , resizeDivBy 3 genIf)+ , (2 , resizeDivBy 3 genBinary)+ , (3 , resizeDivBy 3 genSelect)+ , (20, resizeDivBy 2 genAbs)+ , (2 , resizeDivBy 2 genHasAttr)+ , (10, resizeDivBy 2 genLet)+ , (10, resizeDivBy 2 genWith)+ ]+ where+ genList = NList <$> fairList genExpr+ genSet = NSet mempty <$> fairList genBinding+ genRecSet = NSet Recursive <$> fairList genBinding+ genUnary = liftA2 NUnary Gen.enumBounded genExpr+ genBinary = join (liftA3 NBinary Gen.enumBounded) genExpr+ genSelect = liftA3 NSelect (Gen.maybe genExpr) genExpr genAttrPath+ genHasAttr = liftA2 NHasAttr genExpr genAttrPath+ genAbs = liftA2 NAbs genParams genExpr+ genLet = liftA2 NLet (fairList genBinding) genExpr+ genIf = join (liftA3 NIf genExpr) genExpr+ genWith = join (liftA2 NWith) genExpr+ genAssert = join (liftA2 NAssert) genExpr+ -- | Useful when there are recursive positions at each element of the list as -- it divides the size by the length of the generated list. fairList :: Gen a -> Gen [a] fairList g = Gen.sized $ \s -> do- k <- Gen.int (Range.linear 0 (unSize s))+ k <- Gen.int $ Range.linear 0 $ unSize s -- Use max here to avoid dividing by zero when there is the empty list Gen.resize (Size (unSize s `div` max 1 k)) $ Gen.list (Range.singleton k) g @@ -155,49 +176,53 @@ equivUpToNormalization x y = normalize x == normalize y normalize :: NExpr -> NExpr-normalize = foldFix $ Fix . \case+normalize = foldFix $ \case NConstant (NInt n) | n < 0 ->- NUnary NNeg $ Fix $ NConstant $ NInt $ negate n+ mkNeg $ mkInt $ negate n NConstant (NFloat n) | n < 0 ->- NUnary NNeg $ Fix $ NConstant $ NFloat $ negate n+ mkNeg $ mkFloat $ negate n - NSet recur binds -> NSet recur $ normBinding <$> binds- NLet binds r -> NLet (normBinding <$> binds) r+ NSet recur binds ->+ mkSet recur $ normBinding <$> binds+ NLet binds r ->+ mkLets (normBinding <$> binds) r - NAbs params r -> NAbs (normParams params) r+ NAbs params r ->+ mkFunction (normParams params) r - r -> r+ r -> Fix r where normBinding (NamedVar path r pos) = NamedVar (normKey <$> path) r pos- normBinding (Inherit mr names pos) = Inherit mr (normKey <$> names) pos+ normBinding (Inherit mr names pos) = Inherit mr names pos normKey (DynamicKey quoted) = DynamicKey (normAntiquotedString quoted) normKey (StaticKey name ) = StaticKey name normAntiquotedString- :: Antiquoted (NString NExpr) NExpr -> Antiquoted (NString NExpr) NExpr+ :: Antiquoted (NString NExpr) NExpr+ -> Antiquoted (NString NExpr) NExpr normAntiquotedString (Plain (DoubleQuoted [EscapedNewline])) = EscapedNewline normAntiquotedString (Plain (DoubleQuoted strs)) =- let strs' = normAntiquotedText <$> strs- in- if strs == strs'- then Plain $ DoubleQuoted strs- else normAntiquotedString $ Plain $ DoubleQuoted strs'+ bool normAntiquotedString id (strs == strs')+ (Plain $ DoubleQuoted strs')+ where+ strs' = normAntiquotedText <$> strs normAntiquotedString r = r - normAntiquotedText :: Antiquoted Text NExpr -> Antiquoted Text NExpr+ normAntiquotedText+ :: Antiquoted Text NExpr+ -> Antiquoted Text NExpr normAntiquotedText (Plain "\n" ) = EscapedNewline normAntiquotedText (Plain "''\n") = EscapedNewline normAntiquotedText r = r - normParams (ParamSet binds var (Just "")) = ParamSet binds var mempty+ normParams (ParamSet (Just "") variadic pset) = ParamSet Nothing variadic pset normParams r = r -- | Test that parse . pretty == id up to attribute position information. prop_prettyparse :: Monad m => NExpr -> PropertyT m ()-prop_prettyparse p = do- let prog = show $ prettyNix p+prop_prettyparse p = either (\ s -> do footnote $ show $ vsep@@ -236,16 +261,18 @@ success (equivUpToNormalization p v) )- (parse $ toText prog)+ (parse $ fromString prog) where+ prog = show $ prettyNix p+ parse = parseNixText normalise s = String.unlines $ reverse . dropWhile isSpace . reverse <$> String.lines s ldiff :: String -> String -> [Diff [String]]- ldiff s1 s2 = getDiff ((: mempty) <$> String.lines s1) ((: mempty) <$> String.lines s2)+ ldiff s1 s2 = getDiff (one <$> String.lines s1) (one <$> String.lines s2) tests :: TestLimit -> TestTree-tests n = testProperty "Pretty/Parse Property" $ withTests n $ property $ do- x <- forAll genExpr- prop_prettyparse x+tests n =+ testProperty "Pretty/Parse Property" $+ withTests n $ property $ prop_prettyparse =<< forAll genExpr
tests/PrettyTests.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell #-}+{-# language TemplateHaskell #-} module PrettyTests (tests) where import Test.Tasty@@ -9,29 +9,48 @@ import Nix.Pretty case_indented_antiquotation :: Assertion-case_indented_antiquotation = do- assertPretty (mkIndentedStr 0 "echo $foo") "''echo $foo''"- assertPretty (mkIndentedStr 0 "echo ${foo}") "''echo ''${foo}''"+case_indented_antiquotation =+ do+ assertPretty+ (mkIndentedStr 0 "echo $foo")+ "''echo $foo''"+ assertPretty+ (mkIndentedStr 0 "echo ${foo}")+ "''echo ''${foo}''" case_string_antiquotation :: Assertion-case_string_antiquotation = do- assertPretty (mkStr "echo $foo") "\"echo \\$foo\""- assertPretty (mkStr "echo ${foo}") "\"echo \\${foo}\""+case_string_antiquotation =+ do+ assertPretty+ (mkStr "echo $foo")+ "\"echo \\$foo\""+ assertPretty+ (mkStr "echo ${foo}")+ "\"echo \\${foo}\"" case_function_params :: Assertion case_function_params =- assertPretty (mkFunction (mkParamset mempty True) (mkInt 3)) "{ ... }:\n 3"+ assertPretty+ (mkFunction (mkVariadicParamSet mempty) (mkInt 3))+ "{ ... }:\n 3" case_paths :: Assertion-case_paths = do- assertPretty (mkPath False "~/test.nix") "~/test.nix"- assertPretty (mkPath False "/test.nix") "/test.nix"- assertPretty (mkPath False "./test.nix") "./test.nix"+case_paths =+ do+ assertPretty+ (mkPath False "~/test.nix")+ "~/test.nix"+ assertPretty+ (mkPath False "/test.nix")+ "/test.nix"+ assertPretty+ (mkPath False "./test.nix")+ "./test.nix" tests :: TestTree tests = $testGroupGenerator ----------------------------------------------------------------------------------assertPretty :: NExpr -> String -> Assertion+assertPretty :: NExpr -> Text -> Assertion assertPretty e s = assertEqual ("When pretty-printing " <> show e) s . show $ prettyNix e
tests/ReduceExprTests.hs view
@@ -1,14 +1,13 @@-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# options_ghc -fno-warn-name-shadowing #-} module ReduceExprTests (tests) where-import Data.Fix import Test.Tasty import Test.Tasty.HUnit -import Nix.Atoms import Nix.Expr.Types import Nix.Expr.Types.Annotated import Nix.Parser import Nix.Reduce ( reduceExpr )+import Nix.Expr.Shorthands tests :: TestTree@@ -46,13 +45,13 @@ selectBasic = parseNixTextLoc "{b=2;a=42;}.a" selectBasicExpect :: NExpr-selectBasicExpect = Fix . NConstant $ NInt 42+selectBasicExpect = mkInt 42 selectNested :: Result NExprLoc selectNested = parseNixTextLoc "{a={b=2;a=42;};b={a=2;};}.a.a" selectNestedExpect :: NExpr-selectNestedExpect = Fix . NConstant $ NInt 42+selectNestedExpect = mkInt 42 selectIncorrectAttrPath :: Result NExprLoc selectIncorrectAttrPath = parseNixTextLoc "{a=42;}.b"
tests/TestCommon.hs view
@@ -1,32 +1,32 @@-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# language PartialTypeSignatures #-} module TestCommon where import GHC.Err ( errorWithoutStackTrace ) import Control.Monad.Catch import Data.Time+import Data.Text.IO as Text import Nix import Nix.Standard import Nix.Fresh.Basic import System.Environment import System.IO-import System.Posix.Files-import System.Posix.Temp+import System.PosixCompat.Files+import System.PosixCompat.Temp import System.Process import Test.Tasty.HUnit -hnixEvalFile :: Options -> FilePath -> IO (StdValue (StandardT (StdIdT IO)))+hnixEvalFile :: Options -> Path -> IO (StdValue (StandardT (StdIdT IO))) hnixEvalFile opts file = do parseResult <- parseNixFileLoc file either- (\ err -> fail $ "Parsing failed for file `" <> file <> "`.\n" <> show err)+ (\ err -> fail $ "Parsing failed for file `" <> coerce file <> "`.\n" <> show err) (\ expr -> do setEnv "TEST_VAR" "foo" runWithBasicEffects opts $- catch (evaluateExpression (pure file) nixEvalExprLoc normalForm expr) $+ catch (evaluateExpression (pure $ coerce file) nixEvalExprLoc normalForm expr) $ \case NixException frames -> errorWithoutStackTrace . show@@ -46,30 +46,31 @@ ) (parseNixText src) -nixEvalString :: String -> IO String-nixEvalString expr = do- (fp, h) <- mkstemp "nix-test-eval"- hPutStr h expr- hClose h- res <- nixEvalFile fp- removeLink fp- pure res+nixEvalString :: Text -> IO Text+nixEvalString expr =+ do+ (coerce -> fp, h) <- mkstemp "nix-test-eval"+ Text.hPutStr h expr+ hClose h+ res <- nixEvalFile fp+ removeLink $ coerce fp+ pure res -nixEvalFile :: FilePath -> IO String-nixEvalFile fp = readProcess "nix-instantiate" ["--eval", "--strict", fp] ""+nixEvalFile :: Path -> IO Text+nixEvalFile fp = fromString <$> readProcess "nix-instantiate" ["--eval", "--strict", coerce fp] mempty -assertEvalFileMatchesNix :: FilePath -> Assertion-assertEvalFileMatchesNix fp = do- time <- liftIO getCurrentTime- hnixVal <- (<> "\n") . printNix <$> hnixEvalFile (defaultOptions time) fp- nixVal <- nixEvalFile fp- assertEqual fp nixVal hnixVal+assertEvalFileMatchesNix :: Path -> Assertion+assertEvalFileMatchesNix fp =+ do+ time <- liftIO getCurrentTime+ hnixVal <- (<> "\n") . printNix <$> hnixEvalFile (defaultOptions time) fp+ nixVal <- nixEvalFile fp+ assertEqual (coerce fp) nixVal hnixVal assertEvalMatchesNix :: Text -> Assertion-assertEvalMatchesNix expr = do- time <- liftIO getCurrentTime- hnixVal <- (<> "\n") . printNix <$> hnixEvalText (defaultOptions time) expr- nixVal <- nixEvalString expr'- assertEqual expr' nixVal hnixVal- where- expr' = toString expr+assertEvalMatchesNix expr =+ do+ time <- liftIO getCurrentTime+ hnixVal <- (<> "\n") . printNix <$> hnixEvalText (defaultOptions time) expr+ nixVal <- nixEvalString expr+ assertEqual (toString expr) nixVal hnixVal