mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-26 15:56:18 +02:00
libexpr: Check primop arity earlier
This commit is contained in:
parent
ba3cb4a049
commit
0daccb1121
4 changed files with 33 additions and 10 deletions
|
@ -723,6 +723,23 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrimOp::check()
|
||||||
|
{
|
||||||
|
if (arity > maxPrimOpArity) {
|
||||||
|
throw Error("primop arity must not exceed %1%", maxPrimOpArity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Value::mkPrimOp(PrimOp * p)
|
||||||
|
{
|
||||||
|
p->check();
|
||||||
|
clearValue();
|
||||||
|
internalType = tPrimOp;
|
||||||
|
primOp = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Value * EvalState::addPrimOp(PrimOp && primOp)
|
Value * EvalState::addPrimOp(PrimOp && primOp)
|
||||||
{
|
{
|
||||||
/* Hack to make constants lazy: turn them into a application of
|
/* Hack to make constants lazy: turn them into a application of
|
||||||
|
@ -1692,8 +1709,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
/* We have all the arguments, so call the primop with
|
/* We have all the arguments, so call the primop with
|
||||||
the previous and new arguments. */
|
the previous and new arguments. */
|
||||||
|
|
||||||
assert(arity < 64);
|
Value * vArgs[maxPrimOpArity];
|
||||||
Value * vArgs[64];
|
|
||||||
auto n = argsDone;
|
auto n = argsDone;
|
||||||
for (Value * arg = &vCur; arg->isPrimOpApp(); arg = arg->primOpApp.left)
|
for (Value * arg = &vCur; arg->isPrimOpApp(); arg = arg->primOpApp.left)
|
||||||
vArgs[--n] = arg->primOpApp.right;
|
vArgs[--n] = arg->primOpApp.right;
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We put a limit on primop arity because it lets us use a fixed size array on
|
||||||
|
* the stack. 16 is already an impractical number of arguments. Use an attrset
|
||||||
|
* argument for such overly complicated functions.
|
||||||
|
*/
|
||||||
|
constexpr size_t maxPrimOpArity = 64;
|
||||||
|
|
||||||
class Store;
|
class Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
|
@ -71,6 +77,12 @@ struct PrimOp
|
||||||
* Optional experimental for this to be gated on.
|
* Optional experimental for this to be gated on.
|
||||||
*/
|
*/
|
||||||
std::optional<ExperimentalFeature> experimentalFeature;
|
std::optional<ExperimentalFeature> experimentalFeature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validity check to be performed by functions that introduce primops,
|
||||||
|
* such as RegisterPrimOp() and Value::mkPrimOp().
|
||||||
|
*/
|
||||||
|
void check();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -114,7 +114,8 @@ TEST_F(ValuePrintingTests, vLambda)
|
||||||
TEST_F(ValuePrintingTests, vPrimOp)
|
TEST_F(ValuePrintingTests, vPrimOp)
|
||||||
{
|
{
|
||||||
Value vPrimOp;
|
Value vPrimOp;
|
||||||
vPrimOp.mkPrimOp(nullptr);
|
PrimOp primOp{};
|
||||||
|
vPrimOp.mkPrimOp(&primOp);
|
||||||
|
|
||||||
test(vPrimOp, "<PRIMOP>");
|
test(vPrimOp, "<PRIMOP>");
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,13 +354,7 @@ public:
|
||||||
// Value will be overridden anyways
|
// Value will be overridden anyways
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkPrimOp(PrimOp * p)
|
void mkPrimOp(PrimOp * p);
|
||||||
{
|
|
||||||
clearValue();
|
|
||||||
internalType = tPrimOp;
|
|
||||||
primOp = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void mkPrimOpApp(Value * l, Value * r)
|
inline void mkPrimOpApp(Value * l, Value * r)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue