DfBase#

class hugr.build.dfg.DfBase(parent_op: DP)[source]#

Bases: ParentBuilder[DP], DefinitionBuilder, AbstractContextManager

Base class for dataflow graph builders.

Parameters:

parent_op – The parent operation of the dataflow graph.

Methods

add

Add a command (holding a dataflow operation and the incoming wires) to the graph.

add_alias_defn

Add a type alias definition.

add_cfg

Start building a new CFG nested inside the current dataflow graph.

add_conditional

Start building a new conditional nested inside the current dataflow graph.

add_const

Add a static constant to the graph.

add_if

Start building a new if block nested inside the current dataflow graph.

add_nested

Start building a nested dataflow graph.

add_op

Add a dataflow operation to the graph, wiring in input ports.

add_state_order

Add a state order link between two nodes.

add_tail_loop

Start building a new tail loop nested inside the current dataflow graph.

call

Call a static function in the graph.

define_function

Start building a function definition in the graph.

extend

Add a series of commands to the DFG.

inp

Generate an input port for this node.

inputs

List all incoming wires (output ports of the input node).

insert_cfg

Insert a CFG into the current dataflow graph, wiring in the inputs.

insert_conditional

Insert a conditional into the current dataflow graph, wiring in the inputs.

insert_nested

Insert a nested dataflow graph into the current graph, wiring in the inputs.

insert_tail_loop

Insert a tail loop into the current dataflow graph, wiring in the inputs.

load

Load a constant into the graph as a dataflow value.

load_function

Load a static function into the graph as a higher-order value.

new_nested

Start building a dataflow graph nested inside a larger HUGR.

out

Generate an output port for this node.

out_port

OutPort corresponding to this Wire.

outputs

Returns an iterator over the output ports of this node.

port

Generate a port in direction for this node with offset.

set_outputs

Set the outputs of the dataflow graph.

to_node

Convert to a Node.

Attributes

metadata

Metadata associated with this node.

parent_op

The parent node's operation.

hugr

The Hugr instance that the builder is using.

parent_node

The parent node of the dataflow graph.

input_node

The input node of the dataflow graph.

output_node

The output node of the dataflow graph.

add(com: ops.Command, *, metadata: dict[str, Any] | None = None) Node[source]#

Add a command (holding a dataflow operation and the incoming wires) to the graph.

Parameters:
  • com – The command to add.

  • metadata – Metadata to attach to the function definition. Defaults to None.

Example

>>> dfg = Dfg(tys.Bool)
>>> (i,) = dfg.inputs()
>>> dfg.add(ops.Noop()(i))
Node(3)
add_alias_defn(name: str, ty: Type, parent: ToNode | None = None) Node#

Add a type alias definition.

add_cfg(*args: Wire) Cfg[source]#

Start building a new CFG nested inside the current dataflow graph.

Parameters:

args – The input wires to the new CFG.

Returns:

Builder for new nested CFG.

Example

>>> dfg = Dfg(tys.Bool)
>>> with dfg.add_cfg(dfg.inputs()[0]) as cfg:                    cfg.parent_op
CFG(inputs=[Bool])
add_conditional(cond_wire: Wire, *args: Wire) Conditional[source]#

Start building a new conditional nested inside the current dataflow graph.

Parameters:
  • cond_wire – The wire holding the value (of Sum type) to branch the

  • on. (conditional)

  • args – Remaining input wires to the conditional.

Returns:

Builder for new nested conditional.

Example

>>> dfg = Dfg(tys.Bool, tys.Unit)
>>> (cond, unit) = dfg.inputs()
>>> cond = dfg.add_conditional(cond, unit)
>>> cond.parent_node
Node(3)
add_const(value: val.Value, parent: ToNode | None = None) Node#

Add a static constant to the graph.

Parameters:
  • value – The constant value to add.

  • parent – The parent node of the constant. Defaults to the root node.

Returns:

The node holding the Const operation.

Example

>>> dfg = Dfg()
>>> const_n = dfg.add_const(val.TRUE)
>>> dfg.hugr[const_n].op
Const(TRUE)
add_if(cond_wire: Wire, *args: Wire) If[source]#

Start building a new if block nested inside the current dataflow graph.

Parameters:
  • cond_wire – The wire holding the Bool value to branch the If on.

  • args – Remaining input wires to the If (and subsequent Else).

Returns:

Builder for new nested If.

Example

>>> dfg = Dfg(tys.Bool)
>>> (cond,) = dfg.inputs()
>>> if_ = dfg.add_if(cond, cond)
>>> if_.parent_op
Case(inputs=[Bool])
add_nested(*args: Wire) Dfg[source]#

Start building a nested dataflow graph.

