From 13735a63b4dd11c4a10a4102f8f67cfccc4a9d8c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 26 Aug 2020 09:44:12 +0200 Subject: [PATCH] Add poor man's module system --- corepkgs/local.mk | 3 ++- corepkgs/module.nix | 46 ++++++++++++++++++++++++++++++++++++++++++ src/libexpr/primops.cc | 4 ++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 corepkgs/module.nix diff --git a/corepkgs/local.mk b/corepkgs/local.mk index 2c72d3a31..91dfd30cd 100644 --- a/corepkgs/local.mk +++ b/corepkgs/local.mk @@ -1,7 +1,8 @@ corepkgs_FILES = \ unpack-channel.nix \ derivation.nix \ - fetchurl.nix + fetchurl.nix \ + module.nix $(foreach file,config.nix $(corepkgs_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/corepkgs))) diff --git a/corepkgs/module.nix b/corepkgs/module.nix new file mode 100644 index 000000000..0abff42df --- /dev/null +++ b/corepkgs/module.nix @@ -0,0 +1,46 @@ +let + + showPos = pos: + if pos == null + then "" + else "${pos.file}:${toString pos.line}:${toString pos.column}"; + + getAnyPos = attrs: + builtins.foldl' (prev: name: if prev == null then builtins.unsafeGetAttrPos name attrs else prev) null (builtins.attrNames attrs); + +in + +{ description ? null, extends ? [], options ? {}, config ? ({ config }: {}) } @ inArgs: + +let thisModule = rec { + type = "module"; + + _module = { + inherit description extends options config; + }; + + _allModules = [thisModule] ++ builtins.concatLists (map (mod: assert mod.type or "" == "module"; mod._allModules) extends); + + _allOptions = builtins.foldl' (xs: mod: xs // mod._module.options) {} _allModules; + + _allConfigs = map (mod: mod._module.config { config = final; }) _allModules; + + _allDefinitions = builtins.mapAttrs (name: value: map (x: x) (builtins.catAttrs name _allConfigs)) _allOptions; + + final = builtins.mapAttrs + (name: defs: + if defs == [] + then + _allOptions.${name}.default + or (throw "Option '${name}' is not defined by module at ${showPos (getAnyPos inArgs)} and has no default value.") + else + # FIXME: support merge functions. + if builtins.isList (builtins.head defs) + then builtins.concatLists defs + else + if builtins.isAttrs (builtins.head defs) + then builtins.foldl' (xs: ys: xs // ys) {} defs + else builtins.head defs) + _allDefinitions; + +}; in thisModule diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 65d36ca0e..525828186 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2416,6 +2416,10 @@ void EvalState::createBaseEnv() evalFile(path, v); addConstant("derivation", v); + path = canonPath(settings.nixDataDir + "/nix/corepkgs/module.nix", true); + evalFile(path, v); + addConstant("module", v); + /* Add a value containing the current Nix expression search path. */ mkList(v, searchPath.size()); int n = 0;