about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.hh1
-rw-r--r--src/libexpr/nixexpr.hh1
-rw-r--r--src/libexpr/parser.y10
-rw-r--r--src/libexpr/primops.cc25
-rw-r--r--tests/lang/eval-okay-import.exp1
-rw-r--r--tests/lang/eval-okay-import.nix11
-rw-r--r--tests/lang/imported.nix3
-rw-r--r--tests/lang/imported2.nix1
8 files changed, 50 insertions, 3 deletions
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 6d4cb8abe8d1..ad4c6a4b5f5c 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -124,6 +124,7 @@ public:
 
     /* Parse a Nix expression from the specified file. */
     Expr * parseExprFromFile(const Path & path);
+    Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
 
     /* Parse a Nix expression from the specified string. */
     Expr * parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv);
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 813efbe21acd..fbd5bad81ebc 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -336,5 +336,4 @@ struct StaticEnv
 };
 
 
-
 }
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index dbcffff9965c..06d6d643f6ff 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -592,7 +592,13 @@ Path resolveExprPath(Path path)
 
 Expr * EvalState::parseExprFromFile(const Path & path)
 {
-    return parse(readFile(path).c_str(), path, dirOf(path), staticBaseEnv);
+    return parseExprFromFile(path, staticBaseEnv);
+}
+
+
+Expr * EvalState::parseExprFromFile(const Path & path, StaticEnv & staticEnv)
+{
+    return parse(readFile(path).c_str(), path, dirOf(path), staticEnv);
 }
 
 
@@ -608,7 +614,7 @@ Expr * EvalState::parseExprFromString(const string & s, const Path & basePath)
 }
 
 
- void EvalState::addToSearchPath(const string & s, bool warn)
+void EvalState::addToSearchPath(const string & s, bool warn)
 {
     size_t pos = s.find('=');
     string prefix;
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index f402478dd974..533ae37684f1 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -93,6 +93,30 @@ static void prim_import(EvalState & state, const Pos & pos, Value * * args, Valu
 }
 
 
+static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+    PathSet context;
+    state.forceAttrs(*args[0]);
+    Path path = resolveExprPath(state.coerceToPath(pos, *args[1], context));
+
+    Env * env = &state.allocEnv(args[0]->attrs->size());
+    env->up = &state.baseEnv;
+
+    StaticEnv staticEnv(false, &state.staticBaseEnv);
+
+    unsigned int displ = 0;
+    for (auto & attr : *args[0]->attrs) {
+        staticEnv.vars[attr.name] = displ;
+        env->values[displ++] = attr.value;
+    }
+
+    startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
+    Expr * e = state.parseExprFromFile(path, staticEnv);
+
+    e->eval(state, *env, v);
+}
+
+
 /* Return a string representing the type of the expression. */
 static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
@@ -1247,6 +1271,7 @@ void EvalState::createBaseEnv()
 
     // Miscellaneous
     addPrimOp("import", 1, prim_import);
+    addPrimOp("scopedImport", 2, prim_scopedImport);
     addPrimOp("__typeOf", 1, prim_typeOf);
     addPrimOp("isNull", 1, prim_isNull);
     addPrimOp("__isFunction", 1, prim_isFunction);
diff --git a/tests/lang/eval-okay-import.exp b/tests/lang/eval-okay-import.exp
new file mode 100644
index 000000000000..c508125b55be
--- /dev/null
+++ b/tests/lang/eval-okay-import.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 8 9 10 ]
diff --git a/tests/lang/eval-okay-import.nix b/tests/lang/eval-okay-import.nix
new file mode 100644
index 000000000000..0b18d9413122
--- /dev/null
+++ b/tests/lang/eval-okay-import.nix
@@ -0,0 +1,11 @@
+let
+
+  overrides = {
+    import = fn: scopedImport overrides fn;
+
+    scopedImport = attrs: fn: scopedImport (overrides // attrs) fn;
+
+    builtins = builtins // overrides;
+  } // import ./lib.nix;
+
+in scopedImport overrides ./imported.nix
diff --git a/tests/lang/imported.nix b/tests/lang/imported.nix
new file mode 100644
index 000000000000..fb39ee4efacd
--- /dev/null
+++ b/tests/lang/imported.nix
@@ -0,0 +1,3 @@
+# The function ‘range’ comes from lib.nix and was added to the lexical
+# scope by scopedImport.
+range 1 5 ++ import ./imported2.nix
diff --git a/tests/lang/imported2.nix b/tests/lang/imported2.nix
new file mode 100644
index 000000000000..6d0a2992b732
--- /dev/null
+++ b/tests/lang/imported2.nix
@@ -0,0 +1 @@
+range 6 10