1final: prev:
2with final;
3let
4 silicon = rec {
5 _name = "syvl";
6 isAttrsOnly = value: (builtins.isAttrs value) && (!(isDerivation value));
7
8 # TODO: Remove the tryEval from here
9 # recursiveUpdateAll' = delim: a: b:
10 # let a-names = attrNames a;
11 # in (mapAttrs (n: v:
12 # let e = tryEval v;
13 # in if (e.success && (isAttrsOnly v)) then
14 # (if (any (attr:
15 # let g = tryEval attr;
16 # in g.success
17 # && ((isAttrsOnly attr) || (isList attr) || (isString attr)))
18 # (attrValues v)) then
19 # (recursiveUpdateAll' delim v (b.${n} or { }))
20 # else
21 # (v // (b.${n} or { })))
22 # else if (isList v) then
23 # (v ++ (b.${n} or [ ]))
24 # else if ((delim != null) && (isString v)) then
25 # (if (hasAttr n b) then (v + delim + b.${n}) else v)
26 # else
27 # (b.${n} or v)) a) // (builtins.removeAttrs b a-names);
28 recursiveUpdateAll' =
29 delim: a: b:
30 let
31 a-names = builtins.attrNames a;
32 in
33 (builtins.mapAttrs (
34 n: v:
35
36 # TODO: Is this `tryEval' necessary?
37 let
38 e = builtins.tryEval v;
39 in
40 if (e.success && (builtins.any (x: x) [ (isAttrsOnly v) ])) then
41
42 # TODO: Need this to merge mkShells
43 # in if (e.success && ((isAttrsOnly v) || (v ? shellHook))) then
44
45 # (if (any (attr: (isAttrs attr) || (isList attr) || (isString attr))
46 # (attrValues v)) then
47 # (recursiveUpdateAll' delim v (b.${n} or { }))
48 # else
49 # (v // (b.${n} or { })))
50 (recursiveUpdateAll' delim v (b.${n} or { }))
51 else if (e.success && (isDerivation v) && (b.${n}.__append__ or false)) then
52 (recursiveUpdateAll' delim v (builtins.removeAttrs b.${n} [ "__append__" ]))
53 else if (builtins.isList v) then
54 (v ++ (b.${n} or [ ]))
55 else if ((delim != null) && (builtins.isString v)) then
56 (if (builtins.hasAttr n b) then (v + delim + b.${n}) else v)
57 else
58 (b.${n} or (if (n == "overridePythonAttrs") then "" else v))
59 ) a)
60 // (builtins.removeAttrs b a-names);
61 recursiveUpdateAll = recursiveUpdateAll' null;
62 recursiveFold' = delim: builtins.foldl' (recursiveUpdateAll' delim) { };
63 recursiveFold = builtins.foldl' recursiveUpdateAll { };
64
65 # Adapted From: https://github.com/NixOS/nixpkgs/blob/907316e1d29bcc2416a2341bf7240d1bdbd374a5/lib/fixed-points.nix#L153-L328
66 mergeExtends =
67 f: rattrs: self:
68 let
69 super = rattrs self;
70 in
71 recursiveUpdateAll super (f self super);
72
73 # Adapted From: https://github.com/NixOS/nixpkgs/blob/907316e1d29bcc2416a2341bf7240d1bdbd374a5/lib/fixed-points.nix#L330-L340
74 composeMergedExtensions =
75 f: g: final: prev:
76 let
77 fApplied = f final prev;
78 in
79 recursiveUpdateAll fApplied (g final (recursiveUpdateAll prev fApplied));
80
81 # Adapted From: https://github.com/NixOS/nixpkgs/blob/907316e1d29bcc2416a2341bf7240d1bdbd374a5/lib/fixed-points.nix#L342-L406
82 composeManyMergedExtensions = foldr composeMergedExtensions (final: prev: { });
83
84 # Adapted From: https://github.com/NixOS/nixpkgs/blob/907316e1d29bcc2416a2341bf7240d1bdbd374a5/lib/fixed-points.nix#L430-L452
85 mkMergeExtensibleWithCustomName =
86 extenderName: rattrs:
87 fix' (
88 self:
89 (rattrs self)
90 // {
91 ${extenderName} = f: mkMergeExtensibleWithCustomName extenderName (mergeExtends f rattrs);
92 }
93 );
94
95 # Adapted From: https://github.com/NixOS/nixpkgs/blob/907316e1d29bcc2416a2341bf7240d1bdbd374a5/lib/fixed-points.nix#L408-L428
96 mkMergeExtensible = mkMergeExtensibleWithCustomName "extend";
97
98 tracer = items: compose (map (item: builtins.trace item) items);
99 deepSeqVal = value: builtins.deepSeq value value;
100
101 import = {
102 can =
103 f:
104 let
105 fString = toString f;
106 in
107 ((isString f) || (isPath f))
108 && ((hasSuffix ".nix" fString) || ((builtins.readDir fString) ? "default.nix"));
109 should =
110 f:
111 let
112 should_import = silicon.import.can f;
113 should_return = builtins.isAttrs f || builtins.isFunction f;
114 in
115 {
116 success = should_import || should_return;
117 value =
118 if should_import then
119 (builtins.import f)
120 else if should_return then
121 f
122 else
123 false;
124 };
125 # TODO: Use an args set of includes and ignores
126 all = rec {
127 named =
128 _dir:
129 {
130 ignores ? "default",
131 recurse ? false,
132 }:
133 let
134 dir = toString _dir;
135 removeNix = removeSuffix ".nix";
136 _ignores = toList ignores;
137 in
138 if (builtins.pathExists dir) then
139 (pipe dir (
140 if recurse then
141 [
142 filesystem.listFilesRecursive
143 (filter (
144 file: (hasSuffix ".nix" file) && (!((elem (removeNix file) _ignores) || (hasPrefix "_" file)))
145 ))
146 (map (file: nameValuePair (builtins.baseNameOf (removeNix file)) (builtins.import file)))
147 builtins.listToAttrs
148 ]
149 else
150 [
151 builtins.readDir
152 (filterAttrs (
153 n: v:
154 (!(elem (removeNix n) _ignores))
155 && (!(hasPrefix "_" n))
156 && (
157 if (v == "directory") then
158 ((builtins.readDir "${dir}/${n}") ? "default.nix")
159 else
160 (hasSuffix ".nix" n)
161 )
162 ))
163 (mapAttrs' (n: v: nameValuePair (removeNix n) (builtins.import "${dir}/${n}")))
164 ]
165 ))
166 else
167 { };
168 attrs =
169 _dir:
170 args@{
171 ignores ? [ ],
172 loader ? id,
173 }:
174 let
175 dir = toString _dir;
176 removeNix = removeSuffix ".nix";
177 _ignores = toList ignores;
178 in
179 if (builtins.pathExists dir) then
180 (pipe dir [
181 builtins.readDir
182 (filterAttrs (n: v: !((elem (removeNix n) _ignores) || (hasPrefix "_" n))))
183 (mapAttrs' (
184 n: v:
185 nameValuePair (removeNix n) (
186 if (v == "directory") then
187 (attrs "${dir}/${n}" args)
188 else if (hasSuffix ".nix" n) then
189 (builtins.import "${dir}/${n}")
190 else
191 (loader "${dir}/${n}")
192 )
193 ))
194 ])
195 else
196 { };
197 __functor =
198 self: _dir: args:
199 builtins.attrValues (named _dir args);
200 recursed =
201 dir:
202 {
203 ignores ? [ ],
204 }:
205 let
206 _ignores = toList ignores;
207 in
208 if (builtins.pathExists dir) then
209 (pipe dir [
210 toString
211 filesystem.listFilesRecursive
212 (filter (
213 file:
214 (hasSuffix ".nix" file) && (!((elem (removeSuffix ".nix" file) _ignores) || (hasPrefix "_" file)))
215 ))
216 (map builtins.import)
217 ])
218 else
219 [ ];
220 };
221 };
222
223 intersectArgs = f: with builtins; intersectAttrs (functionArgs f);
224
225 callFunction = f: args: f (intersectArgs f args);
226 callFunction' =
227 f: args: functionArgs:
228 f (intersectAttrs functionArgs args);
229
230 compose = flip pipe;
231
232 callLib =
233 final: prev: self: super: inheritance: file:
234 let
235 args = {
236
237 # `final` is the final state of `lib`
238 # `prev` is the original state of `lib`
239 # `self` is the final state of `syvl`
240 # `super` is the original state of `syvl`
241 ext = {
242 inherit final prev;
243 self = final.syvl;
244 super = prev.syvl;
245 };
246
247 lib = final;
248 inherit (final) syvl;
249 inherit silicon;
250 }
251 // inheritance;
252 ifile = builtins.import file;
253 in
254 if (isAttrs file) then
255 file
256 else if (isFunction file) then
257 (callFunction file args)
258 else if (isAttrs ifile) then
259 ifile
260 else
261 (callFunction ifile args);
262
263 mks = {
264 call =
265 final: prev: self: super: inheritance: f:
266 let
267 apply = callLib final prev self super inheritance;
268 e = silicon.import.should f;
269 in
270 if e.success then
271 (apply e.value)
272 else if (isList f) then
273 (map apply f)
274 else
275 (map apply (silicon.import.all f { }));
276
277 extend =
278 name: final: prev: inheritance: f:
279 let
280 update =
281 silicon: self: super:
282 let
283 extension = mks.call final prev self super inheritance f;
284 in
285 if (isAttrs extension) then
286 (recursiveUpdateAll silicon extension)
287 else
288 (foldl' recursiveUpdateAll silicon extension);
289 in
290 if (hasAttr name prev) then
291 (prev.${name}.extend (update { }))
292 else
293 (mkMergeExtensible (self: update silicon self { }));
294
295 lib =
296 name: lib: inheritance: f:
297 lib.extend (final: prev: { ${name} = mks.extend name final prev inheritance f; });
298
299 "${_name}lib" = mks.lib _name;
300
301 libs =
302 lib: inheritances: fs:
303 lib.extend (
304 final: prev: mapAttrs (name: mks.extend name final prev (inheritances.${name} or { })) fs
305 );
306
307 };
308 __functor = _: mks.lib _name;
309 };
310in
311with silicon;
312{
313 ${_name} = mks.extend _name final prev { inherit inputs; } (silicon.import.all ./. { });
314}