diff options
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 82 |
1 files changed, 48 insertions, 34 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 5b9db6eeaa6e..298f6a3a60e3 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(); } @@ -180,6 +184,7 @@ EvalState::EvalState(const Strings & _searchPath) , sFile(symbols.create("file")) , sLine(symbols.create("line")) , sColumn(symbols.create("column")) + , sFunctor(symbols.create("__functor")) , repair(false) , baseEnv(allocEnv(128)) , staticBaseEnv(false, 0) @@ -212,9 +217,9 @@ EvalState::EvalState(const Strings & _searchPath) allocated. This might be a problem on systems that don't overcommit. */ if (!getenv("GC_INITIAL_HEAP_SIZE")) { - size_t maxSize = 384 * 1024 * 1024; size_t size = 32 * 1024 * 1024; #if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES) + size_t maxSize = 384 * 1024 * 1024; long pageSize = sysconf(_SC_PAGESIZE); long pages = sysconf(_SC_PHYS_PAGES); if (pageSize != -1) @@ -242,7 +247,6 @@ EvalState::EvalState(const Strings & _searchPath) EvalState::~EvalState() { fileEvalCache.clear(); - printCanaries(); } @@ -312,11 +316,6 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const Symbol & sym, co throw EvalError(format(s) % sym % p1 % p2); } -LocalNoInlineNoReturn(void throwTypeError(const char * s)) -{ - throw TypeError(s); -} - LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos)) { throw TypeError(format(s) % pos); @@ -327,11 +326,6 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1)) throw TypeError(format(s) % s1); } -LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1, const string & s2)) -{ - throw TypeError(format(s) % s1 % s2); -} - LocalNoInlineNoReturn(void throwTypeError(const char * s, const ExprLambda & fun, const Symbol & s2, const Pos & pos)) { throw TypeError(format(s) % fun.showNamePos() % s2 % pos); @@ -895,6 +889,17 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po return; } + if (fun.type == tAttrs) { + auto found = fun.attrs->find(sFunctor); + if (found != fun.attrs->end()) { + forceValue(*found->value); + Value * v2 = allocValue(); + callFunction(*found->value, fun, *v2, pos); + forceValue(*v2); + return callFunction(*v2, arg, v, pos); + } + } + if (fun.type != tLambda) throwTypeError("attempt to call something which is not a function but %1%, at %2%", fun, pos); @@ -1255,9 +1260,9 @@ void copyContext(const Value & v, PathSet & context) } -string EvalState::forceString(Value & v, PathSet & context) +string EvalState::forceString(Value & v, PathSet & context, const Pos & pos) { - string s = forceString(v); + string s = forceString(v, pos); copyContext(v, context); return s; } @@ -1312,6 +1317,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 @@ -1432,6 +1440,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)); } @@ -1502,26 +1513,6 @@ void EvalState::printStats() } -void EvalState::printCanaries() -{ -#if HAVE_BOEHMGC - if (!settings.get("debug-gc", false)) return; - - GC_gcollect(); - - if (gcCanaries.empty()) { - printMsg(lvlError, "all canaries have been garbage-collected"); - return; - } - - printMsg(lvlError, "the following canaries have not been garbage-collected:"); - - for (auto i : gcCanaries) - printMsg(lvlError, format(" %1%") % i->string.s); -#endif -} - - size_t valueSize(Value & v) { std::set<const void *> seen; @@ -1573,6 +1564,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: ; } @@ -1599,4 +1595,22 @@ size_t valueSize(Value & v) } +string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const +{ + throw TypeError(format("cannot coerce %1% to a string, at %2%") % + showType() % pos); +} + + +bool ExternalValueBase::operator==(const ExternalValueBase & b) const +{ + return false; +} + + +std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) { + return v.print(str); +} + + } |