summary refs log tree commit diff
path: root/pkgs/lib/default.nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2009-02-09 16:51:03 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2009-02-09 16:51:03 +0000
commit599015e8b071bc8d38779fbfc37961db1ac0f464 (patch)
tree12cfb8ef316f4021ef81d135a5c331804a817809 /pkgs/lib/default.nix
parenteebb6f106c445c5661975a60a55b07ad91c6fa47 (diff)
downloadnixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.gz
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.bz2
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.lz
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.xz
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.tar.zst
nixpkgs-599015e8b071bc8d38779fbfc37961db1ac0f464.zip
* Split lib/default.nix into several files, as it had become a big
  mess.  Also cleaned up some functions:

  - foldl appeared broken (it recursively called fold).
  - Renamed logicalAND/logicalOR to and/or.
  - Removed listOfListsToAttrs, eqStrings: obsolete.
  - Removed isInList, which does the same thing as elem.
  - stringToCharacters: don't return a "" at the end of the list.
  - Renamed concatList to concat, as concatList (singular) is a
    misnomer: it takes two lists.  Likewise, renamed mergeAttr to
    mergeAttrs.

  misc.nix still contains a lot of stuff that should be refactored and
  moved to other files.

svn path=/nixpkgs/trunk/; revision=14013
Diffstat (limited to 'pkgs/lib/default.nix')
-rw-r--r--pkgs/lib/default.nix884
1 files changed, 14 insertions, 870 deletions
diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 349d38f9055..ee3b1ad085d 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -1,873 +1,17 @@
-# Utility functions.
+let 
 
-let
-
-  inherit (builtins)
-    head tail isList stringLength substring lessThan sub
-    listToAttrs attrNames hasAttr;
+  trivial = import ./trivial.nix;
+  lists = import ./lists.nix;
+  strings = import ./strings.nix;
+  attrsets = import ./attrsets.nix;
+  sources = import ./sources.nix;
+  options = import ./options.nix;
+  debug = import ./attrsets.nix;
+  misc = import ./misc.nix;
 
 in
