From 98e81b98e98d9ed31383716f4e0a5b372389fea2 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Wed, 16 Mar 2022 21:48:08 -0500 Subject: [PATCH] Improve lib.generators.toPreserves - Generate dictionaries with symbol keys. This breaks lossless JSON conversion but is consistent with Preserves in the wild. - New record pattern: ``[ 1 2 3 { record = "foo"; } ]``. --- lib.nix | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/lib.nix b/lib.nix index cea1ef7..1aa490d 100644 --- a/lib.nix +++ b/lib.nix @@ -5,31 +5,50 @@ 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. + /* Generates text-encoded Preserves from an arbitrary value. + + Records are generated for lists with a final element in + the form of `{ record = «label»; }`. + + Type: toPreserves :: a -> string + + Example: + toPreserves { } [{ a = 0; b = 1; } "c" [ true false ] { record = "foo"; }] + => "" + */ toPreserves = { }@args: let toPreserves' = toPreserves args; concatItems = toString; + recordLabel = list: + with builtins; + let len = length list; + in if len == 0 then + null + else + let end = elemAt list (len - 1); + in if (isAttrs end) && (attrNames end) == [ "record" ] then + end + else + null; in v: if isAttrs v then "{ ${ concatItems (lib.attrsets.mapAttrsToList - (key: val: "${builtins.toJSON key}: ${toPreserves' val}") v) + (key: val: "${key}: ${toPreserves' val}") v) } }" else if isList v then - "[ ${concatItems (map toPreserves' v)} ]" + let label = recordLabel v; + in if label == null then + "[ ${concatItems (map toPreserves' v)} ]" + else + "<${label.record} ${ + concatItems (map toPreserves' (lib.lists.init 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") + abort "generators.toPreserves: cannot convert a function to Preserves" else if isNull v then "null" else