libexpr: sort binding name in debugger

not doing this exposes the binding name order to the annoying
interference of parse order on symbol order, which wouldn't be so bad if
it didn't make the tests less reliable and, importantly, dependent on
linker behavior (due to primop initialization being done in static
initializer, and the order of static initializers being defined only
within a single translation unit).

fixes #143

Change-Id: I3cf417893fbcf19e9ad3ff8986deb7cbcf3ca511
This commit is contained in:
eldritch horrors 2024-03-18 20:03:31 +01:00
parent 47a237f7ec
commit b3599166ad
3 changed files with 26 additions and 16 deletions

View file

@ -677,12 +677,21 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
} }
static std::set<std::string_view> sortedBindingNames(const SymbolTable & st, const StaticEnv & se)
{
std::set<std::string_view> bindings;
for (auto [symbol, displ] : se.vars)
bindings.emplace(st[symbol]);
return bindings;
}
// just for the current level of StaticEnv, not the whole chain. // just for the current level of StaticEnv, not the whole chain.
void printStaticEnvBindings(const SymbolTable & st, const StaticEnv & se) void printStaticEnvBindings(const SymbolTable & st, const StaticEnv & se)
{ {
std::cout << ANSI_MAGENTA; std::cout << ANSI_MAGENTA;
for (auto & i : se.vars) for (auto & i : sortedBindingNames(st, se))
std::cout << st[i.first] << " "; std::cout << i << " ";
std::cout << ANSI_NORMAL; std::cout << ANSI_NORMAL;
std::cout << std::endl; std::cout << std::endl;
} }
@ -691,13 +700,14 @@ void printStaticEnvBindings(const SymbolTable & st, const StaticEnv & se)
void printWithBindings(const SymbolTable & st, const Env & env) void printWithBindings(const SymbolTable & st, const Env & env)
{ {
if (!env.values[0]->isThunk()) { if (!env.values[0]->isThunk()) {
std::set<std::string_view> bindings;
for (const auto & attr : *env.values[0]->attrs)
bindings.emplace(st[attr.name]);
std::cout << "with: "; std::cout << "with: ";
std::cout << ANSI_MAGENTA; std::cout << ANSI_MAGENTA;
Bindings::iterator j = env.values[0]->attrs->begin(); for (auto & i : bindings)
while (j != env.values[0]->attrs->end()) { std::cout << i << " ";
std::cout << st[j->name] << " ";
++j;
}
std::cout << ANSI_NORMAL; std::cout << ANSI_NORMAL;
std::cout << std::endl; std::cout << std::endl;
} }
@ -718,9 +728,9 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
std::cout << ANSI_MAGENTA; std::cout << ANSI_MAGENTA;
// for the top level, don't print the double underscore ones; // for the top level, don't print the double underscore ones;
// they are in builtins. // they are in builtins.
for (auto & i : se.vars) for (auto & i : sortedBindingNames(st, se))
if (!std::string_view(st[i.first]).starts_with("__")) if (!i.starts_with("__"))
std::cout << st[i.first] << " "; std::cout << i << " ";
std::cout << ANSI_NORMAL; std::cout << ANSI_NORMAL;
std::cout << std::endl; std::cout << std::endl;
if (se.isWith) if (se.isWith)

View file

@ -10,7 +10,7 @@ We expect to be able to see locals like r in the debugger:
nix-repl> :env nix-repl> :env
Env level 0 Env level 0
static: x r static: r x
Env level 1 Env level 1
builtins true false null scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString fetchMercurial fetchTree fetchTarball fetchGit fromTOML derivation abort baseNameOf break builtins derivation derivationStrict dirOf false fetchGit fetchMercurial fetchTarball fetchTree fromTOML import isNull map null placeholder removeAttrs scopedImport throw toString true

View file

@ -14,7 +14,7 @@ as it is in scope.
static: a b static: a b
Env level 2 Env level 2
builtins true false null scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString fetchMercurial fetchTree fetchTarball fetchGit fromTOML derivation abort baseNameOf break builtins derivation derivationStrict dirOf false fetchGit fetchMercurial fetchTarball fetchTree fromTOML import isNull map null placeholder removeAttrs scopedImport throw toString true
nix-repl> meow nix-repl> meow
2 2
@ -35,7 +35,7 @@ If we :st past the frame in the backtrace with the meow in it, the meow should n
static: a b static: a b
Env level 1 Env level 1
builtins true false null scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString fetchMercurial fetchTree fetchTarball fetchGit fromTOML derivation abort baseNameOf break builtins derivation derivationStrict dirOf false fetchGit fetchMercurial fetchTarball fetchTree fromTOML import isNull map null placeholder removeAttrs scopedImport throw toString true
nix-repl> :c nix-repl> :c
trace: before inner break trace: before inner break
@ -52,7 +52,7 @@ If we :st past the frame in the backtrace with the meow in it, the meow should n
static: a b static: a b
Env level 2 Env level 2
builtins true false null scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString fetchMercurial fetchTree fetchTarball fetchGit fromTOML derivation abort baseNameOf break builtins derivation derivationStrict dirOf false fetchGit fetchMercurial fetchTarball fetchTree fromTOML import isNull map null placeholder removeAttrs scopedImport throw toString true
nix-repl> meow' nix-repl> meow'
3 3
@ -71,4 +71,4 @@ If we :st past the frame in the backtrace with the meow in it, the meow should n
static: a b static: a b
Env level 1 Env level 1
builtins true false null scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString fetchMercurial fetchTree fetchTarball fetchGit fromTOML derivation abort baseNameOf break builtins derivation derivationStrict dirOf false fetchGit fetchMercurial fetchTarball fetchTree fromTOML import isNull map null placeholder removeAttrs scopedImport throw toString true