Move property processing, type checking, and merge code into a function
This makes the relationship between property types clearer, and more importantly will let option types parameterized by other option types reuse the code for delegated type checking and merging.
This commit is contained in:
parent
decf15fd57
commit
9255c48a06
|
@ -106,12 +106,9 @@ rec {
|
||||||
else []
|
else []
|
||||||
) configs);
|
) configs);
|
||||||
nrOptions = count (m: isOption m.options) decls;
|
nrOptions = count (m: isOption m.options) decls;
|
||||||
# Process mkMerge and mkIf properties.
|
# Extract the definitions for this loc
|
||||||
defns' = concatMap (m:
|
defns' = map (m: { inherit (m) file; value = m.config.${name}; })
|
||||||
if m.config ? ${name}
|
(filter (m: m.config ? ${name}) configs);
|
||||||
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties m.config.${name})
|
|
||||||
else []
|
|
||||||
) 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);
|
||||||
|
@ -177,27 +174,17 @@ rec {
|
||||||
config value. */
|
config value. */
|
||||||
evalOptionValue = loc: opt: defs:
|
evalOptionValue = loc: opt: defs:
|
||||||
let
|
let
|
||||||
# Process mkOverride properties, adding in the default
|
# Add in the default value for this option, if any.
|
||||||
# value specified in the option declaration (if any).
|
defs' = (optional (opt ? default)
|
||||||
defsFinal' = filterOverrides
|
{ file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
|
||||||
((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs);
|
# Handle properties, check types, and merge everything together
|
||||||
# Sort mkOrder properties.
|
inherit (mergeDefinitions loc opt.type defs') defsFinal mergedValue;
|
||||||
defsFinal =
|
|
||||||
# Avoid sorting if we don't have to.
|
|
||||||
if any (def: def.value._type or "" == "order") defsFinal'
|
|
||||||
then sortProperties defsFinal'
|
|
||||||
else defsFinal';
|
|
||||||
files = map (def: def.file) defsFinal;
|
files = map (def: def.file) defsFinal;
|
||||||
# Type-check the remaining definitions, and merge them if
|
|
||||||
# possible.
|
|
||||||
merged =
|
merged =
|
||||||
if defsFinal == [] then
|
if defsFinal == [] then
|
||||||
throw "The option `${showOption loc}' is used but not defined."
|
throw "The option `${showOption loc}' is used but not defined."
|
||||||
else
|
else
|
||||||
fold (def: res:
|
mergedValue;
|
||||||
if opt.type.check def.value then res
|
|
||||||
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.")
|
|
||||||
(opt.type.merge loc defsFinal) defsFinal;
|
|
||||||
# Finally, apply the ‘apply’ function to the merged
|
# Finally, apply the ‘apply’ function to the merged
|
||||||
# value. This allows options to yield a value computed
|
# value. This allows options to yield a value computed
|
||||||
# from the definitions.
|
# from the definitions.
|
||||||
|
@ -209,6 +196,33 @@ rec {
|
||||||
inherit files;
|
inherit files;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Merge definitions of a value of a given type
|
||||||
|
mergeDefinitions = loc: type: defs: rec {
|
||||||
|
defsFinal =
|
||||||
|
let
|
||||||
|
# Process mkMerge and mkIf properties
|
||||||
|
discharged = concatMap (m:
|
||||||
|
map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value)
|
||||||
|
) defs;
|
||||||
|
|
||||||
|
# Process mkOverride properties
|
||||||
|
overridden = filterOverrides discharged;
|
||||||
|
|
||||||
|
# Sort mkOrder properties
|
||||||
|
sorted =
|
||||||
|
# Avoid sorting if we don't have to.
|
||||||
|
if any (def: def.value._type or "" == "order") overridden
|
||||||
|
then sortProperties overridden
|
||||||
|
else overridden;
|
||||||
|
in sorted;
|
||||||
|
|
||||||
|
# Type-check the remaining definitions, and merge them
|
||||||
|
mergedValue = fold (def: res:
|
||||||
|
if type.check def.value then res
|
||||||
|
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.")
|
||||||
|
(type.merge loc defsFinal) defsFinal;
|
||||||
|
};
|
||||||
|
|
||||||
/* Given a config set, expand mkMerge properties, and push down the
|
/* Given a config set, expand mkMerge properties, and push down the
|
||||||
other properties into the children. The result is a list of
|
other properties into the children. The result is a list of
|
||||||
config sets that do not have properties at top-level. For
|
config sets that do not have properties at top-level. For
|
||||||
|
|
Loading…
Reference in New Issue