@@ -34,6 +34,7 @@ class to enable the new behavior. Sometimes adding a new abstract
3434from mypyc .ir .rtypes import (
3535 RArray ,
3636 RInstance ,
37+ RStruct ,
3738 RTuple ,
3839 RType ,
3940 RVoid ,
@@ -244,6 +245,24 @@ def __init__(self, value: bytes, line: int = -1) -> None:
244245 self .line = line
245246
246247
248+ class Undef (Value ):
249+ """An undefined value.
250+
251+ Use Undef() as the initial value followed by one or more SetElement
252+ ops to initialize a struct. Pseudocode example:
253+
254+ r0 = set_element undef MyStruct, "field1", f1
255+ r1 = set_element r0, "field2", f2
256+ # r1 now has new struct value with two fields set
257+
258+ Warning: The generated code can use an arbitrary runtime values for
259+ this (likely not explicitly initialized).
260+ """
261+
262+ def __init__ (self , rtype : RType ) -> None :
263+ self .type = rtype
264+
265+
247266class Op (Value ):
248267 """Abstract base class for all IR operations.
249268
@@ -1636,6 +1655,39 @@ def accept(self, visitor: OpVisitor[T]) -> T:
16361655 return visitor .visit_get_element_ptr (self )
16371656
16381657
1658+ @final
1659+ class SetElement (RegisterOp ):
1660+ """Set the value of a struct element.
1661+
1662+ This evaluates to a new struct with the changed value.
1663+
1664+ Use together with Undef to initialize a fresh struct value
1665+ (see Undef for more details).
1666+ """
1667+
1668+ error_kind = ERR_NEVER
1669+
1670+ def __init__ (self , src : Value , field : str , item : Value , line : int = - 1 ) -> None :
1671+ super ().__init__ (line )
1672+ assert isinstance (src .type , RStruct ), src .type
1673+ self .type = src .type
1674+ self .src = src
1675+ self .item = item
1676+ self .field = field
1677+
1678+ def sources (self ) -> list [Value ]:
1679+ return [self .src ]
1680+
1681+ def set_sources (self , new : list [Value ]) -> None :
1682+ (self .src ,) = new
1683+
1684+ def stolen (self ) -> list [Value ]:
1685+ return [self .src ]
1686+
1687+ def accept (self , visitor : OpVisitor [T ]) -> T :
1688+ return visitor .visit_set_element (self )
1689+
1690+
16391691@final
16401692class LoadAddress (RegisterOp ):
16411693 """Get the address of a value: result = (type)&src
@@ -1908,6 +1960,10 @@ def visit_set_mem(self, op: SetMem) -> T:
19081960 def visit_get_element_ptr (self , op : GetElementPtr ) -> T :
19091961 raise NotImplementedError
19101962
1963+ @abstractmethod
1964+ def visit_set_element (self , op : SetElement ) -> T :
1965+ raise NotImplementedError
1966+
19111967 @abstractmethod
19121968 def visit_load_address (self , op : LoadAddress ) -> T :
19131969 raise NotImplementedError
0 commit comments