simplify

Annotated simplified.py

26:41d4b988c94d
2006-07-24 paulb Introduced subprograms for If node bodies so that local merging may be more obvious to the annotator.
paul@0 1
#!/usr/bin/env python
paul@0 2
paul@0 3
"""
paul@0 4
Simplified AST nodes for easier type propagation and analysis.
paul@0 5
paul@0 6
Copyright (C) 2006 Paul Boddie <paul@boddie.org.uk>
paul@0 7
paul@0 8
This software is free software; you can redistribute it and/or
paul@0 9
modify it under the terms of the GNU General Public License as
paul@0 10
published by the Free Software Foundation; either version 2 of
paul@0 11
the License, or (at your option) any later version.
paul@0 12
paul@0 13
This software is distributed in the hope that it will be useful,
paul@0 14
but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@0 15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@0 16
GNU General Public License for more details.
paul@0 17
paul@0 18
You should have received a copy of the GNU General Public
paul@0 19
License along with this library; see the file LICENCE.txt
paul@0 20
If not, write to the Free Software Foundation, Inc.,
paul@0 21
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
paul@0 22
"""
paul@0 23
paulb@19 24
from compiler.visitor import ASTVisitor
paulb@19 25
paulb@24 26
# Elementary visitor support.
paulb@24 27
paulb@24 28
class Visitor(ASTVisitor):
paulb@24 29
paulb@24 30
    "A visitor base class."
paulb@24 31
paulb@24 32
    def __init__(self):
paulb@24 33
        ASTVisitor.__init__(self)
paulb@24 34
paulb@24 35
    def default(self, node, *args):
paulb@24 36
        raise ValueError, node.__class__
paulb@24 37
paulb@24 38
    def dispatch(self, node, *args):
paulb@24 39
        return ASTVisitor.dispatch(self, node, *args)
paulb@24 40
paulb@24 41
    def dispatches(self, nodes, *args):
paulb@24 42
        results = []
paulb@24 43
        for node in nodes:
paulb@24 44
            results.append(self.dispatch(node, *args))
paulb@24 45
        return results
paulb@24 46
paulb@24 47
# Simplified program nodes.
paulb@24 48
paul@0 49
class Node:
paul@0 50
paul@0 51
    """
paul@0 52
    A result node with common attributes:
paul@0 53
paul@0 54
    original    The original node from which this node was created.
paulb@16 55
    name        Any name involved (variable or attribute).
paulb@17 56
    index       Any index involved (temporary variable name).
paulb@17 57
    value       Any constant value.
paulb@17 58
    ref         Any reference to (for example) subprograms.
paulb@17 59
paulb@17 60
    Expression-related attributes:
paulb@17 61
paul@0 62
    expr        Any contributing expression.
paulb@16 63
    lvalue      Any target expression.
paulb@16 64
    test        Any test expression in a conditional instruction.
paulb@17 65
    handler     Any exception handler selector expression.
paulb@16 66
paulb@16 67
    Invocation and subprogram attributes:
paulb@16 68
paulb@16 69
    args        Any collection of argument nodes.
paulb@16 70
    params      Any collection of parameter nodes and defaults.
paulb@16 71
paulb@16 72
    Statement-grouping attributes:
paulb@16 73
paulb@16 74
    body        Any conditional code depending on the success of a test.
paulb@16 75
    else_       Any conditional code depending on the failure of a test.
paulb@16 76
    finally_    Any code which will be executed regardless.
paulb@16 77
    code        Any unconditional code.
paul@0 78
    """
paul@0 79
paul@0 80
    def __init__(self, original=None, **kw):
paul@0 81
        self.original = original
paulb@8 82
        if self.original is not None:
paulb@8 83
            self.original._node = self
paul@0 84
        for name, value in kw.items():
paul@0 85
            setattr(self, name, value)
paul@0 86
paul@0 87
    def __repr__(self):
paul@0 88
        if hasattr(self, "name"):
paul@0 89
            return "%s '%s' (at %x)" % (self.__class__, self.name, id(self))
paul@2 90
        if hasattr(self, "index"):
paulb@6 91
            return "%s (%s) (at %x)" % (self.__class__, self.index, id(self))
paul@0 92
        elif hasattr(self, "value"):
paul@0 93
            return "%s %s (at %x)" % (self.__class__, repr(self.value), id(self))
paul@0 94
        elif hasattr(self, "ref"):
paul@0 95
            return "%s '%s' (at %x)" % (self.__class__, self.ref.name, id(self))
paul@0 96
        else:
paul@0 97
            return "%s (at %x)" % (self.__class__, id(self))
paul@0 98
paul@0 99
    def _pprint(self, indent, continuation, s):
paul@0 100
        if continuation:
