libexpr: fix app chain extension
during the value rewrite we accidentally broke extension of incomplete primop application. this only shows up when binding on incomplete call to a primop to a name, binding an incomplete call to *that* to another name, and then finally calling the second binding with enough args for a complete primop application. since this only shows up when calling a primop with three or more args it took a while to surface. we have few builtins that match this: foldl', replaceStrings, and substring. these are not used incompletely in this manner very often, so this lingered. fixes #1102 Change-Id: I218dffc14ae876efc86a86c7eb6c895e2405201c
This commit is contained in:
@@ -20,11 +20,21 @@ inline Value::Value(app_t, EvalMemory & mem, Value & lhs, Value & rhs)
|
||||
}
|
||||
|
||||
inline Value::Value(app_t, EvalMemory & mem, Value & lhs, std::span<Value> args)
|
||||
: Value(app_t{}, mem, lhs, args, {})
|
||||
{
|
||||
auto app = static_cast<Value::App *>(mem.allocBytes(sizeof(Value::App) + args.size_bytes()));
|
||||
}
|
||||
|
||||
inline Value::Value(
|
||||
app_t, EvalMemory & mem, const Value & lhs, std::span<Value> baseArgs, std::span<Value> moreArgs
|
||||
)
|
||||
{
|
||||
auto app = static_cast<Value::App *>(
|
||||
mem.allocBytes(sizeof(Value::App) + baseArgs.size_bytes() + moreArgs.size_bytes())
|
||||
);
|
||||
app->_left = lhs;
|
||||
app->_n = args.size();
|
||||
std::copy(args.begin(), args.end(), app->_args);
|
||||
app->_n = baseArgs.size() + moreArgs.size();
|
||||
std::copy(baseArgs.begin(), baseArgs.end(), app->_args);
|
||||
std::copy(moreArgs.begin(), moreArgs.end(), app->_args + baseArgs.size());
|
||||
raw = tag(tApp, app);
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -1138,7 +1138,14 @@ void EvalState::callFunction(Value & fun, std::span<Value> args, Value & vRes, c
|
||||
|
||||
Value vCur(fun);
|
||||
|
||||
auto makeAppChain = [&]() { vRes = {NewValueAs::app, ctx.mem, vCur, args}; };
|
||||
auto makeAppChain = [&]() {
|
||||
if (vCur.isApp()) {
|
||||
auto & app = vCur.app();
|
||||
vRes = {NewValueAs::app, ctx.mem, app.left(), app.args(), args};
|
||||
} else {
|
||||
vRes = {NewValueAs::app, ctx.mem, vCur, args};
|
||||
}
|
||||
};
|
||||
|
||||
const Attr * functor;
|
||||
|
||||
|
||||
@@ -544,6 +544,10 @@ public:
|
||||
/// lazy and/or partial application of a function.
|
||||
Value(app_t, EvalMemory & mem, Value & lhs, std::span<Value> args);
|
||||
|
||||
/// Constructs a nix language value of type "lambda", which represents a
|
||||
/// lazy and/or partial application of a function.
|
||||
Value(app_t, EvalMemory & mem, const Value & lhs, std::span<Value> baseArgs, std::span<Value> moreArgs);
|
||||
|
||||
/// Constructs a nix language value of type "external", which is only used
|
||||
/// by plugins. Do any existing plugins even use this mechanism?
|
||||
Value(external_t, ExternalValueBase & external)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"234"
|
||||
@@ -0,0 +1,5 @@
|
||||
let
|
||||
a = builtins.substring 1;
|
||||
b = a 3;
|
||||
in
|
||||
b "1234567890"
|
||||
Reference in New Issue
Block a user