about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/eval.cc33
-rw-r--r--src/eval.hh21
-rw-r--r--src/globals.hh10
-rw-r--r--src/test.cc9
4 files changed, 45 insertions, 28 deletions
diff --git a/src/eval.cc b/src/eval.cc
index ad6f5ae2a2a7..3f8aa7b2326b 100644
--- a/src/eval.cc
+++ b/src/eval.cc
@@ -217,14 +217,13 @@ static string evalString(Expr e)
 }
 
 
-/* Evaluate an expression; the result must be a external
-   non-expression reference. */
-static Hash evalExternal(Expr e)
+/* Evaluate an expression; the result must be a value reference. */
+static Hash evalHash(Expr e)
 {
     e = evalValue(e);
     char * s;
-    if (ATmatch(e, "External(<str>)", &s)) return parseHash(s);
-    else throw badTerm("external non-expression value expected", e);
+    if (ATmatch(e, "Hash(<str>)", &s)) return parseHash(s);
+    else throw badTerm("value reference expected", e);
 }
 
 
@@ -244,7 +243,7 @@ void evalArgs(ATermList args, ATermList & argsNF, Environment & env)
         char * s;
         if (ATmatch(eVal, "Str(<str>)", &s)) {
             env[name] = s;
-        } else if (ATmatch(eVal, "External(<str>)", &s)) {
+        } else if (ATmatch(eVal, "Hash(<str>)", &s)) {
             env[name] = queryValuePath(parseHash(s));
         } else throw badTerm("invalid argument value", eVal);
 
@@ -260,7 +259,7 @@ void evalArgs(ATermList args, ATermList & argsNF, Environment & env)
 Expr evalValue(Expr e)
 {
     char * s;
-    Expr eBuildPlatform, eProg;
+    Expr eBuildPlatform, eProg, e2;
     ATermList args;
 
     /* Normal forms. */
@@ -269,14 +268,20 @@ Expr evalValue(Expr e)
         ATmatch(e, "Bool(False)"))
         return e;
 
-    /* External expressions. */
-
-    /* External non-expressions. */
-    if (ATmatch(e, "External(<str>)", &s)) {
+    /* Value references. */
+    if (ATmatch(e, "Hash(<str>)", &s)) {
         parseHash(s); /* i.e., throw exception if not valid */
         return e;
     }
 
+    /* External expression. */
+    if (ATmatch(e, "Deref(<term>)", &e2)) {
+        string fn = queryValuePath(evalHash(e2));
+        ATerm e3 = ATreadFromNamedFile(fn.c_str());
+        if (!e3) throw Error("reading aterm from " + fn);
+        return e3;
+    }
+
     /* Execution primitive. */
 
     if (ATmatch(e, "Exec(<term>, <term>, [<list>])",
@@ -286,14 +291,14 @@ Expr evalValue(Expr e)
 
         checkPlatform(buildPlatform);
 
-        Hash prog = evalExternal(eProg);
+        Hash prog = evalHash(eProg);
 
         Environment env;
         ATermList argsNF;
         evalArgs(args, argsNF, env);
 
         Hash sourceHash = hashExpr(
-            ATmake("Exec(Str(<str>), External(<str>), [])",
+            ATmake("Exec(Str(<str>), Hash(<str>), [])",
                 buildPlatform.c_str(), ((string) prog).c_str()));
 
         /* Do we know a normal form for sourceHash? */
@@ -310,7 +315,7 @@ Expr evalValue(Expr e)
                 (string) sourceHash + "-nf", buildPlatform, prog, env);
         }
 
-        return ATmake("External(<str>)", ((string) targetHash).c_str());
+        return ATmake("Hash(<str>)", ((string) targetHash).c_str());
     }
 
     /* Barf. */
diff --git a/src/eval.hh b/src/eval.hh
index 1a8edcfdea9e..719edb143354 100644
--- a/src/eval.hh
+++ b/src/eval.hh
@@ -12,24 +12,28 @@ using namespace std;
 
 /* Abstract syntax of Nix values:
 
-   e := Hash(h) -- reference to expression value
-      | External(h) -- reference to non-expression value
+   e := Deref(e) -- external expression
+      | Hash(h) -- value reference
       | Str(s) -- string constant
       | Bool(b) -- boolean constant
+      | Var(x) -- variable
       | App(e, e) -- application
       | Lam(x, e) -- lambda abstraction
       | Exec(platform, e, [Arg(e, e)])
           -- primitive; execute e with args e* on platform
       ;
 
+   TODO: Deref(e) allows computed external expressions, which might be
+   too expressive; perhaps this should be Deref(h).
+
    Semantics
 
    Each rule given as eval(e) => e', i.e., expression e has a normal
    form e'.
 
-   eval(Hash(h)) => eval(loadExpr(h))
+   eval(Deref(Hash(h))) => eval(loadExpr(h))
 
-   eval(External(h)) => External(h) # idem for Str, Bool
+   eval(Hash(h)) => Hash(h) # idem for Str, Bool
 
    eval(App(e1, e2)) => eval(App(e1', e2))
      where e1' = eval(e1)
@@ -37,8 +41,7 @@ using namespace std;
    eval(App(Lam(var, body), arg)) =>
      eval(subst(var, arg, body))
 
-   eval(Exec(platform, prog, args)) =>
-     (External(h), h)
+   eval(Exec(platform, prog, args)) => Hash(h)
      where
        fn = ... name of the output (random or by hashing expr) ...
        h =
@@ -47,12 +50,12 @@ using namespace std;
                 , getFile(eval(prog))
                 , map(makeArg . eval, args)
                 ) then
-           hashExternal(fn)
+           hashPath(fn)
          else
            undef
        ... register ...
 
-   makeArg(Arg(Str(nm), (External(h), h))) => (nm, getFile(h))
+   makeArg(Arg(Str(nm), (Hash(h), h))) => (nm, getFile(h))
    makeArg(Arg(Str(nm), (Str(s), _))) => (nm, s)
    makeArg(Arg(Str(nm), (Bool(True), _))) => (nm, "1")
    makeArg(Arg(Str(nm), (Bool(False), _))) => (nm, undef)
@@ -60,7 +63,7 @@ using namespace std;
    getFile :: Hash -> FileName
    loadExpr :: Hash -> FileName
    hashExpr :: Expr -> Hash 
-   hashExternal :: FileName -> Hash
+   hashPath :: FileName -> Hash
    exec :: FileName -> Platform -> FileName -> [(String, String)] -> Status
 */
 
diff --git a/src/globals.hh b/src/globals.hh
index d4fe4b370f2a..b81a787147c3 100644
--- a/src/globals.hh
+++ b/src/globals.hh
@@ -21,9 +21,13 @@ extern string dbRefs;
 
 /* dbNFs :: Hash -> Hash
 
-   Each pair (h1, h2) in this mapping records the fact that the value
-   referenced by h2 is a normal form obtained by evaluating the value
-   referenced by value h1.
+   Each pair (h1, h2) in this mapping records the fact that the normal
+   form of an expression with hash h1 is Hash(h2).
+
+   TODO: maybe this should be that the normal form of an expression
+   with hash h1 is an expression with hash h2; this would be more
+   general, but would require us to store lots of small expressions in
+   the file system just to support the caching mechanism.
 */
 extern string dbNFs;
 
diff --git a/src/test.cc b/src/test.cc
index 56414956202c..39d4b333fa2f 100644
--- a/src/test.cc
+++ b/src/test.cc
@@ -72,7 +72,7 @@ void runTests()
 
     Hash builder1 = addValue("./test-builder-1.sh");
 
-    Expr e1 = ATmake("Exec(Str(<str>), External(<str>), [])",
+    Expr e1 = ATmake("Exec(Str(<str>), Hash(<str>), [])",
         thisSystem.c_str(), ((string) builder1).c_str());
 
     evalTest(e1);
@@ -80,10 +80,15 @@ void runTests()
     Hash builder2 = addValue("./test-builder-2.sh");
 
     Expr e2 = ATmake(
-        "Exec(Str(<str>), External(<str>), [Tup(Str(\"src\"), <term>)])",
+        "Exec(Str(<str>), Hash(<str>), [Tup(Str(\"src\"), <term>)])",
         thisSystem.c_str(), ((string) builder2).c_str(), e1);
 
     evalTest(e2);
+
+    Hash h3 = addValue("./test-expr.nix");
+    Expr e3 = ATmake("Deref(Hash(<str>))", ((string) h3).c_str());
+
+    evalTest(e3);
 }