oasm 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
oasm/__init__.py
CHANGED
|
@@ -2,151 +2,28 @@ import pkgutil
|
|
|
2
2
|
__path__ = pkgutil.extend_path(__path__,__name__)
|
|
3
3
|
__path__.reverse()
|
|
4
4
|
|
|
5
|
-
__all__ = ['table','config','equal','expr','sym','context','flow','meta','multi','domain']
|
|
5
|
+
__all__ = ['table','config','equal','expr','subs','sym','context','flow','meta','multi','domain']
|
|
6
6
|
from pprint import pformat
|
|
7
7
|
|
|
8
|
-
"""
|
|
9
|
-
Open Assembly Tools (OASM) Core Module
|
|
10
|
-
|
|
11
|
-
This module provides a comprehensive set of fundamental data structures and utility classes
|
|
12
|
-
for advanced configuration management, expression processing, and assembly operations.
|
|
13
|
-
|
|
14
|
-
Key features include:
|
|
15
|
-
- Hybrid container types combining list and dictionary functionality
|
|
16
|
-
- Configuration management with JSON persistence capabilities
|
|
17
|
-
- Advanced expression evaluation system with operator overloading
|
|
18
|
-
- Context management for state preservation and manipulation
|
|
19
|
-
- Flow control utilities for programmatic assembly operations
|
|
20
|
-
- Metaprogramming capabilities for dynamic code generation
|
|
21
|
-
- Domain-specific language (DSL) constructs for custom assembly logic
|
|
22
|
-
|
|
23
|
-
Module structure:
|
|
24
|
-
- table: A flexible container that combines list and dictionary functionality
|
|
25
|
-
- config: Extends table with JSON file loading and saving capabilities
|
|
26
|
-
- equal: Deep equality comparison function for complex data structures
|
|
27
|
-
- expr: Expression evaluation system with comprehensive operator support
|
|
28
|
-
- sym: Symbolic expression constructor
|
|
29
|
-
- context: Context management for maintaining and switching execution states
|
|
30
|
-
- flow: Control flow management for assembly operations
|
|
31
|
-
- meta: Metaprogramming utilities for dynamic code generation
|
|
32
|
-
- multi: Multi-node assembly support for distributed operations
|
|
33
|
-
- domain: DSL decorator for custom assembly language constructs
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
8
|
class table(list):
|
|
37
|
-
"""
|
|
38
|
-
A flexible container that combines list and dictionary functionality.
|
|
39
|
-
|
|
40
|
-
The table class extends the built-in list type while adding dictionary-like
|
|
41
|
-
attribute access. This hybrid design allows for both sequential access by index
|
|
42
|
-
and named access by attribute/key.
|
|
43
|
-
|
|
44
|
-
Key features:
|
|
45
|
-
- Supports list operations (append, extend, indexing)
|
|
46
|
-
- Supports dictionary-like attribute and key access
|
|
47
|
-
- Methods for deep copying and conversion to/from dictionaries
|
|
48
|
-
- Callable interface that supports custom functions or method chaining
|
|
49
|
-
|
|
50
|
-
Examples:
|
|
51
|
-
t = table(1, 2, 3, a=4, b=5)
|
|
52
|
-
print(t[0]) # Output: 1
|
|
53
|
-
print(t.a) # Output: 4
|
|
54
|
-
"""
|
|
55
9
|
def __init__(self, *args, **kwargs):
|
|
56
|
-
"""
|
|
57
|
-
Initialize a new table instance.
|
|
58
|
-
|
|
59
|
-
Parameters:
|
|
60
|
-
*args: Positional arguments to be stored as list items
|
|
61
|
-
**kwargs: Keyword arguments to be stored as attributes
|
|
62
|
-
|
|
63
|
-
The initialization process:
|
|
64
|
-
1. Stores all positional arguments as items in the list
|
|
65
|
-
2. Stores all keyword arguments as attributes in the instance dictionary
|
|
66
|
-
"""
|
|
67
10
|
super().__init__(args)
|
|
68
11
|
self.__dict__.update(kwargs)
|
|
69
12
|
def __getitem__(self, key=None):
|
|
70
|
-
"""
|
|
71
|
-
Get an item from the table.
|
|
72
|
-
|
|
73
|
-
Parameters:
|
|
74
|
-
key: The key or index to retrieve. If a string, it accesses an attribute;
|
|
75
|
-
otherwise, it accesses a list item.
|
|
76
|
-
|
|
77
|
-
Returns:
|
|
78
|
-
The requested item from the list or attribute from the dictionary.
|
|
79
|
-
|
|
80
|
-
Raises:
|
|
81
|
-
KeyError: If the key is a string and not found in __dict__
|
|
82
|
-
IndexError: If the key is an integer and out of range for the list
|
|
83
|
-
|
|
84
|
-
This method provides dual functionality:
|
|
85
|
-
- String keys access attributes stored in __dict__
|
|
86
|
-
- Other keys (typically integers) access list items
|
|
87
|
-
"""
|
|
88
13
|
if type(key) is str:
|
|
89
14
|
return self.__dict__[key]
|
|
90
15
|
return super().__getitem__(key)
|
|
91
16
|
def __setitem__(self, key, val):
|
|
92
|
-
"""
|
|
93
|
-
Set an item in the table.
|
|
94
|
-
|
|
95
|
-
Parameters:
|
|
96
|
-
key: The key or index to set. If a string, it sets an attribute;
|
|
97
|
-
otherwise, it sets a list item.
|
|
98
|
-
val: The value to store at the specified key or index.
|
|
99
|
-
|
|
100
|
-
This method provides dual functionality:
|
|
101
|
-
- String keys set attributes in __dict__
|
|
102
|
-
- Other keys (typically integers) set list items
|
|
103
|
-
"""
|
|
104
17
|
if type(key) is str:
|
|
105
18
|
self.__dict__[key] = val
|
|
106
19
|
else:
|
|
107
20
|
super().__setitem__(key, val)
|
|
108
21
|
def __delitem__(self, key):
|
|
109
|
-
"""
|
|
110
|
-
Delete an item from the table.
|
|
111
|
-
|
|
112
|
-
Parameters:
|
|
113
|
-
key: The key or index to delete. If a string, it deletes an attribute;
|
|
114
|
-
otherwise, it deletes a list item.
|
|
115
|
-
|
|
116
|
-
Raises:
|
|
117
|
-
KeyError: If the key is a string and not found in __dict__
|
|
118
|
-
IndexError: If the key is an integer and out of range for the list
|
|
119
|
-
|
|
120
|
-
This method provides dual functionality:
|
|
121
|
-
- String keys delete attributes from __dict__
|
|
122
|
-
- Other keys (typically integers) delete list items
|
|
123
|
-
"""
|
|
124
22
|
if type(key) is str:
|
|
125
23
|
del self.__dict__[key]
|
|
126
24
|
else:
|
|
127
25
|
super().__delitem__(key)
|
|
128
26
|
def __call__(self, *args, **kwargs):
|
|
129
|
-
"""
|
|
130
|
-
Call method for the table class, supporting multiple operational modes.
|
|
131
|
-
|
|
132
|
-
Parameters:
|
|
133
|
-
*args: Positional arguments for the call
|
|
134
|
-
**kwargs: Keyword arguments for the call
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
- Result of the custom __call__ function if defined
|
|
138
|
-
- Self if no arguments provided (identity operation)
|
|
139
|
-
- Self after modification if arguments are provided (for method chaining)
|
|
140
|
-
|
|
141
|
-
The method operates in three modes:
|
|
142
|
-
1. Custom function execution: If a '__call__' attribute exists and is callable,
|
|
143
|
-
it is executed with the table as the first argument
|
|
144
|
-
2. Identity operation: If no arguments are provided, returns self
|
|
145
|
-
3. Modification mode: If arguments are provided:
|
|
146
|
-
- Positional arguments extend the list part
|
|
147
|
-
- Keyword arguments update the dictionary part
|
|
148
|
-
- Returns self to support method chaining
|
|
149
|
-
"""
|
|
150
27
|
func = self.__dict__.get('__call__',None)
|
|
151
28
|
if func is not None:
|
|
152
29
|
return func(self,*args,**kwargs)
|
|
@@ -156,18 +33,6 @@ class table(list):
|
|
|
156
33
|
self.__dict__.update(kwargs)
|
|
157
34
|
return self
|
|
158
35
|
def __repr__(self):
|
|
159
|
-
"""
|
|
160
|
-
Return a string representation of the table.
|
|
161
|
-
|
|
162
|
-
Returns:
|
|
163
|
-
str: A string representation combining list items and dictionary attributes
|
|
164
|
-
in a format similar to '[item1,item2,...,key1=value1,key2=value2,...]'
|
|
165
|
-
|
|
166
|
-
The representation includes:
|
|
167
|
-
1. All list items formatted with pformat for readability
|
|
168
|
-
2. All dictionary attributes in key=value format
|
|
169
|
-
3. Removes trailing commas for cleaner output
|
|
170
|
-
"""
|
|
171
36
|
r = ''
|
|
172
37
|
for i in self[:]:
|
|
173
38
|
r += pformat(i) + ','
|
|
@@ -177,54 +42,11 @@ class table(list):
|
|
|
177
42
|
r = r[:-1]
|
|
178
43
|
return '[' + r + ']'
|
|
179
44
|
def __neg__(self):
|
|
180
|
-
"""
|
|
181
|
-
Implement the unary negation operation for the table class.
|
|
182
|
-
|
|
183
|
-
Returns:
|
|
184
|
-
table: Returns self unchanged. This is a placeholder implementation
|
|
185
|
-
to ensure the table class works smoothly with expression systems.
|
|
186
|
-
|
|
187
|
-
This implementation makes the table class compatible with expression
|
|
188
|
-
systems that may apply unary negation operations. By returning self,
|
|
189
|
-
it effectively ignores the negation operation while maintaining compatibility.
|
|
190
|
-
"""
|
|
191
45
|
return self
|
|
192
46
|
def copy(self):
|
|
193
|
-
"""
|
|
194
|
-
Create a shallow copy of the table.
|
|
195
|
-
|
|
196
|
-
Returns:
|
|
197
|
-
table: A new table instance with copies of the list items and dictionary attributes.
|
|
198
|
-
|
|
199
|
-
This method creates a new table instance where:
|
|
200
|
-
1. The list portion is populated with the items from the original table
|
|
201
|
-
2. The dictionary portion is populated with the attributes from the original table
|
|
202
|
-
3. The copies are shallow - nested mutable objects will still reference the same instances
|
|
203
|
-
"""
|
|
204
47
|
return self.__class__(*self[:],**self.__dict__)
|
|
205
48
|
@staticmethod
|
|
206
49
|
def to_dict(x):
|
|
207
|
-
"""
|
|
208
|
-
Convert a table or other data structure to a serializable dictionary.
|
|
209
|
-
|
|
210
|
-
Parameters:
|
|
211
|
-
x: The object to convert to a dictionary. This can be a table, list,
|
|
212
|
-
tuple, dict, or any other serializable value.
|
|
213
|
-
|
|
214
|
-
Returns:
|
|
215
|
-
dict: A dictionary representation of the input object, with all nested
|
|
216
|
-
objects also converted to dictionaries.
|
|
217
|
-
|
|
218
|
-
The conversion process:
|
|
219
|
-
1. For table instances: Creates a dictionary with a special class marker
|
|
220
|
-
and converts both list items and dictionary attributes recursively
|
|
221
|
-
2. For lists/tuples: Converts each element recursively and returns as a list
|
|
222
|
-
3. For dictionaries: Converts each value recursively while preserving keys
|
|
223
|
-
4. For other types: Returns the value unchanged
|
|
224
|
-
|
|
225
|
-
This method is particularly useful for serialization purposes, allowing
|
|
226
|
-
complex table structures to be converted to a format suitable for JSON.
|
|
227
|
-
"""
|
|
228
50
|
if isinstance(x, table):
|
|
229
51
|
return {f'__{x.__class__.__name__}__':table.to_dict(x[:])}|table.to_dict(x.__dict__)
|
|
230
52
|
elif isinstance(x,(tuple,list)):
|
|
@@ -235,28 +57,6 @@ class table(list):
|
|
|
235
57
|
return x
|
|
236
58
|
@classmethod
|
|
237
59
|
def from_dict(cls,dct):
|
|
238
|
-
"""
|
|
239
|
-
Reconstruct a table or derived class instance from a dictionary representation.
|
|
240
|
-
|
|
241
|
-
Parameters:
|
|
242
|
-
dct (dict): A dictionary containing the serialized representation of
|
|
243
|
-
a table or derived class instance. The dictionary should include
|
|
244
|
-
a special class marker key (__ClassName__) if it represents a table subclass.
|
|
245
|
-
|
|
246
|
-
Returns:
|
|
247
|
-
table or type: A reconstructed table instance if the dictionary contains
|
|
248
|
-
a class marker, or the original dictionary otherwise.
|
|
249
|
-
|
|
250
|
-
The reconstruction process:
|
|
251
|
-
1. Checks for known table-derived classes in a predefined set
|
|
252
|
-
2. Searches for a special class marker in the dictionary
|
|
253
|
-
3. If found, extracts the list items, removes the marker, and instantiates
|
|
254
|
-
the appropriate class with the list items and remaining dictionary attributes
|
|
255
|
-
4. If no class marker is found, returns the original dictionary
|
|
256
|
-
|
|
257
|
-
This method works as the complement to to_dict, allowing serialized
|
|
258
|
-
table structures to be reconstructed from their dictionary representations.
|
|
259
|
-
"""
|
|
260
60
|
cls = {table,config,expr,flow._tbl}|{cls}
|
|
261
61
|
for i in cls:
|
|
262
62
|
if f'__{i.__name__}__' in dct:
|
|
@@ -265,50 +65,10 @@ class table(list):
|
|
|
265
65
|
return dct
|
|
266
66
|
|
|
267
67
|
class config(table):
|
|
268
|
-
|
|
269
|
-
Configuration management class with JSON file persistence capabilities.
|
|
270
|
-
|
|
271
|
-
The config class extends the table container with methods for loading and
|
|
272
|
-
saving configuration data to JSON files. This provides a convenient way to
|
|
273
|
-
manage application settings, preferences, and other configurable data that
|
|
274
|
-
needs to persist between sessions.
|
|
275
|
-
|
|
276
|
-
Key features:
|
|
277
|
-
- Inherits all the flexible container capabilities of the table class
|
|
278
|
-
- JSON file loading and saving functionality
|
|
279
|
-
- Support for hierarchical configuration inheritance
|
|
280
|
-
- Deep copying with attribute modification for temporary configuration changes
|
|
281
|
-
|
|
282
|
-
Class Attributes:
|
|
283
|
-
root (str): Default directory path for configuration files (default: '../json')
|
|
284
|
-
"""
|
|
285
|
-
# Default directory path for storing and retrieving configuration JSON files
|
|
286
|
-
root = '../json'
|
|
68
|
+
root = '.'
|
|
287
69
|
|
|
288
70
|
@classmethod
|
|
289
71
|
def load(cls, name=None):
|
|
290
|
-
"""
|
|
291
|
-
Load configuration data from a JSON file.
|
|
292
|
-
|
|
293
|
-
Parameters:
|
|
294
|
-
name (str, optional): The name of the configuration file to load.
|
|
295
|
-
If not provided, the class name is used.
|
|
296
|
-
|
|
297
|
-
Returns:
|
|
298
|
-
config: A new config instance populated with the loaded data.
|
|
299
|
-
|
|
300
|
-
Raises:
|
|
301
|
-
FileNotFoundError: If the specified configuration file does not exist
|
|
302
|
-
json.JSONDecodeError: If the file contains invalid JSON
|
|
303
|
-
|
|
304
|
-
The loading process:
|
|
305
|
-
1. Collects configuration data from parent classes (excluding table and config)
|
|
306
|
-
2. Loads data from the specified JSON file
|
|
307
|
-
3. Merges the parent class data with the file data
|
|
308
|
-
4. Reconstructs and returns a config instance using from_dict
|
|
309
|
-
|
|
310
|
-
The file path is constructed as: {config.root}/{cls.__module__}.{name or cls.__name__}.json
|
|
311
|
-
"""
|
|
312
72
|
import json
|
|
313
73
|
dct = {}
|
|
314
74
|
for i in cls.__bases__:
|
|
@@ -324,30 +84,6 @@ class config(table):
|
|
|
324
84
|
return val
|
|
325
85
|
|
|
326
86
|
def save(self, *args):
|
|
327
|
-
"""
|
|
328
|
-
Save configuration data to JSON files.
|
|
329
|
-
|
|
330
|
-
Parameters:
|
|
331
|
-
*args: Classes or instances to save. If not provided, saves for all
|
|
332
|
-
parent classes and the instance itself.
|
|
333
|
-
|
|
334
|
-
Raises:
|
|
335
|
-
IOError: If there are issues writing to the file system
|
|
336
|
-
TypeError: If the data cannot be serialized to JSON
|
|
337
|
-
|
|
338
|
-
The saving process:
|
|
339
|
-
1. If no arguments are provided, determines the save targets from the
|
|
340
|
-
class hierarchy (excluding object, type, and immediate parents)
|
|
341
|
-
2. Creates a copy of the instance dictionary
|
|
342
|
-
3. For each target class/instance:
|
|
343
|
-
- Constructs the file path based on module and class/instance name
|
|
344
|
-
- For class targets: Only saves attributes defined in class annotations
|
|
345
|
-
- For instance targets: Saves all attributes
|
|
346
|
-
- Adds a special class marker for potential future reconstruction
|
|
347
|
-
- Writes the data to a JSON file
|
|
348
|
-
|
|
349
|
-
The file path format is: {config.root}/{target.__module__}.{target_name}.json
|
|
350
|
-
"""
|
|
351
87
|
import json
|
|
352
88
|
if len(args) == 0:
|
|
353
89
|
args = self.__class__.__mro__[::-1][4:-1] + (self,)
|
|
@@ -360,26 +96,6 @@ class config(table):
|
|
|
360
96
|
json.dump(dct|{f'__{i.__class__.__name__}__':[]},f)
|
|
361
97
|
|
|
362
98
|
def __call__(self,*args,**kwargs):
|
|
363
|
-
"""
|
|
364
|
-
Create a modified deep copy of the configuration or execute a custom callable.
|
|
365
|
-
|
|
366
|
-
Parameters:
|
|
367
|
-
*args: Positional arguments for the custom callable
|
|
368
|
-
**kwargs: Keyword arguments to modify in the copied configuration
|
|
369
|
-
|
|
370
|
-
Returns:
|
|
371
|
-
- Result of the custom __call__ function if defined
|
|
372
|
-
- A deep copy of the configuration with modified attributes if no custom callable exists
|
|
373
|
-
|
|
374
|
-
The method operates in two modes:
|
|
375
|
-
1. Custom function execution: If a '__call__' attribute exists and is callable,
|
|
376
|
-
it is executed with the configuration as the first argument
|
|
377
|
-
2. Deep copy mode: Creates a deep copy of the configuration and updates its
|
|
378
|
-
attributes with the provided keyword arguments
|
|
379
|
-
|
|
380
|
-
This method is particularly useful for creating temporary configuration
|
|
381
|
-
variations while preserving the original configuration intact.
|
|
382
|
-
"""
|
|
383
99
|
func = self.__dict__.get('__call__',None)
|
|
384
100
|
if func is not None:
|
|
385
101
|
return func(self,*args,**kwargs)
|
|
@@ -392,30 +108,6 @@ class config(table):
|
|
|
392
108
|
import operator
|
|
393
109
|
|
|
394
110
|
def equal(x, y):
|
|
395
|
-
"""
|
|
396
|
-
Deep equality comparison for complex data structures.
|
|
397
|
-
|
|
398
|
-
Parameters:
|
|
399
|
-
x: First object to compare
|
|
400
|
-
y: Second object to compare
|
|
401
|
-
|
|
402
|
-
Returns:
|
|
403
|
-
bool: True if x and y are deeply equal, False otherwise
|
|
404
|
-
|
|
405
|
-
This function performs a recursive deep comparison between two objects,
|
|
406
|
-
handling nested structures like lists, tuples, dictionaries, and table instances.
|
|
407
|
-
|
|
408
|
-
The comparison process:
|
|
409
|
-
1. Checks if x and y are of the same type
|
|
410
|
-
2. For objects with __getitem__ method (like tables), gets their items
|
|
411
|
-
3. For tuples, lists, and dictionaries, performs element-wise recursive comparison:
|
|
412
|
-
- For dictionaries: Checks that all keys in x exist in y and have equal values
|
|
413
|
-
- For sequences: Checks that all corresponding elements are equal
|
|
414
|
-
4. For other types, falls back to the standard == operator
|
|
415
|
-
|
|
416
|
-
This function is particularly useful for comparing complex nested data structures
|
|
417
|
-
where shallow comparison (using ==) would not be sufficient.
|
|
418
|
-
"""
|
|
419
111
|
if type(x) != type(y):
|
|
420
112
|
return False
|
|
421
113
|
if getattr(x,'__getitem__',None) is not None:
|
|
@@ -436,44 +128,7 @@ def equal(x, y):
|
|
|
436
128
|
return x == y
|
|
437
129
|
|
|
438
130
|
class expr(table):
|
|
439
|
-
"""
|
|
440
|
-
Expression evaluation system with comprehensive operator support.
|
|
441
|
-
|
|
442
|
-
The expr class extends the table container to provide a powerful expression
|
|
443
|
-
evaluation system. It allows for the construction and evaluation of symbolic
|
|
444
|
-
expressions with support for attribute access, item access, method calls,
|
|
445
|
-
and a wide range of operators.
|
|
446
|
-
|
|
447
|
-
Key features:
|
|
448
|
-
- Chainable attribute and item access for building complex expressions
|
|
449
|
-
- Comprehensive operator overloading for arithmetic and comparison operations
|
|
450
|
-
- Lazy evaluation of expressions
|
|
451
|
-
- Support for nested expressions and function calls
|
|
452
|
-
- Self-referential expression handling
|
|
453
|
-
|
|
454
|
-
This class forms the core of the expression evaluation system, enabling
|
|
455
|
-
concise and powerful expression building for various assembly and configuration tasks.
|
|
456
|
-
"""
|
|
457
131
|
def __getitem__(self, key):
|
|
458
|
-
"""
|
|
459
|
-
Get an item from the expression or extend the expression chain.
|
|
460
|
-
|
|
461
|
-
Parameters:
|
|
462
|
-
key: The key/index to access or add to the expression chain.
|
|
463
|
-
If a slice, it accesses list items; otherwise, it extends the expression.
|
|
464
|
-
|
|
465
|
-
Returns:
|
|
466
|
-
- List items if key is a slice
|
|
467
|
-
- A new expr instance with the key appended to the expression chain
|
|
468
|
-
|
|
469
|
-
This method has dual functionality:
|
|
470
|
-
1. If the key is a full slice (:), it returns the underlying list items
|
|
471
|
-
2. Otherwise, it creates a new expression by appending the key to the current expression
|
|
472
|
-
|
|
473
|
-
Special handling for self-references:
|
|
474
|
-
- If the expression contains a 'self' attribute, it preserves this attribute
|
|
475
|
-
in the new expression while temporarily removing it during construction
|
|
476
|
-
"""
|
|
477
132
|
if type(key) is slice and key == slice(None,None,None):
|
|
478
133
|
return super().__getitem__(key)
|
|
479
134
|
dct = self.__dict__
|
|
@@ -486,44 +141,8 @@ class expr(table):
|
|
|
486
141
|
else:
|
|
487
142
|
return self.__class__(*self,key,**dct)
|
|
488
143
|
def __getattr__(self, key):
|
|
489
|
-
"""
|
|
490
|
-
Extend the expression chain with attribute access or handle special cases.
|
|
491
|
-
|
|
492
|
-
Parameters:
|
|
493
|
-
key: The attribute name to access
|
|
494
|
-
|
|
495
|
-
Returns:
|
|
496
|
-
- None if the key starts with '_' or is one of the special method names
|
|
497
|
-
- A new expr instance with the attribute name appended to the expression chain otherwise
|
|
498
|
-
|
|
499
|
-
This method handles attribute access for the expression system, with special behavior for:
|
|
500
|
-
1. Special methods and attributes (starting with '_'): Returns None to avoid conflicts
|
|
501
|
-
2. Known special method names: Returns None for methods like 'compute', 'getdoc', etc.
|
|
502
|
-
3. Regular attribute access: Extends the expression chain by calling self[key]
|
|
503
|
-
|
|
504
|
-
This allows for elegant expression building with attribute chaining while avoiding
|
|
505
|
-
conflicts with Python's internal methods and handling special method cases appropriately.
|
|
506
|
-
"""
|
|
507
144
|
return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
|
|
508
145
|
def __repr__(self):
|
|
509
|
-
"""
|
|
510
|
-
Return a string representation of the expression.
|
|
511
|
-
|
|
512
|
-
Returns:
|
|
513
|
-
str: A string representation of the expression in a human-readable format
|
|
514
|
-
that shows the expression's structure and components.
|
|
515
|
-
|
|
516
|
-
The representation depends on the expression's content:
|
|
517
|
-
- Empty expressions return 'expr()'
|
|
518
|
-
- Symbolic expressions (starting with None) begin with 'sym'
|
|
519
|
-
- Regular expressions begin with 'expr(value)'
|
|
520
|
-
- String components are appended with dot notation (e.g., '.attribute')
|
|
521
|
-
- Table components are appended as function calls (e.g., '(args)')
|
|
522
|
-
- Other components are appended as index access (e.g., '[index]')
|
|
523
|
-
|
|
524
|
-
This method helps with debugging and visualization of complex expressions
|
|
525
|
-
by creating a clear textual representation of the expression chain.
|
|
526
|
-
"""
|
|
527
146
|
if len(self) == 0:
|
|
528
147
|
return 'expr()'
|
|
529
148
|
line = 'sym' if self[:][0] is None else 'expr('+pformat(self[:][0])+')'
|
|
@@ -536,30 +155,6 @@ class expr(table):
|
|
|
536
155
|
line += f'[{i}]'
|
|
537
156
|
return line[1:] if line.startswith('.') else line
|
|
538
157
|
def __call__(self, *args, **kwargs):
|
|
539
|
-
"""
|
|
540
|
-
Evaluate the expression with the provided arguments.
|
|
541
|
-
|
|
542
|
-
Parameters:
|
|
543
|
-
*args: Arguments to be used during evaluation (not used in the current implementation)
|
|
544
|
-
**kwargs: Keyword arguments to be used during evaluation (not used in the current implementation)
|
|
545
|
-
|
|
546
|
-
Returns:
|
|
547
|
-
The result of evaluating the expression chain
|
|
548
|
-
|
|
549
|
-
This method evaluates the expression by processing each element in the expression chain:
|
|
550
|
-
1. Starts with the initial value (first element of the chain)
|
|
551
|
-
2. For each subsequent element in the chain:
|
|
552
|
-
- Evaluates any nested expressions in the current element
|
|
553
|
-
- Applies the appropriate operation based on the element type:
|
|
554
|
-
- If string: Performs attribute access
|
|
555
|
-
- If table: Performs function call with arguments from the table
|
|
556
|
-
- Otherwise: Performs item/index access
|
|
557
|
-
3. Handles self-referential expressions through the 'self' attribute
|
|
558
|
-
4. Provides error recovery by converting exceptions into new expression nodes when appropriate
|
|
559
|
-
|
|
560
|
-
The evaluation process supports complex nested expressions and maintains proper context for
|
|
561
|
-
expressions that reference themselves through the 'self' attribute.
|
|
562
|
-
"""
|
|
563
158
|
r = self[:][0]
|
|
564
159
|
body = self[:][1:]
|
|
565
160
|
body.append(table(*args,**kwargs))
|
|
@@ -632,503 +227,101 @@ class expr(table):
|
|
|
632
227
|
#print(self[:],args,kwargs,self.__dict__,r)
|
|
633
228
|
return r
|
|
634
229
|
def __lt__(a, b):
|
|
635
|
-
"""
|
|
636
|
-
Create a new expression representing less than comparison of a and b.
|
|
637
|
-
|
|
638
|
-
Parameters:
|
|
639
|
-
a: The left operand for comparison
|
|
640
|
-
b: The right operand for comparison
|
|
641
|
-
|
|
642
|
-
Returns:
|
|
643
|
-
expr: A new expression that evaluates to a < b
|
|
644
|
-
"""
|
|
645
230
|
return a.__class__(operator.__lt__,table(a,b))
|
|
646
231
|
def __le__(a, b):
|
|
647
|
-
"""
|
|
648
|
-
Create a new expression representing less than or equal comparison of a and b.
|
|
649
|
-
|
|
650
|
-
Parameters:
|
|
651
|
-
a: The left operand for comparison
|
|
652
|
-
b: The right operand for comparison
|
|
653
|
-
|
|
654
|
-
Returns:
|
|
655
|
-
expr: A new expression that evaluates to a <= b
|
|
656
|
-
"""
|
|
657
232
|
return a.__class__(operator.__le__,table(a,b))
|
|
658
233
|
def __eq__(a, b):
|
|
659
|
-
"""
|
|
660
|
-
Create a new expression representing equality comparison of a and b.
|
|
661
|
-
|
|
662
|
-
Parameters:
|
|
663
|
-
a: The left operand for comparison
|
|
664
|
-
b: The right operand for comparison
|
|
665
|
-
|
|
666
|
-
Returns:
|
|
667
|
-
expr: A new expression that evaluates to a == b
|
|
668
|
-
"""
|
|
669
234
|
return a.__class__(operator.__eq__,table(a,b))
|
|
670
235
|
def __ne__(a, b):
|
|
671
|
-
"""
|
|
672
|
-
Create a new expression representing inequality comparison of a and b.
|
|
673
|
-
|
|
674
|
-
Parameters:
|
|
675
|
-
a: The left operand for comparison
|
|
676
|
-
b: The right operand for comparison
|
|
677
|
-
|
|
678
|
-
Returns:
|
|
679
|
-
expr: A new expression that evaluates to a != b
|
|
680
|
-
"""
|
|
681
236
|
return a.__class__(operator.__ne__,table(a,b))
|
|
682
237
|
def __ge__(a, b):
|
|
683
|
-
"""
|
|
684
|
-
Create a new expression representing greater than or equal comparison of a and b.
|
|
685
|
-
|
|
686
|
-
Parameters:
|
|
687
|
-
a: The left operand for comparison
|
|
688
|
-
b: The right operand for comparison
|
|
689
|
-
|
|
690
|
-
Returns:
|
|
691
|
-
expr: A new expression that evaluates to a >= b
|
|
692
|
-
"""
|
|
693
238
|
return a.__class__(operator.__ge__,table(a,b))
|
|
694
239
|
def __gt__(a, b):
|
|
695
|
-
"""
|
|
696
|
-
Create a new expression representing greater than comparison of a and b.
|
|
697
|
-
|
|
698
|
-
Parameters:
|
|
699
|
-
a: The left operand for comparison
|
|
700
|
-
b: The right operand for comparison
|
|
701
|
-
|
|
702
|
-
Returns:
|
|
703
|
-
expr: A new expression that evaluates to a > b
|
|
704
|
-
"""
|
|
705
240
|
return a.__class__(operator.__gt__,table(a,b))
|
|
706
241
|
def __not__(a):
|
|
707
|
-
"""
|
|
708
|
-
Create a new expression representing logical NOT of a.
|
|
709
|
-
|
|
710
|
-
Parameters:
|
|
711
|
-
a: The operand for logical NOT
|
|
712
|
-
|
|
713
|
-
Returns:
|
|
714
|
-
expr: A new expression that evaluates to not a
|
|
715
|
-
"""
|
|
716
242
|
return a.__class__(operator.__not__,table(a))
|
|
717
243
|
def __abs__(a):
|
|
718
|
-
"""
|
|
719
|
-
Create a new expression representing absolute value of a.
|
|
720
|
-
|
|
721
|
-
Parameters:
|
|
722
|
-
a: The operand for absolute value
|
|
723
|
-
|
|
724
|
-
Returns:
|
|
725
|
-
expr: A new expression that evaluates to abs(a)
|
|
726
|
-
"""
|
|
727
244
|
return a.__class__(operator.__abs__,table(a))
|
|
728
245
|
def __round__(a):
|
|
729
|
-
"""
|
|
730
|
-
Create a new expression representing rounding of a.
|
|
731
|
-
|
|
732
|
-
Parameters:
|
|
733
|
-
a: The operand for rounding
|
|
734
|
-
|
|
735
|
-
Returns:
|
|
736
|
-
expr: A new expression that evaluates to round(a)
|
|
737
|
-
"""
|
|
738
246
|
return a.__class__(round,table(a))
|
|
739
247
|
def __add__(a, b):
|
|
740
|
-
"""
|
|
741
|
-
Create a new expression representing addition of a and b.
|
|
742
|
-
|
|
743
|
-
Parameters:
|
|
744
|
-
a: The left operand for addition
|
|
745
|
-
b: The right operand for addition
|
|
746
|
-
|
|
747
|
-
Returns:
|
|
748
|
-
expr: A new expression that evaluates to a + b
|
|
749
|
-
"""
|
|
750
248
|
return plus(a,b)
|
|
751
249
|
def __radd__(a, b):
|
|
752
|
-
"""
|
|
753
|
-
Create a new expression representing reverse addition of b and a.
|
|
754
|
-
|
|
755
|
-
Parameters:
|
|
756
|
-
a: The right operand for addition
|
|
757
|
-
b: The left operand for addition
|
|
758
|
-
|
|
759
|
-
Returns:
|
|
760
|
-
expr: A new expression that evaluates to b + a
|
|
761
|
-
"""
|
|
762
250
|
return plus(b,a)
|
|
763
251
|
def __iadd__(a, b):
|
|
764
|
-
"""
|
|
765
|
-
Create a new expression representing in-place addition of a and b.
|
|
766
|
-
|
|
767
|
-
Parameters:
|
|
768
|
-
a: The left operand for addition
|
|
769
|
-
b: The right operand for addition
|
|
770
|
-
|
|
771
|
-
Returns:
|
|
772
|
-
expr: A new expression that evaluates to a + b
|
|
773
|
-
"""
|
|
774
252
|
return plus(a,b)
|
|
775
253
|
def __and__(a, b):
|
|
776
|
-
"""
|
|
777
|
-
Create a new expression representing bitwise AND of a and b.
|
|
778
|
-
|
|
779
|
-
Parameters:
|
|
780
|
-
a: The left operand for bitwise AND
|
|
781
|
-
b: The right operand for bitwise AND
|
|
782
|
-
|
|
783
|
-
Returns:
|
|
784
|
-
expr: A new expression that evaluates to a & b
|
|
785
|
-
"""
|
|
786
254
|
return a.__class__(operator.__and__,table(a,b))
|
|
787
255
|
def __rand__(a, b):
|
|
788
|
-
"""
|
|
789
|
-
Create a new expression representing reverse bitwise AND of b and a.
|
|
790
|
-
|
|
791
|
-
Parameters:
|
|
792
|
-
a: The right operand for bitwise AND
|
|
793
|
-
b: The left operand for bitwise AND
|
|
794
|
-
|
|
795
|
-
Returns:
|
|
796
|
-
expr: A new expression that evaluates to b & a
|
|
797
|
-
"""
|
|
798
256
|
return a.__class__(operator.__and__,table(b,a))
|
|
799
257
|
def __floordiv__(a, b):
|
|
800
|
-
"""
|
|
801
|
-
Create a new expression representing floor division of a by b.
|
|
802
|
-
|
|
803
|
-
Parameters:
|
|
804
|
-
a: The dividend
|
|
805
|
-
b: The divisor
|
|
806
|
-
|
|
807
|
-
Returns:
|
|
808
|
-
expr: A new expression that evaluates to a // b
|
|
809
|
-
"""
|
|
810
258
|
return a.__class__(operator.__floordiv__,table(a,b))
|
|
811
259
|
def __rfloordiv__(a, b):
|
|
812
|
-
"""
|
|
813
|
-
Create a new expression representing reverse floor division of b by a.
|
|
814
|
-
|
|
815
|
-
Parameters:
|
|
816
|
-
a: The divisor
|
|
817
|
-
b: The dividend
|
|
818
|
-
|
|
819
|
-
Returns:
|
|
820
|
-
expr: A new expression that evaluates to b // a
|
|
821
|
-
"""
|
|
822
260
|
return a.__class__(operator.__floordiv__,table(b,a))
|
|
823
261
|
def __inv__(a):
|
|
824
|
-
"""
|
|
825
|
-
Create a new expression representing bitwise inversion of a.
|
|
826
|
-
|
|
827
|
-
Parameters:
|
|
828
|
-
a: The operand for bitwise inversion
|
|
829
|
-
|
|
830
|
-
Returns:
|
|
831
|
-
expr: A new expression that evaluates to ~a
|
|
832
|
-
"""
|
|
833
262
|
return a.__class__(operator.__inv__,table(a))
|
|
834
263
|
def __invert__(a):
|
|
835
|
-
"""
|
|
836
|
-
Create a new expression representing bitwise NOT of a.
|
|
837
|
-
|
|
838
|
-
Parameters:
|
|
839
|
-
a: The operand for bitwise NOT
|
|
840
|
-
|
|
841
|
-
Returns:
|
|
842
|
-
expr: A new expression that evaluates to ~a
|
|
843
|
-
"""
|
|
844
264
|
return a.__class__(operator.__invert__,table(a))
|
|
845
265
|
def __lshift__(a, b):
|
|
846
|
-
"""
|
|
847
|
-
Create a new expression representing bitwise left shift of a by b.
|
|
848
|
-
|
|
849
|
-
Parameters:
|
|
850
|
-
a: The value to be shifted
|
|
851
|
-
b: The number of positions to shift
|
|
852
|
-
|
|
853
|
-
Returns:
|
|
854
|
-
expr: A new expression that evaluates to a << b
|
|
855
|
-
"""
|
|
856
266
|
return a.__class__(operator.__lshift__,table(a,b))
|
|
857
267
|
def __rlshift__(a, b):
|
|
858
|
-
"""
|
|
859
|
-
Create a new expression representing reverse bitwise left shift of b by a.
|
|
860
|
-
|
|
861
|
-
Parameters:
|
|
862
|
-
a: The number of positions to shift
|
|
863
|
-
b: The value to be shifted
|
|
864
|
-
|
|
865
|
-
Returns:
|
|
866
|
-
expr: A new expression that evaluates to b << a
|
|
867
|
-
"""
|
|
868
268
|
return a.__class__(operator.__lshift__,table(b,a))
|
|
869
269
|
def __mod__(a, b):
|
|
870
|
-
"""
|
|
871
|
-
Create a new expression representing modulo operation of a by b.
|
|
872
|
-
|
|
873
|
-
Parameters:
|
|
874
|
-
a: The dividend
|
|
875
|
-
b: The divisor
|
|
876
|
-
|
|
877
|
-
Returns:
|
|
878
|
-
expr: A new expression that evaluates to a % b
|
|
879
|
-
"""
|
|
880
270
|
return a.__class__(operator.__mod__,table(a,b))
|
|
881
271
|
def __rmod__(a, b):
|
|
882
|
-
"""
|
|
883
|
-
Create a new expression representing reverse modulo operation of b by a.
|
|
884
|
-
|
|
885
|
-
Parameters:
|
|
886
|
-
a: The divisor
|
|
887
|
-
b: The dividend
|
|
888
|
-
|
|
889
|
-
Returns:
|
|
890
|
-
expr: A new expression that evaluates to b % a
|
|
891
|
-
"""
|
|
892
272
|
return a.__class__(operator.__mod__,table(b,a))
|
|
893
273
|
def __mul__(a, b):
|
|
894
|
-
"""
|
|
895
|
-
Create a new expression representing multiplication of a and b.
|
|
896
|
-
|
|
897
|
-
Parameters:
|
|
898
|
-
a: The left operand for multiplication
|
|
899
|
-
b: The right operand for multiplication
|
|
900
|
-
|
|
901
|
-
Returns:
|
|
902
|
-
expr: A new expression that evaluates to a * b
|
|
903
|
-
"""
|
|
904
274
|
return a.__class__(operator.__mul__,table(a,b))
|
|
905
275
|
def __rmul__(a, b):
|
|
906
|
-
"""
|
|
907
|
-
Create a new expression representing reverse multiplication of b and a.
|
|
908
|
-
|
|
909
|
-
Parameters:
|
|
910
|
-
a: The right operand for multiplication
|
|
911
|
-
b: The left operand for multiplication
|
|
912
|
-
|
|
913
|
-
Returns:
|
|
914
|
-
expr: A new expression that evaluates to b * a
|
|
915
|
-
"""
|
|
916
276
|
return a.__class__(operator.__mul__,table(b,a))
|
|
917
277
|
def __matmul__(a, b):
|
|
918
|
-
"""
|
|
919
|
-
Create a new expression representing matrix multiplication of a and b.
|
|
920
|
-
|
|
921
|
-
Parameters:
|
|
922
|
-
a: The left operand for matrix multiplication
|
|
923
|
-
b: The right operand for matrix multiplication
|
|
924
|
-
|
|
925
|
-
Returns:
|
|
926
|
-
expr: A new expression that evaluates to a @ b
|
|
927
|
-
"""
|
|
928
278
|
return a.__class__(operator.__matmul__,table(a,b))
|
|
929
279
|
def __rmatmul__(a, b):
|
|
930
|
-
"""
|
|
931
|
-
Create a new expression representing reverse matrix multiplication of b and a.
|
|
932
|
-
|
|
933
|
-
Parameters:
|
|
934
|
-
a: The right operand for matrix multiplication
|
|
935
|
-
b: The left operand for matrix multiplication
|
|
936
|
-
|
|
937
|
-
Returns:
|
|
938
|
-
expr: A new expression that evaluates to b @ a
|
|
939
|
-
"""
|
|
940
280
|
return a.__class__(operator.__matmul__,table(b,a))
|
|
941
281
|
def __neg__(a):
|
|
942
|
-
"""
|
|
943
|
-
Create a new expression representing unary negation of a.
|
|
944
|
-
|
|
945
|
-
Parameters:
|
|
946
|
-
a: The operand for unary negation
|
|
947
|
-
|
|
948
|
-
Returns:
|
|
949
|
-
expr: A new expression that evaluates to -a
|
|
950
|
-
"""
|
|
951
282
|
return uminus(a)
|
|
952
283
|
def __or__(a, b):
|
|
953
|
-
"""
|
|
954
|
-
Create a new expression representing bitwise OR of a and b.
|
|
955
|
-
|
|
956
|
-
Parameters:
|
|
957
|
-
a: The left operand for bitwise OR
|
|
958
|
-
b: The right operand for bitwise OR
|
|
959
|
-
|
|
960
|
-
Returns:
|
|
961
|
-
expr: A new expression that evaluates to a | b
|
|
962
|
-
"""
|
|
963
284
|
return a.__class__(operator.__or__,table(a,b))
|
|
964
285
|
def __ror__(a, b):
|
|
965
|
-
"""
|
|
966
|
-
Create a new expression representing reverse bitwise OR of b and a.
|
|
967
|
-
|
|
968
|
-
Parameters:
|
|
969
|
-
a: The right operand for bitwise OR
|
|
970
|
-
b: The left operand for bitwise OR
|
|
971
|
-
|
|
972
|
-
Returns:
|
|
973
|
-
expr: A new expression that evaluates to b | a
|
|
974
|
-
"""
|
|
975
286
|
return a.__class__(operator.__or__,table(b,a))
|
|
976
287
|
def __pos__(a):
|
|
977
|
-
"""
|
|
978
|
-
Create a new expression representing unary plus of a.
|
|
979
|
-
|
|
980
|
-
Parameters:
|
|
981
|
-
a: The operand for unary plus
|
|
982
|
-
|
|
983
|
-
Returns:
|
|
984
|
-
expr: A new expression that evaluates to +a
|
|
985
|
-
"""
|
|
986
288
|
return uplus(a)
|
|
987
289
|
def __pow__(a, b):
|
|
988
|
-
"""
|
|
989
|
-
Create a new expression representing exponentiation of a to the power of b.
|
|
990
|
-
|
|
991
|
-
Parameters:
|
|
992
|
-
a: The base
|
|
993
|
-
b: The exponent
|
|
994
|
-
|
|
995
|
-
Returns:
|
|
996
|
-
expr: A new expression that evaluates to a ** b
|
|
997
|
-
"""
|
|
998
290
|
return a.__class__(operator.__pow__,table(a,b))
|
|
999
291
|
def __rpow__(a, b):
|
|
1000
|
-
"""
|
|
1001
|
-
Create a new expression representing reverse exponentiation of b to the power of a.
|
|
1002
|
-
|
|
1003
|
-
Parameters:
|
|
1004
|
-
a: The exponent
|
|
1005
|
-
b: The base
|
|
1006
|
-
|
|
1007
|
-
Returns:
|
|
1008
|
-
expr: A new expression that evaluates to b ** a
|
|
1009
|
-
"""
|
|
1010
292
|
return a.__class__(operator.__pow__,table(b,a))
|
|
1011
293
|
def __rshift__(a, b):
|
|
1012
|
-
"""
|
|
1013
|
-
Create a new expression representing bitwise right shift of a by b.
|
|
1014
|
-
|
|
1015
|
-
Parameters:
|
|
1016
|
-
a: The value to be shifted
|
|
1017
|
-
b: The number of positions to shift
|
|
1018
|
-
|
|
1019
|
-
Returns:
|
|
1020
|
-
expr: A new expression that evaluates to a >> b
|
|
1021
|
-
"""
|
|
1022
294
|
return a.__class__(operator.__rshift__,table(a,b))
|
|
1023
295
|
def __rrshift__(a, b):
|
|
1024
|
-
"""
|
|
1025
|
-
Create a new expression representing reverse bitwise right shift of b by a.
|
|
1026
|
-
|
|
1027
|
-
Parameters:
|
|
1028
|
-
a: The number of positions to shift
|
|
1029
|
-
b: The value to be shifted
|
|
1030
|
-
|
|
1031
|
-
Returns:
|
|
1032
|
-
expr: A new expression that evaluates to b >> a
|
|
1033
|
-
"""
|
|
1034
296
|
return a.__class__(operator.__rshift__,table(b,a))
|
|
1035
297
|
def __sub__(a, b):
|
|
1036
|
-
"""
|
|
1037
|
-
Create a new expression representing subtraction of b from a.
|
|
1038
|
-
|
|
1039
|
-
Parameters:
|
|
1040
|
-
a: The minuend
|
|
1041
|
-
b: The subtrahend
|
|
1042
|
-
|
|
1043
|
-
Returns:
|
|
1044
|
-
expr: A new expression that evaluates to a - b
|
|
1045
|
-
"""
|
|
1046
298
|
return minus(a,b)
|
|
1047
299
|
def __rsub__(a, b):
|
|
1048
|
-
"""
|
|
1049
|
-
Create a new expression representing reverse subtraction of a from b.
|
|
1050
|
-
|
|
1051
|
-
Parameters:
|
|
1052
|
-
a: The subtrahend
|
|
1053
|
-
b: The minuend
|
|
1054
|
-
|
|
1055
|
-
Returns:
|
|
1056
|
-
expr: A new expression that evaluates to b - a
|
|
1057
|
-
"""
|
|
1058
300
|
return minus(b,a)
|
|
1059
301
|
def __truediv__(a, b):
|
|
1060
|
-
"""
|
|
1061
|
-
Create a new expression representing true division of a by b.
|
|
1062
|
-
|
|
1063
|
-
Parameters:
|
|
1064
|
-
a: The dividend
|
|
1065
|
-
b: The divisor
|
|
1066
|
-
|
|
1067
|
-
Returns:
|
|
1068
|
-
expr: A new expression that evaluates to a / b (floating point)
|
|
1069
|
-
"""
|
|
1070
302
|
return a.__class__(operator.__truediv__,table(a,b))
|
|
1071
303
|
def __rtruediv__(a, b):
|
|
1072
|
-
"""
|
|
1073
|
-
Create a new expression representing reverse true division of b by a.
|
|
1074
|
-
|
|
1075
|
-
Parameters:
|
|
1076
|
-
a: The divisor
|
|
1077
|
-
b: The dividend
|
|
1078
|
-
|
|
1079
|
-
Returns:
|
|
1080
|
-
expr: A new expression that evaluates to b / a (floating point)
|
|
1081
|
-
"""
|
|
1082
304
|
return a.__class__(operator.__truediv__,table(b,a))
|
|
1083
305
|
def __xor__(a, b):
|
|
1084
|
-
"""
|
|
1085
|
-
Create a new expression representing bitwise XOR of a and b.
|
|
1086
|
-
|
|
1087
|
-
Parameters:
|
|
1088
|
-
a: The left operand for bitwise XOR
|
|
1089
|
-
b: The right operand for bitwise XOR
|
|
1090
|
-
|
|
1091
|
-
Returns:
|
|
1092
|
-
expr: A new expression that evaluates to a ^ b
|
|
1093
|
-
"""
|
|
1094
306
|
return a.__class__(operator.__xor__,table(a,b))
|
|
1095
307
|
def __rxor__(a, b):
|
|
1096
|
-
"""
|
|
1097
|
-
Create a new expression representing reverse bitwise XOR of b and a.
|
|
1098
|
-
|
|
1099
|
-
Parameters:
|
|
1100
|
-
a: The right operand for bitwise XOR
|
|
1101
|
-
b: The left operand for bitwise XOR
|
|
1102
|
-
|
|
1103
|
-
Returns:
|
|
1104
|
-
expr: A new expression that evaluates to b ^ a
|
|
1105
|
-
"""
|
|
1106
308
|
return a.__class__(operator.__xor__,table(b,a))
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
309
|
+
|
|
310
|
+
def subs(obj, **kwargs):
|
|
311
|
+
if type(obj) in (tuple,list):
|
|
312
|
+
return type(obj)([subs(i,**kwargs) for i in obj])
|
|
313
|
+
elif type(obj) is dict:
|
|
314
|
+
return {k:subs(v,**kwargs) for k,v in obj.items()}
|
|
315
|
+
elif type(obj) is expr:
|
|
316
|
+
return expr(*obj[:],**obj.__dict__,**kwargs)()
|
|
317
|
+
elif isinstance(obj,table):
|
|
318
|
+
return obj.__class__(*subs(obj[:],**kwargs),**subs(obj.__dict__,**kwargs))
|
|
319
|
+
else:
|
|
320
|
+
return obj
|
|
321
|
+
|
|
322
|
+
sym = expr(None)
|
|
1110
323
|
|
|
1111
324
|
class plus_minus:
|
|
1112
|
-
"""Plus and Minus operation handler for symbolic and numeric expressions.
|
|
1113
|
-
|
|
1114
|
-
This class handles both unary and binary arithmetic operations (addition and subtraction)
|
|
1115
|
-
for symbolic expressions and numeric values. It implements intelligent expression
|
|
1116
|
-
simplification and proper handling of mixed symbolic and numeric operands.
|
|
1117
|
-
|
|
1118
|
-
Key features:
|
|
1119
|
-
- Handles unary operations (uplus, uminus) with single arguments
|
|
1120
|
-
- Handles binary operations (plus, minus) with two arguments
|
|
1121
|
-
- Supports mixed operand types (int, float, expr)
|
|
1122
|
-
- Performs expression simplification by combining numeric terms
|
|
1123
|
-
- Properly propagates unary minus through nested expressions
|
|
1124
|
-
- Maintains symbolic structure for non-numeric operations
|
|
1125
|
-
|
|
1126
|
-
The class is instantiated as four global instances:
|
|
1127
|
-
- plus: Binary addition operator
|
|
1128
|
-
- minus: Binary subtraction operator
|
|
1129
|
-
- uplus: Unary plus operator (identity)
|
|
1130
|
-
- uminus: Unary minus operator (negation)
|
|
1131
|
-
"""
|
|
1132
325
|
def __init__(self,name):
|
|
1133
326
|
self._name = name
|
|
1134
327
|
def __repr__(self):
|
|
@@ -1190,25 +383,6 @@ class context_switch:
|
|
|
1190
383
|
self.ctx <= self.top
|
|
1191
384
|
|
|
1192
385
|
class context:
|
|
1193
|
-
"""
|
|
1194
|
-
Context management class with stack-based scoping and attribute forwarding.
|
|
1195
|
-
|
|
1196
|
-
The context class provides a stack-based scoping mechanism that allows
|
|
1197
|
-
for pushing and popping context frames. It forwards attribute and item
|
|
1198
|
-
access operations to the top of the stack, while maintaining a stack of
|
|
1199
|
-
context objects for nested scoping.
|
|
1200
|
-
|
|
1201
|
-
Key features:
|
|
1202
|
-
- Stack-based context management with push/pop functionality
|
|
1203
|
-
- Attribute and item forwarding to the top context frame
|
|
1204
|
-
- Context switching support via operator overloading
|
|
1205
|
-
- Automatic context creation and cleanup with __enter__/__exit__
|
|
1206
|
-
- Customizable table type for context frames
|
|
1207
|
-
|
|
1208
|
-
This class is particularly useful for creating nested scopes where
|
|
1209
|
-
variables can be temporarily shadowed or modified, with automatic
|
|
1210
|
-
restoration when exiting the scope.
|
|
1211
|
-
"""
|
|
1212
386
|
def __init__(self,*args,**kwargs):
|
|
1213
387
|
tbl = kwargs.pop('table',table)
|
|
1214
388
|
object.__setattr__(self,'_tbl',tbl)
|
|
@@ -1245,24 +419,6 @@ class context:
|
|
|
1245
419
|
self._stk.pop()
|
|
1246
420
|
|
|
1247
421
|
class flow(table):
|
|
1248
|
-
"""
|
|
1249
|
-
Flow control container with dynamic attribute and item access.
|
|
1250
|
-
|
|
1251
|
-
The flow class extends the table container to provide a specialized
|
|
1252
|
-
container for managing flow control structures. It features dynamic
|
|
1253
|
-
attribute and item access with auto-vivification - creating new flow
|
|
1254
|
-
instances on-demand when accessing non-existent keys.
|
|
1255
|
-
|
|
1256
|
-
Key features:
|
|
1257
|
-
- Auto-vivification: Creates new flow instances for non-existent keys
|
|
1258
|
-
- Unified attribute and item access
|
|
1259
|
-
- String-based key normalization
|
|
1260
|
-
- Special handling for reserved attributes
|
|
1261
|
-
- Compatibility with table operations
|
|
1262
|
-
|
|
1263
|
-
This class is designed to facilitate the creation of tree-like structures
|
|
1264
|
-
for flow control, where nodes can be dynamically created as needed.
|
|
1265
|
-
"""
|
|
1266
422
|
def __getitem__(self, key):
|
|
1267
423
|
if type(key) is slice:
|
|
1268
424
|
return super().__getitem__(key)
|
|
@@ -1285,23 +441,6 @@ class flow(table):
|
|
|
1285
441
|
flow = context(table=flow)
|
|
1286
442
|
|
|
1287
443
|
class meta:
|
|
1288
|
-
"""
|
|
1289
|
-
Metadata container for tracking hierarchical information and enabling function calls.
|
|
1290
|
-
|
|
1291
|
-
The meta class provides a hierarchical container that stores metadata as a tuple
|
|
1292
|
-
(__meta__) and supports dynamic attribute and item access. When accessing non-existent
|
|
1293
|
-
keys, it creates new meta instances with extended metadata tuples.
|
|
1294
|
-
|
|
1295
|
-
Key features:
|
|
1296
|
-
- Hierarchical metadata storage as tuples
|
|
1297
|
-
- Dynamic creation of child meta instances on attribute/item access
|
|
1298
|
-
- Function call delegation to the first metadata element
|
|
1299
|
-
- Unified attribute and item access patterns
|
|
1300
|
-
- Special handling for None keys (returns self)
|
|
1301
|
-
|
|
1302
|
-
This class is primarily used to create hierarchical function call patterns,
|
|
1303
|
-
where metadata forms a path that can be traversed and eventually executed as a function call.
|
|
1304
|
-
"""
|
|
1305
444
|
def __init__(self, *args):
|
|
1306
445
|
self.__meta__ = args
|
|
1307
446
|
def __getattr__(self, key):
|
|
@@ -1321,24 +460,6 @@ class meta:
|
|
|
1321
460
|
return self.__meta__[0](*args,*self.__meta__[1:],**kwargs)
|
|
1322
461
|
|
|
1323
462
|
class multi(meta):
|
|
1324
|
-
"""
|
|
1325
|
-
Multi-target container for managing multiple instances or operations.
|
|
1326
|
-
|
|
1327
|
-
The multi class extends meta to provide specialized functionality for managing
|
|
1328
|
-
multiple targets or performing operations across multiple instances. It enhances
|
|
1329
|
-
the meta class with multi-target function call behavior and special handling for
|
|
1330
|
-
collections of nodes.
|
|
1331
|
-
|
|
1332
|
-
Key features:
|
|
1333
|
-
- Extended metadata tracking from meta class
|
|
1334
|
-
- Multi-target function call delegation
|
|
1335
|
-
- Special handling for node collections (lists, tuples, ranges)
|
|
1336
|
-
- Support for single-target and multi-target modes
|
|
1337
|
-
- Automatic conversion of range objects to lists
|
|
1338
|
-
|
|
1339
|
-
This class is designed to facilitate operations that need to be applied to multiple
|
|
1340
|
-
targets, providing a unified interface for both single and multiple target scenarios.
|
|
1341
|
-
"""
|
|
1342
463
|
def __call__(self, *args, **kwargs):
|
|
1343
464
|
if len(self.__meta__) == 1:
|
|
1344
465
|
val = self.__class__()
|
|
@@ -1525,43 +646,6 @@ class SubPass(ast.NodeTransformer):
|
|
|
1525
646
|
return node
|
|
1526
647
|
|
|
1527
648
|
def domain(ctx={}, regq=None, sub=None, dump=False):
|
|
1528
|
-
"""Domain-specific language (DSL) decorator for custom assembly language constructs.
|
|
1529
|
-
|
|
1530
|
-
This decorator enables the creation of domain-specific assembly languages by transforming
|
|
1531
|
-
function source code through AST manipulation. It provides a framework for customizing
|
|
1532
|
-
and extending assembly-like syntax for specific hardware or application domains.
|
|
1533
|
-
|
|
1534
|
-
Args:
|
|
1535
|
-
ctx (dict, optional): Context dictionary containing variables and symbols available
|
|
1536
|
-
in the DSL environment. Defaults to empty dict.
|
|
1537
|
-
regq (callable, optional): Register query function used to identify and process
|
|
1538
|
-
register references in the DSL code. If provided, triggers the WithPass AST
|
|
1539
|
-
transformation.
|
|
1540
|
-
sub (bool/callable, optional): AST transformation option:
|
|
1541
|
-
- True: Apply SubPass transformation with the provided context
|
|
1542
|
-
- ast.NodeTransformer instance: Apply custom transformer class with context
|
|
1543
|
-
- callable: Apply custom callable transformation directly to the AST
|
|
1544
|
-
- None: No substitution transformation (default)
|
|
1545
|
-
dump (bool, optional): If True and regq is provided, prints the unparsed transformed
|
|
1546
|
-
AST for debugging purposes. Defaults to False.
|
|
1547
|
-
|
|
1548
|
-
Returns:
|
|
1549
|
-
callable: A decorator that transforms the decorated function's source code via AST
|
|
1550
|
-
manipulation and returns a wrapper that executes the transformed code in the
|
|
1551
|
-
augmented environment.
|
|
1552
|
-
|
|
1553
|
-
Process flow:
|
|
1554
|
-
1. Extracts the source code of the decorated function
|
|
1555
|
-
2. Normalizes indentation to process the code correctly
|
|
1556
|
-
3. Parses the code into an Abstract Syntax Tree (AST)
|
|
1557
|
-
4. Removes existing decorators from the AST
|
|
1558
|
-
5. Applies specified AST transformations (substitution and/or register query)
|
|
1559
|
-
6. Compiles the transformed AST into executable code
|
|
1560
|
-
7. Creates a wrapped function that executes in the augmented environment
|
|
1561
|
-
|
|
1562
|
-
This decorator is particularly useful for creating hardware-specific assembly languages,
|
|
1563
|
-
instruction set simulators, and domain-specific compilation passes within the oasm framework.
|
|
1564
|
-
"""
|
|
1565
649
|
def decorator(func):
|
|
1566
650
|
src = inspect.getsourcelines(func)[0]
|
|
1567
651
|
indent = len(src[0]) - len(src[0].lstrip())
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
oasm/__init__.py,sha256=2sDXVVF7QBc1VwR0TowymfmTZjb-W03CXL9bZYjAmdk,28069
|
|
2
|
+
oasm-0.1.7.dist-info/METADATA,sha256=DtRW39u4QnMR1gAwy6giIBjs3mQFp0JCdUlZpFCtszQ,370
|
|
3
|
+
oasm-0.1.7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
4
|
+
oasm-0.1.7.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
|
|
5
|
+
oasm-0.1.7.dist-info/RECORD,,
|
oasm-0.1.5.dist-info/RECORD
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
oasm/__init__.py,sha256=7hI7IyEOnV3VoPq6ocWUXSiZ9PdoISLXp4NjGyHHYbk,66151
|
|
2
|
-
oasm-0.1.5.dist-info/METADATA,sha256=FJSdJI3ECMter4fbaNsYhL46NRnfT3uvtNGNL-9R5pQ,370
|
|
3
|
-
oasm-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
-
oasm-0.1.5.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
|
|
5
|
-
oasm-0.1.5.dist-info/RECORD,,
|
|
File without changes
|