split /nt/mix
This commit is contained in:
parent
c3f03856d3
commit
9c1e458140
3 changed files with 152 additions and 189 deletions
|
|
@ -1,190 +1,20 @@
|
|||
{this, ...}: let
|
||||
inherit
|
||||
(builtins)
|
||||
attrNames
|
||||
hasAttr
|
||||
isAttrs
|
||||
isFunction
|
||||
listToAttrs
|
||||
removeAttrs
|
||||
typeOf
|
||||
;
|
||||
|
||||
inherit
|
||||
(this)
|
||||
enfIsPrimitive
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.std)
|
||||
filterAttrs
|
||||
hasInfix
|
||||
mergeAttrsList
|
||||
nameValuePair
|
||||
removeSuffix
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.parse)
|
||||
projectOnto
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.types)
|
||||
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.
|
||||
|
||||
importMod = path: inputs:
|
||||
assert enfIsPrimitive "path" path "importMod"; let
|
||||
mod = import path;
|
||||
in
|
||||
if isAttrs mod
|
||||
then mod
|
||||
else let
|
||||
modResult = mod inputs;
|
||||
in
|
||||
# TODO: create a better version of toString that can handle sets, lists, and null
|
||||
assert isFunction mod
|
||||
|| throw ''
|
||||
Mix modules expect primitive type "set" or "lambda" (returning "set").
|
||||
Got primitive type "${typeOf mod}" instead.
|
||||
'';
|
||||
assert isAttrs modResult
|
||||
|| throw ''
|
||||
Mix module provided as primitive type "lambda" must return primitive type "set"!
|
||||
Got primitive return type "${typeOf modResult} instead."
|
||||
''; modResult;
|
||||
|
||||
mkSubMods = list: inputs:
|
||||
list
|
||||
|> map (path: nameValuePair (modNameFromPath path) (importMod path inputs))
|
||||
|> listToAttrs;
|
||||
|
||||
mkIncludes = list: inputs:
|
||||
list
|
||||
|> map (path: (importMod 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'
|
||||
// mkSubMods meta.submods.public inputsWithThis
|
||||
// mkIncludes 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 [
|
||||
base
|
||||
(mkIncludes meta.includes.${name} mixture)
|
||||
(mkSubMods meta.submods.${name} mixture)
|
||||
{
|
||||
this,
|
||||
mix,
|
||||
...
|
||||
}: let
|
||||
inputs = {
|
||||
nt = this;
|
||||
inherit mix;
|
||||
};
|
||||
in
|
||||
mix.newMixture inputs (mixture: {
|
||||
includes = {
|
||||
public = [
|
||||
./mixture.nix
|
||||
];
|
||||
# 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;
|
||||
}
|
||||
protected = [
|
||||
./import.nix
|
||||
];
|
||||
};
|
||||
})
|
||||
|
|
|
|||
65
nt/mix/import.nix
Normal file
65
nt/mix/import.nix
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
{this, ...}: let
|
||||
inherit
|
||||
(builtins)
|
||||
isAttrs
|
||||
isFunction
|
||||
listToAttrs
|
||||
typeOf
|
||||
;
|
||||
|
||||
inherit
|
||||
(this)
|
||||
enfIsPrimitive
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.std)
|
||||
hasInfix
|
||||
mergeAttrsList
|
||||
nameValuePair
|
||||
removeSuffix
|
||||
;
|
||||
|
||||
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.
|
||||
|
||||
importMod = path: inputs:
|
||||
assert enfIsPrimitive "path" path "importMod"; let
|
||||
mod = import path;
|
||||
in
|
||||
if isAttrs mod
|
||||
then mod
|
||||
else let
|
||||
modResult = mod inputs;
|
||||
in
|
||||
# TODO: create a better version of toString that can handle sets, lists, and null
|
||||
assert isFunction mod
|
||||
|| throw ''
|
||||
Mix modules expect primitive type "set" or "lambda" (returning "set").
|
||||
Got primitive type "${typeOf mod}" instead.
|
||||
'';
|
||||
assert isAttrs modResult
|
||||
|| throw ''
|
||||
Mix module provided as primitive type "lambda" must return primitive type "set"!
|
||||
Got primitive return type "${typeOf modResult} instead."
|
||||
''; modResult;
|
||||
|
||||
mkIncludes = list: inputs:
|
||||
list
|
||||
|> map (path: (importMod path inputs))
|
||||
|> mergeAttrsList;
|
||||
|
||||
mkSubMods = list: inputs:
|
||||
list
|
||||
|> map (path: nameValuePair (modNameFromPath path) (importMod path inputs))
|
||||
|> listToAttrs;
|
||||
}
|
||||
68
nt/mix/mixture.nix
Normal file
68
nt/mix/mixture.nix
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
this,
|
||||
nt,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(nt.parse)
|
||||
projectOnto
|
||||
;
|
||||
|
||||
inherit
|
||||
(this.mix)
|
||||
mkIncludes
|
||||
mkSubMods
|
||||
;
|
||||
in {
|
||||
newMixture = inputs: modBuilder: let
|
||||
mkInputs = this: {inherit this;} // inputs;
|
||||
|
||||
# parse mixture declaration structure
|
||||
decl =
|
||||
modBuilder mixture.private
|
||||
|> projectOnto
|
||||
{
|
||||
includes = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
submods = {
|
||||
public = [];
|
||||
private = [];
|
||||
protected = [];
|
||||
};
|
||||
# XXX: TODO: are these needed?
|
||||
# options = Wrap {};
|
||||
# config = Wrap {};
|
||||
};
|
||||
|
||||
descendentInputs = mkInputs mixture.protected;
|
||||
mkMixtureIncludes = layer: mkIncludes decl.includes.${layer} descendentInputs;
|
||||
mkMixtureSubMods = layer: mkSubMods decl.submods.${layer} descendentInputs;
|
||||
includes = {
|
||||
public = mkMixtureIncludes "public";
|
||||
protected = includes.public // mkMixtureIncludes "protected";
|
||||
private = includes.protected // mkMixtureIncludes "private";
|
||||
};
|
||||
submods = {
|
||||
public = mkMixtureSubMods "public";
|
||||
protected = submods.public // mkMixtureSubMods "protected";
|
||||
private = submods.protected // mkMixtureSubMods "private";
|
||||
};
|
||||
|
||||
# mixture components are ordered based on shadowing
|
||||
mixture = {
|
||||
public =
|
||||
includes.public
|
||||
// submods.public;
|
||||
protected =
|
||||
includes.protected
|
||||
// submods.protected;
|
||||
private =
|
||||
includes.private
|
||||
// submods.private;
|
||||
};
|
||||
in
|
||||
mixture.public;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue