-
Notifications
You must be signed in to change notification settings - Fork 25
/
modules.nix
74 lines (62 loc) · 2.44 KB
/
modules.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# module related operations
{ lib
, callPackage
, runCommand
, glibcLocales
, haskellPackages
}:
with (callPackage ./files.nix {});
rec {
# Turns a module name to a file
moduleToFile = mod:
(lib.strings.replaceChars ["."] ["/"] mod) + ".hs";
# Turns a module name into the filepath of its object file
# TODO: bad name, this is module _name_ to object
moduleToObject = mod:
(lib.strings.replaceChars ["."] ["/"] mod) + ".o";
# Turns a filepath name to a module name
fileToModule = file:
lib.strings.removeSuffix ".hs"
(lib.strings.replaceChars ["/"] ["."] file);
# Singles out a given module (by module name) (derivation)
singleOutModule = base: mod: singleOut base (moduleToFile mod);
# Singles out a given module (by module name) (path to module file)
singleOutModulePath = base: mod:
"${singleOut base (moduleToFile mod)}/${moduleToFile mod}";
# Generate a list of haskell module names needed by the haskell file
listModuleImports = baseByModuleName: extsByModuleName: modName:
builtins.fromJSON
(builtins.readFile (listAllModuleImportsJSON baseByModuleName extsByModuleName modName))
;
# Whether the file is a Haskell module or not. It uses very simple
# heuristics: If the file starts with a capital letter, then yes.
isHaskellModuleFile = f:
! (builtins.isNull (builtins.match "[a-zA-Z].*[.]hs$" (builtins.baseNameOf f)));
listModulesInDir = dir:
map fileToModule
(lib.filter isHaskellModuleFile
(listFilesInDir dir));
doesModuleExist = baseByModuleName: modName:
doesFileExist (baseByModuleName modName) (moduleToFile modName);
# Lists all module dependencies, not limited to modules existing in this
# project
listAllModuleImportsJSON = baseByModuleName: extsByModuleName: modName:
let
base = baseByModuleName modName;
modExts =
lib.strings.escapeShellArgs
(map (x: "-X${x}") (extsByModuleName modName));
ghc = haskellPackages.ghcWithPackages (ps: [ ps.ghc ]);
importParser = runCommand "import-parser"
{ buildInputs = [ ghc ];
} "ghc -Wall -Werror -package ghc ${./Imports.hs} -o $out" ;
# XXX: this command needs ghc in the environment so that it can call "ghc
# --print-libdir"...
in runCommand "dependencies-json"
{ buildInputs = [ ghc glibcLocales ];
LANG="en_US.utf-8";
}
''
${importParser} ${singleOutModulePath base modName} ${modExts} > $out
'';
}