aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-02-04 16:03:29 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-02-04 16:03:29 +0000
commit9b44480612dd30a7292ec94a88e4018b8f18e3f0 (patch)
tree0c83114806a4f7724a5dd8dcb0694103e70acb71
parentc4f7ae4aa5fc7071cfa853ec5d75aaf00e7a97fc (diff)
* Use a map to lookup primops.
* Various performance improvements in the evaluator. * Do not link against unused (and missing!) libraries (-lsglr, etc.).
-rw-r--r--src/libexpr/eval.cc68
-rw-r--r--src/libexpr/eval.hh11
-rw-r--r--src/libexpr/nixexpr.cc23
-rw-r--r--src/libexpr/nixexpr.hh9
-rw-r--r--src/libexpr/parser.cc24
-rw-r--r--src/libexpr/parser.hh6
-rw-r--r--src/libexpr/primops.cc12
-rw-r--r--src/libexpr/primops.hh6
-rw-r--r--src/nix-env/Makefile.am2
-rw-r--r--src/nix-env/main.cc5
-rw-r--r--src/nix-instantiate/Makefile.am2
-rw-r--r--src/nix-instantiate/main.cc34
12 files changed, 127 insertions, 75 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index bbb1393f8..802b83aa1 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -3,12 +3,52 @@
#include "primops.hh"
+static void addPrimOp(ATermMap & map, const string & name, void * f)
+{
+ map.set(name, (ATerm) ATmakeBlob(0, f));
+}
+
+
+static void * lookupPrimOp(ATermMap & map, ATerm name)
+{
+ ATermBlob b = (ATermBlob) map.get(name);
+ if (!b) return 0;
+ return ATgetBlobData(b);
+}
+
+
EvalState::EvalState()
- : normalForms(32768, 75)
+ : normalForms(32768, 50)
{
blackHole = ATmake("BlackHole()");
if (!blackHole) throw Error("cannot build black hole");
+
nrEvaluated = nrCached = 0;
+
+ addPrimOp0("true", primTrue);
+ addPrimOp0("false", primFalse);
+ addPrimOp0("null", primNull);
+
+ addPrimOp1("import", primImport);
+ addPrimOp1("derivation", primDerivation);
+ addPrimOp1("baseNameOf", primBaseNameOf);
+ addPrimOp1("toString", primToString);
+ addPrimOp1("isNull", primIsNull);
+
+ primOpsAll.add(primOps0);
+ primOpsAll.add(primOps1);
+}
+
+
+void EvalState::addPrimOp0(const string & name, PrimOp0 primOp)
+{
+ addPrimOp(primOps0, name, (void *) primOp);
+}
+
+
+void EvalState::addPrimOp1(const string & name, PrimOp1 primOp)
+{
+ addPrimOp(primOps1, name, (void *) primOp);
}
@@ -130,7 +170,7 @@ Expr evalExpr2(EvalState & state, Expr e)
{
ATMatcher m;
Expr e1, e2, e3, e4;
- string s1;
+ ATerm name;
/* Normal forms. */
if (atMatch(m, e) >> "Str" ||
@@ -144,11 +184,12 @@ Expr evalExpr2(EvalState & state, Expr e)
return e;
/* Any encountered variables must be undeclared or primops. */
- if (atMatch(m, e) >> "Var" >> s1) {
- if (s1 == "null") return primNull(state);
- if (s1 == "true") return ATmake("Bool(True)");
- if (s1 == "false") return ATmake("Bool(False)");
- return e;
+ if (atMatch(m, e) >> "Var" >> name) {
+ PrimOp0 primOp = (PrimOp0) lookupPrimOp(state.primOps0, name);
+ if (primOp)
+ return primOp(state);
+ else
+ return e;
}
/* Function application. */
@@ -160,13 +201,9 @@ Expr evalExpr2(EvalState & state, Expr e)
e1 = evalExpr(state, e1);
/* Is it a primop or a function? */
- if (atMatch(m, e1) >> "Var" >> s1) {
- if (s1 == "import") return primImport(state, e2);
- if (s1 == "derivation") return primDerivation(state, e2);
- if (s1 == "toString") return primToString(state, e2);
- if (s1 == "baseNameOf") return primBaseNameOf(state, e2);
- if (s1 == "isNull") return primIsNull(state, e2);
- else throw badTerm("undefined variable/primop", e1);
+ if (atMatch(m, e1) >> "Var" >> name) {
+ PrimOp1 primOp = (PrimOp1) lookupPrimOp(state.primOps1, name);
+ if (primOp) return primOp(state, e2); else abort();
}
else if (atMatch(m, e1) >> "Function" >> formals >> e4)
@@ -177,6 +214,7 @@ Expr evalExpr2(EvalState & state, Expr e)
}
/* Attribute selection. */
+ string s1;
if (atMatch(m, e) >> "Select" >> e1 >> s1) {
Expr a = queryAttr(evalExpr(state, e1), s1);
if (!a) throw badTerm(format("missing attribute `%1%'") % s1, e);
@@ -261,7 +299,7 @@ Expr evalExpr(EvalState & state, Expr e)
Expr evalFile(EvalState & state, const Path & path)
{
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
- Expr e = parseExprFromFile(path);
+ Expr e = parseExprFromFile(state, path);
return evalExpr(state, e);
}
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 0bc052676..34ac467f1 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -11,9 +11,17 @@
typedef map<Path, PathSet> DrvPaths;
typedef map<Path, Hash> DrvHashes;
+struct EvalState;
+typedef Expr (* PrimOp0) (EvalState &);
+typedef Expr (* PrimOp1) (EvalState &, Expr arg);
+
+
struct EvalState
{
ATermMap normalForms;
+ ATermMap primOps0; /* nullary primops */
+ ATermMap primOps1; /* unary primops */
+ ATermMap primOpsAll;
DrvPaths drvPaths;
DrvHashes drvHashes; /* normalised derivation hashes */
Expr blackHole;
@@ -22,6 +30,9 @@ struct EvalState
unsigned int nrCached;
EvalState();
+
+ void addPrimOp0(const string & name, PrimOp0 primOp);
+ void addPrimOp1(const string & name, PrimOp1 primOp);
};
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 92027a70e..7739e99a9 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -20,8 +20,7 @@ ATermMap::ATermMap(const ATermMap & map)
table = ATtableCreate(ATgetLength(keys), maxLoadPct);
if (!table) throw Error("cannot create ATerm table");
- for (ATermIterator i(keys); i; ++i)
- set(*i, map.get(*i));
+ add(map, keys);
}
@@ -75,6 +74,26 @@ ATermList ATermMap::keys() const
}
+void ATermMap::add(const ATermMap & map)
+{
+ ATermList keys = map.keys();
+ add(map, keys);
+}
+
+
+void ATermMap::add(const ATermMap & map, ATermList & keys)
+{
+ for (ATermIterator i(keys); i; ++i)
+ set(*i, map.get(*i));
+}
+
+
+void ATermMap::reset()
+{
+ ATtableReset(table);
+}
+
+
ATerm string2ATerm(const string & s)
{
return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue));
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 26c29a2f3..924f8b912 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -23,7 +23,7 @@ private:
ATermTable table;
public:
- ATermMap(unsigned int initialSize = 16, unsigned int maxLoadPct = 75);
+ ATermMap(unsigned int initialSize = 64, unsigned int maxLoadPct = 75);
ATermMap(const ATermMap & map);
~ATermMap();
@@ -37,6 +37,13 @@ public:
void remove(const string & key);
ATermList keys() const;
+
+ void add(const ATermMap & map);
+
+ void reset();
+
+private:
+ void add(const ATermMap & map, ATermList & keys);
};
diff --git a/src/libexpr/parser.cc b/src/libexpr/parser.cc
index 0a550fb35..68b367340 100644
--- a/src/libexpr/parser.cc
+++ b/src/libexpr/parser.cc
@@ -66,7 +66,8 @@ int yyparse(yyscan_t scanner, ParseData * data);
}
-static Expr parse(const char * text, const string & location,
+static Expr parse(EvalState & state,
+ const char * text, const string & location,
const Path & basePath)
{
yyscan_t scanner;
@@ -81,18 +82,8 @@ static Expr parse(const char * text, const string & location,
if (res) throw Error(data.error);
- ATermMap primOps;
- primOps.set("import", (ATerm) ATempty);
- primOps.set("derivation", (ATerm) ATempty);
- primOps.set("true", (ATerm) ATempty);
- primOps.set("false", (ATerm) ATempty);
- primOps.set("null", (ATerm) ATempty);
- primOps.set("isNull", (ATerm) ATempty);
- primOps.set("toString", (ATerm) ATempty);
- primOps.set("baseNameOf", (ATerm) ATempty);
-
try {
- checkVarDefs(primOps, data.result);
+ checkVarDefs(state.primOpsAll, data.result);
} catch (Error & e) {
throw Error(format("%1%, in %2%") % e.msg() % location);
}
@@ -101,7 +92,7 @@ static Expr parse(const char * text, const string & location,
}
-Expr parseExprFromFile(Path path)
+Expr parseExprFromFile(EvalState & state, Path path)
{
assert(path[0] == '/');
@@ -137,11 +128,12 @@ Expr parseExprFromFile(Path path)
readFull(fd, (unsigned char *) text, st.st_size);
text[st.st_size] = 0;
- return parse(text, "`" + path + "'", dirOf(path));
+ return parse(state, text, "`" + path + "'", dirOf(path));
}
-Expr parseExprFromString(const string & s, const Path & basePath)
+Expr parseExprFromString(EvalState & state,
+ const string & s, const Path & basePath)
{
- return parse(s.c_str(), "(string)", basePath);
+ return parse(state, s.c_str(), "(string)", basePath);
}
diff --git a/src/libexpr/parser.hh b/src/libexpr/parser.hh
index 461dae08c..2af5385f6 100644
--- a/src/libexpr/parser.hh
+++ b/src/libexpr/parser.hh
@@ -1,15 +1,15 @@
#ifndef __PARSER_H
#define __PARSER_H
-#include "nixexpr.hh"
+#include "eval.hh"
/* Parse a Nix expression from the specified file. If `path' refers
to a directory, the "/default.nix" is appended. */
-Expr parseExprFromFile(Path path);
+Expr parseExprFromFile(EvalState & state, Path path);
/* Parse a Nix expression from the specified string. */
-Expr parseExprFromString(const string & s,
+Expr parseExprFromString(EvalState & state, const string & s,
const Path & basePath);
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index d1c398a34..92683fcac 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -245,6 +245,18 @@ Expr primToString(EvalState & state, Expr arg)
}
+Expr primTrue(EvalState & state)
+{
+ return ATmake("Bool(True)");
+}
+
+
+Expr primFalse(EvalState & state)
+{
+ return ATmake("Bool(False)");
+}
+
+
Expr primNull(EvalState & state)
{
return ATmake("Null");
diff --git a/src/libexpr/primops.hh b/src/libexpr/primops.hh
index 76d587afd..6b9722dac 100644
--- a/src/libexpr/primops.hh
+++ b/src/libexpr/primops.hh
@@ -8,7 +8,7 @@
argument. */
Expr primImport(EvalState & state, Expr arg);
-/* Construct (as a unobservable) side effect) a Nix derivation
+/* Construct (as a unobservable side effect) a Nix derivation
expression that performs the derivation described by the argument
set. Returns the original set extended with the following
attributes: `outPath' containing the primary output path of the
@@ -24,6 +24,10 @@ Expr primBaseNameOf(EvalState & state, Expr arg);
/* Convert the argument (which can be a path or a uri) to a string. */
Expr primToString(EvalState & state, Expr arg);
+/* Boolean constructors. */
+Expr primTrue(EvalState & state);
+Expr primFalse(EvalState & state);
+
/* Return the null value. */
Expr primNull(EvalState & state);
diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am
index 53d8d9b02..bfe7369c6 100644
--- a/src/nix-env/Makefile.am
+++ b/src/nix-env/Makefile.am
@@ -4,7 +4,7 @@ nix_env_SOURCES = main.cc help.txt
nix_env_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
../libstore/libstore.a ../libutil/libutil.a \
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
- -lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
+ -lATerm
main.o: help.txt.hh
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 0fd4ec63a..3810e9144 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -102,7 +102,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs)
{
- Expr e = parseExprFromFile(absPath(nePath));
+ Expr e = parseExprFromFile(state, absPath(nePath));
if (!parseDerivations(state, e, drvs))
throw badTerm("expected set of derivations", e);
}
@@ -193,7 +193,8 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
const Path & linkPath)
{
/* Get the environment builder expression. */
- Expr envBuilder = parseExprFromFile(nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */
+ Expr envBuilder = parseExprFromFile(state,
+ nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */
/* Construct the whole top level derivation. */
ATermList inputs = ATempty;
diff --git a/src/nix-instantiate/Makefile.am b/src/nix-instantiate/Makefile.am
index d04fdb376..0726d1296 100644
--- a/src/nix-instantiate/Makefile.am
+++ b/src/nix-instantiate/Makefile.am
@@ -4,7 +4,7 @@ nix_instantiate_SOURCES = main.cc help.txt
nix_instantiate_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
../libstore/libstore.a ../libutil/libutil.a \
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
- -lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
+ -lATerm
main.o: help.txt.hh
diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc
index 305c3b551..cc3444837 100644
--- a/src/nix-instantiate/main.cc
+++ b/src/nix-instantiate/main.cc
@@ -15,31 +15,12 @@ void printHelp()
}
-#if 0
-static Path searchPath(const Paths & searchDirs, const Path & relPath)
-{
- if (string(relPath, 0, 1) == "/") return relPath;
-
- for (Paths::const_iterator i = searchDirs.begin();
- i != searchDirs.end(); i++)
- {
- Path path = *i + "/" + relPath;
- if (pathExists(path)) return path;
- }
-
- throw Error(
- format("path `%1%' not found in any of the search directories")
- % relPath);
-}
-#endif
-
-
static Expr evalStdin(EvalState & state)
{
startNest(nest, lvlTalkative, format("evaluating standard input"));
string s, s2;
while (getline(cin, s2)) s += s2 + "\n";
- Expr e = parseExprFromString(s, absPath("."));
+ Expr e = parseExprFromString(state, s, absPath("."));
return evalExpr(state, e);
}
@@ -76,24 +57,11 @@ void run(Strings args)
Strings files;
bool readStdin = false;
-#if 0
- state.searchDirs.push_back(".");
- state.searchDirs.push_back(nixDataDir + "/nix");
-#endif
-
for (Strings::iterator it = args.begin();
it != args.end(); )
{
string arg = *it++;
-#if 0
- if (arg == "--includedir" || arg == "-I") {
- if (it == args.end())
- throw UsageError(format("argument required in `%1%'") % arg);
- state.searchDirs.push_back(*it++);
- }
- else
-#endif
if (arg == "-")
readStdin = true;
else if (arg[0] == '-')