Add mkMerge and obsolete mkThenElse.

svn path=/nixpkgs/trunk/; revision=33796
This commit is contained in:
Nicolas Pierron 2012-04-15 23:31:48 +00:00
parent a9c51d7af3
commit 8a67709183
2 changed files with 61 additions and 14 deletions

View File

@ -41,29 +41,31 @@ rec {
# attributes. # attributes.
unifyModuleSyntax = m: unifyModuleSyntax = m:
let let
getImports = m: delayedModule = delayProperties m;
getImports =
if m ? config || m ? options then if m ? config || m ? options then
attrByPath ["imports"] [] m attrByPath ["imports"] [] m
else else
toList (rmProperties (attrByPath ["require"] [] (delayProperties m))); toList (rmProperties (attrByPath ["require"] [] delayedModule));
getImportedPaths = m: filter isPath (getImports m); getImportedPaths = filter isPath getImports;
getImportedSets = m: filter (x: !isPath x) (getImports m); getImportedSets = filter (x: !isPath x) getImports;
getConfig =
removeAttrs delayedModule ["require" "key"];
getConfig = m:
removeAttrs (delayProperties m) ["require" "key"];
in in
if isModule m then if isModule m then
{ key = "<unknown location>"; } // m { key = "<unknown location>"; } // m
else else
{ {
key = "<unknown location>"; key = "<unknown location>";
imports = getImportedPaths m; imports = getImportedPaths;
config = getConfig m; config = getConfig;
} // ( } // (
if getImportedSets m != [] then if getImportedSets != [] then
assert tail (getImportedSets m) == []; assert tail getImportedSets == [];
{ options = head (getImportedSets m); } { options = head getImportedSets; }
else else
{} {}
); );
@ -124,9 +126,25 @@ rec {
value value
) module; ) module;
# Handle mkMerge function left behind after a delay property.
moduleFlattenMerge = module:
if module ? config &&
isProperty module.config &&
isMerge module.config.property
then
(map (cfg: { key = module.key; config = cfg; }) module.config.content)
++ [ (module // { config = {}; }) ]
else
[ module ];
# Handle mkMerge attributes which are left behind by previous delay
# properties and convert them into a list of modules. Delay properties
# inside the config attribute of a module and create a second module if a
# mkMerge attribute was left behind.
#
# Module -> [ Module ]
delayModule = module: delayModule = module:
moduleApply { config = delayProperties; } module; map (moduleApply { config = delayProperties; }) (moduleFlattenMerge module);
evalDefinitions = opt: values: evalDefinitions = opt: values:
if opt ? type && opt.type.delayOnGlobalEval then if opt ? type && opt.type.delayOnGlobalEval then
@ -170,7 +188,7 @@ rec {
addName = name: addName = name:
if path == "" then name else path + "." + name; if path == "" then name else path + "." + name;
modules = map delayModule modules_; modules = concatLists (map delayModule modules_);
modulesOf = name: filterModules name modules; modulesOf = name: filterModules name modules;
declarationsOf = name: filter (m: m ? options) (modulesOf name); declarationsOf = name: filter (m: m ? options) (modulesOf name);

View File

@ -82,7 +82,19 @@ rec {
attrs; attrs;
delayProperties = # implicit attrs argument. delayProperties = # implicit attrs argument.
delayPropertiesWithIter (f: p: v: lib.mapAttrs f v) ""; let
# mapAttrs except that it also recurse into potential mkMerge
# functions. This may cause a strictness issue because looking the
# type of a string implies evaluating it.
iter = fun: path: value:
lib.mapAttrs (attr: val:
if isProperty val && isMerge val.property then
val // { content = map (fun attr) val.content; }
else
fun attr val
) value;
in
delayPropertiesWithIter iter "";
# Call onDelay functions. # Call onDelay functions.
triggerPropertiesDelay = name: attrs: triggerPropertiesDelay = name: attrs:
@ -179,6 +191,22 @@ rec {
copyProperties = attrs: newAttrs: copyProperties = attrs: newAttrs:
foldProperty id (x: newAttrs) attrs; foldProperty id (x: newAttrs) attrs;
/* Merge. */
# Create "merge" statement which is skipped by the delayProperty function
# and interpreted by the underlying system using properties (modules).
# Create a "Merge" property which only contains a condition.
isMerge = attrs: (typeOf attrs) == "merge";
mkMerge = content: mkProperty {
property = {
_type = "merge";
onDelay = name: val: throw "mkMerge is not the first of the list of properties.";
onEval = val: throw "mkMerge is not allowed on option definitions.";
};
inherit content;
};
/* If. ThenElse. Always. */ /* If. ThenElse. Always. */
# create "if" statement that can be delayed on sets until a "then-else" or # create "if" statement that can be delayed on sets until a "then-else" or
@ -202,6 +230,7 @@ rec {
isThenElse = attrs: (typeOf attrs) == "then-else"; isThenElse = attrs: (typeOf attrs) == "then-else";
mkThenElse = attrs: mkThenElse = attrs:
assert attrs ? thenPart && attrs ? elsePart; assert attrs ? thenPart && attrs ? elsePart;
__trace "Obsolete usage of mkThenElse, replace it by mkMerge."
mkProperty { mkProperty {
property = { property = {
_type = "then-else"; _type = "then-else";