Skip to content

Commit a16389f

Browse files
authored
feat: Packages in hugr-model and envelope support. (#2026)
This PR adds packages to hugr-model with support for envelopes. - Packages for both the AST and table representation of hugr-model. - Packages in the Python model classes. - Reading and writing model envelopes in Rust. - Writing model envelopes in Python.
1 parent 9ad9e6d commit a16389f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+528
-69
lines changed

hugr-core/src/envelope.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
//! - Bit 7,6: Constant "01" to make some headers ascii-printable.
3535
//!
3636
37+
#![allow(deprecated)]
38+
// TODO: Due to a bug in `derive_more`
39+
// (https://github.com/JelteF/derive_more/issues/419) we need to deactivate
40+
// deprecation warnings here. We can reactivate them once the bug is fixed by
41+
// https://github.com/JelteF/derive_more/pull/454.
42+
3743
mod header;
3844

3945
pub use header::{EnvelopeConfig, EnvelopeFormat, ZstdConfig, MAGIC_NUMBERS};
@@ -161,9 +167,11 @@ pub enum EnvelopeError {
161167
ZstdUnsupported,
162168
/// Tried to encode a package with multiple HUGRs, when only 1 was expected.
163169
#[display(
164-
"Packages with multiple HUGRs are currently unsupported. Tried to encode {count} HUGRs, when 1 was expected."
165-
)]
170+
"Packages with multiple HUGRs are currently unsupported. Tried to encode {count} HUGRs, when 1 was expected."
171+
)]
166172
#[from(ignore)]
173+
/// Deprecated: Packages with multiple HUGRs is a legacy feature that is no longer supported.
174+
#[deprecated(since = "0.15.2", note = "Multiple HUGRs are supported via packages.")]
167175
MultipleHugrs {
168176
/// The number of HUGRs in the package.
169177
count: usize,
@@ -244,7 +252,7 @@ fn decode_model(
244252
extension_registry: &ExtensionRegistry,
245253
format: EnvelopeFormat,
246254
) -> Result<Package, EnvelopeError> {
247-
use crate::{import::import_hugr, Extension};
255+
use crate::{import::import_package, Extension};
248256
use hugr_model::v0::bumpalo::Bump;
249257

250258
if format.model_version() != Some(0) {
@@ -255,7 +263,7 @@ fn decode_model(
255263
}
256264

257265
let bump = Bump::default();
258-
let module_list = hugr_model::v0::binary::read_from_reader(&mut stream, &bump)?;
266+
let model_package = hugr_model::v0::binary::read_from_reader(&mut stream, &bump)?;
259267

260268
let mut extension_registry = extension_registry.clone();
261269
if format.append_extensions() {
@@ -266,9 +274,7 @@ fn decode_model(
266274
}
267275
}
268276

269-
// TODO: Import multiple hugrs from the model?
270-
let hugr = import_hugr(&module_list, &extension_registry)?;
271-
Ok(Package::new([hugr])?)
277+
Ok(import_package(&model_package, &extension_registry)?)
272278
}
273279

274280
/// Internal implementation of [`write_envelope`] to call with/without the zstd compression wrapper.
@@ -301,25 +307,20 @@ fn encode_model(
301307
package: &Package,
302308
format: EnvelopeFormat,
303309
) -> Result<(), EnvelopeError> {
304-
use crate::export::export_hugr;
305310
use hugr_model::v0::{binary::write_to_writer, bumpalo::Bump};
306311

312+
use crate::export::export_package;
313+
307314
if format.model_version() != Some(0) {
308315
return Err(EnvelopeError::FormatUnsupported {
309316
format,
310317
feature: None,
311318
});
312319
}
313320

314-
// TODO: Export multiple hugrs to the model?
315-
if package.modules.len() != 1 {
316-
return Err(EnvelopeError::MultipleHugrs {
317-
count: package.modules.len(),
318-
});
319-
}
320321
let bump = Bump::default();
321-
let module = export_hugr(&package.modules[0], &bump);
322-
write_to_writer(&module, &mut writer)?;
322+
let model_package = export_package(package, &bump);
323+
write_to_writer(&model_package, &mut writer)?;
323324

324325
if format.append_extensions() {
325326
serde_json::to_writer(writer, &package.extensions.iter().collect_vec())?;

hugr-core/src/export.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
ops::{
66
constant::CustomSerialized, DataflowBlock, DataflowOpTrait, OpName, OpTrait, OpType, Value,
77
},
8+
package::Package,
89
std_extensions::{
910
arithmetic::{float_types::ConstF64, int_types::ConstInt},
1011
collections::array::ArrayValue,
@@ -27,6 +28,16 @@ use hugr_model::v0::{
2728
use petgraph::unionfind::UnionFind;
2829
use std::fmt::Write;
2930

31+
/// Export a [`Package`] to its representation in the model.
32+
pub fn export_package<'a>(package: &'a Package, bump: &'a Bump) -> table::Package<'a> {
33+
let modules = package
34+
.modules
35+
.iter()
36+
.map(|module| export_hugr(module, bump))
37+
.collect();
38+
table::Package { modules }
39+
}
40+
3041
/// Export a [`Hugr`] graph to its representation in the model.
3142
pub fn export_hugr<'a>(hugr: &'a Hugr, bump: &'a Bump) -> table::Module<'a> {
3243
let mut ctx = Context::new(hugr, bump);

hugr-core/src/import.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{
1414
ExitBlock, FuncDecl, FuncDefn, Input, LoadConstant, LoadFunction, Module, OpType, OpaqueOp,
1515
Output, Tag, TailLoop, Value, CFG, DFG,
1616
},
17+
package::Package,
1718
std_extensions::{
1819
arithmetic::{float_types::ConstF64, int_types::ConstInt},
1920
collections::array::ArrayValue,
@@ -79,7 +80,23 @@ macro_rules! error_uninferred {
7980
($($e:expr),*) => { ImportError::Uninferred(format!($($e),*)) }
8081
}
8182

82-
/// Import a `hugr` module from its model representation.
83+
/// Import a [`Package`] from its model representation.
84+
pub fn import_package(
85+
package: &table::Package,
86+
extensions: &ExtensionRegistry,
87+
) -> Result<Package, ImportError> {
88+
let modules = package
89+
.modules
90+
.iter()
91+
.map(|module| import_hugr(module, extensions))
92+
.collect::<Result<Vec<_>, _>>()?;
93+
94+
// This does not panic since the import already requires a module root.
95+
let package = Package::new(modules).expect("non-module root");
96+
Ok(package)
97+
}
98+
99+
/// Import a [`Hugr`] module from its model representation.
83100
pub fn import_hugr(
84101
module: &table::Module,
85102
extensions: &ExtensionRegistry,

hugr-core/tests/model.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
use std::str::FromStr;
44

55
use hugr::std_extensions::std_reg;
6-
use hugr_core::{export::export_hugr, import::import_hugr};
6+
use hugr_core::{export::export_package, import::import_package};
77
use hugr_model::v0 as model;
88

99
fn roundtrip(source: &str) -> String {
1010
let bump = model::bumpalo::Bump::new();
11-
let module_ast = model::ast::Module::from_str(source).unwrap();
12-
let module_table = module_ast.resolve(&bump).unwrap();
13-
let hugr = import_hugr(&module_table, &std_reg()).unwrap();
14-
let exported_table = export_hugr(&hugr, &bump);
11+
let package_ast = model::ast::Package::from_str(source).unwrap();
12+
let package_table = package_ast.resolve(&bump).unwrap();
13+
let core = import_package(&package_table, &std_reg()).unwrap();
14+
let exported_table = export_package(&core, &bump);
1515
let exported_ast = exported_table.as_ast().unwrap();
1616
exported_ast.to_string()
1717
}

hugr-core/tests/snapshots/model__roundtrip_add.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-add.
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.fn)
810

911
(import arithmetic.int.iadd)

hugr-core/tests/snapshots/model__roundtrip_alias.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-alia
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.fn)
810

911
(import arithmetic.int.types.int)

hugr-core/tests/snapshots/model__roundtrip_call.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-call
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.call)
810

911
(import core.load_const)

hugr-core/tests/snapshots/model__roundtrip_cfg.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cfg.
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.make_adt)
810

911
(import core.ctrl)

hugr-core/tests/snapshots/model__roundtrip_cond.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cond
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.fn)
810

911
(import core.adt)

hugr-core/tests/snapshots/model__roundtrip_const.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import collections.array.array)
810

911
(import compat.const_json)

hugr-core/tests/snapshots/model__roundtrip_constraints.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import collections.array.array)
810

911
(import core.nat)

hugr-core/tests/snapshots/model__roundtrip_loop.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-loop
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.make_adt)
810

911
(import core.type)

hugr-core/tests/snapshots/model__roundtrip_params.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-para
44
---
55
(hugr 0)
66

7+
(mod)
8+
79
(import core.fn)
810

911
(import core.type)

hugr-model/capnp/hugr-v0.capnp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ using LinkId = UInt32;
1818
# The index of a `Link`.
1919
using LinkIndex = UInt32;
2020

21+
struct Package {
22+
modules @0 :List(Module);
23+
}
24+
2125
struct Module {
2226
root @0 :RegionId;
2327
nodes @1 :List(Node);

0 commit comments

Comments
 (0)