defl/defl/_microlang_.py
2024-09-11 11:14:03 -04:00

90 lines
1.9 KiB
Python

#!/usr/bin/env python
'''
WARNING USE OF `eval()`
'''
from dataclasses import dataclass, KW_ONLY
from typing import ClassVar, Iterable
from ._typing_ import *
from ._regex_ import regSpaceOnly
_varMap = {
'(': '(',
')': ')',
'or': 'or',
'and': 'and',
'not': 'not',
'!': 'not',
'~': 'not',
'&': 'and',
'&&': 'and',
'|': 'or',
'||': 'or',
N: N,
'none': N,
'null': N,
'n': N,
't': T,
'true': T,
'f': F,
'false': F,
}
MicroLangStatement = NewType('MicroLang', Iterable)
@dataclass(slots=T, kw_only=T, frozen=T)
class MicroLang():
# TODO string parse
stmnts: MicroLangStatement = field(kw_only=F, repr=T)
env: dict = field(default_factory=dict, repr=T)
@staticmethod
def strToToken(ss):
return re.split(r'([a-zA-Z0-9\_]+|.)', ss)
@staticmethod
def isToken(t) -> bool:
return t.lower() in _varMap
def _eval(_, *args, **kargs):
if isinstance(_.stmnts, str):
stmnts = MicroLang.strToToken(_.stmnts)
else:
stmnts = [x for x in _.stmnts]
for i, state in enumerate(stmnts):
if state in _.env:
state = _.env[state]
if callable(state):
state = state(*args, **kargs)
if isinstance(state, str):
state = state.strip()
stateLow = state.lower()
if (s := _varMap.get(stateLow, U)) is not U:
state = s
stmnts[i] = state
stmnts = [x for x in stmnts if not regSpaceOnly.any(x)]
return stmnts
def eval(_, *args, **kargs):
reduced = _._eval(*args, **kargs)
if not reduced:
return
toEval = ' '.join([str(x) for x in reduced])
try:
return bool(eval(toEval))
except SyntaxError as e:
e.add_note(str(reduced))
raise e
e = eval
def __bool__(_):
return _.eval()