Parameters:

args – The input wires to the nested DFG.

Returns:

Builder for new nested dataflow graph.

Example

>>> dfg = Dfg(tys.Bool)
>>> with dfg.add_nested(dfg.inputs()[0]) as dfg2:                   dfg2.parent_node
Node(3)
add_op(op: ops.DataflowOp, /, *args: Wire, metadata: dict[str, Any] | None = None) Node[source]#

Add a dataflow operation to the graph, wiring in input ports.

Parameters:
  • op – The operation to add.

  • args – The input wires to the operation.

  • metadata – Metadata to attach to the function definition. Defaults to None.

Returns:

The node holding the new operation.

Example

>>> dfg = Dfg(tys.Bool)
>>> dfg.add_op(ops.Noop(), dfg.inputs()[0])
Node(3)
add_state_order(src: Node, dst: Node) None[source]#

Add a state order link between two nodes.

Parameters:
  • src – The source node.

  • dst – The destination node.

Examples

>>> df = dfg.Dfg()
>>> df.add_state_order(df.input_node, df.output_node)
>>> list(df.hugr.outgoing_order_links(df.input_node))
[Node(2)]
add_tail_loop(just_inputs: Sequence[Wire], rest: Sequence[Wire]) TailLoop[source]#

Start building a new tail loop nested inside the current dataflow graph.

Parameters:
  • just_inputs – input wires for types that are only inputs to the loop body.

  • rest – input wires for types that are inputs and outputs of the loop

  • body.

Returns:

Builder for new nested TailLoop.

Example

>>> dfg = Dfg(tys.Bool)
>>> (cond,) = dfg.inputs()
>>> tl = dfg.add_tail_loop([cond], [cond])
>>> tl.parent_op
TailLoop(just_inputs=[Bool], rest=[Bool])
call(func: ToNode, *args: Wire, instantiation: tys.FunctionType | None = None, type_args: Sequence[tys.TypeArg] | None = None) Node[source]#

Call a static function in the graph. See Call for more on how polymorphic functions are handled.

Parameters:
  • func – The node corresponding to the function definition/declaration to call.

  • args – The input wires to the function call.

  • instantiation – The concrete function type to call (needed if polymorphic).

  • type_args – The type arguments for the function (needed if

  • polymorphic).

Returns:

The node holding the Call operation.

define_function(name: str, input_types: TypeRow, output_types: TypeRow | None = None, type_params: list[TypeParam] | None = None, parent: ToNode | None = None) Function#

Start building a function definition in the graph.

Parameters:
  • name – The name of the function.

  • input_types – The input types for the function.

  • output_types – The output types for the function. If not provided, it will be inferred after the function is built.

  • type_params – The type parameters for the function, if polymorphic.

  • parent – The parent node of the constant. Defaults to the root node.

Returns:

The new function builder.

extend(*coms: ops.Command) list[Node][source]#

Add a series of commands to the DFG.

Shorthand for calling add() on each command in coms.

Parameters:

coms – Commands to add.

Returns:

List of the new nodes in the same order as the commands.

Raises:

IndexError – If any input index is not a tracked wire.

Examples

>>> dfg = Dfg(tys.Bool, tys.Unit)
>>> (b, u) = dfg.inputs()
>>> dfg.extend(ops.Noop()(b), ops.Noop()(u))
[Node(3), Node(4)]
hugr: Hugr#

The Hugr instance that the builder is using.

inp(offset: int) InPort#

Generate an input port for this node.

Parameters:

offset – port offset.

Returns:

Incoming port for this node.

Examples

>>> Node(0).inp(1)
InPort(Node(0), 1)
input_node: Node#

The input node of the dataflow graph.

inputs() list[OutPort][source]#

List all incoming wires (output ports of the input node).

Example

>>> dfg = Dfg(tys.Bool)
>>> dfg.inputs()
[OutPort(Node(1), 0)]
insert_cfg(cfg: Cfg, *args: Wire) Node[source]#

Insert a CFG into the current dataflow graph, wiring in the inputs.

Parameters:
  • cfg – The CFG to insert.

  • args – The input wires to the CFG.

Returns:

The root node of the inserted CFG.

Example

>>> from hugr.cfg import Cfg
>>> dfg = Dfg(tys.Bool)
>>> cfg = Cfg(tys.Bool)
>>> dfg.insert_cfg(cfg, dfg.inputs()[0])
Node(3)
insert_conditional(cond: Conditional, cond_wire: Wire, *args: Wire) Node[source]#

Insert a conditional into the current dataflow graph, wiring in the inputs.

Parameters:
  • cond – The conditional to insert.

  • cond_wire – The wire holding the value (of Sum type) to branch the Conditional on.

  • args – Remaining input wires to the conditional.

