diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/eval.cc | 68 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 11 | ||||
-rw-r--r-- | src/libexpr/nixexpr.cc | 23 | ||||
-rw-r--r-- | src/libexpr/nixexpr.hh | 9 | ||||
-rw-r--r-- | src/libexpr/parser.cc | 24 | ||||
-rw-r--r-- | src/libexpr/parser.hh | 6 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 12 | ||||
-rw-r--r-- | src/libexpr/primops.hh | 6 |
8 files changed, 121 insertions, 38 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index bbb1393f8388..802b83aa160d 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 0bc052676deb..34ac467f1d80 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 92027a70ebd7..7739e99a96be 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 26c29a2f38b1..924f8b912f77 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 0a550fb35507..68b367340acf 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 461dae08cd92..2af5385f6275 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 d1c398a34831..92683fcac53d 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 76d587afdb1e..6b9722dac38e 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); |