Add functors (callable attribute sets).

With this, attribute sets with a `__functor` attribute can be applied
just like normal functions. This can be used to attach arbitrary
metadata to a function without callers needing to treat it specially.
This commit is contained in:
Shea Levy 2014-10-15 22:04:48 -04:00
parent 8cfe939b0f
commit 997defa166
4 changed files with 15 additions and 1 deletions

View file

@ -180,6 +180,7 @@ EvalState::EvalState(const Strings & _searchPath)
, sFile(symbols.create("file")) , sFile(symbols.create("file"))
, sLine(symbols.create("line")) , sLine(symbols.create("line"))
, sColumn(symbols.create("column")) , sColumn(symbols.create("column"))
, sFunctor(symbols.create("__functor"))
, repair(false) , repair(false)
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))
, staticBaseEnv(false, 0) , staticBaseEnv(false, 0)
@ -885,6 +886,17 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
return; 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) if (fun.type != tLambda)
throwTypeError("attempt to call something which is not a function but %1%, at %2%", fun, pos); throwTypeError("attempt to call something which is not a function but %1%, at %2%", fun, pos);

View file

@ -126,7 +126,7 @@ public:
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue, const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls, sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
sFile, sLine, sColumn; sFile, sLine, sColumn, sFunctor;
Symbol sDerivationNix; Symbol sDerivationNix;
/* If set, force copying files to the Nix store even if they /* If set, force copying files to the Nix store even if they

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1 @@
({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true