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
|
{...}: let
|
||||||
inherit
|
inherit
|
||||||
(builtins)
|
(builtins)
|
||||||
|
attrNames
|
||||||
elem
|
elem
|
||||||
elemAt
|
elemAt
|
||||||
filter
|
filter
|
||||||
|
|
@ -10,8 +11,10 @@
|
||||||
genList
|
genList
|
||||||
length
|
length
|
||||||
mapAttrs
|
mapAttrs
|
||||||
|
match
|
||||||
partition
|
partition
|
||||||
removeAttrs
|
removeAttrs
|
||||||
|
replaceStrings
|
||||||
stringLength
|
stringLength
|
||||||
substring
|
substring
|
||||||
tail
|
tail
|
||||||
|
|
@ -97,6 +100,14 @@ in rec {
|
||||||
stringInit = x: x |> stringTake 1;
|
stringInit = x: x |> stringTake 1;
|
||||||
stringLast = x: stringElem (stringLength x - 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;
|
countEvensLeq = n: n / 2;
|
||||||
countOddsLeq = n: (n + 1) / 2;
|
countOddsLeq = n: (n + 1) / 2;
|
||||||
|
|
||||||
|
|
@ -151,4 +162,11 @@ in rec {
|
||||||
|> filter (x: head x == name)
|
|> filter (x: head x == name)
|
||||||
|> map tail
|
|> map tail
|
||||||
|> removeAttrsRec);
|
|> 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