Returns:

The root node of the inserted conditional.

Example

>>> from hugr.cond_loop import Conditional
>>> cond = Conditional(tys.Bool, [])
>>> dfg = Dfg(tys.Bool)
>>> cond_n = dfg.insert_conditional(cond, dfg.inputs()[0])
>>> dfg.hugr[cond_n].op
Conditional(sum_ty=Bool, other_inputs=[])
insert_nested(dfg: Dfg, *args: Wire) Node[source]#

Insert a nested dataflow graph into the current graph, wiring in the inputs.

Parameters:
  • dfg – The dataflow graph to insert.

  • args – The input wires to the graph.

Returns:

The root node of the inserted graph.

Example

>>> dfg = Dfg(tys.Bool)
>>> dfg2 = Dfg(tys.Bool)
>>> dfg.insert_nested(dfg2, dfg.inputs()[0])
Node(3)
insert_tail_loop(tl: TailLoop, just_inputs: Sequence[Wire], rest: Sequence[Wire]) Node[source]#

Insert a tail loop into the current dataflow graph, wiring in the inputs.

Parameters:
  • tl – The tail loop to insert.

  • just_inputs – input wires for types that are only inputs to the loop body.

  • rest – input wires for types that are inputs and outputs of the loop

  • body.

Returns:

The root node of the inserted tail loop.

Example

>>> from hugr.cond_loop import TailLoop
>>> tl = TailLoop([tys.Bool], [tys.Bool])
>>> dfg = Dfg(tys.Bool)
>>> (b,) = dfg.inputs()
>>> tl_n = dfg.insert_tail_loop(tl, [b], [b])
>>> dfg.hugr[tl_n].op
TailLoop(just_inputs=[Bool], rest=[Bool])
load(const: ToNode | val.Value, const_parent: ToNode | None = None) Node[source]#

Load a constant into the graph as a dataflow value.

Parameters:
  • const – The constant to load, either a Value that will be added as a child Const node then loaded, or a node corresponding to an existing Const.

  • const_parent – If const is a Value, the parent node for the new constant definition. Defaults to the current dataflow container.

Returns:

The node holding the LoadConst operation.

Example

>>> dfg = Dfg()
>>> const_n = dfg.load(val.TRUE)
>>> len(dfg.hugr) # parent, input, output, const, load
5
>>> dfg.hugr[const_n].op
LoadConst(Bool)
load_function(func: ToNode, instantiation: tys.FunctionType | None = None, type_args: Sequence[tys.TypeArg] | None = None) Node[source]#

Load a static function into the graph as a higher-order value.

Parameters:
  • func – The node corresponding to the function definition/declaration to load.

  • instantiation – The concrete function type to load (needed if polymorphic).

  • type_args – The type arguments for the function (needed if

  • polymorphic).

Returns:

The node holding the LoadFunc operation.

property metadata: dict[str, object]#

Metadata associated with this node.

classmethod new_nested(parent_op: DP, hugr: Hugr, parent: ToNode | None = None) Self[source]#

Start building a dataflow graph nested inside a larger HUGR.

Parameters:
  • parent_op – The parent operation of the new dataflow graph.

  • hugr – The host HUGR instance to build the dataflow graph in.

  • parent – Parent of new dataflow graph’s root node: defaults to the

  • root. (host HUGR)

Example

>>> hugr = Hugr()
>>> dfg = Dfg.new_nested(ops.DFG([]), hugr)
>>> dfg.parent_node
Node(1)
out(offset: int) OutPort#

Generate an output port for this node.

Parameters:

offset – port offset.

Returns:

Outgoing port for this node.

Examples

>>> Node(0).out(1)
OutPort(Node(0), 1)
out_port() OutPort#

OutPort corresponding to this Wire.

output_node: Node#

The output node of the dataflow graph.

outputs() Iterator[OutPort]#

Returns an iterator over the output ports of this node.

parent_node: Node#

The parent node of the dataflow graph.

property parent_op: OpVar#

The parent node’s operation.

port(offset: int, direction: Direction) InPort | OutPort#

Generate a port in direction for this node with offset.

Examples

>>> Node(0).port(1, Direction.INCOMING)
InPort(Node(0), 1)
>>> Node(0).port(1, Direction.OUTGOING)
OutPort(Node(0), 1)
set_outputs(*args: Wire) None[source]#

Set the outputs of the dataflow graph. Connects wires to the output node.

Parameters:

args – Wires to connect to the output node.

Example

>>> dfg = Dfg(tys.Bool)
>>> dfg.set_outputs(dfg.inputs()[0]) # connect input to output
to_node() Node#

Convert to a Node.