CQCL / guppylang

Pythonic quantum-classical programming language
https://pypi.org/project/guppylang
Apache License 2.0
25 stars 2 forks source link

refactor: port HUGR codegen to use HUGR python builder #257

Closed ss2165 closed 1 month ago

ss2165 commented 3 months ago

~Blocked by non-optional tasks in tracking issue: https://github.com/CQCL/hugr/issues/486~

~Now blocked by https://github.com/CQCL/guppylang/issues/280 to avoid bad merge conflicts. (Base on working branch for that issue if starting before that is merged)~

aborgna-q commented 2 months ago

I'm planning to do this in multiple steps, starting from nodes and ports before removing the whole hugr_builder.hugr.Hugr class. There are some incompatibilities that we have to address:

Node and port subclasses

Guppy defines multiple subclasses of its abstract Node and Port classes to provide some type safety and add some handy class methods when possible. (Dashed boxes are abstract classes).

graph TB
  style Port stroke-dasharray: 5 5
  Port --> InPort
  Port --> OutPort
  InPort --> InPortV
  OutPort --> OutPortV
  InPort --> InPortCF
  OutPort --> OutPortCF
graph TB
  style Node stroke-dasharray: 5 5
  Node --> VNode
  Node --> CFNode
  style DFContainingNode stroke-dasharray: 5 5
  Node --> DFContainingNode
  DFContainingNode --> DFContainingVNode
  VNode --> DFContainingVNode
  DFContainingNode --> BlockNode
  CFNode --> BlockNode

The the value *PortV variants include their type and and a non-null offset. In the case of Nodes, each subclass adds a myriad of extra runtime checks to each method call, and type specialisations when dealing with ports.

hugr-py has no such class hierarchy, aside from OutPort and InPort. ParentBuilder could maybe be viewed as a DFContainingNode equivalent, as it implements ToNode and has similar uses.

Fat nodes and ports

Guppy's Nodes and value Ports store their OpType and Type (respectively). This is used throughout guppy to both validate that we're doing the correct thing as well as to easily access the values without explicitly passing the hugr around.

This is somewhat similar to hugr-llvm's FatNodes, but here I believe we can always access the base hugr so it's not that necessary to keep the data around.

Nodes can also be mutated, adding/removing ports to it and updating their operation based on the new ports. I believe this can be delegated to the hugr-py builder's current implementation, so we won't need this feature.

Proposed changes to guppy / hugr-py

I'd like to propose the following:

The hugr classes on both sides are fairly similar, so hopefully we shouldn't need to change hugr-py much more after this.

mark-koch commented 2 months ago

Thank you, that's a great overview of the existing setup in Guppy! I think your migration plan makes sense 👍

Proposed changes to guppy / hugr-cli

Do you mean hugr-py instead of hugr-cli?

Bring in the value/cfg port and node variants (with better names) to hugr-cli

👍

but drop the specialised parent-node classes as these are already covered by ParentBuilder's subclasses.

This would be great, but just do confirm: Do these ParentBuilder subclasses support non-local edges? @ss2165

Drop the fat nodes and ports in guppy. We should be able to modify the call sites to query the hugr instead. We could go either way here. I don't think tracking the types would change the code too much here.

I don't have a strong opinion on this, I'm fine with whatever is easier for you.

Note there might be some rough edges around types since the current ports use Guppy types instead of Hugr types. I think the transition shouldn't be too bad, but there might be some issues with type args, structs etc...

aborgna-q commented 2 months ago

Do you mean hugr-py instead of hugr-cli?

D'oh!

Note there might be some rough edges around types since the current ports use Guppy types instead of Hugr types.

Right. If we keep the slim ports then we can keep the conversion between types in guppy's Hugr for now. I will address the type definitions next.

ss2165 commented 2 months ago

Bring in the value/cfg port and node variants (with better names) to hugr-py

Can they just stay in Guppy and contain a hugr port? Not including them in hugr-py was a conscious simplicity choice in the user-facing API

Do these ParentBuilder subclasses support non-local edges? @ss2165

Yes

aborgna-q commented 2 months ago

Can they just stay in Guppy and contain a hugr port? Not including them in hugr-py was a conscious simplicity choice in the user-facing API

Those would be closely linked with the ParentBuilder variants. If DFG.add_node doesn't return a ValueNode then ValueNode is not really useful anywhere.