* Fixed builtins.genericClosure.

This commit is contained in:
Eelco Dolstra 2010-04-21 15:57:11 +00:00
parent fe2d869e04
commit 0777448ca6
3 changed files with 61 additions and 25 deletions

View File

@ -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();
}

View File

@ -304,7 +304,7 @@ private:
/* Return a string representing the type of the value `v'. */
string showType(Value & v);
string showType(const Value & v);
}

View File

@ -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