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

provider args must be named

+26 -12
+6 -7
checkmate.nix
··· 246 flake.aspects = 247 { aspects, ... }: 248 { 249 - aspectOne.includes = [ (aspects.aspectTwo.provides.hello "mundo") ]; 250 aspectOne.classOne.bar = [ "1" ]; 251 252 aspectTwo.provides.hello = 253 - world: 254 - # deadnix: skip 255 - { aspect-chain, class }: 256 - { 257 classOne.bar = [ world ]; 258 }; 259 }; ··· 275 flake.aspects = 276 { aspects, ... }: 277 { 278 - aspectOne.includes = [ (aspects.aspectTwo "hello") ]; 279 aspectOne.classOne = { }; # required for propagation 280 281 aspectTwo.__functor = 282 - _: message: 283 { class, aspect-chain }: 284 { aspect, ... }: 285 {
··· 246 flake.aspects = 247 { aspects, ... }: 248 { 249 + aspectOne.includes = [ (aspects.aspectTwo.provides.hello { world = "mundo"; }) ]; 250 aspectOne.classOne.bar = [ "1" ]; 251 252 aspectTwo.provides.hello = 253 + { world }: # args must always be named. 254 + _: { 255 classOne.bar = [ world ]; 256 }; 257 }; ··· 273 flake.aspects = 274 { aspects, ... }: 275 { 276 + aspectOne.includes = [ (aspects.aspectTwo { message = "hello"; }) ]; 277 aspectOne.classOne = { }; # required for propagation 278 279 aspectTwo.__functor = 280 + _: 281 + { message }: # args must be always named 282 { class, aspect-chain }: 283 { aspect, ... }: 284 {
+20 -5
nix/types.nix
··· 2 let 3 4 aspectsType = lib.types.submodule { 5 - freeformType = lib.types.lazyAttrsOf aspectSubmodule; 6 }; 7 8 - providerType = lib.types.functionTo aspectSubmodule; 9 10 aspectSubmodule = aspectSubmoduleWithModules [ ]; 11 ··· 22 ... 23 }: 24 { 25 - freeformType = lib.types.lazyAttrsOf lib.types.deferredModule; 26 config._module.args.aspect = config; 27 options.name = lib.mkOption { 28 description = "Aspect name"; ··· 45 type = lib.types.submodule ( 46 { config, ... }: 47 { 48 - freeformType = lib.types.lazyAttrsOf (lib.types.functionTo lib.types.unspecified); 49 config._module.args.provides = config; 50 options.itself = lib.mkOption { 51 readOnly = true; ··· 60 internal = true; 61 visible = false; 62 description = "Functor to default provider"; 63 - type = lib.types.functionTo lib.types.unspecified; 64 default = _: aspect.provides.itself; 65 }; 66 }
··· 2 let 3 4 aspectsType = lib.types.submodule { 5 + freeformType = lib.types.attrsOf aspectSubmodule; 6 }; 7 8 + functionToAspect = lib.types.addCheck (lib.types.functionTo aspectSubmodule) ( 9 + f: 10 + let 11 + args = lib.functionArgs f; 12 + arity = lib.length (lib.attrNames args); 13 + isEmpty = arity == 0; 14 + hasClass = args ? class; 15 + hasChain = args ? aspect-chain; 16 + classOnly = hasClass && arity == 1; 17 + chainOnly = hasChain && arity == 1; 18 + both = hasClass && hasChain && arity == 2; 19 + in 20 + isEmpty || classOnly || chainOnly || both 21 + ); 22 + 23 + providerType = lib.types.either functionToAspect (lib.types.functionTo providerType); 24 25 aspectSubmodule = aspectSubmoduleWithModules [ ]; 26 ··· 37 ... 38 }: 39 { 40 + freeformType = lib.types.attrsOf lib.types.deferredModule; 41 config._module.args.aspect = config; 42 options.name = lib.mkOption { 43 description = "Aspect name"; ··· 60 type = lib.types.submodule ( 61 { config, ... }: 62 { 63 + freeformType = lib.types.attrsOf providerType; 64 config._module.args.provides = config; 65 options.itself = lib.mkOption { 66 readOnly = true; ··· 75 internal = true; 76 visible = false; 77 description = "Functor to default provider"; 78 + type = lib.types.functionTo providerType; 79 default = _: aspect.provides.itself; 80 }; 81 }