libexpr: move floats to auxiliary storage

floats are used very rarely, and our float support is bad enough to
strongly discourage using them on reproducibility grounds alone. we
can thus move them to more expensive storage without hurting folks.

Change-Id: I1086f612f85e294dd3fae4a2d334e09f52bbe4a8
This commit is contained in:
eldritch horrors
2025-09-28 00:02:20 +02:00
parent ce70234904
commit 5def7559a6
4 changed files with 35 additions and 18 deletions
+2
View File
@@ -107,6 +107,8 @@ std::string showType(const Value & v)
switch (v.auxiliary()->type) {
case Value::Acb::tExternal:
return v.external()->showType();
case Value::Acb::tFloat:
return std::string(showType(v.type()));
}
#pragma GCC diagnostic pop
case tThunk: return v.isBlackhole() ? "a black hole" : "a thunk";
+15 -2
View File
@@ -177,14 +177,27 @@ protected:
public:
ExprLiteral(const PosIdx pos, NewValueAs::integer_t, NixInt n) : Expr(pos) { v.mkInt(n); };
ExprLiteral(const PosIdx pos, NewValueAs::integer_t, NixInt::Inner n) : Expr(pos) { v.mkInt(n); };
ExprLiteral(const PosIdx pos, NewValueAs::floating_t, NixFloat nf) : Expr(pos) { v.mkFloat(nf); };
ExprLiteral(const PosIdx pos, NewValueAs::integer_t, NixInt::Inner n) : Expr(pos)
{
v.mkInt(n);
}
Value * maybeThunk(EvalState & state, Env & env) override;
JSON toJSON(const SymbolTable & symbols) const override;
void eval(EvalState & state, Env & env, Value & v) override;
void accept(ExprVisitor & ev, std::unique_ptr<Expr> & ptr) override { ev.visit(*this, ptr); }
};
struct ExprFloat : ExprLiteral
{
Value::Float f;
ExprFloat(const PosIdx pos, NewValueAs::floating_t, double f)
: ExprLiteral(pos)
, f{{Value::Acb::tFloat}, f}
{
v = Value(this->f);
}
};
struct ExprString : ExprLiteral
{
std::string s;
+1 -1
View File
@@ -542,7 +542,7 @@ template<> struct BuildAST<grammar::v1::expr::float_> {
});
}
}();
s.emplaceExpr<ExprLiteral>(ps.at(in), NewValueAs::floating, v);
s.emplaceExpr<ExprFloat>(ps.at(in), NewValueAs::floating, v);
}
};
+17 -15
View File
@@ -34,7 +34,6 @@ typedef enum {
tLambda,
tPrimOp,
tAuxiliary,
tFloat
} InternalType;
/**
@@ -259,11 +258,13 @@ public:
/// Constructs a nix language value of type "float", with the floating
/// point value of @ref f.
Value(floating_t, NixFloat f)
: internalType(tFloat)
, _fpoint(f)
, _float_pad(0)
{ }
Value(floating_t, NixFloat f) : internalType(tAuxiliary), _aux_pad(0)
{
auto fp = gcAllocType<Float>();
fp->type = Acb::tFloat;
fp->value = f;
_auxiliary = fp;
}
/// Constructs a nix language value of type "bool", with the boolean
/// value of @ref b.
@@ -638,12 +639,17 @@ public:
{
enum {
tExternal,
tFloat,
} type;
};
struct External : Acb
{
ExternalValueBase * external;
};
struct Float : Acb
{
NixFloat value;
};
union
{
@@ -688,10 +694,6 @@ public:
const Acb * _auxiliary;
uintptr_t _aux_pad;
};
struct {
NixFloat _fpoint;
uintptr_t _float_pad;
};
};
/**
@@ -719,8 +721,9 @@ public:
switch (_auxiliary->type) {
case Acb::tExternal:
return nExternal;
case Acb::tFloat:
return nFloat;
}
case tFloat: return nFloat;
case tThunk:
return nThunk;
case tApp:
@@ -834,9 +837,7 @@ public:
inline void mkFloat(NixFloat n)
{
clearValue();
internalType = tFloat;
_fpoint = n;
*this = {NewValueAs::floating, n};
}
bool isList() const
@@ -954,7 +955,8 @@ public:
NixFloat fpoint() const
{
return _fpoint;
assert(internalType == tAuxiliary && _auxiliary->type == Acb::tFloat);
return static_cast<const Float *>(_auxiliary)->value;
}
const Acb * auxiliary() const