migrate to nt
This commit is contained in:
parent
6c5e5fd880
commit
9ee4ae5f29
25 changed files with 8 additions and 2240 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*.bak
|
||||||
13
flake.nix
13
flake.nix
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
description = "MyNib - My Nix Library";
|
description = "NixTypes (nt)";
|
||||||
|
|
||||||
inputs.systems.url = "github:nix-systems/default";
|
inputs = {
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
mix.url = "github:emilelcb/mix";
|
||||||
|
};
|
||||||
|
|
||||||
outputs = {self, ...} @ inputs: let
|
outputs = {...} @ inputs:
|
||||||
systems = import inputs.systems;
|
import ./nt inputs;
|
||||||
in
|
|
||||||
import ./nib {inherit systems;};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{systems, ...}: let
|
|
||||||
# TODO: move this to a new module
|
|
||||||
mkMod' = args: mod: import mod args;
|
|
||||||
mkMod = mkMod' {inherit systems nib;};
|
|
||||||
|
|
||||||
std = mkMod ./std;
|
|
||||||
panic = mkMod ./panic.nix;
|
|
||||||
parse = mkMod ./parse;
|
|
||||||
# patterns = mkMod ./patterns.nix;
|
|
||||||
|
|
||||||
types = mkMod ./types;
|
|
||||||
typesystem = mkMod ./typesystem.nix;
|
|
||||||
|
|
||||||
sys = mkMod ./sys.nix;
|
|
||||||
|
|
||||||
nib = std.mergeAttrsList [
|
|
||||||
# submodule content is accessible first by submodule name
|
|
||||||
# then by the name of the content (ie self.submodule.myFunc)
|
|
||||||
{inherit std types panic parse;}
|
|
||||||
|
|
||||||
# submodule content accessible directly (ie self.myFunc)
|
|
||||||
# patterns
|
|
||||||
typesystem
|
|
||||||
sys
|
|
||||||
];
|
|
||||||
in
|
|
||||||
nib
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{nib, ...}: rec {
|
|
||||||
enfType = type: T:
|
|
||||||
assert (nib.isType type T
|
|
||||||
|| nib.panic.badType (nib.typeName type)); true;
|
|
||||||
|
|
||||||
enfSameType = T1: T2: enfType (nib.typeOf T1) T2;
|
|
||||||
|
|
||||||
enfAttrs = enfType (nib.typeOf {});
|
|
||||||
enfList = enfType (nib.typeOf []);
|
|
||||||
enfListOf = type: L:
|
|
||||||
assert (enfList L
|
|
||||||
&& builtins.all (T: nib.isType type T) L
|
|
||||||
|| nib.panic.badType "List ${nib.typeName type}" L); true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
{...}: {
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{nib, ...}: {
|
|
||||||
badType = expect: x:
|
|
||||||
throw "Expected type ${expect} but got ${nib.typeOf x}.";
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{nib, ...} @ args: let
|
|
||||||
struct = import ./struct.nix args;
|
|
||||||
in
|
|
||||||
nib.std.mergeAttrsList [
|
|
||||||
# submodule is included directly to this module (ie self.myFunc)
|
|
||||||
struct
|
|
||||||
]
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
inherit
|
|
||||||
(nib.types)
|
|
||||||
Err
|
|
||||||
Ok'
|
|
||||||
firstErr
|
|
||||||
unwrapSome
|
|
||||||
isTerminal
|
|
||||||
unwrapTerminal
|
|
||||||
;
|
|
||||||
|
|
||||||
inherit
|
|
||||||
(nib.std)
|
|
||||||
attrValueAt
|
|
||||||
;
|
|
||||||
in rec {
|
|
||||||
cmpStructErr' = errBadKeys: errBadValues: path: S: T:
|
|
||||||
if builtins.isAttrs S && builtins.isAttrs T
|
|
||||||
then let
|
|
||||||
keysS = builtins.attrNames S;
|
|
||||||
keysT = builtins.attrNames T;
|
|
||||||
in
|
|
||||||
# ensure all key names match, then recurse
|
|
||||||
if !(keysS == keysT)
|
|
||||||
then errBadKeys path keysS keysT
|
|
||||||
else
|
|
||||||
(firstErr
|
|
||||||
(map
|
|
||||||
(k: cmpStructErr' errBadKeys errBadValues (path ++ [k]) (keysS.${k}) (keysT.${k}))
|
|
||||||
keysS))
|
|
||||||
else
|
|
||||||
# terminating leaf in recursion tree reached
|
|
||||||
# ensure values' types match
|
|
||||||
(builtins.typeOf S == builtins.typeOf T)
|
|
||||||
|| errBadValues path S T;
|
|
||||||
|
|
||||||
cmpStructErr = errBadKeys: errBadValues: cmpStructErr' errBadKeys errBadValues [];
|
|
||||||
|
|
||||||
cmpStruct =
|
|
||||||
cmpStructErr
|
|
||||||
(path: _: _:
|
|
||||||
Err {
|
|
||||||
reason = "keys";
|
|
||||||
inherit path;
|
|
||||||
})
|
|
||||||
(_: _: _: Ok');
|
|
||||||
|
|
||||||
cmpTypedStruct =
|
|
||||||
cmpStructErr
|
|
||||||
(path: _: _:
|
|
||||||
Err {
|
|
||||||
reason = "keys";
|
|
||||||
inherit path;
|
|
||||||
})
|
|
||||||
(path: _: _:
|
|
||||||
Err {
|
|
||||||
reason = "values";
|
|
||||||
inherit path;
|
|
||||||
});
|
|
||||||
|
|
||||||
cmpTypedPartialStruct =
|
|
||||||
cmpStructErr
|
|
||||||
(_: _: _: Ok')
|
|
||||||
(path: _: _:
|
|
||||||
Err {
|
|
||||||
reason = "values";
|
|
||||||
inherit path;
|
|
||||||
});
|
|
||||||
|
|
||||||
# Alternative to mapAttrsRecursiveCond
|
|
||||||
# Allows mapping directly from a child path
|
|
||||||
recmapCondFrom = path: cond: f: T: let
|
|
||||||
delegate = path': recmapCondFrom path' cond f;
|
|
||||||
in
|
|
||||||
if builtins.isAttrs T && cond path T
|
|
||||||
then builtins.mapAttrs (attr: leaf: delegate (path ++ [attr]) leaf) T
|
|
||||||
# else if builtins.isList T
|
|
||||||
# then map (leaf: delegate leaf)
|
|
||||||
else f path T;
|
|
||||||
|
|
||||||
recmapCond = recmapCondFrom [];
|
|
||||||
|
|
||||||
# Alternative to mapAttrsRecursive
|
|
||||||
# NOTE: refuses to go beyond Terminal types
|
|
||||||
recmap = recmapCond (_: leaf: !(isTerminal leaf));
|
|
||||||
|
|
||||||
overrideStructCond = cond: f: S: ext:
|
|
||||||
recmapCond
|
|
||||||
cond
|
|
||||||
(path: leaf:
|
|
||||||
attrValueAt path ext
|
|
||||||
|> unwrapSome (_: f leaf))
|
|
||||||
S;
|
|
||||||
|
|
||||||
# overrideStruct ensures no properties are evaluated (entirely lazy)
|
|
||||||
# TODO: should this be called "overlayStructs" or something? (its not exactly a override...)
|
|
||||||
# NOTE: respects Terminal types
|
|
||||||
overrideStruct =
|
|
||||||
overrideStructCond
|
|
||||||
(_: leaf: !(isTerminal leaf))
|
|
||||||
(leaf:
|
|
||||||
if isTerminal leaf
|
|
||||||
then unwrapTerminal leaf
|
|
||||||
else leaf);
|
|
||||||
|
|
||||||
# # overrideTypedPartialStruct must evaluate properties (not lazy)
|
|
||||||
# # for lazy evaluation use overrideStruct instead!
|
|
||||||
# overrideTypedPartialStruct = overrideStructs' cmpTypedPartialStruct;
|
|
||||||
|
|
||||||
overrideAttrs = A: B: A // B;
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
# Rust inspired pattern matching syntax:
|
|
||||||
# resultA = match [platform arch] [
|
|
||||||
# (Pattern ["darwin" Any] darwin_package)
|
|
||||||
# (Pattern ["openbsd" "x86_64"] openbsd_x86_64_package)
|
|
||||||
# (Pattern [(x: x == "linux") (y: y == "x86_64")] linux_x86_64_package)
|
|
||||||
# (Pattern (x: y: x == "linux" && y == "aarch64") linux_aarch64_package)
|
|
||||||
# (Pattern Any default_package)
|
|
||||||
# ];
|
|
||||||
# resultB = match [platform arch] [
|
|
||||||
# (["darwin" Any] |> case darwin_package)
|
|
||||||
# (["openbsd" "x86_64"] |> case openbsd_x86_64_package)
|
|
||||||
# ([(x: x == "linux") (y: y == "x86_64")] |> case linux_x86_64_package)
|
|
||||||
# ((x: y: x == "linux" && y == "aarch64") |> case linux_aarch64_package)
|
|
||||||
# (Any |> case default_package)
|
|
||||||
# ];
|
|
||||||
types = nib.types;
|
|
||||||
in rec {
|
|
||||||
Pattern = pattern: return: throw "not implemented";
|
|
||||||
case = return: pattern: Pattern pattern return;
|
|
||||||
|
|
||||||
matchesPattern' = pattern: subject: let
|
|
||||||
recurse = p: s:
|
|
||||||
nib.isSameType p s
|
|
||||||
&& (
|
|
||||||
if nib.isList p
|
|
||||||
then builtins.all (map (p: recurse p)) (nib.std.zipLists)
|
|
||||||
else if nib.isAttrs p
|
|
||||||
then builtins.all ()
|
|
||||||
else nib.eq p s
|
|
||||||
);
|
|
||||||
in
|
|
||||||
recurse pattern subject;
|
|
||||||
|
|
||||||
# maybe' :: TList a b -> TList [TPattern c d] -> TMaybe d
|
|
||||||
match' = subject: patterns:
|
|
||||||
nib.enfType (types.TList types.TPattern) patterns
|
|
||||||
&& builtins.foldl' (
|
|
||||||
fix: p:
|
|
||||||
if types.isNone fix
|
|
||||||
# maintain None as a fixed value
|
|
||||||
then fix
|
|
||||||
else matchesPattern' p
|
|
||||||
)
|
|
||||||
types.Some
|
|
||||||
patterns;
|
|
||||||
}
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
inherit
|
|
||||||
(builtins)
|
|
||||||
all
|
|
||||||
attrNames
|
|
||||||
elemAt
|
|
||||||
filter
|
|
||||||
getAttr
|
|
||||||
hasAttr
|
|
||||||
isAttrs
|
|
||||||
length
|
|
||||||
listToAttrs
|
|
||||||
mapAttrs
|
|
||||||
;
|
|
||||||
|
|
||||||
inherit
|
|
||||||
(nib.std)
|
|
||||||
foldl
|
|
||||||
;
|
|
||||||
|
|
||||||
inherit
|
|
||||||
(nib.types)
|
|
||||||
nullableToMaybe
|
|
||||||
;
|
|
||||||
in rec {
|
|
||||||
nameValuePair = name: value: {inherit name value;};
|
|
||||||
|
|
||||||
identityAttrs = value: {${value} = value;};
|
|
||||||
|
|
||||||
identityAttrsMany = values: map (v: identityAttrs v) values;
|
|
||||||
|
|
||||||
hasAttrs = list: xs: all (x: hasAttr x xs) list;
|
|
||||||
|
|
||||||
getAttrOr = default: name: xs:
|
|
||||||
if hasAttr name xs
|
|
||||||
then getAttr name xs
|
|
||||||
else default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Like `genAttrs`, but allows the name of each attribute to be specified in addition to the value.
|
|
||||||
The applied function should return both the new name and value as a `nameValuePair`.
|
|
||||||
::: {.warning}
|
|
||||||
In case of attribute name collision the first entry determines the value,
|
|
||||||
all subsequent conflicting entries for the same name are silently ignored.
|
|
||||||
:::
|
|
||||||
|
|
||||||
# Inputs
|
|
||||||
|
|
||||||
`xs`
|
|
||||||
|
|
||||||
: A list of strings `s` used as generator.
|
|
||||||
|
|
||||||
`f`
|
|
||||||
|
|
||||||
: A function, given a string `s` from the list `xs`, returns a new `nameValuePair`.
|
|
||||||
|
|
||||||
# Type
|
|
||||||
|
|
||||||
```
|
|
||||||
genAttrs' :: [ Any ] -> (Any -> { name :: String; value :: Any; }) -> AttrSet
|
|
||||||
```
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
:::{.example}
|
|
||||||
## `lib.attrsets.genAttrs'` usage example
|
|
||||||
|
|
||||||
```nix
|
|
||||||
genAttrs' [ "foo" "bar" ] (s: nameValuePair ("x_" + s) ("y_" + s))
|
|
||||||
=> { x_foo = "y_foo"; x_bar = "y_bar"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
:::
|
|
||||||
*/
|
|
||||||
genAttrs' = xs: f: listToAttrs (map f xs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Generate an attribute set by mapping a function over a list of
|
|
||||||
attribute names.
|
|
||||||
|
|
||||||
# Inputs
|
|
||||||
|
|
||||||
`names`
|
|
||||||
|
|
||||||
: Names of values in the resulting attribute set.
|
|
||||||
|
|
||||||
`f`
|
|
||||||
|
|
||||||
: A function, given the name of the attribute, returns the attribute's value.
|
|
||||||
|
|
||||||
# Type
|
|
||||||
|
|
||||||
```
|
|
||||||
genAttrs :: [ String ] -> (String -> Any) -> AttrSet
|
|
||||||
```
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
:::{.example}
|
|
||||||
## `lib.attrsets.genAttrs` usage example
|
|
||||||
|
|
||||||
```nix
|
|
||||||
genAttrs [ "foo" "bar" ] (name: "x_" + name)
|
|
||||||
=> { foo = "x_foo"; bar = "x_bar"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
:::
|
|
||||||
*/
|
|
||||||
genAttrs = names: f: genAttrs' names (n: nameValuePair n (f n));
|
|
||||||
|
|
||||||
mapAttrsRecursiveCond = cond: f: set: let
|
|
||||||
recurse = path:
|
|
||||||
mapAttrs (
|
|
||||||
name: value: let
|
|
||||||
next = path ++ [name];
|
|
||||||
in
|
|
||||||
if isAttrs value && cond value
|
|
||||||
then recurse next value
|
|
||||||
else f next value
|
|
||||||
);
|
|
||||||
in
|
|
||||||
recurse [] set;
|
|
||||||
|
|
||||||
mapAttrsRecursive = f: set: mapAttrsRecursiveCond (as: true) f set;
|
|
||||||
|
|
||||||
# form: attrValueAt :: list string -> set -> Maybe Any
|
|
||||||
# given path as a list of strings, return that value of an
|
|
||||||
# attribute set at that path
|
|
||||||
attrValueAt = path: xs:
|
|
||||||
foldl (left: right:
|
|
||||||
if isAttrs left && hasAttr right left
|
|
||||||
then left.${right}
|
|
||||||
else null)
|
|
||||||
xs
|
|
||||||
path
|
|
||||||
|> nullableToMaybe;
|
|
||||||
|
|
||||||
mergeAttrsList = list: let
|
|
||||||
# `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
|
|
||||||
# Type: Int -> Int -> Attrs
|
|
||||||
binaryMerge = start: end:
|
|
||||||
# assert start < end; # Invariant
|
|
||||||
if end - start >= 2
|
|
||||||
then
|
|
||||||
# If there's at least 2 elements, split the range in two, recurse on each part and merge the result
|
|
||||||
# The invariant is satisfied because each half will have at least 1 element
|
|
||||||
binaryMerge start (start + (end - start) / 2) // binaryMerge (start + (end - start) / 2) end
|
|
||||||
else
|
|
||||||
# Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
|
|
||||||
elemAt list start;
|
|
||||||
in
|
|
||||||
if list == []
|
|
||||||
then
|
|
||||||
# Calling binaryMerge as below would not satisfy its invariant
|
|
||||||
{}
|
|
||||||
else binaryMerge 0 (length list);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Filter an attribute set by removing all attributes for which the
|
|
||||||
given predicate return false.
|
|
||||||
|
|
||||||
# Inputs
|
|
||||||
|
|
||||||
`pred`
|
|
||||||
|
|
||||||
: Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
|
|
||||||
|
|
||||||
<!-- TIP -->
|
|
||||||
If possible, decide on `name` first and on `value` only if necessary.
|
|
||||||
This avoids evaluating the value if the name is already enough, making it possible, potentially, to have the argument reference the return value.
|
|
||||||
(Depending on context, that could still be considered a self reference by users; a common pattern in Nix.)
|
|
||||||
|
|
||||||
<!-- TIP -->
|
|
||||||
`filterAttrs` is occasionally the cause of infinite recursion in configuration systems that allow self-references.
|
|
||||||
To support the widest range of user-provided logic, perform the `filterAttrs` call as late as possible.
|
|
||||||
Typically that's right before using it in a derivation, as opposed to an implicit conversion whose result is accessible to the user's expressions.
|
|
||||||
|
|
||||||
`set`
|
|
||||||
|
|
||||||
: The attribute set to filter
|
|
||||||
|
|
||||||
# Type
|
|
||||||
|
|
||||||
```
|
|
||||||
filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
|
|
||||||
```
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
:::{.example}
|
|
||||||
## `lib.attrsets.filterAttrs` usage example
|
|
||||||
|
|
||||||
```nix
|
|
||||||
filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
|
|
||||||
=> { foo = 1; }
|
|
||||||
```
|
|
||||||
|
|
||||||
:::
|
|
||||||
*/
|
|
||||||
filterAttrs = pred: set: removeAttrs set (filter (name: !pred name set.${name}) (attrNames set));
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{...} @ args: let
|
|
||||||
attrs = import ./attrs.nix args;
|
|
||||||
functions = import ./functions.nix args;
|
|
||||||
lists = import ./lists.nix args;
|
|
||||||
strings = import ./strings.nix args;
|
|
||||||
trivial = import ./trivial.nix args;
|
|
||||||
in
|
|
||||||
attrs.mergeAttrsList [
|
|
||||||
attrs
|
|
||||||
functions
|
|
||||||
lists
|
|
||||||
strings
|
|
||||||
trivial
|
|
||||||
]
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
inherit
|
|
||||||
(nib.std)
|
|
||||||
min
|
|
||||||
;
|
|
||||||
in {
|
|
||||||
# yeah fuck the waiter!! it was cold anyways :(
|
|
||||||
flipCurry = f: a: b: f b a;
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
inherit
|
|
||||||
(builtins)
|
|
||||||
concatMap
|
|
||||||
elemAt
|
|
||||||
foldl'
|
|
||||||
genList
|
|
||||||
length
|
|
||||||
;
|
|
||||||
inherit
|
|
||||||
(nib.std)
|
|
||||||
min
|
|
||||||
;
|
|
||||||
in rec {
|
|
||||||
foldl = op: nul: list: let
|
|
||||||
foldl' = n:
|
|
||||||
if n == -1
|
|
||||||
then nul
|
|
||||||
else op (foldl' (n - 1)) (elemAt list n);
|
|
||||||
in
|
|
||||||
foldl' (length list - 1);
|
|
||||||
|
|
||||||
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
|
||||||
|
|
||||||
findFirstIndex = pred: default: list: let
|
|
||||||
# A naive recursive implementation would be much simpler, but
|
|
||||||
# would also overflow the evaluator stack. We use `foldl'` as a workaround
|
|
||||||
# because it reuses the same stack space, evaluating the function for one
|
|
||||||
# element after another. We can't return early, so this means that we
|
|
||||||
# sacrifice early cutoff, but that appears to be an acceptable cost. A
|
|
||||||
# clever scheme with "exponential search" is possible, but appears over-
|
|
||||||
# engineered for now. See https://github.com/NixOS/nixpkgs/pull/235267
|
|
||||||
# Invariant:
|
|
||||||
# - if index < 0 then el == elemAt list (- index - 1) and all elements before el didn't satisfy pred
|
|
||||||
# - if index >= 0 then pred (elemAt list index) and all elements before (elemAt list index) didn't satisfy pred
|
|
||||||
#
|
|
||||||
# We start with index -1 and the 0'th element of the list, which satisfies the invariant
|
|
||||||
resultIndex =
|
|
||||||
foldl' (
|
|
||||||
index: el:
|
|
||||||
if index < 0
|
|
||||||
then
|
|
||||||
# No match yet before the current index, we need to check the element
|
|
||||||
if pred el
|
|
||||||
then
|
|
||||||
# We have a match! Turn it into the actual index to prevent future iterations from modifying it
|
|
||||||
-index - 1
|
|
||||||
else
|
|
||||||
# Still no match, update the index to the next element (we're counting down, so minus one)
|
|
||||||
index - 1
|
|
||||||
else
|
|
||||||
# There's already a match, propagate the index without evaluating anything
|
|
||||||
index
|
|
||||||
) (-1)
|
|
||||||
list;
|
|
||||||
in
|
|
||||||
if resultIndex < 0
|
|
||||||
then default
|
|
||||||
else resultIndex;
|
|
||||||
|
|
||||||
findFirst = pred: default: list: let
|
|
||||||
index = findFirstIndex pred null list;
|
|
||||||
in
|
|
||||||
if index == null
|
|
||||||
then default
|
|
||||||
else elemAt list index;
|
|
||||||
|
|
||||||
zipListsWith = f: fst: snd:
|
|
||||||
genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
|
|
||||||
|
|
||||||
# zipLists = zipListsWith (fst: snd: {inherit fst snd;});
|
|
||||||
|
|
||||||
sublist = start: count: list: let
|
|
||||||
len = length list;
|
|
||||||
in
|
|
||||||
genList (n: elemAt list (n + start)) (
|
|
||||||
if start >= len
|
|
||||||
then 0
|
|
||||||
else if start + count > len
|
|
||||||
then len - start
|
|
||||||
else count
|
|
||||||
);
|
|
||||||
|
|
||||||
take = sublist 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
inherit
|
|
||||||
(builtins)
|
|
||||||
isPath
|
|
||||||
genList
|
|
||||||
replaceStrings
|
|
||||||
substring
|
|
||||||
stringLength
|
|
||||||
;
|
|
||||||
|
|
||||||
inherit
|
|
||||||
(nib.std)
|
|
||||||
warnIf
|
|
||||||
;
|
|
||||||
in rec {
|
|
||||||
# re-export builtin string methods
|
|
||||||
inherit
|
|
||||||
replaceStrings
|
|
||||||
substring
|
|
||||||
stringLength
|
|
||||||
;
|
|
||||||
|
|
||||||
escape = list: replaceStrings list (map (c: "\\${c}") list);
|
|
||||||
|
|
||||||
escapeRegex = escape (stringToCharacters "\\[{()^$?*+|.");
|
|
||||||
|
|
||||||
hasInfix = infix: content:
|
|
||||||
# Before 23.05, paths would be copied to the store before converting them
|
|
||||||
# to strings and comparing. This was surprising and confusing.
|
|
||||||
warnIf (isPath infix)
|
|
||||||
''
|
|
||||||
lib.strings.hasInfix: The first argument (${toString infix}) is a path value, but only strings are supported.
|
|
||||||
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
|
|
||||||
This function also copies the path to the Nix store, which may not be what you want.
|
|
||||||
This behavior is deprecated and will throw an error in the future.''
|
|
||||||
(builtins.match ".*${escapeRegex infix}.*" "${content}" != null);
|
|
||||||
|
|
||||||
removeSuffix = suffix: str:
|
|
||||||
# Before 23.05, paths would be copied to the store before converting them
|
|
||||||
# to strings and comparing. This was surprising and confusing.
|
|
||||||
warnIf (isPath suffix)
|
|
||||||
''
|
|
||||||
lib.strings.removeSuffix: The first argument (${toString suffix}) is a path value, but only strings are supported.
|
|
||||||
There is almost certainly a bug in the calling code, since this function never removes any suffix in such a case.
|
|
||||||
This function also copies the path to the Nix store, which may not be what you want.
|
|
||||||
This behavior is deprecated and will throw an error in the future.''
|
|
||||||
(
|
|
||||||
let
|
|
||||||
sufLen = stringLength suffix;
|
|
||||||
sLen = stringLength str;
|
|
||||||
in
|
|
||||||
if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str
|
|
||||||
then substring 0 (sLen - sufLen) str
|
|
||||||
else str
|
|
||||||
);
|
|
||||||
|
|
||||||
stringToCharacters = s: genList (p: substring p 1 s) (stringLength s);
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
{...}: let
|
|
||||||
inherit
|
|
||||||
(builtins)
|
|
||||||
warn
|
|
||||||
;
|
|
||||||
in {
|
|
||||||
id = x: x;
|
|
||||||
|
|
||||||
min = x: y:
|
|
||||||
if x < y
|
|
||||||
then x
|
|
||||||
else y;
|
|
||||||
|
|
||||||
max = x: y:
|
|
||||||
if x > y
|
|
||||||
then x
|
|
||||||
else y;
|
|
||||||
|
|
||||||
warnIf = cond: msg:
|
|
||||||
if cond
|
|
||||||
then warn msg
|
|
||||||
else x: x;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,74 +0,0 @@
|
||||||
# REF: https://github.com/numtide/flake-utils/blob/main/allSystems.nix
|
|
||||||
# XXX: TODO: Provide access to ALL of these systems
|
|
||||||
[
|
|
||||||
"aarch64-darwin"
|
|
||||||
"aarch64-genode"
|
|
||||||
"aarch64-linux"
|
|
||||||
"aarch64-netbsd"
|
|
||||||
"aarch64-none"
|
|
||||||
"aarch64_be-none"
|
|
||||||
"arm-none"
|
|
||||||
"armv5tel-linux"
|
|
||||||
"armv6l-linux"
|
|
||||||
"armv6l-netbsd"
|
|
||||||
"armv6l-none"
|
|
||||||
"armv7a-darwin"
|
|
||||||
"armv7a-linux"
|
|
||||||
"armv7a-netbsd"
|
|
||||||
"armv7l-linux"
|
|
||||||
"armv7l-netbsd"
|
|
||||||
"avr-none"
|
|
||||||
"i686-cygwin"
|
|
||||||
"i686-darwin"
|
|
||||||
"i686-freebsd13"
|
|
||||||
"i686-genode"
|
|
||||||
"i686-linux"
|
|
||||||
"i686-netbsd"
|
|
||||||
"i686-none"
|
|
||||||
"i686-openbsd"
|
|
||||||
"i686-windows"
|
|
||||||
"javascript-ghcjs"
|
|
||||||
"m68k-linux"
|
|
||||||
"m68k-netbsd"
|
|
||||||
"m68k-none"
|
|
||||||
"microblaze-linux"
|
|
||||||
"microblaze-none"
|
|
||||||
"microblazeel-linux"
|
|
||||||
"microblazeel-none"
|
|
||||||
"mips64el-linux"
|
|
||||||
"mipsel-linux"
|
|
||||||
"mipsel-netbsd"
|
|
||||||
"mmix-mmixware"
|
|
||||||
"msp430-none"
|
|
||||||
"or1k-none"
|
|
||||||
"powerpc-netbsd"
|
|
||||||
"powerpc-none"
|
|
||||||
"powerpc64-linux"
|
|
||||||
"powerpc64le-linux"
|
|
||||||
"powerpcle-none"
|
|
||||||
"riscv32-linux"
|
|
||||||
"riscv32-netbsd"
|
|
||||||
"riscv32-none"
|
|
||||||
"riscv64-linux"
|
|
||||||
"riscv64-netbsd"
|
|
||||||
"riscv64-none"
|
|
||||||
"rx-none"
|
|
||||||
"s390-linux"
|
|
||||||
"s390-none"
|
|
||||||
"s390x-linux"
|
|
||||||
"s390x-none"
|
|
||||||
"vc4-none"
|
|
||||||
"wasm32-wasi"
|
|
||||||
"wasm64-wasi"
|
|
||||||
"x86_64-cygwin"
|
|
||||||
"x86_64-darwin"
|
|
||||||
"x86_64-freebsd13"
|
|
||||||
"x86_64-genode"
|
|
||||||
"x86_64-linux"
|
|
||||||
"x86_64-netbsd"
|
|
||||||
"x86_64-none"
|
|
||||||
"x86_64-openbsd"
|
|
||||||
"x86_64-redox"
|
|
||||||
"x86_64-solaris"
|
|
||||||
"x86_64-windows"
|
|
||||||
]
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
crossLists = nib.std.crossLists;
|
|
||||||
identityAttrsMany = nib.std.identityAttrsMany;
|
|
||||||
|
|
||||||
# === Internal Helper Functions ===
|
|
||||||
toSystemName = arch: platform: "${arch}-${platform}";
|
|
||||||
listsToSystemNames = archs: platforms:
|
|
||||||
crossLists (arch: platform: toSystemName arch platform)
|
|
||||||
[
|
|
||||||
(builtins.attrValues archs)
|
|
||||||
(builtins.attrValues platforms)
|
|
||||||
];
|
|
||||||
in rec {
|
|
||||||
# REF: https://github.com/nix-systems/nix-systems
|
|
||||||
archs = identityAttrsMany [
|
|
||||||
"x86_64"
|
|
||||||
"aarch64"
|
|
||||||
"riscv64"
|
|
||||||
];
|
|
||||||
|
|
||||||
# REF: https://github.com/nix-systems/nix-systems
|
|
||||||
platforms = identityAttrsMany [
|
|
||||||
"linux"
|
|
||||||
"darwin"
|
|
||||||
];
|
|
||||||
|
|
||||||
# Nix System Identifier Lists - Default Supported Systems
|
|
||||||
# systems = systemsDefault;
|
|
||||||
systems.default = systems.x86_64 // systems.aarch64;
|
|
||||||
|
|
||||||
# Nix System Identifier Lists - All Potential Systems
|
|
||||||
systems.all = listsToSystemNames archs platforms;
|
|
||||||
|
|
||||||
# Nix System Identifier Lists - Platform Specific
|
|
||||||
systems.linux = listsToSystemNames archs [platforms.linux];
|
|
||||||
systems.darwin = listsToSystemNames archs [platforms.darwin];
|
|
||||||
|
|
||||||
# Nix System Identifier Lists - Architecture Specific
|
|
||||||
systems.x86_64 = listsToSystemNames [archs.x86_64] platforms;
|
|
||||||
systems.aarch64 = listsToSystemNames [archs.aarch64] platforms;
|
|
||||||
systems.riscv64 = listsToSystemNames [archs.riscv64] platforms;
|
|
||||||
}
|
|
||||||
37
nib/sys.nix
37
nib/sys.nix
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
systems,
|
|
||||||
nib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
std = nib.std;
|
|
||||||
in {
|
|
||||||
# === External Functions ===
|
|
||||||
withPkgs = repo: config: system:
|
|
||||||
import repo {
|
|
||||||
inherit system;
|
|
||||||
}
|
|
||||||
// config;
|
|
||||||
|
|
||||||
mkSys = input: let
|
|
||||||
# function taking a system as argument
|
|
||||||
pkgsFor = input.pkgs;
|
|
||||||
in {
|
|
||||||
inherit pkgsFor;
|
|
||||||
forAllSystems = f:
|
|
||||||
std.genAttrs systems (
|
|
||||||
system: f system (pkgsFor system)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
mkUSys = input: let
|
|
||||||
# functions taking a system as argument
|
|
||||||
pkgsFor = input.pkgs;
|
|
||||||
upkgsFor = input.upkgs;
|
|
||||||
in {
|
|
||||||
inherit pkgsFor upkgsFor;
|
|
||||||
forAllSystems = f:
|
|
||||||
std.genAttrs systems (
|
|
||||||
system: f system (pkgsFor system) (upkgsFor system)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
{nib, ...} @ args: let
|
|
||||||
fault = import ./fault.nix args;
|
|
||||||
maybe = import ./maybe.nix args;
|
|
||||||
res = import ./res.nix args;
|
|
||||||
terminal = import ./terminal.nix args;
|
|
||||||
in
|
|
||||||
nib.std.mergeAttrsList [
|
|
||||||
# submodule is included directly to this module (ie self.myFunc)
|
|
||||||
fault
|
|
||||||
maybe
|
|
||||||
res
|
|
||||||
terminal
|
|
||||||
|
|
||||||
rec {
|
|
||||||
# TODO
|
|
||||||
isAlgebraic = T: false;
|
|
||||||
|
|
||||||
isList = T: !isAlgebraic T && builtins.isList T;
|
|
||||||
isAttrs = T: !isAlgebraic T && builtins.isAttrs T;
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{nib, ...}: rec {
|
|
||||||
# Fault Monad
|
|
||||||
# Wrapper around an error (ie builtins.abort)
|
|
||||||
Fault = error: {
|
|
||||||
_error_ = error;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Pattern Matching
|
|
||||||
isFault = T: builtins.attrNames T == ["_error_"];
|
|
||||||
|
|
||||||
# Unwrap (Monadic Return Operation)
|
|
||||||
unwrapFault = T:
|
|
||||||
assert isFault T || nib.panic.badType "Fault" T;
|
|
||||||
T._error_;
|
|
||||||
|
|
||||||
# Map (Monadic Bind Operation)
|
|
||||||
mapFault = f: T: Fault (f (unwrapFault T));
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
findFirst = nib.std.findFirst;
|
|
||||||
# TODO: try get enum generation working (and other type constructors)
|
|
||||||
# Maybe = mkEnum "nib::Maybe" {
|
|
||||||
# Some = mkEnumVariant {value = "nix::String";};
|
|
||||||
# None = mkEnumVariant {};
|
|
||||||
# };
|
|
||||||
# TODO: you could even simplify this and pregenerate
|
|
||||||
# TODO: monadic operations by defining:
|
|
||||||
# mkMonad = mkEnum ... (blah blah blah)
|
|
||||||
#
|
|
||||||
# NOTE: internal view:
|
|
||||||
# NOTE: sum == enum
|
|
||||||
# NOTE: product == struct
|
|
||||||
# NOTE: terminal == literal/epsilon (in EBNF/Extended Backus-Naur form)
|
|
||||||
# Maybe = {
|
|
||||||
# # "adt" aka "algebraic data type"
|
|
||||||
# _adt_ = nib.types.adt.sum;
|
|
||||||
# _type_ = "Maybe"; # full type signature is "nib::Maybe"
|
|
||||||
# _vars_ = [
|
|
||||||
# {
|
|
||||||
# _adt_ = nib.types.adt.product;
|
|
||||||
# _type_ = "Some"; # type signature is "nib::Maybe::Some"
|
|
||||||
# _body_ = [
|
|
||||||
# # the name "value" was chosen by the user, its not inherit to nib
|
|
||||||
# value = {
|
|
||||||
# _adt_ = nib.types.adt.terminal;
|
|
||||||
# # nib.typeSig simply parses the string by splitting on "::" and forming a list
|
|
||||||
# _sig_ = nib.typeSig "nix::String";
|
|
||||||
# };
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
# {
|
|
||||||
# _adt_ = nib.types.adt.terminal;
|
|
||||||
# _type_ = "None"; # type signature is "nib::Maybe::None"
|
|
||||||
# _sig_ = nib.typeSig "nix::Null";
|
|
||||||
# };
|
|
||||||
# ];
|
|
||||||
# None = {
|
|
||||||
#
|
|
||||||
# };
|
|
||||||
# _body_ = {
|
|
||||||
# _some_ = some; # allows _value_ to be null (yuck!!)
|
|
||||||
# _value_ = value;
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# TODO: you could enforceType types as follows
|
|
||||||
# DEFINE: enforce = pred: var:
|
|
||||||
# DEFINE: assert (pred var) || throw "..."; var;
|
|
||||||
# DEFINE: enforceType = type:
|
|
||||||
# DEFINE: enforce (var: nib.typeOf var == type)
|
|
||||||
# value: let
|
|
||||||
# # NOTE: var is either a fixed-point of enforceType or fails
|
|
||||||
# # NOTE: either way you don't need to worry about a recursive definition!
|
|
||||||
# var = enforceType "nib::Maybe" var;
|
|
||||||
# in { ... }
|
|
||||||
in rec {
|
|
||||||
# Maybe (Option) Monad
|
|
||||||
Maybe = some: value: {
|
|
||||||
_some_ = some; # allows _value_ to be null (yuck!!)
|
|
||||||
_value_ = value;
|
|
||||||
};
|
|
||||||
Some = Maybe true;
|
|
||||||
None = Maybe false null;
|
|
||||||
|
|
||||||
# Pattern Matching (unsafe and safe variants)
|
|
||||||
isMaybe = T: builtins.attrNames T == ["_some_" "_value_"];
|
|
||||||
isSome' = T: isMaybe T && T._some_;
|
|
||||||
isSome = T:
|
|
||||||
assert isMaybe T || nib.panic.badType "Maybe" T;
|
|
||||||
isSome' T;
|
|
||||||
isNone' = T: isMaybe T && !T._some_;
|
|
||||||
isNone = T:
|
|
||||||
assert isMaybe T || nib.panic.badType "Maybe" T;
|
|
||||||
isNone' T;
|
|
||||||
|
|
||||||
# TODO: ensure you check isNone if isSome fails (otherwise it could be another type!)
|
|
||||||
# Unwrap (Monadic Return Operation)
|
|
||||||
unwrapMaybe = f: g: T:
|
|
||||||
if isSome T
|
|
||||||
then f T._value_
|
|
||||||
else g T._value_;
|
|
||||||
unwrapSome = unwrapMaybe (v: v);
|
|
||||||
unwrapNone = f: unwrapMaybe f (v: v);
|
|
||||||
|
|
||||||
# Map (Monadic Bind Operation)
|
|
||||||
mapMaybe = f: unwrapMaybe (v: Some (f v)) (_: None);
|
|
||||||
# NOTE: yes this does nothing, its only here so I don't forget
|
|
||||||
# NOTE: (ie when pregenerating monadic operations with a custom ADT module)
|
|
||||||
mapSome = mapMaybe;
|
|
||||||
|
|
||||||
# Conditionals
|
|
||||||
someOr = f: T:
|
|
||||||
if isSome T
|
|
||||||
then T
|
|
||||||
else f T;
|
|
||||||
|
|
||||||
noneOr = f: T:
|
|
||||||
if isNone T
|
|
||||||
then T
|
|
||||||
else f T;
|
|
||||||
|
|
||||||
firstSome = findFirst isSome' None;
|
|
||||||
|
|
||||||
nullableToMaybe = x:
|
|
||||||
if x == null
|
|
||||||
then None
|
|
||||||
else Some x;
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
{nib, ...}: let
|
|
||||||
findFirst = nib.std.findFirst;
|
|
||||||
in rec {
|
|
||||||
# Res (Result) Monad
|
|
||||||
Res = success: value: {
|
|
||||||
_success_ = success;
|
|
||||||
_value_ = value;
|
|
||||||
};
|
|
||||||
Ok = Res true;
|
|
||||||
Ok' = Ok "ok";
|
|
||||||
Err = Res false;
|
|
||||||
Err' = Err "err";
|
|
||||||
|
|
||||||
# Pattern Matching
|
|
||||||
isRes = R: builtins.attrNames R == ["_success_" "_value_"];
|
|
||||||
isOk' = R: isRes R && R._success_;
|
|
||||||
isOk = R:
|
|
||||||
assert isRes R || nib.panic.badType "Res" R;
|
|
||||||
isOk' R;
|
|
||||||
isErr' = R: isRes R && !R._success_;
|
|
||||||
isErr = R:
|
|
||||||
assert isRes R || nib.panic.badType "Res" R;
|
|
||||||
isErr' R;
|
|
||||||
|
|
||||||
# Unwrap (Monadic Return Operation)
|
|
||||||
unwrapRes = f: g: R:
|
|
||||||
if isOk R
|
|
||||||
then f R._value_
|
|
||||||
else g R._value_;
|
|
||||||
unwrapOk = unwrapRes (v: v);
|
|
||||||
unwrapErr = f: unwrapRes f (v: v);
|
|
||||||
|
|
||||||
# Map (Monadic Bind Operation)
|
|
||||||
mapRes = f: g: unwrapRes (v: Ok (f v)) (v: Err (f v));
|
|
||||||
mapOk = f: mapRes f (v: v);
|
|
||||||
mapErr = f: mapRes (v: v) f;
|
|
||||||
|
|
||||||
# Conditionals
|
|
||||||
okOr = f: R:
|
|
||||||
if isOk R
|
|
||||||
then R
|
|
||||||
else f R;
|
|
||||||
|
|
||||||
errOr = f: R:
|
|
||||||
if isErr R
|
|
||||||
then R
|
|
||||||
else f R;
|
|
||||||
|
|
||||||
# Standard Helpers
|
|
||||||
firstErr = findFirst isErr' Ok';
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
{nib, ...}: rec {
|
|
||||||
# Terminal Monad
|
|
||||||
# Wrapper around a value (preserves lazy eval for the value)
|
|
||||||
Terminal = value: {
|
|
||||||
_nbtype_ = "nib::Terminal";
|
|
||||||
_value_ = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Pattern Matching
|
|
||||||
isTerminal = T:
|
|
||||||
builtins.isAttrs T
|
|
||||||
&& builtins.attrNames T == ["_nbtype_" "_value_"]
|
|
||||||
&& T._nbtype_ == "nib::Terminal";
|
|
||||||
|
|
||||||
# Unwrap (Monadic Return Operation)
|
|
||||||
unwrapTerminal = T:
|
|
||||||
assert isTerminal T || nib.panic.badType "Terminal" T;
|
|
||||||
T._value_;
|
|
||||||
|
|
||||||
# Map (Monadic Bind Operation)
|
|
||||||
mapTerminal = f: T: Terminal (f (unwrapTerminal T));
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{...}: rec {
|
|
||||||
isType = type: T: type == typeOf T;
|
|
||||||
isSameType = T1: T2: typeOf T1 == typeOf T2;
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
typeOf = builtins.typeOf;
|
|
||||||
# TODO
|
|
||||||
typeName = typeOf;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue