From d8cd3115d8e1acc9e866c67265668d5268f2c1ec Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 31 Mar 2010 19:12:08 +0000 Subject: * Get nix-env to compile. --- src/nix-env/nix-env.cc | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src/nix-env') diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 35caf687bf87..ea85656a2bca 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -164,9 +164,12 @@ static void loadDerivations(EvalState & state, Path nixExprPath, string systemFilter, const ATermMap & autoArgs, const string & pathPrefix, DrvInfos & elems) { - getDerivations(state, - findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath)), - pathPrefix, autoArgs, elems); + Value v; + state.eval(loadSourceExpr(state, nixExprPath), v); + + // !!! findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath)) + + getDerivations(state, v, pathPrefix, autoArgs, elems); /* Filter out all derivations not applicable to the current system. */ @@ -221,7 +224,7 @@ static DrvInfos queryInstalled(EvalState & state, const Path & userEnv) e = bottomupRewrite(addPos, e); DrvInfos elems; - getDerivations(state, e, "", ATermMap(1), elems); + // !!! getDerivations(state, e, "", ATermMap(1), elems); return elems; } @@ -255,6 +258,8 @@ static bool createUserEnv(EvalState & state, DrvInfos & elems, const Path & profile, bool keepDerivations, const string & lockToken) { + throw Error("not implemented"); +#if 0 /* Build the components in the user environment, if they don't exist already. */ PathSet drvsToBuild; @@ -355,6 +360,7 @@ static bool createUserEnv(EvalState & state, DrvInfos & elems, switchLink(profile, generation); return true; +#endif } @@ -518,12 +524,11 @@ static void queryInstSources(EvalState & state, Expr e1 = loadSourceExpr(state, instSource.nixExprPath); - for (Strings::const_iterator i = args.begin(); - i != args.end(); ++i) - { + foreach (Strings::const_iterator, i, args) { Expr e2 = parseExprFromString(state, *i, absPath(".")); Expr call = makeCall(e2, e1); - getDerivations(state, call, "", instSource.autoArgs, elems); + Value v; state.eval(call, v); + getDerivations(state, v, "", instSource.autoArgs, elems); } break; @@ -540,7 +545,7 @@ static void queryInstSources(EvalState & state, Path path = followLinksToStorePath(*i); DrvInfo elem; - elem.attrs = boost::shared_ptr(new ATermMap(0)); /* ugh... */ + elem.attrs = new Bindings; string name = baseNameOf(path); string::size_type dash = name.find('-'); if (dash != string::npos) @@ -574,12 +579,14 @@ static void queryInstSources(EvalState & state, } case srcAttrPath: { - for (Strings::const_iterator i = args.begin(); - i != args.end(); ++i) + throw Error("not implemented"); +#if 0 + foreach (Strings::const_iterator, i, args) getDerivations(state, findAlongAttrPath(state, *i, instSource.autoArgs, loadSourceExpr(state, instSource.nixExprPath)), "", instSource.autoArgs, elems); +#endif break; } } @@ -1472,7 +1479,7 @@ void run(Strings args) op(globals, remaining, opFlags, opArgs); - printEvalStats(globals.state); + globals.state.printStats(); } -- cgit 1.4.1 From af2a372bb000d4d5aeec37e43ee0f6245c1bba54 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 7 Apr 2010 15:47:06 +0000 Subject: * Update autoCallFunction() and findAlongAttrPath(). --- src/libexpr/attr-path.cc | 54 +++++++---------- src/libexpr/attr-path.hh | 4 +- src/libexpr/common-opts.cc | 14 +++-- src/libexpr/common-opts.hh | 2 +- src/libexpr/eval.cc | 64 +++++++++++--------- src/libexpr/eval.hh | 34 ++--------- src/libexpr/get-drvs.cc | 9 +-- src/libexpr/get-drvs.hh | 2 +- src/nix-env/nix-env.cc | 22 +++---- src/nix-instantiate/nix-instantiate.cc | 103 ++++++++++----------------------- 10 files changed, 120 insertions(+), 188 deletions(-) (limited to 'src/nix-env') diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 5d81303fe3d0..5f1c0ad7839d 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -6,19 +6,8 @@ namespace nix { -#if 0 -bool isAttrs(EvalState & state, Expr e, ATermMap & attrs) -{ - e = evalExpr(state, e); - ATermList dummy; - if (!matchAttrs(e, dummy)) return false; - queryAllAttrs(e, attrs, false); - return true; -} - - -Expr findAlongAttrPath(EvalState & state, const string & attrPath, - const ATermMap & autoArgs, Expr e) +void findAlongAttrPath(EvalState & state, const string & attrPath, + const Bindings & autoArgs, Expr e, Value & v) { Strings tokens = tokenizeString(attrPath, "."); @@ -26,8 +15,10 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath, Error(format("attribute selection path `%1%' does not match expression") % attrPath); string curPath; + + state.mkThunk_(v, e); - for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) { + foreach (Strings::iterator, i, tokens) { if (!curPath.empty()) curPath += "."; curPath += *i; @@ -39,7 +30,10 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath, if (string2Int(attr, attrIndex)) apType = apIndex; /* Evaluate the expression. */ - e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs)); + Value vTmp; + state.autoCallFunction(autoArgs, v, vTmp); + v = vTmp; + state.forceValue(v); /* It should evaluate to either an attribute set or an expression, according to what is specified in the @@ -47,38 +41,32 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath, if (apType == apAttr) { - ATermMap attrs; - - if (!isAttrs(state, e, attrs)) + if (v.type != tAttrs) throw TypeError( format("the expression selected by the selection path `%1%' should be an attribute set but is %2%") - % curPath % showType(e)); - - e = attrs.get(toATerm(attr)); - if (!e) - throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); + % curPath % showType(v)); + Bindings::iterator a = v.attrs->find(toATerm(attr)); + if (a == v.attrs->end()) + throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); + v = a->second; } else if (apType == apIndex) { - ATermList es; - if (!matchList(e, es)) + if (v.type != tList) throw TypeError( format("the expression selected by the selection path `%1%' should be a list but is %2%") - % curPath % showType(e)); + % curPath % showType(v)); - e = ATelementAt(es, attrIndex); - if (!e) - throw Error(format("list index %1% in selection path `%2%' not found") % attrIndex % curPath); - + if (attrIndex >= v.list.length) + throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % curPath); + + v = v.list.elems[attrIndex]; } } - - return e; } -#endif } diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh index 7abaa83a0167..518a7a95da09 100644 --- a/src/libexpr/attr-path.hh +++ b/src/libexpr/attr-path.hh @@ -10,8 +10,8 @@ namespace nix { -Expr findAlongAttrPath(EvalState & state, const string & attrPath, - const ATermMap & autoArgs, Expr e); +void findAlongAttrPath(EvalState & state, const string & attrPath, + const Bindings & autoArgs, Expr e, Value & v); } diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc index 9e3f8f9614da..d5d3df40a9a9 100644 --- a/src/libexpr/common-opts.cc +++ b/src/libexpr/common-opts.cc @@ -9,7 +9,7 @@ namespace nix { bool parseOptionArg(const string & arg, Strings::iterator & i, const Strings::iterator & argsEnd, EvalState & state, - ATermMap & autoArgs) + Bindings & autoArgs) { if (arg != "--arg" && arg != "--argstr") return false; @@ -19,11 +19,13 @@ bool parseOptionArg(const string & arg, Strings::iterator & i, string name = *i++; if (i == argsEnd) throw error; string value = *i++; - - Expr e = arg == "--arg" - ? parseExprFromString(state, value, absPath(".")) - : makeStr(value); - autoArgs.set(toATerm(name), e); + + Value & v(autoArgs[toATerm(name)]); + + if (arg == "--arg") + state.mkThunk_(v, parseExprFromString(state, value, absPath("."))); + else + mkString(v, value); return true; } diff --git a/src/libexpr/common-opts.hh b/src/libexpr/common-opts.hh index fb9659cdc5a1..80298ce55d1b 100644 --- a/src/libexpr/common-opts.hh +++ b/src/libexpr/common-opts.hh @@ -9,7 +9,7 @@ namespace nix { /* Some common option parsing between nix-env and nix-instantiate. */ bool parseOptionArg(const string & arg, Strings::iterator & i, const Strings::iterator & argsEnd, EvalState & state, - ATermMap & autoArgs); + Bindings & autoArgs); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0d18c552275a..98b6b7bdd150 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -260,6 +260,12 @@ void EvalState::mkAttrs(Value & v) } +void EvalState::mkThunk_(Value & v, Expr expr) +{ + mkThunk(v, baseEnv, expr); +} + + void EvalState::cloneAttrs(Value & src, Value & dst) { mkAttrs(dst); @@ -625,6 +631,37 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) } +void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res) +{ + forceValue(fun); + + ATerm name; + ATermList formals; + ATermBool ellipsis; + + if (fun.type != tLambda || !matchAttrsPat(fun.lambda.pat, formals, ellipsis, name)) { + res = fun; + return; + } + + Value actualArgs; + mkAttrs(actualArgs); + + for (ATermIterator i(formals); i; ++i) { + Expr name, def; ATerm def2; + if (!matchFormal(*i, name, def2)) abort(); + Bindings::const_iterator j = args.find(name); + if (j != args.end()) + (*actualArgs.attrs)[name] = j->second; + else if (!matchDefaultValue(def2, def)) + throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1% ')") + % aterm2String(name)); + } + + callFunction(fun, actualArgs, res); +} + + void EvalState::eval(Expr e, Value & v) { eval(baseEnv, e, v); @@ -1058,33 +1095,6 @@ ATermList flattenList(EvalState & state, Expr e) } -Expr autoCallFunction(Expr e, const ATermMap & args) -{ - Pattern pat; - ATerm body, pos, name; - ATermList formals; - ATermBool ellipsis; - - if (matchFunction(e, pat, body, pos) && matchAttrsPat(pat, formals, ellipsis, name)) { - ATermMap actualArgs(ATgetLength(formals)); - - for (ATermIterator i(formals); i; ++i) { - Expr name, def, value; ATerm def2; - if (!matchFormal(*i, name, def2)) abort(); - if ((value = args.get(name))) - actualArgs.set(name, makeAttrRHS(value, makeNoPos())); - else if (!matchDefaultValue(def2, def)) - throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1%')") - % aterm2String(name)); - } - - e = makeCall(e, makeAttrs(actualArgs)); - } - - return e; -} - - /* Evaluation of various language constructs. These have been taken out of evalExpr2 to reduce stack space usage. (GCC is really dumb about stack space: it just adds up all the local variables and diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index a42b9ebebaba..0ea474447f1f 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -226,13 +226,18 @@ public: void callFunction(Value & fun, Value & arg, Value & v); + /* Automatically call a function for which each argument has a + default value or has a binding in the `args' map. */ + void autoCallFunction(const Bindings & args, Value & fun, Value & res); + /* Allocation primitives. */ Value * allocValues(unsigned int count); Env & allocEnv(); void mkList(Value & v, unsigned int length); void mkAttrs(Value & v); - + void mkThunk_(Value & v, Expr expr); + void cloneAttrs(Value & src, Value & dst); /* Print statistics. */ @@ -244,33 +249,6 @@ public: string showType(Value & v); -#if 0 -/* Evaluate an expression to normal form. */ -Expr evalExpr(EvalState & state, Expr e); - -/* Evaluate an expression, and recursively evaluate list elements and - attributes. If `canonicalise' is true, we remove things like - position information and make sure that attribute sets are in - sorded order. */ -Expr strictEvalExpr(EvalState & state, Expr e); - -/* Specific results. */ -string evalString(EvalState & state, Expr e, PathSet & context); -int evalInt(EvalState & state, Expr e); -bool evalBool(EvalState & state, Expr e); -ATermList evalList(EvalState & state, Expr e); - -/* Flatten nested lists into a single list (or expand a singleton into - a list). */ -ATermList flattenList(EvalState & state, Expr e); - -/* Automatically call a function for which each argument has a default - value or has a binding in the `args' map. Note: result is a call, - not a normal form; it should be evaluated by calling evalExpr(). */ -Expr autoCallFunction(Expr e, const ATermMap & args); -#endif - - } diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 6e651d77f0cf..f5e7242f9f5a 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -155,11 +155,12 @@ static string addToPath(const string & s1, const string & s2) } -static void getDerivations(EvalState & state, Value & v, - const string & pathPrefix, const ATermMap & autoArgs, +static void getDerivations(EvalState & state, Value & vIn, + const string & pathPrefix, const Bindings & autoArgs, DrvInfos & drvs, Done & done) { - // !!! autoCallFunction(evalExpr(state, e), autoArgs) + Value v; + state.autoCallFunction(autoArgs, vIn, v); /* Process the expression. */ DrvInfo drv; @@ -216,7 +217,7 @@ static void getDerivations(EvalState & state, Value & v, void getDerivations(EvalState & state, Value & v, const string & pathPrefix, - const ATermMap & autoArgs, DrvInfos & drvs) + const Bindings & autoArgs, DrvInfos & drvs) { Done done; getDerivations(state, v, pathPrefix, autoArgs, drvs, done); diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index 733f2020129b..f7d1987ea3b7 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -65,7 +65,7 @@ typedef list DrvInfos; bool getDerivation(EvalState & state, Value & v, DrvInfo & drv); void getDerivations(EvalState & state, Value & v, const string & pathPrefix, - const ATermMap & autoArgs, DrvInfos & drvs); + const Bindings & autoArgs, DrvInfos & drvs); } diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index ea85656a2bca..20affa83ddd0 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -47,7 +47,7 @@ struct InstallSourceInfo Path profile; /* for srcProfile */ string systemFilter; /* for srcNixExprDrvs */ bool prebuiltOnly; - ATermMap autoArgs; + Bindings autoArgs; InstallSourceInfo() : prebuiltOnly(false) { }; }; @@ -161,13 +161,11 @@ static Expr loadSourceExpr(EvalState & state, const Path & path) static void loadDerivations(EvalState & state, Path nixExprPath, - string systemFilter, const ATermMap & autoArgs, + string systemFilter, const Bindings & autoArgs, const string & pathPrefix, DrvInfos & elems) { Value v; - state.eval(loadSourceExpr(state, nixExprPath), v); - - // !!! findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath)) + findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath), v); getDerivations(state, v, pathPrefix, autoArgs, elems); @@ -579,14 +577,12 @@ static void queryInstSources(EvalState & state, } case srcAttrPath: { - throw Error("not implemented"); -#if 0 - foreach (Strings::const_iterator, i, args) - getDerivations(state, - findAlongAttrPath(state, *i, instSource.autoArgs, - loadSourceExpr(state, instSource.nixExprPath)), - "", instSource.autoArgs, elems); -#endif + foreach (Strings::const_iterator, i, args) { + Value v; + findAlongAttrPath(state, *i, instSource.autoArgs, + loadSourceExpr(state, instSource.nixExprPath), v); + getDerivations(state, v, "", instSource.autoArgs, elems); + } break; } } diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index ebf1be5b9649..ac405aa6601c 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -37,80 +37,41 @@ static int rootNr = 0; static bool indirectRoot = false; -#if 0 -static void printResult(EvalState & state, Expr e, - bool evalOnly, bool xmlOutput, const ATermMap & autoArgs) -{ - PathSet context; - - if (evalOnly) - if (xmlOutput) - printTermAsXML(e, std::cout, context); - else - std::cout << format("%1%\n") % canonicaliseExpr(e); - - else { - DrvInfos drvs; - getDerivations(state, e, "", autoArgs, drvs); - for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) { - Path drvPath = i->queryDrvPath(state); - if (gcRoot == "") - printGCWarning(); - else - drvPath = addPermRoot(drvPath, - makeRootName(gcRoot, rootNr), - indirectRoot); - std::cout << format("%1%\n") % drvPath; - } - } -} -#endif - - void processExpr(EvalState & state, const Strings & attrPaths, - bool parseOnly, bool strict, const ATermMap & autoArgs, + bool parseOnly, bool strict, const Bindings & autoArgs, bool evalOnly, bool xmlOutput, Expr e) { if (parseOnly) std::cout << format("%1%\n") % canonicaliseExpr(e); - else { - Value v; - PathSet context; - state.eval(e, v); - if (evalOnly) - if (xmlOutput) - printValueAsXML(state, strict, v, std::cout, context); + else + foreach (Strings::const_iterator, i, attrPaths) { + Value v; + findAlongAttrPath(state, *i, autoArgs, e, v); + state.forceValue(v); + + PathSet context; + if (evalOnly) + if (xmlOutput) + printValueAsXML(state, strict, v, std::cout, context); + else { + if (strict) state.strictForceValue(v); + std::cout << v << std::endl; + } else { - if (strict) state.strictForceValue(v); - std::cout << v << std::endl; - } - else { - DrvInfos drvs; - getDerivations(state, v, "", autoArgs, drvs); - foreach (DrvInfos::iterator, i, drvs) { - Path drvPath = i->queryDrvPath(state); - if (gcRoot == "") - printGCWarning(); - else - drvPath = addPermRoot(drvPath, - makeRootName(gcRoot, rootNr), - indirectRoot); - std::cout << format("%1%\n") % drvPath; + DrvInfos drvs; + getDerivations(state, v, "", autoArgs, drvs); + foreach (DrvInfos::iterator, i, drvs) { + Path drvPath = i->queryDrvPath(state); + if (gcRoot == "") + printGCWarning(); + else + drvPath = addPermRoot(drvPath, + makeRootName(gcRoot, rootNr), + indirectRoot); + std::cout << format("%1%\n") % drvPath; + } } } - } - -#if 0 - for (Strings::const_iterator i = attrPaths.begin(); i != attrPaths.end(); ++i) { - Expr e2 = findAlongAttrPath(state, *i, autoArgs, e); - if (!parseOnly) - if (strict) - e2 = state.strictEval(e2); - else - e2 = evalExpr(state, e2); - printResult(state, e2, evalOnly, xmlOutput, autoArgs); - } -#endif } @@ -124,11 +85,9 @@ void run(Strings args) bool xmlOutput = false; bool strict = false; Strings attrPaths; - ATermMap autoArgs(128); + Bindings autoArgs; - for (Strings::iterator i = args.begin(); - i != args.end(); ) - { + for (Strings::iterator i = args.begin(); i != args.end(); ) { string arg = *i++; if (arg == "-") @@ -175,9 +134,7 @@ void run(Strings args) evalOnly, xmlOutput, e); } - for (Strings::iterator i = files.begin(); - i != files.end(); i++) - { + foreach (Strings::iterator, i, files) { Path path = absPath(*i); Expr e = parseExprFromFile(state, path); processExpr(state, attrPaths, parseOnly, strict, autoArgs, -- cgit 1.4.1 From 4d6ad5be1738c64b1de4274cafbd4b8f23ca287c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 12 Apr 2010 18:30:11 +0000 Subject: * Don't use ATerms for the abstract syntax trees anymore. Not finished yet. --- src/libexpr/Makefile.am | 15 +- src/libexpr/attr-path.cc | 5 +- src/libexpr/attr-path.hh | 2 +- src/libexpr/common-opts.cc | 4 +- src/libexpr/eval-test.cc | 22 +- src/libexpr/eval.cc | 467 +++++++++++++++++---------------- src/libexpr/eval.hh | 46 +++- src/libexpr/get-drvs.cc | 21 +- src/libexpr/lexer.l | 24 +- src/libexpr/nixexpr-ast.def | 97 ------- src/libexpr/nixexpr.cc | 110 ++++++-- src/libexpr/nixexpr.hh | 163 ++++++++++-- src/libexpr/parser.hh | 5 +- src/libexpr/parser.y | 191 ++++++++------ src/libexpr/primops.cc | 38 ++- src/libexpr/value-to-xml.cc | 43 +-- src/libmain/shared.cc | 4 +- src/nix-env/nix-env.cc | 5 +- src/nix-instantiate/nix-instantiate.cc | 10 +- 19 files changed, 693 insertions(+), 579 deletions(-) delete mode 100644 src/libexpr/nixexpr-ast.def (limited to 'src/nix-env') diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am index 99f742ffec40..60b1815d9690 100644 --- a/src/libexpr/Makefile.am +++ b/src/libexpr/Makefile.am @@ -8,15 +8,15 @@ libexpr_la_SOURCES = \ pkginclude_HEADERS = \ nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \ get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \ - names.hh nixexpr-ast.hh + names.hh libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \ ../boost/format/libformat.la -BUILT_SOURCES = nixexpr-ast.cc nixexpr-ast.hh \ +BUILT_SOURCES = \ parser-tab.hh lexer-tab.hh parser-tab.cc lexer-tab.cc -EXTRA_DIST = lexer.l parser.y nixexpr-ast.def nixexpr-ast.cc +EXTRA_DIST = lexer.l parser.y AM_CXXFLAGS = \ -I$(srcdir)/.. ${aterm_include} \ @@ -34,15 +34,6 @@ lexer-tab.cc lexer-tab.hh: lexer.l $(flex) --outfile lexer-tab.cc --header-file=lexer-tab.hh $(srcdir)/lexer.l -# ATerm helper function generation. - -nixexpr-ast.cc nixexpr-ast.hh: ../aterm-helper.pl nixexpr-ast.def - $(perl) $(srcdir)/../aterm-helper.pl nixexpr-ast.hh nixexpr-ast.cc < $(srcdir)/nixexpr-ast.def - - -CLEANFILES = - - # SDF stuff (not built by default). nix.tbl: nix.sdf sdf2table -m Nix -s -i nix.sdf -o nix.tbl diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 5f1c0ad7839d..aa421ab431da 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -1,5 +1,4 @@ #include "attr-path.hh" -#include "nixexpr-ast.hh" #include "util.hh" @@ -7,7 +6,7 @@ namespace nix { void findAlongAttrPath(EvalState & state, const string & attrPath, - const Bindings & autoArgs, Expr e, Value & v) + const Bindings & autoArgs, Expr * e, Value & v) { Strings tokens = tokenizeString(attrPath, "."); @@ -46,7 +45,7 @@ void findAlongAttrPath(EvalState & state, const string & attrPath, format("the expression selected by the selection path `%1%' should be an attribute set but is %2%") % curPath % showType(v)); - Bindings::iterator a = v.attrs->find(toATerm(attr)); + Bindings::iterator a = v.attrs->find(attr); if (a == v.attrs->end()) throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); v = a->second; diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh index 518a7a95da09..33587e5edee1 100644 --- a/src/libexpr/attr-path.hh +++ b/src/libexpr/attr-path.hh @@ -11,7 +11,7 @@ namespace nix { void findAlongAttrPath(EvalState & state, const string & attrPath, - const Bindings & autoArgs, Expr e, Value & v); + const Bindings & autoArgs, Expr * e, Value & v); } diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc index d5d3df40a9a9..6171de0f0e84 100644 --- a/src/libexpr/common-opts.cc +++ b/src/libexpr/common-opts.cc @@ -20,10 +20,10 @@ bool parseOptionArg(const string & arg, Strings::iterator & i, if (i == argsEnd) throw error; string value = *i++; - Value & v(autoArgs[toATerm(name)]); + Value & v(autoArgs[name]); if (arg == "--arg") - state.mkThunk_(v, parseExprFromString(state, value, absPath("."))); + state.mkThunk_(v, parseExprFromString(value, absPath("."))); else mkString(v, value); diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc index 77861dea95be..32f4940df90e 100644 --- a/src/libexpr/eval-test.cc +++ b/src/libexpr/eval-test.cc @@ -2,8 +2,8 @@ #include "parser.hh" #include "hash.hh" #include "util.hh" -#include "nixexpr-ast.hh" +#include #include #include @@ -12,8 +12,8 @@ using namespace nix; void doTest(EvalState & state, string s) { - Expr e = parseExprFromString(state, s, absPath(".")); - printMsg(lvlError, format(">>>>> %1%") % e); + Expr * e = parseExprFromString(s, absPath(".")); + std::cerr << ">>>>> " << *e << std::endl; Value v; state.eval(e, v); state.strictForceValue(v); @@ -24,8 +24,10 @@ void doTest(EvalState & state, string s) void run(Strings args) { EvalState state; - + printMsg(lvlError, format("size of value: %1% bytes") % sizeof(Value)); + printMsg(lvlError, format("size of int AST node: %1% bytes") % sizeof(ExprInt)); + printMsg(lvlError, format("size of attrset AST node: %1% bytes") % sizeof(ExprAttrs)); doTest(state, "123"); doTest(state, "{ x = 1; y = 2; }"); @@ -53,7 +55,7 @@ void run(Strings args) doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 2)]"); doTest(state, "let id = x: x; in [1 2] == [(id 1) (id 3)]"); doTest(state, "[1 2] == [3 (let x = x; in x)]"); - doTest(state, "{ x = 1; y.z = 2; } == { y = { z = 2; }; x = 1; }"); + //doTest(state, "{ x = 1; y.z = 2; } == { y = { z = 2; }; x = 1; }"); doTest(state, "{ x = 1; y = 2; } == { x = 2; }"); doTest(state, "{ x = [ 1 2 ]; } == { x = [ 1 ] ++ [ 2 ]; }"); doTest(state, "1 != 1"); @@ -63,23 +65,23 @@ void run(Strings args) doTest(state, "__head [ 1 2 3 ]"); doTest(state, "__add 1 2"); doTest(state, "null"); - doTest(state, "null"); - doTest(state, "\"foo\""); - doTest(state, "let s = \"bar\"; in \"foo${s}\""); + //doTest(state, "\"foo\""); + //doTest(state, "let s = \"bar\"; in \"foo${s}\""); doTest(state, "if true then 1 else 2"); doTest(state, "if false then 1 else 2"); doTest(state, "if false || true then 1 else 2"); doTest(state, "let x = x; in if true || x then 1 else 2"); + doTest(state, "http://nixos.org/"); doTest(state, "/etc/passwd"); //doTest(state, "import ./foo.nix"); doTest(state, "map (x: __add 1 x) [ 1 2 3 ]"); doTest(state, "map (builtins.add 1) [ 1 2 3 ]"); - doTest(state, "builtins.hasAttr \"x\" { x = 1; }"); + //doTest(state, "builtins.hasAttr \"x\" { x = 1; }"); doTest(state, "let x = 1; as = rec { inherit x; y = as.x; }; in as.y"); doTest(state, "let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y"); doTest(state, "let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x"); doTest(state, "builtins.toXML 123"); - doTest(state, "builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }"); + //doTest(state, "builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }"); state.printStats(); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7434aa842242..8ead986b8125 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -4,7 +4,6 @@ #include "util.hh" #include "store-api.hh" #include "derivations.hh" -#include "nixexpr-ast.hh" #include "globals.hh" #include @@ -45,7 +44,7 @@ std::ostream & operator << (std::ostream & str, Value & v) case tAttrs: str << "{ "; foreach (Bindings::iterator, i, *v.attrs) - str << aterm2String(i->first) << " = " << i->second << "; "; + str << i->first << " = " << i->second << "; "; str << "}"; break; case tList: @@ -96,8 +95,6 @@ EvalState::EvalState() : baseEnv(allocEnv()) nrValues = nrEnvs = nrEvaluated = recursionDepth = maxRecursionDepth = 0; deepestStack = (char *) -1; - initNixExprHelpers(); - createBaseEnv(); allowUnsafeEquality = getEnv("NIX_NO_UNSAFE_EQ", "") == ""; @@ -112,9 +109,9 @@ EvalState::~EvalState() void EvalState::addConstant(const string & name, Value & v) { - baseEnv.bindings[toATerm(name)] = v; + baseEnv.bindings[name] = v; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v; + (*baseEnv.bindings["builtins"].attrs)[name2] = v; nrValues += 2; } @@ -126,9 +123,9 @@ void EvalState::addPrimOp(const string & name, v.type = tPrimOp; v.primOp.arity = arity; v.primOp.fun = primOp; - baseEnv.bindings[toATerm(name)] = v; + baseEnv.bindings[name] = v; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v; + (*baseEnv.bindings["builtins"].attrs)[name2] = v; nrValues += 2; } @@ -212,12 +209,12 @@ void mkPath(Value & v, const char * s) } -static Value * lookupWith(Env * env, Sym name) +static Value * lookupWith(Env * env, const Sym & name) { if (!env) return 0; Value * v = lookupWith(env->up, name); if (v) return v; - Bindings::iterator i = env->bindings.find(sWith); + Bindings::iterator i = env->bindings.find(""); if (i == env->bindings.end()) return 0; Bindings::iterator j = i->second.attrs->find(name); if (j != i->second.attrs->end()) return &j->second; @@ -225,7 +222,7 @@ static Value * lookupWith(Env * env, Sym name) } -static Value * lookupVar(Env * env, Sym name) +static Value * lookupVar(Env * env, const Sym & name) { /* First look for a regular variable binding for `name'. */ for (Env * env2 = env; env2; env2 = env2->up) { @@ -251,7 +248,7 @@ static Value * lookupVar(Env * env, Sym name) } #endif - throwEvalError("undefined variable `%1%'", aterm2String(name)); + throwEvalError("undefined variable `%1%'", name); } @@ -284,7 +281,7 @@ void EvalState::mkAttrs(Value & v) } -void EvalState::mkThunk_(Value & v, Expr expr) +void EvalState::mkThunk_(Value & v, Expr * expr) { mkThunk(v, baseEnv, expr); } @@ -302,11 +299,11 @@ void EvalState::evalFile(const Path & path, Value & v) { startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); - Expr e = parseTrees.get(toATerm(path)); + Expr * e = parseTrees[path]; if (!e) { - e = parseExprFromFile(*this, path); - parseTrees.set(toATerm(path), e); + e = parseExprFromFile(path); + parseTrees[path] = e; } try { @@ -334,7 +331,7 @@ struct RecursionCounter }; -void EvalState::eval(Env & env, Expr e, Value & v) +void EvalState::eval(Env & env, Expr * e, Value & v) { /* When changing this function, make sure that you don't cause a (large) increase in stack consumption! */ @@ -350,6 +347,9 @@ void EvalState::eval(Env & env, Expr e, Value & v) nrEvaluated++; + e->eval(*this, env, v); + +#if 0 Sym name; int n; ATerm s; ATermList context, es; @@ -357,138 +357,6 @@ void EvalState::eval(Env & env, Expr e, Value & v) Expr e1, e2, e3, fun, arg, attrs; Pattern pat; Expr body; Pos pos; - if (matchVar(e, name)) { - Value * v2 = lookupVar(&env, name); - forceValue(*v2); - v = *v2; - } - - else if (matchInt(e, n)) - mkInt(v, n); - - else if (matchStr(e, s, context)) { - assert(context == ATempty); - mkString(v, ATgetName(ATgetAFun(s))); - } - - else if (matchPath(e, s)) - mkPath(v, ATgetName(ATgetAFun(s))); - - else if (matchAttrs(e, es)) { - mkAttrs(v); - ATerm e2, pos; - for (ATermIterator i(es); i; ++i) { - if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ - Value & v2 = (*v.attrs)[name]; - nrValues++; - mkThunk(v2, env, e2); - } - } - - else if (matchRec(e, rbnds, nrbnds)) { - /* Create a new environment that contains the attributes in - this `rec'. */ - Env & env2(allocEnv()); - env2.up = &env; - - v.type = tAttrs; - v.attrs = &env2.bindings; - - /* The recursive attributes are evaluated in the new - environment. */ - ATerm name, e2, pos; - for (ATermIterator i(rbnds); i; ++i) { - if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ - Value & v2 = env2.bindings[name]; - nrValues++; - mkThunk(v2, env2, e2); - } - - /* The non-recursive attributes, on the other hand, are - evaluated in the original environment. */ - for (ATermIterator i(nrbnds); i; ++i) { - if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ - Value & v2 = env2.bindings[name]; - nrValues++; - mkThunk(v2, env, e2); - } - } - - else if (matchSelect(e, e2, name)) { - Value v2; - eval(env, e2, v2); - forceAttrs(v2); // !!! eval followed by force is slightly inefficient - Bindings::iterator i = v2.attrs->find(name); - if (i == v2.attrs->end()) - throwEvalError("attribute `%1%' missing", aterm2String(name)); - try { - forceValue(i->second); - } catch (Error & e) { - addErrorPrefix(e, "while evaluating the attribute `%1%':\n", aterm2String(name)); - throw; - } - v = i->second; - } - - else if (matchFunction(e, pat, body, pos)) { - v.type = tLambda; - v.lambda.env = &env; - v.lambda.pat = pat; - v.lambda.body = body; - } - - else if (matchCall(e, fun, arg)) { - Value vFun; - eval(env, fun, vFun); - Value vArg; - mkThunk(vArg, env, arg); // !!! should this be on the heap? - callFunction(vFun, vArg, v); - } - - else if (matchWith(e, attrs, body, pos)) { - Env & env2(allocEnv()); - env2.up = &env; - - Value & vAttrs = env2.bindings[sWith]; - nrValues++; - eval(env, attrs, vAttrs); - forceAttrs(vAttrs); - - eval(env2, body, v); - } - - else if (matchList(e, es)) { - mkList(v, ATgetLength(es)); - for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es)) - mkThunk(v.list.elems[n], env, ATgetFirst(es)); - } - - else if (matchOpEq(e, e1, e2)) { - Value v1; eval(env, e1, v1); - Value v2; eval(env, e2, v2); - mkBool(v, eqValues(v1, v2)); - } - - else if (matchOpNEq(e, e1, e2)) { - Value v1; eval(env, e1, v1); - Value v2; eval(env, e2, v2); - mkBool(v, !eqValues(v1, v2)); - } - - else if (matchOpConcat(e, e1, e2)) { - Value v1; eval(env, e1, v1); - forceList(v1); - Value v2; eval(env, e2, v2); - forceList(v2); - mkList(v, v1.list.length + v2.list.length); - /* !!! This loses sharing with the original lists. We could - use a tCopy node, but that would use more memory. */ - for (unsigned int n = 0; n < v1.list.length; ++n) - v.list.elems[n] = v1.list.elems[n]; - for (unsigned int n = 0; n < v2.list.length; ++n) - v.list.elems[n + v1.list.length] = v2.list.elems[n]; - } - else if (matchConcatStrings(e, es)) { PathSet context; std::ostringstream s; @@ -521,10 +389,6 @@ void EvalState::eval(Env & env, Expr e, Value & v) mkString(v, s.str(), context); } - /* Conditionals. */ - else if (matchIf(e, e1, e2, e3)) - eval(env, evalBool(env, e1) ? e2 : e3, v); - /* Assertions. */ else if (matchAssert(e, e1, e2, pos)) { if (!evalBool(env, e1)) @@ -536,30 +400,6 @@ void EvalState::eval(Env & env, Expr e, Value & v) else if (matchOpNot(e, e1)) mkBool(v, !evalBool(env, e1)); - /* Implication. */ - else if (matchOpImpl(e, e1, e2)) - return mkBool(v, !evalBool(env, e1) || evalBool(env, e2)); - - /* Conjunction (logical AND). */ - else if (matchOpAnd(e, e1, e2)) - mkBool(v, evalBool(env, e1) && evalBool(env, e2)); - - /* Disjunction (logical OR). */ - else if (matchOpOr(e, e1, e2)) - mkBool(v, evalBool(env, e1) || evalBool(env, e2)); - - /* Attribute set update (//). */ - else if (matchOpUpdate(e, e1, e2)) { - Value v2; - eval(env, e1, v2); - - cloneAttrs(v2, v); - - eval(env, e2, v2); - foreach (Bindings::iterator, i, *v2.attrs) - (*v.attrs)[i->first] = i->second; // !!! sharing - } - /* Attribute existence test (?). */ else if (matchOpHasAttr(e, e1, name)) { Value vAttrs; @@ -567,8 +407,130 @@ void EvalState::eval(Env & env, Expr e, Value & v) forceAttrs(vAttrs); mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end()); } +#endif +} + + +void EvalState::eval(Expr * e, Value & v) +{ + eval(baseEnv, e, v); +} - else abort(); + +bool EvalState::evalBool(Env & env, Expr * e) +{ + Value v; + eval(env, e, v); + if (v.type != tBool) + throwTypeError("value is %1% while a Boolean was expected", showType(v)); + return v.boolean; +} + + +void ExprInt::eval(EvalState & state, Env & env, Value & v) +{ + mkInt(v, n); +} + + +void ExprString::eval(EvalState & state, Env & env, Value & v) +{ + mkString(v, s.c_str()); +} + + +void ExprPath::eval(EvalState & state, Env & env, Value & v) +{ + mkPath(v, s.c_str()); +} + + +void ExprAttrs::eval(EvalState & state, Env & env, Value & v) +{ + if (recursive) { + + /* Create a new environment that contains the attributes in + this `rec'. */ + Env & env2(state.allocEnv()); + env2.up = &env; + + v.type = tAttrs; + v.attrs = &env2.bindings; + + /* The recursive attributes are evaluated in the new + environment. */ + foreach (Attrs::iterator, i, attrs) { + Value & v2 = env2.bindings[i->first]; + mkThunk(v2, env2, i->second); + } + + /* The inherited attributes, on the other hand, are + evaluated in the original environment. */ + foreach (list::iterator, i, inherited) { + Value & v2 = env2.bindings[*i]; + mkCopy(v2, *lookupVar(&env, *i)); + } + } + + else { + state.mkAttrs(v); + foreach (Attrs::iterator, i, attrs) { + Value & v2 = (*v.attrs)[i->first]; + mkThunk(v2, env, i->second); + } + } +} + + +void ExprList::eval(EvalState & state, Env & env, Value & v) +{ + state.mkList(v, elems.size()); + for (unsigned int n = 0; n < v.list.length; ++n) + mkThunk(v.list.elems[n], env, elems[n]); +} + + +void ExprVar::eval(EvalState & state, Env & env, Value & v) +{ + Value * v2 = lookupVar(&env, name); + state.forceValue(*v2); + v = *v2; +} + + +void ExprSelect::eval(EvalState & state, Env & env, Value & v) +{ + Value v2; + state.eval(env, e, v2); + state.forceAttrs(v2); // !!! eval followed by force is slightly inefficient + Bindings::iterator i = v2.attrs->find(name); + if (i == v2.attrs->end()) + throwEvalError("attribute `%1%' missing", name); + try { + state.forceValue(i->second); + } catch (Error & e) { + addErrorPrefix(e, "while evaluating the attribute `%1%':\n", name); + throw; + } + v = i->second; +} + + +void ExprLambda::eval(EvalState & state, Env & env, Value & v) +{ + v.type = tLambda; + v.lambda.env = &env; + v.lambda.fun = this; +} + + +void ExprApp::eval(EvalState & state, Env & env, Value & v) +{ + Value vFun; + state.eval(env, e1, vFun); + Value vArg; + mkThunk(vArg, env, e2); // !!! should this be on the heap? + state.callFunction(vFun, vArg, v); } @@ -613,19 +575,17 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) Env & env2(allocEnv()); env2.up = fun.lambda.env; - ATermList formals; ATerm ellipsis, name; - - if (matchVarPat(fun.lambda.pat, name)) { - Value & vArg = env2.bindings[name]; + if (!fun.lambda.fun->matchAttrs) { + Value & vArg = env2.bindings[fun.lambda.fun->arg]; nrValues++; vArg = arg; } - else if (matchAttrsPat(fun.lambda.pat, formals, ellipsis, name)) { + else { forceAttrs(arg); - if (name != sNoAlias) { - env2.bindings[name] = arg; + if (!fun.lambda.fun->arg.empty()) { + env2.bindings[fun.lambda.fun->arg] = arg; nrValues++; } @@ -633,21 +593,15 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) there is no matching actual argument but the formal argument has a default, use the default. */ unsigned int attrsUsed = 0; - for (ATermIterator i(formals); i; ++i) { - Expr def; Sym name; - DefaultValue def2; - if (!matchFormal(*i, name, def2)) abort(); /* can't happen */ - - Bindings::iterator j = arg.attrs->find(name); + foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { + Bindings::iterator j = arg.attrs->find(i->name); - Value & v = env2.bindings[name]; + Value & v = env2.bindings[i->name]; nrValues++; if (j == arg.attrs->end()) { - if (!matchDefaultValue(def2, def)) def = 0; - if (def == 0) throwTypeError("the argument named `%1%' required by the function is missing", - aterm2String(name)); - mkThunk(v, env2, def); + if (!i->def) throwTypeError("the argument named `%1%' required by the function is missing", i->name); + mkThunk(v, env2, i->def); } else { attrsUsed++; mkCopy(v, j->second); @@ -658,13 +612,11 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) argument (unless the attribute match specifies a `...'). TODO: show the names of the expected/unexpected arguments. */ - if (ellipsis == eFalse && attrsUsed != arg.attrs->size()) + if (!fun.lambda.fun->formals->ellipsis && attrsUsed != arg.attrs->size()) throwTypeError("function called with unexpected argument"); } - else abort(); - - eval(env2, fun.lambda.body, v); + eval(env2, fun.lambda.fun->body, v); } @@ -672,45 +624,114 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res { forceValue(fun); - ATerm name; - ATermList formals; - ATermBool ellipsis; - - if (fun.type != tLambda || !matchAttrsPat(fun.lambda.pat, formals, ellipsis, name)) { + if (fun.type != tLambda || !fun.lambda.fun->matchAttrs) { res = fun; return; } Value actualArgs; mkAttrs(actualArgs); - - for (ATermIterator i(formals); i; ++i) { - Expr name, def; ATerm def2; - if (!matchFormal(*i, name, def2)) abort(); - Bindings::const_iterator j = args.find(name); + + foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { + Bindings::const_iterator j = args.find(i->name); if (j != args.end()) - (*actualArgs.attrs)[name] = j->second; - else if (!matchDefaultValue(def2, def)) - throwTypeError("cannot auto-call a function that has an argument without a default value (`%1%')", aterm2String(name)); + (*actualArgs.attrs)[i->name] = j->second; + else if (!i->def) + throwTypeError("cannot auto-call a function that has an argument without a default value (`%1%')", i->name); } callFunction(fun, actualArgs, res); } -void EvalState::eval(Expr e, Value & v) +void ExprWith::eval(EvalState & state, Env & env, Value & v) { - eval(baseEnv, e, v); + Env & env2(state.allocEnv()); + env2.up = &env; + + Value & vAttrs = env2.bindings[""]; + state.eval(env, attrs, vAttrs); + state.forceAttrs(vAttrs); + + state.eval(env2, body, v); } -bool EvalState::evalBool(Env & env, Expr e) +void ExprIf::eval(EvalState & state, Env & env, Value & v) { - Value v; - eval(env, e, v); - if (v.type != tBool) - throwTypeError("value is %1% while a Boolean was expected", showType(v)); - return v.boolean; + state.eval(env, state.evalBool(env, cond) ? then : else_, v); +} + + +void ExprOpEq::eval(EvalState & state, Env & env, Value & v) +{ + Value v1; state.eval(env, e1, v1); + Value v2; state.eval(env, e2, v2); + mkBool(v, state.eqValues(v1, v2)); +} + + +void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) +{ + Value v1; state.eval(env, e1, v1); + Value v2; state.eval(env, e2, v2); + mkBool(v, !state.eqValues(v1, v2)); +} + + +void ExprOpAnd::eval(EvalState & state, Env & env, Value & v) +{ + mkBool(v, state.evalBool(env, e1) && state.evalBool(env, e2)); +} + + +void ExprOpOr::eval(EvalState & state, Env & env, Value & v) +{ + mkBool(v, state.evalBool(env, e1) || state.evalBool(env, e2)); +} + + +void ExprOpImpl::eval(EvalState & state, Env & env, Value & v) +{ + mkBool(v, !state.evalBool(env, e1) || state.evalBool(env, e2)); +} + + +void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) +{ + Value v2; + state.eval(env, e1, v2); + state.forceAttrs(v2); + + state.cloneAttrs(v2, v); + + state.eval(env, e2, v2); + state.forceAttrs(v2); + + foreach (Bindings::iterator, i, *v2.attrs) + (*v.attrs)[i->first] = i->second; // !!! sharing +} + + +void ExprOpConcatStrings::eval(EvalState & state, Env & env, Value & v) +{ + abort(); +} + + +void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) +{ + Value v1; state.eval(env, e1, v1); + state.forceList(v1); + Value v2; state.eval(env, e2, v2); + state.forceList(v2); + state.mkList(v, v1.list.length + v2.list.length); + /* !!! This loses sharing with the original lists. We could use a + tCopy node, but that would use more memory. */ + for (unsigned int n = 0; n < v1.list.length; ++n) + v.list.elems[n] = v1.list.elems[n]; + for (unsigned int n = 0; n < v2.list.length; ++n) + v.list.elems[n + v1.list.length] = v2.list.elems[n]; } @@ -827,7 +848,7 @@ string EvalState::forceStringNoCtx(Value & v) bool EvalState::isDerivation(Value & v) { if (v.type != tAttrs) return false; - Bindings::iterator i = v.attrs->find(toATerm("type")); + Bindings::iterator i = v.attrs->find("type"); return i != v.attrs->end() && forceStringNoCtx(i->second) == "derivation"; } @@ -871,7 +892,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, } if (v.type == tAttrs) { - Bindings::iterator i = v.attrs->find(toATerm("outPath")); + Bindings::iterator i = v.attrs->find("outPath"); if (i == v.attrs->end()) throwTypeError("cannot coerce an attribute set (except a derivation) to a string"); return coerceToString(i->second, context, coerceMore, copyToStore); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index fb4dd802e0b0..cbdd09085d7d 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -3,7 +3,6 @@ #include -#include "aterm.hh" #include "nixexpr.hh" @@ -15,7 +14,7 @@ class EvalState; struct Env; struct Value; -typedef ATerm Sym; +typedef string Sym; typedef std::map Bindings; @@ -55,10 +54,32 @@ struct Value { int integer; bool boolean; + + /* Strings in the evaluator carry a so-called `context' (the + ATermList) which is a list of strings representing store + paths. This is to allow users to write things like + + "--with-freetype2-library=" + freetype + "/lib" + + where `freetype' is a derivation (or a source to be copied + to the store). If we just concatenated the strings without + keeping track of the referenced store paths, then if the + string is used as a derivation attribute, the derivation + will not have the correct dependencies in its inputDrvs and + inputSrcs. + + The semantics of the context is as follows: when a string + with context C is used as a derivation attribute, then the + derivations in C will be added to the inputDrvs of the + derivation, and the other store paths in C will be added to + the inputSrcs of the derivations. + + For canonicity, the store paths should be in sorted order. */ struct { const char * s; const char * * context; } string; + const char * path; Bindings * attrs; struct { @@ -67,15 +88,14 @@ struct Value } list; struct { Env * env; - Expr expr; + Expr * expr; } thunk; struct { Value * left, * right; } app; struct { Env * env; - Pattern pat; - Expr body; + ExprLambda * fun; } lambda; Value * val; struct { @@ -104,7 +124,7 @@ static inline void mkBool(Value & v, bool b) } -static inline void mkThunk(Value & v, Env & env, Expr expr) +static inline void mkThunk(Value & v, Env & env, Expr * expr) { v.type = tThunk; v.thunk.env = &env; @@ -146,7 +166,7 @@ private: bool allowUnsafeEquality; - ATermMap parseTrees; + std::map parseTrees; public: @@ -159,12 +179,12 @@ public: /* Evaluate an expression to normal form, storing the result in value `v'. */ - void eval(Expr e, Value & v); - void eval(Env & env, Expr e, Value & v); + void eval(Expr * e, Value & v); + void eval(Env & env, Expr * e, Value & v); /* Evaluation the expression, then verify that it has the expected type. */ - bool evalBool(Env & env, Expr e); + bool evalBool(Env & env, Expr * e); /* 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 @@ -215,12 +235,12 @@ private: void addPrimOp(const string & name, unsigned int arity, PrimOp primOp); +public: + /* Do a deep equality test between two values. That is, list elements and attributes are compared recursively. */ bool eqValues(Value & v1, Value & v2); -public: - void callFunction(Value & fun, Value & arg, Value & v); /* Automatically call a function for which each argument has a @@ -233,7 +253,7 @@ public: void mkList(Value & v, unsigned int length); void mkAttrs(Value & v); - void mkThunk_(Value & v, Expr expr); + void mkThunk_(Value & v, Expr * expr); void cloneAttrs(Value & src, Value & dst); diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index f5e7242f9f5a..95938d5c1fa7 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -1,5 +1,4 @@ #include "get-drvs.hh" -#include "nixexpr-ast.hh" #include "util.hh" @@ -9,7 +8,7 @@ namespace nix { string DrvInfo::queryDrvPath(EvalState & state) const { if (drvPath == "") { - Bindings::iterator i = attrs->find(toATerm("drvPath")); + Bindings::iterator i = attrs->find("drvPath"); PathSet context; (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; } @@ -20,7 +19,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const string DrvInfo::queryOutPath(EvalState & state) const { if (outPath == "") { - Bindings::iterator i = attrs->find(toATerm("outPath")); + Bindings::iterator i = attrs->find("outPath"); PathSet context; (string &) outPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; } @@ -32,7 +31,7 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const { MetaInfo meta; - Bindings::iterator a = attrs->find(toATerm("meta")); + Bindings::iterator a = attrs->find("meta"); if (a == attrs->end()) return meta; /* fine, empty meta information */ state.forceAttrs(a->second); @@ -51,7 +50,7 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const for (unsigned int j = 0; j < i->second.list.length; ++j) value.stringValues.push_back(state.forceStringNoCtx(i->second.list.elems[j])); } else continue; - meta[aterm2String(i->first)] = value; + meta[i->first] = value; } return meta; @@ -114,12 +113,12 @@ static bool getDerivation(EvalState & state, Value & v, DrvInfo drv; - Bindings::iterator i = v.attrs->find(toATerm("name")); + Bindings::iterator i = v.attrs->find("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); - i = v.attrs->find(toATerm("system")); + i = v.attrs->find("system"); if (i == v.attrs->end()) drv.system = "unknown"; else @@ -171,7 +170,7 @@ static void getDerivations(EvalState & state, Value & vIn, /* !!! undocumented hackery to support combining channels in nix-env.cc. */ - bool combineChannels = v.attrs->find(toATerm("_combineChannels")) != v.attrs->end(); + bool combineChannels = v.attrs->find("_combineChannels") != v.attrs->end(); /* Consider the attributes in sorted order to get more deterministic behaviour in nix-env operations (e.g. when @@ -180,12 +179,12 @@ static void getDerivations(EvalState & state, Value & vIn, precedence). */ StringSet attrs; foreach (Bindings::iterator, i, *v.attrs) - attrs.insert(aterm2String(i->first)); + attrs.insert(i->first); foreach (StringSet::iterator, i, attrs) { startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); string pathPrefix2 = addToPath(pathPrefix, *i); - Value & v2((*v.attrs)[toATerm(*i)]); + Value & v2((*v.attrs)[*i]); if (combineChannels) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); else if (getDerivation(state, v2, pathPrefix2, drvs, done)) { @@ -194,7 +193,7 @@ static void getDerivations(EvalState & state, Value & vIn, if it has a `recurseForDerivations = true' attribute. */ if (v2.type == tAttrs) { - Bindings::iterator j = v2.attrs->find(toATerm("recurseForDerivations")); + Bindings::iterator j = v2.attrs->find("recurseForDerivations"); if (j != v2.attrs->end() && state.forceBool(j->second)) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); } diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 82c3500202b0..f750cfd02d54 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -8,9 +8,7 @@ %{ -#include "aterm.hh" #include "nixexpr.hh" -#include "nixexpr-ast.hh" #define BISON_HEADER_HACK #include "parser-tab.hh" @@ -45,8 +43,9 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) } -static Expr unescapeStr(const char * s) +static Expr * unescapeStr(const char * s) { +#if 0 string t; char c; while ((c = *s++)) { @@ -66,6 +65,7 @@ static Expr unescapeStr(const char * s) else t += c; } return makeStr(toATerm(t), ATempty); +#endif } @@ -105,7 +105,7 @@ inherit { return INHERIT; } \/\/ { return UPDATE; } \+\+ { return CONCAT; } -{ID} { yylval->t = toATerm(yytext); return ID; /* !!! alloc */ } +{ID} { yylval->id = strdup(yytext); return ID; } {INT} { int n = atoi(yytext); /* !!! overflow */ yylval->n = n; return INT; @@ -117,7 +117,7 @@ inherit { return INHERIT; } shouldn't be followed by a "{". Right now "$\"" will be consumed as part of a string, rather than a "$" followed by the string terminator. Disallow "$\"" for now. */ - yylval->t = unescapeStr(yytext); /* !!! alloc */ + yylval->e = unescapeStr(yytext); return STR; } \$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } @@ -126,31 +126,31 @@ inherit { return INHERIT; } \'\'(\ *\n)? { BEGIN(IND_STRING); return IND_STRING_OPEN; } ([^\$\']|\$[^\{\']|\'[^\'\$])+ { - yylval->t = makeIndStr(toATerm(yytext)); + //yylval->t = makeIndStr(toATerm(yytext)); return IND_STR; } \'\'\$ { - yylval->t = makeIndStr(toATerm("$")); + //yylval->t = makeIndStr(toATerm("$")); return IND_STR; } \'\'\' { - yylval->t = makeIndStr(toATerm("''")); + //yylval->t = makeIndStr(toATerm("''")); return IND_STR; } \'\'\\. { - yylval->t = unescapeStr(yytext + 2); + //yylval->t = unescapeStr(yytext + 2); return IND_STR; } \$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } \'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; } \' { - yylval->t = makeIndStr(toATerm("'")); + //yylval->t = makeIndStr(toATerm("'")); return IND_STR; } . return yytext[0]; /* just in case: shouldn't be reached */ -{PATH} { yylval->t = toATerm(yytext); return PATH; /* !!! alloc */ } -{URI} { yylval->t = toATerm(yytext); return URI; /* !!! alloc */ } +{PATH} { yylval->path = strdup(yytext); return PATH; } +{URI} { yylval->uri = strdup(yytext); return URI; } [ \t\r\n]+ /* eat up whitespace */ \#[^\r\n]* /* single-line comments */ diff --git a/src/libexpr/nixexpr-ast.def b/src/libexpr/nixexpr-ast.def deleted file mode 100644 index 36c25dcfe7a0..000000000000 --- a/src/libexpr/nixexpr-ast.def +++ /dev/null @@ -1,97 +0,0 @@ -init initNixExprHelpers - -Pos | string int int | Pos | -NoPos | | Pos | - -Function | Pattern Expr Pos | Expr | -Assert | Expr Expr Pos | Expr | -With | Expr Expr Pos | Expr | -If | Expr Expr Expr | Expr | -OpNot | Expr | Expr | -OpEq | Expr Expr | Expr | -OpNEq | Expr Expr | Expr | -OpAnd | Expr Expr | Expr | -OpOr | Expr Expr | Expr | -OpImpl | Expr Expr | Expr | -OpUpdate | Expr Expr | Expr | -OpHasAttr | Expr string | Expr | -OpPlus | Expr Expr | Expr | -OpConcat | Expr Expr | Expr | -ConcatStrings | ATermList | Expr | -Call | Expr Expr | Expr | -Select | Expr string | Expr | -Var | string | Expr | -Int | int | Expr | - -# Strings in the evaluator carry a so-called `context' (the ATermList) -# which is a list of strings representing store paths. This is to -# allow users to write things like -# -# "--with-freetype2-library=" + freetype + "/lib" -# -# where `freetype' is a derivation (or a source to be copied to the -# store). If we just concatenated the strings without keeping track -# of the referenced store paths, then if the string is used as a -# derivation attribute, the derivation will not have the correct -# dependencies in its inputDrvs and inputSrcs. -# -# The semantics of the context is as follows: when a string with -# context C is used as a derivation attribute, then the derivations in -# C will be added to the inputDrvs of the derivation, and the other -# store paths in C will be added to the inputSrcs of the derivations. -# -# For canonicity, the store paths should be in sorted order. -Str | string ATermList | Expr | -Str | string | Expr | ObsoleteStr - -# Internal to the parser, doesn't occur in ASTs. -IndStr | string | Expr | - -# A path is a reference to a file system object that is to be copied -# to the Nix store when used as a derivation attribute. When it is -# concatenated to a string (i.e., `str + path'), it is also copied and -# the resulting store path is concatenated to the string (with the -# store path in the context). If a string or path is concatenated to -# a path (i.e., `path + str' or `path + path'), the result is a new -# path (if the right-hand side is a string, the context must be -# empty). -Path | string | Expr | - -List | ATermList | Expr | -BlackHole | | Expr | -Undefined | | Expr | -Removed | | Expr | -PrimOp | int ATermBlob ATermList | Expr | -Attrs | ATermList | Expr | -Closed | Expr | Expr | -Rec | ATermList ATermList | Expr | -Bool | ATermBool | Expr | -Null | | Expr | - -Bind | string Expr Pos | ATerm | -BindAttrPath | ATermList Expr Pos | ATerm | # desugared during parsing -Bind | string Expr | ATerm | ObsoleteBind -Inherit | Expr ATermList Pos | ATerm | - -Scope | | Expr | - -VarPat | string | Pattern | -AttrsPat | ATermList ATermBool string | Pattern | # bool = `...' - -Formal | string DefaultValue | ATerm | - -DefaultValue | Expr | DefaultValue | -NoDefaultValue | | DefaultValue | - -True | | ATermBool | -False | | ATermBool | - -PrimOpDef | int ATermBlob | ATerm | - -AttrRHS | Expr Pos | ATerm | - -eTrue = makeBool(makeTrue()) -eFalse = makeBool(makeFalse()) -sOverrides = toATerm("__overrides") -sNoAlias = toATerm("") -sWith = toATerm("") diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 3c5d02b34f66..05dfbd3223e3 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -1,17 +1,94 @@ #include "nixexpr.hh" #include "derivations.hh" #include "util.hh" -#include "aterm.hh" - -#include "nixexpr-ast.hh" -#include "nixexpr-ast.cc" #include namespace nix { - + +std::ostream & operator << (std::ostream & str, Expr & e) +{ + e.show(str); + return str; +} + + +void ExprInt::show(std::ostream & str) +{ + str << n; +} + +void ExprString::show(std::ostream & str) +{ + str << "\"" << s << "\""; // !!! escaping +} + +void ExprPath::show(std::ostream & str) +{ + str << s; +} + +void ExprVar::show(std::ostream & str) +{ + str << name; +} + +void ExprSelect::show(std::ostream & str) +{ + str << "(" << *e << ")." << name; +} + +void ExprAttrs::show(std::ostream & str) +{ + if (recursive) str << "rec "; + str << "{ "; + foreach (list::iterator, i, inherited) + str << "inherited " << *i << "; "; + foreach (Attrs::iterator, i, attrs) + str << i->first << " = " << *i->second << "; "; + str << "}"; +} + +void ExprList::show(std::ostream & str) +{ + str << "[ "; + foreach (vector::iterator, i, elems) + str << "(" << **i << ") "; + str << "]"; +} + +void ExprLambda::show(std::ostream & str) +{ + str << "("; + if (matchAttrs) { + str << "{ "; + bool first = true; + foreach (Formals::Formals_::iterator, i, formals->formals) { + if (first) first = false; else str << ", "; + str << i->name; + if (i->def) str << " ? " << *i->def; + } + str << " }"; + if (arg != "") str << " @ "; + } + if (arg != "") str << arg; + str << ": " << *body << ")"; +} + +void ExprWith::show(std::ostream & str) +{ + str << "with " << *attrs << "; " << *body; +} + +void ExprIf::show(std::ostream & str) +{ + str << "if " << *cond << " then " << *then << " else " << *else_; +} + + +#if 0 string showPos(ATerm pos) { ATerm path; @@ -159,28 +236,7 @@ void checkVarDefs(const ATermMap & defs, Expr e) set done; checkVarDefs2(done, defs, e); } - - -bool matchStr(Expr e, string & s, PathSet & context) -{ - ATermList l; - ATerm s_; - - if (!matchStr(e, s_, l)) return false; - - s = aterm2String(s_); - - for (ATermIterator i(l); i; ++i) - context.insert(aterm2String(*i)); - - return true; -} - - -Expr makeStr(const string & s, const PathSet & context) -{ - return makeStr(toATerm(s), toATermList(context)); -} +#endif } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 9f1050d807d4..ebdfd0a152ca 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -3,7 +3,6 @@ #include -#include "aterm-map.hh" #include "types.hh" @@ -18,22 +17,152 @@ MakeError(Abort, EvalError) MakeError(TypeError, EvalError) -/* Nix expressions are represented as ATerms. The maximal sharing - property of the ATerm library allows us to implement caching of - normals forms efficiently. */ -typedef ATerm Expr; -typedef ATerm DefaultValue; -typedef ATerm Pos; -typedef ATerm Pattern; -typedef ATerm ATermBool; +struct Pos +{ + string file; + unsigned int line, column; +}; + + +/* Abstract syntax of Nix expressions. */ + +struct Env; +struct Value; +struct EvalState; + +struct Expr +{ + virtual void show(std::ostream & str) = 0; + virtual void eval(EvalState & state, Env & env, Value & v) + { + throw Error("not implemented"); + } +}; + +std::ostream & operator << (std::ostream & str, Expr & e); + +#define COMMON_METHODS \ + void show(std::ostream & str); \ + void eval(EvalState & state, Env & env, Value & v); + +struct ExprInt : Expr +{ + int n; + ExprInt(int n) : n(n) { }; + COMMON_METHODS +}; + +struct ExprString : Expr +{ + string s; + ExprString(const string & s) : s(s) { }; + COMMON_METHODS +}; + +struct ExprPath : Expr +{ + string s; + ExprPath(const string & s) : s(s) { }; + COMMON_METHODS +}; + +struct ExprVar : Expr +{ + string name; + ExprVar(const string & name) : name(name) { }; + COMMON_METHODS +}; + +struct ExprSelect : Expr +{ + Expr * e; + string name; + ExprSelect(Expr * e, const string & name) : e(e), name(name) { }; + COMMON_METHODS +}; + +struct ExprAttrs : Expr +{ + bool recursive; + typedef std::map Attrs; + Attrs attrs; + list inherited; + ExprAttrs() : recursive(false) { }; + COMMON_METHODS +}; +struct ExprList : Expr +{ + std::vector elems; + ExprList() { }; + COMMON_METHODS +}; -/* A STL vector of ATerms. Should be used with great care since it's - stored on the heap, and the elements are therefore not roots to the - ATerm garbage collector. */ -typedef vector ATermVector; +struct Formal +{ + string name; + Expr * def; + Formal(const string & name, Expr * def) : name(name), def(def) { }; +}; +struct Formals +{ + typedef std::list Formals_; + Formals_ formals; + bool ellipsis; +}; +struct ExprLambda : Expr +{ + Pos pos; + string arg; + bool matchAttrs; + Formals * formals; + Expr * body; + ExprLambda(const Pos & pos, const string & arg, bool matchAttrs, Formals * formals, Expr * body) + : pos(pos), arg(arg), matchAttrs(matchAttrs), formals(formals), body(body) { }; + COMMON_METHODS +}; + +struct ExprWith : Expr +{ + Pos pos; + Expr * attrs, * body; + ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { }; + COMMON_METHODS +}; + +struct ExprIf : Expr +{ + Expr * cond, * then, * else_; + ExprIf(Expr * cond, Expr * then, Expr * else_) : cond(cond), then(then), else_(else_) { }; + COMMON_METHODS +}; + +#define MakeBinOp(name, s) \ + struct Expr##name : Expr \ + { \ + Expr * e1, * e2; \ + Expr##name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \ + void show(std::ostream & str) \ + { \ + str << *e1 << " " s " " << *e2; \ + } \ + void eval(EvalState & state, Env & env, Value & v); \ + }; + +MakeBinOp(App, "") +MakeBinOp(OpEq, "==") +MakeBinOp(OpNEq, "!=") +MakeBinOp(OpAnd, "&&") +MakeBinOp(OpOr, "||") +MakeBinOp(OpImpl, "->") +MakeBinOp(OpUpdate, "//") +MakeBinOp(OpConcatStrings, "+") +MakeBinOp(OpConcatLists, "++") + + +#if 0 /* Show a position. */ string showPos(ATerm pos); @@ -56,13 +185,7 @@ Expr makeAttrs(const ATermMap & attrs); /* Check whether all variables are defined in the given expression. Throw an exception if this isn't the case. */ void checkVarDefs(const ATermMap & def, Expr e); - - -/* Manipulation of Str() nodes. Note: matchStr() does not clear - context! */ -bool matchStr(Expr e, string & s, PathSet & context); - -Expr makeStr(const string & s, const PathSet & context = PathSet()); +#endif } diff --git a/src/libexpr/parser.hh b/src/libexpr/parser.hh index 3f430eb32539..d1e531ca2921 100644 --- a/src/libexpr/parser.hh +++ b/src/libexpr/parser.hh @@ -9,11 +9,10 @@ namespace nix { /* Parse a Nix expression from the specified file. If `path' refers to a directory, then "/default.nix" is appended. */ -Expr parseExprFromFile(EvalState & state, Path path); +Expr * parseExprFromFile(Path path); /* Parse a Nix expression from the specified string. */ -Expr parseExprFromString(EvalState & state, const string & s, - const Path & basePath); +Expr * parseExprFromString(const string & s, const Path & basePath); } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index a28d56d24f67..96fbe2cb4be2 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -23,13 +23,12 @@ #include "aterm.hh" #include "util.hh" +#include "nixexpr.hh" + #include "parser-tab.hh" #include "lexer-tab.hh" #define YYSTYPE YYSTYPE // workaround a bug in Bison 2.4 -#include "nixexpr.hh" -#include "nixexpr-ast.hh" - using namespace nix; @@ -39,13 +38,14 @@ namespace nix { struct ParseData { - Expr result; + Expr * result; Path basePath; Path path; string error; }; - + +#if 0 static string showAttrPath(ATermList attrPath) { string s; @@ -79,10 +79,12 @@ static ATermList buildAttrs(const Tree & t, ATermList & nonrec) : makeBind(i->first, makeAttrs(buildAttrs(i->second, nonrec)), makeNoPos())); return res; } +#endif -static Expr fixAttrs(bool recursive, ATermList as) +static void fixAttrs(ExprAttrs & attrs) { +#if 0 Tree attrs; /* This ATermMap is needed to ensure that the `leaf' fields in the @@ -135,9 +137,11 @@ static Expr fixAttrs(bool recursive, ATermList as) ATermList rec = buildAttrs(attrs, nonrec); return recursive ? makeRec(rec, nonrec) : makeAttrs(rec); +#endif } +#if 0 static void checkPatternVars(ATerm pos, ATermMap & map, Pattern pat) { ATerm name = sNoAlias; @@ -261,6 +265,7 @@ static Expr stripIndentation(ATermList es) return makeConcatStrings(ATreverse(es2)); } +#endif void backToString(yyscan_t scanner); @@ -269,8 +274,11 @@ void backToIndString(yyscan_t scanner); static Pos makeCurPos(YYLTYPE * loc, ParseData * data) { - return makePos(toATerm(data->path), - loc->first_line, loc->first_column); + Pos pos; + pos.file = data->path; + pos.line = loc->first_line; + pos.column = loc->first_column; + return pos; } #define CUR_POS makeCurPos(yylocp, data) @@ -311,22 +319,31 @@ static void freeAndUnprotect(void * p) %} %union { - ATerm t; - ATermList ts; - struct { - ATermList formals; - bool ellipsis; - } formals; + nix::Expr * e; + nix::ExprList * list; + nix::ExprAttrs * attrs; + nix::Formals * formals; + nix::Formal * formal; int n; + char * id; + char * path; + char * uri; + std::list * ids; } -%type start expr expr_function expr_if expr_op -%type expr_app expr_select expr_simple bind inheritsrc formal -%type pattern -%type binds ids attrpath expr_list string_parts ind_string_parts +%type start expr expr_function expr_if expr_op +%type expr_app expr_select expr_simple +%type expr_list +%type binds +%type attrpath string_parts ind_string_parts %type formals -%token ID STR IND_STR PATH URI +%type formal +%type ids +%token ID ATTRPATH +%token STR IND_STR %token INT +%token PATH +%token URI %token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL %token DOLLAR_CURLY /* == ${ */ %token IND_STRING_OPEN IND_STRING_CLOSE @@ -350,54 +367,63 @@ start: expr { data->result = $1; }; expr: expr_function; expr_function - : pattern ':' expr_function - { checkPatternVars(CUR_POS, $1); $$ = makeFunction($1, $3, CUR_POS); } - | ASSERT expr ';' expr_function + : ID ':' expr_function + { $$ = new ExprLambda(CUR_POS, $1, false, 0, $3); /* checkPatternVars(CUR_POS, $1); $$ = makeFunction($1, $3, CUR_POS); */ } + | '{' formals '}' ':' expr_function + { $$ = new ExprLambda(CUR_POS, "", true, $2, $5); } + | '{' formals '}' '@' ID ':' expr_function + { $$ = new ExprLambda(CUR_POS, $5, true, $2, $7); } + | ID '@' '{' formals '}' ':' expr_function + { $$ = new ExprLambda(CUR_POS, $1, true, $4, $7); } + /* | ASSERT expr ';' expr_function { $$ = makeAssert($2, $4, CUR_POS); } + */ | WITH expr ';' expr_function - { $$ = makeWith($2, $4, CUR_POS); } + { $$ = new ExprWith(CUR_POS, $2, $4); } | LET binds IN expr_function - { $$ = makeSelect(fixAttrs(true, ATinsert($2, makeBindAttrPath(ATmakeList1(toATerm("")), $4, CUR_POS))), toATerm("")); } + { $2->attrs[""] = $4; $2->recursive = true; fixAttrs(*$2); $$ = new ExprSelect($2, ""); } | expr_if ; expr_if - : IF expr THEN expr ELSE expr - { $$ = makeIf($2, $4, $6); } + : IF expr THEN expr ELSE expr { $$ = new ExprIf($2, $4, $6); } | expr_op ; expr_op - : '!' expr_op %prec NEG { $$ = makeOpNot($2); } - | expr_op EQ expr_op { $$ = makeOpEq($1, $3); } - | expr_op NEQ expr_op { $$ = makeOpNEq($1, $3); } - | expr_op AND expr_op { $$ = makeOpAnd($1, $3); } - | expr_op OR expr_op { $$ = makeOpOr($1, $3); } - | expr_op IMPL expr_op { $$ = makeOpImpl($1, $3); } - | expr_op UPDATE expr_op { $$ = makeOpUpdate($1, $3); } + : /* '!' expr_op %prec NEG { $$ = makeOpNot($2); } + | */ + expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } + | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } + | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); } + | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); } + | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); } + | expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); } + /* | expr_op '?' ID { $$ = makeOpHasAttr($1, $3); } - | expr_op '+' expr_op { $$ = makeConcatStrings(ATmakeList2($1, $3)); } - | expr_op CONCAT expr_op { $$ = makeOpConcat($1, $3); } + */ + | expr_op '+' expr_op { $$ = new ExprOpConcatStrings($1, $3); } + | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); } | expr_app ; expr_app : expr_app expr_select - { $$ = makeCall($1, $2); } + { $$ = new ExprApp($1, $2); } | expr_select { $$ = $1; } ; expr_select : expr_select '.' ID - { $$ = makeSelect($1, $3); } + { $$ = new ExprSelect($1, $3); } | expr_simple { $$ = $1; } ; expr_simple - : ID { $$ = makeVar($1); } - | INT { $$ = makeInt($1); } + : ID { $$ = new ExprVar($1); } + | INT { $$ = new ExprInt($1); } /* | '"' string_parts '"' { - /* For efficiency, and to simplify parse trees a bit. */ + /* For efficiency, and to simplify parse trees a bit. * / if ($2 == ATempty) $$ = makeStr(toATerm(""), ATempty); else if (ATgetNext($2) == ATempty) $$ = ATgetFirst($2); else $$ = makeConcatStrings(ATreverse($2)); @@ -405,18 +431,21 @@ expr_simple | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { $$ = stripIndentation(ATreverse($2)); } - | PATH { $$ = makePath(toATerm(absPath(aterm2String($1), data->basePath))); } - | URI { $$ = makeStr($1, ATempty); } + */ + | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } + | URI { $$ = new ExprString($1); } | '(' expr ')' { $$ = $2; } +/* /* Let expressions `let {..., body = ...}' are just desugared - into `(rec {..., body = ...}).body'. */ + into `(rec {..., body = ...}).body'. * / | LET '{' binds '}' { $$ = makeSelect(fixAttrs(true, $3), toATerm("body")); } + */ | REC '{' binds '}' - { $$ = fixAttrs(true, $3); } + { fixAttrs(*$3); $3->recursive = true; $$ = $3; } | '{' binds '}' - { $$ = fixAttrs(false, $2); } - | '[' expr_list ']' { $$ = makeList(ATreverse($2)); } + { fixAttrs(*$2); $$ = $2; } + | '[' expr_list ']' { $$ = $2; } ; string_parts @@ -431,63 +460,56 @@ ind_string_parts | { $$ = ATempty; } ; -pattern - : ID { $$ = makeVarPat($1); } - | '{' formals '}' { $$ = makeAttrsPat($2.formals, $2.ellipsis ? eTrue : eFalse, sNoAlias); } - | '{' formals '}' '@' ID { $$ = makeAttrsPat($2.formals, $2.ellipsis ? eTrue : eFalse, $5); } - | ID '@' '{' formals '}' { $$ = makeAttrsPat($4.formals, $4.ellipsis ? eTrue : eFalse, $1); } - ; - binds - : binds bind { $$ = ATinsert($1, $2); } - | { $$ = ATempty; } - ; - -bind - : attrpath '=' expr ';' - { $$ = makeBindAttrPath(ATreverse($1), $3, CUR_POS); } - | INHERIT inheritsrc ids ';' - { $$ = makeInherit($2, $3, CUR_POS); } + : binds ID '=' expr ';' { $$ = $1; $$->attrs[$2] = $4; } + | binds INHERIT ids ';' + { $$ = $1; + foreach (list::iterator, i, *$3) + $$->inherited.push_back(*i); + } + | binds INHERIT '(' expr ')' ids ';' + { $$ = $1; + /* !!! Should ensure sharing of the expression in $4. */ + foreach (list::iterator, i, *$6) + $$->attrs[*i] = new ExprSelect($4, *i); + } + | { $$ = new ExprAttrs; } ; -inheritsrc - : '(' expr ')' { $$ = $2; } - | { $$ = makeScope(); } +ids + : ids ID { $$ = $1; $1->push_back($2); /* !!! dangerous */ } + | { $$ = new list; } ; -ids: ids ID { $$ = ATinsert($1, $2); } | { $$ = ATempty; }; - attrpath : attrpath '.' ID { $$ = ATinsert($1, $3); } | ID { $$ = ATmakeList1($1); } ; expr_list - : expr_list expr_select { $$ = ATinsert($1, $2); } - | { $$ = ATempty; } + : expr_list expr_select { $$ = $1; $1->elems.push_back($2); /* !!! dangerous */ } + | { $$ = new ExprList; } ; formals - : formal ',' formals /* !!! right recursive */ - { $$.formals = ATinsert($3.formals, $1); $$.ellipsis = $3.ellipsis; } + : formal ',' formals + { $$ = $3; $$->formals.push_front(*$1); /* !!! dangerous */ } | formal - { $$.formals = ATinsert(ATempty, $1); $$.ellipsis = false; } + { $$ = new Formals; $$->formals.push_back(*$1); $$->ellipsis = false; } | - { $$.formals = ATempty; $$.ellipsis = false; } + { $$ = new Formals; $$->ellipsis = false; } | ELLIPSIS - { $$.formals = ATempty; $$.ellipsis = true; } + { $$ = new Formals; $$->ellipsis = true; } ; formal - : ID { $$ = makeFormal($1, makeNoDefaultValue()); } - | ID '?' expr { $$ = makeFormal($1, makeDefaultValue($3)); } + : ID { $$ = new Formal($1, 0); } + | ID '?' expr { $$ = new Formal($1, $3); } ; %% -#include "eval.hh" - #include #include #include @@ -497,9 +519,7 @@ formal namespace nix { -static Expr parse(EvalState & state, - const char * text, const Path & path, - const Path & basePath) +static Expr * parse(const char * text, const Path & path, const Path & basePath) { yyscan_t scanner; ParseData data; @@ -523,7 +543,7 @@ static Expr parse(EvalState & state, } -Expr parseExprFromFile(EvalState & state, Path path) +Expr * parseExprFromFile(Path path) { assert(path[0] == '/'); @@ -544,14 +564,13 @@ Expr parseExprFromFile(EvalState & state, Path path) path = canonPath(path + "/default.nix"); /* Read and parse the input file. */ - return parse(state, readFile(path).c_str(), path, dirOf(path)); + return parse(readFile(path).c_str(), path, dirOf(path)); } -Expr parseExprFromString(EvalState & state, - const string & s, const Path & basePath) +Expr * parseExprFromString(const string & s, const Path & basePath) { - return parse(state, s.c_str(), "(string)", basePath); + return parse(s.c_str(), "(string)", basePath); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 74eb2b26d068..cd40ade008cf 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -5,7 +5,6 @@ #include "util.hh" #include "archive.hh" #include "value-to-xml.hh" -#include "nixexpr-ast.hh" #include "parser.hh" #include "names.hh" @@ -281,7 +280,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) state.forceAttrs(*args[0]); /* Figure out the name first (for stack backtraces). */ - Bindings::iterator attr = args[0]->attrs->find(toATerm("name")); + Bindings::iterator attr = args[0]->attrs->find("name"); if (attr == args[0]->attrs->end()) throw EvalError("required attribute `name' missing"); string drvName; @@ -302,7 +301,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) bool outputHashRecursive = false; foreach (Bindings::iterator, i, *args[0]->attrs) { - string key = aterm2String(i->first); + string key = i->first; startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); try { @@ -449,8 +448,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* !!! assumes a single output */ state.mkAttrs(v); - mkString((*v.attrs)[toATerm("outPath")], outPath, singleton(drvPath)); - mkString((*v.attrs)[toATerm("drvPath")], drvPath, singleton("=" + drvPath)); + mkString((*v.attrs)["outPath"], outPath, singleton(drvPath)); + mkString((*v.attrs)["drvPath"], drvPath, singleton("=" + drvPath)); } @@ -655,7 +654,7 @@ static void prim_attrNames(EvalState & state, Value * * args, Value & v) StringSet names; foreach (Bindings::iterator, i, *args[0]->attrs) - names.insert(aterm2String(i->first)); + names.insert(i->first); unsigned int n = 0; foreach (StringSet::iterator, i, names) @@ -668,7 +667,7 @@ static void prim_getAttr(EvalState & state, Value * * args, Value & v) { string attr = state.forceStringNoCtx(*args[0]); state.forceAttrs(*args[1]); - Bindings::iterator i = args[1]->attrs->find(toATerm(attr)); + Bindings::iterator i = args[1]->attrs->find(attr); if (i == args[1]->attrs->end()) throw EvalError(format("attribute `%1%' missing") % attr); state.forceValue(i->second); @@ -681,7 +680,7 @@ static void prim_hasAttr(EvalState & state, Value * * args, Value & v) { string attr = state.forceStringNoCtx(*args[0]); state.forceAttrs(*args[1]); - mkBool(v, args[1]->attrs->find(toATerm(attr)) != args[1]->attrs->end()); + mkBool(v, args[1]->attrs->find(attr) != args[1]->attrs->end()); } @@ -702,7 +701,7 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v) for (unsigned int i = 0; i < args[1]->list.length; ++i) { state.forceStringNoCtx(args[1]->list.elems[i]); - v.attrs->erase(toATerm(args[1]->list.elems[i].string.s)); + v.attrs->erase(args[1]->list.elems[i].string.s); } } @@ -721,16 +720,16 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) Value & v2(args[0]->list.elems[i]); state.forceAttrs(v2); - Bindings::iterator j = v2.attrs->find(toATerm("name")); + Bindings::iterator j = v2.attrs->find("name"); if (j == v2.attrs->end()) throw TypeError("`name' attribute missing in a call to `listToAttrs'"); string name = state.forceStringNoCtx(j->second); - j = v2.attrs->find(toATerm("value")); + j = v2.attrs->find("value"); if (j == v2.attrs->end()) throw TypeError("`value' attribute missing in a call to `listToAttrs'"); - (*v.attrs)[toATerm(name)] = j->second; // !!! sharing? + (*v.attrs)[name] = j->second; // !!! sharing? } } @@ -977,8 +976,8 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v) string name = state.forceStringNoCtx(*args[0]); DrvName parsed(name); state.mkAttrs(v); - mkString((*v.attrs)[toATerm("name")], parsed.name); - mkString((*v.attrs)[toATerm("version")], parsed.version); + mkString((*v.attrs)["name"], parsed.name); + mkString((*v.attrs)["version"], parsed.version); } @@ -999,10 +998,9 @@ void EvalState::createBaseEnv() { baseEnv.up = 0; - { Value & v = baseEnv.bindings[toATerm("builtins")]; - v.type = tAttrs; - v.attrs = new Bindings; - } + Value & builtins = baseEnv.bindings["builtins"]; + builtins.type = tAttrs; + builtins.attrs = new Bindings; /* Add global constants such as `true' to the base environment. */ Value v; @@ -1025,8 +1023,8 @@ void EvalState::createBaseEnv() /* Add a wrapper around the derivation primop that computes the `drvPath' and `outPath' attributes lazily. */ string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }"; - mkThunk(v, baseEnv, parseExprFromString(*this, s, "/")); - addConstant("derivation", v); + //mkThunk(v, baseEnv, parseExprFromString(s, "/")); + //addConstant("derivation", v); // Miscellaneous addPrimOp("import", 1, prim_import); diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index eff414aba3b5..c8a067aacf77 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -1,7 +1,5 @@ #include "value-to-xml.hh" #include "xml-writer.hh" -#include "nixexpr-ast.hh" -#include "aterm.hh" #include "util.hh" #include @@ -27,31 +25,10 @@ static void showAttrs(EvalState & state, bool strict, Bindings & attrs, { StringSet names; foreach (Bindings::iterator, i, attrs) - names.insert(aterm2String(i->first)); + names.insert(i->first); foreach (StringSet::iterator, i, names) { XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); - printValueAsXML(state, strict, attrs[toATerm(*i)], doc, context, drvsSeen); - } -} - - -static void printPatternAsXML(Pattern pat, XMLWriter & doc) -{ - ATerm name; - ATermList formals; - ATermBool ellipsis; - if (matchVarPat(pat, name)) - doc.writeEmptyElement("varpat", singletonAttrs("name", aterm2String(name))); - else if (matchAttrsPat(pat, formals, ellipsis, name)) { - XMLAttrs attrs; - if (name != sNoAlias) attrs["name"] = aterm2String(name); - if (ellipsis == eTrue) attrs["ellipsis"] = "1"; - XMLOpenElement _(doc, "attrspat", attrs); - for (ATermIterator i(formals); i; ++i) { - Expr name; ATerm dummy; - if (!matchFormal(*i, name, dummy)) abort(); - doc.writeEmptyElement("attr", singletonAttrs("name", aterm2String(name))); - } + printValueAsXML(state, strict, attrs[*i], doc, context, drvsSeen); } } @@ -90,14 +67,14 @@ static void printValueAsXML(EvalState & state, bool strict, Value & v, if (state.isDerivation(v)) { XMLAttrs xmlAttrs; - Bindings::iterator a = v.attrs->find(toATerm("derivation")); + Bindings::iterator a = v.attrs->find("derivation"); Path drvPath; - a = v.attrs->find(toATerm("drvPath")); + a = v.attrs->find("drvPath"); if (a != v.attrs->end() && a->second.type == tString) xmlAttrs["drvPath"] = drvPath = a->second.string.s; - a = v.attrs->find(toATerm("outPath")); + a = v.attrs->find("outPath"); if (a != v.attrs->end() && a->second.type == tString) xmlAttrs["outPath"] = a->second.string.s; @@ -126,7 +103,15 @@ static void printValueAsXML(EvalState & state, bool strict, Value & v, case tLambda: { XMLOpenElement _(doc, "function"); - printPatternAsXML(v.lambda.pat, doc); + if (v.lambda.fun->matchAttrs) { + XMLAttrs attrs; + if (!v.lambda.fun->arg.empty()) attrs["name"] = v.lambda.fun->arg; + if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1"; + XMLOpenElement _(doc, "attrspat", attrs); + foreach (Formals::Formals_::iterator, i, v.lambda.fun->formals->formals) + doc.writeEmptyElement("attr", singletonAttrs("name", i->name)); + } else + doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg)); break; } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index d9cf9a86262a..c53c558c1cdd 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -177,7 +177,7 @@ static void initAndRun(int argc, char * * argv) if (lt != "") setLogType(lt); /* ATerm stuff. !!! find a better place to put this */ - initDerivationsHelpers(); + //initDerivationsHelpers(); /* Put the arguments in a vector. */ Strings args, remaining; @@ -335,7 +335,7 @@ int main(int argc, char * * argv) /* ATerm setup. */ ATerm bottomOfStack; - ATinit(argc, argv, &bottomOfStack); + //ATinit(argc, argv, &bottomOfStack); /* Turn on buffering for cerr. */ #if HAVE_PUBSETBUF diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 20affa83ddd0..6286648d14a0 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -6,7 +6,6 @@ #include "parser.hh" #include "eval.hh" #include "help.txt.hh" -#include "nixexpr-ast.hh" #include "get-drvs.hh" #include "attr-path.hh" #include "pathlocks.hh" @@ -143,9 +142,9 @@ static void getAllExprs(EvalState & state, } -static Expr loadSourceExpr(EvalState & state, const Path & path) +static Expr * loadSourceExpr(EvalState & state, const Path & path) { - if (isNixExpr(path)) return parseExprFromFile(state, absPath(path)); + if (isNixExpr(path)) return parseExprFromFile(absPath(path)); /* The path is a directory. Put the Nix expressions in the directory in an attribute set, with the file name of each diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 7931af6abd02..466c7b499e22 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -23,12 +23,12 @@ void printHelp() } -static Expr parseStdin(EvalState & state) +static Expr * parseStdin(EvalState & state) { startNest(nest, lvlTalkative, format("parsing standard input")); string s, s2; while (getline(std::cin, s2)) s += s2 + "\n"; - return parseExprFromString(state, s, absPath(".")); + return parseExprFromString(s, absPath(".")); } @@ -39,7 +39,7 @@ static bool indirectRoot = false; void processExpr(EvalState & state, const Strings & attrPaths, bool parseOnly, bool strict, const Bindings & autoArgs, - bool evalOnly, bool xmlOutput, Expr e) + bool evalOnly, bool xmlOutput, Expr * e) { if (parseOnly) std::cout << format("%1%\n"); @@ -129,14 +129,14 @@ void run(Strings args) store = openStore(); if (readStdin) { - Expr e = parseStdin(state); + Expr * e = parseStdin(state); processExpr(state, attrPaths, parseOnly, strict, autoArgs, evalOnly, xmlOutput, e); } foreach (Strings::iterator, i, files) { Path path = absPath(*i); - Expr e = parseExprFromFile(state, path); + Expr * e = parseExprFromFile(path); processExpr(state, attrPaths, parseOnly, strict, autoArgs, evalOnly, xmlOutput, e); } -- cgit 1.4.1 From 011b5da0f46e9796fc68bc5daf5fe4dd4b57f933 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 14 Apr 2010 09:39:06 +0000 Subject: * Get nix-env to compile again. --- src/nix-env/nix-env.cc | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) (limited to 'src/nix-env') diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 6286648d14a0..d44517ba678a 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -111,7 +111,7 @@ static bool isNixExpr(const Path & path) static void getAllExprs(EvalState & state, - const Path & path, ATermMap & attrs) + const Path & path, ExprAttrs & attrs) { Strings names = readDirectory(path); StringSet namesSorted(names.begin(), names.end()); @@ -131,8 +131,8 @@ static void getAllExprs(EvalState & state, string attrName = *i; if (hasSuffix(attrName, ".nix")) attrName = string(attrName, 0, attrName.size() - 4); - attrs.set(toATerm(attrName), makeAttrRHS( - parseExprFromFile(state, absPath(path2)), makeNoPos())); + attrs.attrs[state.symbols.create(attrName)] = + parseExprFromFile(state, absPath(path2)); } else /* `path2' is a directory (with no default.nix in it); @@ -144,7 +144,7 @@ static void getAllExprs(EvalState & state, static Expr * loadSourceExpr(EvalState & state, const Path & path) { - if (isNixExpr(path)) return parseExprFromFile(absPath(path)); + if (isNixExpr(path)) return parseExprFromFile(state, absPath(path)); /* The path is a directory. Put the Nix expressions in the directory in an attribute set, with the file name of each @@ -152,10 +152,10 @@ static Expr * loadSourceExpr(EvalState & state, const Path & path) (but keep the attribute set flat, not nested, to make it easier for a user to have a ~/.nix-defexpr directory that includes some system-wide directory). */ - ATermMap attrs; - attrs.set(toATerm("_combineChannels"), makeAttrRHS(makeList(ATempty), makeNoPos())); - getAllExprs(state, path, attrs); - return makeAttrs(attrs); + ExprAttrs * attrs = new ExprAttrs; + attrs->attrs[state.symbols.create("_combineChannels")] = new ExprInt(1); + getAllExprs(state, path, *attrs); + return attrs; } @@ -192,20 +192,6 @@ static Path getDefNixExprPath() } -struct AddPos : TermFun -{ - ATerm operator () (ATerm e) - { - ATerm x, y; - if (matchObsoleteBind(e, x, y)) - return makeBind(x, y, makeNoPos()); - if (matchObsoleteStr(e, x)) - return makeStr(x, ATempty); - return e; - } -}; - - static DrvInfos queryInstalled(EvalState & state, const Path & userEnv) { Path path = userEnv + "/manifest"; @@ -213,16 +199,15 @@ static DrvInfos queryInstalled(EvalState & state, const Path & userEnv) if (!pathExists(path)) return DrvInfos(); /* not an error, assume nothing installed */ + throw Error("not implemented"); +#if 0 Expr e = ATreadFromNamedFile(path.c_str()); if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path); - /* Compatibility: Bind(x, y) -> Bind(x, y, NoPos). */ - AddPos addPos; - e = bottomupRewrite(addPos, e); - DrvInfos elems; // !!! getDerivations(state, e, "", ATermMap(1), elems); return elems; +#endif } @@ -519,11 +504,11 @@ static void queryInstSources(EvalState & state, (import ./foo.nix)' = `(import ./foo.nix).bar'. */ case srcNixExprs: { - Expr e1 = loadSourceExpr(state, instSource.nixExprPath); + Expr * e1 = loadSourceExpr(state, instSource.nixExprPath); foreach (Strings::const_iterator, i, args) { - Expr e2 = parseExprFromString(state, *i, absPath(".")); - Expr call = makeCall(e2, e1); + Expr * e2 = parseExprFromString(state, *i, absPath(".")); + Expr * call = new ExprApp(e2, e1); Value v; state.eval(call, v); getDerivations(state, v, "", instSource.autoArgs, elems); } -- cgit 1.4.1 From 02c1dac90934e1b833c4d6bd9280bda27c146d80 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 16 Apr 2010 13:44:02 +0000 Subject: * In an nested `with' where the inner with is a variable (`with ...; with someVar; ...'), the contents of the variable would be clobbered. (The attributes in the outer `with' were added to the variable.) --- src/libexpr/eval.cc | 8 +++++++- src/libexpr/get-drvs.cc | 13 +++++++------ src/nix-env/nix-env.cc | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src/nix-env') diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 69e7bd8b3c88..ac475c893173 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -649,6 +649,11 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) Env * env3 = &env; for (unsigned int l = prevWith; l; --l, env3 = env3->up) ; + /* Because the first `with' may be a shallow copy of another + attribute set (through a tCopy node), we need to clone its + `attrs' before modifying them. */ + env2.values[0].attrs = new Bindings(*env2.values[0].attrs); + foreach (Bindings::iterator, i, *env3->values[0].attrs) { Bindings::iterator j = env2.values[0].attrs->find(i->first); if (j == env2.values[0].attrs->end()) @@ -1042,7 +1047,8 @@ void EvalState::printStats() printMsg(v, format(" expressions evaluated: %1%") % nrEvaluated); printMsg(v, format(" stack space used: %1% bytes") % (&x - deepestStack)); printMsg(v, format(" max eval() nesting depth: %1%") % maxRecursionDepth); - printMsg(v, format(" stack space per eval() level: %1% bytes") % ((&x - deepestStack) / (float) maxRecursionDepth)); + printMsg(v, format(" stack space per eval() level: %1% bytes") + % ((&x - deepestStack) / (float) maxRecursionDepth)); printMsg(v, format(" environments allocated: %1% (%2% bytes)") % nrEnvs % (nrEnvs * sizeof(Env))); printMsg(v, format(" values allocated in environments: %1% (%2% bytes)") diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 6964e3e3b71f..8af011d54987 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -177,14 +177,15 @@ static void getDerivations(EvalState & state, Value & vIn, there are names clashes between derivations, the derivation bound to the attribute with the "lower" name should take precedence). */ - StringSet attrs; + typedef std::map SortedSymbols; + SortedSymbols attrs; foreach (Bindings::iterator, i, *v.attrs) - attrs.insert(i->first); + attrs.insert(std::pair(i->first, i->first)); - foreach (StringSet::iterator, i, attrs) { - startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); - string pathPrefix2 = addToPath(pathPrefix, *i); - Value & v2((*v.attrs)[state.symbols.create(*i)]); + foreach (SortedSymbols::iterator, i, attrs) { + startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first); + string pathPrefix2 = addToPath(pathPrefix, i->first); + Value & v2((*v.attrs)[i->second]); if (combineChannels) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); else if (getDerivation(state, v2, pathPrefix2, drvs, done)) { diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index d44517ba678a..f9f828fe91fc 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1089,6 +1089,7 @@ static void opQuery(Globals & globals, foreach (vector::iterator, i, elems2) { try { + startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath); /* For table output. */ Strings columns; -- cgit 1.4.1 From 8bb0210fea89f2df70b3c10c431b1383e74093df Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 16 Apr 2010 14:07:52 +0000 Subject: * _combineChannels shouldn't be an integer. --- src/nix-env/nix-env.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix-env') diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index f9f828fe91fc..306b9507d126 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -153,7 +153,7 @@ static Expr * loadSourceExpr(EvalState & state, const Path & path) for a user to have a ~/.nix-defexpr directory that includes some system-wide directory). */ ExprAttrs * attrs = new ExprAttrs; - attrs->attrs[state.symbols.create("_combineChannels")] = new ExprInt(1); + attrs->attrs[state.symbols.create("_combineChannels")] = new ExprList(); getAllExprs(state, path, *attrs); return attrs; } -- cgit 1.4.1 From b7ff69eb7c3f97c33ec18c51ab87b7f3dd967052 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Apr 2010 10:47:56 +0000 Subject: * Refactoring: move the user environment stuff into its own module. --- src/nix-env/Makefile.am | 3 ++- src/nix-env/nix-env.cc | 20 +------------------- src/nix-env/user-env.cc | 28 ++++++++++++++++++++++++++++ src/nix-env/user-env.hh | 16 ++++++++++++++++ 4 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 src/nix-env/user-env.cc create mode 100644 src/nix-env/user-env.hh (limited to 'src/nix-env') diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am index 900524f76ed1..9b0d9951360d 100644 --- a/src/nix-env/Makefile.am +++ b/src/nix-env/Makefile.am @@ -1,6 +1,7 @@ bin_PROGRAMS = nix-env -nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh help.txt +nix_env_SOURCES = nix-env.cc profiles.cc user-env.cc profiles.hh help.txt + nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 306b9507d126..e298c4003b61 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -12,6 +12,7 @@ #include "common-opts.hh" #include "xml-writer.hh" #include "store-api.hh" +#include "user-env.hh" #include "util.hh" #include @@ -192,25 +193,6 @@ static Path getDefNixExprPath() } -static DrvInfos queryInstalled(EvalState & state, const Path & userEnv) -{ - Path path = userEnv + "/manifest"; - - if (!pathExists(path)) - return DrvInfos(); /* not an error, assume nothing installed */ - - throw Error("not implemented"); -#if 0 - Expr e = ATreadFromNamedFile(path.c_str()); - if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path); - - DrvInfos elems; - // !!! getDerivations(state, e, "", ATermMap(1), elems); - return elems; -#endif -} - - /* Ensure exclusive access to a profile. Any command that modifies the profile first acquires this lock. */ static void lockProfile(PathLocks & lock, const Path & profile) diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc new file mode 100644 index 000000000000..0e1fce650ca4 --- /dev/null +++ b/src/nix-env/user-env.cc @@ -0,0 +1,28 @@ +#include "util.hh" +#include "get-drvs.hh" + + +namespace nix { + + +DrvInfos queryInstalled(EvalState & state, const Path & userEnv) +{ + Path path = userEnv + "/manifest"; + + if (!pathExists(path)) + return DrvInfos(); /* not an error, assume nothing installed */ + + throw Error("not implemented"); +#if 0 + Expr e = ATreadFromNamedFile(path.c_str()); + if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path); + + DrvInfos elems; + // !!! getDerivations(state, e, "", ATermMap(1), elems); + return elems; +#endif +} + + +} + diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh new file mode 100644 index 000000000000..6675014f1a31 --- /dev/null +++ b/src/nix-env/user-env.hh @@ -0,0 +1,16 @@ +#ifndef __USER_ENV_H +#define __USER_ENV_H + +#include "get-drvs.hh" + +namespace nix { + +DrvInfos queryInstalled(EvalState & state, const Path & userEnv); + +} + +#endif /* !__USER_ENV_H */ + + + + -- cgit 1.4.1 From 55b5ddd3ca1ff4dfe4cfbfab92a4025d88ef6443 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Apr 2010 12:10:04 +0000 Subject: * Added parsing of manifests in ATerm format. --- src/libexpr/get-drvs.cc | 16 +++-- src/libexpr/get-drvs.hh | 5 ++ src/nix-env/user-env.cc | 157 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 165 insertions(+), 13 deletions(-) (limited to 'src/nix-env') diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 8af011d54987..e9f1063d955f 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -7,7 +7,7 @@ namespace nix { string DrvInfo::queryDrvPath(EvalState & state) const { - if (drvPath == "") { + if (drvPath == "" && attrs) { Bindings::iterator i = attrs->find(state.sDrvPath); PathSet context; (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; @@ -18,7 +18,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const string DrvInfo::queryOutPath(EvalState & state) const { - if (outPath == "") { + if (outPath == "" && attrs) { Bindings::iterator i = attrs->find(state.sOutPath); PathSet context; (string &) outPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; @@ -29,7 +29,9 @@ string DrvInfo::queryOutPath(EvalState & state) const MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const { - MetaInfo meta; + if (metaInfoRead) return meta; + + (bool &) metaInfoRead = true; Bindings::iterator a = attrs->find(state.sMeta); if (a == attrs->end()) return meta; /* fine, empty meta information */ @@ -50,7 +52,7 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const for (unsigned int j = 0; j < i->second.list.length; ++j) value.stringValues.push_back(state.forceStringNoCtx(*i->second.list.elems[j])); } else continue; - meta[i->first] = value; + ((MetaInfo &) meta)[i->first] = value; } return meta; @@ -66,9 +68,11 @@ MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const void DrvInfo::setMetaInfo(const MetaInfo & meta) { - throw Error("not implemented"); + metaInfoRead = true; + this->meta = meta; + #if 0 - ATermMap metaAttrs; + Value * metaAttrs = state.allocValues(1); foreach (MetaInfo::const_iterator, i, meta) { Expr e; switch (i->second.type) { diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index f7d1987ea3b7..6f3c381f8e34 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -29,6 +29,9 @@ struct DrvInfo private: string drvPath; string outPath; + + bool metaInfoRead; + MetaInfo meta; public: string name; @@ -38,6 +41,8 @@ public: /* !!! make this private */ Bindings * attrs; + DrvInfo() : metaInfoRead(false) { }; + string queryDrvPath(EvalState & state) const; string queryOutPath(EvalState & state) const; MetaInfo queryMetaInfo(EvalState & state) const; diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 0e1fce650ca4..8bb760094dab 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -5,22 +5,165 @@ namespace nix { +static void readLegacyManifest(const Path & path, DrvInfos & elems); + + DrvInfos queryInstalled(EvalState & state, const Path & userEnv) { + DrvInfos elems; + Path path = userEnv + "/manifest"; if (!pathExists(path)) return DrvInfos(); /* not an error, assume nothing installed */ - throw Error("not implemented"); -#if 0 - Expr e = ATreadFromNamedFile(path.c_str()); - if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path); + readLegacyManifest(path, elems); - DrvInfos elems; - // !!! getDerivations(state, e, "", ATermMap(1), elems); return elems; -#endif +} + + +/* Code for parsing manifests in the old textual ATerm format. */ + +static void expect(std::istream & str, const string & s) +{ + char s2[s.size()]; + str.read(s2, s.size()); + if (string(s2, s.size()) != s) + throw Error(format("expected string `%1%'") % s); +} + + +static string parseString(std::istream & str) +{ + string res; + expect(str, "\""); + int c; + while ((c = str.get()) != '"') + if (c == '\\') { + c = str.get(); + if (c == 'n') res += '\n'; + else if (c == 'r') res += '\r'; + else if (c == 't') res += '\t'; + else res += c; + } + else res += c; + return res; +} + + +static string parseStr(std::istream & str) +{ + expect(str, "Str("); + string s = parseString(str); + expect(str, ",[])"); + return s; +} + + +static string parseWord(std::istream & str) +{ + string res; + while (isalpha(str.peek())) + res += str.get(); + return res; +} + + +static bool endOfList(std::istream & str) +{ + if (str.peek() == ',') { + str.get(); + return false; + } + if (str.peek() == ']') { + str.get(); + return true; + } + return false; +} + + +static MetaInfo parseMeta(std::istream & str) +{ + MetaInfo meta; + + expect(str, "Attrs(["); + while (!endOfList(str)) { + expect(str, "Bind("); + + MetaValue value; + + string name = parseString(str); + expect(str, ","); + + string type = parseWord(str); + + if (type == "Str") { + expect(str, "("); + value.type = MetaValue::tpString; + value.stringValue = parseString(str); + expect(str, ",[])"); + } + + else if (type == "List") { + expect(str, "(["); + value.type = MetaValue::tpStrings; + while (!endOfList(str)) + value.stringValues.push_back(parseStr(str)); + expect(str, ")"); + } + + else throw Error(format("unexpected token `%1%'") % type); + + expect(str, ",NoPos)"); + meta[name] = value; + } + + expect(str, ")"); + + return meta; +} + + +static void readLegacyManifest(const Path & path, DrvInfos & elems) +{ + string manifest = readFile(path); + std::istringstream str(manifest); + expect(str, "List(["); + + unsigned int n = 0; + + while (!endOfList(str)) { + DrvInfo elem; + expect(str, "Attrs(["); + + while (!endOfList(str)) { + expect(str, "Bind("); + string name = parseString(str); + expect(str, ","); + + if (name == "meta") elem.setMetaInfo(parseMeta(str)); + else { + string value = parseStr(str); + if (name == "name") elem.name = value; + else if (name == "outPath") elem.setOutPath(value); + else if (name == "drvPath") elem.setDrvPath(value); + else if (name == "system") elem.system = value; + } + + expect(str, ",NoPos)"); + } + + expect(str, ")"); + + if (elem.name != "") { + elem.attrPath = int2String(n++); + elems.push_back(elem); + } + } + + expect(str, ")"); } -- cgit 1.4.1 From efc7a579e880ec15ebe9afc0d8766c85c7d53ec2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Apr 2010 13:46:58 +0000 Subject: * Don't use the ATerm library for parsing/printing .drv files. --- src/libexpr/primops.cc | 2 +- src/libmain/shared.cc | 10 -- src/libstore/Makefile.am | 7 -- src/libstore/derivations-ast.def | 10 -- src/libstore/derivations.cc | 223 ++++++++++++++++++++------------------- src/libstore/derivations.hh | 11 +- src/libstore/local-store.cc | 2 - src/libstore/misc.cc | 6 +- src/libutil/Makefile.am | 6 +- src/libutil/aterm.cc | 55 ---------- src/libutil/aterm.hh | 55 ---------- src/libutil/util.cc | 41 +++++++ src/libutil/util.hh | 35 +++--- src/nix-env/user-env.cc | 41 ------- 14 files changed, 174 insertions(+), 330 deletions(-) delete mode 100644 src/libstore/derivations-ast.def delete mode 100644 src/libutil/aterm.cc delete mode 100644 src/libutil/aterm.hh (limited to 'src/nix-env') diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c5579679caf3..b28201593335 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -262,7 +262,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) } drv.inputDrvs = inputs2; - return hashTerm(unparseDerivation(drv)); + return hashString(htSHA256, unparseDerivation(drv)); } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index d9cf9a86262a..825e8762105e 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -87,9 +87,6 @@ static void setLogType(string lt) } -void initDerivationsHelpers(); - - static void closeStore() { try { @@ -176,9 +173,6 @@ static void initAndRun(int argc, char * * argv) string lt = getEnv("NIX_LOG_TYPE"); if (lt != "") setLogType(lt); - /* ATerm stuff. !!! find a better place to put this */ - initDerivationsHelpers(); - /* Put the arguments in a vector. */ Strings args, remaining; while (argc--) args.push_back(*argv++); @@ -333,10 +327,6 @@ int main(int argc, char * * argv) if (argc == 0) abort(); setuidInit(); - /* ATerm setup. */ - ATerm bottomOfStack; - ATinit(argc, argv, &bottomOfStack); - /* Turn on buffering for cerr. */ #if HAVE_PUBSETBUF std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 863871519390..47681242f61b 100644 --- a/src/libstore/Makefile.am +++ b/src/libstore/Makefile.am @@ -12,12 +12,5 @@ pkginclude_HEADERS = \ libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ -BUILT_SOURCES = derivations-ast.cc derivations-ast.hh - -EXTRA_DIST = derivations-ast.def derivations-ast.cc - AM_CXXFLAGS = -Wall \ -I$(srcdir)/.. ${aterm_include} -I$(srcdir)/../libutil - -derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def - $(perl) $(srcdir)/../aterm-helper.pl derivations-ast.hh derivations-ast.cc < $(srcdir)/derivations-ast.def diff --git a/src/libstore/derivations-ast.def b/src/libstore/derivations-ast.def deleted file mode 100644 index 574529ae76c5..000000000000 --- a/src/libstore/derivations-ast.def +++ /dev/null @@ -1,10 +0,0 @@ -init initDerivationsHelpers - -Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm | - -| string string | ATerm | EnvBinding | -| string ATermList | ATerm | DerivationInput | -| string string string string | ATerm | DerivationOutput | - -Closure | ATermList ATermList | ATerm | OldClosure | -| string ATermList | ATerm | OldClosureElem | diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index bc2ec1f907e7..3d0f1eb4247b 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1,22 +1,12 @@ #include "derivations.hh" #include "store-api.hh" -#include "aterm.hh" #include "globals.hh" #include "util.hh" -#include "derivations-ast.hh" -#include "derivations-ast.cc" - namespace nix { -Hash hashTerm(ATerm t) -{ - return hashString(htSHA256, atPrint(t)); -} - - Path writeDerivation(const Derivation & drv, const string & name) { PathSet references; @@ -27,137 +17,150 @@ Path writeDerivation(const Derivation & drv, const string & name) (that can be missing (of course) and should not necessarily be held during a garbage collection). */ string suffix = name + drvExtension; - string contents = atPrint(unparseDerivation(drv)); + string contents = unparseDerivation(drv); return readOnlyMode ? computeStorePathForText(suffix, contents, references) : store->addTextToStore(suffix, contents, references); } -static void checkPath(const string & s) +static Path parsePath(std::istream & str) { + string s = parseString(str); if (s.size() == 0 || s[0] != '/') throw Error(format("bad path `%1%' in derivation") % s); + return s; } -static void parseStrings(ATermList paths, StringSet & out, bool arePaths) +static StringSet parseStrings(std::istream & str, bool arePaths) { - for (ATermIterator i(paths); i; ++i) { - if (ATgetType(*i) != AT_APPL) - throw badTerm("not a path", *i); - string s = aterm2String(*i); - if (arePaths) checkPath(s); - out.insert(s); - } + StringSet res; + while (!endOfList(str)) + res.insert(arePaths ? parsePath(str) : parseString(str)); + return res; } + - -/* Shut up warnings. */ -void throwBadDrv(ATerm t) __attribute__ ((noreturn)); - -void throwBadDrv(ATerm t) -{ - throw badTerm("not a valid derivation", t); -} - - -Derivation parseDerivation(ATerm t) +Derivation parseDerivation(const string & s) { Derivation drv; - ATermList outs, inDrvs, inSrcs, args, bnds; - ATerm builder, platform; + std::istringstream str(s); + expect(str, "Derive(["); - if (!matchDerive(t, outs, inDrvs, inSrcs, platform, builder, args, bnds)) - throwBadDrv(t); - - for (ATermIterator i(outs); i; ++i) { - ATerm id, path, hashAlgo, hash; - if (!matchDerivationOutput(*i, id, path, hashAlgo, hash)) - throwBadDrv(t); + /* Parse the list of outputs. */ + while (!endOfList(str)) { DerivationOutput out; - out.path = aterm2String(path); - checkPath(out.path); - out.hashAlgo = aterm2String(hashAlgo); - out.hash = aterm2String(hash); - drv.outputs[aterm2String(id)] = out; + expect(str, "("); string id = parseString(str); + expect(str, ","); out.path = parsePath(str); + expect(str, ","); out.hashAlgo = parseString(str); + expect(str, ","); out.hash = parseString(str); + expect(str, ")"); + drv.outputs[id] = out; } - for (ATermIterator i(inDrvs); i; ++i) { - ATerm drvPath; - ATermList ids; - if (!matchDerivationInput(*i, drvPath, ids)) - throwBadDrv(t); - Path drvPath2 = aterm2String(drvPath); - checkPath(drvPath2); - StringSet ids2; - parseStrings(ids, ids2, false); - drv.inputDrvs[drvPath2] = ids2; + /* Parse the list of input derivations. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); + Path drvPath = parsePath(str); + expect(str, ",["); + drv.inputDrvs[drvPath] = parseStrings(str, false); + expect(str, ")"); } - - parseStrings(inSrcs, drv.inputSrcs, true); - drv.builder = aterm2String(builder); - drv.platform = aterm2String(platform); - - for (ATermIterator i(args); i; ++i) { - if (ATgetType(*i) != AT_APPL) - throw badTerm("string expected", *i); - drv.args.push_back(aterm2String(*i)); + expect(str, ",["); drv.inputSrcs = parseStrings(str, true); + expect(str, ","); drv.platform = parseString(str); + expect(str, ","); drv.builder = parseString(str); + + /* Parse the builder arguments. */ + expect(str, ",["); + while (!endOfList(str)) + drv.args.push_back(parseString(str)); + + /* Parse the environment variables. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); string name = parseString(str); + expect(str, ","); string value = parseString(str); + expect(str, ")"); + drv.env[name] = value; } + + expect(str, ")"); + return drv; +} - for (ATermIterator i(bnds); i; ++i) { - ATerm s1, s2; - if (!matchEnvBinding(*i, s1, s2)) - throw badTerm("tuple of strings expected", *i); - drv.env[aterm2String(s1)] = aterm2String(s2); - } - return drv; +void printString(std::ostream & str, const string & s) +{ + str << "\""; + for (const char * i = s.c_str(); *i; i++) + if (*i == '\"' || *i == '\\') str << "\\" << *i; + else if (*i == '\n') str << "\\n"; + else if (*i == '\r') str << "\\r"; + else if (*i == '\t') str << "\\t"; + else str << *i; + str << "\""; } -ATerm unparseDerivation(const Derivation & drv) +template +void printStrings(std::ostream & str, ForwardIterator i, ForwardIterator j) { - ATermList outputs = ATempty; - for (DerivationOutputs::const_reverse_iterator i = drv.outputs.rbegin(); - i != drv.outputs.rend(); ++i) - outputs = ATinsert(outputs, - makeDerivationOutput( - toATerm(i->first), - toATerm(i->second.path), - toATerm(i->second.hashAlgo), - toATerm(i->second.hash))); - - ATermList inDrvs = ATempty; - for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin(); - i != drv.inputDrvs.rend(); ++i) - inDrvs = ATinsert(inDrvs, - makeDerivationInput( - toATerm(i->first), - toATermList(i->second))); + str << "["; + bool first = true; + for ( ; i != j; ++i) { + if (first) first = false; else str << ","; + printString(str, *i); + } + str << "]"; +} + + +string unparseDerivation(const Derivation & drv) +{ + std::ostringstream str; + str << "Derive(["; + + bool first = true; + foreach (DerivationOutputs::const_iterator, i, drv.outputs) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printString(str, i->second.path); + str << ","; printString(str, i->second.hashAlgo); + str << ","; printString(str, i->second.hash); + str << ")"; + } + + str << "],["; + first = true; + foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printStrings(str, i->second.begin(), i->second.end()); + str << ")"; + } + + str << "],"; + printStrings(str, drv.inputSrcs.begin(), drv.inputSrcs.end()); + + str << ","; printString(str, drv.platform); + str << ","; printString(str, drv.builder); + str << ","; printStrings(str, drv.args.begin(), drv.args.end()); + + str << ",["; + first = true; + foreach (StringPairs::const_iterator, i, drv.env) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printString(str, i->second); + str << ")"; + } + + str << "])"; - ATermList args = ATempty; - for (Strings::const_reverse_iterator i = drv.args.rbegin(); - i != drv.args.rend(); ++i) - args = ATinsert(args, toATerm(*i)); - - ATermList env = ATempty; - for (StringPairs::const_reverse_iterator i = drv.env.rbegin(); - i != drv.env.rend(); ++i) - env = ATinsert(env, - makeEnvBinding( - toATerm(i->first), - toATerm(i->second))); - - return makeDerive( - outputs, - inDrvs, - toATermList(drv.inputSrcs), - toATerm(drv.platform), - toATerm(drv.builder), - args, - env); + return str.str(); } diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 042f4738d469..95e49d42c9ea 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -1,8 +1,6 @@ #ifndef __DERIVATIONS_H #define __DERIVATIONS_H -#include - #include "hash.hh" #include @@ -53,17 +51,14 @@ struct Derivation }; -/* Hash an aterm. */ -Hash hashTerm(ATerm t); - /* Write a derivation to the Nix store, and return its path. */ Path writeDerivation(const Derivation & drv, const string & name); /* Parse a derivation. */ -Derivation parseDerivation(ATerm t); +Derivation parseDerivation(const string & s); -/* Parse a derivation. */ -ATerm unparseDerivation(const Derivation & drv); +/* Print a derivation. */ +string unparseDerivation(const Derivation & drv); /* Check whether a file name ends with the extensions for derivations. */ diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index a83ba55e2b3e..2c0aa3579293 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -3,8 +3,6 @@ #include "globals.hh" #include "archive.hh" #include "pathlocks.hh" -#include "aterm.hh" -#include "derivations-ast.hh" #include "worker-protocol.hh" #include diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 2d7d13a0e7b4..f2cc20626915 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -2,8 +2,6 @@ #include "store-api.hh" #include "local-store.hh" -#include - namespace nix { @@ -12,9 +10,7 @@ Derivation derivationFromPath(const Path & drvPath) { assertStorePath(drvPath); store->ensurePath(drvPath); - ATerm t = ATreadFromNamedFile(drvPath.c_str()); - if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath); - return parseDerivation(t); + return parseDerivation(readFile(drvPath)); } diff --git a/src/libutil/Makefile.am b/src/libutil/Makefile.am index 55135e3736c0..aa862208c6f9 100644 --- a/src/libutil/Makefile.am +++ b/src/libutil/Makefile.am @@ -1,16 +1,16 @@ pkglib_LTLIBRARIES = libutil.la libutil_la_SOURCES = util.cc hash.cc serialise.cc \ - archive.cc aterm.cc xml-writer.cc + archive.cc xml-writer.cc libutil_la_LIBADD = ../boost/format/libformat.la pkginclude_HEADERS = util.hh hash.hh serialise.hh \ - archive.hh aterm.hh xml-writer.hh types.hh + archive.hh xml-writer.hh types.hh if !HAVE_OPENSSL libutil_la_SOURCES += \ md5.c md5.h sha1.c sha1.h sha256.c sha256.h md32_common.h endif -AM_CXXFLAGS = -Wall -I$(srcdir)/.. ${aterm_include} +AM_CXXFLAGS = -Wall -I$(srcdir)/.. diff --git a/src/libutil/aterm.cc b/src/libutil/aterm.cc deleted file mode 100644 index 25d70478573d..000000000000 --- a/src/libutil/aterm.cc +++ /dev/null @@ -1,55 +0,0 @@ -#include "aterm.hh" - -#include - -using std::string; - - -string nix::atPrint(ATerm t) -{ - if (!t) throw Error("attempt to print null aterm"); - char * s = ATwriteToString(t); - if (!s) throw Error("cannot print term"); - return s; -} - - -std::ostream & operator << (std::ostream & stream, ATerm e) -{ - return stream << nix::atPrint(e); -} - - -nix::Error nix::badTerm(const format & f, ATerm t) -{ - char * s = ATwriteToString(t); - if (!s) throw Error("cannot print term"); - if (strlen(s) > 1000) { - int len; - s = ATwriteToSharedString(t, &len); - if (!s) throw Error("cannot print term"); - } - return Error(format("%1%, in `%2%'") % f.str() % (string) s); -} - - -ATerm nix::toATerm(const char * s) -{ - return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s, 0, ATtrue)); -} - - -ATerm nix::toATerm(const string & s) -{ - return toATerm(s.c_str()); -} - - -ATermList nix::toATermList(const StringSet & ss) -{ - ATermList l = ATempty; - for (StringSet::const_reverse_iterator i = ss.rbegin(); - i != ss.rend(); ++i) - l = ATinsert(l, toATerm(*i)); - return l; -} diff --git a/src/libutil/aterm.hh b/src/libutil/aterm.hh deleted file mode 100644 index b1cbc3b6d895..000000000000 --- a/src/libutil/aterm.hh +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __ATERM_H -#define __ATERM_H - -#include - -#include "types.hh" - - -namespace nix { - - -/* Print an ATerm. */ -string atPrint(ATerm t); - -class ATermIterator -{ - ATermList t; - -public: - ATermIterator(ATermList _t) : t(_t) { } - ATermIterator & operator ++ () - { - t = ATgetNext(t); - return *this; - } - ATerm operator * () - { - return ATgetFirst(t); - } - operator bool () - { - return t != ATempty; - } -}; - - -/* Throw an exception with an error message containing the given - aterm. */ -Error badTerm(const format & f, ATerm t); - - -/* Convert strings to ATerms. */ -ATerm toATerm(const char * s); -ATerm toATerm(const string & s); - -ATermList toATermList(const StringSet & ss); - -} - - -/* Write an ATerm to an output stream. */ -std::ostream & operator << (std::ostream & stream, ATerm e); - - -#endif /* !__ATERM_H */ diff --git a/src/libutil/util.cc b/src/libutil/util.cc index d28d0e823c05..98912e7a002c 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1006,6 +1006,47 @@ bool hasSuffix(const string & s, const string & suffix) } +void expect(std::istream & str, const string & s) +{ + char s2[s.size()]; + str.read(s2, s.size()); + if (string(s2, s.size()) != s) + throw Error(format("expected string `%1%'") % s); +} + + +string parseString(std::istream & str) +{ + string res; + expect(str, "\""); + int c; + while ((c = str.get()) != '"') + if (c == '\\') { + c = str.get(); + if (c == 'n') res += '\n'; + else if (c == 'r') res += '\r'; + else if (c == 't') res += '\t'; + else res += c; + } + else res += c; + return res; +} + + +bool endOfList(std::istream & str) +{ + if (str.peek() == ',') { + str.get(); + return false; + } + if (str.peek() == ']') { + str.get(); + return true; + } + return false; +} + + void ignoreException() { try { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 4de33d3eff26..ff710077ceaa 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -302,32 +302,21 @@ string int2String(int n); bool hasSuffix(const string & s, const string & suffix); -/* Exception handling in destructors: print an error message, then - ignore the exception. */ -void ignoreException(); +/* Read string `s' from stream `str'. */ +void expect(std::istream & str, const string & s); -/* STL functions such as sort() pass a binary function object around - by value, so it gets cloned a lot. This is bad if the function - object has state or is simply large. This adapter wraps the - function object to simulate passing by reference. */ -template -struct binary_function_ref_adapter -{ - F * p; +/* Read a C-style string from stream `str'. */ +string parseString(std::istream & str); - binary_function_ref_adapter(F * _p) - { - p = _p; - } - - typename F::result_type operator () ( - const typename F::first_argument_type & x, - const typename F::second_argument_type & y) - { - return (*p)(x, y); - } -}; + +/* Utility function used to parse legacy ATerms. */ +bool endOfList(std::istream & str); + + +/* Exception handling in destructors: print an error message, then + ignore the exception. */ +void ignoreException(); } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 8bb760094dab..f040f8c11570 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -25,33 +25,6 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv) /* Code for parsing manifests in the old textual ATerm format. */ -static void expect(std::istream & str, const string & s) -{ - char s2[s.size()]; - str.read(s2, s.size()); - if (string(s2, s.size()) != s) - throw Error(format("expected string `%1%'") % s); -} - - -static string parseString(std::istream & str) -{ - string res; - expect(str, "\""); - int c; - while ((c = str.get()) != '"') - if (c == '\\') { - c = str.get(); - if (c == 'n') res += '\n'; - else if (c == 'r') res += '\r'; - else if (c == 't') res += '\t'; - else res += c; - } - else res += c; - return res; -} - - static string parseStr(std::istream & str) { expect(str, "Str("); @@ -70,20 +43,6 @@ static string parseWord(std::istream & str) } -static bool endOfList(std::istream & str) -{ - if (str.peek() == ',') { - str.get(); - return false; - } - if (str.peek() == ']') { - str.get(); - return true; - } - return false; -} - - static MetaInfo parseMeta(std::istream & str) { MetaInfo meta; -- cgit 1.4.1 From f3b8833a48472c3545ea8673d687ea9cadcedd61 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Apr 2010 14:51:58 +0000 Subject: * Drop the dependency on the ATerm library. --- configure.ac | 17 ---- doc/manual/installation.xml | 14 ++- externals/Makefile.am | 43 +-------- externals/max-long.patch | 77 ---------------- externals/sizeof.patch | 56 ------------ release.nix | 11 +-- src/Makefile.am | 2 - src/aterm-helper.pl | 179 -------------------------------------- src/libexpr/Makefile.am | 6 +- src/libmain/Makefile.am | 2 +- src/libmain/shared.cc | 2 - src/libstore/Makefile.am | 2 +- src/nix-env/Makefile.am | 4 +- src/nix-hash/Makefile.am | 2 +- src/nix-instantiate/Makefile.am | 3 +- src/nix-setuid-helper/Makefile.am | 4 +- src/nix-store/Makefile.am | 4 +- src/nix-worker/Makefile.am | 4 +- substitute.mk | 1 - tests/common.sh.in | 5 -- tests/lang.sh | 7 +- 21 files changed, 32 insertions(+), 413 deletions(-) delete mode 100644 externals/max-long.patch delete mode 100644 externals/sizeof.patch delete mode 100755 src/aterm-helper.pl (limited to 'src/nix-env') diff --git a/configure.ac b/configure.ac index 4c92bcb5c3ad..8d3f308d7142 100644 --- a/configure.ac +++ b/configure.ac @@ -203,23 +203,6 @@ AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH], storedir=$withval, storedir='/nix/store') AC_SUBST(storedir) -AC_ARG_WITH(aterm, AC_HELP_STRING([--with-aterm=PATH], - [prefix of CWI ATerm library]), - aterm=$withval, aterm=) -AM_CONDITIONAL(HAVE_ATERM, test -n "$aterm") -if test -z "$aterm"; then - aterm_lib='-L${top_builddir}/externals/inst-aterm/lib -lATerm' - aterm_include='-I${top_builddir}/externals/inst-aterm/include' - aterm_bin='${top_builddir}/externals/inst-aterm/bin' -else - aterm_lib="-L$aterm/lib -lATerm" - aterm_include="-I$aterm/include" - aterm_bin="$aterm/bin" -fi -AC_SUBST(aterm_lib) -AC_SUBST(aterm_include) -AC_SUBST(aterm_bin) - AC_ARG_WITH(openssl, AC_HELP_STRING([--with-openssl=PATH], [prefix of the OpenSSL library]), openssl=$withval, openssl=) diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml index a1b99ca2e812..bc5e21f0d39a 100644 --- a/doc/manual/installation.xml +++ b/doc/manual/installation.xml @@ -96,15 +96,13 @@ ubiquitous 2.5.4a won't. Note that these are only required if you modify the parser or when you are building from the Subversion repository. -Nix uses CWI's ATerm library and the bzip2 compressor (including -the bzip2 library). These are included in the Nix source -distribution. If you build from the Subversion repository, you must -download them yourself and place them in the -externals/ directory. See +Nix uses the bzip2 compressor (including the bzip2 library). It +is included in the Nix source distribution. If you build from the +Subversion repository, you must download it yourself and place it in +the externals/ directory. See externals/Makefile.am for the precise URLs of -these packages. Alternatively, if you already have them installed, -you can use configure's - and +this packages. Alternatively, if you already have it installed, you +can use configure's options to point to their respective locations. diff --git a/externals/Makefile.am b/externals/Makefile.am index c9bc05d71ee5..838f5d704e12 100644 --- a/externals/Makefile.am +++ b/externals/Makefile.am @@ -1,38 +1,3 @@ -# CWI ATerm - -ATERM = aterm-2.5 - -$(ATERM).tar.gz: - @echo "Nix requires the CWI ATerm library to build." - @echo "Please download version 2.5 from" - @echo " http://nixos.org/tarballs/aterm-2.5.tar.gz" - @echo "and place it in the externals/ directory." - false - -$(ATERM): $(ATERM).tar.gz - gzip -d < $(srcdir)/$(ATERM).tar.gz | tar xvf - - patch -d $(ATERM) -p1 < ./max-long.patch - patch -d $(ATERM) -p1 < ./sizeof.patch - -have-aterm: - $(MAKE) $(ATERM) - touch have-aterm - -if HAVE_ATERM -build-aterm: -else -build-aterm: have-aterm - (pfx=`pwd` && \ - cd $(ATERM) && \ - CC="$(CC)" ./configure --prefix=$$pfx/inst-aterm \ - --disable-shared --enable-static && \ - $(MAKE) && \ - $(MAKE) check && \ - $(MAKE) install) - touch build-aterm -endif - - # bzip2 BZIP2 = bzip2-1.0.5 @@ -67,10 +32,10 @@ install: endif -all: build-aterm build-bzip2 +all: build-bzip2 -EXTRA_DIST = $(ATERM).tar.gz $(BZIP2).tar.gz max-long.patch sizeof.patch +EXTRA_DIST = $(BZIP2).tar.gz max-long.patch sizeof.patch ext-clean: - $(RM) -f have-aterm build-aterm have-bzip2 build-bzip2 - $(RM) -rf $(ATERM) $(BZIP2) + $(RM) -f have-bzip2 build-bzip2 + $(RM) -rf $(BZIP2) diff --git a/externals/max-long.patch b/externals/max-long.patch deleted file mode 100644 index a2f260b970b3..000000000000 --- a/externals/max-long.patch +++ /dev/null @@ -1,77 +0,0 @@ -diff -rc aterm-2.8-orig/aterm/hash.c aterm-2.8/aterm/hash.c -*** aterm-2.8-orig/aterm/hash.c 2008-11-10 13:54:22.000000000 +0100 ---- aterm-2.8/aterm/hash.c 2009-01-27 18:14:14.000000000 +0100 -*************** -*** 93,146 **** - } - - /*}}} */ -- /*{{{ static long calc_long_max() */ -- static long calc_long_max() -- { -- long try_long_max; -- long long_max; -- long delta; -- -- try_long_max = 1; -- do { -- long_max = try_long_max; -- try_long_max = long_max * 2; -- } while (try_long_max > 0); -- -- delta = long_max; -- while (delta > 1) { -- while (long_max + delta < 0) { -- delta /= 2; -- } -- long_max += delta; -- } -- -- return long_max; -- -- } -- /*}}} */ - /*{{{ static long calculateNewSize(sizeMinus1, nrdel, nrentries) */ - - static long calculateNewSize - (long sizeMinus1, long nr_deletions, long nr_entries) - { -- -- /* Hack: LONG_MAX (limits.h) is often unreliable, we need to find -- * out the maximum possible value of a signed long dynamically. -- */ -- static long st_long_max = 0; -- -- /* the resulting length has the form 2^k-1 */ -- - if (nr_deletions >= nr_entries/2) { - return sizeMinus1; - } - -! if (st_long_max == 0) { -! st_long_max = calc_long_max(); -! } -! -! if (sizeMinus1 > st_long_max / 2) { -! return st_long_max-1; - } - - return (2*sizeMinus1)+1; ---- 93,109 ---- - } - - /*}}} */ - /*{{{ static long calculateNewSize(sizeMinus1, nrdel, nrentries) */ - - static long calculateNewSize - (long sizeMinus1, long nr_deletions, long nr_entries) - { - if (nr_deletions >= nr_entries/2) { - return sizeMinus1; - } - -! if (sizeMinus1 > LONG_MAX / 2) { -! return LONG_MAX-1; - } - - return (2*sizeMinus1)+1; diff --git a/externals/sizeof.patch b/externals/sizeof.patch deleted file mode 100644 index 2649cc564913..000000000000 --- a/externals/sizeof.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff -rc -x '*~' aterm-2.5-orig/aterm/aterm.c aterm-2.5/aterm/aterm.c -*** aterm-2.5-orig/aterm/aterm.c 2007-02-27 23:41:31.000000000 +0100 ---- aterm-2.5/aterm/aterm.c 2010-02-23 15:10:38.000000000 +0100 -*************** -*** 150,155 **** ---- 150,157 ---- - if (initialized) - return; - -+ assert(sizeof(long) == sizeof(void *)); -+ - /*{{{ Handle arguments */ - - for (lcv=1; lcv < argc; lcv++) { -diff -rc -x '*~' aterm-2.5-orig/aterm/encoding.h aterm-2.5/aterm/encoding.h -*** aterm-2.5-orig/aterm/encoding.h 2007-02-27 23:41:31.000000000 +0100 ---- aterm-2.5/aterm/encoding.h 2010-02-23 15:36:05.000000000 +0100 -*************** -*** 10,24 **** - { - #endif/* __cplusplus */ - -! #if SIZEOF_LONG > 4 -! #define AT_64BIT - #endif - -! #if SIZEOF_LONG != SIZEOF_VOID_P -! #error Size of long is not the same as the size of a pointer - #endif - -! #if SIZEOF_INT > 4 - #error Size of int is not 32 bits - #endif - ---- 10,30 ---- - { - #endif/* __cplusplus */ - -! #include -! -! #ifndef SIZEOF_LONG -! #if ULONG_MAX > 4294967295 -! #define SIZEOF_LONG 8 -! #else -! #define SIZEOF_LONG 4 -! #endif - #endif - -! #if SIZEOF_LONG > 4 -! #define AT_64BIT - #endif - -! #if UINT_MAX > 4294967295 - #error Size of int is not 32 bits - #endif - diff --git a/release.nix b/release.nix index e9afe9c9e6cf..3343f8658091 100644 --- a/release.nix +++ b/release.nix @@ -29,11 +29,8 @@ let --with-xml-flags=--nonet ''; - # Include the ATerm and Bzip2 tarballs in the distribution. + # Include the Bzip2 tarball in the distribution. preConfigure = '' - stripHash ${aterm.src} - cp -pv ${aterm.src} externals/$strippedName - stripHash ${bzip2.src} cp -pv ${bzip2.src} externals/$strippedName @@ -77,7 +74,7 @@ let configureFlags = '' --disable-init-state - --with-aterm=${aterm} --with-bzip2=${bzip2} + --with-bzip2=${bzip2} ''; }; @@ -98,7 +95,7 @@ let configureFlags = '' --disable-init-state - --with-aterm=${aterm} --with-bzip2=${bzip2} + --with-bzip2=${bzip2} --enable-static-nix ''; }; @@ -123,7 +120,7 @@ let configureFlags = '' --disable-init-state --disable-shared - --with-aterm=${aterm} --with-bzip2=${bzip2} + --with-bzip2=${bzip2} ''; lcovFilter = ["*/boost/*" "*-tab.*"]; diff --git a/src/Makefile.am b/src/Makefile.am index 971f7d9d1c75..ec36327730a1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,3 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \ libexpr nix-instantiate nix-env nix-worker nix-setuid-helper \ nix-log2xml bsdiff-4.3 - -EXTRA_DIST = aterm-helper.pl diff --git a/src/aterm-helper.pl b/src/aterm-helper.pl deleted file mode 100755 index f1eb77ee80c2..000000000000 --- a/src/aterm-helper.pl +++ /dev/null @@ -1,179 +0,0 @@ -#! /usr/bin/perl -w - -# This program generates C/C++ code for efficiently manipulating -# ATerms. It generates functions to build and match ATerms according -# to a set of constructor definitions defined in a file read from -# standard input. A constructor is defined by a line with the -# following format: -# -# SYM | ARGS | TYPE | FUN? -# -# where SYM is the name of the constructor, ARGS is a -# whitespace-separated list of argument types, TYPE is the type of the -# resulting ATerm (which should be `ATerm' or a type synonym for -# `ATerm'), and the optional FUN is used to construct the names of the -# build and match functions (it defaults to SYM; overriding it is -# useful if there are overloaded constructors, e.g., with different -# arities). Note that SYM may be empty. -# -# A line of the form -# -# VAR = EXPR -# -# causes a ATerm variable to be generated that is initialised to the -# value EXPR. -# -# Finally, a line of the form -# -# init NAME -# -# causes the initialisation function to be called `NAME'. This -# function must be called before any of the build/match functions or -# the generated variables are used. - -die if scalar @ARGV != 2; - -my $syms = ""; -my $init = ""; -my $initFun = "init"; - -open HEADER, ">$ARGV[0]"; -open IMPL, ">$ARGV[1]"; - -print HEADER "#include \n"; -print HEADER "#ifdef __cplusplus\n"; -print HEADER "namespace nix {\n"; -print HEADER "#endif\n\n\n"; -print IMPL "namespace nix {\n"; - -while () { - s/\#.*//; - next if (/^\s*$/); - - if (/^\s*(\w*)\s*\|([^\|]*)\|\s*(\w+)\s*\|\s*(\w+)?/) { - my $const = $1; - my @types = split ' ', $2; - my $result = $3; - my $funname = $4; - $funname = $const unless defined $funname; - - my $formals = ""; - my $formals2 = ""; - my $args = ""; - my $unpack = ""; - my $n = 1; - foreach my $type (@types) { - my $realType = $type; - $args .= ", "; - if ($type eq "string") { -# $args .= "(ATerm) ATmakeAppl0(ATmakeAFun((char *) e$n, 0, ATtrue))"; -# $type = "const char *"; - $type = "ATerm"; - $args .= "e$n"; - # !!! in the matcher, we should check that the - # argument is a string (i.e., a nullary application). - } elsif ($type eq "int") { - $args .= "(ATerm) ATmakeInt(e$n)"; - } elsif ($type eq "ATermList" || $type eq "ATermBlob") { - $args .= "(ATerm) e$n"; - } else { - $args .= "e$n"; - } - $formals .= ", " if $formals ne ""; - $formals .= "$type e$n"; - $formals2 .= ", "; - $formals2 .= "$type & e$n"; - my $m = $n - 1; - # !!! more checks here - if ($type eq "int") { - $unpack .= " e$n = ATgetInt((ATermInt) ATgetArgument(e, $m));\n"; - } elsif ($type eq "ATermList") { - $unpack .= " e$n = (ATermList) ATgetArgument(e, $m);\n"; - } elsif ($type eq "ATermBlob") { - $unpack .= " e$n = (ATermBlob) ATgetArgument(e, $m);\n"; - } elsif ($realType eq "string") { - $unpack .= " e$n = ATgetArgument(e, $m);\n"; - $unpack .= " if (ATgetType(e$n) != AT_APPL) return false;\n"; - } else { - $unpack .= " e$n = ATgetArgument(e, $m);\n"; - } - $n++; - } - - my $arity = scalar @types; - - print HEADER "extern AFun sym$funname;\n\n"; - - print IMPL "AFun sym$funname = 0;\n"; - - if ($arity == 0) { - print HEADER "extern ATerm const$funname;\n\n"; - print IMPL "ATerm const$funname = 0;\n"; - } - - print HEADER "static inline $result make$funname($formals) __attribute__ ((pure, nothrow));\n"; - print HEADER "static inline $result make$funname($formals) {\n"; - if ($arity == 0) { - print HEADER " return const$funname;\n"; - } - elsif ($arity <= 6) { - print HEADER " return (ATerm) ATmakeAppl$arity(sym$funname$args);\n"; - } else { - $args =~ s/^,//; - print HEADER " ATerm array[$arity] = {$args};\n"; - print HEADER " return (ATerm) ATmakeApplArray(sym$funname, array);\n"; - } - print HEADER "}\n\n"; - - print HEADER "#ifdef __cplusplus\n"; - print HEADER "static inline bool match$funname(ATerm e$formals2) {\n"; - print HEADER " if (ATgetType(e) != AT_APPL || (AFun) ATgetAFun(e) != sym$funname) return false;\n"; - print HEADER "$unpack"; - print HEADER " return true;\n"; - print HEADER "}\n"; - print HEADER "#endif\n\n\n"; - - $init .= " sym$funname = ATmakeAFun(\"$const\", $arity, ATfalse);\n"; - $init .= " ATprotectAFun(sym$funname);\n"; - if ($arity == 0) { - $init .= " const$funname = (ATerm) ATmakeAppl0(sym$funname);\n"; - $init .= " ATprotect(&const$funname);\n"; - } - } - - elsif (/^\s*(\w+)\s*=\s*(.*)$/) { - my $name = $1; - my $value = $2; - print HEADER "extern ATerm $name;\n"; - print IMPL "ATerm $name = 0;\n"; - $init .= " $name = $value;\n"; - $init .= " ATprotect(&$name);\n"; - } - - elsif (/^\s*init\s+(\w+)\s*$/) { - $initFun = $1; - } - - else { - die "bad line: `$_'"; - } -} - -print HEADER "void $initFun();\n\n"; - -print HEADER "static inline const char * aterm2String(ATerm t) {\n"; -print HEADER " return (const char *) ATgetName(ATgetAFun(t));\n"; -print HEADER "}\n\n"; - -print IMPL "\n"; -print IMPL "void $initFun() {\n"; -print IMPL "$init"; -print IMPL "}\n"; - -print HEADER "#ifdef __cplusplus\n"; -print HEADER "}\n"; -print HEADER "#endif\n\n\n"; -print IMPL "}\n"; - -close HEADER; -close IMPL; diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am index 39423394af69..7562631cd455 100644 --- a/src/libexpr/Makefile.am +++ b/src/libexpr/Makefile.am @@ -19,10 +19,8 @@ BUILT_SOURCES = \ EXTRA_DIST = lexer.l parser.y AM_CXXFLAGS = \ - -I$(srcdir)/.. ${aterm_include} \ + -I$(srcdir)/.. \ -I$(srcdir)/../libutil -I$(srcdir)/../libstore -AM_CFLAGS = \ - ${aterm_include} # Parser generation. @@ -47,4 +45,4 @@ bin_PROGRAMS = eval-test eval_test_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ diff --git a/src/libmain/Makefile.am b/src/libmain/Makefile.am index c2946febce34..a9ee6604255e 100644 --- a/src/libmain/Makefile.am +++ b/src/libmain/Makefile.am @@ -15,5 +15,5 @@ AM_CXXFLAGS = \ -DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \ -DNIX_BIN_DIR=\"$(bindir)\" \ -DNIX_VERSION=\"$(VERSION)\" \ - -I$(srcdir)/.. ${aterm_include} -I$(srcdir)/../libutil \ + -I$(srcdir)/.. -I$(srcdir)/../libutil \ -I$(srcdir)/../libstore diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 825e8762105e..3fbec4b5245d 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -13,8 +13,6 @@ #include #include -#include - namespace nix { diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 47681242f61b..9accc3005fc3 100644 --- a/src/libstore/Makefile.am +++ b/src/libstore/Makefile.am @@ -13,4 +13,4 @@ pkginclude_HEADERS = \ libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ AM_CXXFLAGS = -Wall \ - -I$(srcdir)/.. ${aterm_include} -I$(srcdir)/../libutil + -I$(srcdir)/.. -I$(srcdir)/../libutil diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am index 9b0d9951360d..0819a721c871 100644 --- a/src/nix-env/Makefile.am +++ b/src/nix-env/Makefile.am @@ -4,7 +4,7 @@ nix_env_SOURCES = nix-env.cc profiles.cc user-env.cc profiles.hh help.txt nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ nix-env.o: help.txt.hh @@ -12,6 +12,6 @@ nix-env.o: help.txt.hh ../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1) AM_CXXFLAGS = \ - -I$(srcdir)/.. ${aterm_include} \ + -I$(srcdir)/.. \ -I$(srcdir)/../libutil -I$(srcdir)/../libstore \ -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr diff --git a/src/nix-hash/Makefile.am b/src/nix-hash/Makefile.am index 350aa8ebd14c..5f84eb34d6da 100644 --- a/src/nix-hash/Makefile.am +++ b/src/nix-hash/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS = nix-hash nix_hash_SOURCES = nix-hash.cc help.txt nix_hash_LDADD = ../libmain/libmain.la ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ nix-hash.o: help.txt.hh diff --git a/src/nix-instantiate/Makefile.am b/src/nix-instantiate/Makefile.am index 3f6671719c6b..a65907a8d40a 100644 --- a/src/nix-instantiate/Makefile.am +++ b/src/nix-instantiate/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = nix-instantiate nix_instantiate_SOURCES = nix-instantiate.cc help.txt nix_instantiate_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ nix-instantiate.o: help.txt.hh @@ -11,6 +11,5 @@ nix-instantiate.o: help.txt.hh ../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1) AM_CXXFLAGS = \ - ${aterm_include} \ -I$(srcdir)/.. -I$(srcdir)/../libutil -I$(srcdir)/../libstore \ -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr diff --git a/src/nix-setuid-helper/Makefile.am b/src/nix-setuid-helper/Makefile.am index a0fbdf39d61b..35528458c5f6 100644 --- a/src/nix-setuid-helper/Makefile.am +++ b/src/nix-setuid-helper/Makefile.am @@ -2,7 +2,7 @@ libexec_PROGRAMS = nix-setuid-helper nix_setuid_helper_SOURCES = nix-setuid-helper.cc nix_setuid_helper_LDADD = ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} + ../boost/format/libformat.la AM_CXXFLAGS = \ - -I$(srcdir)/.. $(aterm_include) -I$(srcdir)/../libutil + -I$(srcdir)/.. -I$(srcdir)/../libutil diff --git a/src/nix-store/Makefile.am b/src/nix-store/Makefile.am index ca0fec570ceb..9a439dd9219c 100644 --- a/src/nix-store/Makefile.am +++ b/src/nix-store/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS = nix-store nix_store_SOURCES = nix-store.cc dotgraph.cc dotgraph.hh help.txt nix_store_LDADD = ../libmain/libmain.la ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ nix-store.o: help.txt.hh @@ -10,5 +10,5 @@ nix-store.o: help.txt.hh ../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1) AM_CXXFLAGS = \ - -I$(srcdir)/.. $(aterm_include) -I$(srcdir)/../libutil \ + -I$(srcdir)/.. -I$(srcdir)/../libutil \ -I$(srcdir)/../libstore -I$(srcdir)/../libmain diff --git a/src/nix-worker/Makefile.am b/src/nix-worker/Makefile.am index d1163ce3741a..50c8ae36d2e8 100644 --- a/src/nix-worker/Makefile.am +++ b/src/nix-worker/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS = nix-worker nix_worker_SOURCES = nix-worker.cc help.txt nix_worker_LDADD = ../libmain/libmain.la ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la ${aterm_lib} @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ nix-worker.o: help.txt.hh @@ -10,5 +10,5 @@ nix-worker.o: help.txt.hh ../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1) AM_CXXFLAGS = \ - -I$(srcdir)/.. $(aterm_include) -I$(srcdir)/../libutil \ + -I$(srcdir)/.. -I$(srcdir)/../libutil \ -I$(srcdir)/../libstore -I$(srcdir)/../libmain diff --git a/substitute.mk b/substitute.mk index 729116477795..50d63ef5c73b 100644 --- a/substitute.mk +++ b/substitute.mk @@ -24,7 +24,6 @@ -e "s^@xmllint\@^$(xmllint)^g" \ -e "s^@xmlflags\@^$(xmlflags)^g" \ -e "s^@xsltproc\@^$(xsltproc)^g" \ - -e "s^@aterm_bin\@^$(aterm_bin)^g" \ -e "s^@version\@^$(VERSION)^g" \ -e "s^@testPath\@^$(coreutils):$$(dirname $$(type -P expr))^g" \ < $< > $@ || rm $@ diff --git a/tests/common.sh.in b/tests/common.sh.in index 85dd3a38906b..b30bc44b5cc0 100644 --- a/tests/common.sh.in +++ b/tests/common.sh.in @@ -30,7 +30,6 @@ export REAL_STORE_DIR=@storedir@ export NIX_BUILD_HOOK= export PERL=perl export TOP=$(pwd)/.. -export aterm_bin=@aterm_bin@ export bzip2_bin_test="@bzip2_bin_test@" if test "${bzip2_bin_test:0:1}" != "/"; then bzip2_bin_test=`pwd`/${bzip2_bin_test} @@ -41,10 +40,6 @@ export xmlflags="@xmlflags@" export xsltproc="@xsltproc@" export SHELL="@shell@" -# Hack to get "atdiff" to run on Cygwin (Windows looks for -# DLLs in $PATH). -export PATH=$aterm_bin/../lib:$PATH - export version=@version@ export system=@system@ diff --git a/tests/lang.sh b/tests/lang.sh index 18eb0278cfcc..c0d436907317 100644 --- a/tests/lang.sh +++ b/tests/lang.sh @@ -47,10 +47,11 @@ for i in lang/eval-okay-*.nix; do if ! $nixinstantiate $flags --eval-only lang/$i.nix > lang/$i.out; then echo "FAIL: $i should evaluate" fail=1 - elif ! $aterm_bin/atdiff lang/$i.out lang/$i.exp; then - echo "FAIL: evaluation result of $i not as expected" - fail=1 fi + #elif ! $aterm_bin/atdiff lang/$i.out lang/$i.exp; then + # echo "FAIL: evaluation result of $i not as expected" + # fail=1 + #fi fi if test -e lang/$i.exp.xml; then -- cgit 1.4.1 From fe2d869e04372de69719c3989a75247ff44b8fd4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Apr 2010 15:08:58 +0000 Subject: * Store user environment manifests as a Nix expression in $out/manifest.nix rather than as an ATerm. (Hm, I thought I committed this two days ago...) --- corepkgs/buildenv/builder.pl.in | 2 +- src/libexpr/eval.cc | 11 +++- src/libexpr/eval.hh | 11 +++- src/libexpr/get-drvs.cc | 23 +------ src/libexpr/get-drvs.hh | 2 +- src/libexpr/primops.cc | 31 +++++---- src/nix-env/nix-env.cc | 136 --------------------------------------- src/nix-env/profiles.cc | 16 ++++- src/nix-env/profiles.hh | 15 +++++ src/nix-env/user-env.cc | 137 ++++++++++++++++++++++++++++++++++++++-- src/nix-env/user-env.hh | 4 ++ 11 files changed, 205 insertions(+), 183 deletions(-) (limited to 'src/nix-env') diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in index 9932ea577d93..9eb9f7bb08c1 100755 --- a/corepkgs/buildenv/builder.pl.in +++ b/corepkgs/buildenv/builder.pl.in @@ -160,4 +160,4 @@ while (scalar(keys %postponed) > 0) { print STDERR "created $symlinks symlinks in user environment\n"; -symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest"; +symlink($ENV{"manifest"}, "$out/manifest.nix") or die "cannot create manifest"; diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index d259d58a3759..f59ea99e5d41 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -98,6 +98,7 @@ EvalState::EvalState() , sType(symbols.create("type")) , sMeta(symbols.create("meta")) , sName(symbols.create("name")) + , sSystem(symbols.create("system")) , baseEnv(allocEnv(128)) , baseEnvDispl(0) , staticBaseEnv(false, 0) @@ -131,12 +132,13 @@ void EvalState::addPrimOp(const string & name, unsigned int arity, PrimOp primOp) { Value v; + string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; v.type = tPrimOp; v.primOp.arity = arity; v.primOp.fun = primOp; + v.primOp.name = strdup(name2.c_str()); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; - string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; (*baseEnv.values[0].attrs)[symbols.create(name2)] = v; } @@ -550,7 +552,12 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) vArgs[n--] = arg->primOpApp.right; /* And call the primop. */ - primOp->primOp.fun(*this, vArgs, v); + try { + primOp->primOp.fun(*this, vArgs, v); + } catch (Error & e) { + addErrorPrefix(e, "while evaluating the builtin function `%1%':\n", primOp->primOp.name); + throw; + } } else { Value * v2 = allocValues(2); v2[0] = fun; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 6cdc171f5609..a730dc297799 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -92,6 +92,7 @@ struct Value Value * val; struct { PrimOp fun; + char * name; unsigned int arity; } primOp; struct { @@ -138,6 +139,14 @@ static inline void mkCopy(Value & v, Value & src) } +static inline void mkApp(Value & v, Value & left, Value & right) +{ + v.type = tApp; + v.app.left = &left; + v.app.right = &right; +} + + void mkString(Value & v, const char * s); void mkString(Value & v, const string & s, const PathSet & context = PathSet()); void mkPath(Value & v, const char * s); @@ -162,7 +171,7 @@ public: SymbolTable symbols; - const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName; + const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sSystem; private: SrcToStore srcToStore; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index e9f1063d955f..e0ad91d8a54f 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -70,27 +70,6 @@ void DrvInfo::setMetaInfo(const MetaInfo & meta) { metaInfoRead = true; this->meta = meta; - -#if 0 - Value * metaAttrs = state.allocValues(1); - foreach (MetaInfo::const_iterator, i, meta) { - Expr e; - switch (i->second.type) { - case MetaValue::tpInt: e = makeInt(i->second.intValue); break; - case MetaValue::tpString: e = makeStr(i->second.stringValue); break; - case MetaValue::tpStrings: { - ATermList es = ATempty; - foreach (Strings::const_iterator, j, i->second.stringValues) - es = ATinsert(es, makeStr(*j)); - e = makeList(ATreverse(es)); - break; - } - default: abort(); - } - metaAttrs.set(toATerm(i->first), makeAttrRHS(e, makeNoPos())); - } - attrs->set(toATerm("meta"), makeAttrs(metaAttrs)); -#endif } @@ -122,7 +101,7 @@ static bool getDerivation(EvalState & state, Value & v, if (i == v.attrs->end()) throw TypeError("derivation name missing"); drv.name = state.forceStringNoCtx(i->second); - i = v.attrs->find(state.symbols.create("system")); + i = v.attrs->find(state.sSystem); if (i == v.attrs->end()) drv.system = "unknown"; else diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index 6f3c381f8e34..ca7d980027e4 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -41,7 +41,7 @@ public: /* !!! make this private */ Bindings * attrs; - DrvInfo() : metaInfoRead(false) { }; + DrvInfo() : metaInfoRead(false), attrs(0) { }; string queryDrvPath(EvalState & state) const; string queryOutPath(EvalState & state) const; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index b28201593335..a228398e0652 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -89,24 +89,29 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) { startNest(nest, lvlDebug, "finding dependencies"); - Expr attrs = evalExpr(state, args[0]); + state.forceAttrs(*args[0]); /* Get the start set. */ - Expr startSet = queryAttr(attrs, "startSet"); - if (!startSet) throw EvalError("attribute `startSet' required"); - ATermList startSet2 = evalList(state, startSet); + Bindings::iterator startSet = + args[0]->attrs->find(state.symbols.create("startSet")); + if (startSet == args[0]->attrs->end()) + throw EvalError("attribute `startSet' required"); + state.forceList(startSet->second); - set workSet; // !!! gc roots - for (ATermIterator i(startSet2); i; ++i) workSet.insert(*i); + list workSet; + for (unsigned int n = 0; n < startSet->second.list.length; ++n) + workSet.push_back(*startSet->second.list.elems[n]); /* Get the operator. */ - Expr op = queryAttr(attrs, "operator"); - if (!op) throw EvalError("attribute `operator' required"); + Bindings::iterator op = + args[0]->attrs->find(state.symbols.create("operator")); + if (op == args[0]->attrs->end()) + throw EvalError("attribute `operator' required"); /* Construct the closure by applying the operator to element of `workSet', adding the result to `workSet', continuing until no new elements are found. */ - ATermList res = ATempty; + list res; set doneKeys; // !!! gc roots while (!workSet.empty()) { Expr e = *(workSet.begin()); @@ -322,8 +327,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) string s = state.coerceToString(i->second, context, true); drv.env[key] = s; if (key == "builder") drv.builder = s; - else if (key == "system") drv.platform = s; - else if (key == "name") drvName = s; + else if (i->first == state.sSystem) drv.platform = s; + else if (i->first == state.sName) drvName = s; else if (key == "outputHash") outputHash = s; else if (key == "outputHashAlgo") outputHashAlgo = s; else if (key == "outputHashMode") { @@ -830,9 +835,7 @@ static void prim_map(EvalState & state, Value * * args, Value & v) for (unsigned int n = 0; n < v.list.length; ++n) { v.list.elems[n] = &vs[n]; - vs[n].type = tApp; - vs[n].app.left = args[0]; - vs[n].app.right = args[1]->list.elems[n]; + mkApp(vs[n], *args[0], *args[1]->list.elems[n]); } } diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index e298c4003b61..4a9df454d4ff 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -8,7 +8,6 @@ #include "help.txt.hh" #include "get-drvs.hh" #include "attr-path.hh" -#include "pathlocks.hh" #include "common-opts.hh" #include "xml-writer.hh" #include "store-api.hh" @@ -193,141 +192,6 @@ static Path getDefNixExprPath() } -/* Ensure exclusive access to a profile. Any command that modifies - the profile first acquires this lock. */ -static void lockProfile(PathLocks & lock, const Path & profile) -{ - lock.lockPaths(singleton(profile), - (format("waiting for lock on profile `%1%'") % profile).str()); - lock.setDeletion(true); -} - - -/* Optimistic locking is used by long-running operations like `nix-env - -i'. Instead of acquiring the exclusive lock for the entire - duration of the operation, we just perform the operation - optimistically (without an exclusive lock), and check at the end - whether the profile changed while we were busy (i.e., the symlink - target changed). If so, the operation is restarted. Restarting is - generally cheap, since the build results are still in the Nix - store. Most of the time, only the user environment has to be - rebuilt. */ -static string optimisticLockProfile(const Path & profile) -{ - return pathExists(profile) ? readLink(profile) : ""; -} - - -static bool createUserEnv(EvalState & state, DrvInfos & elems, - const Path & profile, bool keepDerivations, - const string & lockToken) -{ - throw Error("not implemented"); -#if 0 - /* Build the components in the user environment, if they don't - exist already. */ - PathSet drvsToBuild; - foreach (DrvInfos::const_iterator, i, elems) - /* Call to `isDerivation' is for compatibility with Nix <= 0.7 - user environments. */ - if (i->queryDrvPath(state) != "" && - isDerivation(i->queryDrvPath(state))) - drvsToBuild.insert(i->queryDrvPath(state)); - - debug(format("building user environment dependencies")); - store->buildDerivations(drvsToBuild); - - /* Get the environment builder expression. */ - Expr envBuilder = parseExprFromFile(state, - nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */ - - /* Construct the whole top level derivation. */ - PathSet references; - ATermList manifest = ATempty; - ATermList inputs = ATempty; - foreach (DrvInfos::iterator, i, elems) { - /* Create a pseudo-derivation containing the name, system, - output path, and optionally the derivation path, as well as - the meta attributes. */ - Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; - - /* Round trip to get rid of "bad" meta values (like - functions). */ - MetaInfo meta = i->queryMetaInfo(state); - i->setMetaInfo(meta); - - ATermList as = ATmakeList5( - makeBind(toATerm("type"), - makeStr("derivation"), makeNoPos()), - makeBind(toATerm("name"), - makeStr(i->name), makeNoPos()), - makeBind(toATerm("system"), - makeStr(i->system), makeNoPos()), - makeBind(toATerm("outPath"), - makeStr(i->queryOutPath(state)), makeNoPos()), - makeBind(toATerm("meta"), - i->attrs->get(toATerm("meta")), makeNoPos())); - - if (drvPath != "") as = ATinsert(as, - makeBind(toATerm("drvPath"), - makeStr(drvPath), makeNoPos())); - - manifest = ATinsert(manifest, makeAttrs(as)); - - inputs = ATinsert(inputs, makeStr(i->queryOutPath(state))); - - /* This is only necessary when installing store paths, e.g., - `nix-env -i /nix/store/abcd...-foo'. */ - store->addTempRoot(i->queryOutPath(state)); - store->ensurePath(i->queryOutPath(state)); - - references.insert(i->queryOutPath(state)); - if (drvPath != "") references.insert(drvPath); - } - - /* Also write a copy of the list of inputs to the store; we need - it for future modifications of the environment. */ - Path manifestFile = store->addTextToStore("env-manifest", - atPrint(canonicaliseExpr(makeList(ATreverse(manifest)))), references); - - Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( - makeBind(toATerm("system"), - makeStr(thisSystem), makeNoPos()), - makeBind(toATerm("derivations"), - makeList(ATreverse(manifest)), makeNoPos()), - makeBind(toATerm("manifest"), - makeStr(manifestFile, singleton(manifestFile)), makeNoPos()) - ))); - - /* Instantiate it. */ - debug(format("evaluating builder expression `%1%'") % topLevel); - DrvInfo topLevelDrv; - if (!getDerivation(state, topLevel, topLevelDrv)) - abort(); - - /* Realise the resulting store expression. */ - debug(format("building user environment")); - store->buildDerivations(singleton(topLevelDrv.queryDrvPath(state))); - - /* Switch the current user environment to the output path. */ - PathLocks lock; - lockProfile(lock, profile); - - Path lockTokenCur = optimisticLockProfile(profile); - if (lockToken != lockTokenCur) { - printMsg(lvlError, format("profile `%1%' changed while we were busy; restarting") % profile); - return false; - } - - debug(format("switching to new user environment")); - Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state)); - switchLink(profile, generation); - - return true; -#endif -} - - static int getPriority(EvalState & state, const DrvInfo & drv) { MetaValue value = drv.queryMetaInfo(state, "priority"); diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc index 75585b1b2907..60576f1ae74b 100644 --- a/src/nix-env/profiles.cc +++ b/src/nix-env/profiles.cc @@ -130,6 +130,20 @@ void switchLink(Path link, Path target) throw SysError(format("renaming `%1%' to `%2%'") % tmp % link); } - + +void lockProfile(PathLocks & lock, const Path & profile) +{ + lock.lockPaths(singleton(profile), + (format("waiting for lock on profile `%1%'") % profile).str()); + lock.setDeletion(true); +} + + +string optimisticLockProfile(const Path & profile) +{ + return pathExists(profile) ? readLink(profile) : ""; +} + + } diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh index 99c20f42d18c..a64258dae224 100644 --- a/src/nix-env/profiles.hh +++ b/src/nix-env/profiles.hh @@ -2,6 +2,7 @@ #define __PROFILES_H #include "types.hh" +#include "pathlocks.hh" #include @@ -37,6 +38,20 @@ void deleteGeneration(const Path & profile, unsigned int gen); void switchLink(Path link, Path target); +/* Ensure exclusive access to a profile. Any command that modifies + the profile first acquires this lock. */ +void lockProfile(PathLocks & lock, const Path & profile); + +/* Optimistic locking is used by long-running operations like `nix-env + -i'. Instead of acquiring the exclusive lock for the entire + duration of the operation, we just perform the operation + optimistically (without an exclusive lock), and check at the end + whether the profile changed while we were busy (i.e., the symlink + target changed). If so, the operation is restarted. Restarting is + generally cheap, since the build results are still in the Nix + store. Most of the time, only the user environment has to be + rebuilt. */ +string optimisticLockProfile(const Path & profile); } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index f040f8c11570..a0e51cae19c3 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -1,5 +1,12 @@ #include "util.hh" #include "get-drvs.hh" +#include "derivations.hh" +#include "store-api.hh" +#include "globals.hh" +#include "shared.hh" +#include "eval.hh" +#include "parser.hh" +#include "profiles.hh" namespace nix { @@ -11,18 +18,138 @@ static void readLegacyManifest(const Path & path, DrvInfos & elems); DrvInfos queryInstalled(EvalState & state, const Path & userEnv) { DrvInfos elems; - - Path path = userEnv + "/manifest"; - if (!pathExists(path)) - return DrvInfos(); /* not an error, assume nothing installed */ + Path manifestFile = userEnv + "/manifest.nix"; + Path oldManifestFile = userEnv + "/manifest"; - readLegacyManifest(path, elems); + if (pathExists(manifestFile)) { + Value v; + state.eval(parseExprFromFile(state, manifestFile), v); + getDerivations(state, v, "", Bindings(), elems); + } else if (pathExists(oldManifestFile)) + readLegacyManifest(oldManifestFile, elems); return elems; } +bool createUserEnv(EvalState & state, DrvInfos & elems, + const Path & profile, bool keepDerivations, + const string & lockToken) +{ + /* Build the components in the user environment, if they don't + exist already. */ + PathSet drvsToBuild; + foreach (DrvInfos::const_iterator, i, elems) + if (i->queryDrvPath(state) != "") + drvsToBuild.insert(i->queryDrvPath(state)); + + debug(format("building user environment dependencies")); + store->buildDerivations(drvsToBuild); + + /* Construct the whole top level derivation. */ + PathSet references; + Value manifest; + state.mkList(manifest, elems.size()); + unsigned int n = 0; + foreach (DrvInfos::iterator, i, elems) { + /* Create a pseudo-derivation containing the name, system, + output path, and optionally the derivation path, as well as + the meta attributes. */ + Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; + + Value & v(*state.allocValues(1)); + manifest.list.elems[n++] = &v; + state.mkAttrs(v); + + mkString((*v.attrs)[state.sType], "derivation"); + mkString((*v.attrs)[state.sName], i->name); + mkString((*v.attrs)[state.sSystem], i->system); + mkString((*v.attrs)[state.sOutPath], i->queryOutPath(state)); + if (drvPath != "") + mkString((*v.attrs)[state.sDrvPath], i->queryDrvPath(state)); + + state.mkAttrs((*v.attrs)[state.sMeta]); + + MetaInfo meta = i->queryMetaInfo(state); + + foreach (MetaInfo::const_iterator, j, meta) { + Value & v2((*(*v.attrs)[state.sMeta].attrs)[state.symbols.create(j->first)]); + switch (j->second.type) { + case MetaValue::tpInt: mkInt(v2, j->second.intValue); break; + case MetaValue::tpString: mkString(v2, j->second.stringValue); break; + case MetaValue::tpStrings: { + state.mkList(v2, j->second.stringValues.size()); + unsigned int m = 0; + foreach (Strings::const_iterator, k, j->second.stringValues) { + v2.list.elems[m] = state.allocValues(1); + mkString(*v2.list.elems[m++], *k); + } + break; + } + default: abort(); + } + } + + /* This is only necessary when installing store paths, e.g., + `nix-env -i /nix/store/abcd...-foo'. */ + store->addTempRoot(i->queryOutPath(state)); + store->ensurePath(i->queryOutPath(state)); + + references.insert(i->queryOutPath(state)); + if (drvPath != "") references.insert(drvPath); + } + + /* Also write a copy of the list of user environment elements to + the store; we need it for future modifications of the + environment. */ + Path manifestFile = store->addTextToStore("env-manifest.nix", + (format("%1%") % manifest).str(), references); + + printMsg(lvlError, manifestFile); + + /* Get the environment builder expression. */ + Value envBuilder; + state.eval(parseExprFromFile(state, nixDataDir + "/nix/corepkgs/buildenv"), envBuilder); + + /* Construct a Nix expression that calls the user environment + builder with the manifest as argument. */ + Value args, topLevel; + state.mkAttrs(args); + mkString((*args.attrs)[state.sSystem], thisSystem); + mkString((*args.attrs)[state.symbols.create("manifest")], + manifestFile, singleton(manifestFile)); + (*args.attrs)[state.symbols.create("derivations")] = manifest; + mkApp(topLevel, envBuilder, args); + + /* Evaluate it. */ + debug("evaluating user environment builder"); + DrvInfo topLevelDrv; + if (!getDerivation(state, topLevel, topLevelDrv)) + abort(); + + /* Realise the resulting store expression. */ + debug("building user environment"); + store->buildDerivations(singleton(topLevelDrv.queryDrvPath(state))); + + /* Switch the current user environment to the output path. */ + PathLocks lock; + lockProfile(lock, profile); + + Path lockTokenCur = optimisticLockProfile(profile); + if (lockToken != lockTokenCur) { + printMsg(lvlError, format("profile `%1%' changed while we were busy; restarting") % profile); + return false; + } + + debug(format("switching to new user environment")); + Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state)); + switchLink(profile, generation); + + return true; +} + + /* Code for parsing manifests in the old textual ATerm format. */ static string parseStr(std::istream & str) diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh index 6675014f1a31..4125d821732f 100644 --- a/src/nix-env/user-env.hh +++ b/src/nix-env/user-env.hh @@ -7,6 +7,10 @@ namespace nix { DrvInfos queryInstalled(EvalState & state, const Path & userEnv); +bool createUserEnv(EvalState & state, DrvInfos & elems, + const Path & profile, bool keepDerivations, + const string & lockToken); + } #endif /* !__USER_ENV_H */ -- cgit 1.4.1 From c82782f9a5190c7489fb8e9bd6876b247b0de0bf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 27 Apr 2010 09:05:11 +0000 Subject: --- src/nix-env/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nix-env') diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am index 0819a721c871..7dfa7425a062 100644 --- a/src/nix-env/Makefile.am +++ b/src/nix-env/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = nix-env -nix_env_SOURCES = nix-env.cc profiles.cc user-env.cc profiles.hh help.txt +nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh user-env.cc user-env.hh help.txt nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ -- cgit 1.4.1 From 84ce7ac76feab6e9a5c074bd1b9550ae543d1db8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 6 May 2010 16:46:48 +0000 Subject: * Store attribute positions in the AST and report duplicate attribute errors with position info. * For all positions, use the position of the first character of the first token, rather than the last character of the first token plus one. --- src/libexpr/eval.cc | 16 +++------------ src/libexpr/lexer.l | 13 +++++++----- src/libexpr/nixexpr.cc | 13 +++++++----- src/libexpr/nixexpr.hh | 10 +++++++-- src/libexpr/parser.y | 55 ++++++++++++++++++++++++-------------------------- src/nix-env/nix-env.cc | 5 +++-- 6 files changed, 56 insertions(+), 56 deletions(-) (limited to 'src/nix-env') diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b4f12c8a9c94..cb124ab8ba44 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -192,11 +192,6 @@ LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & pos)) throw AssertionError(format(s) % pos); } -LocalNoInline(void addErrorPrefix(Error & e, const char * s)) -{ - e.addPrefix(s); -} - LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2)) { e.addPrefix(format(s) % s2); @@ -207,11 +202,6 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const Pos & pos)) e.addPrefix(format(s) % pos); } -LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const string & s3)) -{ - e.addPrefix(format(s) % s2 % s3); -} - void mkString(Value & v, const char * s) { @@ -426,7 +416,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) foreach (Attrs::iterator, i, attrs) { Value & v2 = (*v.attrs)[i->first]; mkCopy(v2, env2.values[displ]); - mkThunk(env2.values[displ++], env2, i->second); + mkThunk(env2.values[displ++], env2, i->second.first); } /* The inherited attributes, on the other hand, are @@ -443,7 +433,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) else { foreach (Attrs::iterator, i, attrs) { Value & v2 = (*v.attrs)[i->first]; - mkThunk(v2, env, i->second); + mkThunk(v2, env, i->second.first); } foreach (list::iterator, i, inherited) { @@ -466,7 +456,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) /* The recursive attributes are evaluated in the new environment. */ foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) - mkThunk(env2.values[displ++], env2, i->second); + mkThunk(env2.values[displ++], env2, i->second.first); /* The inherited attributes, on the other hand, are evaluated in the original environment. */ diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 00de57a7bac9..f29f9b684332 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -19,13 +19,16 @@ namespace nix { static void initLoc(YYLTYPE * loc) { - loc->first_line = 1; - loc->first_column = 1; + loc->first_line = loc->last_line = 1; + loc->first_column = loc->last_column = 1; } static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) { + loc->first_line = loc->last_line; + loc->first_column = loc->last_column; + while (len--) { switch (*s++) { case '\r': @@ -33,11 +36,11 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) s++; /* fall through */ case '\n': - ++loc->first_line; - loc->first_column = 1; + ++loc->last_line; + loc->last_column = 1; break; default: - ++loc->first_column; + ++loc->last_column; } } } diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index a9c83108e950..af0632a94d6e 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -58,7 +58,7 @@ void ExprAttrs::show(std::ostream & str) foreach (list::iterator, i, inherited) str << "inherit " << i->name << "; "; foreach (Attrs::iterator, i, attrs) - str << i->first << " = " << *i->second << "; "; + str << i->first << " = " << *i->second.first << "; "; str << "}"; } @@ -94,7 +94,7 @@ void ExprLet::show(std::ostream & str) foreach (list::iterator, i, attrs->inherited) str << "inherit " << i->name << "; "; foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) - str << i->first << " = " << *i->second << "; "; + str << i->first << " = " << *i->second.first << "; "; str << "in " << *body; } @@ -138,6 +138,9 @@ std::ostream & operator << (std::ostream & str, const Pos & pos) } +Pos noPos; + + /* Computing levels/displacements for variables. */ void Expr::bindVars(const StaticEnv & env) @@ -218,12 +221,12 @@ void ExprAttrs::bindVars(const StaticEnv & env) } foreach (ExprAttrs::Attrs::iterator, i, attrs) - i->second->bindVars(newEnv); + i->second.first->bindVars(newEnv); } else { foreach (ExprAttrs::Attrs::iterator, i, attrs) - i->second->bindVars(env); + i->second.first->bindVars(env); foreach (list::iterator, i, inherited) i->bind(env); @@ -270,7 +273,7 @@ void ExprLet::bindVars(const StaticEnv & env) } foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) - i->second->bindVars(newEnv); + i->second.first->bindVars(newEnv); body->bindVars(newEnv); } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 2d328d382c8d..36cb4e53cd7c 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -23,8 +23,13 @@ struct Pos { string file; unsigned int line, column; + Pos() : line(0), column(0) { }; + Pos(const string & file, unsigned int line, unsigned int column) + : file(file), line(line), column(column) { }; }; +extern Pos noPos; + std::ostream & operator << (std::ostream & str, const Pos & pos); @@ -125,10 +130,11 @@ struct ExprOpHasAttr : Expr struct ExprAttrs : Expr { bool recursive; - typedef std::map Attrs; + typedef std::pair Attr; + typedef std::map Attrs; Attrs attrs; list inherited; - set attrNames; // used during parsing + std::map attrNames; // used during parsing ExprAttrs() : recursive(false) { }; COMMON_METHODS }; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 66da769402dc..99980240f823 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -61,18 +61,18 @@ static string showAttrPath(const vector & attrPath) } -static void dupAttr(const vector & attrPath, const Pos & pos) +static void dupAttr(const vector & attrPath, const Pos & pos, const Pos & prevPos) { - throw ParseError(format("attribute `%1%' at %2% already defined at ") - % showAttrPath(attrPath) % pos); + throw ParseError(format("attribute `%1%' at %2% already defined at %3%") + % showAttrPath(attrPath) % pos % prevPos); } -static void dupAttr(Symbol attr, const Pos & pos) +static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos) { vector attrPath; attrPath.push_back(attr); - throw ParseError(format("attribute `%1%' at %2% already defined at ") - % showAttrPath(attrPath) % pos); + throw ParseError(format("attribute `%1%' at %2% already defined at %3%") + % showAttrPath(attrPath) % pos % prevPos); } @@ -82,19 +82,20 @@ static void addAttr(ExprAttrs * attrs, const vector & attrPath, unsigned int n = 0; foreach (vector::const_iterator, i, attrPath) { n++; - if (attrs->attrs[*i]) { - ExprAttrs * attrs2 = dynamic_cast(attrs->attrs[*i]); - if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos); + ExprAttrs::Attrs::iterator j = attrs->attrs.find(*i); + if (j != attrs->attrs.end()) { + ExprAttrs * attrs2 = dynamic_cast(j->second.first); + if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos, j->second.second); attrs = attrs2; } else { if (attrs->attrNames.find(*i) != attrs->attrNames.end()) - dupAttr(attrPath, pos); - attrs->attrNames.insert(*i); + dupAttr(attrPath, pos, attrs->attrNames[*i]); + attrs->attrNames[*i] = pos; if (n == attrPath.size()) - attrs->attrs[*i] = e; + attrs->attrs[*i] = ExprAttrs::Attr(e, pos); else { ExprAttrs * nested = new ExprAttrs; - attrs->attrs[*i] = nested; + attrs->attrs[*i] = ExprAttrs::Attr(nested, pos); attrs = nested; } } @@ -205,16 +206,12 @@ void backToString(yyscan_t scanner); void backToIndString(yyscan_t scanner); -static Pos makeCurPos(YYLTYPE * loc, ParseData * data) +static Pos makeCurPos(const YYLTYPE & loc, ParseData * data) { - Pos pos; - pos.file = data->path; - pos.line = loc->first_line; - pos.column = loc->first_column; - return pos; + return Pos(data->path, loc.first_line, loc.first_column); } -#define CUR_POS makeCurPos(yylocp, data) +#define CUR_POS makeCurPos(*yylocp, data) } @@ -223,7 +220,7 @@ static Pos makeCurPos(YYLTYPE * loc, ParseData * data) void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error) { data->error = (format("%1%, at %2%") - % error % makeCurPos(loc, data)).str(); + % error % makeCurPos(*loc, data)).str(); } @@ -374,14 +371,14 @@ ind_string_parts ; binds - : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, CUR_POS); } + : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); } | binds INHERIT ids ';' { $$ = $1; foreach (vector::iterator, i, *$3) { if ($$->attrNames.find(*i) != $$->attrNames.end()) - dupAttr(*i, CUR_POS); + dupAttr(*i, makeCurPos(@3, data), $$->attrNames[*i]); $$->inherited.push_back(*i); - $$->attrNames.insert(*i); + $$->attrNames[*i] = makeCurPos(@3, data); } } | binds INHERIT '(' expr ')' ids ';' @@ -389,11 +386,11 @@ binds /* !!! Should ensure sharing of the expression in $4. */ foreach (vector::iterator, i, *$6) { if ($$->attrNames.find(*i) != $$->attrNames.end()) - dupAttr(*i, CUR_POS); - $$->attrs[*i] = new ExprSelect($4, *i); - $$->attrNames.insert(*i); - } - } + dupAttr(*i, makeCurPos(@6, data), $$->attrNames[*i]); + $$->attrs[*i] = ExprAttrs::Attr(new ExprSelect($4, *i), makeCurPos(@6, data)); + $$->attrNames[*i] = makeCurPos(@6, data); + }} + | { $$ = new ExprAttrs; } ; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 4a9df454d4ff..12a256a091f9 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -132,7 +132,7 @@ static void getAllExprs(EvalState & state, if (hasSuffix(attrName, ".nix")) attrName = string(attrName, 0, attrName.size() - 4); attrs.attrs[state.symbols.create(attrName)] = - parseExprFromFile(state, absPath(path2)); + ExprAttrs::Attr(parseExprFromFile(state, absPath(path2)), noPos); } else /* `path2' is a directory (with no default.nix in it); @@ -153,7 +153,8 @@ static Expr * loadSourceExpr(EvalState & state, const Path & path) for a user to have a ~/.nix-defexpr directory that includes some system-wide directory). */ ExprAttrs * attrs = new ExprAttrs; - attrs->attrs[state.symbols.create("_combineChannels")] = new ExprList(); + attrs->attrs[state.symbols.create("_combineChannels")] = + ExprAttrs::Attr(new ExprList(), noPos); getAllExprs(state, path, *attrs); return attrs; } -- cgit 1.4.1 From e2d5e40f4fdd98e5d2ad7b77c00fb97caa3aa259 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 7 May 2010 12:11:05 +0000 Subject: * Keep track of the source positions of attributes. --- src/libexpr/attr-path.cc | 2 +- src/libexpr/common-opts.cc | 2 +- src/libexpr/eval.cc | 59 +++++++++++++++++++++++++--------------- src/libexpr/eval.hh | 11 +++++++- src/libexpr/get-drvs.cc | 32 +++++++++++----------- src/libexpr/primops.cc | 66 ++++++++++++++++++++++++--------------------- src/libexpr/value-to-xml.cc | 11 ++++---- src/nix-env/user-env.cc | 20 +++++++------- 8 files changed, 117 insertions(+), 86 deletions(-) (limited to 'src/nix-env') diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 769acb6b8c0f..0660ba1c1efc 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -48,7 +48,7 @@ void findAlongAttrPath(EvalState & state, const string & attrPath, Bindings::iterator a = v.attrs->find(state.symbols.create(attr)); if (a == v.attrs->end()) throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); - v = a->second; + v = a->second.value; } else if (apType == apIndex) { diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc index a25317de1346..5a4856568b4b 100644 --- a/src/libexpr/common-opts.cc +++ b/src/libexpr/common-opts.cc @@ -20,7 +20,7 @@ bool parseOptionArg(const string & arg, Strings::iterator & i, if (i == argsEnd) throw error; string value = *i++; - Value & v(autoArgs[state.symbols.create(name)]); + Value & v(autoArgs[state.symbols.create(name)].value); if (arg == "--arg") state.mkThunk_( v, parseExprFromString(state, value, absPath("."))); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index cb124ab8ba44..b8ec410f3993 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -44,7 +44,7 @@ std::ostream & operator << (std::ostream & str, Value & v) case tAttrs: str << "{ "; foreach (Bindings::iterator, i, *v.attrs) - str << (string) i->first << " = " << i->second << "; "; + str << (string) i->first << " = " << i->second.value << "; "; str << "}"; break; case tList: @@ -128,7 +128,7 @@ void EvalState::addConstant(const string & name, Value & v) staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - (*baseEnv.values[0].attrs)[symbols.create(name2)] = v; + (*baseEnv.values[0].attrs)[symbols.create(name2)].value = v; } @@ -143,7 +143,7 @@ void EvalState::addPrimOp(const string & name, v.primOp.name = strdup(name2.c_str()); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; - (*baseEnv.values[0].attrs)[symbols.create(name2)] = v; + (*baseEnv.values[0].attrs)[symbols.create(name2)].value = v; } @@ -202,6 +202,11 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const Pos & pos)) e.addPrefix(format(s) % pos); } +LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const Pos & pos)) +{ + e.addPrefix(format(s) % s2 % pos); +} + void mkString(Value & v, const char * s) { @@ -239,7 +244,7 @@ Value * EvalState::lookupVar(Env * env, const VarRef & var) while (1) { Bindings::iterator j = env->values[0].attrs->find(var.name); if (j != env->values[0].attrs->end()) - return &j->second; + return &j->second.value; if (env->prevWith == 0) throwEvalError("undefined variable `%1%'", var.name); for (unsigned int l = env->prevWith; l; --l, env = env->up) ; @@ -290,8 +295,11 @@ void EvalState::mkThunk_(Value & v, Expr * expr) void EvalState::cloneAttrs(Value & src, Value & dst) { mkAttrs(dst); - foreach (Bindings::iterator, i, *src.attrs) - mkCopy((*dst.attrs)[i->first], i->second); + foreach (Bindings::iterator, i, *src.attrs) { + Attr & a = (*dst.attrs)[i->first]; + mkCopy(a.value, i->second.value); + a.pos = i->second.pos; + } } @@ -414,15 +422,16 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) /* The recursive attributes are evaluated in the new environment. */ foreach (Attrs::iterator, i, attrs) { - Value & v2 = (*v.attrs)[i->first]; - mkCopy(v2, env2.values[displ]); + nix::Attr & a = (*v.attrs)[i->first]; + mkCopy(a.value, env2.values[displ]); mkThunk(env2.values[displ++], env2, i->second.first); + a.pos = &i->second.second; } /* The inherited attributes, on the other hand, are evaluated in the original environment. */ foreach (list::iterator, i, inherited) { - Value & v2 = (*v.attrs)[i->name]; + Value & v2 = (*v.attrs)[i->name].value; Value * v3 = state.lookupVar(&env, *i); mkCopy(v2, *v3); mkCopy(env2.values[displ++], *v3); @@ -432,12 +441,13 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) else { foreach (Attrs::iterator, i, attrs) { - Value & v2 = (*v.attrs)[i->first]; - mkThunk(v2, env, i->second.first); + nix::Attr & a = (*v.attrs)[i->first]; + mkThunk(a.value, env, i->second.first); + a.pos = &i->second.second; } foreach (list::iterator, i, inherited) { - Value & v2 = (*v.attrs)[i->name]; + Value & v2 = (*v.attrs)[i->name].value; mkCopy(v2, *state.lookupVar(&env, *i)); } } @@ -494,12 +504,13 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) if (i == v2.attrs->end()) throwEvalError("attribute `%1%' missing", name); try { - state.forceValue(i->second); + state.forceValue(i->second.value); } catch (Error & e) { - addErrorPrefix(e, "while evaluating the attribute `%1%':\n", name); + addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n", + name, *i->second.pos); throw; } - v = i->second; + v = i->second.value; } @@ -601,7 +612,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) mkThunk(env2.values[displ++], env2, i->def); } else { attrsUsed++; - mkCopy(env2.values[displ++], j->second); + mkCopy(env2.values[displ++], j->second.value); } } @@ -721,8 +732,11 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) state.evalAttrs(env, e2, v2); - foreach (Bindings::iterator, i, *v2.attrs) - mkCopy((*v.attrs)[i->first], i->second); + foreach (Bindings::iterator, i, *v2.attrs) { + Attr & a = (*v.attrs)[i->first]; + mkCopy(a.value, i->second.value); + a.pos = i->second.pos; + } } @@ -802,7 +816,7 @@ void EvalState::strictForceValue(Value & v) if (v.type == tAttrs) { foreach (Bindings::iterator, i, *v.attrs) - strictForceValue(i->second); + strictForceValue(i->second.value); } else if (v.type == tList) { @@ -887,7 +901,7 @@ bool EvalState::isDerivation(Value & v) { if (v.type != tAttrs) return false; Bindings::iterator i = v.attrs->find(sType); - return i != v.attrs->end() && forceStringNoCtx(i->second) == "derivation"; + return i != v.attrs->end() && forceStringNoCtx(i->second.value) == "derivation"; } @@ -933,7 +947,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, Bindings::iterator i = v.attrs->find(sOutPath); if (i == v.attrs->end()) throwTypeError("cannot coerce an attribute set (except a derivation) to a string"); - return coerceToString(i->second, context, coerceMore, copyToStore); + return coerceToString(i->second.value, context, coerceMore, copyToStore); } if (coerceMore) { @@ -1021,7 +1035,8 @@ bool EvalState::eqValues(Value & v1, Value & v2) if (v1.attrs->size() != v2.attrs->size()) return false; Bindings::iterator i, j; for (i = v1.attrs->begin(), j = v2.attrs->begin(); i != v1.attrs->end(); ++i, ++j) - if (i->first != j->first || !eqValues(i->second, j->second)) return false; + if (i->first != j->first || !eqValues(i->second.value, j->second.value)) + return false; return true; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 6912e22887fd..1a9862c29533 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -14,8 +14,9 @@ class Hash; class EvalState; struct Env; struct Value; +struct Attr; -typedef std::map Bindings; +typedef std::map Bindings; typedef enum { @@ -111,6 +112,14 @@ struct Env }; +struct Attr +{ + Value value; + Pos * pos; + Attr() : pos(&noPos) { }; +}; + + static inline void mkInt(Value & v, int n) { v.type = tInt; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index e0ad91d8a54f..82a92416bed6 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -10,7 +10,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const if (drvPath == "" && attrs) { Bindings::iterator i = attrs->find(state.sDrvPath); PathSet context; - (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; + (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second.value, context) : ""; } return drvPath; } @@ -21,7 +21,7 @@ string DrvInfo::queryOutPath(EvalState & state) const if (outPath == "" && attrs) { Bindings::iterator i = attrs->find(state.sOutPath); PathSet context; - (string &) outPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; + (string &) outPath = i != attrs->end() ? state.coerceToPath(i->second.value, context) : ""; } return outPath; } @@ -36,21 +36,21 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const Bindings::iterator a = attrs->find(state.sMeta); if (a == attrs->end()) return meta; /* fine, empty meta information */ - state.forceAttrs(a->second); + state.forceAttrs(a->second.value); - foreach (Bindings::iterator, i, *a->second.attrs) { + foreach (Bindings::iterator, i, *a->second.value.attrs) { MetaValue value; - state.forceValue(i->second); - if (i->second.type == tString) { + state.forceValue(i->second.value); + if (i->second.value.type == tString) { value.type = MetaValue::tpString; - value.stringValue = i->second.string.s; - } else if (i->second.type == tInt) { + value.stringValue = i->second.value.string.s; + } else if (i->second.value.type == tInt) { value.type = MetaValue::tpInt; - value.intValue = i->second.integer; - } else if (i->second.type == tList) { + value.intValue = i->second.value.integer; + } else if (i->second.value.type == tList) { value.type = MetaValue::tpStrings; - for (unsigned int j = 0; j < i->second.list.length; ++j) - value.stringValues.push_back(state.forceStringNoCtx(*i->second.list.elems[j])); + for (unsigned int j = 0; j < i->second.value.list.length; ++j) + value.stringValues.push_back(state.forceStringNoCtx(*i->second.value.list.elems[j])); } else continue; ((MetaInfo &) meta)[i->first] = value; } @@ -99,13 +99,13 @@ static bool getDerivation(EvalState & state, Value & v, Bindings::iterator i = v.attrs->find(state.sName); /* !!! 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); + drv.name = state.forceStringNoCtx(i->second.value); i = v.attrs->find(state.sSystem); if (i == v.attrs->end()) drv.system = "unknown"; else - drv.system = state.forceStringNoCtx(i->second); + drv.system = state.forceStringNoCtx(i->second.value); drv.attrs = v.attrs; @@ -168,7 +168,7 @@ static void getDerivations(EvalState & state, Value & vIn, foreach (SortedSymbols::iterator, i, attrs) { startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first); string pathPrefix2 = addToPath(pathPrefix, i->first); - Value & v2((*v.attrs)[i->second]); + Value & v2((*v.attrs)[i->second].value); if (combineChannels) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); else if (getDerivation(state, v2, pathPrefix2, drvs, done)) { @@ -178,7 +178,7 @@ static void getDerivations(EvalState & state, Value & vIn, attribute. */ if (v2.type == tAttrs) { Bindings::iterator j = v2.attrs->find(state.symbols.create("recurseForDerivations")); - if (j != v2.attrs->end() && state.forceBool(j->second)) + if (j != v2.attrs->end() && state.forceBool(j->second.value)) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); } } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 9023d2b1beb4..981f87ce81e5 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -115,18 +115,18 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) args[0]->attrs->find(state.symbols.create("startSet")); if (startSet == args[0]->attrs->end()) throw EvalError("attribute `startSet' required"); - state.forceList(startSet->second); + state.forceList(startSet->second.value); list workSet; - for (unsigned int n = 0; n < startSet->second.list.length; ++n) - workSet.push_back(startSet->second.list.elems[n]); + for (unsigned int n = 0; n < startSet->second.value.list.length; ++n) + workSet.push_back(startSet->second.value.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); + state.forceValue(op->second.value); /* Construct the closure by applying the operator to element of `workSet', adding the result to `workSet', continuing until @@ -143,15 +143,15 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) e->attrs->find(state.symbols.create("key")); if (key == e->attrs->end()) throw EvalError("attribute `key' required"); - state.forceValue(key->second); + state.forceValue(key->second.value); - if (doneKeys.find(key->second) != doneKeys.end()) continue; - doneKeys.insert(key->second); + if (doneKeys.find(key->second.value) != doneKeys.end()) continue; + doneKeys.insert(key->second.value); res.push_back(*e); /* Call the `operator' function with `e' as argument. */ Value call; - mkApp(call, op->second, *e); + mkApp(call, op->second.value, *e); state.forceList(call); /* Add the values returned by the operator to the work set. */ @@ -323,11 +323,11 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) if (attr == args[0]->attrs->end()) throw EvalError("required attribute `name' missing"); string drvName; + Pos & posDrvName(*attr->second.pos); try { - drvName = state.forceStringNoCtx(attr->second); + drvName = state.forceStringNoCtx(attr->second.value); } catch (Error & e) { - e.addPrefix(format("while evaluating the derivation attribute `name' at :\n")); - // !!! % showPos(posDrvName)); + e.addPrefix(format("while evaluating the derivation attribute `name' at %1%:\n") % posDrvName); throw; } @@ -348,9 +348,9 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* The `args' attribute is special: it supplies the command-line arguments to the builder. */ if (key == "args") { - state.forceList(i->second); - for (unsigned int n = 0; n < i->second.list.length; ++n) { - string s = state.coerceToString(*i->second.list.elems[n], context, true); + state.forceList(i->second.value); + for (unsigned int n = 0; n < i->second.value.list.length; ++n) { + string s = state.coerceToString(*i->second.value.list.elems[n], context, true); drv.args.push_back(s); } } @@ -358,7 +358,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* All other attributes are passed to the builder through the environment. */ else { - string s = state.coerceToString(i->second, context, true); + string s = state.coerceToString(i->second.value, context, true); drv.env[key] = s; if (key == "builder") drv.builder = s; else if (i->first == state.sSystem) drv.platform = s; @@ -373,10 +373,10 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) } } catch (Error & e) { - e.addPrefix(format("while evaluating the derivation attribute `%1%' at :\n") - % key /* !!! % showPos(pos) */); - e.addPrefix(format("while instantiating the derivation named `%1%' at :\n") - % drvName /* !!! % showPos(posDrvName) */); + e.addPrefix(format("while evaluating the derivation attribute `%1%' at %2%:\n") + % key % *i->second.pos); + e.addPrefix(format("while instantiating the derivation named `%1%' at %2%:\n") + % drvName % posDrvName); throw; } } @@ -487,8 +487,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* !!! assumes a single output */ state.mkAttrs(v); - mkString((*v.attrs)[state.sOutPath], outPath, singleton(drvPath)); - mkString((*v.attrs)[state.sDrvPath], drvPath, singleton("=" + drvPath)); + mkString((*v.attrs)[state.sOutPath].value, outPath, singleton(drvPath)); + mkString((*v.attrs)[state.sDrvPath].value, drvPath, singleton("=" + drvPath)); } @@ -711,8 +711,9 @@ static void prim_getAttr(EvalState & state, Value * * args, Value & v) Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); if (i == args[1]->attrs->end()) throw EvalError(format("attribute `%1%' missing") % attr); - state.forceValue(i->second); - v = i->second; + // !!! add to stack trace? + state.forceValue(i->second.value); + v = i->second.value; } @@ -764,13 +765,15 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) Bindings::iterator j = v2.attrs->find(state.sName); if (j == v2.attrs->end()) throw TypeError("`name' attribute missing in a call to `listToAttrs'"); - string name = state.forceStringNoCtx(j->second); + string name = state.forceStringNoCtx(j->second.value); j = v2.attrs->find(state.symbols.create("value")); if (j == v2.attrs->end()) throw TypeError("`value' attribute missing in a call to `listToAttrs'"); - mkCopy((*v.attrs)[state.symbols.create(name)], j->second); + Attr & a = (*v.attrs)[state.symbols.create(name)]; + mkCopy(a.value, j->second.value); + a.pos = j->second.pos; } } @@ -787,8 +790,11 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v) foreach (Bindings::iterator, i, *args[1]->attrs) { Bindings::iterator j = args[0]->attrs->find(i->first); - if (j != args[0]->attrs->end()) - mkCopy((*v.attrs)[i->first], i->second); + if (j != args[0]->attrs->end()) { + Attr & a = (*v.attrs)[i->first]; + mkCopy(a.value, i->second.value); + a.pos = i->second.pos; + } } } @@ -817,7 +823,7 @@ static void prim_functionArgs(EvalState & state, Value * * args, Value & v) if (!args[0]->lambda.fun->matchAttrs) return; foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals) - mkBool((*v.attrs)[i->name], i->def); + mkBool((*v.attrs)[i->name].value, i->def); } @@ -1000,8 +1006,8 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v) string name = state.forceStringNoCtx(*args[0]); DrvName parsed(name); state.mkAttrs(v); - mkString((*v.attrs)[state.sName], parsed.name); - mkString((*v.attrs)[state.symbols.create("version")], parsed.version); + mkString((*v.attrs)[state.sName].value, parsed.name); + mkString((*v.attrs)[state.symbols.create("version")].value, parsed.version); } diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index 58e89925ce43..821f715e23c8 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -28,7 +28,8 @@ static void showAttrs(EvalState & state, bool strict, Bindings & attrs, names.insert(i->first); foreach (StringSet::iterator, i, names) { XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); - printValueAsXML(state, strict, attrs[state.symbols.create(*i)], doc, context, drvsSeen); + printValueAsXML(state, strict, attrs[state.symbols.create(*i)].value, + doc, context, drvsSeen); } } @@ -71,12 +72,12 @@ static void printValueAsXML(EvalState & state, bool strict, Value & v, Path drvPath; a = v.attrs->find(state.sDrvPath); - if (a != v.attrs->end() && a->second.type == tString) - xmlAttrs["drvPath"] = drvPath = a->second.string.s; + if (a != v.attrs->end() && a->second.value.type == tString) + xmlAttrs["drvPath"] = drvPath = a->second.value.string.s; a = v.attrs->find(state.sOutPath); - if (a != v.attrs->end() && a->second.type == tString) - xmlAttrs["outPath"] = a->second.string.s; + if (a != v.attrs->end() && a->second.value.type == tString) + xmlAttrs["outPath"] = a->second.value.string.s; XMLOpenElement _(doc, "derivation", xmlAttrs); diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index a0e51cae19c3..72e13fceb191 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -62,19 +62,19 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, manifest.list.elems[n++] = &v; state.mkAttrs(v); - mkString((*v.attrs)[state.sType], "derivation"); - mkString((*v.attrs)[state.sName], i->name); - mkString((*v.attrs)[state.sSystem], i->system); - mkString((*v.attrs)[state.sOutPath], i->queryOutPath(state)); + mkString((*v.attrs)[state.sType].value, "derivation"); + mkString((*v.attrs)[state.sName].value, i->name); + mkString((*v.attrs)[state.sSystem].value, i->system); + mkString((*v.attrs)[state.sOutPath].value, i->queryOutPath(state)); if (drvPath != "") - mkString((*v.attrs)[state.sDrvPath], i->queryDrvPath(state)); + mkString((*v.attrs)[state.sDrvPath].value, i->queryDrvPath(state)); - state.mkAttrs((*v.attrs)[state.sMeta]); + state.mkAttrs((*v.attrs)[state.sMeta].value); MetaInfo meta = i->queryMetaInfo(state); foreach (MetaInfo::const_iterator, j, meta) { - Value & v2((*(*v.attrs)[state.sMeta].attrs)[state.symbols.create(j->first)]); + Value & v2((*(*v.attrs)[state.sMeta].value.attrs)[state.symbols.create(j->first)].value); switch (j->second.type) { case MetaValue::tpInt: mkInt(v2, j->second.intValue); break; case MetaValue::tpString: mkString(v2, j->second.stringValue); break; @@ -116,10 +116,10 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, builder with the manifest as argument. */ Value args, topLevel; state.mkAttrs(args); - mkString((*args.attrs)[state.sSystem], thisSystem); - mkString((*args.attrs)[state.symbols.create("manifest")], + mkString((*args.attrs)[state.sSystem].value, thisSystem); + mkString((*args.attrs)[state.symbols.create("manifest")].value, manifestFile, singleton(manifestFile)); - (*args.attrs)[state.symbols.create("derivations")] = manifest; + (*args.attrs)[state.symbols.create("derivations")].value = manifest; mkApp(topLevel, envBuilder, args); /* Evaluate it. */ -- cgit 1.4.1