from nodes import * from values import Number class Interpeter: def visit(self, node): method_name = f'visit_{type(node).__name__}' method = getattr(self, method_name) return method(node) def visit_NumberNode(self, node) -> Number: return Number(node.value) def visit_AddNode(self, node) -> Number: return Number(self.visit(node.node_a).value + self.visit(node.node_b).value) def visit_SubtractNode(self, node) -> Number: return Number(self.visit(node.node_a).value - self.visit(node.node_b).value) def visit_MultiplyNode(self, node) -> Number: return Number(self.visit(node.node_a).value * self.visit(node.node_b).value) def visit_DivideNode(self, node) -> Number: try: return Number(self.visit(node.node_a).value / self.visit(node.node_b).value) except Exception: raise Exception("Runtime Math error (division)") def visit_PlusNode(self, node) -> Number: return self.visit(node.node) def visit_MinusNode(self, node) -> Number: return Number(-self.visit(node.node).value) def visit_FactorialNode(self, node) -> Number: fact = lambda x: 1 if x == 0 else x * fact(x-1) try: return Number(fact(self.visit(node.node).value)) except Exception: raise Exception("Runtime Math error (Factorial)") def visit_PowerNode(self, node) -> Number: return Number(pow(self.visit(node.node_a).value, self.visit(node.node_b).value)) def visit_ModuleNode(self, node) -> Number: return Number(self.visit(node.node_a).value % self.visit(node.node_b).value) def visit_AverageNode(self, node) -> Number: return Number((self.visit(node.node_a).value + self.visit(node.node_b).value) / 2.0 ) def visit_MaximumNode(self, node) -> Number: return Number(max(self.visit(node.node_a).value, self.visit(node.node_b).value) ) def visit_MinimumNode(self, node) -> Number: return Number(min(self.visit(node.node_a).value, self.visit(node.node_b).value) ) def visit_NegateNode(self, node) -> Number: if not self.visit(node.node).value.is_integer(): raise Exception("Runtime Math error (Negate)") return Number(~int(self.visit(node.node).value))