diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-05-26T11·46+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-05-26T12·26+0200 |
commit | c273c15cb13bb86420dda1e5341a4e19517532b5 (patch) | |
tree | 38b670d6fbd64735502fd60525a625c18d8372ad /tests | |
parent | f0fdbd0897ce63c138ec663ed89a94709a8441a7 (diff) |
Add primop ‘scopedImport’
‘scopedImport’ works like ‘import’, except that it takes a set of attributes to be added to the lexical scope of the expression, essentially extending or overriding the builtin variables. For instance, the expression scopedImport { x = 1; } ./foo.nix where foo.nix contains ‘x’, will evaluate to 1. This has a few applications: * It allows getting rid of function argument specifications in package expressions. For instance, a package expression like: { stdenv, fetchurl, libfoo }: stdenv.mkDerivation { ... buildInputs = [ libfoo ]; } can now we written as just stdenv.mkDerivation { ... buildInputs = [ libfoo ]; } and imported in all-packages.nix as: bar = scopedImport pkgs ./bar.nix; So whereas we once had dependencies listed in three places (buildInputs, the function, and the call site), they now only need to appear in one place. * It allows overriding builtin functions. For instance, to trace all calls to ‘map’: let overrides = { map = f: xs: builtins.trace "map called!" (map f xs); # Ensure that our override gets propagated by calls to # import/scopedImport. import = fn: scopedImport overrides fn; scopedImport = attrs: fn: scopedImport (overrides // attrs) fn; # Also update ‘builtins’. builtins = builtins // overrides; }; in scopedImport overrides ./bla.nix * Similarly, it allows extending the set of builtin functions. For instance, during Nixpkgs/NixOS evaluation, the Nixpkgs library functions could be added to the default scope. There is a downside: calls to scopedImport are not memoized, unlike import. So importing a file multiple times leads to multiple parsings / evaluations. It would be possible to construct the AST only once, but that would require careful handling of variables/environments.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/lang/eval-okay-import.exp | 1 | ||||
-rw-r--r-- | tests/lang/eval-okay-import.nix | 11 | ||||
-rw-r--r-- | tests/lang/imported.nix | 3 | ||||
-rw-r--r-- | tests/lang/imported2.nix | 1 |
4 files changed, 16 insertions, 0 deletions
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 |