from abc import ABC, abstractmethod from datetime import date class BaseType(ABC): @abstractmethod def __str__(self): pass def __init__(self): self.time = NullType(False) def __repr__(self): return str(self) #def __eq__(self,b): # return BoolType(str(type(self).__name__) is b) def __and__(self,other): if isinstance(other, StrType): return StrType(str(self) + str(other)) return NullType() def IS(self,b,invert=False): if b is type(self): return BoolType(True) return BoolType(False) def NOT(self,b,invert=False): return NullType() def ISNOT(self,b,invert=False): return ~self.IS(b) def LISTACCESS(self,b): return NullType() def TIME(self): return self.time class NumType(BaseType): def __init__(self, value: (int, float)): super().__init__() if isinstance(value, str): try: value = int(value) except ValueError: value = float(value) if not isinstance(value, (int, float)): raise TypeError(f"Expected a number, got {type(value)}") self.value = value def __mul__(self,other): if isinstance(other, NumType): return NumType(self.value * other.value) if isinstance(other, ListType): return ListType([item * self for item in other.value]) return NullType() def __truediv__(self,other): if isinstance(other, NumType): return NumType(self.value / other.value) if isinstance(other, ListType): return ListType([item / self for item in other.value]) return NullType() def __add__(self,other): if isinstance(other, NumType): return NumType(self.value + other.value) return NullType() def __sub__(self,other): if isinstance(other, NumType): return NumType(self.value - other.value) return NullType() def __gt__(self, other): if isinstance(other, NumType): return BoolType(self.value > other.value) return NullType def __lt__(self, other): if isinstance(other, NumType): return BoolType(self.value < other.value) return NullType def __ge__(self, other): if isinstance(other, NumType): return BoolType(self.value >= other.value) if isinstance(other, ListType): return ListType([self >= item for item in other.value]) return NullType def __le__(self, other): if isinstance(other, NumType): return BoolType(self.value <= other.value) if isinstance(other, ListType): return ListType([self <= item for item in other.value]) return NullType def __pow__(self, other): if isinstance(other, NumType): return NumType(self.value ** other.value) return NullType def __neg__(self): return NumType(-self.value) def __str__(self): return str(self.value) def IS(self,b,invert=False): if b is type(self): return BoolType(True) if type(b) is self: return BoolType(self.value == b.value) if type(b) is Condition: return b.value(self) return BoolType(False) class StrType(BaseType): def __init__(self, value: str): super().__init__() if not isinstance(value, str): raise TypeError(f"Expected a string, got {type(value)}") self.value = value def __and__(self,other): return StrType(str(self) + str(other)) def __str__(self): return self.value class BoolType(BaseType): def __init__(self, value: bool): super().__init__() if not isinstance(value, bool): raise TypeError(f"Expected a boolean, got {type(value)}") self.value = value def __eq__(self, other): return self.value == other.value def __bool__(self): return self.value def __invert__(self): return BoolType(not self.value) def __str__(self): if self.value: return "true" else: return "false" def __and__(self,other): if isinstance(other, BoolType): return BoolType(self.value and other.value) return NullType def NOT(self): return ~self class ListType(BaseType): def __init__(self, value: list): super().__init__() if not isinstance(value, list): raise TypeError(f"Expected a list, got {type(value)}") self.value = value def __str__(self): return f"[{', '.join(str(item) for item in self.value)}]" def __gt__(self, other): if isinstance(other, NumType): return ListType([item > other for item in self.value]) return NullType def __lt__(self, other): if isinstance(other, NumType): return ListType([item < other for item in self.value]) return NullType def __ge__(self, other): if isinstance(other, NumType): return ListType([item >= other for item in self.value]) if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item >= b_item for a_item, b_item in zip(self.value, other.value)]) return NullType def __le__(self, other): if isinstance(other, NumType): return ListType([item <= other for item in self.value]) if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item <= b_item for a_item, b_item in zip(self.value, other.value)]) return NullType def __and__(self,other): if isinstance(other, BoolType) or isinstance(other, NumType): return ListType([item and other for item in self.value]) if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item and b_item for a_item, b_item in zip(self.value, other.value)]) return NullType def __or__(self,other): if isinstance(other, BoolType) or isinstance(other, NumType): return ListType([item or other for item in self.value]) if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item or b_item for a_item, b_item in zip(self.value, other.value)]) return NullType def __truediv__(self,other): if isinstance(other, NumType): return ListType([item / other for item in self.value]) if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item / b_item for a_item, b_item in zip(self.value, other.value)]) return NullType def WHERE(self,other): if isinstance(other, ListType) and len(self.value) == len(other.value): return ListType([a_item for a_item, b_item in zip(self.value, other.value) if b_item]) return NullType def IS(self,a,invert=False): if a is NumType: return ListType([item.IS(a) for item in self.value]) if a is type(self): return BoolType(True^invert) if type(a) is Condition: return a.value(self) else: return BoolType(False^invert) def OCCURS(self,a): if type(a) is Condition: return ListType([a.value(item.time) for item in self.value]) def NOT(self): return ListType([~item for item in self.value]) def LISTACCESS(self,a): if type(a) is NumType: return self.value[a.value] return NullType() def LISTINDEXASSIGN(self,a,b): if type(a) is NumType: self.value[a.value-1] = b #self.value.insert(a.value,b) return NullType() def TIME(self): return ListType([item.time for item in self.value]) class DateType(BaseType): def __init__(self, value: date): super().__init__() if not isinstance(value, date): raise TypeError(f"Expected a date, got {type(value)}") self.value = value def __gt__(self, other): if isinstance(other, DateType): return BoolType(self.value > other.value) return NullType def __lt__(self, other): if isinstance(other, DateType): return BoolType(self.value < other.value) return NullType def __str__(self): return self.value.strftime('%Y-%m-%dT%H:%M:%S') class Condition(BaseType): def __init__(self, condition): self.value = condition def __and__(self, other): return Condition(lambda x: self.value(x) and other.value(x)) def __or__(self,other): return Condition(lambda x: self.value(x) or other.value(x)) def __str__(self): return str(self.value) class NullType(BaseType): def __init__(self, has_time=True): if has_time: super().__init__() def __str__(self): return "Null"