diff --git a/nib/parse/default.nix b/nib/parse/default.nix new file mode 100644 index 0000000..41d6241 --- /dev/null +++ b/nib/parse/default.nix @@ -0,0 +1,13 @@ +{ + attrs, + result, +}: let + struct = import ./struct.nix {inherit attrs result;}; +in + builtins.listToAttrs [ + # submodule is included directly to this module (ie self.myFunc) + struct + + # submodule content is accessible first by submodule name + # then by the name of the content (ie self.submodule.myFunc) + ] diff --git a/nib/parse/struct.nix b/nib/parse/struct.nix new file mode 100644 index 0000000..3424033 --- /dev/null +++ b/nib/parse/struct.nix @@ -0,0 +1,82 @@ +{ + attrs, + result, +}: rec { + cmpStructErr' = errBadKeys: errBadValues: path: S: T: + if builtins.isAttrs S && builtins.isAttrSet T + then let + keysS = builtins.attrNames S; + keysT = builtins.attrNames T; + in + # ensure all key names match, then recurse + if !(keysS == keysT) + then errBadKeys path keysS keysT + else + (result.firstErr + (builtins.map + (k: cmpStructErr' errBadKeys errBadValues (path ++ [k]) (keysS.${k}) (keysT.${k})) + keysS)) + else + # terminating leaf in recursion tree reached + # ensure values' types match + (builtins.typeOf S == builtins.typeOf T) + || errBadValues path S T; + + cmpStructErr = errBadKeys: errBadValues: cmpStructErr' errBadKeys errBadValues []; + + cmpStruct = + cmpStructErr + (path: keysS: keysT: + result.Err { + reason = "keys"; + inherit path; + }) + (path: S: T: + result.Ok "ok"); + + cmpTypedStruct = + cmpStructErr + (path: keysS: keysT: + result.Err { + reason = "keys"; + inherit path; + }) + (path: S: T: + result.Err { + reason = "values"; + inherit path; + }); + + # check is a function taking two structs + # and returning a result monad. + mergeStruct' = check: template: S: let + res = check template S; + in + result.errOr res ({...}: + attrs.mapAttrsRecursive ( + path: value: let + valueS = attrs.attrValueAt S path; + in + if valueS != null + then valueS + else value + ) + template); + + mergeStruct = mergeStruct' (S: T: result.Ok "ok"); + + mergeTypedStruct = mergeStruct' ( + cmpStructErr + (path: keysS: keysT: + result.Ok "ok") + (path: S: T: + result.Err { + reason = "values"; + inherit path; + }) + ); + + mergeStructStrict = mergeStruct' cmpStruct; + + mergeTypedStructStrict = mergeStruct' cmpTypedStruct; +}