* Implemented the primops necessary for generating the NixOS manual.
This commit is contained in:
		
							parent
							
								
									a353aef0b1
								
							
						
					
					
						commit
						fc92244ba8
					
				
					 8 changed files with 160 additions and 146 deletions
				
			
		|  | @ -16,7 +16,8 @@ void doTest(string s) | |||
|     Expr e = parseExprFromString(state, s, absPath(".")); | ||||
|     printMsg(lvlError, format(">>>>> %1%") % e); | ||||
|     Value v; | ||||
|     state.strictEval(e, v); | ||||
|     state.eval(e, v); | ||||
|     state.strictForceValue(v); | ||||
|     printMsg(lvlError, format("result: %1%") % v); | ||||
| } | ||||
| 
 | ||||
|  | @ -76,6 +77,8 @@ void run(Strings args) | |||
|     doTest("let x = 1; as = rec { inherit x; y = as.x; }; in as.y"); | ||||
|     doTest("let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y"); | ||||
|     doTest("let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x"); | ||||
|     doTest("builtins.toXML 123"); | ||||
|     doTest("builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -302,6 +302,8 @@ void EvalState::eval(Env & env, Expr e, Value & v) | |||
|      | ||||
|     //debug(format("eval: %1%") % e);
 | ||||
| 
 | ||||
|     checkInterrupt(); | ||||
| 
 | ||||
|     nrEvaluated++; | ||||
| 
 | ||||
|     Sym name; | ||||
|  | @ -639,28 +641,6 @@ bool EvalState::evalBool(Env & env, Expr e) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::strictEval(Env & env, Expr e, Value & v) | ||||
| { | ||||
|     eval(env, e, v); | ||||
|      | ||||
|     if (v.type == tAttrs) { | ||||
|         foreach (Bindings::iterator, i, *v.attrs) | ||||
|             forceValue(i->second); | ||||
|     } | ||||
|      | ||||
|     else if (v.type == tList) { | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|             forceValue(v.list.elems[n]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::strictEval(Expr e, Value & v) | ||||
| { | ||||
|     strictEval(baseEnv, e, v); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::forceValue(Value & v) | ||||
| { | ||||
|     if (v.type == tThunk) { | ||||
|  | @ -678,6 +658,22 @@ void EvalState::forceValue(Value & v) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::strictForceValue(Value & v) | ||||
| { | ||||
|     forceValue(v); | ||||
|      | ||||
|     if (v.type == tAttrs) { | ||||
|         foreach (Bindings::iterator, i, *v.attrs) | ||||
|             strictForceValue(i->second); | ||||
|     } | ||||
|      | ||||
|     else if (v.type == tList) { | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|             strictForceValue(v.list.elems[n]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int EvalState::forceInt(Value & v) | ||||
| { | ||||
|     forceValue(v); | ||||
|  | @ -750,6 +746,14 @@ string EvalState::forceStringNoCtx(Value & v) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool EvalState::isDerivation(Value & v) | ||||
| { | ||||
|     if (v.type != tAttrs) return false; | ||||
|     Bindings::iterator i = v.attrs->find(toATerm("type")); | ||||
|     return i != v.attrs->end() && forceStringNoCtx(i->second) == "derivation"; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| string EvalState::coerceToString(Value & v, PathSet & context, | ||||
|     bool coerceMore, bool copyToStore) | ||||
| { | ||||
|  | @ -769,7 +773,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, | |||
| 
 | ||||
|         if (!copyToStore) return path; | ||||
|          | ||||
|         if (isDerivation(path)) | ||||
|         if (nix::isDerivation(path)) | ||||
|             throw EvalError(format("file names are not allowed to end in `%1%'") | ||||
|                 % drvExtension); | ||||
| 
 | ||||
|  | @ -1415,5 +1419,5 @@ void EvalState::printStats() | |||
|         printATermMapStats(); | ||||
| } | ||||
| 
 | ||||
|   | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -169,17 +169,16 @@ public: | |||
|        type. */ | ||||
|     bool evalBool(Env & env, Expr e); | ||||
| 
 | ||||
|     /* Evaluate an expression, and recursively evaluate list elements
 | ||||
|        and attributes. */ | ||||
|     void strictEval(Expr e, Value & v); | ||||
|     void strictEval(Env & env, Expr e, Value & v); | ||||
| 
 | ||||
|     /* If `v' is a thunk, enter it and overwrite `v' with the result
 | ||||
|        of the evaluation of the thunk.  If `v' is a delayed function | ||||
|        application, call the function and overwrite `v' with the | ||||
|        result.  Otherwise, this is a no-op. */ | ||||
|     void forceValue(Value & v); | ||||
| 
 | ||||
|     /* Force a value, then recursively force list elements and
 | ||||
|        attributes. */ | ||||
|     void strictForceValue(Value & v); | ||||
| 
 | ||||
|     /* Force `v', and then verify that it has the expected type. */ | ||||
|     int forceInt(Value & v); | ||||
|     bool forceBool(Value & v); | ||||
|  | @ -190,6 +189,10 @@ public: | |||
|     string forceString(Value & v, PathSet & context); | ||||
|     string forceStringNoCtx(Value & v); | ||||
| 
 | ||||
|     /* Return true iff the value `v' denotes a derivation (i.e. a
 | ||||
|        set with attribute `type = "derivation"'). */ | ||||
|     bool isDerivation(Value & v); | ||||
| 
 | ||||
|     /* String coercion.  Converts strings, paths and derivations to a
 | ||||
|        string.  If `coerceMore' is set, also converts nulls, integers, | ||||
|        booleans and lists to a string.  If `copyToStore' is set, | ||||
|  | @ -219,10 +222,10 @@ private: | |||
|        elements and attributes are compared recursively. */ | ||||
|     bool eqValues(Value & v1, Value & v2); | ||||
| 
 | ||||
|     void callFunction(Value & fun, Value & arg, Value & v); | ||||
| 
 | ||||
| public: | ||||
|      | ||||
|     void callFunction(Value & fun, Value & arg, Value & v); | ||||
| 
 | ||||
|     /* Allocation primitives. */ | ||||
|     Value * allocValues(unsigned int count); | ||||
|     Env & allocEnv(); | ||||
|  | @ -237,6 +240,10 @@ public: | |||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* Return a string representing the type of the value `v'. */ | ||||
| string showType(Value & v); | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /* Evaluate an expression to normal form. */ | ||||
| Expr evalExpr(EvalState & state, Expr e); | ||||
|  |  | |||
|  | @ -18,24 +18,19 @@ static XMLAttrs singletonAttrs(const string & name, const string & value) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* set<Expr> is safe because all the expressions are also reachable
 | ||||
|    from the stack, therefore can't be garbage-collected. */ | ||||
| typedef set<Expr> ExprSet; | ||||
| static void printValueAsXML(EvalState & state, bool strict, Value & v, | ||||
|     XMLWriter & doc, PathSet & context, PathSet & drvsSeen); | ||||
| 
 | ||||
| 
 | ||||
| static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context, | ||||
|     ExprSet & drvsSeen); | ||||
| 
 | ||||
| 
 | ||||
| static void showAttrs(const ATermMap & attrs, XMLWriter & doc, | ||||
|     PathSet & context, ExprSet & drvsSeen) | ||||
| static void showAttrs(EvalState & state, bool strict, Bindings & attrs, | ||||
|     XMLWriter & doc, PathSet & context, PathSet & drvsSeen) | ||||
| { | ||||
|     StringSet names; | ||||
|     for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) | ||||
|         names.insert(aterm2String(i->key)); | ||||
|     for (StringSet::iterator i = names.begin(); i != names.end(); ++i) { | ||||
|     foreach (Bindings::iterator, i, attrs) | ||||
|         names.insert(aterm2String(i->first)); | ||||
|     foreach (StringSet::iterator, i, names) { | ||||
|         XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); | ||||
|         printTermAsXML(attrs.get(toATerm(*i)), doc, context, drvsSeen); | ||||
|         printValueAsXML(state, strict, attrs[toATerm(*i)], doc, context, drvsSeen); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -61,91 +56,93 @@ static void printPatternAsXML(Pattern pat, XMLWriter & doc) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context, | ||||
|     ExprSet & drvsSeen) | ||||
| static void printValueAsXML(EvalState & state, bool strict, Value & v, | ||||
|     XMLWriter & doc, PathSet & context, PathSet & drvsSeen) | ||||
| { | ||||
|     XMLAttrs attrs; | ||||
|     string s; | ||||
|     ATerm s2; | ||||
|     int i; | ||||
|     ATermList as, es; | ||||
|     ATerm pat, body, pos; | ||||
| 
 | ||||
|     checkInterrupt(); | ||||
| 
 | ||||
|     if (matchStr(e, s, context)) /* !!! show the context? */ | ||||
|         doc.writeEmptyElement("string", singletonAttrs("value", s)); | ||||
|     if (strict) state.forceValue(v); | ||||
|          | ||||
|     switch (v.type) { | ||||
| 
 | ||||
|     else if (matchPath(e, s2)) | ||||
|         doc.writeEmptyElement("path", singletonAttrs("value", aterm2String(s2))); | ||||
|         case tInt: | ||||
|             doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str())); | ||||
|             break; | ||||
| 
 | ||||
|     else if (matchNull(e)) | ||||
|         doc.writeEmptyElement("null"); | ||||
|         case tBool: | ||||
|             doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false")); | ||||
|             break; | ||||
| 
 | ||||
|     else if (matchInt(e, i)) | ||||
|         doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % i).str())); | ||||
|         case tString: | ||||
|             /* !!! show the context? */ | ||||
|             doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); | ||||
|             break; | ||||
| 
 | ||||
|     else if (e == eTrue) | ||||
|         doc.writeEmptyElement("bool", singletonAttrs("value", "true")); | ||||
|         case tPath: | ||||
|             doc.writeEmptyElement("path", singletonAttrs("value", v.path)); | ||||
|             break; | ||||
| 
 | ||||
|     else if (e == eFalse) | ||||
|         doc.writeEmptyElement("bool", singletonAttrs("value", "false")); | ||||
|         case tNull: | ||||
|             doc.writeEmptyElement("null"); | ||||
|             break; | ||||
| 
 | ||||
|     else if (matchAttrs(e, as)) { | ||||
|         ATermMap attrs; | ||||
|         queryAllAttrs(e, attrs); | ||||
| 
 | ||||
|         Expr a = attrs.get(toATerm("type")); | ||||
|         if (a && matchStr(a, s, context) && s == "derivation") { | ||||
| 
 | ||||
|             XMLAttrs xmlAttrs; | ||||
|             Path outPath, drvPath; | ||||
|         case tAttrs: | ||||
|             if (state.isDerivation(v)) { | ||||
|                 XMLAttrs xmlAttrs; | ||||
|              | ||||
|             a = attrs.get(toATerm("drvPath")); | ||||
|             if (matchStr(a, drvPath, context)) | ||||
|                 xmlAttrs["drvPath"] = drvPath; | ||||
|          | ||||
|             a = attrs.get(toATerm("outPath")); | ||||
|             if (matchStr(a, outPath, context)) | ||||
|                 xmlAttrs["outPath"] = outPath; | ||||
|          | ||||
|             XMLOpenElement _(doc, "derivation", xmlAttrs); | ||||
|                 Bindings::iterator a = v.attrs->find(toATerm("derivation")); | ||||
| 
 | ||||
|             if (drvsSeen.find(e) == drvsSeen.end()) { | ||||
|                 drvsSeen.insert(e); | ||||
|                 showAttrs(attrs, doc, context, drvsSeen); | ||||
|             } else | ||||
|                 doc.writeEmptyElement("repeated"); | ||||
|                 Path drvPath; | ||||
|                 a = v.attrs->find(toATerm("drvPath")); | ||||
|                 if (a != v.attrs->end() && a->second.type == tString) | ||||
|                     xmlAttrs["drvPath"] = drvPath = a->second.string.s; | ||||
|          | ||||
|                 a = v.attrs->find(toATerm("outPath")); | ||||
|                 if (a != v.attrs->end() && a->second.type == tString) | ||||
|                     xmlAttrs["outPath"] = a->second.string.s; | ||||
| 
 | ||||
|                 XMLOpenElement _(doc, "derivation", xmlAttrs); | ||||
| 
 | ||||
|                 if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { | ||||
|                     drvsSeen.insert(drvPath); | ||||
|                     showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); | ||||
|                 } else | ||||
|                     doc.writeEmptyElement("repeated"); | ||||
|             } | ||||
| 
 | ||||
|             else { | ||||
|                 XMLOpenElement _(doc, "attrs"); | ||||
|                 showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); | ||||
|             } | ||||
|              | ||||
|             break; | ||||
| 
 | ||||
|         case tList: { | ||||
|             XMLOpenElement _(doc, "list"); | ||||
|             for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|                 printValueAsXML(state, strict, v.list.elems[n], doc, context, drvsSeen); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         else { | ||||
|             XMLOpenElement _(doc, "attrs"); | ||||
|             showAttrs(attrs, doc, context, drvsSeen); | ||||
|         case tLambda: { | ||||
|             XMLOpenElement _(doc, "function"); | ||||
|             printPatternAsXML(v.lambda.pat, doc); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     else if (matchList(e, es)) { | ||||
|         XMLOpenElement _(doc, "list"); | ||||
|         for (ATermIterator i(es); i; ++i) | ||||
|             printTermAsXML(*i, doc, context, drvsSeen); | ||||
|         default: | ||||
|             doc.writeEmptyElement("unevaluated"); | ||||
|     } | ||||
| 
 | ||||
|     else if (matchFunction(e, pat, body, pos)) { | ||||
|         XMLOpenElement _(doc, "function"); | ||||
|         printPatternAsXML(pat, doc); | ||||
|     } | ||||
| 
 | ||||
|     else | ||||
|         doc.writeEmptyElement("unevaluated"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printTermAsXML(Expr e, std::ostream & out, PathSet & context) | ||||
| void printValueAsXML(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & out, PathSet & context) | ||||
| { | ||||
|     XMLWriter doc(true, out); | ||||
|     XMLOpenElement root(doc, "expr"); | ||||
|     ExprSet drvsSeen;     | ||||
|     printTermAsXML(e, doc, context, drvsSeen); | ||||
|     PathSet drvsSeen;     | ||||
|     printValueAsXML(state, strict, v, doc, context, drvsSeen); | ||||
| } | ||||
| 
 | ||||
|   | ||||
|  |  | |||
|  | @ -5,11 +5,12 @@ | |||
| #include <map> | ||||
| 
 | ||||
| #include "nixexpr.hh" | ||||
| #include "aterm.hh" | ||||
| #include "eval.hh" | ||||
| 
 | ||||
| namespace nix { | ||||
| 
 | ||||
| void printTermAsXML(Expr e, std::ostream & out, PathSet & context); | ||||
| void printValueAsXML(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & out, PathSet & context); | ||||
|      | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -105,10 +105,7 @@ static bool getDerivation(EvalState & state, Value & v, | |||
| { | ||||
|     try { | ||||
|         state.forceValue(v); | ||||
|         if (v.type != tAttrs) return true; | ||||
| 
 | ||||
|         Bindings::iterator i = v.attrs->find(toATerm("type")); | ||||
|         if (i == v.attrs->end() || state.forceStringNoCtx(i->second) != "derivation") return true; | ||||
|         if (!state.isDerivation(v)) return true; | ||||
| 
 | ||||
|         /* Remove spurious duplicates (e.g., an attribute set like
 | ||||
|            `rec { x = derivation {...}; y = x;}'. */ | ||||
|  | @ -117,7 +114,7 @@ static bool getDerivation(EvalState & state, Value & v, | |||
| 
 | ||||
|         DrvInfo drv; | ||||
|      | ||||
|         i = v.attrs->find(toATerm("name")); | ||||
|         Bindings::iterator i = v.attrs->find(toATerm("name")); | ||||
|         /* !!! We really would like to have a decent back trace here. */ | ||||
|         if (i == v.attrs->end()) throw TypeError("derivation name missing"); | ||||
|         drv.name = state.forceStringNoCtx(i->second); | ||||
|  |  | |||
|  | @ -538,7 +538,6 @@ static void prim_readFile(EvalState & state, Value * * args, Value & v) | |||
|  *************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /* Convert the argument (which can be any Nix expression) to an XML
 | ||||
|    representation returned in a string.  Not all Nix expressions can | ||||
|    be sensibly or completely represented (e.g., functions). */ | ||||
|  | @ -546,10 +545,9 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) | |||
| { | ||||
|     std::ostringstream out; | ||||
|     PathSet context; | ||||
|     printTermAsXML(strictEvalExpr(state, args[0]), out, context); | ||||
|     return makeStr(out.str(), context); | ||||
|     printValueAsXML(state, true, *args[0], out, context); | ||||
|     mkString(v, out.str(), context); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Store a string in the Nix store as a source file that can be used
 | ||||
|  | @ -582,13 +580,12 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| struct FilterFromExpr : PathFilter | ||||
| { | ||||
|     EvalState & state; | ||||
|     Expr filter; | ||||
|     Value & filter; | ||||
|      | ||||
|     FilterFromExpr(EvalState & state, Expr filter) | ||||
|     FilterFromExpr(EvalState & state, Value & filter) | ||||
|         : state(state), filter(filter) | ||||
|     { | ||||
|     } | ||||
|  | @ -599,17 +596,25 @@ struct FilterFromExpr : PathFilter | |||
|         if (lstat(path.c_str(), &st)) | ||||
|             throw SysError(format("getting attributes of path `%1%'") % path); | ||||
| 
 | ||||
|         Expr call = | ||||
|             makeCall( | ||||
|                 makeCall(filter, makeStr(path)), | ||||
|                 makeStr( | ||||
|                     S_ISREG(st.st_mode) ? "regular" : | ||||
|                     S_ISDIR(st.st_mode) ? "directory" : | ||||
|                     S_ISLNK(st.st_mode) ? "symlink" : | ||||
|                     "unknown" /* not supported, will fail! */ | ||||
|                     )); | ||||
|                  | ||||
|         return evalBool(state, call); | ||||
|         /* Call the filter function.  The first argument is the path,
 | ||||
|            the second is a string indicating the type of the file. */ | ||||
|         Value arg1; | ||||
|         mkString(arg1, path); | ||||
| 
 | ||||
|         Value fun2; | ||||
|         state.callFunction(filter, arg1, fun2); | ||||
| 
 | ||||
|         Value arg2; | ||||
|         mkString(arg2,  | ||||
|             S_ISREG(st.st_mode) ? "regular" : | ||||
|             S_ISDIR(st.st_mode) ? "directory" : | ||||
|             S_ISLNK(st.st_mode) ? "symlink" : | ||||
|             "unknown" /* not supported, will fail! */); | ||||
|          | ||||
|         Value res; | ||||
|         state.callFunction(fun2, arg2, res); | ||||
| 
 | ||||
|         return state.forceBool(res); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -617,19 +622,22 @@ struct FilterFromExpr : PathFilter | |||
| static void prim_filterSource(EvalState & state, Value * * args, Value & v) | ||||
| { | ||||
|     PathSet context; | ||||
|     Path path = coerceToPath(state, args[1], context); | ||||
|     Path path = state.coerceToPath(*args[1], context); | ||||
|     if (!context.empty()) | ||||
|         throw EvalError(format("string `%1%' cannot refer to other paths") % path); | ||||
| 
 | ||||
|     FilterFromExpr filter(state, args[0]); | ||||
|     state.forceValue(*args[0]); | ||||
|     if (args[0]->type != tLambda) | ||||
|         throw TypeError(format("first argument in call to `filterSource' is not a function but %1%") % showType(*args[0])); | ||||
| 
 | ||||
|     FilterFromExpr filter(state, *args[0]); | ||||
| 
 | ||||
|     Path dstPath = readOnlyMode | ||||
|         ? computeStorePathForPath(path, true, htSHA256, filter).first | ||||
|         : store->addToStore(path, true, htSHA256, filter); | ||||
| 
 | ||||
|     return makeStr(dstPath, singleton<PathSet>(dstPath)); | ||||
|     mkString(v, dstPath, singleton<PathSet>(dstPath)); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************
 | ||||
|  | @ -927,15 +935,15 @@ static void prim_stringLength(EvalState & state, Value * * args, Value & v) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| static void prim_unsafeDiscardStringContext(EvalState & state, Value * * args, Value & v) | ||||
| { | ||||
|     PathSet context; | ||||
|     string s = coerceToString(state, args[0], context); | ||||
|     return makeStr(s, PathSet()); | ||||
|     string s = state.coerceToString(*args[0], context); | ||||
|     mkString(v, s, PathSet()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a
 | ||||
|    builder without causing the derivation to be built (for instance, | ||||
|    in the derivation that builds NARs in nix-push, when doing | ||||
|  | @ -1053,13 +1061,9 @@ void EvalState::createBaseEnv() | |||
|     addPrimOp("__readFile", 1, prim_readFile); | ||||
| 
 | ||||
|     // Creating files
 | ||||
| #if 0 | ||||
|     addPrimOp("__toXML", 1, prim_toXML); | ||||
| #endif | ||||
|     addPrimOp("__toFile", 2, prim_toFile); | ||||
| #if 0 | ||||
|     addPrimOp("__filterSource", 2, prim_filterSource); | ||||
| #endif | ||||
| 
 | ||||
|     // Attribute sets
 | ||||
|     addPrimOp("__attrNames", 1, prim_attrNames); | ||||
|  | @ -1091,8 +1095,8 @@ void EvalState::createBaseEnv() | |||
|     addPrimOp("toString", 1, prim_toString); | ||||
|     addPrimOp("__substring", 3, prim_substring); | ||||
|     addPrimOp("__stringLength", 1, prim_stringLength); | ||||
| #if 0    
 | ||||
|     addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext); | ||||
| #if 0    
 | ||||
|     addPrimOp("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency); | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue