* Derefencing of hashed expressions.

This commit is contained in:
Eelco Dolstra 2003-06-17 15:45:43 +00:00
parent a7ab242fb4
commit 6656993f83
4 changed files with 45 additions and 28 deletions

View file

@ -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. */

View file

@ -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
*/

View file

@ -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;

View file

@ -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);
}