* Fixed builtins.genericClosure.
This commit is contained in:
parent
fe2d869e04
commit
0777448ca6
3 changed files with 61 additions and 25 deletions
|
@ -73,21 +73,25 @@ std::ostream & operator << (std::ostream & str, Value & v)
|
|||
}
|
||||
|
||||
|
||||
string showType(Value & v)
|
||||
string showType(const Value & v)
|
||||
{
|
||||
switch (v.type) {
|
||||
case tInt: return "an integer";
|
||||
case tBool: return "a boolean";
|
||||
case tString: return "a string";
|
||||
case tPath: return "a path";
|
||||
case tNull: return "null";
|
||||
case tAttrs: return "an attribute set";
|
||||
case tList: return "a list";
|
||||
case tNull: return "null";
|
||||
case tThunk: return "a thunk";
|
||||
case tApp: return "a function application";
|
||||
case tLambda: return "a function";
|
||||
case tCopy: return "a copy";
|
||||
case tBlackhole: return "a black hole";
|
||||
case tPrimOp: return "a built-in function";
|
||||
case tPrimOpApp: return "a partially applied built-in function";
|
||||
default: throw Error(format("unknown type: %1%") % v.type);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ private:
|
|||
|
||||
|
||||
/* Return a string representing the type of the value `v'. */
|
||||
string showType(Value & v);
|
||||
string showType(const Value & v);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -84,7 +84,26 @@ static void prim_isBool(EvalState & state, Value * * args, Value & v)
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
struct CompareValues
|
||||
{
|
||||
bool operator () (const Value & v1, const Value & v2) const
|
||||
{
|
||||
if (v1.type != v2.type)
|
||||
throw EvalError("cannot compare values of different types");
|
||||
switch (v1.type) {
|
||||
case tInt:
|
||||
return v1.integer < v2.integer;
|
||||
case tString:
|
||||
return strcmp(v1.string.s, v2.string.s) < 0;
|
||||
case tPath:
|
||||
return strcmp(v1.path, v2.path) < 0;
|
||||
default:
|
||||
throw EvalError(format("cannot compare %1% with %2%") % showType(v1) % showType(v2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
startNest(nest, lvlDebug, "finding dependencies");
|
||||
|
@ -98,45 +117,60 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
|
|||
throw EvalError("attribute `startSet' required");
|
||||
state.forceList(startSet->second);
|
||||
|
||||
list<Value> workSet;
|
||||
list<Value *> workSet;
|
||||
for (unsigned int n = 0; n < startSet->second.list.length; ++n)
|
||||
workSet.push_back(*startSet->second.list.elems[n]);
|
||||
workSet.push_back(startSet->second.list.elems[n]);
|
||||
|
||||
/* Get the operator. */
|
||||
Bindings::iterator op =
|
||||
args[0]->attrs->find(state.symbols.create("operator"));
|
||||
if (op == args[0]->attrs->end())
|
||||
throw EvalError("attribute `operator' required");
|
||||
|
||||
state.forceValue(op->second);
|
||||
|
||||
/* Construct the closure by applying the operator to element of
|
||||
`workSet', adding the result to `workSet', continuing until
|
||||
no new elements are found. */
|
||||
list<Value> res;
|
||||
set<Expr> doneKeys; // !!! gc roots
|
||||
set<Value, CompareValues> doneKeys;
|
||||
while (!workSet.empty()) {
|
||||
Expr e = *(workSet.begin());
|
||||
workSet.erase(e);
|
||||
Value * e = *(workSet.begin());
|
||||
workSet.pop_front();
|
||||
|
||||
e = strictEvalExpr(state, e);
|
||||
state.forceAttrs(*e);
|
||||
|
||||
Expr key = queryAttr(e, "key");
|
||||
if (!key) throw EvalError("attribute `key' required");
|
||||
Bindings::iterator key =
|
||||
e->attrs->find(state.symbols.create("key"));
|
||||
if (key == e->attrs->end())
|
||||
throw EvalError("attribute `key' required");
|
||||
state.forceValue(key->second);
|
||||
|
||||
if (doneKeys.find(key) != doneKeys.end()) continue;
|
||||
doneKeys.insert(key);
|
||||
res = ATinsert(res, e);
|
||||
if (doneKeys.find(key->second) != doneKeys.end()) continue;
|
||||
doneKeys.insert(key->second);
|
||||
res.push_back(*e);
|
||||
|
||||
/* Call the `operator' function with `e' as argument. */
|
||||
ATermList res = evalList(state, makeCall(op, e));
|
||||
Value call;
|
||||
mkApp(call, op->second, *e);
|
||||
state.forceList(call);
|
||||
|
||||
/* Try to find the dependencies relative to the `path'. */
|
||||
for (ATermIterator i(res); i; ++i)
|
||||
workSet.insert(evalExpr(state, *i));
|
||||
/* Add the values returned by the operator to the work set. */
|
||||
for (unsigned int n = 0; n < call.list.length; ++n) {
|
||||
state.forceValue(*call.list.elems[n]);
|
||||
workSet.push_back(call.list.elems[n]);
|
||||
}
|
||||
}
|
||||
|
||||
return makeList(res);
|
||||
/* Create the result list. */
|
||||
state.mkList(v, res.size());
|
||||
Value * vs = state.allocValues(res.size());
|
||||
|
||||
unsigned int n = 0;
|
||||
foreach (list<Value>::iterator, i, res) {
|
||||
v.list.elems[n] = &vs[n];
|
||||
vs[n++] = *i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void prim_abort(EvalState & state, Value * * args, Value & v)
|
||||
|
@ -1017,9 +1051,7 @@ void EvalState::createBaseEnv()
|
|||
addPrimOp("__isString", 1, prim_isString);
|
||||
addPrimOp("__isInt", 1, prim_isInt);
|
||||
addPrimOp("__isBool", 1, prim_isBool);
|
||||
#if 0
|
||||
addPrimOp("__genericClosure", 1, prim_genericClosure);
|
||||
#endif
|
||||
addPrimOp("abort", 1, prim_abort);
|
||||
addPrimOp("throw", 1, prim_throw);
|
||||
#if 0
|
||||
|
|
Loading…
Reference in a new issue