Skip to content

Commit

Permalink
libnixt: add Value library (#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc authored Apr 8, 2024
1 parent 8fb17e8 commit c217f09
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 7 deletions.
12 changes: 12 additions & 0 deletions libnixt/include/nixt/Value.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <nix/eval.hh>

namespace nixt {

bool isOption(nix::EvalState &State, nix::Value &V);

bool isDerivation(nix::EvalState &State, nix::Value &V);

std::string attrPathStr(nix::EvalState &State, nix::Value &V,
const std::string &AttrPath);

} // namespace nixt
41 changes: 41 additions & 0 deletions libnixt/lib/Value.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "nixt/Value.h"

#include <nix/attr-path.hh>

using namespace nixt;

bool nixt::isOption(nix::EvalState &State, nix::Value &V) {
State.forceValue(V, nix::noPos);
if (V.type() != nix::ValueType::nAttrs)
return false;

// https://github.com/NixOS/nixpkgs/blob/58ca986543b591a8269cbce3328293ca8d64480f/lib/options.nix#L89
try {
auto S = attrPathStr(State, V, "_type");
return S == "option";
} catch (nix::AttrPathNotFound &Error) {
return false;
}
};

bool nixt::isDerivation(nix::EvalState &State, nix::Value &V) {
State.forceValue(V, nix::noPos);
if (V.type() != nix::ValueType::nAttrs)
return false;

try {
// Derivations has a special attribute "type" == "derivation"
auto S = attrPathStr(State, V, "type");
return S == "derivation";
} catch (nix::AttrPathNotFound &Error) {
return false;
}
}

std::string nixt::attrPathStr(nix::EvalState &State, nix::Value &V,
const std::string &AttrPath) {
auto &AutoArgs = *State.allocBindings(0);
auto [VPath, Pos] = nix::findAlongAttrPath(State, AttrPath, AutoArgs, V);
State.forceValue(*VPath, Pos);
return std::string(State.forceStringNoCtx(*VPath, nix::noPos, ""));
}
2 changes: 2 additions & 0 deletions libnixt/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ libnixt = library('nixt',
'lib/HookExpr.cpp',
'lib/Kinds.cpp',
'lib/ParentMap.cpp',
'lib/Value.cpp',
include_directories: libnixdInc,
dependencies: libnixtDeps,
install: true
Expand All @@ -37,6 +38,7 @@ libnixt_test_exe = executable(
'test/ASTReader.cpp',
'test/InitEval.cpp',
'test/Kinds.cpp',
'test/Value.cpp',
dependencies: [ gtest_main, nixt ]
)

Expand Down
10 changes: 3 additions & 7 deletions libnixt/test/ASTReader.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <gtest/gtest.h>

#include "ReaderData/ReaderData.h"
#include "StateTest.h"

#include "nixt/Deserialize.h"
#include "nixt/InitEval.h"
Expand All @@ -12,16 +11,13 @@ using namespace nixt;

namespace {

struct ReaderTest : testing::Test {
std::unique_ptr<nix::EvalState> State;
struct ReaderTest : StateTest {
nix::Pos::Origin O = nix::Pos::none_tag{};
DeserializeContext Ctx;
ValueMap VMap;
EnvMap EMap;
PtrPool<nix::Expr> Pool;
ReaderTest()
: State(new nix::EvalState{{}, nix::openStore("dummy://")}),
Ctx(getDeserializeContext(*State, ".", O)) {}
ReaderTest() : Ctx(getDeserializeContext(*State, ".", O)) {}
};

TEST_F(ReaderTest, AllGrammars) {
Expand Down
13 changes: 13 additions & 0 deletions libnixt/test/StateTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <gtest/gtest.h>

#include <nix/eval.hh>
#include <nix/store-api.hh>

namespace nixt {

struct StateTest : testing::Test {
std::unique_ptr<nix::EvalState> State;
StateTest() : State(new nix::EvalState{{}, nix::openStore("dummy://")}) {}
};

} // namespace nixt
48 changes: 48 additions & 0 deletions libnixt/test/Value.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "StateTest.h"

#include "nixt/Value.h"

using namespace nixt;

namespace {

struct ValueTest : StateTest {
nix::SourcePath cwd() { return State->rootPath(nix::CanonPath::fromCwd()); }
};

TEST_F(ValueTest, IsOption_neg) {
nix::Expr *AST = State->parseExprFromString("1", cwd());
nix::Value V;
State->eval(AST, V);

ASSERT_FALSE(isOption(*State, V));
}

TEST_F(ValueTest, IsOption_pos) {
nix::Expr *AST =
State->parseExprFromString(R"({ _type = "option"; })", cwd());
nix::Value V;
State->eval(AST, V);

ASSERT_TRUE(isOption(*State, V));
}

TEST_F(ValueTest, IsDerivation_neg) {
nix::Expr *AST =
State->parseExprFromString(R"({ _type = "option"; })", cwd());
nix::Value V;
State->eval(AST, V);

ASSERT_FALSE(isDerivation(*State, V));
}

TEST_F(ValueTest, IsDerivation_pos) {
nix::Expr *AST =
State->parseExprFromString(R"({ type = "derivation"; })", cwd());
nix::Value V;
State->eval(AST, V);

ASSERT_TRUE(isDerivation(*State, V));
}

} // namespace

0 comments on commit c217f09

Please sign in to comment.