Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refine scoping rules & names #3

Merged
merged 4 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .envrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
use nix
eval "$(nix print-dev-env -f shell.nix)"
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ code without having to perform a full evaluation. This could be used, e.g. to sh
- **Isolation**: Modules are imported into the Nix store, enforcing boundaries and preventing relative path access.
- **Introspection**: Unlike legacy modules, code is specified in its final form instead of as prototypes (functions), leading to much better and simpler introspective analysis.
- **Simplicity**: The system is kept purposefully simple and flexible in order to remain performant and flexible.
- **Scoping**: Each module and member has access to `self`, `super`, `atom`, `pub` and `std`.
- **Scoping**: Each module and member has access to `mod`, `pre`, `atom`, and `std`.
- **Standard Library**: Includes a standard library (`std`) augmented with `builtins`.

## How It Works
Expand All @@ -27,11 +27,10 @@ code without having to perform a full evaluation. This could be used, e.g. to sh
- Subdirectories with `mod.nix`: Treated as nested modules.

2. **Scoping**:
- `self`: Current module, includes `outPath` for accessing non-Nix files.
- `super`: Parent module (if applicable).
- `atom`: Top-level module.
- `mod`: Current module, includes `outPath` for accessing non-Nix files.
- `pre`: Parent module (if applicable).
- `atom`: Top-level module and external dependencies.
- `std`: Standard library and `builtins`.
- `pub`: External resources, such as other atoms, free-form nix expressions, remote sources, etc.

3. **Composition**: Modules are composed recursively, with `mod.nix` contents taking precedence.

Expand All @@ -53,7 +52,7 @@ in
* Break out large functions or code blocks into their own files
* Organize related functionality into subdirectories with their own "mod.nix" files.
* Leverage provided scopes for clean, modular code.
* Use `"${self}"` when needing to access non-Nix files within a module.
* Use `"${mod}/foo.nix"` when needing to access non-Nix files within a module.

## Future Work

Expand Down
83 changes: 49 additions & 34 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ let
filterMap = scopedImport { std = builtins; } ./std/set/filterMap.nix;
parse = scopedImport { std = builtins; } ./std/file/parse.nix;
compose = import ./.;
cond = set: if set._if or true then set else { };

filterMod = builtins.filterSource (
path: type:
Expand All @@ -14,49 +15,63 @@ let

in
{
pub ? { },
extern ? { },
}:
dir:
let
std = compose { } ./std // builtins;
atom' = builtins.removeAttrs (extern // atom // { inherit extern; }) [
"atom"
(baseNameOf dir)
];
atom = fix (
f: super: dir:
f: pre: dir:
let
contents = builtins.readDir dir;
self =

hasMod = contents."mod.nix" or null == "regular";

mod = if hasMod then scope "${dir + "/mod.nix"}" else { };

scope = scopedImport (
{
inherit std;
atom = atom';
mod = builtins.removeAttrs self [ "mod" ] // {
outPath = filterMod dir;
};
}
// cond {
_if = pre != { };
inherit pre;
}
);

g =
name: type:
let
import' = scopedImport (
{
inherit atom;
std = compose { } ./std // builtins;
self = self // {
outPath = filterMod dir;
};
}
// (if super != { } then { inherit super; } else { })
// (if pub != { } then { inherit pub; } else { })
);
mod =
if contents ? "mod.nix" && contents."mod.nix" == "regular" then
import' "${dir + "/mod.nix"}"
else
{ };
path = dir + "/${name}";
file = parse name;
in
filterMap (
name: type:
let
path = dir + "/${name}";
file = parse name;
in
if type == "directory" then
{ ${name} = f self path; }
else if type == "regular" && file.ext or null == "nix" && name != "mod.nix" then
{ ${file.name} = import' "${path}"; }
else
null # Ignore other file types
) contents
// mod;
if type == "directory" then
{
${name} = f (
self
// cond {
_if = pre != { };
inherit pre;
}
) path;
}
else if type == "regular" && file.ext or null == "nix" && name != "mod.nix" then
{ ${file.name} = scope "${path}"; }
else
null # Ignore other file types
;

self = filterMap g contents // mod;
in
if !(contents."mod.nix" or null == "regular") then
if !hasMod then
{ } # Base case: no module
else
self
Expand Down
2 changes: 1 addition & 1 deletion dev/pkgs.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let
inherit (pub.pins) nixpkgs;
inherit (atom.pins) nixpkgs;
in
import nixpkgs { }
2 changes: 1 addition & 1 deletion dev/shell.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
pkgs ? self.pkgs,
pkgs ? mod.pkgs,
}:
pkgs.mkShell {
packages = with pkgs; [
Expand Down
2 changes: 1 addition & 1 deletion shell.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let
dev = import ./. {
pub = {
extern = {
pins = import ./npins;
};
} ./dev;
Expand Down
2 changes: 1 addition & 1 deletion test/bld/bar/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/bar/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
2 changes: 1 addition & 1 deletion test/bld/buzz/bar/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/bar/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
2 changes: 1 addition & 1 deletion test/bld/buzz/fuzz/bar/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/bar/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = super.bar + 2;
baz = self.bar + 4;
bar = pre.bar + 2;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
2 changes: 1 addition & 1 deletion test/bld/buzz/fuzz/wuzz/bar/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/wuzz/bar/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
2 changes: 1 addition & 1 deletion test/bld/buzz/fuzz/wuzz/cuzz/bar/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/wuzz/cuzz/bar/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
2 changes: 1 addition & 1 deletion test/bld/buzz/fuzz/wuzz/cuzz/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/wuzz/cuzz/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/wuzz/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = super.bar + 2;
baz = self.bar + 4;
bar = pre.bar + 2;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/fuzz/wuzz/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
foo = 1;
bar = super.foo + 2;
baz = self.bar + 4;
bar = pre.foo + 2;
baz = mod.bar + 4;
}
4 changes: 2 additions & 2 deletions test/bld/buzz/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}
4 changes: 2 additions & 2 deletions test/bld/mod.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
foo = 1;
bar = atom.foo + 2;
baz = self.bar + 4;
baz = mod.bar + 4;
test = std.set.filterMap;
x = builtins.readFile "${self}/bum";
x = builtins.readFile "${mod}/bum";
}
4 changes: 2 additions & 2 deletions test/bld/next/mod.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

g = super.foo + 4;
h = self.g + 3;
g = pre.foo + 4;
h = mod.g + 3;
}