about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-04-07T15·47+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-04-07T15·47+0000
commitaf2a372bb000d4d5aeec37e43ee0f6245c1bba54 (patch)
tree7d92b153b255d64c1db807595c9577a43b77f50d
parent9a64454faae2ab4ccedeeaad85a0e094726b4765 (diff)
* Update autoCallFunction() and findAlongAttrPath().
-rw-r--r--src/libexpr/attr-path.cc54
-rw-r--r--src/libexpr/attr-path.hh4
-rw-r--r--src/libexpr/common-opts.cc14
-rw-r--r--src/libexpr/common-opts.hh2
-rw-r--r--src/libexpr/eval.cc64
-rw-r--r--src/libexpr/eval.hh34
-rw-r--r--src/libexpr/get-drvs.cc9
-rw-r--r--src/libexpr/get-drvs.hh2
-rw-r--r--src/nix-env/nix-env.cc22
-rw-r--r--src/nix-instantiate/nix-instantiate.cc103
10 files changed, 120 insertions, 188 deletions
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<DrvInfo> 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,