|
4 | 4 | //! tracking within a specific region of a HUGR, computing resource paths and |
5 | 5 | //! providing efficient lookup of circuit units associated with ports. |
6 | 6 |
|
| 7 | +mod patch; |
| 8 | +pub use patch::CircuitRewriteError; |
| 9 | + |
7 | 10 | use std::{cmp, iter}; |
8 | 11 |
|
9 | 12 | use crate::resource::flow::{DefaultResourceFlow, ResourceFlow}; |
@@ -165,17 +168,15 @@ impl<H: HugrView> ResourceScope<H> { |
165 | 168 | self.hugr |
166 | 169 | } |
167 | 170 |
|
168 | | - pub(crate) fn hugr_mut(&mut self) -> &mut H { |
169 | | - &mut self.hugr |
170 | | - } |
171 | | - |
172 | 171 | /// Wrap the underlying HUGR in a Circuit as reference. |
173 | 172 | pub fn as_circuit(&self) -> Circuit<&H> { |
174 | 173 | Circuit::new(self.hugr()) |
175 | 174 | } |
176 | 175 |
|
177 | | - pub(crate) fn as_circuit_mut(&mut self) -> Circuit<&mut H> { |
178 | | - Circuit::new(self.hugr_mut()) |
| 176 | + /// Careful: this will not update the circuit units, so do not modify |
| 177 | + /// the HUGR using this. |
| 178 | + pub(super) fn as_circuit_mut(&mut self) -> Circuit<&mut H> { |
| 179 | + Circuit::new(&mut self.hugr) |
179 | 180 | } |
180 | 181 |
|
181 | 182 | /// Get the underlying subgraph. |
@@ -390,53 +391,37 @@ impl<H: HugrView> ResourceScope<H> { |
390 | 391 | .flatten() |
391 | 392 | .copied() |
392 | 393 | .collect_vec(); |
393 | | - self.assign_circuit_units(all_inputs, &mut allocator); |
| 394 | + self.assign_missing_circuit_units(all_inputs, &mut allocator); |
394 | 395 |
|
395 | 396 | // Proceed to propagating the circuit units through the subgraph, in topological |
396 | 397 | // order. |
397 | 398 | for node in toposort_subgraph(&self.hugr, &self.subgraph, self.find_sources()) { |
398 | | - if self.hugr.get_optype(node).dataflow_signature().is_none() { |
| 399 | + let Some(sig) = self.hugr.get_optype(node).dataflow_signature() else { |
399 | 400 | // ignore non-dataflow ops |
400 | 401 | continue; |
401 | | - } |
402 | | - self.assign_missing_circuit_units(node, &mut allocator); |
| 402 | + }; |
| 403 | + |
| 404 | + let incoming_ports = sig.input_ports().map(|p| (node, p)); |
| 405 | + self.assign_missing_circuit_units(incoming_ports, &mut allocator); |
403 | 406 | self.propagate_to_outputs(node, flows, &mut allocator); |
404 | 407 | self.propagate_to_next_inputs(node); |
405 | 408 | } |
406 | 409 | } |
407 | 410 |
|
408 | | - /// Assign circuit units to the given ports in order. |
409 | | - fn assign_circuit_units( |
| 411 | + /// Assign circuit units to the given ports in order, if they don't already |
| 412 | + /// have a circuit unit. |
| 413 | + fn assign_missing_circuit_units( |
410 | 414 | &mut self, |
411 | 415 | incoming_ports: impl IntoIterator<Item = (H::Node, IncomingPort)>, |
412 | 416 | allocator: &mut CircuitUnitAllocator, |
413 | 417 | ) { |
414 | 418 | for (node, port) in incoming_ports { |
415 | | - let unit = allocator.allocate_circuit_unit(node, port, &self.hugr); |
416 | 419 | let node_units = node_circuit_units_mut(&mut self.circuit_units, node, &self.hugr); |
417 | | - node_units.port_map.set(port, unit); |
418 | | - } |
419 | | - } |
420 | | - |
421 | | - /// Ensure all input ports of `node` have assigned circuit units. |
422 | | - fn assign_missing_circuit_units( |
423 | | - &mut self, |
424 | | - node: H::Node, |
425 | | - allocator: &mut CircuitUnitAllocator, |
426 | | - ) { |
427 | | - let signature = self |
428 | | - .hugr |
429 | | - .get_optype(node) |
430 | | - .dataflow_signature() |
431 | | - .expect("dataflow op"); |
432 | | - |
433 | | - let mut incoming_ports = signature.input_ports().collect_vec(); |
434 | | - if let Some(node_units) = self.circuit_units.get(&node) { |
435 | | - // Only assign circuit units to input ports without assigned units |
436 | | - incoming_ports.retain(|&p| node_units.port_map.get(p).is_sentinel()); |
| 420 | + if node_units.port_map.get(port).is_sentinel() { |
| 421 | + let unit = allocator.allocate_circuit_unit(node, port, &self.hugr); |
| 422 | + node_units.port_map.set(port, unit); |
| 423 | + } |
437 | 424 | } |
438 | | - |
439 | | - self.assign_circuit_units(incoming_ports.into_iter().map(|p| (node, p)), allocator); |
440 | 425 | } |
441 | 426 |
|
442 | 427 | /// Find source nodes (nodes with no predecessors in the subgraph). |
|
0 commit comments