DSM/interpreter.py

222 lines
5.6 KiB
Python

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))