a first attempt at a node-documentation tool
authorMatthias Braun <matze@braunis.de>
Thu, 10 Nov 2011 17:40:35 +0000 (18:40 +0100)
committerMatthias Braun <matze@braunis.de>
Thu, 10 Nov 2011 17:42:06 +0000 (18:42 +0100)
scripts/gen_docu.py [new file with mode: 0755]
scripts/ir_spec.py
scripts/style.css [new file with mode: 0644]

diff --git a/scripts/gen_docu.py b/scripts/gen_docu.py
new file mode 100755 (executable)
index 0000000..cd142cc
--- /dev/null
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+import sys
+import re
+import docutils.core
+import docutils.writers.html4css1
+from subprocess import Popen, PIPE
+from jinja2 import Environment, Template
+from jinja2.filters import do_dictsort
+from spec_util import is_dynamic_pinned, verify_node, isAbstract, setdefault
+from ir_spec import nodes
+
+def trim(docstring):
+    if not docstring:
+        return ''
+    # Convert tabs to spaces (following the normal Python rules)
+    # and split into a list of lines:
+    lines = docstring.expandtabs().splitlines()
+    # Determine minimum indentation (first line doesn't count):
+    indent = sys.maxint
+    for line in lines[1:]:
+        stripped = line.lstrip()
+        if stripped:
+            indent = min(indent, len(line) - len(stripped))
+    # Remove indentation (first line is special):
+    trimmed = [lines[0].strip()]
+    if indent < sys.maxint:
+        for line in lines[1:]:
+            trimmed.append(line[indent:].rstrip())
+    # Strip off trailing and leading blank lines:
+    while trimmed and not trimmed[-1]:
+        trimmed.pop()
+    while trimmed and not trimmed[0]:
+        trimmed.pop(0)
+    # Return a single string:
+    return '\n'.join(trimmed)
+
+def format_docutils(string):
+       writer = docutils.writers.html4css1.Writer()
+       document = docutils.core.publish_parts(string, writer=writer)['body']
+       return document
+
+env = Environment()
+env.filters['docutils'] = format_docutils
+
+docu_template = env.from_string(
+'''<html>
+       <head>
+               <title>libFirm node specifications</title>
+               <link rel='stylesheet' type='text/css' href='style.css'/>
+       </head>
+       <body>
+               <div class="document">
+               <div class="documentwrapper">
+                       <div class="bodywrapper"><div class="body">
+                               <h1>Firm Node Types</h1>
+                               {% for node in nodes %}
+                               <div class="section" id="{{node.name}}">
+                                       <h3>{{node.name}}</h3>
+                                       {{node.doc|docutils}}
+                                       <h5>Inputs</h5>
+                                       <dl>
+                                       {% for input in node.ins %}
+                                               <dt>{{input[0]}}</dt><dd>{{input[1]}}</dd>
+                                       {% endfor %}
+                                       {% if node.arity == "variable" %}
+                                               <dt>...</dt><dd>additional inputs (oparity_variable)</dd>
+                                       {% elif node.arity == "dynamic" %}
+                                               <dt>...</dt><dd>inputs dynamically mananged (oparity_dynamic)</dd>
+                                       {% endif %}
+                                       </dl>
+                                       {% if node.outs %}
+                                       <h5>Outputs</h5>
+                                       <dl>
+                                       {% for output in node.outs %}
+                                               <dt>{{output[0]}}</dt><dd>{{output[1]}}</dd>
+                                       {% endfor %}
+                                       </dl>
+                                       {% endif %}
+                                       {% if node.attributes %}
+                                       <h5>Attributes</h5>
+                                       <dl>
+                                       {% for attr in node.attrs %}
+                                               <dt>{{attr.name}}</dt><dd>{{attr.comment}} ({{attr.type}})</dd>
+                                       {% endfor %}
+                                       {% endif %}
+                                       </dl>
+                                       <h5>Flags</h5>
+                                       {% for flag in node.flags %} {{flag}} {% endfor %}
+                               </div>
+                               {% endfor %}
+                       </div></div>
+               </div>
+               <div class="sidebar">
+                       <div class="sidebarwrapper">
+                               <h3>Table Of Contents</h3>
+                               <ul>
+                                       <li><a href="#">Firm Node Types</a>
+                                       <ul>
+                                               {% for node in nodes %}
+                                               <li><a href="#{{node.name}}">{{node.name}}</a></li>
+                                               {% endfor %}
+                                       </ul>
+                                       </li>
+                       </div>
+               </div>
+               </div>
+       </body>
+</html>
+''')
+
+#############################
+
+def preprocess_node(node):
+       node.doc = trim(node.__doc__)
+
+def prepare_nodes():
+       real_nodes = []
+       for node in nodes:
+               preprocess_node(node)
+               if isAbstract(node):
+                       continue
+               real_nodes.append(node)
+
+       return real_nodes
+
+def main(argv):
+       real_nodes = prepare_nodes()
+       sys.stdout.write(docu_template.render(nodes = real_nodes))
+
+main(sys.argv)
index 061f1f1..c82d236 100755 (executable)
@@ -316,11 +316,7 @@ class Cmp(Binop):
        attr_struct = "cmp_attr"
 
 class Cond(Op):
