@@ -30,7 +30,7 @@ use crate::extension::resolution::{
3030 WeakExtensionRegistry ,
3131} ;
3232use crate :: extension:: { ExtensionRegistry , ExtensionSet } ;
33- use crate :: ops:: { self , NamedOp , OpTag , OpTrait } ;
33+ use crate :: ops:: { self , Module , NamedOp , OpName , OpTag , OpTrait } ;
3434pub use crate :: ops:: { OpType , DEFAULT_OPTYPE } ;
3535use crate :: { Direction , Node } ;
3636
@@ -63,7 +63,7 @@ pub struct Hugr {
6363
6464impl Default for Hugr {
6565 fn default ( ) -> Self {
66- Self :: new ( crate :: ops :: Module :: new ( ) )
66+ Self :: new ( )
6767 }
6868}
6969
@@ -89,19 +89,50 @@ pub type NodeMetadataMap = serde_json::Map<String, NodeMetadata>;
8989
9090/// Public API for HUGRs.
9191impl Hugr {
92- /// Create a new Hugr, with a single root node.
93- pub fn new ( root : impl Into < OpType > ) -> Self {
94- make_module_hugr ( root . into ( ) , 0 , 0 )
92+ /// Create a new Hugr, with a single [`Module`] operation as the root node.
93+ pub fn new ( ) -> Self {
94+ make_module_hugr ( Module :: new ( ) . into ( ) , 0 , 0 ) . unwrap ( )
9595 }
9696
97- /// Create a new Hugr, with a given root node and preallocated capacity .
97+ /// Create a new Hugr, with a given entrypoint operation .
9898 ///
99- /// If the root optype is [`OpType::Module`], the HUGR module root will
100- /// match the root node. Otherwise, the root node will be a child of the a
101- /// module created at the node hierarchy root. The specific HUGR created depends
102- /// on the operation type, and whether it can be contained
103- pub fn with_capacity ( root : impl Into < OpType > , nodes : usize , ports : usize ) -> Self {
104- make_module_hugr ( root. into ( ) , nodes, ports)
99+ /// If the optype is [`OpType::Module`], the HUGR module root will match the
100+ /// entrypoint node. Otherwise, the entrypoint will be a child of the a
101+ /// module initialized at the node hierarchy root. The specific HUGR created
102+ /// depends on the operation type.
103+ ///
104+ /// # Error
105+ ///
106+ /// Returns [`HugrError::UnsupportedEntrypoint`] if the entrypoint operation
107+ /// requires additional context to be defined. This is the case for
108+ /// [`OpType::Case`], [`OpType::DataflowBlock`], and [`OpType::ExitBlock`]
109+ /// since they are context-specific definitions.
110+ pub fn new_with_entrypoint ( entrypoint_op : impl Into < OpType > ) -> Result < Self , HugrError > {
111+ Self :: with_capacity ( entrypoint_op, 0 , 0 )
112+ }
113+
114+ /// Create a new Hugr, with a given entrypoint operation and preallocated capacity.
115+ ///
116+ /// If the optype is [`OpType::Module`], the HUGR module root will match the
117+ /// entrypoint node. Otherwise, the entrypoint will be a child of the a
118+ /// module initialized at the node hierarchy root. The specific HUGR created
119+ /// depends on the operation type.
120+ ///
121+ /// # Error
122+ ///
123+ /// Returns [`HugrError::UnsupportedEntrypoint`] if the entrypoint operation
124+ /// requires additional context to be defined. This is the case for
125+ /// [`OpType::Case`], [`OpType::DataflowBlock`], and [`OpType::ExitBlock`]
126+ /// since they are context-specific definitions.
127+ pub fn with_capacity (
128+ entrypoint_op : impl Into < OpType > ,
129+ nodes : usize ,
130+ ports : usize ,
131+ ) -> Result < Self , HugrError > {
132+ let entrypoint_op: OpType = entrypoint_op. into ( ) ;
133+ let op_name = entrypoint_op. name ( ) ;
134+ make_module_hugr ( entrypoint_op, nodes, ports)
135+ . ok_or ( HugrError :: UnsupportedEntrypoint { op : op_name } )
105136 }
106137
107138 /// Load a Hugr from a json reader.
@@ -289,6 +320,12 @@ pub enum HugrError {
289320 /// An invalid port was specified.
290321 #[ error( "Invalid port direction {0:?}." ) ]
291322 InvalidPortDirection ( Direction ) ,
323+ /// Cannot initialize a HUGR with the given entrypoint operation type.
324+ #[ error( "Cannot initialize a HUGR with entrypoint type {op}" ) ]
325+ UnsupportedEntrypoint {
326+ /// The name of the unsupported operation.
327+ op : OpName ,
328+ } ,
292329}
293330
294331/// Errors that can occur while loading and validating a Hugr json.
@@ -321,7 +358,7 @@ pub enum LoadHugrError {
321358/// Some operation types are not allowed and will result in a panic. This is the
322359/// case for [`OpType::Case`], [`OpType::DataflowBlock`], and [`OpType::ExitBlock`]
323360/// since they are context-specific operation.
324- fn make_module_hugr ( root_op : OpType , nodes : usize , ports : usize ) -> Hugr {
361+ fn make_module_hugr ( root_op : OpType , nodes : usize , ports : usize ) -> Option < Hugr > {
325362 let mut graph = MultiPortGraph :: with_capacity ( nodes, ports) ;
326363 let hierarchy = Hierarchy :: new ( ) ;
327364 let mut op_types = UnmanagedDenseMap :: with_capacity ( nodes) ;
@@ -395,28 +432,18 @@ fn make_module_hugr(root_op: OpType, nodes: usize, ports: usize) -> Hugr {
395432 }
396433 // Other more exotic ops are unsupported, and will cause a panic.
397434 else {
398- let is_expected = matches ! (
435+ debug_assert ! ( matches!(
399436 root_op,
400437 OpType :: Input ( _)
401438 | OpType :: Output ( _)
402439 | OpType :: DataflowBlock ( _)
403440 | OpType :: ExitBlock ( _)
404441 | OpType :: Case ( _)
405- ) ;
406- if is_expected {
407- panic ! (
408- "Operation type {} is not allowed as a root type of a Hugr being initialized" ,
409- root_op. name( )
410- )
411- } else {
412- panic ! (
413- "Operation type {} should have been allowed in `make_module_hugr`" ,
414- root_op. name( )
415- )
416- }
442+ ) ) ;
443+ return None ;
417444 }
418445
419- hugr
446+ Some ( hugr)
420447}
421448
422449#[ cfg( test) ]
0 commit comments