From 3f699df58cce0887ef7c78673a07bcbcaf11fbed Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Thu, 1 Aug 2024 21:23:41 -0600 Subject: [PATCH] feat: implement with std lib Basic implementation with core features implemented, including isolation of Nix expressions to enforce module boundaries. One core feature still missing is private member semantics. --- default.nix | 58 +++++++++++++++++++++++++++++++++++++++++++ std/file/mod.nix | 1 + std/file/parse.nix | 11 ++++++++ std/fix.nix | 5 ++++ std/mod.nix | 1 + std/set/filterMap.nix | 8 ++++++ std/set/mod.nix | 1 + 7 files changed, 85 insertions(+) create mode 100644 default.nix create mode 100644 std/file/mod.nix create mode 100644 std/file/parse.nix create mode 100644 std/fix.nix create mode 100644 std/mod.nix create mode 100644 std/set/filterMap.nix create mode 100644 std/set/mod.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..4b6301e --- /dev/null +++ b/default.nix @@ -0,0 +1,58 @@ +let + fix = import ./std/fix.nix; + filterMap = scopedImport { std = builtins; } ./std/set/filterMap.nix; + parse = scopedImport { std = builtins; } ./std/file/parse.nix; + compose = import ./.; + + filterMod = builtins.filterSource ( + path: type: + let + file = parse (baseNameOf path); + in + type == "regular" && file.ext or null != "nix" + ); + +in +dir: +let + atom = fix ( + f: super: dir: + let + contents = builtins.readDir dir; + self = + let + import' = scopedImport ( + { + inherit atom; + std = compose ./std // builtins; + self = self // { + outPath = filterMod dir; + }; + } + // (if super != { } then { inherit super; } else { }) + ); + mod = + if contents ? "mod.nix" && contents."mod.nix" == "regular" then + import' "${dir + "/mod.nix"}" + else + { }; + 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; + in + self + ) { } dir; +in +atom diff --git a/std/file/mod.nix b/std/file/mod.nix new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/std/file/mod.nix @@ -0,0 +1 @@ +{ } diff --git a/std/file/parse.nix b/std/file/parse.nix new file mode 100644 index 0000000..bda6816 --- /dev/null +++ b/std/file/parse.nix @@ -0,0 +1,11 @@ +s: +let + r = std.match "([^.]+)\\.(.+)" s; +in +if r == null || std.length r < 2 then + null +else + { + name = std.head r; + ext = std.elemAt r 1; + } diff --git a/std/fix.nix b/std/fix.nix new file mode 100644 index 0000000..0378359 --- /dev/null +++ b/std/fix.nix @@ -0,0 +1,5 @@ +f: +let + x = f x; +in +x diff --git a/std/mod.nix b/std/mod.nix new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/std/mod.nix @@ -0,0 +1 @@ +{ } diff --git a/std/set/filterMap.nix b/std/set/filterMap.nix new file mode 100644 index 0000000..0e08929 --- /dev/null +++ b/std/set/filterMap.nix @@ -0,0 +1,8 @@ +f: set: +std.foldl' ( + acc: key: + let + val = f key set.${key}; + in + if val == null || !std.isAttrs val then acc else acc // val +) { } (std.attrNames set) diff --git a/std/set/mod.nix b/std/set/mod.nix new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/std/set/mod.nix @@ -0,0 +1 @@ +{ }