-
-rec {
-  listOfListsToAttrs = ll : builtins.listToAttrs (map (l : { name = (head l); value = (head (tail l)); }) ll);
-
-
-  # Identity function.
-  id = x: x;
-
-
-  # accumulates / merges all attr sets until null is fed.
-  # example: sumArgs id { a = 'a'; x = 'x'; } { y = 'y'; x = 'X'; } null
-  # result : { a = 'a'; x = 'X'; y = 'Y'; }
-  innerSumArgs = f : x : y : (if y == null then (f x)
-	else (innerSumArgs f (x // y)));
-  sumArgs = f : innerSumArgs f {};
-
-  # Advanced sumArgs version. Hm, twice as slow, I'm afraid.
-  # composedArgs id (x:x//{a="b";}) (x:x//{b=x.a + "c";}) null;
-  # {a="b" ; b="bc";};
-  innerComposedArgs = f : x : y : (if y==null then (f x)
-  	else (if (builtins.isAttrs y) then 
-		(innerComposedArgs f (x//y))
-	else (innerComposedArgs f (y x))));
-  composedArgs = f: innerComposedArgs f {};
-
-  defaultMergeArg = x : y: if builtins.isAttrs y then
-    y
-  else 
-    (y x);
-  defaultMerge = x: y: x // (defaultMergeArg x y);
-  sumTwoArgs = f: x: y: 
-    f (defaultMerge x y);
-  foldArgs = merger: f: init: x: 
-    let arg=(merger init (defaultMergeArg init x)); in  
-      # now add the function with composed args already applied to the final attrs
-    setAttrMerge "passthru" {} (f arg) ( x : x // { function = foldArgs merger f arg; } );
-
-  # returns f x // { passthru.fun = y : f (merge x y); } while preserving other passthru names.
-  # example: let ex = applyAndFun (x : removeAttrs x ["fixed"])  (mergeOrApply mergeAttr) {name = 6;};
-  #              usage1 = ex.passthru.fun { name = 7; };    # result: { name = 7;}
-  #              usage2 = ex.passthru.fun (a: a // {name = __add a.name 1; }); # result: { a = 7; }
-  # fix usage:
-  #              usage3a = ex.passthru.fun (a: a // {name2 = a.fixed.toBePassed; }); # usage3a will fail because toBePassed is not yet given
-  #              usage3b usage3a.passthru.fun { toBePassed = "foo";}; # result { name = 7; name2 = "foo"; toBePassed = "foo"; fixed = <this attrs>; }
-  applyAndFun = f : merge : x : assert (__isAttrs x || __isFunction x);
-    let takeFix = if (__isFunction x) then x else (attr: merge attr x); in
-    setAttrMerge "passthru" {} (fix (fixed : f (takeFix {inherit fixed;})))
-      ( y : y //
-        {
-          fun = z : applyAndFun f merge (fixed: merge (takeFix fixed) z);
-          funMerge = z : applyAndFun f merge (fixed: let e = takeFix fixed; in merge e (merge e z));
-        } );
-  mergeOrApply = merge : x : y : if (__isFunction y) then  y x else merge x y;
-
-  # rec { # an example of how composedArgsAndFun can be used
-  #  a  = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
-  #  # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
-  #  b  = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
-  #  # instead of passing/ overriding values you can use a merge function:
-  #  c  = b.passthru.function ( x: { a = x.a  ++ ["4"]; }); # consider using (maybeAttr "a" [] x)
-  # }
-  # result:
-  # {
-  #   a = { a = ["2"];     meta = { d = "bar"; }; passthru = { function = .. }; };
-  #   b = { a = ["3"];     meta = { d2 = "bar2"; }; passthru = { function = .. }; };
-  #   c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
-  #   # c2 is equal to c
-  # }
-  composedArgsAndFun = f: foldArgs defaultMerge f {};
-
-  # example a = pairMap (x : y : x + y) ["a" "b" "c" "d"];
-  # result: ["ab" "cd"]
-  innerPairMap = acc: f: l: 
-  	if l == [] then acc else
-	innerPairMap (acc ++ [(f (head l)(head (tail l)))])
-		f (tail (tail l));
-  pairMap = innerPairMap [];
-
-  
-  
-  # "Fold" a binary function `op' between successive elements of
-  # `list' with `nul' as the starting value, i.e., `fold op nul [x_1
-  # x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.  (This is
-  # Haskell's foldr).
-  fold = op: nul: list:
-    if list == []
-    then nul
-    else op (head list) (fold op nul (tail list));
-
-  # Haskell's fold
-  foldl = op: nul: list:
-    if list == []
-    then nul
-    else fold op (op nul (head list)) (tail list);
-
-    
-  # Concatenate a list of lists.
-  concatList = x : y : x ++ y;
-  concatLists = fold concatList [];
-
-
-  # Concatenate a list of strings.
-  concatStrings =
-    fold (x: y: x + y) "";
-
-
-  # Map and concatenate the result.
-  concatMap = f: list: concatLists (map f list);
-
-  concatMapStrings = f: list: concatStrings (map f list);
-  
-
-  # Place an element between each element of a list, e.g.,
-  # `intersperse "," ["a" "b" "c"]' returns ["a" "," "b" "," "c"].
-  intersperse = separator: list:
-    if list == [] || tail list == []
-    then list
-    else [(head list) separator]
-         ++ (intersperse separator (tail list));
-
-  toList = x : if (__isList x) then x else [x];
-
-  concatStringsSep = separator: list:
-    concatStrings (intersperse separator list);
-
-  makeLibraryPath = paths: concatStringsSep ":" (map (path: path + "/lib") paths);
-
-
-  # Flatten the argument into a single list; that is, nested lists are
-  # spliced into the top-level lists.  E.g., `flatten [1 [2 [3] 4] 5]
-  # == [1 2 3 4 5]' and `flatten 1 == [1]'.
-  flatten = x:
-    if isList x
-    then fold (x: y: (flatten x) ++ y) [] x
-    else [x];
-
-
-  # Return an attribute from nested attribute sets.  For instance ["x"
-  # "y"] applied to some set e returns e.x.y, if it exists.  The
-  # default value is returned otherwise.
-  # comment: there is also builtins.getAttr ? (is there a better name for this function?)
-  getAttr = attrPath: default: e:
-    let attr = head attrPath;
-    in
-      if attrPath == [] then e
-      else if builtins ? hasAttr && builtins.hasAttr attr e
-      then getAttr (tail attrPath) default (builtins.getAttr attr e)
-      else default;
-
-  # shortcut for getAttr ["name"] default attrs
-  maybeAttr = name: default: attrs:
-    if (__hasAttr name attrs) then (__getAttr name attrs) else default;
-
-
-  # Filter a list using a predicate; that is, return a list containing
-  # every element from `list' for which `pred' returns true.
-  filter = pred: list:
-    fold (x: y: if pred x then [x] ++ y else y) [] list;
-
-
-  # Return true if `list' has an element `x':
-  elem = x: list: fold (a: bs: x == a || bs) false list;
-
-
-  # Find the sole element in the list matching the specified
-  # predicate, returns `default' if no such element exists, or
-  # `multiple' if there are multiple matching elements.
-  findSingle = pred: default: multiple: list:
-    let found = filter pred list;
-    in if found == [] then default
-       else if tail found != [] then multiple
-       else head found;
-
-
-  # Return true iff function `pred' returns true for at least element
-  # of `list'.
-  any = pred: list:
-    if list == [] then false
-    else if pred (head list) then true
-    else any pred (tail list);
-
-
-  # Return true iff function `pred' returns true for all elements of
-  # `list'.
-  all = pred: list:
-    if list == [] then true
-    else if pred (head list) then all pred (tail list)
-    else false;
-
-  # much shorter implementations using map and fold (are lazy as well)
-  # which ones are better?
-  # true if all/ at least one element(s) satisfy f
-  # all = f : l : fold logicalAND true (map f l);
-  # any = f : l : fold logicalOR false (map f l);
-
-
-  # Return true if each element of a list is equal, false otherwise.
-  eqLists = xs: ys:
-    if xs == [] && ys == [] then true
-    else if xs == [] || ys == [] then false
-    else head xs == head ys && eqLists (tail xs) (tail ys);
-
-    
-  # Workaround, but works in stable Nix now.
-  eqStrings = a: b: (a+(substring 0 0 b)) == ((substring 0 0 a)+b);
-
-  
-  # Determine whether a filename ends in the given suffix.
-  hasSuffix = ext: fileName:
-    let lenFileName = stringLength fileName;
-        lenExt = stringLength ext;
-    in !(lessThan lenFileName lenExt) &&
-       substring (sub lenFileName lenExt) lenFileName fileName == ext;
-
-  hasSuffixHack = a: b: hasSuffix (a+(substring 0 0 b)) ((substring 0 0 a)+b);
-
-         
-  # Bring in a path as a source, filtering out all Subversion and CVS
-  # directories, as well as backup files (*~).
-  cleanSource =
-    let filter = name: type: let baseName = baseNameOf (toString name); in ! (
-      # Filter out Subversion and CVS directories.
-      (type == "directory" && (baseName == ".svn" || baseName == "CVS")) ||
-      # Filter out backup files.
-      (hasSuffix "~" baseName)
-    );
-    in src: builtins.filterSource filter src;
-
-
-  # Get all files ending with the specified suffices from the given
-  # directory.  E.g. `sourceFilesBySuffices ./dir [".xml" ".c"]'.
-  sourceFilesBySuffices = path: exts:
-    let filter = name: type: 
-      let base = baseNameOf (toString name);
-      in type != "directory" && any (ext: hasSuffix ext base) exts;
-    in builtins.filterSource filter path;
-
-
-  # Return a singleton list or an empty list, depending on a boolean
-  # value.  Useful when building lists with optional elements
-  # (e.g. `++ optional (system == "i686-linux") flashplayer').
-  optional = cond: elem: if cond then [elem] else [];
-
-
-  # Return a list or an empty list, dependening on a boolean value.
-  optionals = cond: elems: if cond then elems else [];
-
-  optionalString = cond: string: if cond then string else "";
-
-  
-  # Return the second argument if the first one is true or the empty version
-  # of the second argument.
-  ifEnable = cond: val:
-    if cond then val
-    else if builtins.isList val then []
-    else if builtins.isAttrs val then {}
-    # else if builtins.isString val then ""
-    else if (val == true || val == false) then false
-    else null;
-
-    
-  # Return a list of integers from `first' up to and including `last'.
-  range = first: last:
-    if builtins.lessThan last first
-    then []
-    else [first] ++ range (builtins.add first 1) last;
-
-    
-  # Return true only if there is an attribute and it is true.
-  checkFlag = attrSet: name:
-	if (name == "true") then true else
-	if (name == "false") then false else
-	if (isInList (getAttr ["flags"] [] attrSet) name) then true else
-	getAttr [name] false attrSet ;
-
-        
-  logicalOR = x: y: x || y;
-  logicalAND = x: y: x && y;
-
-
-  # Input : attrSet, [ [name default] ... ], name
-  # Output : its value or default.
-  getValue = attrSet: argList: name:
-  ( getAttr [name] (if checkFlag attrSet name then true else
-	if argList == [] then null else
-	let x = builtins.head argList; in
-		if (head x) == name then 
-			(head (tail x))
-		else (getValue attrSet 
-			(tail argList) name)) attrSet );
-
-                        
-  # Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
-  # Output : are reqs satisfied? It's asserted.
-  checkReqs = attrSet : argList : condList :
-  (
-    fold logicalAND true 
-      (map (x: let name = (head x) ; in
-	
-	((checkFlag attrSet name) -> 
-	(fold logicalAND true
-	(map (y: let val=(getValue attrSet argList y); in
-		(val!=null) && (val!=false)) 
-	(tail x))))) condList)) ;
-	
-   
-  isInList = list: x:
-	if (list == []) then false else
-	if (x == (head list)) then true else
-	isInList (tail list) x;
-
-          
-  uniqList = {inputList, outputList ? []}:
-	if (inputList == []) then outputList else
-	let x=head inputList; 
-	newOutputList = outputList ++
-	 (if (isInList outputList x) then [] else [x]);
-	in uniqList {outputList=newOutputList; 
-		inputList = (tail inputList);};
-
-  uniqListExt = {inputList, outputList ? [],
-    getter ? (x : x), compare ? (x: y: x==y)}:
-	if (inputList == []) then outputList else
-	let x=head inputList; 
-	isX = y: (compare (getter y) (getter x));
-	newOutputList = outputList ++
-	 (if any isX outputList then [] else [x]);
-	in uniqListExt {outputList=newOutputList; 
-		inputList = (tail inputList);
-		inherit getter compare;
-		};
-
-
-                
-  condConcat = name: list: checker:
-	if list == [] then name else
-	if checker (head list) then 
-		condConcat 
-			(name + (head (tail list))) 
-			(tail (tail list)) 
-			checker
-	else condConcat
-		name (tail (tail list)) checker;
-
-  # Merge sets of attributes and use the function f to merge
-  # attributes values.
-  zip = f: sets:
-    builtins.listToAttrs (map (name: {
-      inherit name;
-      value =
-        f name
-          (map (__getAttr name)
-            (filter (__hasAttr name) sets));
-    }) (concatMap builtins.attrNames sets));
-
-  # divide a list in two depending on the evaluation of a predicate.
-  partition = pred:
-    fold (h: t:
-      if pred h
-      then { right = [h] ++ t.right; wrong = t.wrong; }
-      else { right = t.right; wrong = [h] ++ t.wrong; }
-    ) { right = []; wrong = []; };
-
-  # Take a function and evaluate it with its own returned value.
-  fix = f:
-    (rec { result = f result; }).result;
-
-  # flatten a list of elements by following the properties of the elements.
-  # next   : return the list of following elements.
-  # seen   : lists of elements already visited.
-  # default: result if 'x' is empty.
-  # x      : list of values that have to be processed.
-  uniqFlatten = next: seen: default: x:
-    if x == []
-    then default
-    else
-      let h = head x; t = tail x; n = next h; in
-      if elem h seen
-      then uniqFlatten next seen default t
-      else uniqFlatten next (seen ++ [h]) (default ++ [h]) (n ++ t)
-    ;
-
-  /* If. ThenElse. Always. */
-
-  # create "if" statement that can be dealyed on sets until a "then-else" or
-  # "always" set is reached.  When an always set is reached the condition
-  # is ignore.
-
-  isIf = attrs: (typeOf attrs) == "if";
-  mkIf = condition: thenelse:
-    if isIf thenelse then
-      mkIf (condition && thenelse.condition) thenelse.thenelse
-    else {
-      _type = "if";
-      inherit condition thenelse;
-    };
-
-
-  isNotdef = attrs: (typeOf attrs) == "notdef";
-  mkNotdef = {_type = "notdef";};
-
-
-  isThenElse = attrs: (typeOf attrs) == "then-else";
-  mkThenElse = attrs:
-    assert attrs ? thenPart && attrs ? elsePart;
-    attrs // { _type = "then-else"; };
-
-
-  isAlways = attrs: (typeOf attrs) == "always";
-  mkAlways = value: { inherit value; _type = "always"; };
-
-  pushIf = f: attrs:
-    if isIf attrs then pushIf f (
-      let val = attrs.thenelse; in
-      # evaluate the condition.
-      if isThenElse val then
-        if attrs.condition then
-          val.thenPart
-        else
-          val.elsePart
-      # ignore the condition.
-      else if isAlways val then
-        val.value
-      # otherwise
-      else
-        f attrs.condition val)
-    else
-      attrs;
-
-  # take care otherwise you will have to handle this by hand.
-  rmIf = pushIf (condition: val: val);
-
-  evalIf = pushIf (condition: val:
-    if condition then val else mkNotdef
-  );
-
-  delayIf = pushIf (condition: val:
-    # rewrite the condition on sub-attributes.
-    mapAttrs (name: mkIf condition) val
-  );
-
-  /* Options. */
-
-  mkOption = attrs: attrs // {_type = "option";};
-
-  typeOf = x: if (__isAttrs x && x ? _type) then x._type else "";
-
-  isOption = attrs: (typeOf attrs) == "option";
-
-  addDefaultOptionValues = defs: opts: opts //
-    builtins.listToAttrs (map (defName:
-      { name = defName;
-        value = 
-          let
-            defValue = builtins.getAttr defName defs;
-            optValue = builtins.getAttr defName opts;
-          in
-          if typeOf defValue == "option"
-          then
-            # `defValue' is an option.
-            if builtins.hasAttr defName opts
-            then builtins.getAttr defName opts
-            else defValue.default
-          else
-            # `defValue' is an attribute set containing options.
-            # So recurse.
-            if builtins.hasAttr defName opts && builtins.isAttrs optValue 
-            then addDefaultOptionValues defValue optValue
-            else addDefaultOptionValues defValue {};
-      }
-    ) (builtins.attrNames defs));
-
-  mergeDefaultOption = list:
-    if list != [] && tail list == [] then head list
-    else if all __isFunction list then x: mergeDefaultOption (map (f: f x) list)
-    else if all __isList list then concatLists list
-    else if all __isAttrs list then mergeAttrs list
-    else if all (x: true == x || false == x) list then fold logicalOR false list
-    else if all (x: x == toString x) list then concatStrings list
-    else throw "Cannot merge values.";
-
-  mergeTypedOption = typeName: predicate: merge: list:
-    if all predicate list then merge list
-    else throw "Expect a ${typeName}.";
-
-  mergeEnableOption = mergeTypedOption "boolean"
-    (x: true == x || false == x) (fold logicalOR false);
-
-  mergeListOption = mergeTypedOption "list"
-    __isList concatLists;
-
-  mergeStringOption = mergeTypedOption "string"
-    (x: if builtins ? isString then builtins.isString x else x + "")
-    concatStrings;
-
-  mergeOneOption = list:
-    if list == [] then abort "This case should never happens."
-    else if tail list != [] then throw "Multiple definitions. Only one is allowed for this option."
-    else head list;
-
-
-  # Handle the traversal of option sets.  All sets inside 'opts' are zipped
-  # and options declaration and definition are separated.  If no option are
-  # declared at a specific depth, then the function recurse into the values.
-  # Other cases are handled by the optionHandler which contains two
-  # functions that are used to defined your goal.
-  # - export is a function which takes two arguments which are the option
-  # and the list of values.
-  # - notHandle is a function which takes the list of values are not handle
-  # by this function.
-  handleOptionSets = optionHandler@{export, notHandle, ...}: path: opts:
-    if all __isAttrs opts then
-      zip (attr: opts:
-        let
-          # Compute the path to reach the attribute.
-          name = if path == "" then attr else path + "." + attr;
-
-          # Divide the definitions of the attribute "attr" between
-          # declaration (isOption) and definitions (!isOption).
-          test = partition isOption opts;
-          decls = test.right; defs = test.wrong;
-
-          # Return the option declaration and add missing default
-          # attributes.
-          opt = {
-            inherit name;
-            merge = mergeDefaultOption;
-            apply = id;
-          } // (head decls);
-
-          # Return the list of option sets.
-          optAttrs = map delayIf defs;
-
-          # return the list of option values.
-          # Remove undefined values that are coming from evalIf.
-          optValues = filter (x: !isNotdef x) (map evalIf defs);
-        in
-          if decls == [] then handleOptionSets optionHandler name optAttrs
-          else addErrorContext "while evaluating the option ${name}:" (
-            if tail decls != [] then throw "Multiple options."
-            else export opt optValues
-          )
-      ) opts
-   else addErrorContext "while evaluating ${path}:" (notHandle opts);
-
-  # Merge option sets and produce a set of values which is the merging of
-  # all options declare and defined.  If no values are defined for an
-  # option, then the default value is used otherwise it use the merge
-  # function of each option to get the result.
-  mergeOptionSets = noOption: newMergeOptionSets; # ignore argument
-  newMergeOptionSets =
-    handleOptionSets {
-      export = opt: values:
-        opt.apply (
-          if values == [] then
-            if opt ? default then opt.default
-            else throw "Not defined."
-          else opt.merge values
-        );
-      notHandle = opts: throw "Used without option declaration.";
-    };
-
-  # Keep all option declarations.
-  filterOptionSets =
-    handleOptionSets {
-      export = opt: values: opt;
-      notHandle = opts: {};
-    };
-
-  # Evaluate a list of option sets that would be merged with the
-  # function "merge" which expects two arguments.  The attribute named
-  # "require" is used to imports option declarations and bindings.
-  #
-  # * cfg[0-9]: configuration
-  # * cfgSet[0-9]: configuration set
-  #
-  # merge: the function used to merge options sets.
-  # pkgs: is the set of packages available. (nixpkgs)
-  # opts: list of option sets or option set functions.
-  # config: result of this evaluation.
-  fixOptionSetsFun = merge: pkgs: opts: config:
-    let
-      # remove possible mkIf to access the require attribute.
-      noImportConditions = cfgSet0:
-        let cfgSet1 = delayIf cfgSet0; in
-        if cfgSet1 ? require then
-          cfgSet1 // { require = rmIf cfgSet1.require; }
-        else
-          cfgSet1;
-
-      # call configuration "files" with one of the existing convention.
-      argumentHandler = cfg:
-        let
-          # {..}
-          cfg0 = cfg;
-          # {pkgs, config, ...}: {..}
-          cfg1 = cfg { inherit pkgs config merge; };
-          # pkgs: config: {..}
-          cfg2 = cfg {} {};
-        in
-        if __isFunction cfg0 then
-          if builtins.isAttrs cfg1 then cfg1
-          else builtins.trace "Use '{pkgs, config, ...}:'." cfg2
-        else cfg0;
-
-      preprocess = cfg0:
-        let cfg1 = argumentHandler cfg0;
-            cfg2 = noImportConditions cfg1;
-        in cfg2;
-
-      getRequire = x: toList (getAttr ["require"] [] (preprocess x));
-      rmRequire = x: removeAttrs (preprocess x) ["require"];
-    in
-      merge "" (
-        map rmRequire (
-          uniqFlatten getRequire [] [] (toList opts)
-        )
-      );
-
-  fixOptionSets = merge: pkgs: opts:
-    fix (fixOptionSetsFun merge pkgs opts);
-
-  optionAttrSetToDocList = (l: attrs:
-    (if (getAttr ["_type"] "" attrs) == "option" then
-      [({
-	#inherit (attrs) description;
-        description = if attrs ? description then attrs.description else 
-          throw ("No description ${toString l} : ${whatis attrs}");
-      }
-      //(if attrs ? example then {inherit(attrs) example;} else {} )
-      //(if attrs ? default then {inherit(attrs) default;} else {} )
-      //{name = l;}
-      )]
-      else (concatLists (map (s: (optionAttrSetToDocList 
-        (l + (if l=="" then "" else ".") + s) (builtins.getAttr s attrs)))
-        (builtins.attrNames attrs)))));
-
-  innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else 
-	innerModifySumArgs f x (a // b);
-  modifySumArgs = f: x: innerModifySumArgs f x {};
-
-  # Wrapper aroung addErrorContext.  The builtin should not be used
-  # directly.
-  addErrorContext =
-    if builtins ? addErrorContext
-    then builtins.addErrorContext
-    else msg: val: val;
-
-  debugVal = if builtins ? trace then x: (builtins.trace x x) else x: x;
-  debugXMLVal = if builtins ? trace then x: (builtins.trace (builtins.toXML x) x) else x: x;
-
-  # this can help debug your code as well - designed to not produce thousands of lines
-  traceWhatis = x : __trace (whatis x) x;
-  traceMarked = str: x: __trace (str + (whatis x)) x;
-  attrNamesToStr = a : concatStringsSep "; " (map (x : "${x}=") (__attrNames a));
-  whatis = x :
-      if (__isAttrs x) then
-          if (x ? outPath) then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }"
-          else "x is attr set { ${attrNamesToStr x} }"
-      else if (__isFunction x) then "x is a function"
-      else if (x == []) then "x is an empty list"
-      else if (__isList x) then "x is a list, first item is : ${whatis (__head x)}"
-      else if (x == true) then "x is boolean true"
-      else if (x == false) then "x is boolean false"
-      else if (x == null) then "x is null"
-      else "x is probably a string starting, starting characters: ${__substring 0 50 x}..";
-  # trace the arguments passed to function and its result 
-  traceCall  = n : f : a : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
-  traceCall2 = n : f : a : b : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
-  traceCall3 = n : f : a : b : c : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
-
-
-
-  innerClosePropagation = ready: list: if list == [] then ready else
-    if (head list) ? propagatedBuildInputs then 
-      innerClosePropagation (ready ++ [(head list)]) 
-        ((head list).propagatedBuildInputs ++ (tail list)) else
-      innerClosePropagation (ready ++ [(head list)]) (tail list);
-
-  closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
-
-  stringToCharacters = s : let l = __stringLength s; in
-    if (__lessThan l 1) then [""] else  [(__substring 0 1 s)] ++ stringToCharacters (__substring 1 (__sub l 1) s);
-
-  # should this be implemented as primop ? Yes it should..
-  escapeShellArg = s :
-    let escapeChar = x : if ( x == "'" ) then "'\"'\"'" else x;
-    in "'" + concatStrings (map escapeChar (stringToCharacters s) ) +"'";
-
-  defineShList = name : list : "\n${name}=(${concatStringsSep " " (map escapeShellArg list)})\n";
-
-  # this as well :-) arg: http://foo/bar/bz.ext returns bz.ext
-  dropPath = s : 
-      if s == "" then "" else
-      let takeTillSlash = left : c : s :
-          if left == 0 then s
-          else if (__substring left 1 s == "/") then
-                  (__substring (__add left 1) (__sub c 1) s)
-          else takeTillSlash (__sub left 1) (__add c 1) s; in
-      takeTillSlash (__sub (__stringLength s) 1) 1 s;
-
-  # calls a function (f attr value ) for each record item. returns a list
-  # should be renamed to mapAttrsFlatten
-  mapRecordFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r);
-
-  # maps a function on each attr value
-  # f = attr : value : ..
-  mapAttrs = f : r : listToAttrs ( mapRecordFlatten (a : v : nv a ( f a v ) )  r);
-
-  # to be used with listToAttrs (_a_ttribute _v_alue)
-  nv = name : value : { inherit name value; };
-  # attribute set containing one attribute
-  nvs = name : value : listToAttrs [ (nv name value) ];
-  # adds / replaces an attribute of an attribute set
-  setAttr = set : name : v : set // (nvs name v);
-
-  # setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
-  # setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; } 
-  # setAttrMerge "a" [] {         } (x : x ++ [3]) -> { a = [  3]; }
-  setAttrMerge = name : default : attrs : f :
-    setAttr attrs name (f (maybeAttr name default attrs));
-
-  # iterates over a list of attributes collecting the attribute attr if it exists
-  catAttrs = attr : l : fold ( s : l : if (hasAttr attr s) then [(builtins.getAttr attr s)] ++ l else l) [] l;
-
-  mergeAttr = x : y : x // y;
-  mergeAttrs = fold mergeAttr {};
-
-  attrVals = nameList : attrSet :
-    map (x: builtins.getAttr x attrSet) nameList;
-
-  # Using f = a : b = b the result is similar to //
-  # merge attributes with custom function handling the case that the attribute
-  # exists in both sets
-  mergeAttrsWithFunc = f : set1 : set2 :
-    fold (n: set : if (__hasAttr n set) 
-                        then setAttr set n (f (__getAttr n set) (__getAttr n set2))
-                        else set )
-           set1 (__attrNames set2);
-
-  # merging two attribute set concatenating the values of same attribute names
-  # eg { a = 7; } {  a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
-  mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) );
-
-  # merges attributes using //, if a name exisits in both attributes
-  # an error will be triggered unless its listed in mergeLists
-  # so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
-  # { buildInputs = [a b]; }
-  # merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
-  # in these cases the first buildPhase will override the second one
-  # ! depreceated, use mergeAttrByFunc instead
-  mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
-                           overrideSnd ? [ "buildPhase" ]
-                         } : attrs1 : attrs2 :
-    fold (n: set : 
-        setAttr set n ( if (__hasAttr n set) 
-            then # merge 
-              if elem n mergeLists # attribute contains list, merge them by concatenating
-                then (__getAttr n attrs2) ++ (__getAttr n attrs1)
-              else if elem n overrideSnd
-                then __getAttr n attrs1
-              else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
-            else __getAttr n attrs2 # add attribute not existing in attr1
-           )) attrs1 (__attrNames attrs2);
-
-
-  # example usage:
-  # mergeAttrByFunc  {
-  #   inherit mergeAttrBy; # defined below
-  #   buildInputs = [ a b ];
-  # } {
-  #  buildInputs = [ c d ];
-  # };
-  # will result in
-  # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
-  # is used by prepareDerivationArgs and can be used when composing using
-  # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
-  mergeAttrByFunc = x : y :
-    let
-          mergeAttrBy2 = { mergeAttrBy=mergeAttr; }
-                      // (maybeAttr "mergeAttrBy" {} x)
-                      // (maybeAttr "mergeAttrBy" {} y); in
-    mergeAttrs [
-      x y
-      (mapAttrs ( a : v : # merge special names using given functions
-          if (__hasAttr a x)
-             then if (__hasAttr a y)
-               then v (__getAttr a x) (__getAttr a y) # both have attr, use merge func
-               else (__getAttr a x) # only x has attr
-             else (__getAttr a y) # only y has attr)
-          ) (removeAttrs mergeAttrBy2
-                         # don't merge attrs which are neither in x nor y
-                         (filter (a : (! __hasAttr a x) && (! __hasAttr a y) )
-                                 (__attrNames mergeAttrBy2))
-            )
-      )
-    ];
-  mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
-  # sane defaults (same name as attr name so that inherit can be used)
-  mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
-    listToAttrs (map (n : nv n concatList) [ "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ])
-    // listToAttrs (map (n : nv n mergeAttr) [ "passthru" "meta" "cfg" "flags" ]);
-
-  # returns atribute values as a list 
-  flattenAttrs = set : map ( attr : builtins.getAttr attr set) (attrNames set);
-  mapIf = cond : f :  fold ( x : l : if (cond x) then [(f x)] ++ l else l) [];
-
-  # pick attrs subset_attr_names and apply f 
-  subsetmap = f : attrs : subset_attr_names : 
-    listToAttrs (fold ( attr : r : if __hasAttr attr attrs
-          then r ++ [ (  nv attr ( f (__getAttr attr attrs) ) ) ] else r ) []
-      subset_attr_names );
-
-  # prepareDerivationArgs tries to make writing configurable derivations easier
-  # example:
-  #  prepareDerivationArgs {
-  #    mergeAttrBy = {
-  #       myScript = x : y : x ++ "\n" ++ y;
-  #    };
-  #    cfg = {
-  #      readlineSupport = true;
-  #    };
-  #    flags = {
-  #      readline = {
-  #        set = {
-  #           configureFlags = [ "--with-compiler=${compiler}" ];
-  #           buildInputs = [ compiler ];
-  #           pass = { inherit compiler; READLINE=1; };
-  #           assertion = compiler.dllSupport;
-  #           myScript = "foo";
-  #        };
-  #        unset = { configureFlags = ["--without-compiler"]; };
-  #      };
-  #    };
-  #    src = ...
-  #    buildPhase = '' ... '';
-  #    name = ...
-  #    myScript = "bar";
-  #  };
-  # if you don't have need for unset you can omit the surrounding set = { .. } attr
-  # all attrs except flags cfg and mergeAttrBy will be merged with the
-  # additional data from flags depending on config settings
-  # It's used in composableDerivation in all-packages.nix. It's also used
-  # heavily in the new python and libs implementation
-  #
-  # should we check for misspelled cfg options?
-  prepareDerivationArgs = args:
-    let args2 = { cfg = {}; flags = {}; } // args;
-        flagName = name : "${name}Support";
-        cfgWithDefaults = (listToAttrs (map (n : nv (flagName n) false) (attrNames args2.flags)))
-                          // args2.cfg;
-        opts = flattenAttrs (mapAttrs (a : v :
-                let v2 = if (v ? set || v ? unset) then v else { set = v; };
-                    n = if (__getAttr (flagName a) cfgWithDefaults) then "set" else "unset";
-                    attr = maybeAttr n {} v2; in
-                if (maybeAttr "assertion" true attr)
-                  then attr
-                  else throw "assertion of flag ${a} of derivation ${args.name} failed"
-               ) args2.flags );
-    in removeAttrs
-      (mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
-      ["flags" "cfg" "mergeAttrBy" "fixed" ]; # fixed may be passed as fix argument or such
-
-}
+  { inherit trivial lists strings attrsets sources options debug; }
+  # !!! don't include everything at top-level; perhaps only the most
+  # commonly used functions.
+  // trivial // lists // strings // attrsets // sources // options
+  // debug // misc