paul@0 101
            print (" " * max(0, indent - len(continuation))) + continuation + s
paul@0 102
        else:
paul@0 103
            print (" " * indent) + s
paul@0 104
paul@0 105
    def pprint(self, indent=0, continuation=None):
paul@0 106
        self._pprint(indent, continuation, repr(self))
paul@0 107
paul@0 108
        # Show other details.
paul@0 109
paul@0 110
        if hasattr(self, "params"):
paul@0 111
            for name, default in self.params:
paul@0 112
                self._pprint(indent + 2, "( ", "%s -> %s" % (name, default))
paulb@24 113
            if hasattr(self, "star") and self.star:
paulb@24 114
                name, default = self.star
paulb@24 115
                self._pprint(indent + 2, "( ", "%s -> %s" % (name, default))
paulb@24 116
            if hasattr(self, "dstar") and self.dstar:
paulb@24 117
                name, default = self.dstar
paulb@24 118
                self._pprint(indent + 2, "( ", "%s -> %s" % (name, default))
paul@0 119
        if getattr(self, "acquire_locals", 0):
paul@0 120
            self._pprint(indent + 2, "( ", "acquiring locals")
paulb@18 121
        if getattr(self, "structure", 0):
paulb@18 122
            self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name)
paul@0 123
        if hasattr(self, "test"):
paul@0 124
            self.test.pprint(indent + 2, "? ")
paulb@17 125
        for attr in "code", "body", "else_", "finally_":
paul@0 126
            if hasattr(self, attr) and getattr(self, attr):
paul@0 127
                self._pprint(indent, "", "{ (%s)" % attr)
paul@0 128
                for node in getattr(self, attr):
paul@0 129
                    node.pprint(indent + 2)
paul@0 130
                self._pprint(indent, "", "}")
paulb@17 131
        if hasattr(self, "handler"):
paulb@17 132
            self.handler.pprint(indent + 2, "! ")
paul@0 133
        if hasattr(self, "expr"):
paul@0 134
            self.expr.pprint(indent + 2, "- ")
paul@1 135
        if hasattr(self, "nodes"):
paul@1 136
            for node in self.nodes:
paul@1 137
                node.pprint(indent + 2, "- ")
paul@0 138
        if hasattr(self, "lvalue"):
paul@0 139
            self.lvalue.pprint(indent + 2, "= ")
paul@0 140
        if hasattr(self, "args"):
paul@0 141
            for arg in self.args:
paul@0 142
                arg.pprint(indent + 2, "( ")
paulb@24 143
            if hasattr(self, "star") and self.star:
paulb@24 144
                self.star.pprint(indent + 2, "( ")
paulb@24 145
            if hasattr(self, "dstar") and self.dstar:
paulb@24 146
                self.dstar.pprint(indent + 2, "( ")
paul@0 147
paul@0 148
class Module(Node): "A Python module."
paul@0 149
class Subprogram(Node): "A subprogram: functions, methods and loops."
paulb@24 150
class Constant(Node): "A constant."
paul@0 151
class Pass(Node): "A placeholder node corresponding to pass."
paul@0 152
class Invoke(Node): "A function, method or loop invocation."
paul@0 153
class Return(Node): "Return an evaluated expression."
paul@0 154
class Assign(Node): "A grouping node for assignment-related operations."
paul@0 155
class Keyword(Node): "A grouping node for keyword arguments."
paul@1 156
class Global(Node): "A global name designator."
paul@3 157
class Import(Node): "A module import operation."
paul@0 158
class LoadTemp(Node): "Load a previously-stored temporary value."
paul@0 159
class LoadName(Node): "Load a named object."
paulb@21 160
class LoadGlobal(Node): "Load a named global object."
paul@0 161
class LoadAttr(Node): "Load an object attribute."
paul@0 162
class LoadRef(Node): "Load a reference, typically a subprogram."
paul@0 163
class LoadExc(Node): "Load a handled exception."
paul@0 164
class StoreTemp(Node): "Store a temporary value."
paul@0 165
class StoreName(Node): "Associate a name with an object."
paulb@21 166
class StoreGlobal(Node): "Associate a name with an object in the global namespace."
paul@0 167
class StoreAttr(Node): "Associate an object's attribute with a value."
paul@0 168
class ReleaseTemp(Node): "Release a temporary value."
paul@0 169
class Conditional(Node): "A conditional node consisting of a test and outcomes."
paul@0 170
class Try(Node): "A try...except...else...finally grouping node."
paul@5 171
class Raise(Node): "An exception raising node."
paul@1 172
class Not(Node): "A negation of an expression."
paulb@24 173
class Class(Node): "A Python class."
paulb@19 174
paul@0 175
# vim: tabstop=4 expandtab shiftwidth=4