Merge pull request #45038 from symphorien/optopt
module system: rework module merging
This commit is contained in:
commit
9113696051
@ -145,7 +145,7 @@ rec {
|
|||||||
foldAttrs = op: nul: list_of_attrs:
|
foldAttrs = op: nul: list_of_attrs:
|
||||||
fold (n: a:
|
fold (n: a:
|
||||||
fold (name: o:
|
fold (name: o:
|
||||||
o // (listToAttrs [{inherit name; value = op n.${name} (a.${name} or nul); }])
|
o // { ${name} = op n.${name} (a.${name} or nul); }
|
||||||
) a (attrNames n)
|
) a (attrNames n)
|
||||||
) {} list_of_attrs;
|
) {} list_of_attrs;
|
||||||
|
|
||||||
|
@ -192,29 +192,53 @@ rec {
|
|||||||
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
|
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
|
||||||
|
|
||||||
mergeModules' = prefix: options: configs:
|
mergeModules' = prefix: options: configs:
|
||||||
listToAttrs (map (name: {
|
let
|
||||||
|
/* byName is like foldAttrs, but will look for attributes to merge in the
|
||||||
|
specified attribute name.
|
||||||
|
|
||||||
|
byName "foo" (module: value: ["module.hidden=${module.hidden},value=${value}"])
|
||||||
|
[
|
||||||
|
{
|
||||||
|
hidden="baz";
|
||||||
|
foo={qux="bar"; gla="flop";};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
hidden="fli";
|
||||||
|
foo={qux="gne"; gli="flip";};
|
||||||
|
}
|
||||||
|
]
|
||||||
|
===>
|
||||||
|
{
|
||||||
|
gla = [ "module.hidden=baz,value=flop" ];
|
||||||
|
gli = [ "module.hidden=fli,value=flip" ];
|
||||||
|
qux = [ "module.hidden=baz,value=bar" "module.hidden=fli,value=gne" ];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
byName = attr: f: modules: foldl' (acc: module:
|
||||||
|
foldl' (inner: name:
|
||||||
|
inner // { ${name} = (acc.${name} or []) ++ (f module module.${attr}.${name}); }
|
||||||
|
) acc (attrNames module.${attr})
|
||||||
|
) {} modules;
|
||||||
|
# an attrset 'name' => list of submodules that declare ‘name’.
|
||||||
|
declsByName = byName "options"
|
||||||
|
(module: option: [{ inherit (module) file; options = option; }])
|
||||||
|
options;
|
||||||
|
# an attrset 'name' => list of submodules that define ‘name’.
|
||||||
|
defnsByName = byName "config" (module: value:
|
||||||
|
map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
|
||||||
|
) configs;
|
||||||
|
# extract the definitions for each loc
|
||||||
|
defnsByName' = byName "config"
|
||||||
|
(module: value: [{ inherit (module) file; inherit value; }])
|
||||||
|
configs;
|
||||||
|
in
|
||||||
|
(flip mapAttrs declsByName (name: decls:
|
||||||
# We're descending into attribute ‘name’.
|
# We're descending into attribute ‘name’.
|
||||||
inherit name;
|
|
||||||
value =
|
|
||||||
let
|
let
|
||||||
loc = prefix ++ [name];
|
loc = prefix ++ [name];
|
||||||
# Get all submodules that declare ‘name’.
|
defns = defnsByName.${name} or [];
|
||||||
decls = concatMap (m:
|
defns' = defnsByName'.${name} or [];
|
||||||
if m.options ? ${name}
|
|
||||||
then [ { inherit (m) file; options = m.options.${name}; } ]
|
|
||||||
else []
|
|
||||||
) options;
|
|
||||||
# Get all submodules that define ‘name’.
|
|
||||||
defns = concatMap (m:
|
|
||||||
if m.config ? ${name}
|
|
||||||
then map (config: { inherit (m) file; inherit config; })
|
|
||||||
(pushDownProperties m.config.${name})
|
|
||||||
else []
|
|
||||||
) configs;
|
|
||||||
nrOptions = count (m: isOption m.options) decls;
|
nrOptions = count (m: isOption m.options) decls;
|
||||||
# Extract the definitions for this loc
|
|
||||||
defns' = map (m: { inherit (m) file; value = m.config.${name}; })
|
|
||||||
(filter (m: m.config ? ${name}) configs);
|
|
||||||
in
|
in
|
||||||
if nrOptions == length decls then
|
if nrOptions == length decls then
|
||||||
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
|
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
|
||||||
@ -226,8 +250,8 @@ rec {
|
|||||||
in
|
in
|
||||||
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
|
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
|
||||||
else
|
else
|
||||||
mergeModules' loc decls defns;
|
mergeModules' loc decls defns
|
||||||
}) (concatMap (m: attrNames m.options) options))
|
))
|
||||||
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
|
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
|
||||||
|
|
||||||
/* Merge multiple option declarations into a single declaration. In
|
/* Merge multiple option declarations into a single declaration. In
|
||||||
|
Loading…
Reference in New Issue
Block a user