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

test using fixpoints

+76 -15
+55 -4
checkmate.nix
··· 118 118 119 119 aspects."test dependencies on aspects" = 120 120 let 121 - flake = mkFlake ({ 121 + flake = mkFlake { 122 122 flake.aspects = 123 123 { aspects, ... }: 124 124 { ··· 133 133 classOne.bar = [ "user" ]; 134 134 }; 135 135 }; 136 - }); 136 + }; 137 137 expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 138 138 expected = [ 139 139 "os" ··· 146 146 147 147 aspects."test provides" = 148 148 let 149 - flake = mkFlake ({ 149 + flake = mkFlake { 150 150 flake.aspects = 151 151 { aspects, ... }: 152 152 { ··· 178 178 classOne.bar = [ "three:${class}:${lib.concatStringsSep "/" aspect-chain}" ]; 179 179 }; 180 180 }; 181 - }); 181 + }; 182 182 expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 183 183 expected = [ 184 184 "three:classOne:aspectOne/aspectTwo.foo" 185 185 "two:classOne:aspectOne" 186 + ]; 187 + in 188 + { 189 + inherit expr expected; 190 + }; 191 + 192 + aspects."test provides using fixpoints" = 193 + let 194 + flake = mkFlake { 195 + flake.aspects = 196 + { aspects, ... }: 197 + { 198 + aspectOne = { 199 + classOne.bar = [ "1" ]; 200 + includes = [ 201 + aspects.aspectTwo 202 + ]; 203 + }; 204 + 205 + aspectTwo = 206 + { aspect, ... }: 207 + { 208 + classOne.bar = [ "2" ]; 209 + includes = [ aspect.provides.three-and-four-and-five ]; 210 + provides = 211 + { provides, ... }: 212 + { 213 + three-and-four-and-five = _: { 214 + classOne.bar = [ "3" ]; 215 + includes = [ 216 + provides.four 217 + aspects.five 218 + ]; 219 + }; 220 + four = _: { 221 + classOne.bar = [ "4" ]; 222 + }; 223 + }; 224 + }; 225 + 226 + five.classOne.bar = [ "5" ]; 227 + }; 228 + }; 229 + 230 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 231 + expected = [ 232 + "1" 233 + "2" 234 + "3" 235 + "4" 236 + "5" 186 237 ]; 187 238 in 188 239 {
+21 -11
types.nix
··· 8 8 providerType = lib.types.functionTo aspectSubmoduleType; 9 9 10 10 aspectSubmoduleType = lib.types.submodule ( 11 - { name, config, ... }: 11 + { 12 + name, 13 + aspect, 14 + config, 15 + ... 16 + }: 12 17 { 13 18 freeformType = lib.types.lazyAttrsOf lib.types.deferredModule; 19 + config._module.args.aspect = config; 14 20 options.name = lib.mkOption { 15 21 description = "Aspect name"; 16 22 default = name; ··· 29 35 options.provides = lib.mkOption { 30 36 description = "Providers of aspect for other aspects"; 31 37 default = { }; 32 - type = lib.types.submodule { 33 - freeformType = lib.types.lazyAttrsOf providerType; 34 - options.itself = lib.mkOption { 35 - readOnly = true; 36 - description = "Provides itself"; 37 - type = providerType; 38 - default = _: config; 39 - }; 40 - }; 38 + type = lib.types.submodule ( 39 + { config, ... }: 40 + { 41 + freeformType = lib.types.lazyAttrsOf providerType; 42 + config._module.args.provides = config; 43 + options.itself = lib.mkOption { 44 + readOnly = true; 45 + description = "Provides itself"; 46 + type = providerType; 47 + default = _: aspect; 48 + }; 49 + } 50 + ); 41 51 }; 42 52 options.__functor = lib.mkOption { 43 53 internal = true; 44 54 visible = false; 45 55 description = "Functor to default provider"; 46 56 type = lib.types.functionTo lib.types.unspecified; 47 - default = _: config.provides.itself; 57 + default = _: aspect.provides.itself; 48 58 }; 49 59 } 50 60 );