<filename>My_Interpreter/imp_ast.py

from equality import *

class Statement(Equality):
    pass

class Aexp(Equality):
    pass

class Bexp(Equality):
    pass

class AssignStatement(Statement):
    def __init__(self, name, aexp):
        self.name = name
        self.aexp = aexp

    def __repr__(self):
        return 'AssignStatement(%s, %s)' % (self.name, self.aexp)

    def defprintvar(self):
        return self.name

    def defprintint(self):
        return self.aexp

    def eval(self, env):
        value = self.aexp.eval(env)
        env[self.name] = value

class XorStatement(Statement):
    def __init__(self, name, aexp):
        self.name = name
        self.aexp = aexp

    def __repr__(self):
        return "XorStatement(%s, %s)" % (self.name, self.aexp)

    def eval(self, env):
        left_value = self.name.eval(env)
        right_value = self.aexp.eval(env)
        value = right_value ^ left_value
        env[self.name.printvar()] = value

class CompoundStatement(Statement):
    def __init__(self, first, second):
        self.first = first
        self.second = second

    def __repr__(self):
        return 'CompoundStatement(%s, %s)' % (self.first, self.second)

    def eval(self, env):
        self.first.eval(env)
        self.second.eval(env)

class IfStatement(Statement):
    def __init__(self, condition, true_stmt, false_stmt):
        self.condition = condition
        self.true_stmt = true_stmt
        self.false_stmt = false_stmt

    def __repr__(self):
        return 'IfStatement(%s, %s, %s)' % (self.condition, self.true_stmt, self.false_stmt)

    def eval(self, env):
        condition_value = self.condition.eval(env)
        if condition_value:
            self.true_stmt.eval(env)
        else:
            if self.false_stmt:
                self.false_stmt.eval(env)

class TernaryStatement(Statement):
    def __init__(self, condition, true_stmt, false_stmt):
        self.condition = condition
        self.true_stmt = true_stmt
        self.false_stmt = false_stmt

    def __repr__(self):
        return "TernaryStatement(%s, %s, %s)" % (self.condition, self.true_stmt, self.false_stmt)

    def eval(self, env):
        raise RuntimeError("Error, variable", "has not initialized yet.")
        condition_value = self.condition.eval(env)
        if condition_value:
            print(self.true_stmt.eval(env))
        else:
            if self.false_stmt:
                print(self.false_stmt.eval(env))

class DefStatement(Statement):
    def __init__(self, result, body):
        self.result = result
        self.body = body

    def __repr__(self):
        return 'DefStatement(%s, %s)' % (self.result, self.body)

    def eval(self, env):
        body_value = self.body.eval(env)
        if self.result.printvar() in env.keys():
            return print(env.get(self.result.printvar()))
        else:
            raise RuntimeError("Error, variable", self.result.printvar(), "has not initialized yet.")

class WhileStatement(Statement):
    def __init__(self, condition, body):
        self.condition = condition
        self.body = body

    def __repr__(self):
        return 'WhileStatement(%s, %s)' % (self.condition, self.body)

    def eval(self, env):
        condition_value = self.condition.eval(env)
        while condition_value:
            self.body.eval(env)
            condition_value = self.condition.eval(env)

class ForStatement(Statement):
    def __init__(self, counter, index1, index2, body):
        self.counter = counter
        self.index1 = index1
        self.index2 = index2
        self.body = body

    def __repr__(self):
        return "ForStatement(%s, %s, %s, %s)" % (self.counter, self.index1, self.index2, self.body)

    def eval(self, env):
        start = self.index1.eval(env)
        end = self.index2.eval(env)
        for i in range(start, end):
            self.body.eval(env)

class RangeStatement(Statement):
    def __init__(self, index1, index2):
        self.index1 = index1
        self.index2 = index2

    def __repr__(self):
        return 'RangeStatement (%s %s)' % (self.index1, self.index2)

    def eval(self, env):
        start = self.index1.eval(env)
        end = self.index2.eval(env)
        range(start, end)

class IntAexp(Aexp):
    def __init__(self, i):
        self.i = i

    def __repr__(self):
        return 'IntAexp(%d)' % self.i

    def printvar(self):
        return self.i

    def printint(self):
        return self.i

    def eval(self, env):
        return self.i

class VarAexp(Aexp):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return 'VarAexp(%s)' % self.name

    def printvar(self):
        return self.name

    def printint(self):
        return self.name

    def eval(self, env):
        if self.name in env:
            return env[self.name]
        else:
            return 0

class PrintStatement(Statement):
    def __init__(self, result):
        self.result = result

    def __repr__(self):
        return 'PrintAexp(%w)' % self.result

    def eval(self, env):
        if self.result.printvar() in env.keys():
            return print(env.get(self.result.printvar()))
        else:
            return print(self.result.printint())

class BinopAexp(Aexp):
    def __init__(self, op, left, right):
        self.op = op
        self.left = left
        self.right = right

    def __repr__(self):
        return 'BinopAexp(%s, %s, %s)' % (self.op, self.left, self.right)

    def return_value(self):
        return self.op, self.left, self.right

    def eval(self, env):
        left_value = self.left.eval(env)
        right_value = self.right.eval(env)
        if self.op == '+':
            value = left_value + right_value
        elif self.op == '-':
            value = left_value - right_value
        elif self.op == '*':
            value = left_value * right_value
        elif self.op == '/':
            value = left_value / right_value
        elif self.op == '~':
            value = ~ right_value
        elif self.op == '^':
            value = left_value ^ right_value
        else:
            raise RuntimeError('unknown operator: ' + self.op)
        return value

class UnaryAexp(Aexp):
    def __init__(self, op, right):
        self.op = op
        self.right = right

    def __repr__(self):
        return 'UnaryAexp(%s, %s)' % (self.right, self.op)

    def eval(self, env):
        right_value = self.right.eval(env)
        if self.op == '~':
            value = ~right_value
        else:
            raise  RuntimeError('Unknown operator:' + self.op)
        return value

class RelopBexp(Bexp):
    def __init__(self, op, left, right):
        self.op = op
        self.left = left
        self.right = right

    def __repr__(self):
        return 'RelopBexp(%s, %s, %s)' % (self.op, self.left, self.right)

    def eval(self, env):
        left_value = self.left.eval(env)
        right_value = self.right.eval(env)
        if self.op == '<':
            value = left_value < right_value
        elif self.op == '<=':
            value = left_value <= right_value
        elif self.op == '>':
            value = left_value > right_value
        elif self.op == '>=':
            value = left_value >= right_value
        elif self.op == '=':
            value = left_value == right_value
        elif self.op == '!=':
            value = left_value != right_value
        else:
            raise RuntimeError('unknown operator: ' + self.op)
        return value

class AndBexp(Bexp):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __repr__(self):
        return 'AndBexp(%s, %s)' % (self.left, self.right)

    def eval(self, env):
        left_value = self.left.eval(env)
        right_value = self.right.eval(env)
        return left_value and right_value

class OrBexp(Bexp):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __repr__(self):
        return 'OrBexp(%s, %s)' % (self.left, self.right)

    def eval(self, env):
        left_value = self.left.eval(env)
        right_value = self.right.eval(env)
        return left_value or right_value

class NotBexp(Bexp):
    def __init__(self, exp):
        self.exp = exp

    def __repr__(self):
        return 'NotBexp(%s)' % self.exp

    def eval(self, env):
        value = self.exp.eval(env)
        return not value
