aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-12 12:49:59 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-12 12:49:59 +0100
commitb3e8d72770b4100843c60b35633e529e6e69d543 (patch)
treef50070c3c31dd862b837bb514a9e0b10e68216a1 /src/libexpr/eval.cc
parentae4a3cfa030438ca05ad3bf61fa301dee6c1dbb5 (diff)
parent5cdcaf5e8edd6679f667502eec421ac4e725d4ef (diff)
Merge pull request #762 from ctheune/ctheune-floats
Implement floats
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index de9454422..8ce2f3dfa 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -128,6 +128,9 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
case tExternal:
str << *v.external;
break;
+ case tFloat:
+ str << v.fpoint;
+ break;
default:
throw Error("invalid value");
}
@@ -161,6 +164,7 @@ string showType(const Value & v)
case tPrimOp: return "a built-in function";
case tPrimOpApp: return "a partially applied built-in function";
case tExternal: return v.external->showType();
+ case tFloat: return "a float";
}
abort();
}
@@ -579,6 +583,12 @@ Value * ExprInt::maybeThunk(EvalState & state, Env & env)
return &v;
}
+Value * ExprFloat::maybeThunk(EvalState & state, Env & env)
+{
+ nrAvoided++;
+ return &v;
+}
+
Value * ExprPath::maybeThunk(EvalState & state, Env & env)
{
nrAvoided++;
@@ -666,6 +676,11 @@ void ExprInt::eval(EvalState & state, Env & env, Value & v)
}
+void ExprFloat::eval(EvalState & state, Env & env, Value & v)
+{
+ v = this->v;
+}
+
void ExprString::eval(EvalState & state, Env & env, Value & v)
{
v = this->v;
@@ -1211,6 +1226,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
PathSet context;
std::ostringstream s;
NixInt n = 0;
+ NixFloat nf = 0;
bool first = !forceString;
ValueType firstType = tString;
@@ -1229,15 +1245,30 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
}
if (firstType == tInt) {
- if (vTmp.type != tInt)
+ if (vTmp.type == tInt) {
+ n += vTmp.integer;
+ } else if (vTmp.type == tFloat) {
+ // Upgrade the type from int to float;
+ firstType = tFloat;
+ nf = n;
+ nf += vTmp.fpoint;
+ } else
throwEvalError("cannot add %1% to an integer, at %2%", showType(vTmp), pos);
- n += vTmp.integer;
+ } else if (firstType == tFloat) {
+ if (vTmp.type == tInt) {
+ nf += vTmp.integer;
+ } else if (vTmp.type == tFloat) {
+ nf += vTmp.fpoint;
+ } else
+ throwEvalError("cannot add %1% to a float, at %2%", showType(vTmp), pos);
} else
s << state.coerceToString(pos, vTmp, context, false, firstType == tString);
}
if (firstType == tInt)
mkInt(v, n);
+ else if (firstType == tFloat)
+ mkFloat(v, nf);
else if (firstType == tPath) {
if (!context.empty())
throwEvalError("a string that refers to a store path cannot be appended to a path, at %1%", pos);
@@ -1295,6 +1326,17 @@ NixInt EvalState::forceInt(Value & v, const Pos & pos)
}
+NixFloat EvalState::forceFloat(Value & v, const Pos & pos)
+{
+ forceValue(v, pos);
+ if (v.type == tInt)
+ return v.integer;
+ else if (v.type != tFloat)
+ throwTypeError("value is %1% while a float was expected, at %2%", v, pos);
+ return v.fpoint;
+}
+
+
bool EvalState::forceBool(Value & v)
{
forceValue(v);
@@ -1413,6 +1455,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
if (v.type == tBool && v.boolean) return "1";
if (v.type == tBool && !v.boolean) return "";
if (v.type == tInt) return std::to_string(v.integer);
+ if (v.type == tFloat) return std::to_string(v.fpoint);
if (v.type == tNull) return "";
if (v.isList()) {
@@ -1474,6 +1517,13 @@ bool EvalState::eqValues(Value & v1, Value & v2)
uniqList on a list of sets.) Will remove this eventually. */
if (&v1 == &v2) return true;
+ // Special case type-compatibility between float and int
+ if (v1.type == tInt && v2.type == tFloat)
+ return v1.integer == v2.fpoint;
+ if (v1.type == tFloat && v2.type == tInt)
+ return v1.fpoint == v2.integer;
+
+ // All other types are not compatible with each other.
if (v1.type != v2.type) return false;
switch (v1.type) {
@@ -1531,6 +1581,9 @@ bool EvalState::eqValues(Value & v1, Value & v2)
case tExternal:
return *v1.external == *v2.external;
+ case tFloat:
+ return v1.fpoint == v2.fpoint;
+
default:
throwEvalError("cannot compare %1% with %2%", showType(v1), showType(v2));
}