about summary refs log tree commit diff
path: root/users/sterni/nix/flow
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2021-02-22T13·32+0100
committersterni <sternenseemann@systemli.org>2021-03-01T17·34+0000
commit3b33c1bd7627c9427a410276c2a49c2b04f70edc (patch)
tree0cd92fecc34ad0db0d4b3af9e0f1f266172a988d /users/sterni/nix/flow
parent369f504250fe6508d3b927c6c8320a2525edfad1 (diff)
feat(users/sterni/nix): add sternis nix lib r/2257
What you see here is mostly the fallout of me implementing a correct
urlencode implementation in nix for Profpatsch's blog implementation
(although they'll probably keep it at arm's length).

Where I want to go from here:

* Extend this library towards general purpose nix™, mainly by
  implementing missing interfaces which you'd still have to use
  <nixpkgs/lib> for right now. Reexposing parts of <nixpkgs/lib>
  with better naming is fine for now, at some point I'd contemplate
  making this depend on nothing outside of depot, maybe even itself
  (should be easy we only use yants for an easily replaceable check).

* Improve error messages possibly by carefully reintroducing yants. I
  originally typed essentially everything using yants, but turns out
  this can a) be dangerous when stuff you are handling throws because
  type checking means evaluating and b) has a incredible performance
  cost in some cases.

* Reexpose builtins with better naming and slightly wrapped so they
  don't unrecoverably throw in cases where a null or something would
  suffice.

Change-Id: I33ab08ca4e62dbc16b86c66c653935686e6b0e79
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2541
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: Profpatsch <mail@profpatsch.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'users/sterni/nix/flow')
-rw-r--r--users/sterni/nix/flow/default.nix54
-rw-r--r--users/sterni/nix/flow/tests/default.nix49
2 files changed, 103 insertions, 0 deletions
diff --git a/users/sterni/nix/flow/default.nix b/users/sterni/nix/flow/default.nix
new file mode 100644
index 0000000000..838e65bfb2
--- /dev/null
+++ b/users/sterni/nix/flow/default.nix
@@ -0,0 +1,54 @@
+{ depot, ... }:
+
+let
+
+  inherit (depot.nix)
+    yants
+    ;
+
+  # we must avoid evaluating any of the sublists
+  # as they may contain conditions that throw
+  condition = yants.restrict "condition"
+    (ls: builtins.length ls == 2)
+    (yants.list yants.any);
+
+  /* cond :: [ [ bool any ] ] -> any
+   *
+   * Like the common lisp macro: takes a list
+   * of two elemented lists whose first element
+   * is a boolean. The second element of the
+   * first list that has true as its first
+   * element is returned.
+   *
+   * Example:
+   *
+   * cond [
+   *   [ (builtins.isString true) 12 ]
+   *   [ (3 == 2) 13 ]
+   *   [ true 42 ]
+   * ]
+   *
+   * => 42
+   */
+  cond = conds:
+    if builtins.length conds == 0
+    then builtins.throw "cond: exhausted all conditions"
+    else
+      let
+        c = condition (builtins.head conds);
+      in
+        if builtins.head c
+        then builtins.elemAt c 1
+        else cond (builtins.tail conds);
+
+  # TODO(sterni): condf or magic
+  # like <nixpkgs/pkgs/build-support/coq/extra-lib.nix>
+
+  match = val: matcher: matcher."${val}";
+
+in {
+  inherit
+    cond
+    match
+    ;
+}
diff --git a/users/sterni/nix/flow/tests/default.nix b/users/sterni/nix/flow/tests/default.nix
new file mode 100644
index 0000000000..0bec4a3bd7
--- /dev/null
+++ b/users/sterni/nix/flow/tests/default.nix
@@ -0,0 +1,49 @@
+{ depot, ... }:
+
+let
+
+  inherit (depot.nix.runTestsuite)
+    runTestsuite
+    it
+    assertEq
+    assertThrows
+    ;
+
+  inherit (depot.users.sterni.nix.flow)
+    cond
+    match
+    ;
+
+  dontEval = builtins.throw "this should not get evaluated";
+
+  testCond = it "tests cond" [
+    (assertThrows "malformed cond list"
+      (cond [ [ true 1 2 ] [ false 1 ] ]))
+    (assertEq "last is true" "last"
+      (cond [
+        [ false dontEval]
+        [ false dontEval ]
+        [ true "last" ]
+      ]))
+    (assertEq "first is true" 1
+      (cond [
+        [ true 1 ]
+        [ true dontEval ]
+        [ true dontEval ]
+      ]))
+  ];
+
+  testMatch = it "tests match" [
+    (assertEq "basic match usage" 42
+      (match "answer" {
+        "answer" = 42;
+        "banana" = dontEval;
+        "maleur" = dontEval;
+      }))
+  ];
+
+in
+  runTestsuite "nix.flow" [
+    testCond
+    testMatch
+  ]