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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
//
//
// The Nimrod Compiler
// (c) Copyright 2009 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit depends;
// This module implements a dependency file generator.
interface
{$include 'config.inc'}
uses
nsystem, nos, options, ast, astalgo, msgs, ropes, idents, passes, importer;
function genDependPass(): TPass;
procedure generateDot(const project: string);
implementation
type
TGen = object(TPassContext)
module: PSym;
filename: string;
end;
PGen = ^TGen;
var
gDotGraph: PRope; // the generated DOT file; we need a global variable
procedure addDependencyAux(const importing, imported: string);
begin
appf(gDotGraph, '$1 -> $2;$n', [toRope(importing),
toRope(imported)]);
// s1 -> s2_4 [label="[0-9]"];
end;
function addDotDependency(c: PPassContext; n: PNode): PNode;
var
i: int;
g: PGen;
imported: string;
begin
result := n;
if n = nil then exit;
g := PGen(c);
case n.kind of
nkImportStmt: begin
for i := 0 to sonsLen(n)-1 do begin
imported := splitFile(getModuleFile(n.sons[i])).name;
addDependencyAux(g.module.name.s, imported);
end
end;
nkFromStmt: begin
imported := splitFile(getModuleFile(n.sons[0])).name;
addDependencyAux(g.module.name.s, imported);
end;
nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: begin
for i := 0 to sonsLen(n)-1 do {@discard} addDotDependency(c, n.sons[i]);
end
else begin end
end
end;
procedure generateDot(const project: string);
begin
writeRope(
ropef('digraph $1 {$n$2}$n', [
toRope(changeFileExt(extractFileName(project), '')), gDotGraph]),
changeFileExt(project, 'dot') );
end;
function myOpen(module: PSym; const filename: string): PPassContext;
var
g: PGen;
begin
new(g);
{@ignore}
fillChar(g^, sizeof(g^), 0);
{@emit}
g.module := module;
g.filename := filename;
result := g;
end;
function gendependPass(): TPass;
begin
initPass(result);
result.open := myOpen;
result.process := addDotDependency;
end;
end.
|