Used for intermediate assignment targets. This takes the valueReg and mutates targetReg into it. Cases: 1. targetReg is KIND_ARRAY or KIND_SCALAR in which case it has been pre-allocated and is a secondary return. 2. targetReg is KIND_NAMED in which case it's a _na
(self: NumExpr, targetNode: ast.AST, valueReg: NumReg)
| 945 | return self.assignTarget |
| 946 | |
| 947 | def _mutate(self: NumExpr, targetNode: ast.AST, valueReg: NumReg) -> NumReg: |
| 948 | ''' |
| 949 | Used for intermediate assignment targets. This takes the valueReg and |
| 950 | mutates targetReg into it. |
| 951 | |
| 952 | Cases: |
| 953 | 1. targetReg is KIND_ARRAY or KIND_SCALAR in which case it has been |
| 954 | pre-allocated and is a secondary return. |
| 955 | 2. targetReg is KIND_NAMED in which case it's a _named_ temporary. I.e. |
| 956 | a temporary that we cannot re-use because it was assigned as an |
| 957 | intermediate assignment target. |
| 958 | |
| 959 | In some cases this will require a new temporary. For example, if the output |
| 960 | dtype is smaller than the valueReg.dchar it can't be mutated to a named |
| 961 | output. |
| 962 | ''' |
| 963 | # print(f'Mutating: {targetNode} and {valueReg}') |
| 964 | |
| 965 | if isinstance(targetNode, ast.Name): |
| 966 | if valueReg.kind & (_KIND_ARRAY|_KIND_SCALAR): |
| 967 | # This is a copy, like NumExpr( 'y=x' ) |
| 968 | targetReg = _ASTAssembler[type(targetNode)](self, targetNode) |
| 969 | targetReg.dchar = valueReg.dchar |
| 970 | return self._copy(targetReg, valueReg) |
| 971 | # else KIND_TEMP|KIND_NAMED |
| 972 | nodeId = targetNode.id |
| 973 | if nodeId in self.registers: |
| 974 | # Pre-existing, pre-known output. |
| 975 | # Often in-line operation, e.g. NumExpr('b=2*b') |
| 976 | # Should we count how many times each temporary is used? |
| 977 | # As this is a case where if the temp is used twice we can't |
| 978 | # get rid of it, but if it's used once we can pop it. |
| 979 | targetReg = self.registers[nodeId] |
| 980 | # Intermediate assignment targets keep their KIND |
| 981 | program = self._codeStream.getbuffer() |
| 982 | oldToken = program[_RET_LOC] |
| 983 | program[_RET_LOC] = targetReg._num |
| 984 | return targetReg |
| 985 | |
| 986 | if valueReg.itemsize <= _DCHAR_ITEMSIZE[self.assignDChar]: |
| 987 | # Can mutate as the valueReg temporary's itemsize is less-than-equal to |
| 988 | # the output array's. |
| 989 | self.registers.pop(valueReg.name) |
| 990 | valueReg.name = nodeId |
| 991 | if nodeId in self.local_dict: # Pre-allocated array found |
| 992 | nodeRef = self.local_dict[nodeId] |
| 993 | if type(nodeRef) != np.ndarray: nodeRef = np.asarray( nodeRef ) |
| 994 | valueReg.ref = nodeRef if np.isscalar(nodeRef) else weakref.ref(nodeRef) |
| 995 | |
| 996 | valueReg.kind = _KIND_RETURN |
| 997 | self.assignTarget = self.registers[nodeId] = valueReg |
| 998 | return valueReg |
| 999 | |
| 1000 | else: |
| 1001 | # Else mutate valueRegister into assignTarget |
| 1002 | # TODO: rewind |
| 1003 | raise NotImplementedError('TODO: rewind program') |
| 1004 |