final: prev: let lib = final; in with lib; { generators = with final.generators; prev.generators // { # Generates Preserves from an arbitrary value. # Records are generated for functions that take # a single formal argument `toRecord` and return # a list of values. toPreserves = { }@args: let toPreserves' = toPreserves args; concatItems = toString; in v: if isAttrs v then "{ ${ concatItems (lib.attrsets.mapAttrsToList (key: val: "${key}: ${toPreserves' val}") v) } }" else if isList v then "[ ${concatItems (map toPreserves' v)} ]" else if isBool v then (if v then "#t" else "#f") else if isFunction v then (if (lib.functionArgs v) == { toRecord = false; } then let items = v { toRecord = null; }; in "<${head items} ${toString (map toPreserves' (tail items))}>" else abort "generators.toPreserves: cannot convert a function to Preserves") else if isNull v then "null" else builtins.toJSON v; }; }