-
Notifications
You must be signed in to change notification settings - Fork 8
/
dhall.nix
89 lines (81 loc) · 3.12 KB
/
dhall.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{ system, pkgs, lib }:
let
dhallPkg = pkgs.dhall;
# “Pipe” mechanism for nix store files.
# The given file is piped through the command and put into $out.
# Can be chained quite easily.
pipe =
{ name # of the derivation
, invocation # list of executable and args
, file # file to pipe in
}:
assert (builtins.isList invocation && invocation != []);
let command = builtins.head invocation;
args = builtins.tail invocation;
in derivation {
builder = pkgs.writeScript "toStdin-builder.sh" ''
#!${pkgs.dash}/bin/dash
<"$file" $command "$@" > $out
'';
inherit command args file name system;
outputs = [ "out" ];
};
# Pipe a file to the dhall language compiler, save result to $out.
pipeDhall =
{ name # of the derivation
, file # file to pipe in
, explain ? false # whether errors should be longform
}:
pipe {
inherit name file;
invocation = [ "${dhallPkg}/bin/dhall" ]
++ lib.optional explain "--explain";
};
# Save a nix value in a formatted dhall file.
# Uses `toDhallValue`.
toDhallDrv = name: val:
pipe {
inherit name;
invocation = ["${dhallPkg}/bin/dhall-format"];
file = (pkgs.writeText "${name}-unformatted"
(toDhallValue {} val).rep);
};
# Convert a nix value (that doesn’t contain nulls or functions)
# into an unformatted dhall value string (no type annotations).
toDhallValue = {}: v: with builtins;
if isInt v then dhall.unsafe.integer v
else if isBool v then dhall.unsafe.bool v
else if isString v then dhall.unsafe.text v
else if isList v then dhall.unsafe.list (map (toDhallValue {}) v)
else if isAttrs v then dhall.unsafe.record
(lib.mapAttrs (_: val: toDhallValue {} val) v)
# nice?
else if null == v then abort "toDhallValue: null can’t be converted"
else if isFunction v then abort "toDhallValue: functions can’t be converted"
else abort "toDhallValue: should not happen";
# Unsafe builders of dhall values.
# Contain their structured form in `.val`
# and their formatted dhall string representations in `.rep`.
# Attention: Recursive values (e.g. list elements)
# must already be structured dhall values!
dhall.unsafe = with builtins;
let val = v: r: { val = v; rep = r; };
in {
bool = b: val b (if b then "True" else "False");
natural = n: val n "+${toString n}";
integer = i: val i (toString i);
# double =
# TODO: escaping
text = t: val t t;
list = l: val l "[${lib.concatMapStringsSep ", " (x: x.rep) l}]";
optional = o: val o (if o == null
then "[]"
else "[${o.rep}]");
record = r: val r ("{ "
+ lib.concatStringsSep ", " (lib.mapAttrsToList
# TODO: escaping
(name: value: "${toString name} = ${value.rep}") r)
+ " }");
# union =
};
in { inherit pipeDhall toDhallDrv; }