hercules-ci-cnix-expr 0.5.0.0 → 0.5.1.0
raw patch · 6 files changed
+270/−137 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Hercules.CNix.Expr: instance GHC.Read.Read a => GHC.Read.Read (Hercules.CNix.Expr.ViaJSON a)
- Hercules.CNix.Expr: instance GHC.Show.Show a => GHC.Show.Show (Hercules.CNix.Expr.ViaJSON a)
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.FromValue Hercules.CNix.Expr.Typed.NixInt GHC.Int.Int64
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue Foreign.C.Types.CBool
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue Foreign.C.Types.CDouble
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue GHC.Int.Int64
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue Foreign.C.Types.CBool
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue Foreign.C.Types.CDouble
- Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue GHC.Int.Int64
- Hercules.CNix.Expr.Raw: instance GHC.Generics.Generic Hercules.CNix.Expr.Raw.RawValueType
- Hercules.CNix.Expr.Raw: instance GHC.Show.Show Hercules.CNix.Expr.Raw.RawValueType
- Hercules.CNix.Expr.Schema: instance (s GHC.Types.~ t) => GHC.OverloadedLabels.IsLabel s (Hercules.CNix.Expr.Schema.AttrLabel t)
- Hercules.CNix.Expr.Schema: instance GHC.Exception.Type.Exception Hercules.CNix.Expr.Schema.NixException
- Hercules.CNix.Expr.Schema: instance GHC.Show.Show Hercules.CNix.Expr.Schema.NixException
- Hercules.CNix.Expr.Schema: instance GHC.Show.Show Hercules.CNix.Expr.Schema.Provenance
- Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.FromPSObject GHC.Int.Int64 GHC.Int.Int64
- Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.PossibleTypesForSchema GHC.Int.Int64
- Hercules.CNix.Expr.Typed: instance Hercules.CNix.Expr.Typed.CheckType GHC.Int.Int64
- Hercules.CNix.Expr.Typed: instance Hercules.CNix.Expr.Typed.HasRawValueType GHC.Int.Int64
+ Hercules.CNix.Expr: instance GHC.Internal.Read.Read a => GHC.Internal.Read.Read (Hercules.CNix.Expr.ViaJSON a)
+ Hercules.CNix.Expr: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Hercules.CNix.Expr.ViaJSON a)
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.FromValue Hercules.CNix.Expr.Typed.NixInt GHC.Internal.Int.Int64
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue GHC.Internal.Foreign.C.Types.CBool
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue GHC.Internal.Foreign.C.Types.CDouble
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToRawValue GHC.Internal.Int.Int64
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue GHC.Internal.Foreign.C.Types.CBool
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue GHC.Internal.Foreign.C.Types.CDouble
+ Hercules.CNix.Expr: instance Hercules.CNix.Expr.ToValue GHC.Internal.Int.Int64
+ Hercules.CNix.Expr.Raw: instance GHC.Internal.Generics.Generic Hercules.CNix.Expr.Raw.RawValueType
+ Hercules.CNix.Expr.Raw: instance GHC.Internal.Show.Show Hercules.CNix.Expr.Raw.RawValueType
+ Hercules.CNix.Expr.Schema: instance (s GHC.Types.~ t) => GHC.Internal.OverloadedLabels.IsLabel s (Hercules.CNix.Expr.Schema.AttrLabel t)
+ Hercules.CNix.Expr.Schema: instance GHC.Internal.Exception.Type.Exception Hercules.CNix.Expr.Schema.NixException
+ Hercules.CNix.Expr.Schema: instance GHC.Internal.Show.Show Hercules.CNix.Expr.Schema.NixException
+ Hercules.CNix.Expr.Schema: instance GHC.Internal.Show.Show Hercules.CNix.Expr.Schema.Provenance
+ Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.FromPSObject GHC.Internal.Int.Int64 GHC.Internal.Int.Int64
+ Hercules.CNix.Expr.Schema: instance Hercules.CNix.Expr.Schema.PossibleTypesForSchema GHC.Internal.Int.Int64
+ Hercules.CNix.Expr.Typed: instance Hercules.CNix.Expr.Typed.CheckType GHC.Internal.Int.Int64
+ Hercules.CNix.Expr.Typed: instance Hercules.CNix.Expr.Typed.HasRawValueType GHC.Internal.Int.Int64
Files
- CHANGELOG.md +4/−0
- hercules-ci-cnix-expr.cabal +28/−9
- include/hercules-ci-cnix/expr.hxx +4/−0
- src/Hercules/CNix/Expr.hs +225/−123
- src/Hercules/CNix/Expr/Context.hs +4/−0
- src/Hercules/CNix/Expr/Typed.hs +5/−5
CHANGELOG.md view
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.5.1.0 - 2026-01-06++- Nix support up to 2.33+ ## 0.5.0.0 - 2025-07-18 - `init` now installs synchronous signal handlers for you. You may remove your call to `installDefaultSigINTHandler`.
hercules-ci-cnix-expr.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: hercules-ci-cnix-expr-version: 0.5.0.0+version: 0.5.1.0 synopsis: Bindings for the Nix evaluator category: Nix, CI, Testing, DevOps homepage: https://docs.hercules-ci.com@@ -25,10 +25,19 @@ description: Whether to enable IDE workarounds. You shouldn't need this. default: False +flag nix-2_31+ description: nix-store >= 2.31+ default: False+ manual: False+ -- match the C++ language standard Nix is using common cxx-opts- cxx-options:- -std=c++2a+ if flag(nix-2_31)+ cxx-options:+ -std=c++23+ else+ cxx-options:+ -std=c++2a cxx-options: -Wall@@ -41,12 +50,22 @@ if impl(ghc >= 8.10) ghc-options: -optcxx-Wall- -optcxx-std=c++2a+ if flag(nix-2_31)+ ghc-options:+ -optcxx-std=c++23+ else+ ghc-options:+ -optcxx-std=c++2a else -- Remove soon ghc-options:- -optc-std=c++2a -optc-Wall+ if flag(nix-2_31)+ ghc-options:+ -optc-std=c++23+ else+ ghc-options:+ -optc-std=c++2a if os(darwin) ghc-options: -pgmc=clang++ @@ -97,11 +116,11 @@ extra-libraries: boost_context pkgconfig-depends:- nix-store >= 2.28- , nix-expr >= 2.28+ nix-store >= 2.28 && < 2.34+ , nix-expr >= 2.28 && < 2.34 -- TODO: replace nix-main stack overflow detection?- , nix-main >= 2.28- , nix-flake >= 2.28+ , nix-main >= 2.28 && < 2.34+ , nix-flake >= 2.28 && < 2.34 test-suite hercules-ci-cnix-expr-unit-tests
include/hercules-ci-cnix/expr.hxx view
@@ -1,9 +1,13 @@ #pragma once #include <nix/store/derivations.hh>+#include <nix/expr/value.hh> #include <hercules-ci-cnix/store.hxx> typedef nix::Strings::iterator StringsIterator; typedef nix::DerivationOutputs::iterator DerivationOutputsIterator; typedef nix::StringPairs::iterator StringPairsIterator;+#if NIX_IS_AT_LEAST(2, 30, 0)+typedef nix::ListView ListViewType;+#endif
src/Hercules/CNix/Expr.hs view
@@ -8,7 +8,6 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}- -- redundant-constraints: False positive in default signature for `toRawValue` {-# OPTIONS_GHC -Wno-redundant-constraints #-} @@ -53,10 +52,10 @@ getLocalFlake, getFlakeFromGit, getFlakeFromArchiveUrl,- ToRawValue(..),- ToValue(..),- FromValue(..),- ViaJSON(..),+ ToRawValue (..),+ ToValue (..),+ FromValue (..),+ ViaJSON (..), -- * Re-exports RawValue,@@ -73,6 +72,8 @@ import Conduit import qualified Data.Aeson as A+import Data.Aeson.KeyMap (toMapText)+import qualified Data.ByteString.Unsafe as BS import Data.Coerce (coerce) import qualified Data.HashMap.Lazy as H import qualified Data.Map as M@@ -81,19 +82,17 @@ import qualified Data.Vector as V import Foreign (nullPtr) import qualified Foreign.C.String+import qualified Hercules.CNix as CNix import Hercules.CNix.Encapsulation (moveToForeignPtrWrapper) import Hercules.CNix.Expr.Context import Hercules.CNix.Expr.Raw import Hercules.CNix.Expr.Typed import Hercules.CNix.Store import Hercules.CNix.Store.Context-import qualified Hercules.CNix as CNix import qualified Language.C.Inline.Cpp as C import qualified Language.C.Inline.Cpp.Exception as C import Protolude hiding (evalState) import System.Directory (makeAbsolute)-import Data.Aeson.KeyMap (toMapText)-import qualified Data.ByteString.Unsafe as BS C.context (Hercules.CNix.Store.Context.context <> Hercules.CNix.Expr.Context.evalContext) @@ -200,12 +199,10 @@ }|] pass --{- | Configure the stack overflow handler to sleep before returning, allowing- other threads to continue for a bit.-- No-op before Nix 2.12--}+-- | Configure the stack overflow handler to sleep before returning, allowing+-- other threads to continue for a bit.+--+-- No-op before Nix 2.12 setExtraStackOverflowHandlerToSleep :: IO () setExtraStackOverflowHandlerToSleep = void@@ -259,15 +256,16 @@ }|] -- | (private) Make an EvalState and leak it.-newEvalState :: MonadIO m => Store -> m (Ptr EvalState)-newEvalState (Store store) = liftIO- [C.throwBlock| EvalState* {- nix::LookupPath emptyLookupPath;- return new EvalState(emptyLookupPath, *$(refStore* store), fetchSettings, evalSettings);+newEvalState :: (MonadIO m) => Store -> m (Ptr EvalState)+newEvalState (Store store) =+ liftIO+ [C.throwBlock| EvalState* {+ nix::LookupPath emptyLookupPath;+ return new EvalState(emptyLookupPath, *$(refStore* store), fetchSettings, evalSettings); } |] -- | (private) Don't leak it.-deleteEvalState :: MonadIO m => (Ptr EvalState) -> m ()+deleteEvalState :: (MonadIO m) => (Ptr EvalState) -> m () deleteEvalState st = liftIO [C.throwBlock| void { delete $(EvalState* st); } |] withEvalState ::@@ -277,20 +275,26 @@ withEvalState store = bracket (newEvalState store) deleteEvalState withEvalStateConduit ::- MonadResource m =>+ (MonadResource m) => Store -> (Ptr EvalState -> ConduitT i o m r) -> ConduitT i o m r withEvalStateConduit store = bracketP (newEvalState store) deleteEvalState -- | Insert an allowed path. Only has an effect when in restricted or pure mode.+{- ORMOLU_DISABLE -} addAllowedPath :: Ptr EvalState -> ByteString -> IO () addAllowedPath evalState path = [C.throwBlock| void { std::string path = std::string($bs-ptr:path, $bs-len:path); EvalState &evalState = *$(EvalState *evalState);+#if NIX_IS_AT_LEAST(2, 32, 0)+ evalState.allowPathLegacy(path);+#else evalState.allowPath(path);+#endif }|]+{- ORMOLU_ENABLE -} addInternalAllowedPaths :: Ptr EvalState -> IO () addInternalAllowedPaths _evalState = do@@ -348,6 +352,7 @@ return $(EvalState *evalState)->isFunctor(*$(Value *v)); }|] +{- ORMOLU_DISABLE -} getRecurseForDerivations :: Ptr EvalState -> Value NixAttrs -> IO Bool getRecurseForDerivations evalState (Value (RawValue v)) = (0 /=)@@ -355,6 +360,14 @@ Value *v = $(Value *v); EvalState &evalState = *$(EvalState *evalState); auto attrs = v->attrs();+#if NIX_IS_AT_LEAST(2, 32, 0)+ auto iter = attrs->get(evalState.s.recurseForDerivations);+ if (!iter) {+ return 0;+ } else {+ return evalState.forceBool(*iter->value, iter->pos, "while evaluating whether to traverse into an attribute set to find more derivations");+ }+#else // Bindings::const_iterator iter; // 2.24 auto iter = attrs->find(evalState.sRecurseForDerivations); if (iter == attrs->end()) {@@ -366,8 +379,11 @@ // nixpkgs master 67e2de195a4aa0a50ffb1e1ba0b4fb531dca67dc return evalState.forceBool(*iter->value, iter->pos, "while evaluating whether to traverse into an attribute set to find more derivations"); }+#endif } |]+{- ORMOLU_ENABLE -} +{- ORMOLU_DISABLE -} getAttr :: Ptr EvalState -> Value NixAttrs -> ByteString -> IO (Maybe RawValue) getAttr evalState (Value (RawValue v)) k = mkNullableRawValue@@ -376,6 +392,14 @@ EvalState &evalState = *$(EvalState *evalState); Symbol k = evalState.symbols.create($bs-cstr:k); auto attrs = v.attrs();+#if NIX_IS_AT_LEAST(2, 32, 0)+ auto iter = attrs->get(k);+ if (!iter) {+ return nullptr;+ } else {+ return iter->value;+ }+#else // Bindings::const_iterator iter; // 2.24 auto iter = attrs->find(k); if (iter == attrs->end()) {@@ -383,32 +407,64 @@ } else { return iter->value; }+#endif }|]+{- ORMOLU_ENABLE -} -- | Converts 'nullPtr' to 'Nothing'; actual values to @Just (a :: 'RawValue')@ mkNullableRawValue :: Ptr Value' -> IO (Maybe RawValue) mkNullableRawValue p | p == nullPtr = pure Nothing mkNullableRawValue p = Just <$> mkRawValue p +{- ORMOLU_DISABLE -} getAttrs :: Ptr EvalState -> Value NixAttrs -> IO (Map ByteString RawValue) getAttrs evalState (Value (RawValue v)) = do+#if NIX_IS_AT_LEAST(2, 32, 0)+ -- In Nix 2.32+, we need to collect all attrs in C++ since iteration changed+ size <- [C.exp| size_t { $(Value *v)->attrs()->size() }|]+ let collect :: C.CSize -> Map ByteString RawValue -> IO (Map ByteString RawValue)+ collect i acc | i >= size = pure acc+ collect i acc = do+ name <-+ BS.unsafePackMallocCString+ =<< [C.block| const char *{+ EvalState &evalState = *$(EvalState *evalState);+ auto iter = $(Value *v)->attrs()->begin();+ for (size_t j = 0; j < $(size_t i); j++) ++iter;+ SymbolStr str = evalState.symbols[iter->name];+ return stringdup(static_cast<std::string>(str));+ }|]+ value <- mkRawValue =<< [C.block| Value *{+ auto iter = $(Value *v)->attrs()->begin();+ for (size_t j = 0; j < $(size_t i); j++) ++iter;+ return new (NoGC) Value(*iter->value);+ }|]+ let acc' = M.insert name value acc+ seq acc' pass+ collect (i + 1) acc'+ collect 0 mempty+#else begin <- [C.exp| const Attr *{ $(Value *v)->attrs()->begin() }|] end <- [C.exp| const Attr *{ $(Value *v)->attrs()->end() }|] let gather :: Map ByteString RawValue -> Ptr Attr' -> IO (Map ByteString RawValue) gather acc i | i == end = pure acc gather acc i = do- name <- BS.unsafePackMallocCString =<< [C.block| const char *{- EvalState &evalState = *$(EvalState *evalState);- SymbolStr str = evalState.symbols[$(Attr *i)->name];- return stringdup(static_cast<std::string>(str));- }|]+ name <-+ BS.unsafePackMallocCString+ =<< [C.block| const char *{+ EvalState &evalState = *$(EvalState *evalState);+ SymbolStr str = evalState.symbols[$(Attr *i)->name];+ return stringdup(static_cast<std::string>(str));+ }|] value <- mkRawValue =<< [C.exp| Value *{ new (NoGC) Value(*$(Attr *i)->value) } |] let acc' = M.insert name value acc seq acc' pass gather acc' =<< [C.exp| Attr *{ &$(Attr *i)[1] }|] gather mempty begin+#endif+{- ORMOLU_ENABLE -} -getDrvFile :: MonadIO m => Ptr EvalState -> RawValue -> m StorePath+getDrvFile :: (MonadIO m) => Ptr EvalState -> RawValue -> m StorePath getDrvFile evalState (RawValue v) = liftIO do moveToForeignPtrWrapper =<< [C.throwBlock| nix::StorePath *{@@ -438,12 +494,26 @@ Right _ -> do pure $ Right Nothing +#if NIX_IS_AT_LEAST(2, 30, 0) getList :: Value NixList -> IO [RawValue] getList (Value (RawValue nixList)) = do len <- [C.exp| int { $(Value *nixList)->listSize() }|]+ bracket+ [C.exp| ListViewType * { new ListViewType($(Value *nixList)->listView()) }|]+ (\listView -> [C.exp| void { delete $(ListViewType *listView) }|])+ (\listView -> do+ let getElem i = mkRawValue =<< [C.exp| Value * { (*$(ListViewType *listView))[$(int i)] }|]+ for [0 .. (len - 1)] \i -> do+ getElem i+ )+#else+getList :: Value NixList -> IO [RawValue]+getList (Value (RawValue nixList)) = do+ len <- [C.exp| int { $(Value *nixList)->listSize() }|] let getElem i = mkRawValue =<< [C.exp| Value * { $(Value *nixList)->listElems()[$(int i)] }|] for [0 .. (len - 1)] \i -> do getElem i+#endif getAttrList :: Ptr EvalState -> Value NixAttrs -> ByteString -> IO (Either SomeException (Maybe [RawValue])) getAttrList evalState attrset attrName = do@@ -498,18 +568,24 @@ return r; }|] +{- ORMOLU_DISABLE -} mkPath :: Ptr EvalState -> ByteString -> IO (Value NixPath) mkPath evalState path = Value <$> ( mkRawValue =<< [C.throwBlock| Value *{- Value *r = new (NoGC) Value();- std::string s($bs-ptr:path, $bs-len:path);- EvalState & state = *$(EvalState *evalState);- r->mkPath(state.rootPath(CanonPath(s)));- return r;- }|]+ Value *r = new (NoGC) Value();+ std::string s($bs-ptr:path, $bs-len:path);+ EvalState & state = *$(EvalState *evalState);+#if NIX_IS_AT_LEAST(2, 33, 0)+ r->mkPath(state.rootPath(CanonPath(s)), state.mem);+#else+ r->mkPath(state.rootPath(CanonPath(s)));+#endif+ return r;+ }|] )+{- ORMOLU_ENABLE -} getFlakeFromFlakeRef :: Ptr EvalState -> ByteString -> IO RawValue getFlakeFromFlakeRef evalState flakeRef = do@@ -542,35 +618,34 @@ absPath <- encodeUtf8 . toS <$> makeAbsolute (toS path) mkRawValue =<< [C.throwBlock| Value *{- EvalState &evalState = *$(EvalState *evalState);- Value *r = new (NoGC) Value();- std::string path($bs-ptr:absPath, $bs-len:absPath);- auto flakeRef = nix::parseFlakeRef(- fetchSettings,- path,- {},- true);- nix::flake::callFlake(evalState,- nix::flake::lockFlake(- flakeSettings,- evalState,- flakeRef,- nix::flake::LockFlags {- .updateLockFile = false,- .useRegistries = false,- .allowUnlocked = false,- }),- *r);- return r;- }|]+ EvalState &evalState = *$(EvalState *evalState);+ Value *r = new (NoGC) Value();+ std::string path($bs-ptr:absPath, $bs-len:absPath);+ auto flakeRef = nix::parseFlakeRef(+ fetchSettings,+ path,+ {},+ true);+ nix::flake::callFlake(evalState,+ nix::flake::lockFlake(+ flakeSettings,+ evalState,+ flakeRef,+ nix::flake::LockFlags {+ .updateLockFile = false,+ .useRegistries = false,+ .allowUnlocked = false,+ }),+ *r);+ return r;+ }|] getFlakeFromGit :: Ptr EvalState -> Text -> Text -> Text -> IO RawValue getFlakeFromGit evalState url ref rev =- let- urlb = encodeUtf8 url- refb = encodeUtf8 ref- revb = encodeUtf8 rev- in [C.throwBlock| Value *{+ let urlb = encodeUtf8 url+ refb = encodeUtf8 ref+ revb = encodeUtf8 rev+ in [C.throwBlock| Value *{ EvalState &evalState = *$(EvalState *evalState); Value *r = new (NoGC) Value(); std::string url($bs-ptr:urlb, $bs-len:urlb);@@ -599,7 +674,7 @@ *r); return r; }|]- >>= mkRawValue+ >>= mkRawValue getFlakeFromArchiveUrl :: Ptr EvalState -> Text -> IO RawValue getFlakeFromArchiveUrl evalState url = do@@ -612,15 +687,15 @@ p' <- getStringIgnoreContext p getFlakeFromFlakeRef evalState p' -traverseWithKey_ :: Applicative f => (k -> a -> f ()) -> Map k a -> f ()+traverseWithKey_ :: (Applicative f) => (k -> a -> f ()) -> Map k a -> f () traverseWithKey_ f = M.foldrWithKey (\k a more -> f k a *> more) (pure ()) class ToRawValue a where toRawValue :: Ptr EvalState -> a -> IO RawValue- default toRawValue :: ToValue a => Ptr EvalState -> a -> IO RawValue+ default toRawValue :: (ToValue a) => Ptr EvalState -> a -> IO RawValue toRawValue evalState a = rtValue <$> toValue evalState a -class ToRawValue a => ToValue a where+class (ToRawValue a) => ToValue a where type NixTypeFor a :: Type toValue :: Ptr EvalState -> a -> IO (Value (NixTypeFor a)) @@ -660,10 +735,10 @@ toValue _ b = coerce <$> [C.block| Value *{- Value *r = new (NoGC) Value();- r->mkBool($(bool b));- return r;- }|]+ Value *r = new (NoGC) Value();+ r->mkBool($(bool b));+ return r;+ }|] instance ToRawValue Bool @@ -681,10 +756,10 @@ toValue _ i = coerce <$> [C.block| Value *{- Value *r = new (NoGC) Value();- r->mkInt($(int64_t i));- return r;- }|]+ Value *r = new (NoGC) Value();+ r->mkInt($(int64_t i));+ return r;+ }|] instance ToRawValue Int @@ -699,10 +774,10 @@ toValue _ f = coerce <$> [C.block| Value *{- Value *r = new (NoGC) Value();- r->mkFloat($(double f));- return r;- }|]+ Value *r = new (NoGC) Value();+ r->mkFloat($(double f));+ return r;+ }|] instance ToRawValue Double @@ -710,24 +785,36 @@ type NixTypeFor Double = NixFloat toValue es f = toValue es (fromRational (toRational f) :: C.CDouble) +{- ORMOLU_DISABLE -} -- | Nix String instance ToValue ByteString where type NixTypeFor ByteString = NixString- toValue _ s =+ toValue evalState s = -- TODO simplify when r->mkString(string_view) is safe in all supported Nix versions coerce <$> [C.block| Value *{- Value *r = new (NoGC) Value();- std::string_view s($bs-ptr:s, $bs-len:s);- // If empty, the pointer may be invalid; don't use it.- if (s.size() == 0) {- r->mkString("");- }- else {- r->mkString(GC_STRNDUP(s.data(), s.size()));- }- return r;- }|]+ Value *r = new (NoGC) Value();+ std::string_view s($bs-ptr:s, $bs-len:s);+#if NIX_IS_AT_LEAST(2, 33, 0)+ EvalState &evalState = *$(EvalState *evalState);+ if (s.size() == 0) {+ r->mkString(std::string_view(""), evalState.mem);+ }+ else {+ r->mkString(std::string_view(GC_STRNDUP(s.data(), s.size()), s.size()), evalState.mem);+ }+#else+ // If empty, the pointer may be invalid; don't use it.+ if (s.size() == 0) {+ r->mkString("");+ }+ else {+ r->mkString(GC_STRNDUP(s.data(), s.size()));+ }+#endif+ return r;+ }|]+{- ORMOLU_ENABLE -} -- | Nix String instance ToRawValue ByteString@@ -740,47 +827,53 @@ type NixTypeFor Text = NixString toValue es s = toValue es (encodeUtf8 s) -instance ToRawValue a => ToRawValue (Map ByteString a)+instance (ToRawValue a) => ToRawValue (Map ByteString a) -withBindingsBuilder :: Integral n => Ptr EvalState -> n -> (Ptr BindingsBuilder' -> IO ()) -> IO (Value NixAttrs)+withBindingsBuilder :: (Integral n) => Ptr EvalState -> n -> (Ptr BindingsBuilder' -> IO ()) -> IO (Value NixAttrs) withBindingsBuilder evalState n f = do withBindingsBuilder' evalState n \bb -> do f bb- v <- [C.block| Value* {- auto v = new (NoGC) Value();- v->mkAttrs(*$(BindingsBuilder *bb));- return v;- }|]+ v <-+ [C.block| Value* {+ auto v = new (NoGC) Value();+ v->mkAttrs(*$(BindingsBuilder *bb));+ return v;+ }|] Value <$> mkRawValue v -withBindingsBuilder' :: Integral n => Ptr EvalState -> n -> (Ptr BindingsBuilder' -> IO a) -> IO a+{- ORMOLU_DISABLE -}+withBindingsBuilder' :: (Integral n) => Ptr EvalState -> n -> (Ptr BindingsBuilder' -> IO a) -> IO a withBindingsBuilder' evalState n = let l :: C.CInt l = fromIntegral n- in- bracket- [C.block| BindingsBuilder* {- auto &evalState = *$(EvalState *evalState);- return new BindingsBuilder(evalState, evalState.allocBindings($(int l)));- }|]- \bb -> [C.block| void { delete $(BindingsBuilder *bb); }|]+ in bracket+ [C.block| BindingsBuilder* {+ auto &evalState = *$(EvalState *evalState);+#if NIX_IS_AT_LEAST(2, 32, 0)+ return new BindingsBuilder(evalState.buildBindings($(int l)));+#else+ return new BindingsBuilder(evalState, evalState.allocBindings($(int l)));+#endif+ }|]+ \bb -> [C.block| void { delete $(BindingsBuilder *bb); }|]+{- ORMOLU_ENABLE -} -instance ToRawValue a => ToValue (Map ByteString a) where+instance (ToRawValue a) => ToValue (Map ByteString a) where type NixTypeFor (Map ByteString a) = NixAttrs toValue evalState attrs = withBindingsBuilder evalState (length attrs) \bb -> do attrs & traverseWithKey_ \k a -> do RawValue aRaw <- toRawValue evalState a [C.block| void {- EvalState &evalState = *$(EvalState *evalState);- std::string k($bs-ptr:k, $bs-len:k);- Value &a = *$(Value *aRaw);- $(BindingsBuilder *bb)->alloc(evalState.symbols.create(k)) = a;- }|]+ EvalState &evalState = *$(EvalState *evalState);+ std::string k($bs-ptr:k, $bs-len:k);+ Value &a = *$(Value *aRaw);+ $(BindingsBuilder *bb)->alloc(evalState.symbols.create(k)) = a;+ }|] -instance ToRawValue a => ToRawValue (Map Text a)+instance (ToRawValue a) => ToRawValue (Map Text a) -instance ToRawValue a => ToValue (Map Text a) where+instance (ToRawValue a) => ToValue (Map Text a) where type NixTypeFor (Map Text a) = NixAttrs toValue evalState attrs = toValue evalState (M.mapKeys encodeUtf8 attrs) @@ -806,15 +899,15 @@ newtype ViaJSON a = ViaJSON {fromViaJSON :: a} deriving newtype (Eq, Ord, Read, Show) -instance A.ToJSON a => ToRawValue (ViaJSON a) where+instance (A.ToJSON a) => ToRawValue (ViaJSON a) where toRawValue es (ViaJSON a) = toRawValue es (A.toJSON a) -hmTraverseWithKey_ :: Applicative f => (k -> a -> f ()) -> H.HashMap k a -> f ()+hmTraverseWithKey_ :: (Applicative f) => (k -> a -> f ()) -> H.HashMap k a -> f () hmTraverseWithKey_ f = H.foldrWithKey (\k a more -> f k a *> more) (pure ()) -instance ToRawValue a => ToRawValue (H.HashMap Text a)+instance (ToRawValue a) => ToRawValue (H.HashMap Text a) -instance ToRawValue a => ToValue (H.HashMap Text a) where+instance (ToRawValue a) => ToValue (H.HashMap Text a) where type NixTypeFor (H.HashMap Text a) = NixAttrs toValue evalState attrs = withBindingsBuilder evalState (length attrs) \bb -> do@@ -822,15 +915,16 @@ RawValue aRaw <- toRawValue evalState a let k = encodeUtf8 k' [C.block| void {- EvalState &evalState = *$(EvalState *evalState);- std::string k($bs-ptr:k, $bs-len:k);- Value &a = *$(Value *aRaw);- $(BindingsBuilder *bb)->alloc(evalState.symbols.create(k)) = a;- }|]+ EvalState &evalState = *$(EvalState *evalState);+ std::string k($bs-ptr:k, $bs-len:k);+ Value &a = *$(Value *aRaw);+ $(BindingsBuilder *bb)->alloc(evalState.symbols.create(k)) = a;+ }|] -instance ToRawValue a => ToRawValue (Vector a)+instance (ToRawValue a) => ToRawValue (Vector a) -instance ToRawValue a => ToValue (Vector a) where+{- ORMOLU_DISABLE -}+instance (ToRawValue a) => ToValue (Vector a) where type NixTypeFor (Vector a) = NixList toValue evalState vec = coerce <$> do@@ -838,8 +932,15 @@ l = fromIntegral (length vec) b <- [C.block| ListBuilder* {+#if NIX_IS_AT_LEAST(2, 33, 0) EvalState &evalState = *$(EvalState *evalState);+ return new (NoGC) ListBuilder(evalState.mem, $(int l));+#elif NIX_IS_AT_LEAST(2, 32, 0)+ return new (NoGC) ListBuilder($(int l));+#else+ EvalState &evalState = *$(EvalState *evalState); return new (NoGC) ListBuilder(evalState, $(int l));+#endif }|] vec & V.imapM_ \i a -> do RawValue aRaw <- toRawValue evalState a@@ -855,9 +956,10 @@ return v; }|] Value <$> mkRawValue v+{- ORMOLU_ENABLE -} -instance ToRawValue a => ToRawValue [a]+instance (ToRawValue a) => ToRawValue [a] -instance ToRawValue a => ToValue [a] where+instance (ToRawValue a) => ToValue [a] where type NixTypeFor [a] = NixList toValue es l = toValue es (V.fromList l)
src/Hercules/CNix/Expr/Context.hs view
@@ -33,6 +33,8 @@ data ListBuilder' +data ListViewType'+ context :: C.Context context = C.cppCtx@@ -57,4 +59,6 @@ =: [t|BindingsBuilder'|] <> C.TypeName "ListBuilder" =: [t|ListBuilder'|]+ <> C.TypeName "ListViewType"+ =: [t|ListViewType'|] }
src/Hercules/CNix/Expr/Typed.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE CPP #-} module Hercules.CNix.Expr.Typed ( Value (..),@@ -137,8 +137,8 @@ getBool :: Value Bool -> IO Bool getBool (Value (RawValue v)) =- (0 /=) <$>- [C.exp| int { $(Value *v)->boolean() ? 1 : 0 }|]+ (0 /=)+ <$> [C.exp| int { $(Value *v)->boolean() ? 1 : 0 }|] getInt :: Value NixInt -> IO Int64 getInt (Value (RawValue v)) =@@ -154,8 +154,8 @@ hasContext :: Value NixString -> IO Bool hasContext (Value (RawValue v)) =- (0 /=) <$>- [C.exp| int { $(Value *v)->context() ? 1 : 0 }|]+ (0 /=)+ <$> [C.exp| int { $(Value *v)->context() ? 1 : 0 }|] class CheckType a where checkType :: Ptr EvalState -> RawValue -> IO (Maybe (Value a))