From a440fba8e3cf552a2609be9da0202b355adebe2c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 26 Jun 2009 13:53:31 +0000 Subject: [PATCH] * Refactoring: move the types out of options.nix, which is much too big. Also, they could be useful beyond option handling. svn path=/nixpkgs/trunk/; revision=16055 --- pkgs/lib/default.nix | 5 +- pkgs/lib/options.nix | 112 ++------------------------------------- pkgs/lib/types.nix | 121 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 111 deletions(-) create mode 100644 pkgs/lib/types.nix diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix index 55e7c8ab1f8..de5c04811c0 100644 --- a/pkgs/lib/default.nix +++ b/pkgs/lib/default.nix @@ -7,13 +7,14 @@ let attrsets = import ./attrsets.nix; sources = import ./sources.nix; options = import ./options.nix; + types = import ./types.nix; meta = import ./meta.nix; debug = import ./debug.nix; misc = import ./misc.nix; in - { inherit trivial lists strings stringsWithDeps attrsets sources options meta debug; } + { inherit trivial lists strings stringsWithDeps attrsets sources options types meta debug; } # !!! don't include everything at top-level; perhaps only the most # commonly used functions. // trivial // lists // strings // stringsWithDeps // attrsets // sources - // options // meta // debug // misc + // options // types // meta // debug // misc diff --git a/pkgs/lib/options.nix b/pkgs/lib/options.nix index 6f408090738..6cf21ec6bcf 100644 --- a/pkgs/lib/options.nix +++ b/pkgs/lib/options.nix @@ -10,9 +10,8 @@ with import ./attrsets.nix; rec { - - hasType = x: isAttrs x && x ? _type; - typeOf = x: if hasType x then x._type else ""; + inherit (lib) typeOf; + isOption = attrs: (typeOf attrs) == "option"; mkOption = attrs: attrs // { @@ -131,112 +130,7 @@ rec { opt1 // opt2 )) {} opts; - - # name (name of the type) - # check (boolean function) - # merge (default merge function) - # iter (iterate on all elements contained in this type) - # fold (fold all elements contained in this type) - # hasOptions (boolean: whatever this option contains an option set) - # path (path contatenated to the option name contained contained in the option set) - isOptionType = attrs: (typeOf attrs) == "option-type"; - mkOptionType = attrs@{ - name - , check ? (x: true) - , merge ? mergeDefaultOption - # Handle complex structure types. - , iter ? (f: path: v: f path v) - , fold ? (op: nul: v: op v nul) - , docPath ? lib.id - # If the type can contains option sets. - , hasOptions ? false - }: { _type = "option-type"; - inherit name check merge iter fold docPath hasOptions; - }; - - - types = { - - inferred = mkOptionType { - name = "inferred type"; - }; - - bool = mkOptionType { - name = "boolean"; - check = lib.traceValIfNot builtins.isBool; - merge = fold lib.or false; - }; - - int = mkOptionType { - name = "integer"; - check = lib.traceValIfNot builtins.isInt; - }; - - string = mkOptionType { - name = "string"; - check = lib.traceValIfNot (x: builtins ? isString -> builtins.isString x); - merge = lib.concatStrings; - }; - - attrs = mkOptionType { - name = "attribute set"; - check = lib.traceValIfNot builtins.isAttrs; - merge = fold lib.mergeAttrs {}; - }; - - # derivation is a reserved keyword. - package = mkOptionType { - name = "derivation"; - check = lib.traceValIfNot isDerivation; - }; - - - list = elemType: mkOptionType { - name = "list of ${elemType.name}s"; - check = value: lib.traceValIfNot isList value && all elemType.check value; - merge = concatLists; - iter = f: path: list: map (elemType.iter f (path + ".*")) list; - fold = op: nul: list: lib.fold (e: l: elemType.fold op l e) nul list; - docPath = path: elemType.docPath (path + ".*"); - inherit (elemType) hasOptions; - }; - - attrsOf = elemType: mkOptionType { - name = "attribute set of ${elemType}s"; - check = x: lib.traceValIfNot builtins.isAttrs x - && fold (e: v: v && elemType.check e) true (lib.attrValues x); - merge = fold lib.mergeAttrs {}; - iter = f: path: set: lib.mapAttrs (name: elemType.iter f (path + "." + name)) set; - fold = op: nul: set: fold (e: l: elemType.fold op l e) nul (lib.attrValues set); - docPath = path: elemType.docPath (path + "."); - inherit (elemType) hasOptions; - }; - - uniq = elemType: mkOptionType { - inherit (elemType) name check iter fold docPath hasOptions; - merge = list: - if tail list == [] then - head list - else - throw "Multiple definitions. Only one is allowed for this option."; - }; - - nullOr = elemType: mkOptionType { - inherit (elemType) name merge docPath hasOptions; - check = x: builtins.isNull x || elemType.check x; - iter = f: path: v: if v == null then v else elemType.iter f path v; - fold = op: nul: v: if v == null then nul else elemType.fold op nul v; - }; - - optionSet = mkOptionType { - name = "option set"; - check = x: lib.traceValIfNot builtins.isAttrs x; - hasOptions = true; - }; - - }; - - + # !!! This function will be removed because this can be done with the # multiple option declarations. addDefaultOptionValues = defs: opts: opts // diff --git a/pkgs/lib/types.nix b/pkgs/lib/types.nix new file mode 100644 index 00000000000..a9fa41ebdd5 --- /dev/null +++ b/pkgs/lib/types.nix @@ -0,0 +1,121 @@ +# Definitions related to run-time type checking. Used in particular +# to type-check NixOS configurations. + +let lib = import ./default.nix; in + +with import ./lists.nix; +with import ./attrsets.nix; +with import ./options.nix; + +rec { + + hasType = x: isAttrs x && x ? _type; + typeOf = x: if hasType x then x._type else ""; + + + # name (name of the type) + # check (boolean function) + # merge (default merge function) + # iter (iterate on all elements contained in this type) + # fold (fold all elements contained in this type) + # hasOptions (boolean: whatever this option contains an option set) + # path (path contatenated to the option name contained contained in the option set) + isOptionType = attrs: typeOf attrs == "option-type"; + mkOptionType = + { name + , check ? (x: true) + , merge ? mergeDefaultOption + # Handle complex structure types. + , iter ? (f: path: v: f path v) + , fold ? (op: nul: v: op v nul) + , docPath ? lib.id + # If the type can contains option sets. + , hasOptions ? false + }: + + { _type = "option-type"; + inherit name check merge iter fold docPath hasOptions; + }; + + + types = { + + inferred = mkOptionType { + name = "inferred type"; + }; + + bool = mkOptionType { + name = "boolean"; + check = lib.traceValIfNot builtins.isBool; + merge = fold lib.or false; + }; + + int = mkOptionType { + name = "integer"; + check = lib.traceValIfNot builtins.isInt; + }; + + string = mkOptionType { + name = "string"; + check = lib.traceValIfNot (x: builtins ? isString -> builtins.isString x); + merge = lib.concatStrings; + }; + + attrs = mkOptionType { + name = "attribute set"; + check = lib.traceValIfNot builtins.isAttrs; + merge = fold lib.mergeAttrs {}; + }; + + # derivation is a reserved keyword. + package = mkOptionType { + name = "derivation"; + check = lib.traceValIfNot isDerivation; + }; + + list = elemType: mkOptionType { + name = "list of ${elemType.name}s"; + check = value: lib.traceValIfNot isList value && all elemType.check value; + merge = concatLists; + iter = f: path: list: map (elemType.iter f (path + ".*")) list; + fold = op: nul: list: lib.fold (e: l: elemType.fold op l e) nul list; + docPath = path: elemType.docPath (path + ".*"); + inherit (elemType) hasOptions; + }; + + attrsOf = elemType: mkOptionType { + name = "attribute set of ${elemType}s"; + check = x: lib.traceValIfNot builtins.isAttrs x + && fold (e: v: v && elemType.check e) true (lib.attrValues x); + merge = fold lib.mergeAttrs {}; + iter = f: path: set: lib.mapAttrs (name: elemType.iter f (path + "." + name)) set; + fold = op: nul: set: fold (e: l: elemType.fold op l e) nul (lib.attrValues set); + docPath = path: elemType.docPath (path + "."); + inherit (elemType) hasOptions; + }; + + uniq = elemType: mkOptionType { + inherit (elemType) name check iter fold docPath hasOptions; + merge = list: + if tail list == [] then + head list + else + throw "Multiple definitions. Only one is allowed for this option."; + }; + + nullOr = elemType: mkOptionType { + inherit (elemType) name merge docPath hasOptions; + check = x: builtins.isNull x || elemType.check x; + iter = f: path: v: if v == null then v else elemType.iter f path v; + fold = op: nul: v: if v == null then nul else elemType.fold op nul v; + }; + + optionSet = mkOptionType { + name = "option set"; + check = x: lib.traceValIfNot builtins.isAttrs x; + hasOptions = true; + }; + + }; + +}