summary refs log tree commit diff stats
path: root/nim/depends.pas
blob: 6711875fe81bcdc48a4a19d24b75dee1c8c7c588 (plain) (blame)
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.