gen_docu: fix missing attributes, show generation time at the end
[libfirm] / scripts / gen_docu.py
1 #!/usr/bin/env python
2 import sys
3 import re
4 import docutils.core
5 import docutils.writers.html4css1
6 from datetime import datetime
7 from jinja2 import Environment, Template
8 from jinja2.filters import do_dictsort
9 from spec_util import is_dynamic_pinned, verify_node, isAbstract, setdefault
10 from ir_spec import nodes
11
12 def trim(docstring):
13     if not docstring:
14         return ''
15     # Convert tabs to spaces (following the normal Python rules)
16     # and split into a list of lines:
17     lines = docstring.expandtabs().splitlines()
18     # Determine minimum indentation (first line doesn't count):
19     indent = sys.maxint
20     for line in lines[1:]:
21         stripped = line.lstrip()
22         if stripped:
23             indent = min(indent, len(line) - len(stripped))
24     # Remove indentation (first line is special):
25     trimmed = [lines[0].strip()]
26     if indent < sys.maxint:
27         for line in lines[1:]:
28             trimmed.append(line[indent:].rstrip())
29     # Strip off trailing and leading blank lines:
30     while trimmed and not trimmed[-1]:
31         trimmed.pop()
32     while trimmed and not trimmed[0]:
33         trimmed.pop(0)
34     # Return a single string:
35     return '\n'.join(trimmed)
36
37 def format_docutils(string):
38         writer = docutils.writers.html4css1.Writer()
39         document = docutils.core.publish_parts(string, writer=writer)['body']
40         return document
41
42 env = Environment()
43 env.filters['docutils'] = format_docutils
44
45 docu_template = env.from_string(
46 '''<html>
47         <head>
48                 <title>libFirm node specifications</title>
49                 <link rel='stylesheet' type='text/css' href='style.css'/>
50         </head>
51         <body>
52                 <div class="document">
53                 <div class="documentwrapper">
54                         <div class="bodywrapper"><div class="body">
55                                 <h1>Firm Node Types</h1>
56                                 {% for node in nodes %}
57                                 <div class="section" id="{{node.name}}">
58                                         <h3>{{node.name}}</h3>
59                                         {{node.doc|docutils}}
60                                         <h5>Inputs</h5>
61                                         <dl>
62                                         {% for input in node.ins %}
63                                                 <dt>{{input[0]}}</dt><dd>{{input[1]}}</dd>
64                                         {% endfor %}
65                                         {% if node.arity == "variable" %}
66                                                 <dt>...</dt><dd>additional inputs (oparity_variable)</dd>
67                                         {% elif node.arity == "dynamic" %}
68                                                 <dt>...</dt><dd>inputs dynamically mananged (oparity_dynamic)</dd>
69                                         {% endif %}
70                                         </dl>
71                                         {% if node.outs %}
72                                         <h5>Outputs</h5>
73                                         <dl>
74                                         {% for output in node.outs %}
75                                                 <dt>{{output[0]}}</dt><dd>{{output[1]}}</dd>
76                                         {% endfor %}
77                                         </dl>
78                                         {% endif %}
79                                         {% if node.attrs %}
80                                         <h5>Attributes</h5>
81                                         <dl>
82                                         {% for attr in node.attrs %}
83                                                 <dt>{{attr.name}}</dt><dd>{{attr.comment}} ({{attr.type}})</dd>
84                                         {% endfor %}
85                                         {% endif %}
86                                         </dl>
87                                         <h5>Flags</h5>
88                                         {% for flag in node.flags %} {{flag}} {% endfor %}
89                                 </div>
90                                 {% endfor %}
91                         </div></div>
92                 </div>
93                 <div class="sidebar">
94                         <div class="sidebarwrapper">
95                                 <h3>Table Of Contents</h3>
96                                 <ul>
97                                         <li><a href="#">Firm Node Types</a>
98                                         <ul>
99                                                 {% for node in nodes %}
100                                                 <li><a href="#{{node.name}}">{{node.name}}</a></li>
101                                                 {% endfor %}
102                                         </ul>
103                                         </li>
104                         </div>
105                 </div>
106                 </div>
107                 <div class="footer">
108                         Generated {{time}}
109                 </div>
110         </body>
111 </html>
112 ''')
113
114 #############################
115
116 def preprocess_node(node):
117         node.doc = trim(node.__doc__)
118
119 def prepare_nodes():
120         real_nodes = []
121         for node in nodes:
122                 preprocess_node(node)
123                 if isAbstract(node):
124                         continue
125                 real_nodes.append(node)
126
127         return real_nodes
128
129 def main(argv):
130         real_nodes = prepare_nodes()
131         time = datetime.now().replace(microsecond=0).isoformat(' ')
132         sys.stdout.write(docu_template.render(nodes = real_nodes, time=time))
133
134 main(sys.argv)