* Memoize the evaluation of Fix expressions to speed up computation.

This commit is contained in:
Eelco Dolstra 2003-07-21 08:55:49 +00:00
parent 7984cfc7c1
commit 401452e57a
2 changed files with 47 additions and 25 deletions

View File

@ -8,15 +8,24 @@
typedef ATerm Expr; typedef ATerm Expr;
typedef map<ATerm, ATerm> NormalForms;
static Strings searchDirs; struct EvalState
{
Strings searchDirs;
NormalForms normalForms;
};
static string searchPath(string relPath) static Expr evalFile(EvalState & state, string fileName);
static Expr evalExpr(EvalState & state, Expr e);
static string searchPath(const Strings & searchDirs, string relPath)
{ {
if (string(relPath, 0, 1) == "/") return relPath; if (string(relPath, 0, 1) == "/") return relPath;
for (Strings::iterator i = searchDirs.begin(); for (Strings::const_iterator i = searchDirs.begin();
i != searchDirs.end(); i++) i != searchDirs.end(); i++)
{ {
string path = *i + "/" + relPath; string path = *i + "/" + relPath;
@ -29,9 +38,6 @@ static string searchPath(string relPath)
} }
static Expr evalFile(string fileName);
static Expr substExpr(string x, Expr rep, Expr e) static Expr substExpr(string x, Expr rep, Expr e)
{ {
char * s; char * s;
@ -98,7 +104,7 @@ static Expr substExprMany(ATermList formals, ATermList args, Expr body)
} }
static Expr evalExpr(Expr e) static Expr evalExpr2(EvalState & state, Expr e)
{ {
char * s1; char * s1;
Expr e1, e2, e3, e4; Expr e1, e2, e3, e4;
@ -119,21 +125,22 @@ static Expr evalExpr(Expr e)
/* Application. */ /* Application. */
if (ATmatch(e, "App(<term>, [<list>])", &e1, &e2)) { if (ATmatch(e, "App(<term>, [<list>])", &e1, &e2)) {
e1 = evalExpr(e1); e1 = evalExpr(state, e1);
if (!ATmatch(e1, "Function([<list>], <term>)", &e3, &e4)) if (!ATmatch(e1, "Function([<list>], <term>)", &e3, &e4))
throw badTerm("expecting a function", e1); throw badTerm("expecting a function", e1);
return evalExpr(substExprMany((ATermList) e3, (ATermList) e2, e4)); return evalExpr(state,
substExprMany((ATermList) e3, (ATermList) e2, e4));
} }
/* Fix inclusion. */ /* Fix inclusion. */
if (ATmatch(e, "IncludeFix(<str>)", &s1)) { if (ATmatch(e, "IncludeFix(<str>)", &s1)) {
string fileName(s1); string fileName(s1);
return evalFile(s1); return evalFile(state, s1);
} }
/* Relative files. */ /* Relative files. */
if (ATmatch(e, "Relative(<str>)", &s1)) { if (ATmatch(e, "Relative(<str>)", &s1)) {
string srcPath = searchPath(s1); string srcPath = searchPath(state.searchDirs, s1);
string dstPath; string dstPath;
FSId id; FSId id;
addToStore(srcPath, dstPath, id, true); addToStore(srcPath, dstPath, id, true);
@ -160,7 +167,7 @@ static Expr evalExpr(Expr e)
ATerm bnd = ATgetFirst(bnds); ATerm bnd = ATgetFirst(bnds);
if (!ATmatch(bnd, "(<str>, <term>)", &s1, &e1)) if (!ATmatch(bnd, "(<str>, <term>)", &s1, &e1))
throw badTerm("binding expected", bnd); throw badTerm("binding expected", bnd);
bndMap[s1] = evalExpr(e1); bndMap[s1] = evalExpr(state, e1);
bnds = ATgetNext(bnds); bnds = ATgetNext(bnds);
} }
@ -218,7 +225,7 @@ static Expr evalExpr(Expr e)
/* BaseName primitive function. */ /* BaseName primitive function. */
if (ATmatch(e, "BaseName(<term>)", &e1)) { if (ATmatch(e, "BaseName(<term>)", &e1)) {
e1 = evalExpr(e1); e1 = evalExpr(state, e1);
if (!ATmatch(e1, "<str>", &s1)) if (!ATmatch(e1, "<str>", &s1))
throw badTerm("string expected", e1); throw badTerm("string expected", e1);
return ATmake("<str>", baseNameOf(s1).c_str()); return ATmake("<str>", baseNameOf(s1).c_str());
@ -229,22 +236,37 @@ static Expr evalExpr(Expr e)
} }
static Expr evalFile(string relPath) static Expr evalExpr(EvalState & state, Expr e)
{ {
string path = searchPath(relPath); /* Consult the memo table to quickly get the normal form of
previously evaluated expressions. */
NormalForms::iterator i = state.normalForms.find(e);
if (i != state.normalForms.end()) return i->second;
/* Otherwise, evaluate and memoize. */
Expr nf = evalExpr2(state, e);
state.normalForms[e] = nf;
return nf;
}
static Expr evalFile(EvalState & state, string relPath)
{
string path = searchPath(state.searchDirs, relPath);
Expr e = ATreadFromNamedFile(path.c_str()); Expr e = ATreadFromNamedFile(path.c_str());
if (!e) if (!e)
throw Error(format("unable to read a term from `%1%'") % path); throw Error(format("unable to read a term from `%1%'") % path);
return evalExpr(e); return evalExpr(state, e);
} }
void run(Strings args) void run(Strings args)
{ {
EvalState state;
Strings files; Strings files;
searchDirs.push_back("."); state.searchDirs.push_back(".");
searchDirs.push_back(nixDataDir + "/fix"); state.searchDirs.push_back(nixDataDir + "/fix");
for (Strings::iterator it = args.begin(); for (Strings::iterator it = args.begin();
it != args.end(); ) it != args.end(); )
@ -254,7 +276,7 @@ void run(Strings args)
if (arg == "--includedir" || arg == "-I") { if (arg == "--includedir" || arg == "-I") {
if (it == args.end()) if (it == args.end())
throw UsageError(format("argument required in `%1%'") % arg); throw UsageError(format("argument required in `%1%'") % arg);
searchDirs.push_back(*it++); state.searchDirs.push_back(*it++);
} }
else if (arg[0] == '-') else if (arg[0] == '-')
throw UsageError(format("unknown flag `%1%`") % arg); throw UsageError(format("unknown flag `%1%`") % arg);
@ -267,7 +289,7 @@ void run(Strings args)
for (Strings::iterator it = files.begin(); for (Strings::iterator it = files.begin();
it != files.end(); it++) it != files.end(); it++)
{ {
Expr e = evalFile(*it); Expr e = evalFile(state, *it);
char * s; char * s;
if (ATmatch(e, "FSId(<str>)", &s)) { if (ATmatch(e, "FSId(<str>)", &s)) {
cout << format("%1%\n") % s; cout << format("%1%\n") % s;

View File

@ -117,7 +117,7 @@ void runTests()
((string) builder1id).c_str(), ((string) builder1id).c_str(),
builder1fn.c_str(), builder1fn.c_str(),
((string) builder1id).c_str()); ((string) builder1id).c_str());
FSId fs1id = writeTerm(fs1, "", 0); FSId fs1id = writeTerm(fs1, "");
realise(fs1id); realise(fs1id);
realise(fs1id); realise(fs1id);
@ -127,7 +127,7 @@ void runTests()
((string) builder1id).c_str(), ((string) builder1id).c_str(),
(builder1fn + "_bla").c_str(), (builder1fn + "_bla").c_str(),
((string) builder1id).c_str()); ((string) builder1id).c_str());
FSId fs2id = writeTerm(fs2, "", 0); FSId fs2id = writeTerm(fs2, "");
realise(fs2id); realise(fs2id);
realise(fs2id); realise(fs2id);
@ -143,7 +143,7 @@ void runTests()
thisSystem.c_str(), thisSystem.c_str(),
out1fn.c_str()); out1fn.c_str());
debug(printTerm(fs3)); debug(printTerm(fs3));
FSId fs3id = writeTerm(fs3, "", 0); FSId fs3id = writeTerm(fs3, "");
realise(fs3id); realise(fs3id);
realise(fs3id); realise(fs3id);
@ -158,7 +158,7 @@ void runTests()
((string) builder4id).c_str(), ((string) builder4id).c_str(),
builder4fn.c_str(), builder4fn.c_str(),
((string) builder4id).c_str()); ((string) builder4id).c_str());
FSId fs4id = writeTerm(fs4, "", 0); FSId fs4id = writeTerm(fs4, "");
realise(fs4id); realise(fs4id);
@ -174,7 +174,7 @@ void runTests()
out5fn.c_str(), out5fn.c_str(),
((string) builder4fn).c_str()); ((string) builder4fn).c_str());
debug(printTerm(fs5)); debug(printTerm(fs5));
FSId fs5id = writeTerm(fs5, "", 0); FSId fs5id = writeTerm(fs5, "");
realise(fs5id); realise(fs5id);
realise(fs5id); realise(fs5id);