libexpr: move lambdas to auxiliary storage

Change-Id: Ibe4885f17c0ba1634ed6dbca0a45f8bd4619d69b
This commit is contained in:
eldritch horrors
2025-09-28 00:02:20 +02:00
parent 6e242e8b9b
commit 002dfbb2e3
4 changed files with 30 additions and 26 deletions
+9
View File
@@ -26,6 +26,15 @@ inline Value::Value(app_t, EvalMemory & mem, Value & lhs, std::span<Value *> arg
}
}
inline Value::Value(lambda_t, EvalMemory & mem, Env & env, ExprLambda & lambda)
: internalType(tAuxiliary)
, _aux_pad(0)
{
auto lp = mem.allocType<Lambda>();
*lp = Lambda{{Acb::tLambda}, &env, &lambda};
_auxiliary = lp;
}
[[gnu::always_inline]]
void * EvalMemory::allocBytes(size_t size)
{
+2 -1
View File
@@ -108,6 +108,7 @@ std::string showType(const Value & v)
return v.external()->showType();
case Value::Acb::tFloat:
case Value::Acb::tNull:
case Value::Acb::tLambda:
return std::string(showType(v.type()));
case Value::Acb::tPrimOp:
return fmt("the built-in function '%s'", v.primOp()->name);
@@ -1415,7 +1416,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
void ExprLambda::eval(EvalState & state, Env & env, Value & v)
{
v.mkLambda(&env, this);
v = {NewValueAs::lambda, state.ctx.mem, env, *this};
}
namespace {
+15 -21
View File
@@ -77,7 +77,6 @@ typedef enum {
tList,
tThunk,
tApp,
tLambda,
tAuxiliary,
} InternalType;
@@ -259,6 +258,7 @@ public:
struct String;
struct Acb;
struct Null;
struct Lambda;
static const Null NULL_ACB;
@@ -521,10 +521,7 @@ public:
/// This takes the environment the lambda is closed over @ref env, and
/// the lambda expression itself @ref lambda, which will not be evaluated
/// until it is applied.
Value(lambda_t, Env & env, ExprLambda & lambda)
: internalType(tLambda)
, _lambda({ .env = &env, .fun = &lambda })
{ }
Value(lambda_t, EvalMemory & mem, Env & env, ExprLambda & lambda);
/// Constructs an evil thunk, whose evaluation represents infinite recursion.
explicit Value(blackhole_t)
@@ -582,7 +579,10 @@ public:
}
// type() == nFunction
inline bool isLambda() const { return internalType == tLambda; };
inline bool isLambda() const
{
return internalType == tAuxiliary && _auxiliary->type == Acb::tLambda;
};
inline bool isPrimOp() const
{
return internalType == tAuxiliary && _auxiliary->type == Acb::tPrimOp;
@@ -690,6 +690,7 @@ public:
tFloat,
tNull,
tPrimOp,
tLambda,
} type;
};
struct External : Acb
@@ -706,6 +707,11 @@ public:
{
explicit PrimOp(PrimOpDetails && p) : Acb{tPrimOp}, PrimOpDetails(std::move(p)) {}
};
struct Lambda : Acb
{
Env * env;
ExprLambda * fun;
};
union
{
@@ -737,11 +743,6 @@ public:
Expr * expr;
} _thunk;
App _app;
struct
{
Env * env;
ExprLambda * fun;
} _lambda;
struct {
const Acb * _auxiliary;
uintptr_t _aux_pad;
@@ -765,8 +766,6 @@ public:
case tAttrs: return nAttrs;
case tList:
return nList;
case tLambda:
return nFunction;
case tAuxiliary:
switch (_auxiliary->type) {
case Acb::tExternal:
@@ -776,6 +775,7 @@ public:
case Acb::tNull:
return nNull;
case Acb::tPrimOp:
case Acb::tLambda:
return nFunction;
}
case tThunk:
@@ -868,13 +868,6 @@ public:
*this = {NewValueAs::app, *l, *r};
}
inline void mkLambda(Env * e, ExprLambda * f)
{
internalType = tLambda;
_lambda.env = e;
_lambda.fun = f;
}
inline void mkBlackhole()
{
internalType = tThunk;
@@ -992,7 +985,8 @@ public:
const auto & lambda() const
{
return _lambda;
assert(internalType == tAuxiliary && _auxiliary->type == Acb::tLambda);
return *static_cast<const Lambda *>(_auxiliary);
}
const PrimOp * primOp() const
+4 -4
View File
@@ -110,6 +110,7 @@ TEST_F(ValuePrintingTests, vApp)
TEST_F(ValuePrintingTests, vLambda)
{
EvalMemory mem;
Env env {
.up = nullptr,
.values = { }
@@ -120,8 +121,7 @@ TEST_F(ValuePrintingTests, vLambda)
ExprLambda eLambda(posIdx, std::make_unique<AttrsPattern>(), std::make_unique<ExprLiteral>(noPos, NewValueAs::integer, 0));
eLambda.pattern->name = createSymbol("a");
Value vLambda;
vLambda.mkLambda(&env, &eLambda);
Value vLambda{NewValueAs::lambda, mem, env, eLambda};
test(vLambda, "«lambda @ «none»:1:1»");
@@ -546,6 +546,7 @@ TEST_F(ValuePrintingTests, ansiColorsList)
TEST_F(ValuePrintingTests, ansiColorsLambda)
{
EvalMemory mem;
Env env {
.up = nullptr,
.values = { }
@@ -556,8 +557,7 @@ TEST_F(ValuePrintingTests, ansiColorsLambda)
ExprLambda eLambda(posIdx, std::make_unique<AttrsPattern>(), std::make_unique<ExprLiteral>(noPos, NewValueAs::integer, 0));
eLambda.pattern->name = createSymbol("a");
Value vLambda;
vLambda.mkLambda(&env, &eLambda);
Value vLambda{NewValueAs::lambda, mem, env, eLambda};
test(vLambda,
ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL,