Lichen

Annotated tests/getattr_visitor.py

601:adcdaeb19307
2017-02-19 Paul Boddie Fixed the context test and set operation to replace the local context with any applicable attribute context. Added a test of method rebinding that requires this fix. method-wrapper-for-context
paul@488 1
class Expr:
paul@488 2
paul@488 3
    "An expression."
paul@488 4
paul@488 5
    def __init__(self, ops):
paul@488 6
        self.ops = ops
paul@488 7
paul@488 8
    def children(self):
paul@488 9
        return self.ops
paul@488 10
paul@488 11
class Binary:
paul@488 12
paul@488 13
    "A binary operator."
paul@488 14
paul@488 15
    def __init__(self, left, op, right):
paul@488 16
        self.left = left
paul@488 17
        self.op = op
paul@488 18
        self.right = right
paul@488 19
paul@488 20
    def children(self):
paul@488 21
        return self.left, self.right
paul@488 22
paul@488 23
class Unary:
paul@488 24
paul@488 25
    "A unary operator."
paul@488 26
paul@488 27
    def __init__(self, op, operand):
paul@488 28
        self.op = op
paul@488 29
        self.operand = operand
paul@488 30
paul@488 31
    def children(self):
paul@488 32
        return self.operand,
paul@488 33
paul@488 34
class Value:
paul@488 35
paul@488 36
    "A general value."
paul@488 37
paul@488 38
    def __init__(self, value):
paul@488 39
        self.value = value
paul@488 40
paul@488 41
    def children(self):
paul@488 42
        return ()
paul@488 43
paul@488 44
class Visitor:
paul@488 45
paul@488 46
    "Visit nodes in an expression tree."
paul@488 47
paul@488 48
    def __init__(self):
paul@488 49
        self.indent = 0
paul@488 50
paul@488 51
    def visit(self, node):
paul@488 52
paul@488 53
        # Obtain the method for the node name.
paul@488 54
paul@489 55
        fn = getattr(self, node.__name__)
paul@488 56
paul@488 57
        # Call the method.
paul@488 58
paul@488 59
        fn(node)
paul@488 60
paul@488 61
        # Visit the node's children.
paul@488 62
paul@488 63
        self.visitChildren(node)
paul@488 64
paul@488 65
    def visitChildren(self, node):
paul@488 66
        self.indent += 1
paul@488 67
        for n in node.children():
paul@488 68
            self.visit(n)
paul@488 69
        self.indent -= 1
paul@488 70
paul@488 71
    def writeIndent(self):
paul@488 72
        i = 0
paul@488 73
        while i < self.indent:
paul@488 74
            print "",
paul@488 75
            i += 1
paul@488 76
paul@488 77
    def Expr(self, node):
paul@488 78
        self.writeIndent()
paul@488 79
        print "Expression..."
paul@488 80
paul@488 81
    def Binary(self, node):
paul@488 82
        self.writeIndent()
paul@488 83
        print "Binary operation", node.op
paul@488 84
paul@488 85
    def Unary(self, node):
paul@488 86
        self.writeIndent()
paul@488 87
        print "Unary operation", node.op
paul@488 88
paul@488 89
    def Value(self, node):
paul@488 90
        self.writeIndent()
paul@488 91
        print "Value", node.value
paul@488 92
paul@488 93
# Test the visitor with an example expression.
paul@488 94
paul@488 95
expr = Expr([Binary(Value(1), "+", Binary(Unary("-", Value(2)), "*", Value(3)))])
paul@488 96
Visitor().visit(expr)