from datetime import datetime from collections import deque from arden_types import StrType, NumType, DateType, ListType, NullType, BoolType, Condition import math import copy class InterpreterError(Exception): pass class Interpreter: def __init__(self): self.variables = {} self.it_queue = deque() def interpret(self, node): node_type = node["type"] args = node.get('arg', []) if node_type == "WHERE": self.it_queue.append(self.interpret(args[0])) evaluated_args = [self.interpret(arg) for arg in (args if isinstance(args, list) else [args])] return getattr(self, node_type)(node, *evaluated_args) def STATEMENTBLOCK(self,node): for stmt in node.get("statements"): self.interpret(stmt) #Statements def WRITE(self,node,a): print(a) def TRACE(self,node,a): print(f"LINE {node['line']}: {a}") def ASSIGN(self,node,a): #self.variables.update({node.get("varname"): (self.variables.get(node.get("varname")[0],NullType()),a)}) self.variables.update({node.get("varname"): copy.copy(a)}) def TIMEASSIGN(self,node,a): #self.variables.update({node.get("varname"): (a,self.variables.get(node.get("varname"))[1])}) value = self.variables[node.get("varname")] value.time = a self.variables.update({node.get("varname"): copy.copy(value)}) def LISTINDEXASSIGN(self,node,a,b): value = self.variables[node.get("varname")] return value.LISTINDEXASSIGN(a,b) def LISTINDEXTIMEASSIGN(self,node,a,b): value = self.variables[node.get("varname")] return value.LISTINDEXASSIGN(a,b) def IF(self,node,a): if a: self.interpret(node.get("statements")) return for elseif in node.get("elseif"): if self.interpret(elseif): return else: if node.get("else"): self.interpret(node.get("else")) def ELSEIF(self,node,a): if a: self.interpret(node.get("statements")) return True return False def ELSE(self,node): self.interpret(node.get("statements")) def FOR(self,node,a): for x in a.value: self.variables[node.get("varname")] = x self.interpret(node.get("statements")) del self.variables[node.get("varname")] #Types def NUMTOKEN(self,node): return NumType(node.get("value")) def STRTOKEN(self,node): return StrType(node.get("value")) def TIMETOKEN(self,node): try: return DateType(datetime.strptime(node.get("value"), "%Y-%m-%dT%H:%M:%S")) except ValueError: return DateType(datetime.strptime(node.get("value"), "%Y-%m-%d")) def NULLTOKEN(self,node): return NullType() def NOW(self,node): return DateType(datetime.now()) def VARIABLE(self,node): return self.variables.get(node.get("name")) def TIME(self,node,a): return a.TIME() def LIST(self,node): return ListType([self.interpret(node) for node in node["elements"]]) def BOOL(self,node): return BoolType(True) if node.get("value") == "1" else BoolType(False) def NULLTYPE(self,node): return NullType def NUMTYPE(self,node): return NumType def LISTTYPE(self,node): return ListType def TRUE(self,node): return True def FALSE(self,node): return False def IT(self,node): if self.it_queue: return self.it_queue[-1] return NullType() def LISTACCESS(self,node,a,b): return a.LISTACCESS(b) #Binary Operators def AMBERSAND(self,node,a,b): return a & b def PLUS(self,node,a,b): return a + b def MINUS(self,node,a,b): return a - b def TIMES(self,node,a,b): return a * b def DIVIDE(self,node,a,b): return a / b def POWER(self,node,a,b): return a ** b def WHERE(self,node,a,b): res = a.WHERE(b) self.it_queue.pop() return res def GT(self,node,a,b): return a > b def LT(self,node,a,b): return a < b def AND(self,node,a,b): return a & b def OR(self,node,a,b): return a | b def RANGE(self,node,a,b): rangelist = [] x = range(a.value,b.value+1) for i in x: rangelist.append(NumType(i)) return ListType(rangelist) #Unary Operators def UMINUS(self,node,a): return -a def COS(self,node,a): return NumType(math.cos(a)) def SIN(self,node,a): return NumType(math.sin(a)) def IS(self,node,a,b): return a.IS(b) def ISNOT(self,node,a,b): return a.IS(b).NOT() def OCCURS(self,node,a,b): return a.OCCURS(b) def NOT(self,a): return ~a def FIRST(self,node,a): return a.value[0] def COUNT(self,node, a): return NumType(len(a.value)) #Conditions def LESS(self,node,a): return Condition(lambda x: x < a) def BEFORE(self,node,a): return Condition(lambda x: x < a) def GREATER(self,node,a): return Condition(lambda x: x > a) def AFTER(self,node,a): return Condition(lambda x: x > a) def LESSEQUAL(self,node,a): return Condition(lambda x: x <= a) def GREATEREQUAL(self,node,a): return Condition(lambda x: x >= a) def WITHIN(self,node,a,b): return Condition(lambda x: (a <= x) & (x <= b))