refactor(tvix): Clean up MixEvalArgs internals

Previously, MixEvalArgs (a generic data type used to handle --arg,
--argstr, and -I arguments to `nix-build`, `nix eval`, etc.) was storing
the difference between --arg and --argstr by prepending a single
character (either 'E' or 'S') to the value of the arg. This is messy and
un-type-safe, so this commit refactors that to use a proper enum and a
std::pair, which allows us to add a switch and get totality checking.
yay, types!

Change-Id: I883f8db3136d05dda190fac0a1b494386c2ff87b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1862
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
Griffin Smith 2020-08-27 11:28:43 -04:00 committed by glittershark
parent 4ff9d5dee8
commit 3bada1d41e
2 changed files with 23 additions and 13 deletions

View file

@ -12,15 +12,17 @@ MixEvalArgs::MixEvalArgs() {
.longName("arg") .longName("arg")
.description("argument to be passed to Nix functions") .description("argument to be passed to Nix functions")
.labels({"name", "expr"}) .labels({"name", "expr"})
.handler( .handler([&](std::vector<std::string> ss) {
[&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'E' + ss[1]; }); auto_args_[ss[0]] = std::make_pair(kArgTypeExpr, ss[1]);
});
mkFlag() mkFlag()
.longName("argstr") .longName("argstr")
.description("string-valued argument to be passed to Nix functions") .description("string-valued argument to be passed to Nix functions")
.labels({"name", "string"}) .labels({"name", "string"})
.handler( .handler([&](std::vector<std::string> ss) {
[&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'S' + ss[1]; }); auto_args_[ss[0]] = std::make_pair(kArgTypeString, ss[1]);
});
mkFlag() mkFlag()
.shortName('I') .shortName('I')
@ -33,16 +35,22 @@ MixEvalArgs::MixEvalArgs() {
} }
std::unique_ptr<Bindings> MixEvalArgs::getAutoArgs(EvalState& state) { std::unique_ptr<Bindings> MixEvalArgs::getAutoArgs(EvalState& state) {
auto res = Bindings::New(autoArgs.size()); auto res = Bindings::New(auto_args_.size());
for (auto& i : autoArgs) { for (auto& [arg, arg_value] : auto_args_) {
Value* v = state.allocValue(); Value* v = state.allocValue();
if (i.second[0] == 'E') { switch (arg_value.first) {
state.mkThunk_(*v, state.parseExprFromString(std::string(i.second, 1), case kArgTypeExpr: {
absPath("."))); state.mkThunk_(
} else { *v, state.parseExprFromString(arg_value.second, absPath(".")));
mkString(*v, std::string(i.second, 1)); break;
} }
res->push_back(Attr(state.symbols.Create(i.first), v)); case kArgTypeString: {
mkString(*v, arg_value.second);
break;
}
}
res->push_back(Attr(state.symbols.Create(arg), v));
} }
return res; return res;
} }

View file

@ -8,6 +8,8 @@ class Store;
class EvalState; class EvalState;
class Bindings; class Bindings;
enum ArgType { kArgTypeString, kArgTypeExpr };
struct MixEvalArgs : virtual Args { struct MixEvalArgs : virtual Args {
MixEvalArgs(); MixEvalArgs();
@ -16,7 +18,7 @@ struct MixEvalArgs : virtual Args {
Strings searchPath; Strings searchPath;
private: private:
std::map<std::string, std::string> autoArgs; std::map<std::string, std::pair<ArgType, std::string>> auto_args_;
}; };
Path lookupFileArg(EvalState& state, std::string s); Path lookupFileArg(EvalState& state, std::string s);