oasm 0.1.2__py3-none-any.whl → 0.1.4__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
@@ -8,39 +8,145 @@ from pprint import pformat
8
8
  """
9
9
  Open Assembly Tools (OASM) Core Module
10
10
 
11
- This module provides fundamental data structures and utility classes that support
12
- assembler configuration, expression processing, and flow control.
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
13
 
14
- The module includes:
15
- - table: Flexible list-dictionary hybrid container
16
- - config: Configuration management with JSON persistence
17
- - expr: Expression evaluation system
18
- - context: Context management for assembly operations
19
- - flow: Control flow management
20
- - meta: Metaprogramming utilities
21
- - multi: Multi-node assembly support
22
- - domain: Domain-specific language constructs
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
23
34
  """
24
35
 
25
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
+ """
26
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
+ """
27
67
  super().__init__(args)
28
68
  self.__dict__.update(kwargs)
29
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
+ """
30
88
  if type(key) is str:
31
89
  return self.__dict__[key]
32
90
  return super().__getitem__(key)
33
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
+ """
34
104
  if type(key) is str:
35
105
  self.__dict__[key] = val
36
106
  else:
37
107
  super().__setitem__(key, val)
38
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
+ """
39
124
  if type(key) is str:
40
125
  del self.__dict__[key]
41
126
  else:
42
127
  super().__delitem__(key)
43
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
+ """
44
150
  func = self.__dict__.get('__call__',None)
45
151
  if func is not None:
46
152
  return func(self,*args,**kwargs)
@@ -50,6 +156,18 @@ class table(list):
50
156
  self.__dict__.update(kwargs)
51
157
  return self
52
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
+ """
53
171
  r = ''
54
172
  for i in self[:]:
55
173
  r += pformat(i) + ','
@@ -59,11 +177,54 @@ class table(list):
59
177
  r = r[:-1]
60
178
  return '[' + r + ']'
61
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
+ """
62
191
  return self
63
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
+ """
64
204
  return self.__class__(*self[:],**self.__dict__)
65
205
  @staticmethod
66
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
+ """
67
228
  if isinstance(x, table):
68
229
  return {f'__{x.__class__.__name__}__':table.to_dict(x[:])}|table.to_dict(x.__dict__)
69
230
  elif isinstance(x,(tuple,list)):
@@ -74,6 +235,28 @@ class table(list):
74
235
  return x
75
236
  @classmethod
76
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
+ """
77
260
  cls = {table,config,expr,flow._tbl}|{cls}
78
261
  for i in cls:
79
262
  if f'__{i.__name__}__' in dct:
@@ -82,10 +265,50 @@ class table(list):
82
265
  return dct
83
266
 
84
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
85
286
  root = '../json'
86
287
 
87
288
  @classmethod
88
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
+ """
89
312
  import json
90
313
  dct = {}
91
314
  for i in cls.__bases__:
@@ -101,6 +324,30 @@ class config(table):
101
324
  return val
102
325
 
103
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
+ """
104
351
  import json
105
352
  if len(args) == 0:
106
353
  args = self.__class__.__mro__[::-1][4:-1] + (self,)
@@ -113,6 +360,26 @@ class config(table):
113
360
  json.dump(dct|{f'__{i.__class__.__name__}__':[]},f)
114
361
 
115
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
+ """
116
383
  func = self.__dict__.get('__call__',None)
117
384
  if func is not None:
118
385
  return func(self,*args,**kwargs)
@@ -125,6 +392,30 @@ class config(table):
125
392
  import operator
126
393
 
127
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
+ """
128
419
  if type(x) != type(y):
129
420
  return False
130
421
  if getattr(x,'__getitem__',None) is not None:
@@ -145,7 +436,44 @@ def equal(x, y):
145
436
  return x == y
146
437
 
147
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
+ """
148
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
+ """
149
477
  if type(key) is slice and key == slice(None,None,None):
150
478
  return super().__getitem__(key)
151
479
  dct = self.__dict__
@@ -158,8 +486,44 @@ class expr(table):
158
486
  else:
159
487
  return self.__class__(*self,key,**dct)
160
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
+ """
161
507
  return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
162
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
+ """
163
527
  if len(self) == 0:
164
528
  return 'expr()'
165
529
  line = 'sym' if self[:][0] is None else 'expr('+pformat(self[:][0])+')'
@@ -172,6 +536,30 @@ class expr(table):
172
536
  line += f'[{i}]'
173
537
  return line[1:] if line.startswith('.') else line
174
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
+ """
175
563
  r = self[:][0]
176
564
  body = self[:][1:]
177
565
  body.append(table(*args,**kwargs))
@@ -244,89 +632,503 @@ class expr(table):
244
632
  #print(self[:],args,kwargs,self.__dict__,r)
245
633
  return r
246
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
+ """
247
645
  return a.__class__(operator.__lt__,table(a,b))
248
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
+ """
249
657
  return a.__class__(operator.__le__,table(a,b))
250
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
+ """
251
669
  return a.__class__(operator.__eq__,table(a,b))
252
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
+ """
253
681
  return a.__class__(operator.__ne__,table(a,b))
254
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
+ """
255
693
  return a.__class__(operator.__ge__,table(a,b))
256
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
+ """
257
705
  return a.__class__(operator.__gt__,table(a,b))
258
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
+ """
259
716
  return a.__class__(operator.__not__,table(a))
260
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
+ """
261
727
  return a.__class__(operator.__abs__,table(a))
262
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
+ """
263
738
  return a.__class__(round,table(a))
264
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
+ """
265
750
  return plus(a,b)
266
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
+ """
267
762
  return plus(b,a)
268
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
+ """
269
774
  return plus(a,b)
