summary refs log tree commit diff
path: root/pkgs/lib
diff options
context:
space:
mode:
authorNicolas Pierron <nicolas.b.pierron@gmail.com>2009-10-12 17:51:21 +0000
committerNicolas Pierron <nicolas.b.pierron@gmail.com>2009-10-12 17:51:21 +0000
commitb15cbb639e076471735d77b67949e9c7878cdea9 (patch)
tree508c0573c2285c748773507208c076cef33ea1f5 /pkgs/lib
parent81694a7f54c518efb55da278d661c7569ee4867a (diff)
downloadnixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar.gz
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar.bz2
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar.lz
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar.xz
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.tar.zst
nixpkgs-b15cbb639e076471735d77b67949e9c7878cdea9.zip
Refactor a bit to add names to intermediate computations. Add a cross
temporary result to fetch information from the evaluation to make them
available inside the option declaration.

Add: isNotDefined flag inside the option.

svn path=/nixpkgs/trunk/; revision=17766
Diffstat (limited to 'pkgs/lib')
-rw-r--r--pkgs/lib/modules.nix201
1 files changed, 111 insertions, 90 deletions
diff --git a/pkgs/lib/modules.nix b/pkgs/lib/modules.nix
index a60b240beee..1744d39d8de 100644
--- a/pkgs/lib/modules.nix
+++ b/pkgs/lib/modules.nix
@@ -165,7 +165,7 @@ rec {
       declarationsOf = name: filter (m: m ? options) (modulesOf name);
       definitionsOf  = name: filter (m: m ? config ) (modulesOf name);
 
-      recurseInto = name: modules:
+      recurseInto = name:
         moduleMerge (addName name) (modulesOf name);
 
       recurseForOption = name: modules:
@@ -184,105 +184,126 @@ rec {
 
       eol = "\n";
 
-      errDefinedWithoutDeclaration = name:
-        let
-          badModules =
-            filter (m: ! isAttrs m.config)
-              (definitionsOf name);
-        in
-          "${eol
-          }Option '${addName name}' defined without option declaration.${eol
-          }${errorSource badModules}${eol
-          }";
+      allNames = modulesNames modules;
+
+      getResults = m:
+        let fetchResult = s: mapAttrs (n: v: v.result) s; in {
+          options = fetchResult m.options;
+          config = fetchResult m.config;
+        };
 
       endRecursion =  { options = {}; config = {}; };
 
     in if modules == [] then endRecursion else
+      getResults (fix (crossResults: moduleZip {
+        options = lib.zipWithNames allNames (name: values: rec {
+          config = lib.getAttr name crossResults.config;
+
+          declarations = declarationsOf name;
+          declarationSources =
+            map (m: {
+              source = m.key;
+            }) declarations;
+
 
-      lib.fix (result:
-        moduleZip {
-          options = lib.zip (name: values:
-            if any isOption values then
-              let
-                decls = # add location to sub-module options.
-                  map (m:
-                    mapSubOptions
-                      (unifyOptionModule {inherit (m) key;})
-                      m.options
-                  ) (declarationsOf name);
-              in
-                addOptionMakeUp
-                  { name = addName name; recurseInto = recurseForOption; }
-                  (mergeOptionDecls decls)
-                // {
-                  declarations =
-                    map (m: {
-                      source = m.key;
-                    }) (declarationsOf name);
-    
-                  definitions =
-                    map (m: {
-                      source = m.key;
-                      value = m.config;
-                    }) (definitionsOf name);
-
-                  config = builtins.tryEval
-                    (builtins.toXML (lib.getAttr name result.config));
-                }
-            else if all isAttrs values then
-              (recurseInto name modules).options
+          hasOptions = values != [];
+          isOption = any lib.isOption values;
+
+          decls = # add location to sub-module options.
+            map (m:
+              mapSubOptions
+                (unifyOptionModule {inherit (m) key;})
+                m.options
+            ) declarations;
+
+          decl =
+            addOptionMakeUp
+              { name = addName name; recurseInto = recurseForOption; }
+              (mergeOptionDecls decls);
+
+          value = decl // (with config; {
+            inherit (config) isNotDefined;
+            declarations = declarationSources;
+            definitions = definitionSources;
+            config = strictResult;
+          });
+
+          recurse = (recurseInto name).options;
+
+          result =
+            if isOption then value
+            else if all isAttrs values then recurse
             else
               throw "${eol
                 }Unexpected type where option declarations are expected.${eol
-                }${errorSource (declarationsOf name)}${eol
-              }"
-          );
-
-          config = lib.zipWithNames (modulesNames modules) (name: values_:
-            let
-              hasOpt = builtins.hasAttr name result.options;
-              opt = lib.getAttr name result.options;
-              values = values_ ++
-                optionals
-                  (hasOpt && isOption opt && opt ? extraConfigs)
-                  opt.extraConfigs;
-
-            in if hasOpt && isOption opt then
-              let defs = evalDefinitions opt values; in
-              lib.addErrorContext "${eol
-                }while evaluating the option '${addName name}'.${eol
-                }${errorSource (modulesOf name)}${eol
-              }" (
-                opt.apply (
-                  if defs == [] then
-                    if opt ? default then opt.default
-                    else throw "Not defined."
-                  else opt.merge defs
-                )
-              )
+                }${errorSource declarations}${eol
+              }";
 
-            else if hasOpt && lib.attrNames opt == [] then
-              throw (errDefinedWithoutDeclaration name)
-
-            else if any (v: isOption (rmProperties v)) values then
-              let
-                badModules =
-                  filter (m: isOption m.config)
-                    (definitionsOf name);
-              in
-                throw "${eol
-                  }Option ${addName name} is defined in the configuration section.${eol
-                  }${errorSource badModules}${eol
-                }"
-
-            else if all isAttrs values then
-              (recurseInto name modules).config
-            else
-              throw (errDefinedWithoutDeclaration name)
-          );
+        });
+
+        config = lib.zipWithNames allNames (name: values_: rec {
+          option = lib.getAttr name crossResults.options;
+
+          definitions = definitionsOf name;
+          definitionSources =
+            map (m: {
+              source = m.key;
+              value = m.config;
+            }) definitions;
+
+
+          values = values_ ++
+            optionals (option.isOption && option.decl ? extraConfigs)
+              option.decl.extraConfigs;
+
+          defs = evalDefinitions option.decl values;
+
+          isNotDefined = defs == [];
+
+          value =
+            lib.addErrorContext "${eol
+              }while evaluating the option '${addName name}'.${eol
+              }${errorSource (modulesOf name)}${eol
+            }" (
+              let opt = option.decl; in
+              opt.apply (
+                if isNotDefined then
+                  if opt ? default then opt.default
+                  else throw "Not defined."
+                else opt.merge defs
+              )
+            );
+
+          strictResult = builtins.tryEval (builtins.toXML value);
+
+          recurse = (recurseInto name).config;
+
+          configIsAnOption = v: isOption (rmProperties v);
+          errConfigIsAnOption =
+            let badModules = filter (m: configIsAnOption m.config) definitions; in
+            "${eol
+              }Option ${addName name} is defined in the configuration section.${eol
+              }${errorSource badModules}${eol
+            }";
+
+          errDefinedWithoutDeclaration =
+            let badModules = definitions; in
+            "${eol
+              }Option '${addName name}' defined without option declaration.${eol
+              }${errorSource badModules}${eol
+            }";
+
+          result =
+            if option.isOption then value
+            else if !option.hasOptions then throw errDefinedWithoutDeclaration
+            else if any configIsAnOption values then throw errConfigIsAnOption
+            else if all isAttrs values then recurse
+            # plain value during the traversal
+            else throw errDefinedWithoutDeclaration;
+
+        });
+      } modules));
 
-        } modules
-      );
 
   fixMergeModules = initModules: {...}@args:
     lib.fix (result: