mirror of
https://github.com/NixOS/nix
synced 2025-06-28 05:21:16 +02:00
Merge pull request #11304 from hercules-ci/repl-doc-functor
`:doc`: support `__functor`
This commit is contained in:
commit
88998fae74
6 changed files with 266 additions and 18 deletions
|
@ -4,6 +4,7 @@
|
|||
#include "print.hh"
|
||||
#include "eval.hh"
|
||||
#include "eval-error.hh"
|
||||
#include "eval-settings.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
@ -138,5 +139,12 @@ inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view e
|
|||
}
|
||||
}
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline CallDepth EvalState::addCallDepth(const PosIdx pos) {
|
||||
if (callDepth > settings.maxCallDepth)
|
||||
error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
|
||||
|
||||
return CallDepth(callDepth);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -616,6 +616,25 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
|
|||
strdup(ss.data()),
|
||||
};
|
||||
}
|
||||
if (isFunctor(v)) {
|
||||
try {
|
||||
Value & functor = *v.attrs()->find(sFunctor)->value;
|
||||
Value * vp = &v;
|
||||
Value partiallyApplied;
|
||||
// The first paramater is not user-provided, and may be
|
||||
// handled by code that is opaque to the user, like lib.const = x: y: y;
|
||||
// So preferably we show docs that are relevant to the
|
||||
// "partially applied" function returned by e.g. `const`.
|
||||
// We apply the first argument:
|
||||
callFunction(functor, 1, &vp, partiallyApplied, noPos);
|
||||
auto _level = addCallDepth(noPos);
|
||||
return getDoc(partiallyApplied);
|
||||
}
|
||||
catch (Error & e) {
|
||||
e.addTrace(nullptr, "while partially calling '%1%' to retrieve documentation", "__functor");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -1471,26 +1490,9 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v)
|
|||
v.mkLambda(&env, this);
|
||||
}
|
||||
|
||||
namespace {
|
||||
/** Increments a count on construction and decrements on destruction.
|
||||
*/
|
||||
class CallDepth {
|
||||
size_t & count;
|
||||
public:
|
||||
CallDepth(size_t & count) : count(count) {
|
||||
++count;
|
||||
}
|
||||
~CallDepth() {
|
||||
--count;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos)
|
||||
{
|
||||
if (callDepth > settings.maxCallDepth)
|
||||
error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
|
||||
CallDepth _level(callDepth);
|
||||
auto _level = addCallDepth(pos);
|
||||
|
||||
auto trace = settings.traceFunctionCalls
|
||||
? std::make_unique<FunctionCallTrace>(positions[pos])
|
||||
|
|
|
@ -41,6 +41,21 @@ namespace eval_cache {
|
|||
class EvalCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a count on construction and decrements on destruction.
|
||||
*/
|
||||
class CallDepth {
|
||||
size_t & count;
|
||||
|
||||
public:
|
||||
CallDepth(size_t & count) : count(count) {
|
||||
++count;
|
||||
}
|
||||
~CallDepth() {
|
||||
--count;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that implements a primop.
|
||||
*/
|
||||
|
@ -625,6 +640,12 @@ public:
|
|||
const char * doc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the documentation for a value. This will evaluate the value if
|
||||
* it is a thunk, and it will partially apply __functor if applicable.
|
||||
*
|
||||
* @param v The value to get the documentation for.
|
||||
*/
|
||||
std::optional<Doc> getDoc(Value & v);
|
||||
|
||||
private:
|
||||
|
@ -649,6 +670,11 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Check that the call depth is within limits, and increment it, until the returned object is destroyed.
|
||||
*/
|
||||
inline CallDepth addCallDepth(const PosIdx pos);
|
||||
|
||||
/**
|
||||
* Do a deep equality test between two values. That is, list
|
||||
* elements and attributes are compared recursively.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue