mirror of
https://github.com/nmattia/snack.git
synced 2024-11-24 12:16:17 +03:00
133 lines
3.8 KiB
Nix
133 lines
3.8 KiB
Nix
# Functions related to module specs
|
|
{ lib
|
|
, callPackage
|
|
}:
|
|
|
|
with (callPackage ./modules.nix {});
|
|
with (callPackage ./package-spec.nix {});
|
|
with (callPackage ./lib.nix {});
|
|
|
|
rec {
|
|
makeModuleSpec =
|
|
modName:
|
|
modImports:
|
|
modFiles:
|
|
modDirs:
|
|
modBase:
|
|
modDeps:
|
|
modExts:
|
|
modGhcOpts:
|
|
{ moduleName = modName;
|
|
|
|
# local module imports, i.e. not part of an external dependency
|
|
moduleImports = modImports;
|
|
|
|
moduleFiles = modFiles;
|
|
moduleDirectories = modDirs;
|
|
moduleBase = modBase;
|
|
moduleDependencies =
|
|
if builtins.isList modDeps
|
|
then modDeps
|
|
else abort "module dependencies should be a list";
|
|
moduleGhcOpts = modGhcOpts;
|
|
moduleExtensions = modExts;
|
|
};
|
|
|
|
|
|
moduleSpecFold =
|
|
{ baseByModuleName
|
|
, filesByModuleName
|
|
, dirsByModuleName
|
|
, depsByModuleName
|
|
, extsByModuleName
|
|
, ghcOptsByModuleName
|
|
}:
|
|
result:
|
|
let
|
|
modImportsNames = modName:
|
|
lib.lists.filter
|
|
(modName': ! builtins.isNull (baseByModuleName modName'))
|
|
(listModuleImports baseByModuleName extsByModuleName modName);
|
|
in
|
|
# TODO: DFS instead of Fold
|
|
{ f = modName:
|
|
{ "${modName}" =
|
|
makeModuleSpec
|
|
modName
|
|
(map (mn: result.${mn}) (modImportsNames modName))
|
|
(filesByModuleName modName)
|
|
(dirsByModuleName modName)
|
|
(baseByModuleName modName)
|
|
(depsByModuleName modName)
|
|
(extsByModuleName modName)
|
|
(ghcOptsByModuleName modName);
|
|
};
|
|
empty = {} ;
|
|
reduce = a: b: a // b;
|
|
elemLabel = lib.id;
|
|
elemChildren = modImportsNames;
|
|
};
|
|
|
|
# Returns a list of all modules in the module spec graph
|
|
flattenModuleSpec = modSpec:
|
|
[ modSpec ] ++
|
|
( lib.lists.concatMap flattenModuleSpec modSpec.moduleImports );
|
|
|
|
allTransitiveDeps = allTransitiveLists "moduleDependencies";
|
|
allTransitiveGhcOpts = allTransitiveLists "moduleGhcOpts";
|
|
allTransitiveExtensions = allTransitiveLists "moduleExtensions";
|
|
allTransitiveDirectories = allTransitiveLists "moduleDirectories";
|
|
allTransitiveImports = allTransitiveLists "moduleImports";
|
|
|
|
allTransitiveLists = attr: modSpecs:
|
|
lib.lists.unique
|
|
(
|
|
foldDAG
|
|
{ f = modSpec:
|
|
lib.lists.foldl
|
|
(x: y: x ++ [y])
|
|
[] modSpec.${attr};
|
|
empty = [];
|
|
elemLabel = modSpec: modSpec.moduleName;
|
|
reduce = a: b: a ++ b;
|
|
elemChildren = modSpec: modSpec.moduleImports;
|
|
}
|
|
modSpecs
|
|
)
|
|
;
|
|
|
|
# Takes a package spec and returns (modSpecs -> Fold)
|
|
modSpecFoldFromPackageSpec = pkgSpec:
|
|
let
|
|
baseByModuleName = modName:
|
|
let res = pkgSpecAndBaseByModuleName pkgSpec modName;
|
|
in if res == null then null else res.base;
|
|
depsByModuleName = modName:
|
|
(pkgSpecByModuleName
|
|
pkgSpec
|
|
(abort "asking dependencies for external module: ${modName}")
|
|
modName).packageDependencies
|
|
modName
|
|
;
|
|
extsByModuleName = modName:
|
|
(pkgSpecByModuleName
|
|
pkgSpec
|
|
(abort "asking extensions for external module: ${modName}")
|
|
modName).packageExtensions;
|
|
ghcOptsByModuleName = modName:
|
|
(pkgSpecByModuleName
|
|
pkgSpec
|
|
(abort "asking ghc options for external module: ${modName}")
|
|
modName).packageGhcOpts;
|
|
in
|
|
moduleSpecFold
|
|
{ baseByModuleName = baseByModuleName;
|
|
filesByModuleName = pkgSpec.packageExtraFiles;
|
|
dirsByModuleName = pkgSpec.packageExtraDirectories;
|
|
depsByModuleName = depsByModuleName;
|
|
extsByModuleName = extsByModuleName;
|
|
ghcOptsByModuleName = ghcOptsByModuleName;
|
|
};
|
|
|
|
}
|