oasm 0.1.1__py3-none-any.whl → 0.1.3__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
|
@@ -5,25 +5,148 @@ __path__.reverse()
|
|
|
5
5
|
__all__ = ['table','config','equal','expr','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
|
+
|
|
8
36
|
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
|
+
"""
|
|
9
55
|
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
|
+
"""
|
|
10
67
|
super().__init__(args)
|
|
11
68
|
self.__dict__.update(kwargs)
|
|
12
69
|
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
|
+
"""
|
|
13
88
|
if type(key) is str:
|
|
14
89
|
return self.__dict__[key]
|
|
15
90
|
return super().__getitem__(key)
|
|
16
91
|
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
|
+
"""
|
|
17
104
|
if type(key) is str:
|
|
18
105
|
self.__dict__[key] = val
|
|
19
106
|
else:
|
|
20
107
|
super().__setitem__(key, val)
|
|
21
108
|
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
|
+
"""
|
|
22
124
|
if type(key) is str:
|
|
23
125
|
del self.__dict__[key]
|
|
24
126
|
else:
|
|
25
127
|
super().__delitem__(key)
|
|
26
128
|
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
|
+
"""
|
|
27
150
|
func = self.__dict__.get('__call__',None)
|
|
28
151
|
if func is not None:
|
|
29
152
|
return func(self,*args,**kwargs)
|
|
@@ -33,6 +156,18 @@ class table(list):
|
|
|
33
156
|
self.__dict__.update(kwargs)
|
|
34
157
|
return self
|
|
35
158
|
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
|
+
"""
|
|
36
171
|
r = ''
|
|
37
172
|
for i in self[:]:
|
|
38
173
|
r += pformat(i) + ','
|
|
@@ -42,11 +177,54 @@ class table(list):
|
|
|
42
177
|
r = r[:-1]
|
|
43
178
|
return '[' + r + ']'
|
|
44
179
|
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
|
+
"""
|
|
45
191
|
return self
|
|
46
192
|
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
|
+
"""
|
|
47
204
|
return self.__class__(*self[:],**self.__dict__)
|
|
48
205
|
@staticmethod
|
|
49
206
|
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
|
+
"""
|
|
50
228
|
if isinstance(x, table):
|
|
51
229
|
return {f'__{x.__class__.__name__}__':table.to_dict(x[:])}|table.to_dict(x.__dict__)
|
|
52
230
|
elif isinstance(x,(tuple,list)):
|
|
@@ -57,6 +235,28 @@ class table(list):
|
|
|
57
235
|
return x
|
|
58
236
|
@classmethod
|
|
59
237
|
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
|
+
"""
|
|
60
260
|
cls = {table,config,expr,flow._tbl}|{cls}
|
|
61
261
|
for i in cls:
|
|
62
262
|
if f'__{i.__name__}__' in dct:
|
|
@@ -65,10 +265,50 @@ class table(list):
|
|
|
65
265
|
return dct
|
|
66
266
|
|
|
67
267
|
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
|
|
68
286
|
root = '../json'
|
|
69
287
|
|
|
70
288
|
@classmethod
|
|
71
289
|
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
|
+
"""
|
|
72
312
|
import json
|
|
73
313
|
dct = {}
|
|
74
314
|
for i in cls.__bases__:
|
|
@@ -84,6 +324,30 @@ class config(table):
|
|
|
84
324
|
return val
|
|
85
325
|
|
|
86
326
|
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
|
+
"""
|
|
87
351
|
import json
|
|
88
352
|
if len(args) == 0:
|
|
89
353
|
args = self.__class__.__mro__[::-1][4:-1] + (self,)
|
|
@@ -96,6 +360,26 @@ class config(table):
|
|
|
96
360
|
json.dump(dct|{f'__{i.__class__.__name__}__':[]},f)
|
|
97
361
|
|
|
98
362
|
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
|
+
"""
|
|
99
383
|
func = self.__dict__.get('__call__',None)
|
|
100
384
|
if func is not None:
|
|
101
385
|
return func(self,*args,**kwargs)
|
|
@@ -108,6 +392,30 @@ class config(table):
|
|
|
108
392
|
import operator
|
|
109
393
|
|
|
110
394
|
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
|
+
"""
|
|
111
419
|
if type(x) != type(y):
|
|
112
420
|
return False
|
|
113
421
|
if getattr(x,'__getitem__',None) is not None:
|
|
@@ -128,7 +436,44 @@ def equal(x, y):
|
|
|
128
436
|
return x == y
|
|
129
437
|
|
|
130
438
|
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
|
+
"""
|
|
131
457
|
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
|
+
"""
|
|
132
477
|
if type(key) is slice and key == slice(None,None,None):
|
|
133
478
|
return super().__getitem__(key)
|
|
134
479
|
dct = self.__dict__
|
|
@@ -141,8 +486,44 @@ class expr(table):
|
|
|
141
486
|
else:
|
|
142
487
|
return self.__class__(*self,key,**dct)
|
|
143
488
|
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
|
+
"""
|
|
144
507
|
return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
|
|
145
508
|
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
|
+
"""
|
|
146
527
|
if len(self) == 0:
|
|
147
528
|
return 'expr()'
|
|
148
529
|
line = 'sym' if self[:][0] is None else 'expr('+pformat(self[:][0])+')'
|
|
@@ -155,6 +536,30 @@ class expr(table):
|
|
|
155
536
|
line += f'[{i}]'
|
|
156
537
|
return line[1:] if line.startswith('.') else line
|
|
157
538
|
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
|
+
"""
|
|
158
563
|
r = self[:][0]
|
|
159
564
|
body = self[:][1:]
|
|
160
565
|
body.append(table(*args,**kwargs))
|
|
@@ -227,89 +632,503 @@ class expr(table):
|
|
|
227
632
|
#print(self[:],args,kwargs,self.__dict__,r)
|
|
228
633
|
return r
|
|
229
634
|
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
|
+
"""
|
|
230
645
|
return a.__class__(operator.__lt__,table(a,b))
|
|
231
646
|
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
|
+
"""
|
|
232
657
|
return a.__class__(operator.__le__,table(a,b))
|
|
233
658
|
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
|
+
"""
|
|
234
669
|
return a.__class__(operator.__eq__,table(a,b))
|
|
235
670
|
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
|
+
"""
|
|
236
681
|
return a.__class__(operator.__ne__,table(a,b))
|
|
237
682
|
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
|
+
"""
|
|
238
693
|
return a.__class__(operator.__ge__,table(a,b))
|
|
239
694
|
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
|
+
"""
|
|
240
705
|
return a.__class__(operator.__gt__,table(a,b))
|
|
241
706
|
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
|
+
"""
|
|
242
716
|
return a.__class__(operator.__not__,table(a))
|
|
243
717
|
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
|
+
"""
|
|
244
727
|
return a.__class__(operator.__abs__,table(a))
|
|
245
728
|
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
|
+
"""
|
|
246
738
|
return a.__class__(round,table(a))
|
|
247
739
|
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
|
+
"""
|
|
248
750
|
return plus(a,b)
|
|
249
751
|
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
|
+
"""
|
|
250
762
|
return plus(b,a)
|
|
251
763
|
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
|
+
"""
|
|
252
774
|
return plus(a,b)
|
|
253
775
|
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
|
+
"""
|
|
254
786
|
return a.__class__(operator.__and__,table(a,b))
|
|
255
787
|
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
|
+
"""
|
|
256
798
|
return a.__class__(operator.__and__,table(b,a))
|
|
257
799
|
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
|
+
"""
|
|
258
810
|
return a.__class__(operator.__floordiv__,table(a,b))
|
|
259
811
|
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
|
+
"""
|
|
260
822
|
return a.__class__(operator.__floordiv__,table(b,a))
|
|
261
823
|
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
|
+
"""
|
|
262
833
|
return a.__class__(operator.__inv__,table(a))
|
|
263
834
|
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
|
+
"""
|
|
264
844
|
return a.__class__(operator.__invert__,table(a))
|
|
265
845
|
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
|
+
"""
|
|
266
856
|
return a.__class__(operator.__lshift__,table(a,b))
|
|
267
857
|
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
|
+
"""
|
|
268
868
|
return a.__class__(operator.__lshift__,table(b,a))
|
|
269
869
|
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
|
+
"""
|
|
270
880
|
return a.__class__(operator.__mod__,table(a,b))
|
|
271
881
|
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
|
+
"""
|
|
272
892
|
return a.__class__(operator.__mod__,table(b,a))
|
|
273
893
|
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
|
+
"""
|
|
274
904
|
return a.__class__(operator.__mul__,table(a,b))
|
|
275
905
|
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
|
+
"""
|
|
276
916
|
return a.__class__(operator.__mul__,table(b,a))
|
|
277
917
|
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
|
+
"""
|
|
278
928
|
return a.__class__(operator.__matmul__,table(a,b))
|
|
279
929
|
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
|
+
"""
|
|
280
940
|
return a.__class__(operator.__matmul__,table(b,a))
|
|
281
941
|
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
|
+
"""
|
|
282
951
|
return uminus(a)
|
|
283
952
|
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
|
+
"""
|
|
284
963
|
return a.__class__(operator.__or__,table(a,b))
|
|
285
964
|
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
|
+
"""
|
|
286
975
|
return a.__class__(operator.__or__,table(b,a))
|
|
287
976
|
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
|
+
"""
|
|
288
986
|
return uplus(a)
|
|
289
987
|
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
|
+
"""
|
|
290
998
|
return a.__class__(operator.__pow__,table(a,b))
|
|
291
999
|
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
|
+
"""
|
|
292
1010
|
return a.__class__(operator.__pow__,table(b,a))
|
|
293
1011
|
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
|
+
"""
|
|
294
1022
|
return a.__class__(operator.__rshift__,table(a,b))
|
|
295
1023
|
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
|
+
"""
|
|
296
1034
|
return a.__class__(operator.__rshift__,table(b,a))
|
|
297
1035
|
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
|
+
"""
|
|
298
1046
|
return minus(a,b)
|
|
299
1047
|
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
|
+
"""
|
|
300
1058
|
return minus(b,a)
|
|
301
1059
|
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
|
+
"""
|
|
302
1070
|
return a.__class__(operator.__truediv__,table(a,b))
|
|
303
1071
|
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
|
+
"""
|
|
304
1082
|
return a.__class__(operator.__truediv__,table(b,a))
|
|
305
1083
|
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
|
+
"""
|
|
306
1094
|
return a.__class__(operator.__xor__,table(a,b))
|
|
307
1095
|
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
|
+
"""
|
|
308
1106
|
return a.__class__(operator.__xor__,table(b,a))
|
|
309
1107
|
|
|
310
|
-
|
|
1108
|
+
# Root symbolic expression for creating symbolic references
|
|
1109
|
+
sym = expr(None) # Symbolic expression root used for creating attribute-based symbol paths
|
|
311
1110
|
|
|
312
1111
|
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
|
+
"""
|
|
313
1132
|
def __init__(self,name):
|
|
314
1133
|
self._name = name
|
|
315
1134
|
def __repr__(self):
|
|
@@ -371,6 +1190,25 @@ class context_switch:
|
|
|
371
1190
|
self.ctx <= self.top
|
|
372
1191
|
|
|
373
1192
|
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
|
+
"""
|
|
374
1212
|
def __init__(self,*args,**kwargs):
|
|
375
1213
|
tbl = kwargs.pop('table',table)
|
|
376
1214
|
object.__setattr__(self,'_tbl',tbl)
|
|
@@ -407,6 +1245,24 @@ class context:
|
|
|
407
1245
|
self._stk.pop()
|
|
408
1246
|
|
|
409
1247
|
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
|
+
"""
|
|
410
1266
|
def __getitem__(self, key):
|
|
411
1267
|
if type(key) is slice:
|
|
412
1268
|
return super().__getitem__(key)
|
|
@@ -429,6 +1285,23 @@ class flow(table):
|
|
|
429
1285
|
flow = context(table=flow)
|
|
430
1286
|
|
|
431
1287
|
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
|
+
"""
|
|
432
1305
|
def __init__(self, *args):
|
|
433
1306
|
self.__meta__ = args
|
|
434
1307
|
def __getattr__(self, key):
|
|
@@ -448,6 +1321,24 @@ class meta:
|
|
|
448
1321
|
return self.__meta__[0](*args,*self.__meta__[1:],**kwargs)
|
|
449
1322
|
|
|
450
1323
|
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
|
+
"""
|
|
451
1342
|
def __call__(self, *args, **kwargs):
|
|
452
1343
|
if len(self.__meta__) == 1:
|
|
453
1344
|
val = self.__class__()
|
|
@@ -646,6 +1537,43 @@ class SubPass(ast.NodeTransformer):
|
|
|
646
1537
|
return node
|
|
647
1538
|
|
|
648
1539
|
def domain(ctx={}, regq=None, sub=None, dump=False):
|
|
1540
|
+
"""Domain-specific language (DSL) decorator for custom assembly language constructs.
|
|
1541
|
+
|
|
1542
|
+
This decorator enables the creation of domain-specific assembly languages by transforming
|
|
1543
|
+
function source code through AST manipulation. It provides a framework for customizing
|
|
1544
|
+
and extending assembly-like syntax for specific hardware or application domains.
|
|
1545
|
+
|
|
1546
|
+
Args:
|
|
1547
|
+
ctx (dict, optional): Context dictionary containing variables and symbols available
|
|
1548
|
+
in the DSL environment. Defaults to empty dict.
|
|
1549
|
+
regq (callable, optional): Register query function used to identify and process
|
|
1550
|
+
register references in the DSL code. If provided, triggers the WithPass AST
|
|
1551
|
+
transformation.
|
|
1552
|
+
sub (bool/callable, optional): AST transformation option:
|
|
1553
|
+
- True: Apply SubPass transformation with the provided context
|
|
1554
|
+
- ast.NodeTransformer instance: Apply custom transformer class with context
|
|
1555
|
+
- callable: Apply custom callable transformation directly to the AST
|
|
1556
|
+
- None: No substitution transformation (default)
|
|
1557
|
+
dump (bool, optional): If True and regq is provided, prints the unparsed transformed
|
|
1558
|
+
AST for debugging purposes. Defaults to False.
|
|
1559
|
+
|
|
1560
|
+
Returns:
|
|
1561
|
+
callable: A decorator that transforms the decorated function's source code via AST
|
|
1562
|
+
manipulation and returns a wrapper that executes the transformed code in the
|
|
1563
|
+
augmented environment.
|
|
1564
|
+
|
|
1565
|
+
Process flow:
|
|
1566
|
+
1. Extracts the source code of the decorated function
|
|
1567
|
+
2. Normalizes indentation to process the code correctly
|
|
1568
|
+
3. Parses the code into an Abstract Syntax Tree (AST)
|
|
1569
|
+
4. Removes existing decorators from the AST
|
|
1570
|
+
5. Applies specified AST transformations (substitution and/or register query)
|
|
1571
|
+
6. Compiles the transformed AST into executable code
|
|
1572
|
+
7. Creates a wrapped function that executes in the augmented environment
|
|
1573
|
+
|
|
1574
|
+
This decorator is particularly useful for creating hardware-specific assembly languages,
|
|
1575
|
+
instruction set simulators, and domain-specific compilation passes within the oasm framework.
|
|
1576
|
+
"""
|
|
649
1577
|
def decorator(func):
|
|
650
1578
|
src = inspect.getsourcelines(func)[0]
|
|
651
1579
|
indent = len(src[0]) - len(src[0].lstrip())
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
oasm/__init__.py,sha256=S3K4YGKR7RUijQDSCEhSdpD49TNxomWHfuZrnaeZGZk,66704
|
|
2
|
+
oasm-0.1.3.dist-info/METADATA,sha256=SM5AUPPVDPd73O1qgHVW0mgVsLZnGhY5d3Hd6IRArs0,370
|
|
3
|
+
oasm-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
+
oasm-0.1.3.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
|
|
5
|
+
oasm-0.1.3.dist-info/RECORD,,
|
oasm-0.1.1.dist-info/RECORD
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
oasm/__init__.py,sha256=orMLmLUqo81GsN50Aa4FWBWU1MjuMdoaxoqa7SDerUk,28169
|
|
2
|
-
oasm-0.1.1.dist-info/METADATA,sha256=OSYNDE3UaGRu-6vnZhPi8wWRzs5FQsr0iFf7oTomX2E,370
|
|
3
|
-
oasm-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
-
oasm-0.1.1.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
|
|
5
|
-
oasm-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|