* 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) { |     switch (v.type) { | ||||||
|         case tInt: return "an integer"; |         case tInt: return "an integer"; | ||||||
|         case tBool: return "a boolean"; |         case tBool: return "a boolean"; | ||||||
|         case tString: return "a string"; |         case tString: return "a string"; | ||||||
|         case tPath: return "a path"; |         case tPath: return "a path"; | ||||||
|  |         case tNull: return "null"; | ||||||
|         case tAttrs: return "an attribute set"; |         case tAttrs: return "an attribute set"; | ||||||
|         case tList: return "a list"; |         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 tLambda: return "a function"; | ||||||
|  |         case tCopy: return "a copy"; | ||||||
|  |         case tBlackhole: return "a black hole"; | ||||||
|         case tPrimOp: return "a built-in function"; |         case tPrimOp: return "a built-in function"; | ||||||
|         case tPrimOpApp: return "a partially applied 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'. */ | /* 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) | static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     startNest(nest, lvlDebug, "finding dependencies"); |     startNest(nest, lvlDebug, "finding dependencies"); | ||||||
|  | @ -98,45 +117,60 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
|         throw EvalError("attribute `startSet' required"); |         throw EvalError("attribute `startSet' required"); | ||||||
|     state.forceList(startSet->second); |     state.forceList(startSet->second); | ||||||
| 
 | 
 | ||||||
|     list<Value> workSet; |     list<Value *> workSet; | ||||||
|     for (unsigned int n = 0; n < startSet->second.list.length; ++n) |     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. */ |     /* Get the operator. */ | ||||||
|     Bindings::iterator op = |     Bindings::iterator op = | ||||||
|         args[0]->attrs->find(state.symbols.create("operator")); |         args[0]->attrs->find(state.symbols.create("operator")); | ||||||
|     if (op == args[0]->attrs->end()) |     if (op == args[0]->attrs->end()) | ||||||
|         throw EvalError("attribute `operator' required"); |         throw EvalError("attribute `operator' required"); | ||||||
|  |     state.forceValue(op->second); | ||||||
| 
 | 
 | ||||||
|     /* Construct the closure by applying the operator to element of
 |     /* Construct the closure by applying the operator to element of
 | ||||||
|        `workSet', adding the result to `workSet', continuing until |        `workSet', adding the result to `workSet', continuing until | ||||||
|        no new elements are found. */ |        no new elements are found. */ | ||||||
|     list<Value> res; |     list<Value> res; | ||||||
|     set<Expr> doneKeys; // !!! gc roots
 |     set<Value, CompareValues> doneKeys; | ||||||
|     while (!workSet.empty()) { |     while (!workSet.empty()) { | ||||||
| 	Expr e = *(workSet.begin()); | 	Value * e = *(workSet.begin()); | ||||||
| 	workSet.erase(e); | 	workSet.pop_front(); | ||||||
| 
 | 
 | ||||||
|         e = strictEvalExpr(state, e); |         state.forceAttrs(*e); | ||||||
| 
 | 
 | ||||||
|         Expr key = queryAttr(e, "key"); |         Bindings::iterator key = | ||||||
|         if (!key) throw EvalError("attribute `key' required"); |             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; |         if (doneKeys.find(key->second) != doneKeys.end()) continue; | ||||||
|         doneKeys.insert(key); |         doneKeys.insert(key->second); | ||||||
|         res = ATinsert(res, e); |         res.push_back(*e); | ||||||
|          |          | ||||||
|         /* Call the `operator' function with `e' as argument. */ |         /* 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'. */ |         /* Add the values returned by the operator to the work set. */ | ||||||
|         for (ATermIterator i(res); i; ++i) |         for (unsigned int n = 0; n < call.list.length; ++n) { | ||||||
|             workSet.insert(evalExpr(state, *i)); |             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) | static void prim_abort(EvalState & state, Value * * args, Value & v) | ||||||
|  | @ -1017,9 +1051,7 @@ void EvalState::createBaseEnv() | ||||||
|     addPrimOp("__isString", 1, prim_isString); |     addPrimOp("__isString", 1, prim_isString); | ||||||
|     addPrimOp("__isInt", 1, prim_isInt); |     addPrimOp("__isInt", 1, prim_isInt); | ||||||
|     addPrimOp("__isBool", 1, prim_isBool); |     addPrimOp("__isBool", 1, prim_isBool); | ||||||
| #if 0 |  | ||||||
|     addPrimOp("__genericClosure", 1, prim_genericClosure); |     addPrimOp("__genericClosure", 1, prim_genericClosure); | ||||||
| #endif |  | ||||||
|     addPrimOp("abort", 1, prim_abort); |     addPrimOp("abort", 1, prim_abort); | ||||||
|     addPrimOp("throw", 1, prim_throw); |     addPrimOp("throw", 1, prim_throw); | ||||||
| #if 0 | #if 0 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue