From b9e75fc5bc38664c1f0896ec0c1d5c5c32169f2a Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Mon, 14 Oct 2024 15:21:28 +0100 Subject: [PATCH 1/8] Emulate `TypeBound`s on parameters via constraints. --- hugr-core/Cargo.toml | 1 + hugr-core/src/export.rs | 45 +++++- hugr-core/src/import.rs | 140 ++++++++++++++---- hugr-core/tests/model.rs | 7 + .../model__roundtrip_constraints.snap | 18 +++ hugr-model/capnp/hugr-v0.capnp | 2 + hugr-model/src/v0/binary/read.rs | 7 + hugr-model/src/v0/binary/write.rs | 8 + hugr-model/src/v0/mod.rs | 12 ++ hugr-model/src/v0/text/hugr.pest | 4 + hugr-model/src/v0/text/parse.rs | 10 ++ hugr-model/src/v0/text/print.rs | 8 + .../tests/fixtures/model-constraints.edn | 15 ++ 13 files changed, 242 insertions(+), 35 deletions(-) create mode 100644 hugr-core/tests/snapshots/model__roundtrip_constraints.snap create mode 100644 hugr-model/tests/fixtures/model-constraints.edn diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index 274c21837..477f8f499 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -20,6 +20,7 @@ workspace = true extension_inference = [] declarative = ["serde_yaml"] model_unstable = ["hugr-model"] +default = ["model_unstable"] [[test]] name = "model" diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 68f3a15c0..66419fcd9 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -7,7 +7,7 @@ use crate::{ type_param::{TypeArgVariable, TypeParam}, type_row::TypeRowBase, CustomType, FuncTypeBase, MaybeRV, PolyFuncTypeBase, RowVariable, SumType, TypeArg, - TypeBase, TypeEnum, + TypeBase, TypeBound, TypeEnum, }, Direction, Hugr, HugrView, IncomingPort, Node, Port, }; @@ -46,6 +46,8 @@ struct Context<'a> { term_map: FxHashMap, model::TermId>, /// The current scope for local variables. local_scope: Option, + /// Constraints to be added to the local scope. + local_constraints: Vec, /// Mapping from extension operations to their declarations. decl_operations: FxHashMap<(ExtensionId, OpName), model::NodeId>, } @@ -63,6 +65,7 @@ impl<'a> Context<'a> { term_map: FxHashMap::default(), local_scope: None, decl_operations: FxHashMap::default(), + local_constraints: Vec::new(), } } @@ -173,9 +176,11 @@ impl<'a> Context<'a> { } fn with_local_scope(&mut self, node: model::NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let old_scope = self.local_scope.replace(node); + let prev_local_scope = self.local_scope.replace(node); + let prev_local_constraints = std::mem::take(&mut self.local_constraints); let result = f(self); - self.local_scope = old_scope; + self.local_scope = prev_local_scope; + self.local_constraints = prev_local_constraints; result } @@ -676,14 +681,23 @@ impl<'a> Context<'a> { t: &PolyFuncTypeBase, ) -> (&'a [model::Param<'a>], model::TermId) { let mut params = BumpVec::with_capacity_in(t.params().len(), self.bump); + let scope = self + .local_scope + .expect("exporting poly func type outside of local scope"); for (i, param) in t.params().iter().enumerate() { let name = self.bump.alloc_str(&i.to_string()); - let r#type = self.export_type_param(param); + let r#type = self.export_type_param(param, Some(model::LocalRef::Index(scope, i as _))); let param = model::Param::Implicit { name, r#type }; params.push(param) } + params.extend( + self.local_constraints + .drain(..) + .map(|constraint| model::Param::Constraint { constraint }), + ); + let body = self.export_func_type(t.body()); (params.into_bump_slice(), body) @@ -794,20 +808,35 @@ impl<'a> Context<'a> { self.make_term(model::Term::List { items, tail: None }) } - pub fn export_type_param(&mut self, t: &TypeParam) -> model::TermId { + pub fn export_type_param( + &mut self, + t: &TypeParam, + var: Option>, + ) -> model::TermId { match t { // This ignores the type bound for now. - TypeParam::Type { .. } => self.make_term(model::Term::Type), + TypeParam::Type { b } => { + if let (Some(var), TypeBound::Copyable) = (var, b) { + let term = self.make_term(model::Term::Var(var)); + let copy = self.make_term(model::Term::CopyConstraint { term }); + let discard = self.make_term(model::Term::DiscardConstraint { term }); + self.local_constraints.extend([copy, discard]); + } + + self.make_term(model::Term::Type) + } // This ignores the type bound for now. TypeParam::BoundedNat { .. } => self.make_term(model::Term::NatType), TypeParam::String => self.make_term(model::Term::StrType), TypeParam::List { param } => { - let item_type = self.export_type_param(param); + let item_type = self.export_type_param(param, None); self.make_term(model::Term::ListType { item_type }) } TypeParam::Tuple { params } => { let items = self.bump.alloc_slice_fill_iter( - params.iter().map(|param| self.export_type_param(param)), + params + .iter() + .map(|param| self.export_type_param(param, None)), ); let types = self.make_term(model::Term::List { items, tail: None }); self.make_term(model::Term::ApplyFull { diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index feabe815f..f93f0da47 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -116,7 +116,7 @@ struct Context<'a> { nodes: FxHashMap, /// The types of the local variables that are currently in scope. - local_variables: FxIndexMap<&'a str, model::TermId>, + local_variables: FxIndexMap<&'a str, LocalVar>, custom_name_cache: FxHashMap<&'a str, (ExtensionId, SmolStr)>, } @@ -159,16 +159,16 @@ impl<'a> Context<'a> { fn resolve_local_ref( &self, local_ref: &model::LocalRef, - ) -> Result<(usize, model::TermId), ImportError> { + ) -> Result<(usize, LocalVar), ImportError> { let term = match local_ref { model::LocalRef::Index(_, index) => self .local_variables .get_index(*index as usize) - .map(|(_, term)| (*index as usize, *term)), + .map(|(_, v)| (*index as usize, *v)), model::LocalRef::Named(name) => self .local_variables .get_full(name) - .map(|(index, _, term)| (index, *term)), + .map(|(index, _, v)| (index, *v)), }; term.ok_or_else(|| model::ModelError::InvalidLocal(local_ref.to_string()).into()) @@ -893,20 +893,65 @@ impl<'a> Context<'a> { let mut imported_params = Vec::with_capacity(decl.params.len()); for param in decl.params { - // TODO: `PolyFuncType` should be able to handle constraints - // and distinguish between implicit and explicit parameters. match param { model::Param::Implicit { name, r#type } => { - imported_params.push(ctx.import_type_param(*r#type)?); - ctx.local_variables.insert(name, *r#type); + ctx.local_variables.insert(name, LocalVar::new(*r#type)); } model::Param::Explicit { name, r#type } => { - imported_params.push(ctx.import_type_param(*r#type)?); - ctx.local_variables.insert(name, *r#type); + ctx.local_variables.insert(name, LocalVar::new(*r#type)); } - model::Param::Constraint { constraint: _ } => { - return Err(error_unsupported!("constraints")); + model::Param::Constraint { .. } => {} + } + } + + for param in decl.params { + if let model::Param::Constraint { constraint } = param { + let constraint = ctx.get_term(*constraint)?; + + match constraint { + model::Term::CopyConstraint { term } => { + let model::Term::Var(var) = ctx.get_term(*term)? else { + return Err(error_unsupported!( + "constraint on term that is not a variable" + )); + }; + + let var = ctx.resolve_local_ref(var)?.0; + ctx.local_variables.get_index_mut(var).unwrap().1.copy = true; + } + model::Term::DiscardConstraint { term } => { + let model::Term::Var(var) = ctx.get_term(*term)? else { + return Err(error_unsupported!( + "constraint on term that is not a variable" + )); + }; + + let var = ctx.resolve_local_ref(var)?.0; + ctx.local_variables.get_index_mut(var).unwrap().1.discard = true; + } + _ => { + return Err(error_unsupported!("constraint other than copy or discard")) + } + } + } + } + + let mut index = 0; + + for param in decl.params { + // TODO: `PolyFuncType` should be able to distinguish between implicit and explicit parameters. + match param { + model::Param::Implicit { r#type, .. } => { + let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; + imported_params.push(ctx.import_type_param(*r#type, bound)?); + index += 1; + } + model::Param::Explicit { r#type, .. } => { + let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; + imported_params.push(ctx.import_type_param(*r#type, bound)?); + index += 1; } + model::Param::Constraint { constraint: _ } => {} } } @@ -916,17 +961,15 @@ impl<'a> Context<'a> { } /// Import a [`TypeParam`] from a term that represents a static type. - fn import_type_param(&mut self, term_id: model::TermId) -> Result { + fn import_type_param( + &mut self, + term_id: model::TermId, + bound: TypeBound, + ) -> Result { match self.get_term(term_id)? { model::Term::Wildcard => Err(error_uninferred!("wildcard")), - model::Term::Type => { - // As part of the migration from `TypeBound`s to constraints, we pretend that all - // `TypeBound`s are copyable. - Ok(TypeParam::Type { - b: TypeBound::Copyable, - }) - } + model::Term::Type => Ok(TypeParam::Type { b: bound }), model::Term::StaticType => Err(error_unsupported!("`type` as `TypeParam`")), model::Term::Constraint => Err(error_unsupported!("`constraint` as `TypeParam`")), @@ -938,7 +981,7 @@ impl<'a> Context<'a> { model::Term::FuncType { .. } => Err(error_unsupported!("`(fn ...)` as `TypeParam`")), model::Term::ListType { item_type } => { - let param = Box::new(self.import_type_param(*item_type)?); + let param = Box::new(self.import_type_param(*item_type, TypeBound::Any)?); Ok(TypeParam::List { param }) } @@ -952,7 +995,11 @@ impl<'a> Context<'a> { | model::Term::List { .. } | model::Term::ExtSet { .. } | model::Term::Adt { .. } - | model::Term::Control { .. } => Err(model::ModelError::TypeError(term_id).into()), + | model::Term::Control { .. } + | model::Term::CopyConstraint { .. } + | model::Term::DiscardConstraint { .. } => { + Err(model::ModelError::TypeError(term_id).into()) + } model::Term::ControlType => { Err(error_unsupported!("type of control types as `TypeParam`")) @@ -960,7 +1007,7 @@ impl<'a> Context<'a> { } } - /// Import a `TypeArg` froma term that represents a static type or value. + /// Import a `TypeArg` from a term that represents a static type or value. fn import_type_arg(&mut self, term_id: model::TermId) -> Result { match self.get_term(term_id)? { model::Term::Wildcard => Err(error_uninferred!("wildcard")), @@ -969,8 +1016,9 @@ impl<'a> Context<'a> { } model::Term::Var(var) => { - let (index, var_type) = self.resolve_local_ref(var)?; - let decl = self.import_type_param(var_type)?; + let (index, var) = self.resolve_local_ref(var)?; + let bound = var.bound()?; + let decl = self.import_type_param(var.r#type, bound)?; Ok(TypeArg::new_var_use(index, decl)) } @@ -1008,7 +1056,11 @@ impl<'a> Context<'a> { model::Term::FuncType { .. } | model::Term::Adt { .. } - | model::Term::Control { .. } => Err(model::ModelError::TypeError(term_id).into()), + | model::Term::Control { .. } + | model::Term::CopyConstraint { .. } + | model::Term::DiscardConstraint { .. } => { + Err(model::ModelError::TypeError(term_id).into()) + } } } @@ -1109,7 +1161,11 @@ impl<'a> Context<'a> { | model::Term::List { .. } | model::Term::Control { .. } | model::Term::ControlType - | model::Term::Nat(_) => Err(model::ModelError::TypeError(term_id).into()), + | model::Term::Nat(_) + | model::Term::DiscardConstraint { .. } + | model::Term::CopyConstraint { .. } => { + Err(model::ModelError::TypeError(term_id).into()) + } } } @@ -1285,3 +1341,33 @@ impl<'a> Names<'a> { Ok(Self { items }) } } + +#[derive(Debug, Clone, Copy)] +struct LocalVar { + r#type: model::TermId, + copy: bool, + discard: bool, +} + +impl LocalVar { + pub fn new(r#type: model::TermId) -> Self { + Self { + r#type, + copy: false, + discard: false, + } + } + + pub fn bound(&self) -> Result { + match (self.copy, self.discard) { + (true, true) => Ok(TypeBound::Copyable), + (false, false) => Ok(TypeBound::Any), + (true, false) => Err(error_unsupported!( + "type that is copyable but not discardable" + )), + (false, true) => Err(error_unsupported!( + "type that is discardable but not copyable" + )), + } + } +} diff --git a/hugr-core/tests/model.rs b/hugr-core/tests/model.rs index 611eda660..d9ef0d2c9 100644 --- a/hugr-core/tests/model.rs +++ b/hugr-core/tests/model.rs @@ -58,3 +58,10 @@ pub fn test_roundtrip_params() { "../../hugr-model/tests/fixtures/model-params.edn" ))); } + +#[test] +pub fn test_roundtrip_constraints() { + insta::assert_snapshot!(roundtrip(include_str!( + "../../hugr-model/tests/fixtures/model-constraints.edn" + ))); +} diff --git a/hugr-core/tests/snapshots/model__roundtrip_constraints.snap b/hugr-core/tests/snapshots/model__roundtrip_constraints.snap new file mode 100644 index 000000000..372a98a2f --- /dev/null +++ b/hugr-core/tests/snapshots/model__roundtrip_constraints.snap @@ -0,0 +1,18 @@ +--- +source: hugr-core/tests/model.rs +expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-constraints.edn\"))" +--- +(hugr 0) + +(declare-func array.replicate + (forall ?0 type) + (forall ?1 nat) + (where (copy ?0)) + (where (discard ?0)) + [?0] [(@ array.Array ?0 ?1)] (ext)) + +(declare-func tuple.copy + (forall ?0 type) + (where (copy ?0)) + (where (discard ?0)) + [(@ foo.tuple ?0)] [(@ foo.tuple ?0) (@ foo.tuple ?0)] (ext)) diff --git a/hugr-model/capnp/hugr-v0.capnp b/hugr-model/capnp/hugr-v0.capnp index 95db81205..644607dc5 100644 --- a/hugr-model/capnp/hugr-v0.capnp +++ b/hugr-model/capnp/hugr-v0.capnp @@ -157,6 +157,8 @@ struct Term { funcType @17 :FuncType; control @18 :TermId; controlType @19 :Void; + copyConstraint @20 :TermId; + discardConstraint @21 :TermId; } struct Apply { diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index 681bd4ea9..5e305f964 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -332,6 +332,13 @@ fn read_term<'a>(bump: &'a Bump, reader: hugr_capnp::term::Reader) -> ReadResult Which::Control(values) => model::Term::Control { values: model::TermId(values), }, + + Which::CopyConstraint(term) => model::Term::CopyConstraint { + term: model::TermId(term), + }, + Which::DiscardConstraint(term) => model::Term::DiscardConstraint { + term: model::TermId(term), + }, }) } diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index a4b64d646..6da291e44 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -212,5 +212,13 @@ fn write_term(mut builder: hugr_capnp::term::Builder, term: &model::Term) { builder.set_outputs(outputs.0); builder.set_extensions(extensions.0); } + + model::Term::CopyConstraint { term } => { + builder.set_copy_constraint(term.0); + } + + model::Term::DiscardConstraint { term } => { + builder.set_discard_constraint(term.0); + } } } diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index cb8713b32..40f17a4fc 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -662,6 +662,18 @@ pub enum Term<'a> { /// /// `ctrl : static` ControlType, + + /// Constraint that requires a runtime type to be copyable. + CopyConstraint { + /// The runtime type that must be copyable. + term: TermId, + }, + + /// Constraint that requires a runtime type to be discardable. + DiscardConstraint { + /// The runtime type that must be discardable. + term: TermId, + }, } /// A parameter to a function or alias. diff --git a/hugr-model/src/v0/text/hugr.pest b/hugr-model/src/v0/text/hugr.pest index 132d78567..be6609656 100644 --- a/hugr-model/src/v0/text/hugr.pest +++ b/hugr-model/src/v0/text/hugr.pest @@ -92,6 +92,8 @@ term = { | term_ctrl_type | term_apply_full | term_apply + | term_copy + | term_discard } term_wildcard = { "_" } @@ -114,3 +116,5 @@ term_adt = { "(" ~ "adt" ~ term ~ ")" } term_func_type = { "(" ~ "fn" ~ term ~ term ~ term ~ ")" } term_ctrl = { "(" ~ "ctrl" ~ term ~ ")" } term_ctrl_type = { "ctrl" } +term_copy = { "(" ~ "copy" ~ term ~ ")" } +term_discard = { "(" ~ "discard" ~ term ~ ")" } diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index fa486454b..2d158687e 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -209,6 +209,16 @@ impl<'a> ParseContext<'a> { Term::Control { values } } + Rule::term_copy => { + let term = self.parse_term(inner.next().unwrap())?; + Term::CopyConstraint { term } + } + + Rule::term_discard => { + let term = self.parse_term(inner.next().unwrap())?; + Term::DiscardConstraint { term } + } + r => unreachable!("term: {:?}", r), }; diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 01b9d7195..041445bac 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -598,6 +598,14 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { self.print_text("ctrl"); Ok(()) } + Term::CopyConstraint { term } => self.print_parens(|this| { + this.print_text("copy"); + this.print_term(*term) + }), + Term::DiscardConstraint { term } => self.print_parens(|this| { + this.print_text("discard"); + this.print_term(*term) + }), } } diff --git a/hugr-model/tests/fixtures/model-constraints.edn b/hugr-model/tests/fixtures/model-constraints.edn new file mode 100644 index 000000000..f1011cef7 --- /dev/null +++ b/hugr-model/tests/fixtures/model-constraints.edn @@ -0,0 +1,15 @@ +(hugr 0) + +(declare-func array.replicate + (forall ?t type) + (forall ?n nat) + (where (copy ?t)) + (where (discard ?t)) + [?t] [(@ array.Array ?t ?n)] + (ext)) + +(declare-func tuple.copy + (forall ?t type) + (where (copy ?t)) + (where (discard ?t)) + [(@ foo.tuple ?t)] [(@ foo.tuple ?t) (@ foo.tuple ?t)] (ext)) From 0293340f85386926bbbcd3da1ab44524ae8ac33e Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Wed, 13 Nov 2024 13:15:11 +0000 Subject: [PATCH 2/8] Separate parameters and constraints in declarations. --- hugr-core/src/export.rs | 23 +++++++------ hugr-core/src/import.rs | 52 +++++++++++++---------------- hugr-model/capnp/hugr-v0.capnp | 21 +++++++----- hugr-model/src/v0/binary/read.rs | 16 ++++++--- hugr-model/src/v0/binary/write.rs | 3 +- hugr-model/src/v0/mod.rs | 15 +++++---- hugr-model/src/v0/text/hugr.pest | 16 ++++----- hugr-model/src/v0/text/parse.rs | 24 +++++++++++--- hugr-model/src/v0/text/print.rs | 54 ++++++++++++++++++------------- 9 files changed, 127 insertions(+), 97 deletions(-) diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 66419fcd9..a56219d63 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -237,10 +237,11 @@ impl<'a> Context<'a> { OpType::FuncDefn(func) => self.with_local_scope(node_id, |this| { let name = this.get_func_name(node).unwrap(); - let (params, signature) = this.export_poly_func_type(&func.signature); + let (params, constraints, signature) = this.export_poly_func_type(&func.signature); let decl = this.bump.alloc(model::FuncDecl { name, params, + constraints, signature, }); let extensions = this.export_ext_set(&func.signature.body().extension_reqs); @@ -252,10 +253,11 @@ impl<'a> Context<'a> { OpType::FuncDecl(func) => self.with_local_scope(node_id, |this| { let name = this.get_func_name(node).unwrap(); - let (params, func) = this.export_poly_func_type(&func.signature); + let (params, constraints, func) = this.export_poly_func_type(&func.signature); let decl = this.bump.alloc(model::FuncDecl { name, params, + constraints, signature: func, }); model::Operation::DeclareFunc { decl } @@ -267,6 +269,7 @@ impl<'a> Context<'a> { let decl = this.bump.alloc(model::AliasDecl { name: &alias.name, params: &[], + constraints: &[], r#type, }); model::Operation::DeclareAlias { decl } @@ -279,6 +282,7 @@ impl<'a> Context<'a> { let decl = this.bump.alloc(model::AliasDecl { name: &alias.name, params: &[], + constraints: &[], r#type, }); model::Operation::DefineAlias { decl, value } @@ -455,10 +459,11 @@ impl<'a> Context<'a> { let decl = self.with_local_scope(node, |this| { let name = this.make_qualified_name(opdef.extension(), opdef.name()); - let (params, r#type) = this.export_poly_func_type(poly_func_type); + let (params, constraints, r#type) = this.export_poly_func_type(poly_func_type); let decl = this.bump.alloc(model::OperationDecl { name, params, + constraints, r#type, }); decl @@ -679,7 +684,7 @@ impl<'a> Context<'a> { pub fn export_poly_func_type( &mut self, t: &PolyFuncTypeBase, - ) -> (&'a [model::Param<'a>], model::TermId) { + ) -> (&'a [model::Param<'a>], &'a [model::TermId], model::TermId) { let mut params = BumpVec::with_capacity_in(t.params().len(), self.bump); let scope = self .local_scope @@ -692,15 +697,13 @@ impl<'a> Context<'a> { params.push(param) } - params.extend( - self.local_constraints - .drain(..) - .map(|constraint| model::Param::Constraint { constraint }), - ); + let constraints = self + .bump + .alloc_slice_fill_iter(self.local_constraints.drain(..)); let body = self.export_func_type(t.body()); - (params.into_bump_slice(), body) + (params.into_bump_slice(), constraints, body) } pub fn export_type(&mut self, t: &TypeBase) -> model::TermId { diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index f93f0da47..ef847e01e 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -900,39 +900,32 @@ impl<'a> Context<'a> { model::Param::Explicit { name, r#type } => { ctx.local_variables.insert(name, LocalVar::new(*r#type)); } - model::Param::Constraint { .. } => {} } } - for param in decl.params { - if let model::Param::Constraint { constraint } = param { - let constraint = ctx.get_term(*constraint)?; - - match constraint { - model::Term::CopyConstraint { term } => { - let model::Term::Var(var) = ctx.get_term(*term)? else { - return Err(error_unsupported!( - "constraint on term that is not a variable" - )); - }; - - let var = ctx.resolve_local_ref(var)?.0; - ctx.local_variables.get_index_mut(var).unwrap().1.copy = true; - } - model::Term::DiscardConstraint { term } => { - let model::Term::Var(var) = ctx.get_term(*term)? else { - return Err(error_unsupported!( - "constraint on term that is not a variable" - )); - }; - - let var = ctx.resolve_local_ref(var)?.0; - ctx.local_variables.get_index_mut(var).unwrap().1.discard = true; - } - _ => { - return Err(error_unsupported!("constraint other than copy or discard")) - } + for constraint in decl.constraints { + match ctx.get_term(*constraint)? { + model::Term::CopyConstraint { term } => { + let model::Term::Var(var) = ctx.get_term(*term)? else { + return Err(error_unsupported!( + "constraint on term that is not a variable" + )); + }; + + let var = ctx.resolve_local_ref(var)?.0; + ctx.local_variables.get_index_mut(var).unwrap().1.copy = true; + } + model::Term::DiscardConstraint { term } => { + let model::Term::Var(var) = ctx.get_term(*term)? else { + return Err(error_unsupported!( + "constraint on term that is not a variable" + )); + }; + + let var = ctx.resolve_local_ref(var)?.0; + ctx.local_variables.get_index_mut(var).unwrap().1.discard = true; } + _ => return Err(error_unsupported!("constraint other than copy or discard")), } } @@ -951,7 +944,6 @@ impl<'a> Context<'a> { imported_params.push(ctx.import_type_param(*r#type, bound)?); index += 1; } - model::Param::Constraint { constraint: _ } => {} } } diff --git a/hugr-model/capnp/hugr-v0.capnp b/hugr-model/capnp/hugr-v0.capnp index 644607dc5..de4bf3b8b 100644 --- a/hugr-model/capnp/hugr-v0.capnp +++ b/hugr-model/capnp/hugr-v0.capnp @@ -56,38 +56,44 @@ struct Operation { struct FuncDefn { name @0 :Text; params @1 :List(Param); - signature @2 :TermId; + constraints @2 :List(TermId); + signature @3 :TermId; } struct FuncDecl { name @0 :Text; params @1 :List(Param); - signature @2 :TermId; + constraints @2 :List(TermId); + signature @3 :TermId; } struct AliasDefn { name @0 :Text; params @1 :List(Param); - type @2 :TermId; - value @3 :TermId; + constraints @2 :List(TermId); + type @3 :TermId; + value @4 :TermId; } struct AliasDecl { name @0 :Text; params @1 :List(Param); - type @2 :TermId; + constraints @2 :List(TermId); + type @3 :TermId; } struct ConstructorDecl { name @0 :Text; params @1 :List(Param); - type @2 :TermId; + constraints @2 :List(TermId); + type @3 :TermId; } struct OperationDecl { name @0 :Text; params @1 :List(Param); - type @2 :TermId; + constraints @2 :List(TermId); + type @3 :TermId; } } @@ -192,7 +198,6 @@ struct Param { union { implicit @0 :Implicit; explicit @1 :Explicit; - constraint @2 :TermId; } struct Implicit { diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index 5e305f964..0447878d1 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -140,10 +140,12 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let signature = model::TermId(reader.get_signature()); let decl = bump.alloc(model::FuncDecl { name, params, + constraints, signature, }); model::Operation::DefineFunc { decl } @@ -152,10 +154,12 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let signature = model::TermId(reader.get_signature()); let decl = bump.alloc(model::FuncDecl { name, params, + constraints, signature, }); model::Operation::DeclareFunc { decl } @@ -164,11 +168,13 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let value = model::TermId(reader.get_value()); let decl = bump.alloc(model::AliasDecl { name, params, + constraints, r#type, }); model::Operation::DefineAlias { decl, value } @@ -177,10 +183,12 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let decl = bump.alloc(model::AliasDecl { name, params, + constraints, r#type, }); model::Operation::DeclareAlias { decl } @@ -189,10 +197,12 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let decl = bump.alloc(model::ConstructorDecl { name, params, + constraints, r#type, }); model::Operation::DeclareConstructor { decl } @@ -201,10 +211,12 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); + let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let decl = bump.alloc(model::OperationDecl { name, params, + constraints, r#type, }); model::Operation::DeclareOperation { decl } @@ -369,9 +381,5 @@ fn read_param<'a>( let r#type = model::TermId(reader.get_type()); model::Param::Explicit { name, r#type } } - Which::Constraint(constraint) => { - let constraint = model::TermId(constraint); - model::Param::Constraint { constraint } - } }) } diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index 6da291e44..2b709389a 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -100,7 +100,7 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode } } -fn write_param(mut builder: hugr_capnp::param::Builder, param: &model::Param) { +fn write_param(builder: hugr_capnp::param::Builder, param: &model::Param) { match param { model::Param::Implicit { name, r#type } => { let mut builder = builder.init_implicit(); @@ -112,7 +112,6 @@ fn write_param(mut builder: hugr_capnp::param::Builder, param: &model::Param) { builder.set_name(name); builder.set_type(r#type.0); } - model::Param::Constraint { constraint } => builder.set_constraint(constraint.0), } } diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index 40f17a4fc..12ce5d115 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -397,6 +397,8 @@ pub struct FuncDecl<'a> { pub name: &'a str, /// The static parameters of the function. pub params: &'a [Param<'a>], + /// The constraints on the static parameters. + pub constraints: &'a [TermId], /// The signature of the function. pub signature: TermId, } @@ -408,6 +410,8 @@ pub struct AliasDecl<'a> { pub name: &'a str, /// The static parameters of the alias. pub params: &'a [Param<'a>], + /// The constraints on the static parameters. + pub constraints: &'a [TermId], /// The type of the alias. pub r#type: TermId, } @@ -419,6 +423,8 @@ pub struct ConstructorDecl<'a> { pub name: &'a str, /// The static parameters of the constructor. pub params: &'a [Param<'a>], + /// The constraints on the static parameters. + pub constraints: &'a [TermId], /// The type of the constructed term. pub r#type: TermId, } @@ -430,6 +436,8 @@ pub struct OperationDecl<'a> { pub name: &'a str, /// The static parameters of the operation. pub params: &'a [Param<'a>], + /// The constraints on the static parameters. + pub constraints: &'a [TermId], /// The type of the operation. This must be a function type. pub r#type: TermId, } @@ -701,13 +709,6 @@ pub enum Param<'a> { /// This must be a term of type `static`. r#type: TermId, }, - /// A constraint that should be satisfied by other parameters in a parameter list. - Constraint { - /// The constraint to be satisfied. - /// - /// This must be a term of type `constraint`. - constraint: TermId, - }, } /// Errors that can occur when traversing and interpreting the model. diff --git a/hugr-model/src/v0/text/hugr.pest b/hugr-model/src/v0/text/hugr.pest index be6609656..62f980ef0 100644 --- a/hugr-model/src/v0/text/hugr.pest +++ b/hugr-model/src/v0/text/hugr.pest @@ -56,16 +56,16 @@ node_tag = { "(" ~ "tag" ~ tag ~ port_lists? ~ signature? ~ meta* node_custom = { "(" ~ (term_apply | term_apply_full) ~ port_lists? ~ signature? ~ meta* ~ region* ~ ")" } signature = { "(" ~ "signature" ~ term ~ ")" } -func_header = { symbol ~ param* ~ term ~ term ~ term } -alias_header = { symbol ~ param* ~ term } -ctr_header = { symbol ~ param* ~ term } -operation_header = { symbol ~ param* ~ term } +func_header = { symbol ~ param* ~ where_clause* ~ term ~ term ~ term } +alias_header = { symbol ~ param* ~ where_clause* ~ term } +ctr_header = { symbol ~ param* ~ where_clause* ~ term } +operation_header = { symbol ~ param* ~ where_clause* ~ term } -param = { param_implicit | param_explicit | param_constraint } +param = { param_implicit | param_explicit } -param_implicit = { "(" ~ "forall" ~ term_var ~ term ~ ")" } -param_explicit = { "(" ~ "param" ~ term_var ~ term ~ ")" } -param_constraint = { "(" ~ "where" ~ term ~ ")" } +param_implicit = { "(" ~ "forall" ~ term_var ~ term ~ ")" } +param_explicit = { "(" ~ "param" ~ term_var ~ term ~ ")" } +where_clause = { "(" ~ "where" ~ term ~ ")" } region = { region_dfg | region_cfg } region_dfg = { "(" ~ "dfg" ~ port_lists? ~ signature? ~ meta* ~ node* ~ ")" } diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index 2d158687e..b7f3fa629 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -554,6 +554,7 @@ impl<'a> ParseContext<'a> { let mut inner = pair.into_inner(); let name = self.parse_symbol(&mut inner)?; let params = self.parse_params(&mut inner)?; + let constraints = self.parse_constraints(&mut inner)?; let inputs = self.parse_term(inner.next().unwrap())?; let outputs = self.parse_term(inner.next().unwrap())?; @@ -569,6 +570,7 @@ impl<'a> ParseContext<'a> { Ok(self.bump.alloc(FuncDecl { name, params, + constraints, signature: func, })) } @@ -579,11 +581,13 @@ impl<'a> ParseContext<'a> { let mut inner = pair.into_inner(); let name = self.parse_symbol(&mut inner)?; let params = self.parse_params(&mut inner)?; + let constraints = self.parse_constraints(&mut inner)?; let r#type = self.parse_term(inner.next().unwrap())?; Ok(self.bump.alloc(AliasDecl { name, params, + constraints, r#type, })) } @@ -594,11 +598,13 @@ impl<'a> ParseContext<'a> { let mut inner = pair.into_inner(); let name = self.parse_symbol(&mut inner)?; let params = self.parse_params(&mut inner)?; + let constraints = self.parse_constraints(&mut inner)?; let r#type = self.parse_term(inner.next().unwrap())?; Ok(self.bump.alloc(ConstructorDecl { name, params, + constraints, r#type, })) } @@ -609,11 +615,13 @@ impl<'a> ParseContext<'a> { let mut inner = pair.into_inner(); let name = self.parse_symbol(&mut inner)?; let params = self.parse_params(&mut inner)?; + let constraints = self.parse_constraints(&mut inner)?; let r#type = self.parse_term(inner.next().unwrap())?; Ok(self.bump.alloc(OperationDecl { name, params, + constraints, r#type, })) } @@ -637,11 +645,6 @@ impl<'a> ParseContext<'a> { let r#type = self.parse_term(inner.next().unwrap())?; Param::Explicit { name, r#type } } - Rule::param_constraint => { - let mut inner = param.into_inner(); - let constraint = self.parse_term(inner.next().unwrap())?; - Param::Constraint { constraint } - } _ => unreachable!(), }; @@ -651,6 +654,17 @@ impl<'a> ParseContext<'a> { Ok(self.bump.alloc_slice_copy(¶ms)) } + fn parse_constraints(&mut self, pairs: &mut Pairs<'a, Rule>) -> ParseResult<&'a [TermId]> { + let mut constraints = Vec::new(); + + for pair in filter_rule(pairs, Rule::where_clause) { + let constraint = self.parse_term(pair.into_inner().next().unwrap())?; + constraints.push(constraint); + } + + Ok(self.bump.alloc_slice_copy(&constraints)) + } + fn parse_signature(&mut self, pairs: &mut Pairs<'a, Rule>) -> ParseResult> { let Some(Rule::signature) = pairs.peek().map(|p| p.as_rule()) else { return Ok(None); diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 041445bac..6568c37a4 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -127,7 +127,6 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { match param { Param::Implicit { name, .. } => self.locals.push(name), Param::Explicit { name, .. } => self.locals.push(name), - Param::Constraint { .. } => {} } } @@ -178,9 +177,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; match self.module.get_term(decl.signature) { Some(Term::FuncType { @@ -208,9 +206,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; match self.module.get_term(decl.signature) { Some(Term::FuncType { @@ -303,9 +300,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_term(*value)?; @@ -318,9 +314,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_meta(node_data.meta)?; @@ -333,9 +328,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_meta(node_data.meta)?; @@ -348,9 +342,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(decl.name); }); - for param in decl.params { - this.print_param(*param)?; - } + this.print_params(decl.params)?; + this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_meta(node_data.meta)?; @@ -460,6 +453,14 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { } } + fn print_params(&mut self, params: &'a [Param<'a>]) -> PrintResult<()> { + for param in params { + self.print_param(*param)?; + } + + Ok(()) + } + fn print_param(&mut self, param: Param<'a>) -> PrintResult<()> { self.print_parens(|this| match param { Param::Implicit { name, r#type } => { @@ -472,13 +473,20 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { this.print_text(format!("?{}", name)); this.print_term(r#type) } - Param::Constraint { constraint } => { - this.print_text("where"); - this.print_term(constraint) - } }) } + fn print_constraints(&mut self, terms: &'a [TermId]) -> PrintResult<()> { + for term in terms { + self.print_parens(|this| { + this.print_text("where"); + this.print_term(*term) + })?; + } + + Ok(()) + } + fn print_term(&mut self, term_id: TermId) -> PrintResult<()> { let term_data = self .module From 1cba000c0ba45ec715114d0158ac2017cdbb9beb Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Wed, 13 Nov 2024 13:30:40 +0000 Subject: [PATCH 3/8] Simplified param representation. --- hugr-core/src/export.rs | 6 +++++- hugr-core/src/import.rs | 33 +++++++---------------------- hugr-model/capnp/hugr-v0.capnp | 20 +++++++----------- hugr-model/src/v0/binary/read.rs | 24 ++++++++------------- hugr-model/src/v0/binary/write.rs | 20 +++++++----------- hugr-model/src/v0/mod.rs | 35 ++++++++++++++----------------- hugr-model/src/v0/text/parse.rs | 14 ++++++++++--- hugr-model/src/v0/text/print.rs | 32 ++++++++++------------------ 8 files changed, 74 insertions(+), 110 deletions(-) diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index a56219d63..11be37c20 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -693,7 +693,11 @@ impl<'a> Context<'a> { for (i, param) in t.params().iter().enumerate() { let name = self.bump.alloc_str(&i.to_string()); let r#type = self.export_type_param(param, Some(model::LocalRef::Index(scope, i as _))); - let param = model::Param::Implicit { name, r#type }; + let param = model::Param { + name, + r#type, + sort: model::ParamSort::Implicit, + }; params.push(param) } diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index ef847e01e..03bab0208 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -892,16 +892,11 @@ impl<'a> Context<'a> { self.with_local_socpe(|ctx| { let mut imported_params = Vec::with_capacity(decl.params.len()); - for param in decl.params { - match param { - model::Param::Implicit { name, r#type } => { - ctx.local_variables.insert(name, LocalVar::new(*r#type)); - } - model::Param::Explicit { name, r#type } => { - ctx.local_variables.insert(name, LocalVar::new(*r#type)); - } - } - } + ctx.local_variables.extend( + decl.params + .iter() + .map(|param| (param.name, LocalVar::new(param.r#type))), + ); for constraint in decl.constraints { match ctx.get_term(*constraint)? { @@ -929,22 +924,10 @@ impl<'a> Context<'a> { } } - let mut index = 0; - - for param in decl.params { + for (index, param) in decl.params.iter().enumerate() { // TODO: `PolyFuncType` should be able to distinguish between implicit and explicit parameters. - match param { - model::Param::Implicit { r#type, .. } => { - let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; - imported_params.push(ctx.import_type_param(*r#type, bound)?); - index += 1; - } - model::Param::Explicit { r#type, .. } => { - let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; - imported_params.push(ctx.import_type_param(*r#type, bound)?); - index += 1; - } - } + let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; + imported_params.push(ctx.import_type_param(param.r#type, bound)?); } let body = ctx.import_func_type::(decl.signature)?; diff --git a/hugr-model/capnp/hugr-v0.capnp b/hugr-model/capnp/hugr-v0.capnp index de4bf3b8b..7f6a7eceb 100644 --- a/hugr-model/capnp/hugr-v0.capnp +++ b/hugr-model/capnp/hugr-v0.capnp @@ -195,18 +195,12 @@ struct Term { } struct Param { - union { - implicit @0 :Implicit; - explicit @1 :Explicit; - } - - struct Implicit { - name @0 :Text; - type @1 :TermId; - } + name @0 :Text; + type @1 :TermId; + sort @2 :ParamSort; +} - struct Explicit { - name @0 :Text; - type @1 :TermId; - } +enum ParamSort { + implicit @0; + explicit @1; } diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index 0447878d1..5040c5fbe 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -367,19 +367,13 @@ fn read_param<'a>( bump: &'a Bump, reader: hugr_capnp::param::Reader, ) -> ReadResult> { - use hugr_capnp::param::Which; - Ok(match reader.which()? { - Which::Implicit(reader) => { - let reader = reader?; - let name = bump.alloc_str(reader.get_name()?.to_str()?); - let r#type = model::TermId(reader.get_type()); - model::Param::Implicit { name, r#type } - } - Which::Explicit(reader) => { - let reader = reader?; - let name = bump.alloc_str(reader.get_name()?.to_str()?); - let r#type = model::TermId(reader.get_type()); - model::Param::Explicit { name, r#type } - } - }) + let name = bump.alloc_str(reader.get_name()?.to_str()?); + let r#type = model::TermId(reader.get_type()); + + let sort = match reader.get_sort()? { + hugr_capnp::ParamSort::Implicit => model::ParamSort::Implicit, + hugr_capnp::ParamSort::Explicit => model::ParamSort::Explicit, + }; + + Ok(model::Param { name, r#type, sort }) } diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index 2b709389a..221be67b4 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -100,19 +100,13 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode } } -fn write_param(builder: hugr_capnp::param::Builder, param: &model::Param) { - match param { - model::Param::Implicit { name, r#type } => { - let mut builder = builder.init_implicit(); - builder.set_name(name); - builder.set_type(r#type.0); - } - model::Param::Explicit { name, r#type } => { - let mut builder = builder.init_explicit(); - builder.set_name(name); - builder.set_type(r#type.0); - } - } +fn write_param(mut builder: hugr_capnp::param::Builder, param: &model::Param) { + builder.set_name(param.name); + builder.set_type(param.r#type.0); + builder.set_sort(match param.sort { + model::ParamSort::Implicit => hugr_capnp::ParamSort::Implicit, + model::ParamSort::Explicit => hugr_capnp::ParamSort::Explicit, + }); } fn write_global_ref(mut builder: hugr_capnp::global_ref::Builder, global_ref: &model::GlobalRef) { diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index 12ce5d115..24ad26b20 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -689,26 +689,23 @@ pub enum Term<'a> { /// Parameter names must be unique within a parameter list. /// Implicit and explicit parameters share a namespace. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Param<'a> { - /// An implicit parameter that should be inferred, unless a full application form is used +pub struct Param<'a> { + /// The name of the parameter. + pub name: &'a str, + /// The type of the parameter. + pub r#type: TermId, + /// The sort of the parameter (implicit or explicit). + pub sort: ParamSort, +} + +/// The sort of a parameter (implicit or explicit). +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ParamSort { + /// The parameter is implicit and should be inferred, unless a full application form is used /// (see [`Term::ApplyFull`] and [`Operation::CustomFull`]). - Implicit { - /// The name of the parameter. - name: &'a str, - /// The type of the parameter. - /// - /// This must be a term of type `static`. - r#type: TermId, - }, - /// An explicit parameter that should always be provided. - Explicit { - /// The name of the parameter. - name: &'a str, - /// The type of the parameter. - /// - /// This must be a term of type `static`. - r#type: TermId, - }, + Implicit, + /// The parameter is explicit and should always be provided. + Explicit, } /// Errors that can occur when traversing and interpreting the model. diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index b7f3fa629..17744c6a0 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -7,7 +7,7 @@ use thiserror::Error; use crate::v0::{ AliasDecl, ConstructorDecl, FuncDecl, GlobalRef, LinkRef, LocalRef, MetaItem, Module, Node, - NodeId, Operation, OperationDecl, Param, Region, RegionId, RegionKind, Term, TermId, + NodeId, Operation, OperationDecl, Param, ParamSort, Region, RegionId, RegionKind, Term, TermId, }; mod pest_parser { @@ -637,13 +637,21 @@ impl<'a> ParseContext<'a> { let mut inner = param.into_inner(); let name = &inner.next().unwrap().as_str()[1..]; let r#type = self.parse_term(inner.next().unwrap())?; - Param::Implicit { name, r#type } + Param { + name, + r#type, + sort: ParamSort::Implicit, + } } Rule::param_explicit => { let mut inner = param.into_inner(); let name = &inner.next().unwrap().as_str()[1..]; let r#type = self.parse_term(inner.next().unwrap())?; - Param::Explicit { name, r#type } + Param { + name, + r#type, + sort: ParamSort::Explicit, + } } _ => unreachable!(), }; diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 6568c37a4..4bb6e0925 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -2,8 +2,8 @@ use pretty::{Arena, DocAllocator, RefDoc}; use std::borrow::Cow; use crate::v0::{ - GlobalRef, LinkRef, LocalRef, MetaItem, ModelError, Module, NodeId, Operation, Param, RegionId, - RegionKind, Term, TermId, + GlobalRef, LinkRef, LocalRef, MetaItem, ModelError, Module, NodeId, Operation, Param, + ParamSort, RegionId, RegionKind, Term, TermId, }; type PrintError = ModelError; @@ -122,14 +122,7 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { f: impl FnOnce(&mut Self) -> PrintResult, ) -> PrintResult { let locals = std::mem::take(&mut self.locals); - - for param in params { - match param { - Param::Implicit { name, .. } => self.locals.push(name), - Param::Explicit { name, .. } => self.locals.push(name), - } - } - + self.locals.extend(params.iter().map(|param| param.name)); let result = f(self); self.locals = locals; result @@ -462,17 +455,14 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { } fn print_param(&mut self, param: Param<'a>) -> PrintResult<()> { - self.print_parens(|this| match param { - Param::Implicit { name, r#type } => { - this.print_text("forall"); - this.print_text(format!("?{}", name)); - this.print_term(r#type) - } - Param::Explicit { name, r#type } => { - this.print_text("param"); - this.print_text(format!("?{}", name)); - this.print_term(r#type) - } + self.print_parens(|this| { + match param.sort { + ParamSort::Implicit => this.print_text("forall"), + ParamSort::Explicit => this.print_text("param"), + }; + + this.print_text(format!("?{}", param.name)); + this.print_term(param.r#type) }) } From f22581efb5dd3e8fa311bbfbd85f6d94d55a9aa3 Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Wed, 13 Nov 2024 13:45:30 +0000 Subject: [PATCH 4/8] Write constraint lists properly in capnp. --- hugr-model/src/v0/binary/write.rs | 6 ++++++ hugr-model/tests/binary.rs | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index 221be67b4..1d5f49244 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -60,12 +60,14 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_func_defn(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_signature(decl.signature.0); } model::Operation::DeclareFunc { decl } => { let mut builder = builder.init_func_decl(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_signature(decl.signature.0); } @@ -73,6 +75,7 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_alias_defn(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); builder.set_value(value.0); } @@ -80,6 +83,7 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_alias_decl(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); } @@ -87,12 +91,14 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_constructor_decl(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); } model::Operation::DeclareOperation { decl } => { let mut builder = builder.init_operation_decl(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); + let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); } diff --git a/hugr-model/tests/binary.rs b/hugr-model/tests/binary.rs index 043061677..93955fe6e 100644 --- a/hugr-model/tests/binary.rs +++ b/hugr-model/tests/binary.rs @@ -51,3 +51,8 @@ pub fn test_params() { pub fn test_decl_exts() { binary_roundtrip(include_str!("fixtures/model-decl-exts.edn")); } + +#[test] +pub fn test_constraints() { + binary_roundtrip(include_str!("fixtures/model-constraints.edn")); +} From d377fccdd6adff50073c1dd615a3f10a9ea334de Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Wed, 13 Nov 2024 14:36:46 +0000 Subject: [PATCH 5/8] Removed model_unstable from default features. --- hugr-core/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index 477f8f499..274c21837 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -20,7 +20,6 @@ workspace = true extension_inference = [] declarative = ["serde_yaml"] model_unstable = ["hugr-model"] -default = ["model_unstable"] [[test]] name = "model" From 7d0f3448dcb4a048621dc09c0e9b767d9704ee03 Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Mon, 18 Nov 2024 12:44:26 +0000 Subject: [PATCH 6/8] Replaced copy and discardable constraints with a single nonlinear constraint. --- hugr-core/Cargo.toml | 1 + hugr-core/src/export.rs | 5 +- hugr-core/src/import.rs | 47 ++++--------------- .../model__roundtrip_constraints.snap | 10 ++-- hugr-model/capnp/hugr-v0.capnp | 3 +- hugr-model/src/v0/binary/read.rs | 5 +- hugr-model/src/v0/binary/write.rs | 8 +--- hugr-model/src/v0/mod.rs | 12 ++--- hugr-model/src/v0/text/hugr.pest | 6 +-- hugr-model/src/v0/text/parse.rs | 9 +--- hugr-model/src/v0/text/print.rs | 8 +--- .../tests/fixtures/model-constraints.edn | 10 ++-- 12 files changed, 33 insertions(+), 91 deletions(-) diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index 274c21837..477f8f499 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -20,6 +20,7 @@ workspace = true extension_inference = [] declarative = ["serde_yaml"] model_unstable = ["hugr-model"] +default = ["model_unstable"] [[test]] name = "model" diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 11be37c20..966f3c680 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -825,9 +825,8 @@ impl<'a> Context<'a> { TypeParam::Type { b } => { if let (Some(var), TypeBound::Copyable) = (var, b) { let term = self.make_term(model::Term::Var(var)); - let copy = self.make_term(model::Term::CopyConstraint { term }); - let discard = self.make_term(model::Term::DiscardConstraint { term }); - self.local_constraints.extend([copy, discard]); + let non_linear = self.make_term(model::Term::NonLinearConstraint { term }); + self.local_constraints.push(non_linear); } self.make_term(model::Term::Type) diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index 03bab0208..e0d0b4df6 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -900,7 +900,7 @@ impl<'a> Context<'a> { for constraint in decl.constraints { match ctx.get_term(*constraint)? { - model::Term::CopyConstraint { term } => { + model::Term::NonLinearConstraint { term } => { let model::Term::Var(var) = ctx.get_term(*term)? else { return Err(error_unsupported!( "constraint on term that is not a variable" @@ -908,17 +908,7 @@ impl<'a> Context<'a> { }; let var = ctx.resolve_local_ref(var)?.0; - ctx.local_variables.get_index_mut(var).unwrap().1.copy = true; - } - model::Term::DiscardConstraint { term } => { - let model::Term::Var(var) = ctx.get_term(*term)? else { - return Err(error_unsupported!( - "constraint on term that is not a variable" - )); - }; - - let var = ctx.resolve_local_ref(var)?.0; - ctx.local_variables.get_index_mut(var).unwrap().1.discard = true; + ctx.local_variables[var].bound = TypeBound::Copyable; } _ => return Err(error_unsupported!("constraint other than copy or discard")), } @@ -926,7 +916,7 @@ impl<'a> Context<'a> { for (index, param) in decl.params.iter().enumerate() { // TODO: `PolyFuncType` should be able to distinguish between implicit and explicit parameters. - let bound = ctx.local_variables.get_index(index).unwrap().1.bound()?; + let bound = ctx.local_variables[index].bound; imported_params.push(ctx.import_type_param(param.r#type, bound)?); } @@ -971,8 +961,7 @@ impl<'a> Context<'a> { | model::Term::ExtSet { .. } | model::Term::Adt { .. } | model::Term::Control { .. } - | model::Term::CopyConstraint { .. } - | model::Term::DiscardConstraint { .. } => { + | model::Term::NonLinearConstraint { .. } => { Err(model::ModelError::TypeError(term_id).into()) } @@ -992,8 +981,7 @@ impl<'a> Context<'a> { model::Term::Var(var) => { let (index, var) = self.resolve_local_ref(var)?; - let bound = var.bound()?; - let decl = self.import_type_param(var.r#type, bound)?; + let decl = self.import_type_param(var.r#type, var.bound)?; Ok(TypeArg::new_var_use(index, decl)) } @@ -1032,8 +1020,7 @@ impl<'a> Context<'a> { model::Term::FuncType { .. } | model::Term::Adt { .. } | model::Term::Control { .. } - | model::Term::CopyConstraint { .. } - | model::Term::DiscardConstraint { .. } => { + | model::Term::NonLinearConstraint { .. } => { Err(model::ModelError::TypeError(term_id).into()) } } @@ -1137,8 +1124,7 @@ impl<'a> Context<'a> { | model::Term::Control { .. } | model::Term::ControlType | model::Term::Nat(_) - | model::Term::DiscardConstraint { .. } - | model::Term::CopyConstraint { .. } => { + | model::Term::NonLinearConstraint { .. } => { Err(model::ModelError::TypeError(term_id).into()) } } @@ -1320,29 +1306,14 @@ impl<'a> Names<'a> { #[derive(Debug, Clone, Copy)] struct LocalVar { r#type: model::TermId, - copy: bool, - discard: bool, + bound: TypeBound, } impl LocalVar { pub fn new(r#type: model::TermId) -> Self { Self { r#type, - copy: false, - discard: false, - } - } - - pub fn bound(&self) -> Result { - match (self.copy, self.discard) { - (true, true) => Ok(TypeBound::Copyable), - (false, false) => Ok(TypeBound::Any), - (true, false) => Err(error_unsupported!( - "type that is copyable but not discardable" - )), - (false, true) => Err(error_unsupported!( - "type that is discardable but not copyable" - )), + bound: TypeBound::Any, } } } diff --git a/hugr-core/tests/snapshots/model__roundtrip_constraints.snap b/hugr-core/tests/snapshots/model__roundtrip_constraints.snap index 372a98a2f..f085c4785 100644 --- a/hugr-core/tests/snapshots/model__roundtrip_constraints.snap +++ b/hugr-core/tests/snapshots/model__roundtrip_constraints.snap @@ -7,12 +7,10 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons (declare-func array.replicate (forall ?0 type) (forall ?1 nat) - (where (copy ?0)) - (where (discard ?0)) + (where (nonlinear ?0)) [?0] [(@ array.Array ?0 ?1)] (ext)) -(declare-func tuple.copy +(declare-func array.copy (forall ?0 type) - (where (copy ?0)) - (where (discard ?0)) - [(@ foo.tuple ?0)] [(@ foo.tuple ?0) (@ foo.tuple ?0)] (ext)) + (where (nonlinear ?0)) + [(@ array.Array ?0)] [(@ array.Array ?0) (@ array.Array ?0)] (ext)) diff --git a/hugr-model/capnp/hugr-v0.capnp b/hugr-model/capnp/hugr-v0.capnp index 7f6a7eceb..19612bf53 100644 --- a/hugr-model/capnp/hugr-v0.capnp +++ b/hugr-model/capnp/hugr-v0.capnp @@ -163,8 +163,7 @@ struct Term { funcType @17 :FuncType; control @18 :TermId; controlType @19 :Void; - copyConstraint @20 :TermId; - discardConstraint @21 :TermId; + nonLinearConstraint @20 :TermId; } struct Apply { diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index 5040c5fbe..e352aba93 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -345,10 +345,7 @@ fn read_term<'a>(bump: &'a Bump, reader: hugr_capnp::term::Reader) -> ReadResult values: model::TermId(values), }, - Which::CopyConstraint(term) => model::Term::CopyConstraint { - term: model::TermId(term), - }, - Which::DiscardConstraint(term) => model::Term::DiscardConstraint { + Which::NonLinearConstraint(term) => model::Term::NonLinearConstraint { term: model::TermId(term), }, }) diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index 1d5f49244..e6ac64201 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -212,12 +212,8 @@ fn write_term(mut builder: hugr_capnp::term::Builder, term: &model::Term) { builder.set_extensions(extensions.0); } - model::Term::CopyConstraint { term } => { - builder.set_copy_constraint(term.0); - } - - model::Term::DiscardConstraint { term } => { - builder.set_discard_constraint(term.0); + model::Term::NonLinearConstraint { term } => { + builder.set_non_linear_constraint(term.0); } } } diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index 24ad26b20..0a5b4c169 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -671,15 +671,9 @@ pub enum Term<'a> { /// `ctrl : static` ControlType, - /// Constraint that requires a runtime type to be copyable. - CopyConstraint { - /// The runtime type that must be copyable. - term: TermId, - }, - - /// Constraint that requires a runtime type to be discardable. - DiscardConstraint { - /// The runtime type that must be discardable. + /// Constraint that requires a runtime type to be copyable and discardable. + NonLinearConstraint { + /// The runtime type that must be copyable and discardable. term: TermId, }, } diff --git a/hugr-model/src/v0/text/hugr.pest b/hugr-model/src/v0/text/hugr.pest index 62f980ef0..4c3bd169e 100644 --- a/hugr-model/src/v0/text/hugr.pest +++ b/hugr-model/src/v0/text/hugr.pest @@ -92,8 +92,7 @@ term = { | term_ctrl_type | term_apply_full | term_apply - | term_copy - | term_discard + | term_non_linear } term_wildcard = { "_" } @@ -116,5 +115,4 @@ term_adt = { "(" ~ "adt" ~ term ~ ")" } term_func_type = { "(" ~ "fn" ~ term ~ term ~ term ~ ")" } term_ctrl = { "(" ~ "ctrl" ~ term ~ ")" } term_ctrl_type = { "ctrl" } -term_copy = { "(" ~ "copy" ~ term ~ ")" } -term_discard = { "(" ~ "discard" ~ term ~ ")" } +term_non_linear = { "(" ~ "nonlinear" ~ term ~ ")" } diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index 17744c6a0..672edbbe9 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -209,14 +209,9 @@ impl<'a> ParseContext<'a> { Term::Control { values } } - Rule::term_copy => { + Rule::term_non_linear => { let term = self.parse_term(inner.next().unwrap())?; - Term::CopyConstraint { term } - } - - Rule::term_discard => { - let term = self.parse_term(inner.next().unwrap())?; - Term::DiscardConstraint { term } + Term::NonLinearConstraint { term } } r => unreachable!("term: {:?}", r), diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 4bb6e0925..2cb682e84 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -596,12 +596,8 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { self.print_text("ctrl"); Ok(()) } - Term::CopyConstraint { term } => self.print_parens(|this| { - this.print_text("copy"); - this.print_term(*term) - }), - Term::DiscardConstraint { term } => self.print_parens(|this| { - this.print_text("discard"); + Term::NonLinearConstraint { term } => self.print_parens(|this| { + this.print_text("nonlinear"); this.print_term(*term) }), } diff --git a/hugr-model/tests/fixtures/model-constraints.edn b/hugr-model/tests/fixtures/model-constraints.edn index f1011cef7..5db6b9886 100644 --- a/hugr-model/tests/fixtures/model-constraints.edn +++ b/hugr-model/tests/fixtures/model-constraints.edn @@ -3,13 +3,11 @@ (declare-func array.replicate (forall ?t type) (forall ?n nat) - (where (copy ?t)) - (where (discard ?t)) + (where (nonlinear ?t)) [?t] [(@ array.Array ?t ?n)] (ext)) -(declare-func tuple.copy +(declare-func array.copy (forall ?t type) - (where (copy ?t)) - (where (discard ?t)) - [(@ foo.tuple ?t)] [(@ foo.tuple ?t) (@ foo.tuple ?t)] (ext)) + (where (nonlinear ?t)) + [(@ array.Array ?t)] [(@ array.Array ?t) (@ array.Array ?t)] (ext)) From 719af158fd00c05f3d9c140c14bee0b21afa0f64 Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Mon, 18 Nov 2024 14:40:14 +0000 Subject: [PATCH 7/8] try_for_each --- hugr-model/src/v0/text/print.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 2cb682e84..561d55e70 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -370,10 +370,9 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { } fn print_regions(&mut self, regions: &'a [RegionId]) -> PrintResult<()> { - for region in regions { - self.print_region(*region)?; - } - Ok(()) + regions + .iter() + .try_for_each(|region| self.print_region(*region)) } fn print_region(&mut self, region: RegionId) -> PrintResult<()> { @@ -408,11 +407,10 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { .get_region(region) .ok_or(PrintError::RegionNotFound(region))?; - for node_id in region_data.children { - self.print_node(*node_id)?; - } - - Ok(()) + region_data + .children + .iter() + .try_for_each(|node_id| self.print_node(*node_id)) } fn print_port_lists( @@ -447,11 +445,7 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { } fn print_params(&mut self, params: &'a [Param<'a>]) -> PrintResult<()> { - for param in params { - self.print_param(*param)?; - } - - Ok(()) + params.iter().try_for_each(|param| self.print_param(*param)) } fn print_param(&mut self, param: Param<'a>) -> PrintResult<()> { From a05ae29831d95222b459db58d68216c789cda081 Mon Sep 17 00:00:00 2001 From: Lukas Heidemann Date: Mon, 18 Nov 2024 15:05:58 +0000 Subject: [PATCH 8/8] No constraints in aliases --- hugr-core/Cargo.toml | 1 - hugr-core/src/export.rs | 2 -- hugr-model/capnp/hugr-v0.capnp | 8 +++----- hugr-model/src/v0/binary/read.rs | 4 ---- hugr-model/src/v0/binary/write.rs | 2 -- hugr-model/src/v0/mod.rs | 2 -- hugr-model/src/v0/text/hugr.pest | 2 +- hugr-model/src/v0/text/parse.rs | 2 -- hugr-model/src/v0/text/print.rs | 2 -- 9 files changed, 4 insertions(+), 21 deletions(-) diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index 477f8f499..274c21837 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -20,7 +20,6 @@ workspace = true extension_inference = [] declarative = ["serde_yaml"] model_unstable = ["hugr-model"] -default = ["model_unstable"] [[test]] name = "model" diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 966f3c680..55d586b7b 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -269,7 +269,6 @@ impl<'a> Context<'a> { let decl = this.bump.alloc(model::AliasDecl { name: &alias.name, params: &[], - constraints: &[], r#type, }); model::Operation::DeclareAlias { decl } @@ -282,7 +281,6 @@ impl<'a> Context<'a> { let decl = this.bump.alloc(model::AliasDecl { name: &alias.name, params: &[], - constraints: &[], r#type, }); model::Operation::DefineAlias { decl, value } diff --git a/hugr-model/capnp/hugr-v0.capnp b/hugr-model/capnp/hugr-v0.capnp index 19612bf53..94341beba 100644 --- a/hugr-model/capnp/hugr-v0.capnp +++ b/hugr-model/capnp/hugr-v0.capnp @@ -70,16 +70,14 @@ struct Operation { struct AliasDefn { name @0 :Text; params @1 :List(Param); - constraints @2 :List(TermId); - type @3 :TermId; - value @4 :TermId; + type @2 :TermId; + value @3 :TermId; } struct AliasDecl { name @0 :Text; params @1 :List(Param); - constraints @2 :List(TermId); - type @3 :TermId; + type @2 :TermId; } struct ConstructorDecl { diff --git a/hugr-model/src/v0/binary/read.rs b/hugr-model/src/v0/binary/read.rs index e352aba93..5381a7dc8 100644 --- a/hugr-model/src/v0/binary/read.rs +++ b/hugr-model/src/v0/binary/read.rs @@ -168,13 +168,11 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); - let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let value = model::TermId(reader.get_value()); let decl = bump.alloc(model::AliasDecl { name, params, - constraints, r#type, }); model::Operation::DefineAlias { decl, value } @@ -183,12 +181,10 @@ fn read_operation<'a>( let reader = reader?; let name = bump.alloc_str(reader.get_name()?.to_str()?); let params = read_list!(bump, reader, get_params, read_param); - let constraints = read_scalar_list!(bump, reader, get_constraints, model::TermId); let r#type = model::TermId(reader.get_type()); let decl = bump.alloc(model::AliasDecl { name, params, - constraints, r#type, }); model::Operation::DeclareAlias { decl } diff --git a/hugr-model/src/v0/binary/write.rs b/hugr-model/src/v0/binary/write.rs index e6ac64201..f3a0a14d2 100644 --- a/hugr-model/src/v0/binary/write.rs +++ b/hugr-model/src/v0/binary/write.rs @@ -75,7 +75,6 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_alias_defn(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); - let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); builder.set_value(value.0); } @@ -83,7 +82,6 @@ fn write_operation(mut builder: hugr_capnp::operation::Builder, operation: &mode let mut builder = builder.init_alias_decl(); builder.set_name(decl.name); write_list!(builder, init_params, write_param, decl.params); - let _ = builder.set_constraints(model::TermId::unwrap_slice(decl.constraints)); builder.set_type(decl.r#type.0); } diff --git a/hugr-model/src/v0/mod.rs b/hugr-model/src/v0/mod.rs index 0a5b4c169..16c7cb6c6 100644 --- a/hugr-model/src/v0/mod.rs +++ b/hugr-model/src/v0/mod.rs @@ -410,8 +410,6 @@ pub struct AliasDecl<'a> { pub name: &'a str, /// The static parameters of the alias. pub params: &'a [Param<'a>], - /// The constraints on the static parameters. - pub constraints: &'a [TermId], /// The type of the alias. pub r#type: TermId, } diff --git a/hugr-model/src/v0/text/hugr.pest b/hugr-model/src/v0/text/hugr.pest index 4c3bd169e..d05e3d774 100644 --- a/hugr-model/src/v0/text/hugr.pest +++ b/hugr-model/src/v0/text/hugr.pest @@ -57,7 +57,7 @@ node_custom = { "(" ~ (term_apply | term_apply_full) ~ port_lists? ~ signature = { "(" ~ "signature" ~ term ~ ")" } func_header = { symbol ~ param* ~ where_clause* ~ term ~ term ~ term } -alias_header = { symbol ~ param* ~ where_clause* ~ term } +alias_header = { symbol ~ param* ~ term } ctr_header = { symbol ~ param* ~ where_clause* ~ term } operation_header = { symbol ~ param* ~ where_clause* ~ term } diff --git a/hugr-model/src/v0/text/parse.rs b/hugr-model/src/v0/text/parse.rs index 672edbbe9..370dbeac0 100644 --- a/hugr-model/src/v0/text/parse.rs +++ b/hugr-model/src/v0/text/parse.rs @@ -576,13 +576,11 @@ impl<'a> ParseContext<'a> { let mut inner = pair.into_inner(); let name = self.parse_symbol(&mut inner)?; let params = self.parse_params(&mut inner)?; - let constraints = self.parse_constraints(&mut inner)?; let r#type = self.parse_term(inner.next().unwrap())?; Ok(self.bump.alloc(AliasDecl { name, params, - constraints, r#type, })) } diff --git a/hugr-model/src/v0/text/print.rs b/hugr-model/src/v0/text/print.rs index 561d55e70..512f6d1e4 100644 --- a/hugr-model/src/v0/text/print.rs +++ b/hugr-model/src/v0/text/print.rs @@ -294,7 +294,6 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { }); this.print_params(decl.params)?; - this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_term(*value)?; @@ -308,7 +307,6 @@ impl<'p, 'a: 'p> PrintContext<'p, 'a> { }); this.print_params(decl.params)?; - this.print_constraints(decl.constraints)?; this.print_term(decl.r#type)?; this.print_meta(node_data.meta)?;