-       """Conditionally change control flow.
-       Input:  A value of mode_b
-       Output: A tuple of two control flows. The first is taken if the input is
-               false, the second if it is true.
-       """
+       """Conditionally change control flow."""
        ins      = [
                ("selector",  "condition parameter"),
        ]
@@ -632,6 +628,7 @@ class Mod(Op):
        """returns the remainder of its operands from an implied division.
 
        Examples:
+
        * mod(5,3)   produces 2
        * mod(5,-3)  produces 2
        * mod(-5,3)  produces -2
@@ -878,21 +875,21 @@ class Sub(Binop):
 class SymConst(Op):
        """A symbolic constant.
 
-        - symconst_type_tag   The symbolic constant represents a type tag.  The
-                              type the tag stands for is given explicitly.
-        - symconst_type_size  The symbolic constant represents the size of a type.
-                              The type of which the constant represents the size
-                              is given explicitly.
-        - symconst_type_align The symbolic constant represents the alignment of a
-                              type.  The type of which the constant represents the
-                              size is given explicitly.
-        - symconst_addr_ent   The symbolic constant represents the address of an
-                              entity (variable or method).  The variable is given
-                              explicitly by a firm entity.
-        - symconst_ofs_ent    The symbolic constant represents the offset of an
-                              entity in its owner type.
-        - symconst_enum_const The symbolic constant is a enumeration constant of
-                              an enumeration type."""
+        - *symconst_type_tag*  The symbolic constant represents a type tag.  The
+                               type the tag stands for is given explicitly.
+        - *symconst_type_size* The symbolic constant represents the size of a type.
+                               The type of which the constant represents the size
+                               is given explicitly.
+        - *symconst_type_align* The symbolic constant represents the alignment of a
+                               type.  The type of which the constant represents the
+                               size is given explicitly.
+        - *symconst_addr_ent*  The symbolic constant represents the address of an
+                               entity (variable or method).  The variable is given
+                               explicitly by a firm entity.
+        - *symconst_ofs_ent*   The symbolic constant represents the offset of an
+                               entity in its owner type.
+        - *symconst_enum_const* The symbolic constant is a enumeration constant of
+                               an enumeration type."""
        mode       = "mode_P"
        flags      = [ "constlike", "start_block" ]
        knownBlock = True
diff --git a/scripts/style.css b/scripts/style.css
new file mode 100644 (file)
index 0000000..24ba055
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * documentation formatting (heavily inspired by jinja.css)
+ */
+body {
+       font-family: Georgia, serif;
+       font-size: 17px;
+       background-color: white;
+       color: #000;
+       margin: 0;
+       padding: 0;
+}
+
+div.body {
+       background-color: #ffffff;
+       color: #3E4349;
+       padding: 0 30px 0 30px;
+}
+
+div.document {
+       width: 940px;
+       margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+       float: left;
+       width: 100%;
+}
+
+div.bodywrapper {
+       margin: 0 0 0 220px;
+}
+
+div.sidebar {
+       width: 220px;
+}
+
+div.sidebarwrapper {
+       padding: 10px 5px 0 10px;
+}
+
+div.sidebar {
+       float: left;
+       width: 230px;
+       margin-left: -100%;
+       font-size: 90%;
+}
+
+div.sidebar ul {
+       list-style: none;
+}
+
+div.sidebar ul ul,
+div.sidebar ul.want-points {
+       margin-left: 20px;
+       list-style: square;
+}
+
+div.sidebar ul ul {
+       margin-top: 0;
+       margin-bottom: 0;
+}
+
+div.sidebar form {
+       margin-top: 10px;
+}
+
+div.sidebar input {
+       border: 1px solid #98dbcc;
+       font-family: sans-serif;
+       font-size: 1em;
+}
+
+a {
+       color: #aa0000;
+       text-decoration: underline;
+}
+
+a:hover {
+       color: #dd0000;
+       text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+       font-family: Crimson Text, Georgia, serif;
+       font-weight: normal;
+       margin: 30px 0px 10px 0px;
+       padding: 0;
+       color: black;
+}
+
+div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
+div.body h2 { font-size: 180%; }
+div.body h3 { font-size: 150%; }
+div.body h4 { font-size: 130%; }
+div.body h5 { font-size: 100%; }
+div.body h6 { font-size: 100%; }
+
+div.body p, div.body dd, div.body li {
+       line-height: 1.4em;
+}
+
+ul, ol {
+       margin: 10px 0 10px 30px;
+       padding: 0;
+}
+
+pre {
+       background: #eee;
+       padding: 7px 30px;
+       margin: 15px -30px;
+       line-height: 1.3em;
+}
+
+dl pre, blockquote pre, li pre {
+       margin-left: -60px;
+       padding-left: 60px;
+}
+
+dl dl pre {
+       margin-left: -90px;
+       padding-left: 90px;
+}
+
+tt {
+       background-color: #E8EFF0;
+       color: #222;
+       /* padding: 1px 2px; */
+}
+
+a.reference {
+       text-decoration: none;
+       border-bottom: 1px dotted #bb0000;
+}
+
+a.reference:hover {
+       border-bottom: 1px solid #dd0000;
+}
+
+a.footnote-reference {
+       text-decoration: none;
+       font-size: 0.7em;
+       vertical-align: top;
+       border-bottom: 1px dotted #bb0000;
+}
+
+a.footnote-reference:hover {
+       border-bottom: 1px solid #dd0000;
+}