-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
WIP: init seqWithCallPos #12715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
WIP: init seqWithCallPos #12715
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
let | ||
showPos = | ||
pos: if pos == null then "" else "${pos.file}:${toString pos.line}:${toString pos.column}"; | ||
|
||
# ({pos,isThunk, printValue} -> a -> b ) -> (a -> c) -> a -> c | ||
tracePos = builtins.seqWithCallPos ( | ||
{ | ||
pos, | ||
printValue, | ||
terminalWidth, | ||
... | ||
}: | ||
a: | ||
let | ||
msg = "${showPos pos} ${printValue a}"; | ||
in | ||
builtins.seq a builtins.trace msg null | ||
) (a: a); | ||
in | ||
tracePos 42 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs to be converted to a test, but we should probably get some feedback from the Nix team first. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. This file was mainly to show what would be possible. Before i go ahead and clean this up it should be discussed in the team if this is wanted at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some more examples how this can be useful, would be probably helpful to motivate. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
#include "value-to-xml.hh" | ||
#include "primops.hh" | ||
#include "fetch-to-store.hh" | ||
#include "terminal.hh" | ||
#include <span> | ||
|
||
#include <boost/container/small_vector.hpp> | ||
#include <nlohmann/json.hpp> | ||
|
@@ -513,6 +515,97 @@ static RegisterPrimOp primop_isFunction({ | |
.fun = prim_isFunction, | ||
}); | ||
|
||
void prim_isThunk(EvalState & state, const PosIdx pos, Value * * args, Value & v) | ||
{ | ||
auto &arg = *args[0]; | ||
v.mkBool(arg.isThunk()); | ||
} | ||
|
||
static RegisterPrimOp primop_isThunk({ | ||
.name = "isThunk", | ||
.args = {"v"}, | ||
.doc = R"( | ||
Returns `true` if the argument is a thunk, `false` otherwise. | ||
|
||
This is internal, because the thunk-ness of a value is not a stable property, while the Nix language is meant to be referentially transparent. | ||
)", | ||
.fun = prim_isThunk, | ||
.internal = true | ||
}); | ||
|
||
void prim_printValue(EvalState & state, const PosIdx pos, Value * * args, Value & v) | ||
{ | ||
auto &arg = *args[0]; | ||
std::stringstream ss; | ||
printValue(state, ss, arg); | ||
v.mkString(ss.str()); | ||
} | ||
|
||
static RegisterPrimOp primop_printValue({ | ||
.name = "printValue", | ||
.args = {"v"}, | ||
.doc = R"( | ||
Print any value to an informative string. | ||
|
||
This is internal, because the format is not a stable behavior, while the Nix language is meant to be stable over time. | ||
)", | ||
.fun = prim_printValue, | ||
.internal = true | ||
}); | ||
|
||
|
||
/* Determine whether the argument is an integer. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong description? |
||
static void prim_seqWithCallPos(EvalState & state, const PosIdx pos, Value * * args, Value & v) | ||
{ | ||
auto p = args[0]; | ||
auto f = args[1]; | ||
auto a = args[2]; | ||
state.forceValue(*args[0], pos); | ||
state.forceValue(*args[1], pos); | ||
auto intro_args = state.buildBindings(4); | ||
auto pos_attrs = state.allocValue(); | ||
intro_args.insert(state.symbols.create("pos"), pos_attrs, noPos); | ||
|
||
auto vIsThunk = get(state.internalPrimOps, "isThunk"); | ||
assert(vIsThunk); | ||
intro_args.insert(state.symbols.create("isThunk"), *vIsThunk, noPos); | ||
|
||
auto vPrintValue = get(state.internalPrimOps, "printValue"); | ||
assert(vPrintValue); | ||
intro_args.insert(state.symbols.create("printValue"), *vPrintValue, noPos); | ||
|
||
auto [rows,cols] = getWindowSize(); | ||
auto vCols = state.allocValue(); | ||
vCols->mkInt(cols); | ||
intro_args.insert(state.symbols.create("terminalWidth"), vCols , noPos); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed this builtin in the PR and propose to leave out the terminalWidth for the first iteration. |
||
|
||
Value intro_args_value; | ||
intro_args_value.mkAttrs(intro_args); | ||
state.mkPos(*pos_attrs, pos); | ||
|
||
Value * pargs[2] = {&intro_args_value, a}; | ||
|
||
Value * _pRes = state.allocValue(); | ||
try { | ||
state.callFunction(*p, std::span<Value *>(pargs, 2), *_pRes, pos); | ||
} catch (Error & e) { | ||
e.addTrace(state.positions[pos], "while calling the first function passed to builtins.seqWithCallPos"); | ||
ignoreExceptionExceptInterrupt(lvlDebug); | ||
} | ||
|
||
state.callFunction(*f, *a, v, pos); | ||
} | ||
|
||
static RegisterPrimOp primop_seqWithCallPos({ | ||
.name = "__seqWithCallPos", | ||
.args = {"p", "f", "a"}, | ||
.doc = R"( | ||
Stuff | ||
)", | ||
.fun = prim_seqWithCallPos, | ||
}); | ||
|
||
|
||
/* Determine whether the argument is an integer. */ | ||
static void prim_isInt(EvalState & state, const PosIdx pos, Value * * args, Value & v) | ||
{ | ||
|
Uh oh!
There was an error while loading. Please reload this page.