diff --git a/auto_editor/analyze.py b/auto_editor/analyze.py index 061c2c306..5fae2bede 100644 --- a/auto_editor/analyze.py +++ b/auto_editor/analyze.py @@ -37,6 +37,7 @@ from numpy.typing import NDArray from auto_editor.ffwrapper import FileInfo + from auto_editor.lib.data_structs import Env from auto_editor.output import Ensure from auto_editor.utils.bar import Bar from auto_editor.utils.log import Log @@ -489,9 +490,7 @@ def pixeldiff(self, s: int) -> NDArray[np.uint64]: return self.cache("pixeldiff", pobj, result) -def edit_method( - val: str, filesetup: FileSetup, env: dict[str, Any] -) -> NDArray[np.bool_]: +def edit_method(val: str, filesetup: FileSetup, env: Env) -> NDArray[np.bool_]: assert isinstance(filesetup, FileSetup) src = filesetup.src tb = filesetup.tb diff --git a/auto_editor/lang/palet.py b/auto_editor/lang/palet.py index 419eafd88..21de45232 100644 --- a/auto_editor/lang/palet.py +++ b/auto_editor/lang/palet.py @@ -31,7 +31,6 @@ Number = Union[int, float, complex, Fraction] Real = Union[int, float, Fraction] BoolList = NDArray[np.bool_] - Env = dict[str, Any] class ClosingError(MyError): @@ -1108,7 +1107,7 @@ def my_eval(env: Env, node: object) -> Any: if type(node) is Sym: val = env.get(node.val) if val is None: - if mat := get_close_matches(node.val, env): + if mat := get_close_matches(node.val, env.data): raise MyError(f"'{node.val}' not found. Did you mean: {mat[0]}") raise MyError(f"'{node.val}' not found.") return val @@ -1157,7 +1156,9 @@ def my_eval(env: Env, node: object) -> Any: return node -env: Env = {} + +# fmt: off +env = Env() env.update({ # constants "true": True, @@ -1337,6 +1338,7 @@ def my_eval(env: Env, node: object) -> Any: "rename": Syntax(syn_rename), "delete": Syntax(syn_delete), }) +# fmt: on def interpret(env: Env, parser: Parser) -> list: diff --git a/auto_editor/lib/data_structs.py b/auto_editor/lib/data_structs.py index f60ed761c..e6cb1488c 100644 --- a/auto_editor/lib/data_structs.py +++ b/auto_editor/lib/data_structs.py @@ -2,10 +2,41 @@ from fractions import Fraction from io import StringIO +from typing import Any import numpy as np +class Env: + __slots__ = "data" + + def __init__(self) -> None: + self.data: dict[str, Any] = {} + + def __getitem__(self, key: str) -> Any: + return self.data[key] + + def __setitem__(self, key: str, val: Any) -> None: + self.data[key] = val + + def __delitem__(self, key: str) -> None: + del self.data[key] + + def __contains__(self, item: Any) -> bool: + return item in self.data + + def update(self, my_dict: dict[str, Any]) -> None: + self.data.update(my_dict) + + def get(self, key: str) -> Any: + return self.data.get(key) + + def copy(self) -> Env: + new_env = Env() + new_env.update(self.data.copy()) + return new_env + + class Sym: __slots__ = ("val", "hash") diff --git a/auto_editor/utils/cmdkw.py b/auto_editor/utils/cmdkw.py index 8fe6de2c9..d39fffa1d 100644 --- a/auto_editor/utils/cmdkw.py +++ b/auto_editor/utils/cmdkw.py @@ -3,6 +3,7 @@ from difflib import get_close_matches from typing import TYPE_CHECKING, NamedTuple +from auto_editor.lib.data_structs import Env from auto_editor.utils.types import CoerceError if TYPE_CHECKING: @@ -103,7 +104,9 @@ def get_next_token(self) -> str | None: return None -def parse_with_palet(text: str, build: pAttrs, env: dict) -> dict[str, Any]: +def parse_with_palet( + text: str, build: pAttrs, _env: Env | dict[str, Any] +) -> dict[str, Any]: from auto_editor.lang.palet import Lexer, Parser, interpret from auto_editor.lib.data_structs import print_str from auto_editor.lib.err import MyError @@ -118,6 +121,11 @@ def parse_with_palet(text: str, build: pAttrs, env: dict) -> dict[str, Any]: def go(text: str, c: Any) -> Any: try: + if isinstance(_env, Env): + env = _env + else: + env = Env() + env.update(_env) results = interpret(env, Parser(Lexer(build.name, text))) except MyError as e: raise ParserError(e)