diff options
author | Shea Levy <shea@shealevy.com> | 2014-11-30T18·16-0500 |
---|---|---|
committer | Shea Levy <shea@shealevy.com> | 2014-12-02T15·27-0500 |
commit | 320659b0cd161249c95e736c3fb309b1a73ea728 (patch) | |
tree | f58c49ae4828572d4642a4d02360f8a415a9f0f9 /src/libexpr/eval.cc | |
parent | 5f04da905fcd01ea2d68cdbf7af41c836df5bb4e (diff) |
Allow external code using libnixexpr to add types
Code that links to libnixexpr (e.g. plugins loaded with importNative, or nix-exec) may want to provide custom value types and operations on values of those types. For example, nix-exec is currently using sets where a custom IO value type would be more appropriate. This commit provides a generic hook for such types in the form of tExternal and the ExternalBase virtual class, which contains all functions necessary for libnixexpr's type-polymorphic functions (e.g. `showType`) to be implemented.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index ebb28021c180..b0afccdfbaaf 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -104,6 +104,9 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con case tPrimOpApp: str << "<PRIMOP-APP>"; break; + case tExternal: + str << *v.external; + break; default: throw Error("invalid value"); } @@ -136,6 +139,7 @@ string showType(const Value & v) case tBlackhole: return "a black hole"; case tPrimOp: return "a built-in function"; case tPrimOpApp: return "a partially applied built-in function"; + case tExternal: return v.external->showType(); } abort(); } @@ -1314,6 +1318,9 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context, return coerceToString(pos, *i->value, context, coerceMore, copyToStore); } + if (v.type == tExternal) + return v.external->coerceToString(pos, context, coerceMore, copyToStore); + if (coerceMore) { /* Note that `false' is represented as an empty string for @@ -1434,6 +1441,9 @@ bool EvalState::eqValues(Value & v1, Value & v2) case tPrimOpApp: return false; + case tExternal: + return *v1.external == *v2.external; + default: throwEvalError("cannot compare %1% with %2%", showType(v1), showType(v2)); } @@ -1575,6 +1585,11 @@ size_t valueSize(Value & v) sz += doValue(*v.primOpApp.left); sz += doValue(*v.primOpApp.right); break; + case tExternal: + if (seen.find(v.external) != seen.end()) break; + seen.insert(v.external); + sz += v.external->valueSize(seen); + break; default: ; } @@ -1601,4 +1616,22 @@ size_t valueSize(Value & v) } +string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) +{ + throw TypeError(format("cannot coerce %1% to a string, at %2%") % + showType() % pos); +} + + +bool ExternalValueBase::operator==(const ExternalValueBase & b) +{ + return false; +} + + +std::ostream & operator << (std::ostream & str, ExternalValueBase & v) { + return v.print(str); +} + + } |