diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-08-06T16·05+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-08-06T16·05+0000 |
commit | 1ecc97b6bdb27e56d832ca48cdafd3dbb5185a04 (patch) | |
tree | 4de27ee42f04bb50766f33a58d830677bd8fa80b /src/libexpr/parser.y | |
parent | 54945a2950174ded83d58336061b4a9990cdbbfd (diff) |
* Add a Nix expression search path feature. Paths between angle
brackets, e.g. import <nixpkgs/pkgs/lib> are resolved by looking them up relative to the elements listed in the search path. This allows us to get rid of hacks like import "${builtins.getEnv "NIXPKGS_ALL"}/pkgs/lib" The search path can be specified through the ‘-I’ command-line flag and through the colon-separated ‘NIX_PATH’ environment variable, e.g., $ nix-build -I /etc/nixos ... If a file is not found in the search path, an error message is lazily thrown.
Diffstat (limited to 'src/libexpr/parser.y')
-rw-r--r-- | src/libexpr/parser.y | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index a64d327b454b..cd63666dc5f0 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -17,19 +17,22 @@ #include "util.hh" #include "nixexpr.hh" +#include "eval.hh" namespace nix { struct ParseData { + EvalState & state; SymbolTable & symbols; Expr * result; Path basePath; Path path; string error; Symbol sLetBody; - ParseData(SymbolTable & symbols) - : symbols(symbols) + ParseData(EvalState & state) + : state(state) + , symbols(state.symbols) , sLetBody(symbols.create("<let-body>")) { }; }; @@ -253,7 +256,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err %token <id> ID ATTRPATH %token <e> STR IND_STR %token <n> INT -%token <path> PATH +%token <path> PATH SPATH %token <uri> URI %token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW %token DOLLAR_CURLY /* == ${ */ @@ -350,6 +353,20 @@ expr_simple $$ = stripIndentation(data->symbols, *$2); } | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } + | SPATH { + string path($1 + 1, strlen($1) - 2); + Path path2 = data->state.findFile(path); + /* The file wasn't found in the search path. However, we can't + throw an error here, because the expression might never be + evaluated. So return an expression that lazily calls + ‘abort’. */ + $$ = path2 == "" + ? (Expr * ) new ExprApp( + new ExprVar(data->symbols.create("throw")), + new ExprString(data->symbols.create( + (format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str()))) + : (Expr * ) new ExprPath(path2); + } | URI { $$ = new ExprString(data->symbols.create($1)); } | '(' expr ')' { $$ = $2; } /* Let expressions `let {..., body = ...}' are just desugared @@ -454,7 +471,7 @@ Expr * EvalState::parse(const char * text, const Path & path, const Path & basePath) { yyscan_t scanner; - ParseData data(symbols); + ParseData data(*this); data.basePath = basePath; data.path = path; @@ -510,5 +527,25 @@ Expr * EvalState::parseExprFromString(const string & s, const Path & basePath) return parse(s.c_str(), "(string)", basePath); } - + +void EvalState::addToSearchPath(const string & s) +{ + Path path = absPath(s); + if (pathExists(path)) { + debug(format("adding path `%1%' to the search path") % path); + searchPath.insert(searchPathInsertionPoint, path); + } +} + + +Path EvalState::findFile(const string & path) +{ + foreach (Paths::iterator, i, searchPath) { + Path res = *i + "/" + path; + if (pathExists(res)) return canonPath(res); + } + return ""; +} + + } |