| 74 | |
| 75 | |
| 76 | class Term: |
| 77 | def __new__(cls, name, env, side=None, encoding=None): |
| 78 | klass = Constant if not isinstance(name, str) else cls |
| 79 | supr_new = super(Term, klass).__new__ |
| 80 | return supr_new(klass) |
| 81 | |
| 82 | is_local: bool |
| 83 | |
| 84 | def __init__(self, name, env, side=None, encoding=None) -> None: |
| 85 | # name is a str for Term, but may be something else for subclasses |
| 86 | self._name = name |
| 87 | self.env = env |
| 88 | self.side = side |
| 89 | tname = str(name) |
| 90 | self.is_local = tname.startswith(LOCAL_TAG) or tname in DEFAULT_GLOBALS |
| 91 | self._value = self._resolve_name() |
| 92 | self.encoding = encoding |
| 93 | |
| 94 | @property |
| 95 | def local_name(self) -> str: |
| 96 | return self.name.replace(LOCAL_TAG, "") |
| 97 | |
| 98 | def __repr__(self) -> str: |
| 99 | return pprint_thing(self.name) |
| 100 | |
| 101 | def __call__(self, *args, **kwargs): |
| 102 | return self.value |
| 103 | |
| 104 | def evaluate(self, *args, **kwargs) -> Term: |
| 105 | return self |
| 106 | |
| 107 | def _resolve_name(self): |
| 108 | local_name = str(self.local_name) |
| 109 | is_local = self.is_local |
| 110 | if local_name in self.env.scope and isinstance( |
| 111 | self.env.scope[local_name], type |
| 112 | ): |
| 113 | is_local = False |
| 114 | |
| 115 | res = self.env.resolve(local_name, is_local=is_local) |
| 116 | self.update(res) |
| 117 | |
| 118 | if hasattr(res, "ndim") and isinstance(res.ndim, int) and res.ndim > 2: |
| 119 | raise NotImplementedError( |
| 120 | "N-dimensional objects, where N > 2, are not supported with eval" |
| 121 | ) |
| 122 | return res |
| 123 | |
| 124 | def update(self, value) -> None: |
| 125 | """ |
| 126 | search order for local (i.e., @variable) variables: |
| 127 | |
| 128 | scope, key_variable |
| 129 | [('locals', 'local_name'), |
| 130 | ('globals', 'local_name'), |
| 131 | ('locals', 'key'), |
| 132 | ('globals', 'key')] |
| 133 | """ |