add mix as a primitive (for nt bootstrap)
This commit is contained in:
parent
6e8eaa982c
commit
498412e050
2 changed files with 172 additions and 0 deletions
154
nt/primitives/mix/default.nix
Normal file
154
nt/primitives/mix/default.nix
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
{this, ...}: let
|
||||
inherit
|
||||
(builtins)
|
||||
attrNames
|
||||
attrValues
|
||||
hasAttr
|
||||
listToAttrs
|
||||
removeAttrs
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.util)
|
||||
filterAttrs
|
||||
hasInfix
|
||||
mergeAttrsList
|
||||
nameValuePair
|
||||
projectOnto
|
||||
removeSuffix
|
||||
Wrap
|
||||
;
|
||||
|
||||
modNameFromPath = path: let
|
||||
name = baseNameOf path |> removeSuffix ".nix";
|
||||
in
|
||||
assert (! hasInfix "." name)
|
||||
|| throw ''
|
||||
Mix module ${path} has invalid name \"${name}\".
|
||||
Module names must not contain the . (period) character.
|
||||
''; name;
|
||||
in rec {
|
||||
# by default the imported module is given the basename of its path
|
||||
# but you can set it manually by using the `mix.mod` function.
|
||||
importMods = list: inputs:
|
||||
list
|
||||
|> map (path: nameValuePair (modNameFromPath path) (import path inputs))
|
||||
|> listToAttrs;
|
||||
|
||||
importMergeMods = list: inputs:
|
||||
list
|
||||
|> map (path: (import path inputs))
|
||||
|> mergeAttrsList;
|
||||
|
||||
# create a new and empty mixture
|
||||
newMixture' = let
|
||||
self = {
|
||||
# trapdoor attribute
|
||||
_' = {
|
||||
path = [];
|
||||
modName = null;
|
||||
};
|
||||
};
|
||||
in
|
||||
self;
|
||||
|
||||
# a splash of this, a splash of that ^_^
|
||||
add = ingredients: mixture: let
|
||||
sidedish = mergeAttrsList ingredients;
|
||||
in
|
||||
# bone apple tea ;-;
|
||||
mixture // filterAttrs (x: _: ! hasAttr x mixture) sidedish;
|
||||
|
||||
newMixture = inputs: modBuilder: let
|
||||
inputs' = removeAttrs inputs ["this"];
|
||||
inputsWithThis = inputs' // {this = mixture;};
|
||||
|
||||
# mixture components are ordered based on shadowing
|
||||
mixture =
|
||||
inputs'
|
||||
// importMods meta.submods.public inputsWithThis
|
||||
// importMergeMods meta.includes.public inputsWithThis
|
||||
// content;
|
||||
|
||||
# this = {
|
||||
# # trapdoor attribute
|
||||
# _' = {
|
||||
# path = [];
|
||||
# };
|
||||
# parent' = throw "Mix: The mixture's root module has no parent by definition.";
|
||||
# };
|
||||
|
||||
# partition modAttrs' into metadata and content
|
||||
modAttrs' = modBuilder mixture;
|
||||
content = removeAttrs modAttrs' (attrNames meta);
|
||||
# attributes expected by and that directly modify mix's behaviour
|
||||
meta =
|
||||
modAttrs'
|
||||
|> projectOnto
|
||||
{
|
||||
includes = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
submods = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
options = Wrap {};
|
||||
config = Wrap {};
|
||||
};
|
||||
in
|
||||
mixture;
|
||||
|
||||
mkMod = mixture: modBuilder: let
|
||||
# XXX: TODO
|
||||
# modAttrs = modBuilder privateMixture;
|
||||
modAttrs = modBuilder mixture;
|
||||
|
||||
# attributes expected by and that directly modify mix's behaviour
|
||||
meta =
|
||||
modAttrs
|
||||
|> projectOnto
|
||||
{
|
||||
includes = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
submods = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
options = Wrap {};
|
||||
config = Wrap {};
|
||||
};
|
||||
|
||||
# XXX: TODO
|
||||
# protectedMixture = add [public protected] mixture;
|
||||
# privateMixture = add [private] protectedMixture;
|
||||
|
||||
mkInterface = name: mixture: base:
|
||||
mergeAttrsList
|
||||
(attrValues <| importMods meta.includes.${name} mixture)
|
||||
++ [
|
||||
base
|
||||
(importMods meta.submods.${name} mixture)
|
||||
];
|
||||
# XXX: TODO
|
||||
# NOTE: public submodules are still DESCENDENTS
|
||||
# NOTE: and should be able to access protected values :)
|
||||
# public = mkInterface "public" protectedMixture content;
|
||||
# protected = mkInterface "protected" protectedMixture public;
|
||||
# private = mkInterface "private" privateMixture protected;
|
||||
content = throw "TODO";
|
||||
public = mkInterface "public" mixture content;
|
||||
protected = mkInterface "protected" mixture public;
|
||||
private = mkInterface "private" mixture protected;
|
||||
in
|
||||
# XXX: TODO
|
||||
# public;
|
||||
modAttrs;
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
{...}: let
|
||||
inherit
|
||||
(builtins)
|
||||
attrNames
|
||||
elem
|
||||
elemAt
|
||||
filter
|
||||
|
|
@ -10,8 +11,10 @@
|
|||
genList
|
||||
length
|
||||
mapAttrs
|
||||
match
|
||||
partition
|
||||
removeAttrs
|
||||
replaceStrings
|
||||
stringLength
|
||||
substring
|
||||
tail
|
||||
|
|
@ -97,6 +100,14 @@ in rec {
|
|||
stringInit = x: x |> stringTake 1;
|
||||
stringLast = x: stringElem (stringLength x - 1);
|
||||
|
||||
stringToCharacters = s: genList (p: substring p 1 s) (stringLength s);
|
||||
|
||||
escape = list: replaceStrings list (map (c: "\\${c}") list);
|
||||
escapeRegex = escape (stringToCharacters "\\[{()^$?*+|.");
|
||||
|
||||
hasInfix = infix: content:
|
||||
match ".*${escapeRegex infix}.*" "${content}" != null;
|
||||
|
||||
countEvensLeq = n: n / 2;
|
||||
countOddsLeq = n: (n + 1) / 2;
|
||||
|
||||
|
|
@ -151,4 +162,11 @@ in rec {
|
|||
|> filter (x: head x == name)
|
||||
|> map tail
|
||||
|> removeAttrsRec);
|
||||
|
||||
filterAttrs = pred: xs:
|
||||
attrNames xs
|
||||
|> filter (name: ! pred name xs.${name})
|
||||
|> removeAttrs xs;
|
||||
|
||||
nameValuePair = name: value: {inherit name value;};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue