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
This commit is contained in:
Nicolas Pierron 2009-10-12 17:51:21 +00:00
parent 81694a7f54
commit b15cbb639e

View file

@ -165,7 +165,7 @@ rec {
declarationsOf = name: filter (m: m ? options) (modulesOf name); declarationsOf = name: filter (m: m ? options) (modulesOf name);
definitionsOf = name: filter (m: m ? config ) (modulesOf name); definitionsOf = name: filter (m: m ? config ) (modulesOf name);
recurseInto = name: modules: recurseInto = name:
moduleMerge (addName name) (modulesOf name); moduleMerge (addName name) (modulesOf name);
recurseForOption = name: modules: recurseForOption = name: modules:
@ -184,105 +184,126 @@ rec {
eol = "\n"; eol = "\n";
errDefinedWithoutDeclaration = name: allNames = modulesNames modules;
let
badModules = getResults = m:
filter (m: ! isAttrs m.config) let fetchResult = s: mapAttrs (n: v: v.result) s; in {
(definitionsOf name); options = fetchResult m.options;
in config = fetchResult m.config;
"${eol };
}Option '${addName name}' defined without option declaration.${eol
}${errorSource badModules}${eol
}";
endRecursion = { options = {}; config = {}; }; endRecursion = { options = {}; config = {}; };
in if modules == [] then endRecursion else in if modules == [] then endRecursion else
getResults (fix (crossResults: moduleZip {
options = lib.zipWithNames allNames (name: values: rec {
config = lib.getAttr name crossResults.config;
lib.fix (result: declarations = declarationsOf name;
moduleZip { declarationSources =
options = lib.zip (name: values: map (m: {
if any isOption values then source = m.key;
let }) declarations;
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)); hasOptions = values != [];
} isOption = any lib.isOption values;
else if all isAttrs values then
(recurseInto name modules).options 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 else
throw "${eol throw "${eol
}Unexpected type where option declarations are expected.${eol }Unexpected type where option declarations are expected.${eol
}${errorSource (declarationsOf name)}${eol }${errorSource declarations}${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 config = lib.zipWithNames allNames (name: values_: rec {
let defs = evalDefinitions opt values; in option = lib.getAttr name crossResults.options;
lib.addErrorContext "${eol
}while evaluating the option '${addName name}'.${eol definitions = definitionsOf name;
}${errorSource (modulesOf name)}${eol definitionSources =
}" ( map (m: {
opt.apply ( source = m.key;
if defs == [] then value = m.config;
if opt ? default then opt.default }) definitions;
else throw "Not defined."
else opt.merge defs
) 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
) )
);
else if hasOpt && lib.attrNames opt == [] then strictResult = builtins.tryEval (builtins.toXML value);
throw (errDefinedWithoutDeclaration name)
else if any (v: isOption (rmProperties v)) values then recurse = (recurseInto name).config;
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 configIsAnOption = v: isOption (rmProperties v);
(recurseInto name modules).config errConfigIsAnOption =
else let badModules = filter (m: configIsAnOption m.config) definitions; in
throw (errDefinedWithoutDeclaration name) "${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: fixMergeModules = initModules: {...}@args:
lib.fix (result: lib.fix (result: