@@ -417,9 +417,9 @@ def make_interface(self):
417
417
def __add__ (self , other ):
418
418
raise NotImplementedError ()
419
419
420
+ @abstractmethod
420
421
def __iadd__ (self , other ):
421
- # __iadd__ is explicitly overriden to enforce that it is non-mutating.
422
- return self + other
422
+ raise NotImplementedError ()
423
423
424
424
def flip (self ) -> "IOInterface" :
425
425
raise NotImplementedError ()
@@ -436,11 +436,9 @@ class IO(IOInterface):
436
436
# https://www.python.org/dev/peps/pep-0468/.
437
437
def __init__ (self , ** kwargs ):
438
438
self ._ports = {}
439
- self ._decl = []
440
439
self ._bound = False
441
440
for name , typ in kwargs .items ():
442
- self .add (name , typ )
443
- self ._decl .extend ((name , typ ))
441
+ self ._add (name , typ )
444
442
445
443
@property
446
444
def ports (self ):
@@ -454,36 +452,52 @@ def bind(self, defn):
454
452
self ._bound = True
455
453
456
454
def decl (self ):
457
- return self ._decl
455
+ return _flatten (
456
+ (name , type (port ).flip ()) for name , port in self ._ports .items ()
457
+ )
458
458
459
459
def make_interface (self ):
460
460
decl = self .decl ()
461
461
name = _make_interface_name (decl )
462
462
dct = dict (_io = self , _decl = decl , _initialized = False )
463
463
return InterfaceKind (name , (_DeclareSingletonInterface ,), dct )
464
464
465
- def __add__ (self , other ):
466
- """
467
- Attempts to combine this IO and @other. Returns a new IO object with the
468
- combined ports, unless:
469
- * @other is not of type IOInterface, in which case a TypeError is
470
- raised
465
+ def __add__ (self , other : 'IO' ) -> 'IO' :
466
+ """Attempts to combine this IO and @other. Returns a new IO object with
467
+ the combined ports, unless:
468
+ * @other is not of type IO, in which case a TypeError is raised
471
469
* this or @other has already been bound, in which case an Exception is
472
470
raised
473
471
* this and @other have common port names, in which case an Exception
474
472
is raised
475
473
"""
476
- if not isinstance (other , IOInterface ):
477
- raise TypeError (f"unsupported operand type(s) for +: 'IO' and "
478
- f"'{ type (other ).__name__ } '" )
474
+ if not isinstance (other , IO ):
475
+ raise TypeError (
476
+ f"unsupported operand type(s) for +: 'IO' and "
477
+ f"'{ type (other ).__name__ } '"
478
+ )
479
+ if self ._bound or other ._bound :
480
+ raise Exception ("Adding bound IO not allowed" )
481
+ if self ._ports .keys () & other ._ports .keys ():
482
+ raise Exception ("Adding IO with duplicate port names not allowed" )
483
+ return IO (** _dict_from_decl (self .decl () + other .decl ()))
484
+
485
+ def __iadd__ (self , other : 'IO' ) -> 'IO' :
486
+ """Attempts to combine this @IO and other in place, with the same
487
+ caveats as __add__.
488
+ """
489
+ if not isinstance (other , IO ):
490
+ raise TypeError (
491
+ f"unsupported operand type(s) for +: 'IO' and "
492
+ f"'{ type (other ).__name__ } '"
493
+ )
479
494
if self ._bound or other ._bound :
480
495
raise Exception ("Adding bound IO not allowed" )
481
496
if self ._ports .keys () & other ._ports .keys ():
482
497
raise Exception ("Adding IO with duplicate port names not allowed" )
483
- decl = self ._decl + other ._decl
484
- return IO (** _dict_from_decl (decl ))
498
+ self ._ports .update (other ._ports )
485
499
486
- def add (self , name , typ ):
500
+ def _add (self , name , typ ):
487
501
if self ._bound :
488
502
raise RuntimeError ("Can not add to a bound IO" )
489
503
# Definition port.
@@ -505,7 +519,7 @@ def __getattr__(self, key: str):
505
519
return super ().__getattribute__ (key )
506
520
507
521
def fields (self ):
508
- return _dict_from_decl (self ._decl )
522
+ return _dict_from_decl (self .decl () )
509
523
510
524
def flip (self ):
511
525
return IO (** {name : T .flip () for name , T in self .fields ().items ()})
@@ -534,26 +548,32 @@ def inst_ports(self):
534
548
return self ._inst_ports .copy ()
535
549
536
550
def decl (self ):
537
- return _flatten ((name , type (port ))
538
- for name , port in self ._ports .items ())
551
+ return _flatten (
552
+ (name , type (port )) for name , port in self ._ports .items ()
553
+ )
539
554
540
555
def make_interface (self ):
541
556
decl = self .decl ()
542
557
name = _make_interface_name (decl )
543
- dct = dict (_io = self , _decl = decl , _initialized = False ,
544
- _initialized_inst = False )
558
+ dct = {
559
+ "_io" : self ,
560
+ "_decl" : decl ,
561
+ "_initialized" : False ,
562
+ "_initialized_inst" : False ,
563
+ }
545
564
return InterfaceKind (name , (_DeclareSingletonInstanceInterface ,), dct )
546
565
547
- def add (self , name , typ ):
548
- super ().add (name , typ )
566
+ def _add (self , name , typ ):
567
+ super ()._add (name , typ )
549
568
# Instance port.
550
569
inst_ref = LazyInstRef (name = name )
551
570
inst_port = _make_port (typ , inst_ref , flip = False )
552
571
self ._inst_ports [name ] = inst_port
553
572
554
573
def __add__ (self , other ):
555
- raise NotImplementedError (f"Addition operator disallowed on "
556
- f"{ cls .__name__ } " )
574
+ raise NotImplementedError (
575
+ f"Addition operator disallowed on { cls .__name__ } "
576
+ )
557
577
558
578
def flip (self ):
559
579
raise NotImplementedError ()
0 commit comments