fake.modules transposition for aspect-oriented Dendritic Nix. with cross-aspect dependencies. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix aspect oriented

improve aspect dependencies (#4)

authored by oeiuwq.com and committed by

GitHub 2b001767 5b06ff9f

+55 -38
+1 -1
README.md
··· 64 64 As a deps-free library from `./default.nix`: 65 65 66 66 ```nix 67 - let transpose = import ./default.nix lib; in 67 + let transpose = import ./default.nix { lib = pkgs.lib; }; in 68 68 transpose { a.b.c = 1; } # => { b.a.c = 1; } 69 69 ``` 70 70
+8 -5
checkmate.nix
··· 124 124 { 125 125 aspectOne = { 126 126 description = "os config"; 127 - require = with config; [ aspectTwo.provide.default ]; 128 - classOne.foo = lib.mkDefault "os"; 127 + requires = with config; [ aspectTwo ]; 128 + classOne.bar = [ "os" ]; 129 129 }; 130 130 131 131 aspectTwo = { 132 132 description = "user config at os level"; 133 - classOne.foo = "user"; 133 + classOne.bar = [ "user" ]; 134 134 }; 135 135 }; 136 136 }); 137 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).foo; 138 - expected = "user"; 137 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 138 + expected = [ 139 + "os" 140 + "user" 141 + ]; 139 142 in 140 143 { 141 144 inherit expr expected;
+46 -32
flakeModule.nix
··· 1 - { lib, config, ... }: 1 + { 2 + lib, 3 + config, 4 + ... 5 + }: 2 6 let 3 - flakeModules = 7 + aspects = config.flake.aspects; 8 + 9 + transpose = import ./. { inherit lib emit; }; 10 + emit = transposed: [ 11 + { 12 + inherit (transposed) parent child; 13 + value = aspectModule aspects.${transposed.child} transposed.parent; 14 + } 15 + ]; 16 + 17 + aspectModule = 18 + aspect: class: 4 19 let 5 - aspects = config.flake.aspects; 6 - transpose = import ./. { inherit lib emit; }; 7 - require = 8 - fromAspect: class: f: 9 - (f fromAspect).${class} or { }; 10 - emit = 11 - transposed: 12 - let 13 - class = transposed.parent; 14 - aspect = transposed.child; 15 - required.imports = lib.map (require aspect class) aspects.${aspect}.require; 16 - item = { 17 - inherit (transposed) parent child; 18 - value.imports = [ 19 - transposed.value 20 - required 21 - ]; 22 - }; 23 - in 24 - [ 25 - item 26 - ]; 20 + require = f: aspectModule (f (aspect // { inherit class; })) class; 21 + module.imports = lib.flatten [ 22 + (aspect.${class} or { }) 23 + (lib.map require aspect.requires) 24 + ]; 27 25 in 28 - transpose aspects; 26 + module; 27 + 28 + providerType = lib.types.functionTo aspectSubmoduleType; 29 29 30 30 aspectSubmoduleType = lib.types.submodule ( 31 31 { name, config, ... }: 32 32 { 33 33 freeformType = lib.types.lazyAttrsOf lib.types.deferredModule; 34 + options.name = lib.mkOption { 35 + readOnly = true; 36 + description = "Aspect name"; 37 + default = name; 38 + type = lib.types.str; 39 + }; 34 40 options.description = lib.mkOption { 35 41 description = "Aspect description"; 36 42 default = "Aspect ${name}"; 37 43 type = lib.types.str; 38 44 }; 39 - options.require = lib.mkOption { 45 + options.requires = lib.mkOption { 40 46 description = "Providers to ask aspects from"; 41 47 type = lib.types.listOf providerType; 42 48 default = [ ]; 43 49 }; 44 - options.provide = lib.mkOption { 45 - description = "Providers for ${name} aspect"; 50 + options.provides = lib.mkOption { 51 + description = "Providers of aspect for other aspects"; 46 52 default = { }; 47 53 type = lib.types.submodule { 48 54 freeformType = lib.types.lazyAttrsOf providerType; 49 - options.default = lib.mkOption { 50 - description = "Provider of ${name} aspect"; 55 + options.itself = lib.mkOption { 56 + readOnly = true; 57 + description = "Provides itself"; 51 58 type = providerType; 52 59 default = _: config; 53 60 }; 54 61 }; 55 62 }; 63 + options.__functor = lib.mkOption { 64 + internal = true; 65 + readOnly = true; 66 + visible = false; 67 + description = "Functor to default provider"; 68 + type = lib.types.unspecified; 69 + default = _: config.provides.itself; 70 + }; 56 71 } 57 72 ); 58 73 59 - providerType = lib.types.functionTo aspectSubmoduleType; 60 74 in 61 75 { 62 76 options.flake.aspects = lib.mkOption { ··· 70 84 freeformType = lib.types.lazyAttrsOf aspectSubmoduleType; 71 85 }; 72 86 }; 73 - config.flake.modules = flakeModules; 87 + config.flake.modules = transpose aspects; 74 88 }