Skip to content

Commit

Permalink
nixd: general cleanups (#240)
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc authored Aug 11, 2023
2 parents 3a7c998 + a44b8db commit 1b5f8b0
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 131 deletions.
11 changes: 7 additions & 4 deletions nixd/include/nixd/AST/EvalAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@ class EvalAST : public ParseAST {
/// Inject myself into nix cache.
void injectAST(nix::EvalState &State, lspserver::PathRef Path) const;

std::optional<nix::Value> searchUpValue(const nix::Expr *Expr) const;

/// Try to search (traverse) up the expr and find the first `Env` associated
/// ancestor, return its env
nix::Env *searchUpEnv(const nix::Expr *Expr) const;

/// Similar to `searchUpEnv`, but search for Values
nix::Value searchUpValue(const nix::Expr *Expr) const;
std::optional<nix::Value>
getValueStatic(const nix::Expr *Expr) const noexcept;

/// Get the evaluation result (fixed point) of the expression.
nix::Value getValue(const nix::Expr *Expr) const;
std::optional<nix::Value> getValue(const nix::Expr *Expr) const noexcept;

nix::Value getValueEval(const nix::Expr *Expr, nix::EvalState &State) const;
std::optional<nix::Value> getValueEval(const nix::Expr *Expr,
nix::EvalState &State) const noexcept;

/// Get the corresponding 'Env' while evaluating the expression.
/// nix 'Env's contains dynamic variable name bindings at evaluation, might
Expand Down
14 changes: 10 additions & 4 deletions nixd/include/nixd/AST/ParseAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class ParseAST {
return nPair(getDisplOf(E, Displ));
}

std::optional<lspserver::Range> lRange(const void *Ptr) const {
std::optional<lspserver::Range> lRange(const void *Ptr) const noexcept {
try {
return toLSPRange(nRange(Ptr));
} catch (...) {
Expand All @@ -147,20 +147,26 @@ class ParseAST {
/// Lookup an AST node that ends before or on the cursor.
/// { } |
/// ^
[[nodiscard]] const nix::Expr *lookupEnd(lspserver::Position Desired) const;
/// @returns nullptr, if not found
[[nodiscard]] const nix::Expr *
lookupEnd(lspserver::Position Desired) const noexcept;

/// Lookup AST nodes that contains the cursor
/// { | }
/// ^~~~~~~~^
///
/// @returns empty vector, if there is no such expression
[[nodiscard]] std::vector<const nix::Expr *>
lookupContain(lspserver::Position Desired) const;
lookupContain(lspserver::Position Desired) const noexcept;

[[nodiscard]] const nix::Expr *
lookupContainMin(lspserver::Position Desired) const;
lookupContainMin(lspserver::Position Desired) const noexcept;

/// Lookup an AST node that starts after or on the cursor
/// | { }
/// ^
///
/// @returns nullptr, if not found
[[nodiscard]] const nix::Expr *lookupStart(lspserver::Position Desired) const;

void collectSymbols(const nix::Expr *E, std::vector<nix::Symbol> &R) const {
Expand Down
4 changes: 2 additions & 2 deletions nixd/include/nixd/Nix/Option.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <optional>
#include <string>

namespace nix::nixd {
namespace nixd {
struct OptionInfo {
std::optional<std::string> Type;
std::optional<std::string> Description;
Expand All @@ -15,4 +15,4 @@ struct OptionInfo {
};

OptionInfo optionInfo(nix::EvalState &State, nix::Value &V);
} // namespace nix::nixd
} // namespace nixd
8 changes: 4 additions & 4 deletions nixd/include/nixd/Nix/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
#include <nix/attr-path.hh>
#include <nix/eval.hh>

namespace nix::nixd {
namespace nixd {

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

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

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

extern int PrintDepth;

} // namespace nix::nixd
} // namespace nixd
71 changes: 48 additions & 23 deletions nixd/lib/AST/EvalAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@ void EvalAST::rewriteAST() {
}
}

nix::Value EvalAST::getValue(const nix::Expr *Expr) const {
if (const auto *EV = dynamic_cast<const nix::ExprVar *>(Expr)) {
if (!EV->fromWith) {
const auto *EnvExpr = searchEnvExpr(EV, ParentMap);
if (const auto *EL = dynamic_cast<const nix::ExprLambda *>(EnvExpr)) {
const auto *F = EnvMap.at(EL->body);
return *F->values[EV->displ];
}
}
}
return ValueMap.at(Expr);
std::optional<nix::Value>
EvalAST::getValue(const nix::Expr *Expr) const noexcept {
if (auto OpStaticValue = getValueStatic(Expr))
return OpStaticValue;
if (ValueMap.contains(Expr))
return ValueMap.at(Expr);
return std::nullopt;
}

void EvalAST::injectAST(nix::EvalState &State, lspserver::PathRef Path) const {
Expand All @@ -45,7 +41,7 @@ void EvalAST::injectAST(nix::EvalState &State, lspserver::PathRef Path) const {
DummyValue);
}

nix::Value EvalAST::searchUpValue(const nix::Expr *Expr) const {
std::optional<nix::Value> EvalAST::searchUpValue(const nix::Expr *Expr) const {
for (;;) {
if (ValueMap.contains(Expr))
return ValueMap.at(Expr);
Expand All @@ -54,7 +50,7 @@ nix::Value EvalAST::searchUpValue(const nix::Expr *Expr) const {

Expr = parent(Expr);
}
throw std::out_of_range("No such value associated to ancestors");
return std::nullopt;
}

nix::Env *EvalAST::searchUpEnv(const nix::Expr *Expr) const {
Expand All @@ -66,20 +62,49 @@ nix::Env *EvalAST::searchUpEnv(const nix::Expr *Expr) const {

Expr = parent(Expr);
}
throw std::out_of_range("No such env associated to ancestors");
return nullptr;
}

nix::Value EvalAST::getValueEval(const nix::Expr *Expr,
nix::EvalState &State) const {
std::optional<nix::Value>
EvalAST::getValueEval(const nix::Expr *Expr,
nix::EvalState &State) const noexcept {
auto OpVCurrent = getValue(Expr);
if (OpVCurrent)
return OpVCurrent;

// It is not evaluated.
// Let's find evaluated parent, and try to eval it then.
auto OpVAncestor = searchUpValue(Expr);
if (!OpVAncestor)
return std::nullopt;

// TODO: add tests
try {
return getValue(Expr);
} catch (std::out_of_range &) {
// It is not evaluated.
// Let's find evaluated parent, and try to eval it then.
auto V = searchUpValue(Expr);
forceValueDepth(State, V, 2);
return getValue(Expr);
forceValueDepth(State, *OpVAncestor, 2);
} catch (...) {
}
return getValue(Expr);
}

std::optional<nix::Value>
EvalAST::getValueStatic(const nix::Expr *Expr) const noexcept {
const auto *EVar = dynamic_cast<const nix::ExprVar *>(Expr);
if (!EVar)
return std::nullopt;

if (EVar->fromWith)
return std::nullopt;

const auto *EnvExpr = searchEnvExpr(EVar, ParentMap);

// TODO: split this method, and make rec { }, let-binding available
const auto *ELambda = dynamic_cast<const nix::ExprLambda *>(EnvExpr);
if (!ELambda)
return std::nullopt;

if (!EnvMap.contains(ELambda->body))
return std::nullopt;
const auto *F = EnvMap.at(ELambda->body);
return *F->values[EVar->displ];
}
} // namespace nixd
10 changes: 5 additions & 5 deletions nixd/lib/AST/ParseAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ ParseAST::lookupDef(lspserver::Position Desired) const {
}

[[nodiscard]] const nix::Expr *
ParseAST::lookupEnd(lspserver::Position Desired) const {
ParseAST::lookupEnd(lspserver::Position Desired) const noexcept {
struct VTy : RecursiveASTVisitor<VTy> {
const ParseAST &This;

const nix::Expr *R;
const nix::Expr *R = nullptr;
lspserver::Position RStart = {INT_MAX, INT_MAX};
lspserver::Position REnd = {INT_MIN, INT_MIN};

Expand All @@ -52,7 +52,7 @@ ParseAST::lookupEnd(lspserver::Position Desired) const {
}

std::vector<const nix::Expr *>
ParseAST::lookupContain(lspserver::Position Desired) const {
ParseAST::lookupContain(lspserver::Position Desired) const noexcept {
struct VTy : RecursiveASTVisitor<VTy> {
const ParseAST &This;

Expand All @@ -73,7 +73,7 @@ ParseAST::lookupContain(lspserver::Position Desired) const {
}

[[nodiscard]] const nix::Expr *
ParseAST::lookupContainMin(lspserver::Position Desired) const {
ParseAST::lookupContainMin(lspserver::Position Desired) const noexcept {
struct VTy : RecursiveASTVisitor<VTy> {
const ParseAST &This;

Expand Down Expand Up @@ -103,7 +103,7 @@ ParseAST::lookupStart(lspserver::Position Desired) const {
struct VTy : RecursiveASTVisitor<VTy> {
const ParseAST &This;

const nix::Expr *R;
const nix::Expr *R = nullptr;
lspserver::Position RStart = {INT_MAX, INT_MAX};
lspserver::Position REnd = {INT_MIN, INT_MIN};

Expand Down
4 changes: 2 additions & 2 deletions nixd/lib/Nix/Option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#include <llvm/Support/FormatVariadic.h>

namespace nix::nixd {
namespace nixd {

OptionInfo optionInfo(nix::EvalState &State, nix::Value &V) {
OptionInfo Info;
Expand Down Expand Up @@ -41,4 +41,4 @@ std::string OptionInfo::mdDoc() {
Example, Description);
}

} // namespace nix::nixd
} // namespace nixd
16 changes: 8 additions & 8 deletions nixd/lib/Nix/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
#include <nix/eval.hh>
#include <nix/print.hh>

namespace nix::nixd {
namespace nixd {

bool isOption(EvalState &State, Value &V) {
State.forceValue(V, noPos);
if (V.type() != ValueType::nAttrs)
bool 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
auto S = attrPathStr(State, V, "_type");
return S && S.value() == "option";
};

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

// Derivations has a special attribute "type" == "derivation"
Expand All @@ -41,7 +41,7 @@ std::optional<std::string> attrPathStr(nix::EvalState &State, nix::Value &V,

int PrintDepth;

} // namespace nix::nixd
} // namespace nixd

namespace nix {

Expand Down
Loading

0 comments on commit 1b5f8b0

Please sign in to comment.