forked from lix-project/lix
* Use a map to lookup primops.
* Various performance improvements in the evaluator. * Do not link against unused (and missing!) libraries (-lsglr, etc.).
This commit is contained in:
parent
c4f7ae4aa5
commit
9b44480612
|
@ -3,12 +3,52 @@
|
||||||
#include "primops.hh"
|
#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()
|
EvalState::EvalState()
|
||||||
: normalForms(32768, 75)
|
: normalForms(32768, 50)
|
||||||
{
|
{
|
||||||
blackHole = ATmake("BlackHole()");
|
blackHole = ATmake("BlackHole()");
|
||||||
if (!blackHole) throw Error("cannot build black hole");
|
if (!blackHole) throw Error("cannot build black hole");
|
||||||
|
|
||||||
nrEvaluated = nrCached = 0;
|
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;
|
ATMatcher m;
|
||||||
Expr e1, e2, e3, e4;
|
Expr e1, e2, e3, e4;
|
||||||
string s1;
|
ATerm name;
|
||||||
|
|
||||||
/* Normal forms. */
|
/* Normal forms. */
|
||||||
if (atMatch(m, e) >> "Str" ||
|
if (atMatch(m, e) >> "Str" ||
|
||||||
|
@ -144,10 +184,11 @@ Expr evalExpr2(EvalState & state, Expr e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
/* Any encountered variables must be undeclared or primops. */
|
/* Any encountered variables must be undeclared or primops. */
|
||||||
if (atMatch(m, e) >> "Var" >> s1) {
|
if (atMatch(m, e) >> "Var" >> name) {
|
||||||
if (s1 == "null") return primNull(state);
|
PrimOp0 primOp = (PrimOp0) lookupPrimOp(state.primOps0, name);
|
||||||
if (s1 == "true") return ATmake("Bool(True)");
|
if (primOp)
|
||||||
if (s1 == "false") return ATmake("Bool(False)");
|
return primOp(state);
|
||||||
|
else
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,13 +201,9 @@ Expr evalExpr2(EvalState & state, Expr e)
|
||||||
e1 = evalExpr(state, e1);
|
e1 = evalExpr(state, e1);
|
||||||
|
|
||||||
/* Is it a primop or a function? */
|
/* Is it a primop or a function? */
|
||||||
if (atMatch(m, e1) >> "Var" >> s1) {
|
if (atMatch(m, e1) >> "Var" >> name) {
|
||||||
if (s1 == "import") return primImport(state, e2);
|
PrimOp1 primOp = (PrimOp1) lookupPrimOp(state.primOps1, name);
|
||||||
if (s1 == "derivation") return primDerivation(state, e2);
|
if (primOp) return primOp(state, e2); else abort();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (atMatch(m, e1) >> "Function" >> formals >> e4)
|
else if (atMatch(m, e1) >> "Function" >> formals >> e4)
|
||||||
|
@ -177,6 +214,7 @@ Expr evalExpr2(EvalState & state, Expr e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attribute selection. */
|
/* Attribute selection. */
|
||||||
|
string s1;
|
||||||
if (atMatch(m, e) >> "Select" >> e1 >> s1) {
|
if (atMatch(m, e) >> "Select" >> e1 >> s1) {
|
||||||
Expr a = queryAttr(evalExpr(state, e1), s1);
|
Expr a = queryAttr(evalExpr(state, e1), s1);
|
||||||
if (!a) throw badTerm(format("missing attribute `%1%'") % s1, e);
|
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)
|
Expr evalFile(EvalState & state, const Path & path)
|
||||||
{
|
{
|
||||||
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
|
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
|
||||||
Expr e = parseExprFromFile(path);
|
Expr e = parseExprFromFile(state, path);
|
||||||
return evalExpr(state, e);
|
return evalExpr(state, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,17 @@
|
||||||
typedef map<Path, PathSet> DrvPaths;
|
typedef map<Path, PathSet> DrvPaths;
|
||||||
typedef map<Path, Hash> DrvHashes;
|
typedef map<Path, Hash> DrvHashes;
|
||||||
|
|
||||||
|
struct EvalState;
|
||||||
|
typedef Expr (* PrimOp0) (EvalState &);
|
||||||
|
typedef Expr (* PrimOp1) (EvalState &, Expr arg);
|
||||||
|
|
||||||
|
|
||||||
struct EvalState
|
struct EvalState
|
||||||
{
|
{
|
||||||
ATermMap normalForms;
|
ATermMap normalForms;
|
||||||
|
ATermMap primOps0; /* nullary primops */
|
||||||
|
ATermMap primOps1; /* unary primops */
|
||||||
|
ATermMap primOpsAll;
|
||||||
DrvPaths drvPaths;
|
DrvPaths drvPaths;
|
||||||
DrvHashes drvHashes; /* normalised derivation hashes */
|
DrvHashes drvHashes; /* normalised derivation hashes */
|
||||||
Expr blackHole;
|
Expr blackHole;
|
||||||
|
@ -22,6 +30,9 @@ struct EvalState
|
||||||
unsigned int nrCached;
|
unsigned int nrCached;
|
||||||
|
|
||||||
EvalState();
|
EvalState();
|
||||||
|
|
||||||
|
void addPrimOp0(const string & name, PrimOp0 primOp);
|
||||||
|
void addPrimOp1(const string & name, PrimOp1 primOp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,7 @@ ATermMap::ATermMap(const ATermMap & map)
|
||||||
table = ATtableCreate(ATgetLength(keys), maxLoadPct);
|
table = ATtableCreate(ATgetLength(keys), maxLoadPct);
|
||||||
if (!table) throw Error("cannot create ATerm table");
|
if (!table) throw Error("cannot create ATerm table");
|
||||||
|
|
||||||
for (ATermIterator i(keys); i; ++i)
|
add(map, keys);
|
||||||
set(*i, map.get(*i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
ATerm string2ATerm(const string & s)
|
||||||
{
|
{
|
||||||
return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue));
|
return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue));
|
||||||
|
|
|
@ -23,7 +23,7 @@ private:
|
||||||
ATermTable table;
|
ATermTable table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ATermMap(unsigned int initialSize = 16, unsigned int maxLoadPct = 75);
|
ATermMap(unsigned int initialSize = 64, unsigned int maxLoadPct = 75);
|
||||||
ATermMap(const ATermMap & map);
|
ATermMap(const ATermMap & map);
|
||||||
~ATermMap();
|
~ATermMap();
|
||||||
|
|
||||||
|
@ -37,6 +37,13 @@ public:
|
||||||
void remove(const string & key);
|
void remove(const string & key);
|
||||||
|
|
||||||
ATermList keys() const;
|
ATermList keys() const;
|
||||||
|
|
||||||
|
void add(const ATermMap & map);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void add(const ATermMap & map, ATermList & keys);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
const Path & basePath)
|
||||||
{
|
{
|
||||||
yyscan_t scanner;
|
yyscan_t scanner;
|
||||||
|
@ -81,18 +82,8 @@ static Expr parse(const char * text, const string & location,
|
||||||
|
|
||||||
if (res) throw Error(data.error);
|
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 {
|
try {
|
||||||
checkVarDefs(primOps, data.result);
|
checkVarDefs(state.primOpsAll, data.result);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
throw Error(format("%1%, in %2%") % e.msg() % location);
|
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] == '/');
|
assert(path[0] == '/');
|
||||||
|
|
||||||
|
@ -137,11 +128,12 @@ Expr parseExprFromFile(Path path)
|
||||||
readFull(fd, (unsigned char *) text, st.st_size);
|
readFull(fd, (unsigned char *) text, st.st_size);
|
||||||
text[st.st_size] = 0;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
#ifndef __PARSER_H
|
#ifndef __PARSER_H
|
||||||
#define __PARSER_H
|
#define __PARSER_H
|
||||||
|
|
||||||
#include "nixexpr.hh"
|
#include "eval.hh"
|
||||||
|
|
||||||
|
|
||||||
/* Parse a Nix expression from the specified file. If `path' refers
|
/* Parse a Nix expression from the specified file. If `path' refers
|
||||||
to a directory, the "/default.nix" is appended. */
|
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. */
|
/* Parse a Nix expression from the specified string. */
|
||||||
Expr parseExprFromString(const string & s,
|
Expr parseExprFromString(EvalState & state, const string & s,
|
||||||
const Path & basePath);
|
const Path & basePath);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
Expr primNull(EvalState & state)
|
||||||
{
|
{
|
||||||
return ATmake("Null");
|
return ATmake("Null");
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
argument. */
|
argument. */
|
||||||
Expr primImport(EvalState & state, Expr arg);
|
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
|
expression that performs the derivation described by the argument
|
||||||
set. Returns the original set extended with the following
|
set. Returns the original set extended with the following
|
||||||
attributes: `outPath' containing the primary output path of the
|
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. */
|
/* Convert the argument (which can be a path or a uri) to a string. */
|
||||||
Expr primToString(EvalState & state, Expr arg);
|
Expr primToString(EvalState & state, Expr arg);
|
||||||
|
|
||||||
|
/* Boolean constructors. */
|
||||||
|
Expr primTrue(EvalState & state);
|
||||||
|
Expr primFalse(EvalState & state);
|
||||||
|
|
||||||
/* Return the null value. */
|
/* Return the null value. */
|
||||||
Expr primNull(EvalState & state);
|
Expr primNull(EvalState & state);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ nix_env_SOURCES = main.cc help.txt
|
||||||
nix_env_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
|
nix_env_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
|
||||||
../libstore/libstore.a ../libutil/libutil.a \
|
../libstore/libstore.a ../libutil/libutil.a \
|
||||||
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
|
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
|
||||||
-lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
|
-lATerm
|
||||||
|
|
||||||
main.o: help.txt.hh
|
main.o: help.txt.hh
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
|
||||||
|
|
||||||
void loadDerivations(EvalState & state, Path nePath, 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))
|
if (!parseDerivations(state, e, drvs))
|
||||||
throw badTerm("expected set of derivations", e);
|
throw badTerm("expected set of derivations", e);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,8 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
|
||||||
const Path & linkPath)
|
const Path & linkPath)
|
||||||
{
|
{
|
||||||
/* Get the environment builder expression. */
|
/* 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. */
|
/* Construct the whole top level derivation. */
|
||||||
ATermList inputs = ATempty;
|
ATermList inputs = ATempty;
|
||||||
|
|
|
@ -4,7 +4,7 @@ nix_instantiate_SOURCES = main.cc help.txt
|
||||||
nix_instantiate_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
|
nix_instantiate_LDADD = ../libmain/libmain.a ../libexpr/libexpr.a \
|
||||||
../libstore/libstore.a ../libutil/libutil.a \
|
../libstore/libstore.a ../libutil/libutil.a \
|
||||||
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
|
../boost/format/libformat.a -L../../externals/inst/lib -ldb_cxx \
|
||||||
-lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
|
-lATerm
|
||||||
|
|
||||||
main.o: help.txt.hh
|
main.o: help.txt.hh
|
||||||
|
|
||||||
|
|
|
@ -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)
|
static Expr evalStdin(EvalState & state)
|
||||||
{
|
{
|
||||||
startNest(nest, lvlTalkative, format("evaluating standard input"));
|
startNest(nest, lvlTalkative, format("evaluating standard input"));
|
||||||
string s, s2;
|
string s, s2;
|
||||||
while (getline(cin, s2)) s += s2 + "\n";
|
while (getline(cin, s2)) s += s2 + "\n";
|
||||||
Expr e = parseExprFromString(s, absPath("."));
|
Expr e = parseExprFromString(state, s, absPath("."));
|
||||||
return evalExpr(state, e);
|
return evalExpr(state, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,24 +57,11 @@ void run(Strings args)
|
||||||
Strings files;
|
Strings files;
|
||||||
bool readStdin = false;
|
bool readStdin = false;
|
||||||
|
|
||||||
#if 0
|
|
||||||
state.searchDirs.push_back(".");
|
|
||||||
state.searchDirs.push_back(nixDataDir + "/nix");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (Strings::iterator it = args.begin();
|
for (Strings::iterator it = args.begin();
|
||||||
it != args.end(); )
|
it != args.end(); )
|
||||||
{
|
{
|
||||||
string arg = *it++;
|
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 == "-")
|
if (arg == "-")
|
||||||
readStdin = true;
|
readStdin = true;
|
||||||
else if (arg[0] == '-')
|
else if (arg[0] == '-')
|
||||||
|
|
Loading…
Reference in a new issue