debugger: add randnode debug command
[libfirm] / scripts / spec_util.py
1 import sys
2
3 abstracts = set()
4 def abstract(cls):
5         abstracts.add(cls)
6         return cls
7 def isAbstract(nodetype):
8         return nodetype in abstracts
9
10 def is_dynamic_pinned(node):
11         return node.pinned in ["memory", "exception"]
12
13 def is_fragile(node):
14         return hasattr(node, "flags") and "fragile" in node.flags
15
16 def inout_contains(l, name):
17         for entry in l:
18                 if entry[0] == name:
19                         return True
20         return False
21
22 def verify_node(node):
23         if not hasattr(node, "pinned"):
24                 print "%s: NO PINNED SET" % node.__name__
25         elif node.pinned not in ["yes", "no", "memory", "exception"]:
26                 print "%s: UNKNOWN PINNED MODE: %s" % (node.__name__, node.pinned)
27
28         if not hasattr(node, "flags") and not isAbstract(node):
29                 print "WARNING: no flags specified for %s\n" % node.__name__
30         elif type(node.flags) != list:
31                 print "ERROR: flags of %s not a list" % node.__name__
32         if hasattr(node, "pinned_init") and not is_dynamic_pinned(node):
33                 print "ERROR: node %s has pinned_init attribute but is not marked as dynamically pinned" % node.__name__
34         if hasattr(node, "flags") and "uses_memory" in node.flags:
35                 if not inout_contains(node.ins, "mem"):
36                         print "ERROR: memory op %s needs an input named 'mem'" % node.__name__
37         if is_fragile(node):
38                 if not is_dynamic_pinned(node):
39                         print "ERROR: fragile node %s must be dynamically pinned" % node.__name__
40                 if not hasattr(node, "throws_init"):
41                         print "ERROR: fragile node %s needs a throws_init attribute" % node.__name__
42                 if not inout_contains(node.outs, "X_regular"):
43                         print "ERROR: fragile node %s needs an output named 'X_regular'" % node.__name__
44                 if not inout_contains(node.outs, "X_except"):
45                         print "ERROR: fragile node %s needs an output named 'X_except'" % node.__name__
46         else:
47                 if hasattr(node, "throws_init"):
48                         print "ERROR: throws_init only makes sense for fragile nodes"
49
50
51 def setldefault(node, attr, val):
52         # Don't use hasattr, as these things should not be inherited
53         if attr not in node.__dict__:
54                 setattr(node, attr, val)
55
56 def setdefault(node, attr, val):
57         # Don't use hasattr, as these things should not be inherited
58         if not hasattr(node, attr):
59                 setattr(node, attr, val)
60
61 def setnodedefaults(node):
62         setldefault(node, "name", node.__name__)
63         if isAbstract(node):
64                 return
65
66         setdefault(node, "ins", [])
67         setdefault(node, "arity", len(node.ins))
68         setdefault(node, "attrs", [])
69         setdefault(node, "constructor_args", [])
70         setdefault(node, "customSerializer", False)
71         if hasattr(node, "outs"):
72                 node.mode = "mode_T"
73
74 def trim_docstring(docstring):
75     if not docstring:
76         return ''
77     # Convert tabs to spaces (following the normal Python rules)
78     # and split into a list of lines:
79     lines = docstring.expandtabs().splitlines()
80     # Determine minimum indentation (first line doesn't count):
81     indent = sys.maxint
82     for line in lines[1:]:
83         stripped = line.lstrip()
84         if stripped:
85             indent = min(indent, len(line) - len(stripped))
86     # Remove indentation (first line is special):
87     trimmed = [lines[0].strip()]
88     if indent < sys.maxint:
89         for line in lines[1:]:
90             trimmed.append(line[indent:].rstrip())
91     # Strip off trailing and leading blank lines:
92     while trimmed and not trimmed[-1]:
93         trimmed.pop()
94     while trimmed and not trimmed[0]:
95         trimmed.pop(0)
96     # Return a single string:
97     return '\n'.join(trimmed)