hugr_model/v0/ast/
mod.rs

1//! Abstract syntax tree representation of hugr modules.
2//!
3//! This module defines the abstract syntax tree for hugr graphs. The AST types
4//! implement [`Display`] and [`FromStr`] for pretty printing into and parsing
5//! from the s-expression based hugr text form. This is useful for debugging and
6//! writing hugr modules by hand. For a more performant serialization format, see
7//! [binary] instead.
8//!
9//! The data types in this module logically mirror those of the [table]
10//! representation, but are encoded differently. Instead of using ids, the AST
11//! data structure is recursive and uses names for symbols, variables and links.
12//! [`Term`]s, [`Node`]s and [`Region`]s can be referred to individually in this
13//! form, whereas the table form requires them to be seen in the context of a
14//! module. An AST module can be translated into a table module via [`Module::resolve`].
15//! This representation makes different efficiency tradeoffs than the table
16//! form by using standard heap based data structures instead of a bump
17//! allocated arena. This is slower but considerably more ergonomic.
18//!
19//! [binary]: crate::v0::binary
20//! [table]: crate::v0::table
21//! [`Display`]: std::fmt::Display
22//! [`FromStr`]: std::str::FromStr
23use std::sync::Arc;
24
25use bumpalo::Bump;
26
27use super::table::{self};
28use super::{LinkName, Literal, RegionKind, SymbolName, VarName};
29
30mod parse;
31mod print;
32mod resolve;
33mod view;
34
35pub use resolve::ResolveError;
36
37/// A module in the hugr AST.
38///
39/// See [`table::Module`] for the table representation.
40///
41/// [`table::Module`]: crate::v0::table::Module
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct Module {
44    /// The root region of the module.
45    ///
46    /// This must be a region of kind [`RegionKind::Module`].
47    pub root: Region,
48}
49
50impl Module {
51    /// Try to convert this module into the table representation.
52    ///
53    /// This conversion resolves the names of variables, symbols and links
54    /// according to their scoping rules described in the [`scope`] module.
55    /// Whenever a symbol is used but not defined in scope, an import node will
56    /// be inserted into the module region and all references to that symbol will
57    /// refer to the import node. This gives the opportunity to link the missing symbols.
58    ///
59    /// [`scope`]: crate::v0::scope
60    pub fn resolve<'a>(
61        &'a self,
62        bump: &'a Bump,
63    ) -> Result<table::Module<'a>, resolve::ResolveError> {
64        let mut ctx = resolve::Context::new(bump);
65        ctx.resolve_module(self)?;
66        Ok(ctx.finish())
67    }
68}
69
70/// A node in the hugr AST.
71///
72/// See [`table::Node`] for the table representation.
73///
74/// [`table::Node`]: crate::v0::table::Node
75#[derive(Debug, Clone, PartialEq, Eq, Default)]
76pub struct Node {
77    /// The operation that the node performs.
78    pub operation: Operation,
79
80    /// The names of the links connected to the input ports of the node.
81    pub inputs: Box<[LinkName]>,
82
83    /// The names of the links connected to the output ports of the node.
84    pub outputs: Box<[LinkName]>,
85
86    /// The regions in the node.
87    pub regions: Box<[Region]>,
88
89    /// Metadata attached to the node.
90    pub meta: Box<[Term]>,
91
92    /// The input/output signature of the node.
93    pub signature: Option<Term>,
94}
95
96/// The operation of a [`Node`] in the hugr AST.
97///
98/// See [`table::Operation`] for the table representation.
99///
100/// [`table::Operation`]: crate::v0::table::Operation
101#[derive(Debug, Clone, PartialEq, Eq, Default)]
102pub enum Operation {
103    /// Invalid operation to be used as a placeholder.
104    #[default]
105    Invalid,
106    /// Data flow graphs.
107    Dfg,
108    /// Control flow graphs.
109    Cfg,
110    /// Basic blocks in a control flow graph.
111    Block,
112    /// Function definitions.
113    DefineFunc(Box<Symbol>),
114    /// Function declarations.
115    DeclareFunc(Box<Symbol>),
116    /// Custom operations.
117    Custom(Term),
118    /// Alias definitions.
119    DefineAlias(Box<Symbol>, Term),
120    /// Alias declarations.
121    DeclareAlias(Box<Symbol>),
122    /// Tail controlled loops.
123    TailLoop,
124    /// Conditional operations.
125    Conditional,
126    /// Constructor declarations.
127    DeclareConstructor(Box<Symbol>),
128    /// Operation declarations.
129    DeclareOperation(Box<Symbol>),
130    /// Symbol imports.
131    Import(SymbolName),
132}
133
134impl Operation {
135    /// The name of the symbol introduced by this operation, if any.
136    pub fn symbol_name(&self) -> Option<&SymbolName> {
137        if let Operation::Import(symbol_name) = self {
138            Some(symbol_name)
139        } else {
140            Some(&self.symbol()?.name)
141        }
142    }
143
144    /// The symbol declared or defined by this operation, if any.
145    pub fn symbol(&self) -> Option<&Symbol> {
146        match self {
147            Operation::DefineFunc(symbol)
148            | Operation::DeclareFunc(symbol)
149            | Operation::DefineAlias(symbol, _)
150            | Operation::DeclareAlias(symbol)
151            | Operation::DeclareConstructor(symbol)
152            | Operation::DeclareOperation(symbol) => Some(symbol),
153            _ => None,
154        }
155    }
156}
157
158/// A symbol declaration in the hugr AST.
159///
160/// See [`table::Symbol`] for the table representation.
161///
162/// [`table::Symbol`]: crate::v0::table::Symbol
163#[derive(Debug, Clone, PartialEq, Eq)]
164pub struct Symbol {
165    /// The name of the symbol.
166    pub name: SymbolName,
167    /// The parameters of the symbol.
168    pub params: Box<[Param]>,
169    /// Constraints that the symbol imposes on the parameters.j
170    pub constraints: Box<[Term]>,
171    /// The type of the terms produced when the symbol is applied.
172    pub signature: Term,
173}
174
175/// A parameter of a [`Symbol`] in the hugr AST.
176///
177/// See [`table::Param`] for the table representation.
178///
179/// [`table::Param`]: crate::v0::table::Param
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct Param {
182    /// The name of the parameter.
183    pub name: VarName,
184    /// The type of the parameter.
185    pub r#type: Term,
186}
187
188/// A region in the hugr AST.
189///
190/// See [`table::Region`] for the table representation.
191///
192/// [`table::Region`]: crate::v0::table::Region
193#[derive(Debug, Clone, PartialEq, Eq, Default)]
194pub struct Region {
195    /// The kind of the region. See [`RegionKind`] for details.
196    pub kind: RegionKind,
197    /// The names of the links connected to the source ports of the region.
198    pub sources: Box<[LinkName]>,
199    /// The names of the links connected to the target ports of the region.
200    pub targets: Box<[LinkName]>,
201    /// The nodes in the region. The order of the nodes is not significant.
202    pub children: Box<[Node]>,
203    /// The metadata attached to the region.
204    pub meta: Box<[Term]>,
205    /// The source/target signature of the region.
206    pub signature: Option<Term>,
207}
208
209/// A term in the hugr AST.
210///
211/// To facilitate sharing where possible, terms in the AST use reference
212/// counting. This makes it cheap to clone and share terms.
213///
214/// See [`table::Term`] for the table representation.
215///
216/// [`table::Term`]: crate::v0::table::Term
217#[derive(Debug, Clone, PartialEq, Eq, Default)]
218pub enum Term {
219    /// Standin for any term.
220    #[default]
221    Wildcard,
222    /// Local variable, identified by its name.
223    Var(VarName),
224    /// Symbol application.
225    Apply(SymbolName, Arc<[Term]>),
226    /// List of static data.
227    List(Arc<[SeqPart]>),
228    /// Static literal value.
229    Literal(Literal),
230    /// Tuple of static data.
231    Tuple(Arc<[SeqPart]>),
232    /// Function constant.
233    Func(Arc<Region>),
234    /// Extension set.
235    ///
236    /// __REMARK__: Extension sets will be removed, so this is a standin.
237    ExtSet,
238}
239
240impl From<Literal> for Term {
241    fn from(value: Literal) -> Self {
242        Self::Literal(value)
243    }
244}
245
246/// A part of a tuple/list [`Term`] in the hugr AST.
247///
248/// See [`table::SeqPart`] for the table representation.
249///
250/// [`table::SeqPart`]: crate::v0::table::SeqPart
251#[derive(Debug, Clone, PartialEq, Eq)]
252pub enum SeqPart {
253    /// An individual item in the sequence.
254    Item(Term),
255    /// A sequence to be spliced into this sequence.
256    Splice(Term),
257}