summary refs log tree commit diff
path: root/lib/modules.nix
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2014-05-01 17:29:30 -0400
committerNicolas B. Pierron <nicolas.b.pierron@gmail.com>2015-03-12 23:42:57 +0100
commit9255c48a06913a064da4e103e6b7c1d94fb4fb90 (patch)
tree05f47d92e7a82dff212dd7329c8bb7b1bf1c0f45 /lib/modules.nix
parentdecf15fd57c8f26079cdfc7572f1097decfc296f (diff)
downloadnixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar.gz
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar.bz2
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar.lz
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar.xz
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.tar.zst
nixpkgs-9255c48a06913a064da4e103e6b7c1d94fb4fb90.zip
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.
Diffstat (limited to 'lib/modules.nix')
-rw-r--r--lib/modules.nix58
1 files changed, 36 insertions, 22 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index d0b8f90e5ce..8bf8016b431 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -106,12 +106,9 @@ rec {
               else []
             ) configs);
           nrOptions = count (m: isOption m.options) decls;
-          # Process mkMerge and mkIf properties.
-          defns' = concatMap (m:
-            if m.config ? ${name}
-              then map (m': { inherit (m) file; value = m'; }) (dischargeProperties m.config.${name})
-              else []
-            ) configs;
+          # Extract the definitions for this loc
+          defns' = map (m: { inherit (m) file; value = m.config.${name}; })
+            (filter (m: m.config ? ${name}) configs);
         in
           if nrOptions == length decls then
             let opt = fixupOptionType loc (mergeOptionDecls loc decls);
@@ -177,27 +174,17 @@ rec {
      config value. */
   evalOptionValue = loc: opt: defs:
     let
-      # Process mkOverride properties, adding in the default
-      # value specified in the option declaration (if any).
-      defsFinal' = filterOverrides
-        ((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs);
-      # Sort mkOrder properties.
-      defsFinal =
-        # Avoid sorting if we don't have to.
-        if any (def: def.value._type or "" == "order") defsFinal'
-        then sortProperties defsFinal'
-        else defsFinal';
+      # Add in the default value for this option, if any.
+      defs' = (optional (opt ? default)
+        { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
+      # Handle properties, check types, and merge everything together
+      inherit (mergeDefinitions loc opt.type defs') defsFinal mergedValue;
       files = map (def: def.file) defsFinal;
-      # Type-check the remaining definitions, and merge them if
-      # possible.
       merged =
         if defsFinal == [] then
           throw "The option `${showOption loc}' is used but not defined."
         else
-          fold (def: res:
-            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;
+          mergedValue;
       # Finally, apply the ‘apply’ function to the merged
       # value.  This allows options to yield a value computed
       # from the definitions.
@@ -209,6 +196,33 @@ rec {
         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
      other properties into the children.  The result is a list of
      config sets that do not have properties at top-level.  For