222 lines
5.6 KiB
Python
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)) |