* 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 /* Evaluate an expression; the result must be a value reference. */
non-expression reference. */ static Hash evalHash(Expr e)
static Hash evalExternal(Expr e)
{ {
e = evalValue(e); e = evalValue(e);
char * s; char * s;
if (ATmatch(e, "External(<str>)", &s)) return parseHash(s); if (ATmatch(e, "Hash(<str>)", &s)) return parseHash(s);
else throw badTerm("external non-expression value expected", e); else throw badTerm("value reference expected", e);
} }
@ -244,7 +243,7 @@ void evalArgs(ATermList args, ATermList & argsNF, Environment & env)
char * s; char * s;
if (ATmatch(eVal, "Str(<str>)", &s)) { if (ATmatch(eVal, "Str(<str>)", &s)) {
env[name] = s; env[name] = s;
} else if (ATmatch(eVal, "External(<str>)", &s)) { } else if (ATmatch(eVal, "Hash(<str>)", &s)) {
env[name] = queryValuePath(parseHash(s)); env[name] = queryValuePath(parseHash(s));
} else throw badTerm("invalid argument value", eVal); } else throw badTerm("invalid argument value", eVal);
@ -260,7 +259,7 @@ void evalArgs(ATermList args, ATermList & argsNF, Environment & env)
Expr evalValue(Expr e) Expr evalValue(Expr e)
{ {
char * s; char * s;
Expr eBuildPlatform, eProg; Expr eBuildPlatform, eProg, e2;
ATermList args; ATermList args;
/* Normal forms. */ /* Normal forms. */
@ -269,14 +268,20 @@ Expr evalValue(Expr e)
ATmatch(e, "Bool(False)")) ATmatch(e, "Bool(False)"))
return e; return e;
/* External expressions. */ /* Value references. */
if (ATmatch(e, "Hash(<str>)", &s)) {
/* External non-expressions. */
if (ATmatch(e, "External(<str>)", &s)) {
parseHash(s); /* i.e., throw exception if not valid */ parseHash(s); /* i.e., throw exception if not valid */
return e; 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. */ /* Execution primitive. */
if (ATmatch(e, "Exec(<term>, <term>, [<list>])", if (ATmatch(e, "Exec(<term>, <term>, [<list>])",
@ -286,14 +291,14 @@ Expr evalValue(Expr e)
checkPlatform(buildPlatform); checkPlatform(buildPlatform);
Hash prog = evalExternal(eProg); Hash prog = evalHash(eProg);
Environment env; Environment env;
ATermList argsNF; ATermList argsNF;
evalArgs(args, argsNF, env); evalArgs(args, argsNF, env);
Hash sourceHash = hashExpr( Hash sourceHash = hashExpr(
ATmake("Exec(Str(<str>), External(<str>), [])", ATmake("Exec(Str(<str>), Hash(<str>), [])",
buildPlatform.c_str(), ((string) prog).c_str())); buildPlatform.c_str(), ((string) prog).c_str()));
/* Do we know a normal form for sourceHash? */ /* Do we know a normal form for sourceHash? */
@ -310,7 +315,7 @@ Expr evalValue(Expr e)
(string) sourceHash + "-nf", buildPlatform, prog, env); (string) sourceHash + "-nf", buildPlatform, prog, env);
} }
return ATmake("External(<str>)", ((string) targetHash).c_str()); return ATmake("Hash(<str>)", ((string) targetHash).c_str());
} }
/* Barf. */ /* Barf. */

View File

@ -12,24 +12,28 @@ using namespace std;
/* Abstract syntax of Nix values: /* Abstract syntax of Nix values:
e := Hash(h) -- reference to expression value e := Deref(e) -- external expression
| External(h) -- reference to non-expression value | Hash(h) -- value reference
| Str(s) -- string constant | Str(s) -- string constant
| Bool(b) -- boolean constant | Bool(b) -- boolean constant
| Var(x) -- variable
| App(e, e) -- application | App(e, e) -- application
| Lam(x, e) -- lambda abstraction | Lam(x, e) -- lambda abstraction
| Exec(platform, e, [Arg(e, e)]) | Exec(platform, e, [Arg(e, e)])
-- primitive; execute e with args e* on platform -- 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 Semantics
Each rule given as eval(e) => e', i.e., expression e has a normal Each rule given as eval(e) => e', i.e., expression e has a normal
form e'. 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)) eval(App(e1, e2)) => eval(App(e1', e2))
where e1' = eval(e1) where e1' = eval(e1)
@ -37,8 +41,7 @@ using namespace std;
eval(App(Lam(var, body), arg)) => eval(App(Lam(var, body), arg)) =>
eval(subst(var, arg, body)) eval(subst(var, arg, body))
eval(Exec(platform, prog, args)) => eval(Exec(platform, prog, args)) => Hash(h)
(External(h), h)
where where
fn = ... name of the output (random or by hashing expr) ... fn = ... name of the output (random or by hashing expr) ...
h = h =
@ -47,12 +50,12 @@ using namespace std;
, getFile(eval(prog)) , getFile(eval(prog))
, map(makeArg . eval, args) , map(makeArg . eval, args)
) then ) then
hashExternal(fn) hashPath(fn)
else else
undef undef
... register ... ... 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), (Str(s), _))) => (nm, s)
makeArg(Arg(Str(nm), (Bool(True), _))) => (nm, "1") makeArg(Arg(Str(nm), (Bool(True), _))) => (nm, "1")
makeArg(Arg(Str(nm), (Bool(False), _))) => (nm, undef) makeArg(Arg(Str(nm), (Bool(False), _))) => (nm, undef)
@ -60,7 +63,7 @@ using namespace std;
getFile :: Hash -> FileName getFile :: Hash -> FileName
loadExpr :: Hash -> FileName loadExpr :: Hash -> FileName
hashExpr :: Expr -> Hash hashExpr :: Expr -> Hash
hashExternal :: FileName -> Hash hashPath :: FileName -> Hash
exec :: FileName -> Platform -> FileName -> [(String, String)] -> Status exec :: FileName -> Platform -> FileName -> [(String, String)] -> Status
*/ */

View File

@ -21,9 +21,13 @@ extern string dbRefs;
/* dbNFs :: Hash -> Hash /* dbNFs :: Hash -> Hash
Each pair (h1, h2) in this mapping records the fact that the value Each pair (h1, h2) in this mapping records the fact that the normal
referenced by h2 is a normal form obtained by evaluating the value form of an expression with hash h1 is Hash(h2).
referenced by value h1.
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; extern string dbNFs;

View File

@ -72,7 +72,7 @@ void runTests()
Hash builder1 = addValue("./test-builder-1.sh"); 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()); thisSystem.c_str(), ((string) builder1).c_str());
evalTest(e1); evalTest(e1);
@ -80,10 +80,15 @@ void runTests()
Hash builder2 = addValue("./test-builder-2.sh"); Hash builder2 = addValue("./test-builder-2.sh");
Expr e2 = ATmake( 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); thisSystem.c_str(), ((string) builder2).c_str(), e1);
evalTest(e2); evalTest(e2);
Hash h3 = addValue("./test-expr.nix");
Expr e3 = ATmake("Deref(Hash(<str>))", ((string) h3).c_str());
evalTest(e3);
} }