mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-26 07:46:21 +02:00
Move import docs
This commit is contained in:
parent
f53b5f1058
commit
7a02865b94
3 changed files with 80 additions and 78 deletions
|
@ -13,56 +13,3 @@ For instance, `derivation` is also available as `builtins.derivation`.
|
||||||
|
|
||||||
`derivation` is described in [its own section](derivations.md).
|
`derivation` is described in [its own section](derivations.md).
|
||||||
|
|
||||||
- `import` *path*; `builtins.import` *path*
|
|
||||||
|
|
||||||
Load, parse and return the Nix expression in the file *path*. If
|
|
||||||
*path* is a directory, the file ` default.nix ` in that directory
|
|
||||||
is loaded. Evaluation aborts if the file doesn’t exist or contains
|
|
||||||
an incorrect Nix expression. `import` implements Nix’s module
|
|
||||||
system: you can put any Nix expression (such as a set or a
|
|
||||||
function) in a separate file, and use it from Nix expressions in
|
|
||||||
other files.
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> Unlike some languages, `import` is a regular function in Nix.
|
|
||||||
> Paths using the angle bracket syntax (e.g., `import` *\<foo\>*)
|
|
||||||
> are [normal path values](language-values.md).
|
|
||||||
|
|
||||||
A Nix expression loaded by `import` must not contain any *free
|
|
||||||
variables* (identifiers that are not defined in the Nix expression
|
|
||||||
itself and are not built-in). Therefore, it cannot refer to
|
|
||||||
variables that are in scope at the call site. For instance, if you
|
|
||||||
have a calling expression
|
|
||||||
|
|
||||||
```nix
|
|
||||||
rec {
|
|
||||||
x = 123;
|
|
||||||
y = import ./foo.nix;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
then the following `foo.nix` will give an error:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
x + 456
|
|
||||||
```
|
|
||||||
|
|
||||||
since `x` is not in scope in `foo.nix`. If you want `x` to be
|
|
||||||
available in `foo.nix`, you should pass it as a function argument:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
rec {
|
|
||||||
x = 123;
|
|
||||||
y = import ./foo.nix x;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
and
|
|
||||||
|
|
||||||
```nix
|
|
||||||
x: x + 456
|
|
||||||
```
|
|
||||||
|
|
||||||
(The function argument doesn’t have to be called `x` in `foo.nix`;
|
|
||||||
any name would work.)
|
|
||||||
|
|
|
@ -74,10 +74,10 @@ void EvalState::realiseContext(const PathSet & context)
|
||||||
|
|
||||||
/* Load and evaluate an expression from path specified by the
|
/* Load and evaluate an expression from path specified by the
|
||||||
argument. */
|
argument. */
|
||||||
static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vScope, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.coerceToPath(pos, *args[1], context);
|
Path path = state.coerceToPath(pos, vPath, context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
|
@ -99,6 +99,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return storePath;
|
return storePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto optStorePath = isValidDerivationInStore()) {
|
if (auto optStorePath = isValidDerivationInStore()) {
|
||||||
auto storePath = *optStorePath;
|
auto storePath = *optStorePath;
|
||||||
Derivation drv = readDerivation(*state.store, realPath, Derivation::nameFromPath(storePath));
|
Derivation drv = readDerivation(*state.store, realPath, Derivation::nameFromPath(storePath));
|
||||||
|
@ -133,17 +134,18 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
|
||||||
mkApp(v, **fun, w);
|
mkApp(v, **fun, w);
|
||||||
state.forceAttrs(v, pos);
|
state.forceAttrs(v, pos);
|
||||||
} else {
|
} else {
|
||||||
state.forceAttrs(*args[0]);
|
if (!vScope)
|
||||||
if (args[0]->attrs->empty())
|
|
||||||
state.evalFile(realPath, v);
|
state.evalFile(realPath, v);
|
||||||
else {
|
else {
|
||||||
Env * env = &state.allocEnv(args[0]->attrs->size());
|
state.forceAttrs(*vScope);
|
||||||
|
|
||||||
|
Env * env = &state.allocEnv(vScope->attrs->size());
|
||||||
env->up = &state.baseEnv;
|
env->up = &state.baseEnv;
|
||||||
|
|
||||||
StaticEnv staticEnv(false, &state.staticBaseEnv);
|
StaticEnv staticEnv(false, &state.staticBaseEnv);
|
||||||
|
|
||||||
unsigned int displ = 0;
|
unsigned int displ = 0;
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *vScope->attrs) {
|
||||||
staticEnv.vars[attr.name] = displ;
|
staticEnv.vars[attr.name] = displ;
|
||||||
env->values[displ++] = attr.value;
|
env->values[displ++] = attr.value;
|
||||||
}
|
}
|
||||||
|
@ -156,6 +158,77 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RegisterPrimOp primop_scopedImport(RegisterPrimOp::Info {
|
||||||
|
.name = "scopedImport",
|
||||||
|
.arity = 2,
|
||||||
|
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
import(state, pos, *args[1], args[0], v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static RegisterPrimOp primop_import({
|
||||||
|
.name = "import",
|
||||||
|
.args = {"path"},
|
||||||
|
.doc = R"(
|
||||||
|
Load, parse and return the Nix expression in the file *path*. If
|
||||||
|
*path* is a directory, the file ` default.nix ` in that directory
|
||||||
|
is loaded. Evaluation aborts if the file doesn’t exist or contains
|
||||||
|
an incorrect Nix expression. `import` implements Nix’s module
|
||||||
|
system: you can put any Nix expression (such as a set or a
|
||||||
|
function) in a separate file, and use it from Nix expressions in
|
||||||
|
other files.
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Unlike some languages, `import` is a regular function in Nix.
|
||||||
|
> Paths using the angle bracket syntax (e.g., `import` *\<foo\>*)
|
||||||
|
> are [normal path values](language-values.md).
|
||||||
|
|
||||||
|
A Nix expression loaded by `import` must not contain any *free
|
||||||
|
variables* (identifiers that are not defined in the Nix expression
|
||||||
|
itself and are not built-in). Therefore, it cannot refer to
|
||||||
|
variables that are in scope at the call site. For instance, if you
|
||||||
|
have a calling expression
|
||||||
|
|
||||||
|
```nix
|
||||||
|
rec {
|
||||||
|
x = 123;
|
||||||
|
y = import ./foo.nix;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
then the following `foo.nix` will give an error:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
x + 456
|
||||||
|
```
|
||||||
|
|
||||||
|
since `x` is not in scope in `foo.nix`. If you want `x` to be
|
||||||
|
available in `foo.nix`, you should pass it as a function argument:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
rec {
|
||||||
|
x = 123;
|
||||||
|
y = import ./foo.nix x;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```nix
|
||||||
|
x: x + 456
|
||||||
|
```
|
||||||
|
|
||||||
|
(The function argument doesn’t have to be called `x` in `foo.nix`;
|
||||||
|
any name would work.)
|
||||||
|
)",
|
||||||
|
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
import(state, pos, *args[0], nullptr, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* Want reasonable symbol names, so extern C */
|
/* Want reasonable symbol names, so extern C */
|
||||||
/* !!! Should we pass the Pos or the file name too? */
|
/* !!! Should we pass the Pos or the file name too? */
|
||||||
extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
|
extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
|
||||||
|
@ -3429,12 +3502,6 @@ void EvalState::createBaseEnv()
|
||||||
addConstant("__langVersion", v);
|
addConstant("__langVersion", v);
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
auto vScopedImport = addPrimOp("scopedImport", 2, prim_scopedImport);
|
|
||||||
Value * v2 = allocValue();
|
|
||||||
mkAttrs(*v2, 0);
|
|
||||||
mkApp(v, *vScopedImport, *v2);
|
|
||||||
forceValue(v);
|
|
||||||
addConstant("import", v);
|
|
||||||
if (evalSettings.enableNativeCode) {
|
if (evalSettings.enableNativeCode) {
|
||||||
addPrimOp("__importNative", 2, prim_importNative);
|
addPrimOp("__importNative", 2, prim_importNative);
|
||||||
addPrimOp("__exec", 1, prim_exec);
|
addPrimOp("__exec", 1, prim_exec);
|
||||||
|
@ -3444,7 +3511,7 @@ void EvalState::createBaseEnv()
|
||||||
mkList(v, searchPath.size());
|
mkList(v, searchPath.size());
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (auto & i : searchPath) {
|
for (auto & i : searchPath) {
|
||||||
v2 = v.listElems()[n++] = allocValue();
|
auto v2 = v.listElems()[n++] = allocValue();
|
||||||
mkAttrs(*v2, 2);
|
mkAttrs(*v2, 2);
|
||||||
mkString(*allocAttr(*v2, symbols.create("path")), i.second);
|
mkString(*allocAttr(*v2, symbols.create("path")), i.second);
|
||||||
mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);
|
mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);
|
||||||
|
|
|
@ -32,8 +32,6 @@ expect_trace() {
|
||||||
|
|
||||||
# failure inside a tryEval
|
# failure inside a tryEval
|
||||||
expect_trace 'builtins.tryEval (throw "example")' "
|
expect_trace 'builtins.tryEval (throw "example")' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace entered (string):1:19 at
|
function-trace entered (string):1:19 at
|
||||||
function-trace exited (string):1:19 at
|
function-trace exited (string):1:19 at
|
||||||
|
@ -42,32 +40,24 @@ function-trace exited (string):1:1 at
|
||||||
|
|
||||||
# Missing argument to a formal function
|
# Missing argument to a formal function
|
||||||
expect_trace '({ x }: x) { }' "
|
expect_trace '({ x }: x) { }' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace exited (string):1:1 at
|
function-trace exited (string):1:1 at
|
||||||
"
|
"
|
||||||
|
|
||||||
# Too many arguments to a formal function
|
# Too many arguments to a formal function
|
||||||
expect_trace '({ x }: x) { x = "x"; y = "y"; }' "
|
expect_trace '({ x }: x) { x = "x"; y = "y"; }' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace exited (string):1:1 at
|
function-trace exited (string):1:1 at
|
||||||
"
|
"
|
||||||
|
|
||||||
# Not enough arguments to a lambda
|
# Not enough arguments to a lambda
|
||||||
expect_trace '(x: y: x + y) 1' "
|
expect_trace '(x: y: x + y) 1' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace exited (string):1:1 at
|
function-trace exited (string):1:1 at
|
||||||
"
|
"
|
||||||
|
|
||||||
# Too many arguments to a lambda
|
# Too many arguments to a lambda
|
||||||
expect_trace '(x: x) 1 2' "
|
expect_trace '(x: x) 1 2' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace exited (string):1:1 at
|
function-trace exited (string):1:1 at
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
|
@ -76,8 +66,6 @@ function-trace exited (string):1:1 at
|
||||||
|
|
||||||
# Not a function
|
# Not a function
|
||||||
expect_trace '1 2' "
|
expect_trace '1 2' "
|
||||||
function-trace entered undefined position at
|
|
||||||
function-trace exited undefined position at
|
|
||||||
function-trace entered (string):1:1 at
|
function-trace entered (string):1:1 at
|
||||||
function-trace exited (string):1:1 at
|
function-trace exited (string):1:1 at
|
||||||
"
|
"
|
||||||
|
|
Loading…
Reference in a new issue