aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2020-12-12 02:15:11 +0100
committerSilvan Mosberger <contact@infinisil.com>2020-12-12 03:31:50 +0100
commitbf9890396731a2bbe4f04a49684dee463d818906 (patch)
tree171d646c0540828a294346e887c214ba44b5472c
parent22ead43a0b8f94f5a4fb64cff14bf6a2a35d671c (diff)
Add ValueType checking functions for types that have the same NormalType
-rw-r--r--src/libexpr/eval-inline.hh6
-rw-r--r--src/libexpr/eval.cc20
-rw-r--r--src/libexpr/flake/flake.cc4
-rw-r--r--src/libexpr/primops.cc6
-rw-r--r--src/libexpr/value.hh14
-rw-r--r--src/nix/flake.cc6
-rw-r--r--src/nix/main.cc2
-rw-r--r--src/nix/repl.cc8
8 files changed, 40 insertions, 26 deletions
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index 9b644d5cb..8c40c2565 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -32,7 +32,7 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const
void EvalState::forceValue(Value & v, const Pos & pos)
{
- if (v.type == tThunk) {
+ if (v.isThunk()) {
Env * env = v.thunk.env;
Expr * expr = v.thunk.expr;
try {
@@ -46,9 +46,9 @@ void EvalState::forceValue(Value & v, const Pos & pos)
throw;
}
}
- else if (v.type == tApp)
+ else if (v.isApp())
callFunction(*v.app.left, *v.app.right, v, noPos);
- else if (v.type == tBlackhole)
+ else if (v.isBlackhole())
throwEvalError(pos, "infinite recursion encountered");
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index f33426b59..5f9d19b8d 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -158,10 +158,10 @@ std::ostream & operator << (std::ostream & str, const Value & v)
const Value *getPrimOp(const Value &v) {
const Value * primOp = &v;
- while (primOp->type == tPrimOpApp) {
+ while (primOp->isPrimOpApp()) {
primOp = primOp->primOpApp.left;
}
- assert(primOp->type == tPrimOp);
+ assert(primOp->isPrimOp());
return primOp;
}
@@ -601,9 +601,9 @@ Value & EvalState::getBuiltin(const string & name)
std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
{
- if (v.type == tPrimOp || v.type == tPrimOpApp) {
+ if (v.isPrimOp() || v.isPrimOpApp()) {
auto v2 = &v;
- while (v2->type == tPrimOpApp)
+ while (v2->isPrimOpApp())
v2 = v2->primOpApp.left;
if (v2->primOp->doc)
return Doc {
@@ -1227,11 +1227,11 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
/* Figure out the number of arguments still needed. */
size_t argsDone = 0;
Value * primOp = &fun;
- while (primOp->type == tPrimOpApp) {
+ while (primOp->isPrimOpApp()) {
argsDone++;
primOp = primOp->primOpApp.left;
}
- assert(primOp->type == tPrimOp);
+ assert(primOp->isPrimOp());
auto arity = primOp->primOp->arity;
auto argsLeft = arity - argsDone;
@@ -1242,7 +1242,7 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
Value * vArgs[arity];
auto n = arity - 1;
vArgs[n--] = &arg;
- for (Value * arg = &fun; arg->type == tPrimOpApp; arg = arg->primOpApp.left)
+ for (Value * arg = &fun; arg->isPrimOpApp(); arg = arg->primOpApp.left)
vArgs[n--] = arg->primOpApp.right;
/* And call the primop. */
@@ -1264,7 +1264,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
forceValue(fun, pos);
- if (fun.type == tPrimOp || fun.type == tPrimOpApp) {
+ if (fun.isPrimOp() || fun.isPrimOpApp()) {
callPrimOp(fun, arg, v, pos);
return;
}
@@ -1285,7 +1285,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
}
}
- if (fun.type != tLambda)
+ if (!fun.isLambda())
throwTypeError(pos, "attempt to call something which is not a function but %1%", fun);
ExprLambda & lambda(*fun.lambda.fun);
@@ -1378,7 +1378,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
}
}
- if (fun.type != tLambda || !fun.lambda.fun->matchAttrs) {
+ if (!fun.isLambda() || !fun.lambda.fun->matchAttrs) {
res = fun;
return;
}
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index c126b2c40..2f9658ab8 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -73,7 +73,7 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
static void forceTrivialValue(EvalState & state, Value & value, const Pos & pos)
{
- if (value.type == tThunk && value.isTrivial())
+ if (value.isThunk() && value.isTrivial())
state.forceValue(value, pos);
}
@@ -216,7 +216,7 @@ static Flake getFlake(
if (auto outputs = vInfo.attrs->get(sOutputs)) {
expectType(state, nFunction, *outputs->value, *outputs->pos);
- if (outputs->value->type == tLambda && outputs->value->lambda.fun->matchAttrs) {
+ if (outputs->value->isLambda() && outputs->value->lambda.fun->matchAttrs) {
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
if (formal.name != state.sSelf)
flake.inputs.emplace(formal.name, FlakeInput {
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index d501f7482..f6ca612f4 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -2239,11 +2239,11 @@ static RegisterPrimOp primop_catAttrs({
static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
- if (args[0]->type == tPrimOpApp || args[0]->type == tPrimOp) {
+ if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) {
state.mkAttrs(v, 0);
return;
}
- if (args[0]->type != tLambda)
+ if (!args[0]->isLambda())
throw TypeError({
.hint = hintfmt("'functionArgs' requires a function"),
.errPos = pos
@@ -2674,7 +2674,7 @@ static void prim_sort(EvalState & state, const Pos & pos, Value * * args, Value
auto comparator = [&](Value * a, Value * b) {
/* Optimization: if the comparator is lessThan, bypass
callFunction. */
- if (args[0]->type == tPrimOp && args[0]->primOp->fun == prim_lessThan)
+ if (args[0]->isPrimOp() && args[0]->primOp->fun == prim_lessThan)
return CompareValues()(a, b);
Value vTmp1, vTmp2;
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index 0995dcd7b..e743da9c3 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -126,6 +126,20 @@ struct Value
inline void setExternal() { type = tExternal; };
inline void setFloat() { type = tFloat; };
+ // Functions needed to distinguish the type
+ // These should be removed eventually, by putting the functionality that's
+ // needed by callers into methods of this type
+
+ // normalType() == nThunk
+ inline bool isThunk() const { return type == tThunk; };
+ inline bool isApp() const { return type == tApp; };
+ inline bool isBlackhole() const { return type == tBlackhole; };
+
+ // normalType() == nFunction
+ inline bool isLambda() const { return type == tLambda; };
+ inline bool isPrimOp() const { return type == tPrimOp; };
+ inline bool isPrimOpApp() const { return type == tPrimOpApp; };
+
union
{
NixInt integer;
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 80b050091..e4da0348c 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -260,7 +260,7 @@ struct CmdFlakeCheck : FlakeCommand
auto checkOverlay = [&](const std::string & attrPath, Value & v, const Pos & pos) {
try {
state->forceValue(v, pos);
- if (v.type != tLambda || v.lambda.fun->matchAttrs || std::string(v.lambda.fun->arg) != "final")
+ if (!v.isLambda() || v.lambda.fun->matchAttrs || std::string(v.lambda.fun->arg) != "final")
throw Error("overlay does not take an argument named 'final'");
auto body = dynamic_cast<ExprLambda *>(v.lambda.fun->body);
if (!body || body->matchAttrs || std::string(body->arg) != "prev")
@@ -276,7 +276,7 @@ struct CmdFlakeCheck : FlakeCommand
auto checkModule = [&](const std::string & attrPath, Value & v, const Pos & pos) {
try {
state->forceValue(v, pos);
- if (v.type == tLambda) {
+ if (v.isLambda()) {
if (!v.lambda.fun->matchAttrs || !v.lambda.fun->formals->ellipsis)
throw Error("module must match an open attribute set ('{ config, ... }')");
} else if (v.normalType() == nAttrs) {
@@ -371,7 +371,7 @@ struct CmdFlakeCheck : FlakeCommand
auto checkBundler = [&](const std::string & attrPath, Value & v, const Pos & pos) {
try {
state->forceValue(v, pos);
- if (v.type != tLambda)
+ if (!v.isLambda())
throw Error("bundler must be a function");
if (!v.lambda.fun->formals ||
v.lambda.fun->formals->argNames.find(state->symbols.create("program")) == v.lambda.fun->formals->argNames.end() ||
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 27b1d7257..e7a15dec9 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -272,7 +272,7 @@ void mainWrapped(int argc, char * * argv)
auto builtins = state.baseEnv.values[0]->attrs;
for (auto & builtin : *builtins) {
auto b = nlohmann::json::object();
- if (builtin.value->type != tPrimOp) continue;
+ if (!builtin.value->isPrimOp()) continue;
auto primOp = builtin.value->primOp;
if (!primOp->doc) continue;
b["arity"] = primOp->arity;
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 56184efb9..047e2dc59 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -450,7 +450,7 @@ bool NixRepl::processLine(string line)
PathSet context;
auto filename = state->coerceToString(noPos, v, context);
pos.file = state->symbols.create(filename);
- } else if (v.type == tLambda) {
+ } else if (v.isLambda()) {
pos = v.lambda.fun->pos;
} else {
// assume it's a derivation
@@ -760,13 +760,13 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
break;
case nFunction:
- if (v.type == tLambda) {
+ if (v.isLambda()) {
std::ostringstream s;
s << v.lambda.fun->pos;
str << ANSI_BLUE "«lambda @ " << filterANSIEscapes(s.str()) << "»" ANSI_NORMAL;
- } else if (v.type == tPrimOp) {
+ } else if (v.isPrimOp()) {
str << ANSI_MAGENTA "«primop»" ANSI_NORMAL;
- } else if (v.type == tPrimOpApp) {
+ } else if (v.isPrimOpApp()) {
str << ANSI_BLUE "«primop-app»" ANSI_NORMAL;
} else {
abort();