about summary refs log tree commit diff
path: root/src/libexpr
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 /src/libexpr
parent9a64454faae2ab4ccedeeaad85a0e094726b4765 (diff)
* Update autoCallFunction() and findAlongAttrPath().
Diffstat (limited to 'src/libexpr')
-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
8 files changed, 81 insertions, 102 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);
 
  
 }