from abstractiterator import *
from abstractaggregate import *

UndefinedError="UndefinedError"

class Tree(AbstractAggregate):
    def __init__(self, root):
        self.root=root

    def createIterator(self):
        return TreeIterator(self.root)

    def __repr__(self):
        return `self.root`
    
class TreeIterator(AbstractIterator):
    def __init__(self,root):
        self.root=root
        self.unvisited=[]
        self.unvisited.append(root)

    def first(self):
        pass

    def next(self):
        removed=self.unvisited.pop(0)
        if isinstance(removed, BinaryNode):
            self.unvisited.insert(0,removed.right)
            self.unvisited.insert(0,removed.left)
            return self.next()
        else:
            return removed

    def isDone(self):
        return len(self.unvisited)==0

    def currentItem(self):
        pass

    def reset(self):
        self.unvisited=[]
        self.unvisited.append(self.root)

class TreeNode:
    def validate(self, dict):
        pass
    def interpret(self, dict):
        pass
    def trace(self, level):
        print '.'*level+'<empty>'

class BinaryNode(TreeNode):
    def __init__(self, left, right):
        self.left, self.right=left, right
    def validate(self, dict):
        self.left.validate(dict)
        self.right.validate(dict)
    def trace(self, level):
        print '.'*level+'['+self.label+']'
        self.left.trace(level+3)
        self.right.trace(level+3)
    def __repr__(self):
        return '('+`self.left`+self.label+`self.right`+')'

class TimesNode(BinaryNode):
    label='*'
    def interpret(self, dict):
        return self.left.interpret(dict)*self.right.interpret(dict)

class DivideNode(BinaryNode):
    label='/'
    def interpret(self, dict):
        return self.left.interpret(dict)/self.right.interpret(dict)

class PlusNode(BinaryNode):
    label='+'
    def interpret(self, dict):
        return self.left.interpret(dict)+self.right.interpret(dict)

class MinusNode(BinaryNode):
    label='-'
    def interpret(self, dict):
        return self.left.interpret(dict)-self.right.interpret(dict)

class NumNode(TreeNode):
    def __init__(self, num):
        self.num=float(num)
    def interpret(self,dict):
        return self.num
    def trace(self,level):
        print '.'*level+`self.num`
    def __repr__(self):
        return `self.num`

class CellNode(TreeNode):
    def __init__(self, row, col):
        self.row=row
        self.col=col
    def interpret(self,dict):
        return dict[(self.row, self.col)].getValue()
    def trace(self,level):
        print '.'*level+`self.row`+' '+`self.col`
    def __repr__(self):
        return '$'+`self.row`+'$'+`self.col`