270
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
+ """
271
786
  return a.__class__(operator.__and__,table(a,b))
272
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
+ """
273
798
  return a.__class__(operator.__and__,table(b,a))
274
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
+ """
275
810
  return a.__class__(operator.__floordiv__,table(a,b))
276
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
+ """
277
822
  return a.__class__(operator.__floordiv__,table(b,a))
278
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
+ """
279
833
  return a.__class__(operator.__inv__,table(a))
280
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
+ """
281
844
  return a.__class__(operator.__invert__,table(a))
282
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
+ """
283
856
  return a.__class__(operator.__lshift__,table(a,b))
284
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
+ """
285
868
  return a.__class__(operator.__lshift__,table(b,a))
286
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
+ """
287
880
  return a.__class__(operator.__mod__,table(a,b))
288
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
+ """
289
892
  return a.__class__(operator.__mod__,table(b,a))
290
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
+ """
291
904
  return a.__class__(operator.__mul__,table(a,b))
292
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
+ """
293
916
  return a.__class__(operator.__mul__,table(b,a))
294
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
+ """
295
928
  return a.__class__(operator.__matmul__,table(a,b))
296
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
+ """
297
940
  return a.__class__(operator.__matmul__,table(b,a))
298
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
+ """
299
951
  return uminus(a)
300
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
+ """
301
963
  return a.__class__(operator.__or__,table(a,b))
302
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
+ """
303
975
  return a.__class__(operator.__or__,table(b,a))
304
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
+ """
305
986
  return uplus(a)
306
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
+ """
307
998
  return a.__class__(operator.__pow__,table(a,b))
308
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
+ """
309
1010
  return a.__class__(operator.__pow__,table(b,a))
310
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
+ """
311
1022
  return a.__class__(operator.__rshift__,table(a,b))
312
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
+ """
313
1034
  return a.__class__(operator.__rshift__,table(b,a))
314
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
+ """
315
1046
  return minus(a,b)
316
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
+ """
317
1058
  return minus(b,a)
318
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
+ """
319
1070
  return a.__class__(operator.__truediv__,table(a,b))
320
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
+ """
321
1082
  return a.__class__(operator.__truediv__,table(b,a))
322
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
+ """
323
1094
  return a.__class__(operator.__xor__,table(a,b))
324
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
+ """
325
1106
  return a.__class__(operator.__xor__,table(b,a))
326
1107
 
327
- sym = expr(None)
1108
+ # Root symbolic expression for creating symbolic references
1109
+ sym = expr(None) # Symbolic expression root used for creating attribute-based symbol paths
328
1110
 
329
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
+ """
330
1132
  def __init__(self,name):
331
1133
  self._name = name
332
1134
  def __repr__(self):
@@ -356,7 +1158,7 @@ class plus_minus:
356
1158
  if type(x) is expr:
357
1159
  if len(x) > 0 and x[:][0] is plus:
358
1160
  t = x[:][1]
359
- (term if type(t[0]) is expr else atom).append(t[0])
1161
+ (term if type(t[0]) is expr else atom).append(-t[0] if sub else t[0])
360
1162
  (term if type(t[1]) is expr else atom).append(-t[1] if sub else t[1])
361
1163
  else:
362
1164
  term.append(-x if sub else x)
@@ -388,6 +1190,25 @@ class context_switch:
388
1190
  self.ctx <= self.top
389
1191
 
390
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
+ """
391
1212
  def __init__(self,*args,**kwargs):
392
1213
  tbl = kwargs.pop('table',table)
393
1214
  object.__setattr__(self,'_tbl',tbl)
@@ -424,6 +1245,24 @@ class context:
424
1245
  self._stk.pop()
425
1246
 
426
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
+ """
427
1266
  def __getitem__(self, key):
428
1267
  if type(key) is slice:
429
1268
  return super().__getitem__(key)
@@ -446,6 +1285,23 @@ class flow(table):
446
1285
  flow = context(table=flow)
447
1286
 
448
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
+ """
449
1305
  def __init__(self, *args):
450
1306
  self.__meta__ = args
451
1307
  def __getattr__(self, key):
@@ -465,6 +1321,24 @@ class meta:
465
1321
  return self.__meta__[0](*args,*self.__meta__[1:],**kwargs)
466
1322
 
467
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
+ """
468
1342
  def __call__(self, *args, **kwargs):
469
1343
  if len(self.__meta__) == 1:
470
1344
  val = self.__class__()
@@ -663,6 +1537,43 @@ class SubPass(ast.NodeTransformer):
663
1537
  return node
664
1538
 
665
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
+ """
666
1577
  def decorator(func):
667
1578
  src = inspect.getsourcelines(func)[0]
668
1579
  indent = len(src[0]) - len(src[0].lstrip())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oasm
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Open ASseMbly tools
5
5
  Author-email: nzturn <nzturn@gmail.com>
6
6
  Keywords: asm,dsl
@@ -0,0 +1,5 @@
1
+ oasm/__init__.py,sha256=7Ysrt9CdNWtMfyils2KYpiCQFXPMRlv2xCeCSBhnUgw,66722
2
+ oasm-0.1.4.dist-info/METADATA,sha256=tRmbpeCw5wkLjWpMpRYWd5FvdNY4iFehe_kj_9jxkCo,370
3
+ oasm-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
+ oasm-0.1.4.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
5
+ oasm-0.1.4.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- oasm/__init__.py,sha256=Q0G6HilXbVsaW9BdQgV9YYzfxCJUo6qz1VDUyZ1Bvh0,28753
2
- oasm-0.1.2.dist-info/METADATA,sha256=78ArYUMb3d55G8dBQqOgSO6VF12sqKaNge-sMcVk-OI,370
3
- oasm-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4
- oasm-0.1.2.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
5
- oasm-0.1.2.dist-info/RECORD,,
File without changes