From 7b242ac8391fa3b3d73329b647ebd608cbfe44ee Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Jan 2024 14:56:48 +0000 Subject: [PATCH 01/42] Refactor: break out fn valid_row for validating a TypeRow --- src/types.rs | 14 +++++++++++--- src/types/signature.rs | 8 +++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/types.rs b/src/types.rs index ff8164221..074a61fec 100644 --- a/src/types.rs +++ b/src/types.rs @@ -305,9 +305,9 @@ impl Type { // There is no need to check the components against the bound, // that is guaranteed by construction (even for deserialization) match &self.0 { - TypeEnum::Tuple(row) | TypeEnum::Sum(SumType::General { row }) => row - .iter() - .try_for_each(|t| t.validate(extension_registry, var_decls)), + TypeEnum::Tuple(row) | TypeEnum::Sum(SumType::General { row }) => { + valid_row(row, extension_registry, var_decls) + } TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), @@ -347,6 +347,14 @@ pub(crate) trait Substitution { fn extension_registry(&self) -> &ExtensionRegistry; } +fn valid_row( + row: &TypeRow, + exts: &ExtensionRegistry, + var_decls: &[TypeParam], +) -> Result<(), SignatureError> { + row.iter().try_for_each(|t| t.validate(exts, var_decls)) +} + fn subst_row(row: &TypeRow, tr: &impl Substitution) -> TypeRow { let res = row .iter() diff --git a/src/types/signature.rs b/src/types/signature.rs index ebcd44a7c..4fba72116 100644 --- a/src/types/signature.rs +++ b/src/types/signature.rs @@ -5,7 +5,7 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; -use super::{subst_row, Substitution, Type, TypeRow}; +use super::{subst_row, valid_row, Substitution, Type, TypeRow}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -34,10 +34,8 @@ impl FunctionType { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - self.input - .iter() - .chain(self.output.iter()) - .try_for_each(|t| t.validate(extension_registry, var_decls))?; + valid_row(&self.input, extension_registry, var_decls)?; + valid_row(&self.output, extension_registry, var_decls)?; self.extension_reqs.validate(var_decls) } From ba050108bc349fee47033c0b1f3e6dcfa9ec15dc Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Jan 2024 15:39:39 +0000 Subject: [PATCH 02/42] Type::{validate,substitute}_in_row, {Substitution,SubstValues}::apply_typevar_in_row --- src/types.rs | 36 ++++++++++++++++++++++++++++++++++-- src/types/poly_func.rs | 23 ++++++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index 074a61fec..80ff16b81 100644 --- a/src/types.rs +++ b/src/types.rs @@ -316,6 +316,23 @@ impl Type { } } + fn validate_in_row( + &self, + extension_registry: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError> { + if let TypeEnum::Variable(idx, bound) = &self.0 { + // Allow also the Variable to be a *list* of types of the specified bound + let list_bound = TypeParam::List { + param: Box::new((*bound).into()), + }; + if check_typevar_decl(var_decls, *idx, &list_bound).is_ok() { + return Ok(()); + }; + } + self.validate(extension_registry, var_decls) + } + pub(crate) fn substitute(&self, t: &impl Substitution) -> Self { match &self.0 { TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), @@ -326,6 +343,13 @@ impl Type { TypeEnum::Sum(SumType::General { row }) => Type::new_sum(subst_row(row, t)), } } + + fn substitute_in_row(&self, t: &impl Substitution) -> Vec { + match &self.0 { + TypeEnum::Variable(idx, bound) => t.apply_typevar_in_row(*idx, *bound), + _ => vec![self.substitute(t)], + } + } } /// A function that replaces type variables with values. @@ -344,6 +368,13 @@ pub(crate) trait Substitution { /// Apply to a variable whose kind is any given [TypeParam] fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; + fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + let TypeArg::Type { ty } = self.apply_var(idx, &TypeParam::Type { b: bound }) else { + panic!("Applying to type did not produce type") + }; + vec![ty] + } + fn extension_registry(&self) -> &ExtensionRegistry; } @@ -352,13 +383,14 @@ fn valid_row( exts: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - row.iter().try_for_each(|t| t.validate(exts, var_decls)) + row.iter() + .try_for_each(|t| t.validate_in_row(exts, var_decls)) } fn subst_row(row: &TypeRow, tr: &impl Substitution) -> TypeRow { let res = row .iter() - .map(|ty| ty.substitute(tr)) + .flat_map(|ty| ty.substitute_in_row(tr)) .collect::>() .into(); res diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 98d2ac1ed..67fb68c53 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -7,7 +7,7 @@ use crate::{ use itertools::Itertools; use super::type_param::{check_type_args, TypeArg, TypeParam}; -use super::{FunctionType, Substitution}; +use super::{FunctionType, Substitution, Type, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -160,6 +160,27 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } + fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + let arg = self + .0 + .get(idx) + .expect("Undeclared type variable - call validate() ?"); + match arg { + TypeArg::Sequence { elems } => elems + .iter() + .map(|ta| match ta { + TypeArg::Type { ty } => ty.clone(), + _ => panic!("Not a list of types - did validate() ?"), + }) + .collect(), + TypeArg::Type { ty } => { + debug_assert_eq!(check_type_arg(arg, &TypeParam::Type { b: bound }), Ok(())); + vec![ty.clone()] + } + _ => panic!("Not a type or list of types - did validate() ?"), + } + } + fn extension_registry(&self) -> &ExtensionRegistry { self.1 } From 59c585439f42544d8346ba7b2e3846f7461c0a5c Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 14:16:50 +0000 Subject: [PATCH 03/42] [test] types.rs::construct - also validate --- src/types.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 80ff16b81..aa09c10c0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -439,10 +439,16 @@ pub(crate) mod test { pub(crate) use poly_func::test::nested_func; use super::*; + use crate::extension::PRELUDE; + use crate::{const_extension_ids, Extension}; use crate::{extension::prelude::USIZE_T, ops::AliasDecl}; use crate::types::TypeBound; + const_extension_ids! { + const MY_EXT: ExtensionId = "my_extension"; + } + #[test] fn construct() { let t: Type = Type::new_tuple(vec![ @@ -451,7 +457,7 @@ pub(crate) mod test { Type::new_extension(CustomType::new( "my_custom", [], - "my_extension".try_into().unwrap(), + MY_EXT, TypeBound::Copyable, )), Type::new_alias(AliasDecl::new("my_alias", TypeBound::Eq)), @@ -461,6 +467,17 @@ pub(crate) mod test { "Tuple([usize([]), Function(forall . [[]][]), my_custom([]), Alias(my_alias)])" .to_string() ); + + let mut ext = Extension::new(MY_EXT); + ext.add_type( + "my_custom".into(), + vec![], + "".into(), + TypeBound::Copyable.into(), + ) + .unwrap(); + let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), ext]).unwrap(); + t.validate(®, &[]).unwrap() } #[test] From 72b4fb2483453453debf79888a6ec501cae4bc24 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:01:54 +0000 Subject: [PATCH 04/42] [tests] poly_func.rs: test row variables --- src/types.rs | 2 +- src/types/poly_func.rs | 89 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/types.rs b/src/types.rs index aa09c10c0..384a6a28e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -268,7 +268,7 @@ impl Type { /// New use (occurrence) of the type variable with specified DeBruijn index. /// For use in type schemes only: `bound` must match that with which the /// variable was declared (i.e. as a [TypeParam::Type]`(bound)`). - pub fn new_var_use(idx: usize, bound: TypeBound) -> Self { + pub const fn new_var_use(idx: usize, bound: TypeBound) -> Self { Self(TypeEnum::Variable(idx, bound), bound) } diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 67fb68c53..79be32b28 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -242,7 +242,7 @@ pub(crate) mod test { use lazy_static::lazy_static; use smol_str::SmolStr; - use crate::extension::prelude::{array_type, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; + use crate::extension::prelude::{array_type, BOOL_T, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; use crate::extension::{ ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, PRELUDE, PRELUDE_REGISTRY, }; @@ -639,4 +639,91 @@ pub(crate) mod test { ) ) } + + #[test] + fn row_variables() { + const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; + // Mismatched TypeBound (Copyable vs Any) + PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TypeParam::Type { + b: TypeBound::Copyable, + }), + }], + FunctionType::new( + vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + ), + &PRELUDE_REGISTRY, + ) + .unwrap_err(); + + let pf = PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TP), + }], + FunctionType::new( + vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + ), + &PRELUDE_REGISTRY, + ) + .unwrap(); + + fn seq2() -> Vec { + vec![USIZE_T.into(), BOOL_T.into()] + } + pf.instantiate(&[TypeArg::Type { ty: USIZE_T }], &PRELUDE_REGISTRY) + .unwrap_err(); + pf.instantiate( + &[TypeArg::Sequence { + elems: vec![USIZE_T.into(), TypeArg::Sequence { elems: seq2() }], + }], + &PRELUDE_REGISTRY, + ) + .unwrap_err(); + + let t2 = pf + .instantiate(&[TypeArg::Sequence { elems: seq2() }], &PRELUDE_REGISTRY) + .unwrap(); + assert_eq!( + t2, + FunctionType::new( + vec![USIZE_T, USIZE_T, BOOL_T], + vec![Type::new_sum(vec![USIZE_T, BOOL_T])] + ) + ); + } + + #[test] + fn row_variables_inner() { + let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_var_use( + 0, + TypeBound::Copyable, + )])); + let pf = PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TypeParam::Type { + b: TypeBound::Copyable, + }), + }], + FunctionType::new(vec![USIZE_T, inner_fty.clone()], vec![inner_fty]), + &PRELUDE_REGISTRY, + ) + .unwrap(); + + let inner3 = Type::new_function(FunctionType::new_endo(vec![USIZE_T, BOOL_T, USIZE_T])); + let t3 = pf + .instantiate( + &[TypeArg::Sequence { + elems: vec![USIZE_T.into(), BOOL_T.into(), USIZE_T.into()], + }], + &PRELUDE_REGISTRY, + ) + .unwrap(); + assert_eq!( + t3, + FunctionType::new(vec![USIZE_T, inner3.clone()], vec![inner3]) + ); + } } From 2cf1e7f0bd71f9cff8a79e4fd1dbb9b7f147b30b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:14:33 +0000 Subject: [PATCH 05/42] [test] validate Hugr passing around Function of unknown arity --- src/hugr/validate/test.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index d974339e7..510acb658 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -559,6 +559,26 @@ fn no_polymorphic_consts() -> Result<(), Box> { Ok(()) } +#[test] +fn inner_row_variables() -> Result<(), Box> { + let tv = Type::new_var_use(0, TypeBound::Any); + let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); + let mut fb = FunctionBuilder::new( + "id", + PolyFuncType::new( + [TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + }], + FunctionType::new_endo(vec![inner_ft.clone()]), + ), + )?; + // All the wires here are carrying higher-order Function values + // (the Functions themselves have variable arity, but that's fine as we are not calling them) + let id = fb.add_dataflow_op(LeafOp::Noop { ty: inner_ft }, fb.input_wires())?; + fb.finish_hugr_with_outputs(id.outputs(), &EMPTY_REG)?; + Ok(()) +} + #[cfg(feature = "extension_inference")] mod extension_tests { use super::*; From 8899806e4493843427c176a59675ffe806f11509 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:22:07 +0000 Subject: [PATCH 06/42] [tests]Validation prevents row variables being used in node signatures --- src/hugr/validate/test.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index 510acb658..ecd69bcdb 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -4,6 +4,7 @@ use super::*; use crate::builder::test::closed_dfg_root_hugr; use crate::builder::{ BuildError, Container, Dataflow, DataflowHugr, DataflowSubContainer, FunctionBuilder, + HugrBuilder, }; use crate::extension::prelude::{BOOL_T, PRELUDE, USIZE_T}; use crate::extension::{ @@ -579,6 +580,33 @@ fn inner_row_variables() -> Result<(), Box> { Ok(()) } +#[test] +fn no_outer_row_variables() -> Result<(), Box> { + let tv = Type::new_var_use(0, TypeBound::Any); + let fb = FunctionBuilder::new( + "impossible_id_of_unknown_arity", + PolyFuncType::new( + [TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + }], + FunctionType::new_endo(vec![tv]), + ), + )?; + // Input and Output nodes have a Port whose type is List(Type(Any)) + // - so this is illegal because the wire between them is not a type: + let err = fb + .clone() + .finish_hugr_with_outputs(fb.input_wires(), &EMPTY_REG) + .unwrap_err(); + assert_matches!( + err, + BuildError::InvalidHUGR(ValidationError::SignatureError { .. }) + ); + // Also try leaving no inputs/outputs - so this should be illegal because the ports are unconnected + fb.finish_hugr(&EMPTY_REG).unwrap_err(); + Ok(()) +} + #[cfg(feature = "extension_inference")] mod extension_tests { use super::*; From e1f182502f6cec77f07a9bf62b6e5431538800b2 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 16:33:50 +0000 Subject: [PATCH 07/42] Simplify default apply_typevar_in_row --- src/types.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types.rs b/src/types.rs index 384a6a28e..3d3d4d3f3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -369,10 +369,7 @@ pub(crate) trait Substitution { fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { - let TypeArg::Type { ty } = self.apply_var(idx, &TypeParam::Type { b: bound }) else { - panic!("Applying to type did not produce type") - }; - vec![ty] + vec![self.apply_typevar(idx, bound)] } fn extension_registry(&self) -> &ExtensionRegistry; From 1074093d8274c7c709203ba151f0ad196443ecfe Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 16:49:31 +0000 Subject: [PATCH 08/42] Separate TypeEnum::RowVariable --- src/extension.rs | 3 +++ src/hugr/validate/test.rs | 4 ++-- src/types.rs | 39 +++++++++++++++++++++++++++------------ src/types/poly_func.rs | 10 +++++----- src/types/serialize.rs | 3 +++ 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/extension.rs b/src/extension.rs index f87925755..5f98d07b8 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -123,6 +123,9 @@ pub enum SignatureError { /// A type variable that was used has not been declared #[error("Type variable {idx} was not declared ({num_decls} in scope)")] FreeTypeVar { idx: usize, num_decls: usize }, + /// A row variable was found outside of a row + #[error("Row variable {idx} was found outside of a type row")] + RowTypeVarOutsideRow { idx: usize }, /// The type stored in a [LeafOp::TypeApply] is not what we compute from the /// [ExtensionRegistry]. /// diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index ecd69bcdb..98ec7db49 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -562,7 +562,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { #[test] fn inner_row_variables() -> Result<(), Box> { - let tv = Type::new_var_use(0, TypeBound::Any); + let tv = Type::new_row_var(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", @@ -582,7 +582,7 @@ fn inner_row_variables() -> Result<(), Box> { #[test] fn no_outer_row_variables() -> Result<(), Box> { - let tv = Type::new_var_use(0, TypeBound::Any); + let tv = Type::new_row_var(0, TypeBound::Any); let fb = FunctionBuilder::new( "impossible_id_of_unknown_arity", PolyFuncType::new( diff --git a/src/types.rs b/src/types.rs index 3d3d4d3f3..6a59afb47 100644 --- a/src/types.rs +++ b/src/types.rs @@ -153,10 +153,14 @@ pub enum TypeEnum { #[allow(missing_docs)] #[display(fmt = "Function({})", "_0")] Function(Box), - // DeBruijn index, and cache of TypeBound (checked in validation) + /// DeBruijn index, and cache of TypeBound of [TypeParam::Type] (checked in validation) #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] Variable(usize, TypeBound), + /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] + /// of this bound (checked in validation) + #[display(fmt = "RowVar({})", _0)] + RowVariable(usize, TypeBound), #[allow(missing_docs)] #[display(fmt = "Tuple({})", "_0")] Tuple(TypeRow), @@ -171,7 +175,7 @@ impl TypeEnum { TypeEnum::Extension(c) => c.bound(), TypeEnum::Alias(a) => a.bound, TypeEnum::Function(_) => TypeBound::Copyable, - TypeEnum::Variable(_, b) => *b, + TypeEnum::Variable(_, b) | TypeEnum::RowVariable(_, b) => *b, TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, TypeEnum::Sum(SumType::General { row }) => { least_upper_bound(row.iter().map(Type::least_upper_bound)) @@ -272,6 +276,13 @@ impl Type { Self(TypeEnum::Variable(idx, bound), bound) } + /// New use (occurrence) of the row variable with specified DeBruijn index. + /// For use in type schemes only: `bound` must match that with which the + /// variable was declared (i.e. as a [TypeParam::List]`(`[TypeParam::Type]`(bound))`). + pub const fn new_row_var(idx: usize, bound: TypeBound) -> Self { + Self(TypeEnum::RowVariable(idx, bound), bound) + } + /// Report the least upper TypeBound, if there is one. #[inline(always)] pub const fn least_upper_bound(&self) -> TypeBound { @@ -313,6 +324,9 @@ impl Type { TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), TypeEnum::Function(ft) => ft.validate(extension_registry, var_decls), TypeEnum::Variable(idx, bound) => check_typevar_decl(var_decls, *idx, &(*bound).into()), + TypeEnum::RowVariable(idx, _) => { + Err(SignatureError::RowTypeVarOutsideRow { idx: *idx }) + } } } @@ -321,22 +335,23 @@ impl Type { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - if let TypeEnum::Variable(idx, bound) = &self.0 { - // Allow also the Variable to be a *list* of types of the specified bound - let list_bound = TypeParam::List { - param: Box::new((*bound).into()), - }; - if check_typevar_decl(var_decls, *idx, &list_bound).is_ok() { - return Ok(()); + if let TypeEnum::RowVariable(idx, bound) = self.0 { + let t = TypeParam::List { + param: Box::new(bound.into()), }; + check_typevar_decl(var_decls, idx, &t) + } else { + self.validate(extension_registry, var_decls) } - self.validate(extension_registry, var_decls) } pub(crate) fn substitute(&self, t: &impl Substitution) -> Self { match &self.0 { TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), TypeEnum::Variable(idx, bound) => t.apply_typevar(*idx, *bound), + TypeEnum::RowVariable(_, _) => { + panic!("Row Variable found outside of row - should have been detected in validate") + } TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), TypeEnum::Tuple(elems) => Type::new_tuple(subst_row(elems, t)), @@ -346,7 +361,7 @@ impl Type { fn substitute_in_row(&self, t: &impl Substitution) -> Vec { match &self.0 { - TypeEnum::Variable(idx, bound) => t.apply_typevar_in_row(*idx, *bound), + TypeEnum::RowVariable(idx, bound) => t.apply_rowvar(*idx, *bound), _ => vec![self.substitute(t)], } } @@ -368,7 +383,7 @@ pub(crate) trait Substitution { /// Apply to a variable whose kind is any given [TypeParam] fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; - fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { vec![self.apply_typevar(idx, bound)] } diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 79be32b28..6026f783d 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -160,7 +160,7 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } - fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { let arg = self .0 .get(idx) @@ -652,7 +652,7 @@ pub(crate) mod test { }], FunctionType::new( vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -663,8 +663,8 @@ pub(crate) mod test { param: Box::new(TP), }], FunctionType::new( - vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + vec![USIZE_T, Type::new_row_var(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -697,7 +697,7 @@ pub(crate) mod test { #[test] fn row_variables_inner() { - let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_var_use( + let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_row_var( 0, TypeBound::Copyable, )])); diff --git a/src/types/serialize.rs b/src/types/serialize.rs index ad10c3ff5..1aac86e5f 100644 --- a/src/types/serialize.rs +++ b/src/types/serialize.rs @@ -17,6 +17,7 @@ pub(super) enum SerSimpleType { Opaque(CustomType), Alias(AliasDecl), V { i: usize, b: TypeBound }, + R { i: usize, b: TypeBound }, } impl From for SerSimpleType { @@ -34,6 +35,7 @@ impl From for SerSimpleType { TypeEnum::Alias(a) => SerSimpleType::Alias(a), TypeEnum::Function(sig) => SerSimpleType::G(sig), TypeEnum::Variable(i, b) => SerSimpleType::V { i, b }, + TypeEnum::RowVariable(i, b) => SerSimpleType::R { i, b }, TypeEnum::Sum(sum) => SerSimpleType::Sum(sum), TypeEnum::Tuple(inner) => SerSimpleType::Tuple { inner }, } @@ -54,6 +56,7 @@ impl From for Type { SerSimpleType::Opaque(custom) => Type::new_extension(custom), SerSimpleType::Alias(a) => Type::new_alias(a), SerSimpleType::V { i, b } => Type::new_var_use(i, b), + SerSimpleType::R { i, b } => Type::new_row_var(i, b), } } } From 98c75a21ca34af3652a811e7b0c37dc2e948796f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 15 Apr 2024 12:43:54 +0100 Subject: [PATCH 09/42] Doc updates - no DeBruijn, ref OpDef vs FuncDefn --- hugr/src/types.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 5e85307d9..712731522 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -202,7 +202,7 @@ pub enum TypeEnum { #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] Variable(usize, TypeBound), - /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] + /// Variable index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] /// of this bound (checked in validation) #[display(fmt = "RowVar({})", _0)] RowVariable(usize, TypeBound), @@ -317,9 +317,13 @@ impl Type { Self(TypeEnum::Variable(idx, bound), bound) } - /// New use (occurrence) of the row variable with specified DeBruijn index. - /// For use in type schemes only: `bound` must match that with which the - /// variable was declared (i.e. as a [TypeParam::List]`(`[TypeParam::Type]`(bound))`). + /// New use (occurrence) of the row variable with specified index. + /// `bound` must match that with which the variable was declared + /// (i.e. as a [TypeParam::List]` of a `[TypeParam::Type]` of that bound). + /// For use in [OpDef], not [FuncDefn], type schemes only. + /// + /// [OpDef]: crate::extension::OpDef + /// [FuncDefn]: crate::ops::FuncDefn pub const fn new_row_var(idx: usize, bound: TypeBound) -> Self { Self(TypeEnum::RowVariable(idx, bound), bound) } From b918bee0f9f53340d4166bebd6df93cfd21470fd Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 15 Apr 2024 12:44:16 +0100 Subject: [PATCH 10/42] Remove unused test setup changes --- hugr/src/types.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 712731522..55f5555d9 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -504,16 +504,10 @@ pub(crate) fn check_typevar_decl( #[cfg(test)] pub(crate) mod test { use super::*; - use crate::extension::PRELUDE; - use crate::{const_extension_ids, Extension}; use crate::{extension::prelude::USIZE_T, ops::AliasDecl}; use crate::types::TypeBound; - const_extension_ids! { - const MY_EXT: ExtensionId = "my_extension"; - } - #[test] fn construct() { let t: Type = Type::new_tuple(vec![ @@ -522,7 +516,7 @@ pub(crate) mod test { Type::new_extension(CustomType::new( "my_custom", [], - MY_EXT, + "my_extension".try_into().unwrap(), TypeBound::Copyable, )), Type::new_alias(AliasDecl::new("my_alias", TypeBound::Eq)), @@ -531,17 +525,6 @@ pub(crate) mod test { &t.to_string(), "[usize, Function([[]][]), my_custom, Alias(my_alias)]" ); - - let mut ext = Extension::new(MY_EXT); - ext.add_type( - "my_custom".into(), - vec![], - "".into(), - TypeBound::Copyable.into(), - ) - .unwrap(); - let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), ext]).unwrap(); - t.validate(®, &[]).unwrap() } #[test] From 4b0e23fe67d675dc41383226c78b2eaca648640f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Thu, 9 May 2024 18:50:04 +0100 Subject: [PATCH 11/42] Combine Type::substitute(_in_row), doc, add TODOs --- hugr/src/types.rs | 41 +++++++++++++++++++----------------- hugr/src/types/type_param.rs | 16 +++++++++++--- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 39d6b6b9f..5e8e0f4e3 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -351,13 +351,15 @@ impl Type { TypeBound::Copyable.contains(self.least_upper_bound()) } - /// Checks all variables used in the type are in the provided list - /// of bound variables, and that for each [CustomType] the corresponding + /// Checks that this [Type] represents a single Type, not a row variable, + /// that all variables used within are in the provided list of bound variables, + /// and that for each [CustomType], the corresponding /// [TypeDef] is in the [ExtensionRegistry] and the type arguments /// [validate] and fit into the def's declared parameters. /// /// [validate]: crate::types::type_param::TypeArg::validate /// [TypeDef]: crate::extension::TypeDef + // ALAN TODO rename - validate_type, validate1type ? pub(crate) fn validate( &self, extension_registry: &ExtensionRegistry, @@ -380,6 +382,7 @@ impl Type { } } + // ALAN TODO rename to validate_var_len (?) fn validate_in_row( &self, extension_registry: &ExtensionRegistry, @@ -395,32 +398,32 @@ impl Type { } } - pub(crate) fn substitute(&self, t: &Substitution) -> Self { + // ALAN TODO 2. FunctionType.validate_fixed_len, validate_var_len + // ALAN TODO 4. subst_row / valid_row => TypeRow::substitute, TypeRow::validate_var_len + + /// Applies a substitution to a type. + /// This may result in a row of types, if this [Type] is not really a single type but actually a row variable + /// Invariants may be confirmed by validation: + /// * If [Type::validate] returns successfully, this method will return a Vec containing exactly one type + /// * If [Type::validate] fails, but [Type::validate_in_row] succeeds, this method may (depending on structure of self) + /// return a Vec containing any number of [Type]s. These may (or not) pass [Type::validate] + fn substitute(&self, t: &Substitution) -> Vec { match &self.0 { - TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), + TypeEnum::RowVariable(idx, bound) => t.apply_rowvar(*idx, *bound), + TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => vec![self.clone()], TypeEnum::Variable(idx, bound) => { let TypeArg::Type { ty } = t.apply_var(*idx, &((*bound).into())) else { panic!("Variable was not a type - try validate() first") }; - ty + vec![ty] } - TypeEnum::RowVariable(_, _) => { - panic!("Row Variable found outside of row - should have been detected in validate") - } - TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), - TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), + TypeEnum::Extension(cty) => vec![Type::new_extension(cty.substitute(t))], + TypeEnum::Function(bf) => vec![Type::new_function(bf.substitute(t))], TypeEnum::Sum(SumType::General { rows }) => { - Type::new_sum(rows.iter().map(|x| subst_row(x, t))) + vec![Type::new_sum(rows.iter().map(|x| subst_row(x, t)))] } } } - - fn substitute_in_row(&self, t: &Substitution) -> Vec { - match &self.0 { - TypeEnum::RowVariable(idx, bound) => t.apply_rowvar(*idx, *bound), - _ => vec![self.substitute(t)], - } - } } /// Details a replacement of type variables with a finite list of known values. @@ -475,7 +478,7 @@ fn valid_row( fn subst_row(row: &TypeRow, tr: &Substitution) -> TypeRow { let res = row .iter() - .flat_map(|ty| ty.substitute_in_row(tr)) + .flat_map(|ty| ty.substitute(tr)) .collect::>() .into(); res diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 3e57fcab7..34f9ad853 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -258,9 +258,19 @@ impl TypeArg { pub(crate) fn substitute(&self, t: &Substitution) -> Self { match self { - TypeArg::Type { ty } => TypeArg::Type { - ty: ty.substitute(t), - }, + TypeArg::Type { ty } => { + // A row variable standing for many types is represented as a single type + // ALAN TODO: add test that would fail if we didn't handle this + let tys = ty + .substitute(t) + .into_iter() + .map(|ty| TypeArg::Type { ty }) + .collect::>(); + match as TryInto<[TypeArg; 1]>>::try_into(tys) { + Ok([ty]) => ty, + Err(elems) => TypeArg::Sequence { elems }, + } + } TypeArg::BoundedNat { .. } => self.clone(), // We do not allow variables as bounds on BoundedNat's TypeArg::Opaque { arg: CustomTypeArg { typ, .. }, From a0aba20d3a18c4472000076c93b34f525a6f05fe Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Thu, 9 May 2024 19:20:30 +0100 Subject: [PATCH 12/42] FunctionType/PolyFuncType validate_varargs (fixed-len not reqd) --- hugr/src/extension/op_def.rs | 5 ++++- hugr/src/hugr/validate.rs | 5 ++++- hugr/src/types.rs | 4 ++-- hugr/src/types/poly_func.rs | 9 ++++++--- hugr/src/types/signature.rs | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 1e68400ea..bcda1d067 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -398,7 +398,10 @@ impl OpDef { // TODO https://github.com/CQCL/hugr/issues/624 validate declared TypeParams // for both type scheme and custom binary if let SignatureFunc::TypeScheme(ts) = &self.signature_func { - ts.poly_func.validate(exts)?; + // The type scheme may contain row variables so be of variable length; + // these will have to be substituted to fixed-length concrete types when + // the OpDef is instantiated into an actual OpType. + ts.poly_func.validate_varargs(exts)?; } Ok(()) } diff --git a/hugr/src/hugr/validate.rs b/hugr/src/hugr/validate.rs index 40de5d805..30c795d6d 100644 --- a/hugr/src/hugr/validate.rs +++ b/hugr/src/hugr/validate.rs @@ -305,7 +305,10 @@ impl<'a, 'b> ValidationContext<'a, 'b> { // Static edges must *not* refer to type variables declared by enclosing FuncDefns // as these are only types at runtime. EdgeKind::Const(ty) => ty.validate(self.extension_registry, &[]), - EdgeKind::Function(pf) => pf.validate(self.extension_registry), + // Allow function "value" to have unknown arity. A Call node will have to provide + // TypeArgs that produce a known arity, but a LoadFunction might pass the function + // value ("function pointer") around without knowing how to call it. + EdgeKind::Function(pf) => pf.validate_varargs(self.extension_registry), _ => Ok(()), } } diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 5e8e0f4e3..c1e1496fc 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -374,7 +374,8 @@ impl Type { TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), - TypeEnum::Function(ft) => ft.validate(extension_registry, var_decls), + // FunctionTypes used as types of values may have unknown arity (e.g. if they are not called) + TypeEnum::Function(ft) => ft.validate_varargs(extension_registry, var_decls), TypeEnum::Variable(idx, bound) => check_typevar_decl(var_decls, *idx, &(*bound).into()), TypeEnum::RowVariable(idx, _) => { Err(SignatureError::RowTypeVarOutsideRow { idx: *idx }) @@ -398,7 +399,6 @@ impl Type { } } - // ALAN TODO 2. FunctionType.validate_fixed_len, validate_var_len // ALAN TODO 4. subst_row / valid_row => TypeRow::substitute, TypeRow::validate_var_len /// Applies a substitution to a type. diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index 1b9b06451..3e5a5626c 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -73,9 +73,12 @@ impl PolyFuncType { /// Validates this instance, checking that the types in the body are /// wellformed with respect to the registry, and the type variables declared. - pub fn validate(&self, reg: &ExtensionRegistry) -> Result<(), SignatureError> { + /// Allows both inputs and outputs to contain [RowVariable]s + /// + /// [RowVariable]: [crate::types::TypeEnum::RowVariable] + pub fn validate_varargs(&self, reg: &ExtensionRegistry) -> Result<(), SignatureError> { // TODO https://github.com/CQCL/hugr/issues/624 validate TypeParams declared here, too - self.body.validate(reg, &self.params) + self.body.validate_varargs(reg, &self.params) } /// Instantiates an outer [PolyFuncType], i.e. with no free variables @@ -125,7 +128,7 @@ pub(crate) mod test { extension_registry: &ExtensionRegistry, ) -> Result { let res = Self::new(params, body); - res.validate(extension_registry)?; + res.validate_varargs(extension_registry)?; Ok(res) } } diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index 5f3a52cd4..cb47181c0 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -32,7 +32,7 @@ impl FunctionType { self } - pub(crate) fn validate( + pub(super) fn validate_varargs( &self, extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], From bd0689fcfcd1d200e915aa23ab3387ddbc17570f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 10:48:09 +0100 Subject: [PATCH 13/42] Type::validate(=>_1type), fix TypeParam to call validate_in_row --- hugr/src/hugr/validate.rs | 4 ++-- hugr/src/types.rs | 8 ++++---- hugr/src/types/type_param.rs | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hugr/src/hugr/validate.rs b/hugr/src/hugr/validate.rs index 30c795d6d..95ea36e4c 100644 --- a/hugr/src/hugr/validate.rs +++ b/hugr/src/hugr/validate.rs @@ -301,10 +301,10 @@ impl<'a, 'b> ValidationContext<'a, 'b> { var_decls: &[TypeParam], ) -> Result<(), SignatureError> { match &port_kind { - EdgeKind::Value(ty) => ty.validate(self.extension_registry, var_decls), + EdgeKind::Value(ty) => ty.validate_1type(self.extension_registry, var_decls), // Static edges must *not* refer to type variables declared by enclosing FuncDefns // as these are only types at runtime. - EdgeKind::Const(ty) => ty.validate(self.extension_registry, &[]), + EdgeKind::Const(ty) => ty.validate_1type(self.extension_registry, &[]), // Allow function "value" to have unknown arity. A Call node will have to provide // TypeArgs that produce a known arity, but a LoadFunction might pass the function // value ("function pointer") around without knowing how to call it. diff --git a/hugr/src/types.rs b/hugr/src/types.rs index c1e1496fc..d4f47b9c0 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -359,8 +359,7 @@ impl Type { /// /// [validate]: crate::types::type_param::TypeArg::validate /// [TypeDef]: crate::extension::TypeDef - // ALAN TODO rename - validate_type, validate1type ? - pub(crate) fn validate( + pub(crate) fn validate_1type( &self, extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], @@ -383,7 +382,8 @@ impl Type { } } - // ALAN TODO rename to validate_var_len (?) + /// Checks that this [Type] is valid (as per [Type::validate_1type]), but also + /// allows row variables that may become multiple types fn validate_in_row( &self, extension_registry: &ExtensionRegistry, @@ -395,7 +395,7 @@ impl Type { }; check_typevar_decl(var_decls, idx, &t) } else { - self.validate(extension_registry, var_decls) + self.validate_1type(extension_registry, var_decls) } } diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 34f9ad853..6c2bee4c3 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -237,7 +237,8 @@ impl TypeArg { var_decls: &[TypeParam], ) -> Result<(), SignatureError> { match self { - TypeArg::Type { ty } => ty.validate(extension_registry, var_decls), + // Row variables are represented as Types, even inside TypeArgs + TypeArg::Type { ty } => ty.validate_in_row(extension_registry, var_decls), TypeArg::BoundedNat { .. } => Ok(()), TypeArg::Opaque { arg: custarg } => { // We could also add a facility to Extension to validate that the constant *value* From 72f4b98ea1cbd5a425b15d8695178cce52bc72fb Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 11:29:42 +0100 Subject: [PATCH 14/42] {subst,valid}_row => TypeRow::{substitute,validate_var_len} --- hugr/src/types.rs | 24 ++---------------------- hugr/src/types/signature.rs | 11 ++++++----- hugr/src/types/type_row.rs | 31 +++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index d4f47b9c0..9ef5b4be4 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -369,7 +369,7 @@ impl Type { match &self.0 { TypeEnum::Sum(SumType::General { rows }) => rows .iter() - .try_for_each(|row| valid_row(row, extension_registry, var_decls)), + .try_for_each(|row| row.validate_var_len(extension_registry, var_decls)), TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), @@ -399,8 +399,6 @@ impl Type { } } - // ALAN TODO 4. subst_row / valid_row => TypeRow::substitute, TypeRow::validate_var_len - /// Applies a substitution to a type. /// This may result in a row of types, if this [Type] is not really a single type but actually a row variable /// Invariants may be confirmed by validation: @@ -420,7 +418,7 @@ impl Type { TypeEnum::Extension(cty) => vec![Type::new_extension(cty.substitute(t))], TypeEnum::Function(bf) => vec![Type::new_function(bf.substitute(t))], TypeEnum::Sum(SumType::General { rows }) => { - vec![Type::new_sum(rows.iter().map(|x| subst_row(x, t)))] + vec![Type::new_sum(rows.iter().map(|r| r.substitute(t)))] } } } @@ -466,24 +464,6 @@ impl<'a> Substitution<'a> { } } -fn valid_row( - row: &TypeRow, - exts: &ExtensionRegistry, - var_decls: &[TypeParam], -) -> Result<(), SignatureError> { - row.iter() - .try_for_each(|t| t.validate_in_row(exts, var_decls)) -} - -fn subst_row(row: &TypeRow, tr: &Substitution) -> TypeRow { - let res = row - .iter() - .flat_map(|ty| ty.substitute(tr)) - .collect::>() - .into(); - res -} - pub(crate) fn check_typevar_decl( decls: &[TypeParam], idx: usize, diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index cb47181c0..89b49461a 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -5,7 +5,7 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; -use super::{subst_row, valid_row, Substitution, Type, TypeRow}; +use super::{Substitution, Type, TypeRow}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -37,15 +37,16 @@ impl FunctionType { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - valid_row(&self.input, extension_registry, var_decls)?; - valid_row(&self.output, extension_registry, var_decls)?; + self.input.validate_var_len(extension_registry, var_decls)?; + self.output + .validate_var_len(extension_registry, var_decls)?; self.extension_reqs.validate(var_decls) } pub(crate) fn substitute(&self, tr: &Substitution) -> Self { FunctionType { - input: subst_row(&self.input, tr), - output: subst_row(&self.output, tr), + input: self.input.substitute(tr), + output: self.output.substitute(tr), extension_reqs: self.extension_reqs.substitute(tr), } } diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index 1f0d379cb..5facd9677 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -7,9 +7,12 @@ use std::{ ops::{Deref, DerefMut}, }; -use super::Type; -use crate::utils::display_list; +use super::{type_param::TypeParam, Substitution, Type}; use crate::PortIndex; +use crate::{ + extension::{ExtensionRegistry, SignatureError}, + utils::display_list, +}; use delegate::delegate; use itertools::Itertools; @@ -40,6 +43,8 @@ impl TypeRow { #[inline(always)] /// Returns the port type given an offset. Returns `None` if the offset is out of bounds. + // Note/TODO: it might be good to disable this if we are indexing over (past) a Row Variable, + // as substitution could change where in the row the offset refers. pub fn get(&self, offset: impl PortIndex) -> Option<&Type> { self.types.get(offset.index()) } @@ -78,6 +83,28 @@ impl TypeRow { pub fn is_empty(&self) -> bool ; } } + + /// Applies a substitution to the row. Note this may change the length + /// if-and-only-if the row contains any [RowVariable] + /// + /// [RowVariable]: [crate::types::TypeEnum::RowVariable] + pub(super) fn substitute(&self, tr: &Substitution) -> TypeRow { + let res = self + .iter() + .flat_map(|ty| ty.substitute(tr)) + .collect::>() + .into(); + res + } + + pub(super) fn validate_var_len( + &self, + exts: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError> { + self.iter() + .try_for_each(|t| t.validate_in_row(exts, var_decls)) + } } impl Default for TypeRow { From d9653aa406359b732ece5a6b51b1c51211ea82a5 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 12:30:56 +0100 Subject: [PATCH 15/42] Normalize representation of row variable as TypeArg; extend check_type_arg --- hugr/src/types/type_param.rs | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 6c2bee4c3..67bdf13b3 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -12,6 +12,7 @@ use crate::extension::ExtensionRegistry; use crate::extension::ExtensionSet; use crate::extension::SignatureError; +use super::TypeEnum; use super::{check_typevar_decl, CustomType, Substitution, Type, TypeBound}; /// The upper non-inclusive bound of a [`TypeParam::BoundedNat`] @@ -217,6 +218,12 @@ impl TypeArg { TypeParam::Type { b } => TypeArg::Type { ty: Type::new_var_use(idx, b), }, + TypeParam::List { param: bx } if matches!(*bx, TypeParam::Type { .. }) => { + let TypeParam::Type { b } = *bx else { panic!() }; + TypeArg::Type { + ty: Type::new_row_var(idx, b), + } + } TypeParam::Extensions => TypeArg::Extensions { es: ExtensionSet::type_var(idx), }, @@ -326,6 +333,23 @@ impl CustomTypeArg { /// Checks a [TypeArg] is as expected for a [TypeParam] pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgError> { + check_type_arg_rv(arg, param, false) +} + +fn check_type_arg_rv( + arg: &TypeArg, + param: &TypeParam, + allow_rowvars: bool, +) -> Result<(), TypeArgError> { + // allow_row_vars only applies if we are checking against values allowed inside a list + // (where the row variable could stand for *several* elements) + debug_assert!(!allow_rowvars || matches!(param, TypeParam::Type { .. })); + fn rowvar_in_list(ty: &Type, list_elem: &TypeParam) -> bool { + let TypeParam::Type { b } = list_elem else { + return false; + }; + matches!(ty.0, TypeEnum::RowVariable(_, _)) && b.contains(ty.least_upper_bound()) + } match (arg, param) { ( TypeArg::Variable { @@ -334,13 +358,21 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr _, ) if param.contains(cached_decl) => Ok(()), (TypeArg::Type { ty }, TypeParam::Type { b: bound }) - if bound.contains(ty.least_upper_bound()) => + if bound.contains(ty.least_upper_bound()) + && (allow_rowvars || !matches!(ty.0, TypeEnum::RowVariable(_, _))) => { Ok(()) } (TypeArg::Sequence { elems }, TypeParam::List { param }) => { - elems.iter().try_for_each(|arg| check_type_arg(arg, param)) + let allow_rvs = matches!(&**param, TypeParam::Type { .. }); + elems + .iter() + .try_for_each(|arg| check_type_arg_rv(arg, param, allow_rvs)) } + // Also allow a single "Type" to be used for a List *only* if the Type is a row variable + // (i.e., it's not really a Type, it's multiple Types) + (TypeArg::Type { ty }, TypeParam::List { param }) if rowvar_in_list(ty, &**param) => Ok(()), + (TypeArg::Sequence { elems: items }, TypeParam::Tuple { params: types }) => { if items.len() != types.len() { Err(TypeArgError::WrongNumberTuple(items.len(), types.len())) From 15bf1779c342407f1bc026420e6f03c5a91e94ad Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 13:15:17 +0100 Subject: [PATCH 16/42] Test bad schema, test can't fit row variable into type hole --- hugr/src/extension/op_def.rs | 14 ++++++++++++ hugr/src/types/poly_func.rs | 43 ++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index bcda1d067..6658bed8a 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -478,6 +478,7 @@ mod test { use crate::extension::{SignatureError, EMPTY_REG, PRELUDE_REGISTRY}; use crate::ops::{CustomOp, OpName}; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; + use crate::types::type_param::TypeArgError; use crate::types::Type; use crate::types::{type_param::TypeParam, FunctionType, PolyFuncType, TypeArg, TypeBound}; use crate::Hugr; @@ -633,6 +634,19 @@ mod test { def.compute_signature(&args, &EMPTY_REG), Ok(FunctionType::new_endo(vec![tv])) ); + // But not with an external row variable + let arg = TypeArg::Type { + ty: Type::new_row_var(0, TypeBound::Eq), + }; + assert_eq!( + def.compute_signature(&[arg.clone()], &EMPTY_REG), + Err(SignatureError::TypeArgMismatch( + TypeArgError::TypeMismatch { + param: TypeBound::Any.into(), + arg + } + )) + ); Ok(()) } diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index 3e5a5626c..cf55dcbf7 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -103,11 +103,13 @@ impl PolyFuncType { pub(crate) mod test { use std::num::NonZeroU64; + use cool_asserts::assert_matches; use lazy_static::lazy_static; use crate::extension::prelude::{BOOL_T, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; use crate::extension::{ - ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, PRELUDE, PRELUDE_REGISTRY, + ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, EMPTY_REG, PRELUDE, + PRELUDE_REGISTRY, }; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; @@ -336,27 +338,44 @@ pub(crate) mod test { Ok(()) } + const TP_ANY: TypeParam = TypeParam::Type { b: TypeBound::Any }; #[test] - fn row_variables() { - const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; + fn row_variables_bad_schema() { // Mismatched TypeBound (Copyable vs Any) - PolyFuncType::new_validated( - [TypeParam::List { - param: Box::new(TypeParam::Type { - b: TypeBound::Copyable, - }), - }], + let decl = TypeParam::List { + param: Box::new(TP_ANY), + }; + let e = PolyFuncType::new_validated( + [decl.clone()], FunctionType::new( - vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_tuple(vec![Type::new_row_var(0, TypeBound::Any)])], + vec![USIZE_T], + vec![Type::new_row_var(0, TypeBound::Copyable)], ), &PRELUDE_REGISTRY, ) .unwrap_err(); + assert_matches!(e, SignatureError::TypeVarDoesNotMatchDeclaration { actual, cached } => { + assert_eq!(actual, decl); + assert_eq!(cached, TypeParam::List {param: Box::new(TypeParam::Type {b: TypeBound::Copyable})}); + }); + // Declared as row variable, used as type variable + let e = PolyFuncType::new_validated( + [decl.clone()], + FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + &EMPTY_REG, + ) + .unwrap_err(); + assert_matches!(e, SignatureError::TypeVarDoesNotMatchDeclaration { actual, cached } => { + assert_eq!(actual, decl); + assert_eq!(cached, TP_ANY); + }); + } + #[test] + fn row_variables() { let pf = PolyFuncType::new_validated( [TypeParam::List { - param: Box::new(TP), + param: Box::new(TP_ANY), }], FunctionType::new( vec![USIZE_T, Type::new_row_var(0, TypeBound::Any)], From bc11c684b59f0e184d3750d85114d1148a6c7d95 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 15:30:49 +0100 Subject: [PATCH 17/42] Extend validation tests using eval+parallel --- hugr/src/hugr/validate/test.rs | 116 +++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 7 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index a620cf51a..4793d40e7 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -7,10 +7,10 @@ use crate::builder::{ FunctionBuilder, HugrBuilder, ModuleBuilder, SubContainer, }; use crate::extension::prelude::{BOOL_T, PRELUDE, PRELUDE_ID, USIZE_T}; -use crate::extension::{Extension, ExtensionSet, TypeDefBound, EMPTY_REG, PRELUDE_REGISTRY}; +use crate::extension::{Extension, ExtensionSet, OpDef, TypeDefBound, EMPTY_REG, PRELUDE_REGISTRY}; use crate::hugr::hugrmut::sealed::HugrMutInternals; use crate::hugr::HugrMut; -use crate::ops::dataflow::IOTrait; +use crate::ops::dataflow::{IOTrait, LoadFunction}; use crate::ops::handle::NodeHandle; use crate::ops::leaf::MakeTuple; use crate::ops::{self, Noop, OpType, Value}; @@ -546,23 +546,125 @@ fn no_polymorphic_consts() -> Result<(), Box> { Ok(()) } +fn rowparam() -> TypeParam { + TypeParam::List { + param: Box::new(TypeBound::Any.into()), + } +} + +fn add_eval_op(e: &mut Extension) -> &mut OpDef { + let inputs = Type::new_row_var(0, TypeBound::Any); + let outputs = Type::new_row_var(1, TypeBound::Any); + let evaled_fn = Type::new_function(FunctionType::new(inputs.clone(), outputs.clone())); + let pf = PolyFuncType::new( + [rowparam(), rowparam()], + FunctionType::new(vec![evaled_fn, inputs], outputs), + ); + e.add_op("eval".into(), "".into(), pf).unwrap() +} + +fn add_parallel_op(e: &mut Extension) -> &mut OpDef { + let rv = |idx| Type::new_row_var(idx, TypeBound::Any); + let pf = PolyFuncType::new( + [rowparam(), rowparam(), rowparam(), rowparam()], + FunctionType::new( + vec![ + Type::new_function(FunctionType::new(rv(0), rv(2))), + Type::new_function(FunctionType::new(rv(1), rv(3))), + ], + Type::new_function(FunctionType::new(vec![rv(0), rv(1)], vec![rv(2), rv(3)])), + ), + ); + e.add_op("parallel".into(), "".into(), pf).unwrap() +} + +#[test] +fn instantiate_row_variables() -> Result<(), Box> { + fn uint_seq(i: usize) -> TypeArg { + TypeArg::Sequence { + elems: vec![TypeArg::Type { ty: USIZE_T }; i], + } + } + let mut e = Extension::new(EXT_ID); + add_eval_op(&mut e); + add_parallel_op(&mut e); + let mut dfb = DFGBuilder::new(FunctionType::new( + vec![ + Type::new_function(FunctionType::new(USIZE_T, vec![USIZE_T, USIZE_T])), + USIZE_T, + ], // function + argument + vec![USIZE_T; 4], // results (twice each) + ))?; + let [func, int] = dfb.input_wires_arr(); + let eval = + e.instantiate_extension_op("eval".into(), [uint_seq(1), uint_seq(2)], &PRELUDE_REGISTRY)?; + let [a, b] = dfb.add_dataflow_op(eval, [func, int])?.outputs_arr(); + let par = e.instantiate_extension_op( + "parallel".into(), + [uint_seq(1), uint_seq(1), uint_seq(2), uint_seq(2)], + &PRELUDE_REGISTRY, + )?; + let [par_func] = dfb.add_dataflow_op(par, [func, func])?.outputs_arr(); + let eval2 = + e.instantiate_extension_op("eval".into(), [uint_seq(2), uint_seq(4)], &PRELUDE_REGISTRY)?; + let eval2 = dfb.add_dataflow_op(eval2, [par_func, a, b])?; + dfb.finish_hugr_with_outputs( + eval2.outputs(), + &ExtensionRegistry::try_new([PRELUDE.to_owned(), e]).unwrap(), + )?; + Ok(()) +} + #[test] fn inner_row_variables() -> Result<(), Box> { + let mut e = Extension::new(EXT_ID); + add_parallel_op(&mut e); + fn to_seq(t: Type) -> TypeArg { + TypeArg::Sequence { + elems: vec![t.into()], + } + } let tv = Type::new_row_var(0, TypeBound::Any); - let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); + let inner_ft = Type::new_function(FunctionType::new_endo(tv.clone())); + let ft_usz = Type::new_function(FunctionType::new_endo(vec![tv.clone(), USIZE_T])); let mut fb = FunctionBuilder::new( "id", PolyFuncType::new( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], - FunctionType::new_endo(vec![inner_ft.clone()]), + FunctionType::new(inner_ft.clone(), ft_usz), ), )?; // All the wires here are carrying higher-order Function values - // (the Functions themselves have variable arity, but that's fine as we are not calling them) - let id = fb.add_dataflow_op(Noop { ty: inner_ft }, fb.input_wires())?; - fb.finish_hugr_with_outputs(id.outputs(), &EMPTY_REG)?; + let [func_arg] = fb.input_wires_arr(); + let [id_usz] = { + let bldr = fb.define_function("id_usz", FunctionType::new_endo(USIZE_T).into())?; + let vals = bldr.input_wires(); + let [inner_def] = bldr.finish_with_outputs(vals)?.outputs_arr(); + let loadf = LoadFunction::try_new( + FunctionType::new_endo(USIZE_T).into(), + [], + &PRELUDE_REGISTRY, + ) + .unwrap(); + fb.add_dataflow_op(loadf, [inner_def])?.outputs_arr() + }; + let par = e.instantiate_extension_op( + "parallel".into(), + [ + to_seq(tv.clone()), + to_seq(USIZE_T), + to_seq(tv.clone()), + to_seq(USIZE_T), + ], + &PRELUDE_REGISTRY, + )?; + let par_func = fb.add_dataflow_op(par, [func_arg, id_usz])?; + fb.finish_hugr_with_outputs( + par_func.outputs(), + &ExtensionRegistry::try_new([PRELUDE.to_owned(), e]).unwrap(), + )?; Ok(()) } From f39373b6a49dc13fb2271e454203df36073adc57 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 10 May 2024 18:01:02 +0100 Subject: [PATCH 18/42] And extend no_outer_row_variables to include unconnected out'port's of eval --- hugr/src/hugr/validate/test.rs | 71 ++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 4793d40e7..ebc1185f0 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -1,4 +1,5 @@ use cool_asserts::assert_matches; +use rstest::rstest; use super::*; use crate::builder::test::closed_dfg_root_hugr; @@ -615,15 +616,16 @@ fn instantiate_row_variables() -> Result<(), Box> { Ok(()) } +fn single_type_seq(t: Type) -> TypeArg { + TypeArg::Sequence { + elems: vec![t.into()], + } +} + #[test] fn inner_row_variables() -> Result<(), Box> { let mut e = Extension::new(EXT_ID); add_parallel_op(&mut e); - fn to_seq(t: Type) -> TypeArg { - TypeArg::Sequence { - elems: vec![t.into()], - } - } let tv = Type::new_row_var(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(tv.clone())); let ft_usz = Type::new_function(FunctionType::new_endo(vec![tv.clone(), USIZE_T])); @@ -652,12 +654,7 @@ fn inner_row_variables() -> Result<(), Box> { }; let par = e.instantiate_extension_op( "parallel".into(), - [ - to_seq(tv.clone()), - to_seq(USIZE_T), - to_seq(tv.clone()), - to_seq(USIZE_T), - ], + [tv.clone(), USIZE_T, tv.clone(), USIZE_T].map(single_type_seq), &PRELUDE_REGISTRY, )?; let par_func = fb.add_dataflow_op(par, [func_arg, id_usz])?; @@ -668,30 +665,46 @@ fn inner_row_variables() -> Result<(), Box> { Ok(()) } -#[test] -fn no_outer_row_variables() -> Result<(), Box> { - let tv = Type::new_row_var(0, TypeBound::Any); - let fb = FunctionBuilder::new( - "impossible_id_of_unknown_arity", +#[rstest] +#[case(false)] +#[case(true)] +fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box> { + let mut e = Extension::new(EXT_ID); + add_eval_op(&mut e); + let tv = Type::new_row_var(0, TypeBound::Copyable); + let mut fb = FunctionBuilder::new( + "bad_eval", PolyFuncType::new( [TypeParam::List { - param: Box::new(TypeParam::Type { b: TypeBound::Any }), + param: Box::new(TypeParam::Type { + b: TypeBound::Copyable, + }), }], - FunctionType::new_endo(vec![tv]), + FunctionType::new( + Type::new_function(FunctionType::new(USIZE_T, tv.clone())), + if connect { vec![tv.clone()] } else { vec![] }, + ), ), )?; - // Input and Output nodes have a Port whose type is List(Type(Any)) - // - so this is illegal because the wire between them is not a type: - let err = fb - .clone() - .finish_hugr_with_outputs(fb.input_wires(), &EMPTY_REG) - .unwrap_err(); - assert_matches!( - err, - BuildError::InvalidHUGR(ValidationError::SignatureError { .. }) + let [func_arg] = fb.input_wires_arr(); + let i = fb.add_load_value(crate::extension::prelude::ConstUsize::new(5)); + let ev = e.instantiate_extension_op( + "eval".into(), + [single_type_seq(USIZE_T.into()), single_type_seq(tv)], + &PRELUDE_REGISTRY, + )?; + let ev = fb.add_dataflow_op(ev, [func_arg, i])?; + let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), e]).unwrap(); + if connect { + fb.set_outputs(ev.outputs())?; + } + assert_eq!( + fb.finish_hugr(®).unwrap_err(), + ValidationError::SignatureError { + node: ev.node(), + cause: SignatureError::RowTypeVarOutsideRow { idx: 0 } + } ); - // Also try leaving no inputs/outputs - so this should be illegal because the ports are unconnected - fb.finish_hugr(&EMPTY_REG).unwrap_err(); Ok(()) } From bd39303045473106c9689ddf431910515759af92 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sat, 11 May 2024 00:19:29 +0100 Subject: [PATCH 19/42] comments re. canonicalization, tests --- hugr/src/types/type_param.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 67bdf13b3..646673e79 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -219,6 +219,11 @@ impl TypeArg { ty: Type::new_var_use(idx, b), }, TypeParam::List { param: bx } if matches!(*bx, TypeParam::Type { .. }) => { + // There are two reasonable schemes for representing row variables: + // 1. TypeArg::Variable(idx, TypeParam::List(TypeParam::Type(typebound))) + // 2. TypeArg::Type(Type::new_row_var(idx, typebound)) + // Here we prefer the latter for canonicalization, although we cannot really + // prevent both if users construct the TypeArg variants directly (doing so will break Eq) let TypeParam::Type { b } = *bx else { panic!() }; TypeArg::Type { ty: Type::new_row_var(idx, b), @@ -268,7 +273,9 @@ impl TypeArg { match self { TypeArg::Type { ty } => { // A row variable standing for many types is represented as a single type - // ALAN TODO: add test that would fail if we didn't handle this + // TODO: this case can't happen until we start substituting across Hugrs + // (rather than just their types) - e.g. instantiating the *body* (not just type) + // of a FuncDefn, polymorphic over a row variable, with multiple types let tys = ty .substitute(t) .into_iter() From ed64d128936d9badcee568e7fd1d10f098edb140 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sat, 11 May 2024 10:59:07 +0100 Subject: [PATCH 20/42] clippy --- hugr/src/hugr/validate/test.rs | 13 ++++++------- hugr/src/types/type_param.rs | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index ebc1185f0..15b4d9ac3 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -597,17 +597,16 @@ fn instantiate_row_variables() -> Result<(), Box> { vec![USIZE_T; 4], // results (twice each) ))?; let [func, int] = dfb.input_wires_arr(); - let eval = - e.instantiate_extension_op("eval".into(), [uint_seq(1), uint_seq(2)], &PRELUDE_REGISTRY)?; + let eval = e.instantiate_extension_op("eval", [uint_seq(1), uint_seq(2)], &PRELUDE_REGISTRY)?; let [a, b] = dfb.add_dataflow_op(eval, [func, int])?.outputs_arr(); let par = e.instantiate_extension_op( - "parallel".into(), + "parallel", [uint_seq(1), uint_seq(1), uint_seq(2), uint_seq(2)], &PRELUDE_REGISTRY, )?; let [par_func] = dfb.add_dataflow_op(par, [func, func])?.outputs_arr(); let eval2 = - e.instantiate_extension_op("eval".into(), [uint_seq(2), uint_seq(4)], &PRELUDE_REGISTRY)?; + e.instantiate_extension_op("eval", [uint_seq(2), uint_seq(4)], &PRELUDE_REGISTRY)?; let eval2 = dfb.add_dataflow_op(eval2, [par_func, a, b])?; dfb.finish_hugr_with_outputs( eval2.outputs(), @@ -653,7 +652,7 @@ fn inner_row_variables() -> Result<(), Box> { fb.add_dataflow_op(loadf, [inner_def])?.outputs_arr() }; let par = e.instantiate_extension_op( - "parallel".into(), + "parallel", [tv.clone(), USIZE_T, tv.clone(), USIZE_T].map(single_type_seq), &PRELUDE_REGISTRY, )?; @@ -689,8 +688,8 @@ fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box Ok(()), + (TypeArg::Type { ty }, TypeParam::List { param }) if rowvar_in_list(ty, param) => Ok(()), (TypeArg::Sequence { elems: items }, TypeParam::Tuple { params: types }) => { if items.len() != types.len() { From d02c9c0a8ae416971ea3d3314b716560e907d85f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sat, 11 May 2024 11:00:07 +0100 Subject: [PATCH 21/42] single_type_seq -> seq1ty --- hugr/src/hugr/validate/test.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 15b4d9ac3..457f75588 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -615,7 +615,7 @@ fn instantiate_row_variables() -> Result<(), Box> { Ok(()) } -fn single_type_seq(t: Type) -> TypeArg { +fn seq1ty(t: Type) -> TypeArg { TypeArg::Sequence { elems: vec![t.into()], } @@ -653,7 +653,7 @@ fn inner_row_variables() -> Result<(), Box> { }; let par = e.instantiate_extension_op( "parallel", - [tv.clone(), USIZE_T, tv.clone(), USIZE_T].map(single_type_seq), + [tv.clone(), USIZE_T, tv.clone(), USIZE_T].map(seq1ty), &PRELUDE_REGISTRY, )?; let par_func = fb.add_dataflow_op(par, [func_arg, id_usz])?; @@ -687,11 +687,8 @@ fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box Date: Sun, 12 May 2024 19:04:54 +0100 Subject: [PATCH 22/42] Combine helpers giving extension_with_eval_parallel --- hugr/src/hugr/validate/test.rs | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 457f75588..d2510aca5 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -8,7 +8,7 @@ use crate::builder::{ FunctionBuilder, HugrBuilder, ModuleBuilder, SubContainer, }; use crate::extension::prelude::{BOOL_T, PRELUDE, PRELUDE_ID, USIZE_T}; -use crate::extension::{Extension, ExtensionSet, OpDef, TypeDefBound, EMPTY_REG, PRELUDE_REGISTRY}; +use crate::extension::{Extension, ExtensionSet, TypeDefBound, EMPTY_REG, PRELUDE_REGISTRY}; use crate::hugr::hugrmut::sealed::HugrMutInternals; use crate::hugr::HugrMut; use crate::ops::dataflow::{IOTrait, LoadFunction}; @@ -547,13 +547,14 @@ fn no_polymorphic_consts() -> Result<(), Box> { Ok(()) } -fn rowparam() -> TypeParam { - TypeParam::List { - param: Box::new(TypeBound::Any.into()), +fn extension_with_eval_parallel() -> Extension { + fn rowparam() -> TypeParam { + TypeParam::List { + param: Box::new(TypeBound::Any.into()), + } } -} + let mut e = Extension::new(EXT_ID); -fn add_eval_op(e: &mut Extension) -> &mut OpDef { let inputs = Type::new_row_var(0, TypeBound::Any); let outputs = Type::new_row_var(1, TypeBound::Any); let evaled_fn = Type::new_function(FunctionType::new(inputs.clone(), outputs.clone())); @@ -561,10 +562,8 @@ fn add_eval_op(e: &mut Extension) -> &mut OpDef { [rowparam(), rowparam()], FunctionType::new(vec![evaled_fn, inputs], outputs), ); - e.add_op("eval".into(), "".into(), pf).unwrap() -} + e.add_op("eval".into(), "".into(), pf).unwrap(); -fn add_parallel_op(e: &mut Extension) -> &mut OpDef { let rv = |idx| Type::new_row_var(idx, TypeBound::Any); let pf = PolyFuncType::new( [rowparam(), rowparam(), rowparam(), rowparam()], @@ -576,7 +575,9 @@ fn add_parallel_op(e: &mut Extension) -> &mut OpDef { Type::new_function(FunctionType::new(vec![rv(0), rv(1)], vec![rv(2), rv(3)])), ), ); - e.add_op("parallel".into(), "".into(), pf).unwrap() + e.add_op("parallel".into(), "".into(), pf).unwrap(); + + e } #[test] @@ -586,9 +587,7 @@ fn instantiate_row_variables() -> Result<(), Box> { elems: vec![TypeArg::Type { ty: USIZE_T }; i], } } - let mut e = Extension::new(EXT_ID); - add_eval_op(&mut e); - add_parallel_op(&mut e); + let e = extension_with_eval_parallel(); let mut dfb = DFGBuilder::new(FunctionType::new( vec![ Type::new_function(FunctionType::new(USIZE_T, vec![USIZE_T, USIZE_T])), @@ -623,8 +622,7 @@ fn seq1ty(t: Type) -> TypeArg { #[test] fn inner_row_variables() -> Result<(), Box> { - let mut e = Extension::new(EXT_ID); - add_parallel_op(&mut e); + let e = extension_with_eval_parallel(); let tv = Type::new_row_var(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(tv.clone())); let ft_usz = Type::new_function(FunctionType::new_endo(vec![tv.clone(), USIZE_T])); @@ -668,8 +666,7 @@ fn inner_row_variables() -> Result<(), Box> { #[case(false)] #[case(true)] fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box> { - let mut e = Extension::new(EXT_ID); - add_eval_op(&mut e); + let e = extension_with_eval_parallel(); let tv = Type::new_row_var(0, TypeBound::Copyable); let mut fb = FunctionBuilder::new( "bad_eval", @@ -720,7 +717,7 @@ fn test_polymorphic_call() -> Result<(), Box> { ) .with_extension_delta(ExtensionSet::type_var(1)), ); - // The higher-order "eval" operation - takes a function and its argument. + // Single-input/output version of the higher-order "eval" operation, with extension param. // Note the extension-delta of the eval node includes that of the input function. e.add_op( "eval".into(), From ce727620c0dbd4d915382b23c56af40218a482be Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sun, 12 May 2024 19:13:32 +0100 Subject: [PATCH 23/42] Add RowVar to serialization/tys.py --- hugr-py/src/hugr/serialization/tys.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/hugr-py/src/hugr/serialization/tys.py b/hugr-py/src/hugr/serialization/tys.py index 86078fc27..daee10b43 100644 --- a/hugr-py/src/hugr/serialization/tys.py +++ b/hugr-py/src/hugr/serialization/tys.py @@ -214,6 +214,15 @@ class Variable(ConfiguredBaseModel): b: "TypeBound" +class RowVar(ConfiguredBaseModel): + """A variable standing for a row of some (unknown) number of types. + May occur only within a row; not a node input/output.""" + + t: Literal["R"] = "R" + i: int + b: "TypeBound" + + class USize(ConfiguredBaseModel): """Unsigned integer size type.""" @@ -321,7 +330,15 @@ class Type(RootModel): """A HUGR type.""" root: Annotated[ - Qubit | Variable | USize | FunctionType | Array | SumType | Opaque | Alias, + Qubit + | Variable + | RowVar + | USize + | FunctionType + | Array + | SumType + | Opaque + | Alias, WrapValidator(_json_custom_error_validator), Field(discriminator="t"), ] From c556a8ae111981f27359c1c6ccf4a2171e838449 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sun, 12 May 2024 19:15:18 +0100 Subject: [PATCH 24/42] Regenerate schema --- .../schema/hugr_schema_strict_v1.json | 346 ++++-------------- specification/schema/hugr_schema_v1.json | 346 ++++-------------- .../schema/testing_hugr_schema_strict_v1.json | 346 ++++-------------- .../schema/testing_hugr_schema_v1.json | 346 ++++-------------- 4 files changed, 324 insertions(+), 1060 deletions(-) diff --git a/specification/schema/hugr_schema_strict_v1.json b/specification/schema/hugr_schema_strict_v1.json index 056ceeaf2..fef6770e5 100644 --- a/specification/schema/hugr_schema_strict_v1.json +++ b/specification/schema/hugr_schema_strict_v1.json @@ -7,11 +7,7 @@ "t": { "const": "Alias", "default": "Alias", - "enum": [ - "Alias" - ], - "title": "T", - "type": "string" + "title": "T" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -53,11 +49,7 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "enum": [ - "AliasDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -100,11 +92,7 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "enum": [ - "AliasDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -132,11 +120,7 @@ "t": { "const": "Array", "default": "Array", - "enum": [ - "Array" - ], - "title": "T", - "type": "string" + "title": "T" }, "len": { "title": "Len", @@ -156,11 +140,7 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "n": { "title": "N", @@ -179,11 +159,7 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "bound": { "anyOf": [ @@ -229,11 +205,7 @@ "op": { "const": "CFG", "default": "CFG", - "enum": [ - "CFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -271,11 +243,7 @@ "op": { "const": "Call", "default": "Call", - "enum": [ - "Call" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -326,11 +294,7 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "enum": [ - "CallIndirect" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -368,11 +332,7 @@ "op": { "const": "Case", "default": "Case", - "enum": [ - "Case" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -410,11 +370,7 @@ "op": { "const": "Conditional", "default": "Conditional", - "enum": [ - "Conditional" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "other_inputs": { "items": { @@ -481,11 +437,7 @@ "op": { "const": "Const", "default": "Const", - "enum": [ - "Const" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "v": { "$ref": "#/$defs/Value" @@ -542,11 +494,7 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "enum": [ - "CustomOp" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "extension": { "title": "Extension", @@ -606,11 +554,7 @@ "op": { "const": "DFG", "default": "DFG", - "enum": [ - "DFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -648,11 +592,7 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "enum": [ - "DataflowBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "inputs": { "items": { @@ -719,11 +659,7 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "enum": [ - "ExitBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "cfg_outputs": { "items": { @@ -747,11 +683,7 @@ "v": { "const": "Extension", "default": "Extension", - "enum": [ - "Extension" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "extensions": { "items": { @@ -781,11 +713,7 @@ "tya": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "es": { "items": { @@ -807,11 +735,7 @@ "tp": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tp", - "type": "string" + "title": "Tp" } }, "title": "ExtensionsParam", @@ -843,11 +767,7 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "enum": [ - "FuncDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -891,11 +811,7 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "enum": [ - "FuncDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -920,11 +836,7 @@ "t": { "const": "G", "default": "G", - "enum": [ - "G" - ], - "title": "T", - "type": "string" + "title": "T" }, "input": { "items": { @@ -962,11 +874,7 @@ "v": { "const": "Function", "default": "Function", - "enum": [ - "Function" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "hugr": { "title": "Hugr" @@ -985,20 +893,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "General", "default": "General", - "enum": [ - "General" - ], - "title": "S", - "type": "string" + "title": "S" }, "rows": { "items": { @@ -1043,11 +943,7 @@ "op": { "const": "Input", "default": "Input", - "enum": [ - "Input" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1089,11 +985,7 @@ "op": { "const": "Lift", "default": "Lift", - "enum": [ - "Lift" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "type_row": { "items": { @@ -1121,11 +1013,7 @@ "tp": { "const": "List", "default": "List", - "enum": [ - "List" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1163,11 +1051,7 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "enum": [ - "LoadConstant" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "datatype": { "$ref": "#/$defs/Type" @@ -1206,11 +1090,7 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "enum": [ - "LoadFunction" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1261,11 +1141,7 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "enum": [ - "MakeTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -1307,11 +1183,7 @@ "op": { "const": "Module", "default": "Module", - "enum": [ - "Module" - ], - "title": "Op", - "type": "string" + "title": "Op" } }, "required": [ @@ -1346,11 +1218,7 @@ "op": { "const": "Noop", "default": "Noop", - "enum": [ - "Noop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "ty": { "$ref": "#/$defs/Type" @@ -1485,11 +1353,7 @@ "t": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "T", - "type": "string" + "title": "T" }, "extension": { "title": "Extension", @@ -1525,11 +1389,7 @@ "tya": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1551,11 +1411,7 @@ "tp": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1593,11 +1449,7 @@ "op": { "const": "Output", "default": "Output", - "enum": [ - "Output" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1642,27 +1494,43 @@ "t": { "const": "Q", "default": "Q", - "enum": [ - "Q" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "Qubit", "type": "object" }, + "RowVar": { + "additionalProperties": false, + "description": "A variable standing for a row of some (unknown) number of types.\nMay occur only within a row; not a node input/output.", + "properties": { + "t": { + "const": "R", + "default": "R", + "title": "T" + }, + "i": { + "title": "I", + "type": "integer" + }, + "b": { + "$ref": "#/$defs/TypeBound" + } + }, + "required": [ + "i", + "b" + ], + "title": "RowVar", + "type": "object" + }, "SequenceArg": { "additionalProperties": false, "properties": { "tya": { "const": "Sequence", "default": "Sequence", - "enum": [ - "Sequence" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "elems": { "items": { @@ -1706,11 +1574,7 @@ "v": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "tag": { "title": "Tag", @@ -1761,11 +1625,7 @@ "op": { "const": "Tag", "default": "Tag", - "enum": [ - "Tag" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tag": { "title": "Tag", @@ -1816,11 +1676,7 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "enum": [ - "TailLoop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "just_inputs": { "items": { @@ -1856,11 +1712,7 @@ "tp": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "params": { "items": { @@ -1883,11 +1735,7 @@ "v": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "vs": { "items": { @@ -1913,6 +1761,7 @@ "I": "#/$defs/USize", "Opaque": "#/$defs/Opaque", "Q": "#/$defs/Qubit", + "R": "#/$defs/RowVar", "Sum": "#/$defs/SumType", "V": "#/$defs/Variable" }, @@ -1925,6 +1774,9 @@ { "$ref": "#/$defs/Variable" }, + { + "$ref": "#/$defs/RowVar" + }, { "$ref": "#/$defs/USize" }, @@ -2040,11 +1892,7 @@ "tya": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "ty": { "$ref": "#/$defs/Type" @@ -2062,11 +1910,7 @@ "tp": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2085,11 +1929,7 @@ "t": { "const": "I", "default": "I", - "enum": [ - "I" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "USize", @@ -2102,20 +1942,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "Unit", "default": "Unit", - "enum": [ - "Unit" - ], - "title": "S", - "type": "string" + "title": "S" }, "size": { "title": "Size", @@ -2154,11 +1986,7 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "enum": [ - "UnpackTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -2211,11 +2039,7 @@ "t": { "const": "V", "default": "V", - "enum": [ - "V" - ], - "title": "T", - "type": "string" + "title": "T" }, "i": { "title": "I", @@ -2237,11 +2061,7 @@ "tya": { "const": "Variable", "default": "Variable", - "enum": [ - "Variable" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "idx": { "title": "Idx", @@ -2264,11 +2084,7 @@ "version": { "const": "v1", "default": "v1", - "enum": [ - "v1" - ], - "title": "Version", - "type": "string" + "title": "Version" }, "nodes": { "items": { diff --git a/specification/schema/hugr_schema_v1.json b/specification/schema/hugr_schema_v1.json index 27d58db73..e3be9cf18 100644 --- a/specification/schema/hugr_schema_v1.json +++ b/specification/schema/hugr_schema_v1.json @@ -7,11 +7,7 @@ "t": { "const": "Alias", "default": "Alias", - "enum": [ - "Alias" - ], - "title": "T", - "type": "string" + "title": "T" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -53,11 +49,7 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "enum": [ - "AliasDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -100,11 +92,7 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "enum": [ - "AliasDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -132,11 +120,7 @@ "t": { "const": "Array", "default": "Array", - "enum": [ - "Array" - ], - "title": "T", - "type": "string" + "title": "T" }, "len": { "title": "Len", @@ -156,11 +140,7 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "n": { "title": "N", @@ -179,11 +159,7 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "bound": { "anyOf": [ @@ -229,11 +205,7 @@ "op": { "const": "CFG", "default": "CFG", - "enum": [ - "CFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -271,11 +243,7 @@ "op": { "const": "Call", "default": "Call", - "enum": [ - "Call" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -326,11 +294,7 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "enum": [ - "CallIndirect" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -368,11 +332,7 @@ "op": { "const": "Case", "default": "Case", - "enum": [ - "Case" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -410,11 +370,7 @@ "op": { "const": "Conditional", "default": "Conditional", - "enum": [ - "Conditional" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "other_inputs": { "items": { @@ -481,11 +437,7 @@ "op": { "const": "Const", "default": "Const", - "enum": [ - "Const" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "v": { "$ref": "#/$defs/Value" @@ -542,11 +494,7 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "enum": [ - "CustomOp" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "extension": { "title": "Extension", @@ -606,11 +554,7 @@ "op": { "const": "DFG", "default": "DFG", - "enum": [ - "DFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -648,11 +592,7 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "enum": [ - "DataflowBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "inputs": { "items": { @@ -719,11 +659,7 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "enum": [ - "ExitBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "cfg_outputs": { "items": { @@ -747,11 +683,7 @@ "v": { "const": "Extension", "default": "Extension", - "enum": [ - "Extension" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "extensions": { "items": { @@ -781,11 +713,7 @@ "tya": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "es": { "items": { @@ -807,11 +735,7 @@ "tp": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tp", - "type": "string" + "title": "Tp" } }, "title": "ExtensionsParam", @@ -843,11 +767,7 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "enum": [ - "FuncDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -891,11 +811,7 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "enum": [ - "FuncDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -920,11 +836,7 @@ "t": { "const": "G", "default": "G", - "enum": [ - "G" - ], - "title": "T", - "type": "string" + "title": "T" }, "input": { "items": { @@ -962,11 +874,7 @@ "v": { "const": "Function", "default": "Function", - "enum": [ - "Function" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "hugr": { "title": "Hugr" @@ -985,20 +893,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "General", "default": "General", - "enum": [ - "General" - ], - "title": "S", - "type": "string" + "title": "S" }, "rows": { "items": { @@ -1043,11 +943,7 @@ "op": { "const": "Input", "default": "Input", - "enum": [ - "Input" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1089,11 +985,7 @@ "op": { "const": "Lift", "default": "Lift", - "enum": [ - "Lift" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "type_row": { "items": { @@ -1121,11 +1013,7 @@ "tp": { "const": "List", "default": "List", - "enum": [ - "List" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1163,11 +1051,7 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "enum": [ - "LoadConstant" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "datatype": { "$ref": "#/$defs/Type" @@ -1206,11 +1090,7 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "enum": [ - "LoadFunction" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1261,11 +1141,7 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "enum": [ - "MakeTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -1307,11 +1183,7 @@ "op": { "const": "Module", "default": "Module", - "enum": [ - "Module" - ], - "title": "Op", - "type": "string" + "title": "Op" } }, "required": [ @@ -1346,11 +1218,7 @@ "op": { "const": "Noop", "default": "Noop", - "enum": [ - "Noop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "ty": { "$ref": "#/$defs/Type" @@ -1485,11 +1353,7 @@ "t": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "T", - "type": "string" + "title": "T" }, "extension": { "title": "Extension", @@ -1525,11 +1389,7 @@ "tya": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1551,11 +1411,7 @@ "tp": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1593,11 +1449,7 @@ "op": { "const": "Output", "default": "Output", - "enum": [ - "Output" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1642,27 +1494,43 @@ "t": { "const": "Q", "default": "Q", - "enum": [ - "Q" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "Qubit", "type": "object" }, + "RowVar": { + "additionalProperties": true, + "description": "A variable standing for a row of some (unknown) number of types.\nMay occur only within a row; not a node input/output.", + "properties": { + "t": { + "const": "R", + "default": "R", + "title": "T" + }, + "i": { + "title": "I", + "type": "integer" + }, + "b": { + "$ref": "#/$defs/TypeBound" + } + }, + "required": [ + "i", + "b" + ], + "title": "RowVar", + "type": "object" + }, "SequenceArg": { "additionalProperties": true, "properties": { "tya": { "const": "Sequence", "default": "Sequence", - "enum": [ - "Sequence" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "elems": { "items": { @@ -1706,11 +1574,7 @@ "v": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "tag": { "title": "Tag", @@ -1761,11 +1625,7 @@ "op": { "const": "Tag", "default": "Tag", - "enum": [ - "Tag" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tag": { "title": "Tag", @@ -1816,11 +1676,7 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "enum": [ - "TailLoop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "just_inputs": { "items": { @@ -1856,11 +1712,7 @@ "tp": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "params": { "items": { @@ -1883,11 +1735,7 @@ "v": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "vs": { "items": { @@ -1913,6 +1761,7 @@ "I": "#/$defs/USize", "Opaque": "#/$defs/Opaque", "Q": "#/$defs/Qubit", + "R": "#/$defs/RowVar", "Sum": "#/$defs/SumType", "V": "#/$defs/Variable" }, @@ -1925,6 +1774,9 @@ { "$ref": "#/$defs/Variable" }, + { + "$ref": "#/$defs/RowVar" + }, { "$ref": "#/$defs/USize" }, @@ -2040,11 +1892,7 @@ "tya": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "ty": { "$ref": "#/$defs/Type" @@ -2062,11 +1910,7 @@ "tp": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2085,11 +1929,7 @@ "t": { "const": "I", "default": "I", - "enum": [ - "I" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "USize", @@ -2102,20 +1942,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "Unit", "default": "Unit", - "enum": [ - "Unit" - ], - "title": "S", - "type": "string" + "title": "S" }, "size": { "title": "Size", @@ -2154,11 +1986,7 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "enum": [ - "UnpackTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -2211,11 +2039,7 @@ "t": { "const": "V", "default": "V", - "enum": [ - "V" - ], - "title": "T", - "type": "string" + "title": "T" }, "i": { "title": "I", @@ -2237,11 +2061,7 @@ "tya": { "const": "Variable", "default": "Variable", - "enum": [ - "Variable" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "idx": { "title": "Idx", @@ -2264,11 +2084,7 @@ "version": { "const": "v1", "default": "v1", - "enum": [ - "v1" - ], - "title": "Version", - "type": "string" + "title": "Version" }, "nodes": { "items": { diff --git a/specification/schema/testing_hugr_schema_strict_v1.json b/specification/schema/testing_hugr_schema_strict_v1.json index 39687363c..297b6be95 100644 --- a/specification/schema/testing_hugr_schema_strict_v1.json +++ b/specification/schema/testing_hugr_schema_strict_v1.json @@ -7,11 +7,7 @@ "t": { "const": "Alias", "default": "Alias", - "enum": [ - "Alias" - ], - "title": "T", - "type": "string" + "title": "T" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -53,11 +49,7 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "enum": [ - "AliasDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -100,11 +92,7 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "enum": [ - "AliasDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -132,11 +120,7 @@ "t": { "const": "Array", "default": "Array", - "enum": [ - "Array" - ], - "title": "T", - "type": "string" + "title": "T" }, "len": { "title": "Len", @@ -156,11 +140,7 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "n": { "title": "N", @@ -179,11 +159,7 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "bound": { "anyOf": [ @@ -229,11 +205,7 @@ "op": { "const": "CFG", "default": "CFG", - "enum": [ - "CFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -271,11 +243,7 @@ "op": { "const": "Call", "default": "Call", - "enum": [ - "Call" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -326,11 +294,7 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "enum": [ - "CallIndirect" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -368,11 +332,7 @@ "op": { "const": "Case", "default": "Case", - "enum": [ - "Case" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -410,11 +370,7 @@ "op": { "const": "Conditional", "default": "Conditional", - "enum": [ - "Conditional" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "other_inputs": { "items": { @@ -481,11 +437,7 @@ "op": { "const": "Const", "default": "Const", - "enum": [ - "Const" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "v": { "$ref": "#/$defs/Value" @@ -542,11 +494,7 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "enum": [ - "CustomOp" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "extension": { "title": "Extension", @@ -606,11 +554,7 @@ "op": { "const": "DFG", "default": "DFG", - "enum": [ - "DFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -648,11 +592,7 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "enum": [ - "DataflowBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "inputs": { "items": { @@ -719,11 +659,7 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "enum": [ - "ExitBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "cfg_outputs": { "items": { @@ -747,11 +683,7 @@ "v": { "const": "Extension", "default": "Extension", - "enum": [ - "Extension" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "extensions": { "items": { @@ -781,11 +713,7 @@ "tya": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "es": { "items": { @@ -807,11 +735,7 @@ "tp": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tp", - "type": "string" + "title": "Tp" } }, "title": "ExtensionsParam", @@ -864,11 +788,7 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "enum": [ - "FuncDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -912,11 +832,7 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "enum": [ - "FuncDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -941,11 +857,7 @@ "t": { "const": "G", "default": "G", - "enum": [ - "G" - ], - "title": "T", - "type": "string" + "title": "T" }, "input": { "items": { @@ -983,11 +895,7 @@ "v": { "const": "Function", "default": "Function", - "enum": [ - "Function" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "hugr": { "title": "Hugr" @@ -1006,20 +914,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "General", "default": "General", - "enum": [ - "General" - ], - "title": "S", - "type": "string" + "title": "S" }, "rows": { "items": { @@ -1064,11 +964,7 @@ "op": { "const": "Input", "default": "Input", - "enum": [ - "Input" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1110,11 +1006,7 @@ "op": { "const": "Lift", "default": "Lift", - "enum": [ - "Lift" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "type_row": { "items": { @@ -1142,11 +1034,7 @@ "tp": { "const": "List", "default": "List", - "enum": [ - "List" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1184,11 +1072,7 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "enum": [ - "LoadConstant" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "datatype": { "$ref": "#/$defs/Type" @@ -1227,11 +1111,7 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "enum": [ - "LoadFunction" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1282,11 +1162,7 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "enum": [ - "MakeTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -1328,11 +1204,7 @@ "op": { "const": "Module", "default": "Module", - "enum": [ - "Module" - ], - "title": "Op", - "type": "string" + "title": "Op" } }, "required": [ @@ -1367,11 +1239,7 @@ "op": { "const": "Noop", "default": "Noop", - "enum": [ - "Noop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "ty": { "$ref": "#/$defs/Type" @@ -1562,11 +1430,7 @@ "t": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "T", - "type": "string" + "title": "T" }, "extension": { "title": "Extension", @@ -1602,11 +1466,7 @@ "tya": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1628,11 +1488,7 @@ "tp": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1670,11 +1526,7 @@ "op": { "const": "Output", "default": "Output", - "enum": [ - "Output" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1719,27 +1571,43 @@ "t": { "const": "Q", "default": "Q", - "enum": [ - "Q" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "Qubit", "type": "object" }, + "RowVar": { + "additionalProperties": false, + "description": "A variable standing for a row of some (unknown) number of types.\nMay occur only within a row; not a node input/output.", + "properties": { + "t": { + "const": "R", + "default": "R", + "title": "T" + }, + "i": { + "title": "I", + "type": "integer" + }, + "b": { + "$ref": "#/$defs/TypeBound" + } + }, + "required": [ + "i", + "b" + ], + "title": "RowVar", + "type": "object" + }, "SequenceArg": { "additionalProperties": false, "properties": { "tya": { "const": "Sequence", "default": "Sequence", - "enum": [ - "Sequence" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "elems": { "items": { @@ -1783,11 +1651,7 @@ "v": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "tag": { "title": "Tag", @@ -1838,11 +1702,7 @@ "op": { "const": "Tag", "default": "Tag", - "enum": [ - "Tag" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tag": { "title": "Tag", @@ -1893,11 +1753,7 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "enum": [ - "TailLoop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "just_inputs": { "items": { @@ -1933,11 +1789,7 @@ "tp": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "params": { "items": { @@ -1960,11 +1812,7 @@ "v": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "vs": { "items": { @@ -1990,6 +1838,7 @@ "I": "#/$defs/USize", "Opaque": "#/$defs/Opaque", "Q": "#/$defs/Qubit", + "R": "#/$defs/RowVar", "Sum": "#/$defs/SumType", "V": "#/$defs/Variable" }, @@ -2002,6 +1851,9 @@ { "$ref": "#/$defs/Variable" }, + { + "$ref": "#/$defs/RowVar" + }, { "$ref": "#/$defs/USize" }, @@ -2117,11 +1969,7 @@ "tya": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "ty": { "$ref": "#/$defs/Type" @@ -2139,11 +1987,7 @@ "tp": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2162,11 +2006,7 @@ "t": { "const": "I", "default": "I", - "enum": [ - "I" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "USize", @@ -2179,20 +2019,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "Unit", "default": "Unit", - "enum": [ - "Unit" - ], - "title": "S", - "type": "string" + "title": "S" }, "size": { "title": "Size", @@ -2231,11 +2063,7 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "enum": [ - "UnpackTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -2288,11 +2116,7 @@ "t": { "const": "V", "default": "V", - "enum": [ - "V" - ], - "title": "T", - "type": "string" + "title": "T" }, "i": { "title": "I", @@ -2314,11 +2138,7 @@ "tya": { "const": "Variable", "default": "Variable", - "enum": [ - "Variable" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "idx": { "title": "Idx", @@ -2342,11 +2162,7 @@ "version": { "const": "v1", "default": "v1", - "enum": [ - "v1" - ], - "title": "Version", - "type": "string" + "title": "Version" }, "typ": { "anyOf": [ diff --git a/specification/schema/testing_hugr_schema_v1.json b/specification/schema/testing_hugr_schema_v1.json index 7b87683af..6d06445f6 100644 --- a/specification/schema/testing_hugr_schema_v1.json +++ b/specification/schema/testing_hugr_schema_v1.json @@ -7,11 +7,7 @@ "t": { "const": "Alias", "default": "Alias", - "enum": [ - "Alias" - ], - "title": "T", - "type": "string" + "title": "T" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -53,11 +49,7 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "enum": [ - "AliasDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -100,11 +92,7 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "enum": [ - "AliasDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -132,11 +120,7 @@ "t": { "const": "Array", "default": "Array", - "enum": [ - "Array" - ], - "title": "T", - "type": "string" + "title": "T" }, "len": { "title": "Len", @@ -156,11 +140,7 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "n": { "title": "N", @@ -179,11 +159,7 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "enum": [ - "BoundedNat" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "bound": { "anyOf": [ @@ -229,11 +205,7 @@ "op": { "const": "CFG", "default": "CFG", - "enum": [ - "CFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -271,11 +243,7 @@ "op": { "const": "Call", "default": "Call", - "enum": [ - "Call" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -326,11 +294,7 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "enum": [ - "CallIndirect" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -368,11 +332,7 @@ "op": { "const": "Case", "default": "Case", - "enum": [ - "Case" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -410,11 +370,7 @@ "op": { "const": "Conditional", "default": "Conditional", - "enum": [ - "Conditional" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "other_inputs": { "items": { @@ -481,11 +437,7 @@ "op": { "const": "Const", "default": "Const", - "enum": [ - "Const" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "v": { "$ref": "#/$defs/Value" @@ -542,11 +494,7 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "enum": [ - "CustomOp" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "extension": { "title": "Extension", @@ -606,11 +554,7 @@ "op": { "const": "DFG", "default": "DFG", - "enum": [ - "DFG" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -648,11 +592,7 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "enum": [ - "DataflowBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "inputs": { "items": { @@ -719,11 +659,7 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "enum": [ - "ExitBlock" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "cfg_outputs": { "items": { @@ -747,11 +683,7 @@ "v": { "const": "Extension", "default": "Extension", - "enum": [ - "Extension" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "extensions": { "items": { @@ -781,11 +713,7 @@ "tya": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "es": { "items": { @@ -807,11 +735,7 @@ "tp": { "const": "Extensions", "default": "Extensions", - "enum": [ - "Extensions" - ], - "title": "Tp", - "type": "string" + "title": "Tp" } }, "title": "ExtensionsParam", @@ -864,11 +788,7 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "enum": [ - "FuncDecl" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -912,11 +832,7 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "enum": [ - "FuncDefn" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "name": { "title": "Name", @@ -941,11 +857,7 @@ "t": { "const": "G", "default": "G", - "enum": [ - "G" - ], - "title": "T", - "type": "string" + "title": "T" }, "input": { "items": { @@ -983,11 +895,7 @@ "v": { "const": "Function", "default": "Function", - "enum": [ - "Function" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "hugr": { "title": "Hugr" @@ -1006,20 +914,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "General", "default": "General", - "enum": [ - "General" - ], - "title": "S", - "type": "string" + "title": "S" }, "rows": { "items": { @@ -1064,11 +964,7 @@ "op": { "const": "Input", "default": "Input", - "enum": [ - "Input" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1110,11 +1006,7 @@ "op": { "const": "Lift", "default": "Lift", - "enum": [ - "Lift" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "type_row": { "items": { @@ -1142,11 +1034,7 @@ "tp": { "const": "List", "default": "List", - "enum": [ - "List" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1184,11 +1072,7 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "enum": [ - "LoadConstant" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "datatype": { "$ref": "#/$defs/Type" @@ -1227,11 +1111,7 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "enum": [ - "LoadFunction" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1282,11 +1162,7 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "enum": [ - "MakeTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -1328,11 +1204,7 @@ "op": { "const": "Module", "default": "Module", - "enum": [ - "Module" - ], - "title": "Op", - "type": "string" + "title": "Op" } }, "required": [ @@ -1367,11 +1239,7 @@ "op": { "const": "Noop", "default": "Noop", - "enum": [ - "Noop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "ty": { "$ref": "#/$defs/Type" @@ -1562,11 +1430,7 @@ "t": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "T", - "type": "string" + "title": "T" }, "extension": { "title": "Extension", @@ -1602,11 +1466,7 @@ "tya": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1628,11 +1488,7 @@ "tp": { "const": "Opaque", "default": "Opaque", - "enum": [ - "Opaque" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1670,11 +1526,7 @@ "op": { "const": "Output", "default": "Output", - "enum": [ - "Output" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "types": { "items": { @@ -1719,27 +1571,43 @@ "t": { "const": "Q", "default": "Q", - "enum": [ - "Q" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "Qubit", "type": "object" }, + "RowVar": { + "additionalProperties": true, + "description": "A variable standing for a row of some (unknown) number of types.\nMay occur only within a row; not a node input/output.", + "properties": { + "t": { + "const": "R", + "default": "R", + "title": "T" + }, + "i": { + "title": "I", + "type": "integer" + }, + "b": { + "$ref": "#/$defs/TypeBound" + } + }, + "required": [ + "i", + "b" + ], + "title": "RowVar", + "type": "object" + }, "SequenceArg": { "additionalProperties": true, "properties": { "tya": { "const": "Sequence", "default": "Sequence", - "enum": [ - "Sequence" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "elems": { "items": { @@ -1783,11 +1651,7 @@ "v": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "tag": { "title": "Tag", @@ -1838,11 +1702,7 @@ "op": { "const": "Tag", "default": "Tag", - "enum": [ - "Tag" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tag": { "title": "Tag", @@ -1893,11 +1753,7 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "enum": [ - "TailLoop" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "just_inputs": { "items": { @@ -1933,11 +1789,7 @@ "tp": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "params": { "items": { @@ -1960,11 +1812,7 @@ "v": { "const": "Tuple", "default": "Tuple", - "enum": [ - "Tuple" - ], - "title": "ValueTag", - "type": "string" + "title": "ValueTag" }, "vs": { "items": { @@ -1990,6 +1838,7 @@ "I": "#/$defs/USize", "Opaque": "#/$defs/Opaque", "Q": "#/$defs/Qubit", + "R": "#/$defs/RowVar", "Sum": "#/$defs/SumType", "V": "#/$defs/Variable" }, @@ -2002,6 +1851,9 @@ { "$ref": "#/$defs/Variable" }, + { + "$ref": "#/$defs/RowVar" + }, { "$ref": "#/$defs/USize" }, @@ -2117,11 +1969,7 @@ "tya": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "ty": { "$ref": "#/$defs/Type" @@ -2139,11 +1987,7 @@ "tp": { "const": "Type", "default": "Type", - "enum": [ - "Type" - ], - "title": "Tp", - "type": "string" + "title": "Tp" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2162,11 +2006,7 @@ "t": { "const": "I", "default": "I", - "enum": [ - "I" - ], - "title": "T", - "type": "string" + "title": "T" } }, "title": "USize", @@ -2179,20 +2019,12 @@ "t": { "const": "Sum", "default": "Sum", - "enum": [ - "Sum" - ], - "title": "T", - "type": "string" + "title": "T" }, "s": { "const": "Unit", "default": "Unit", - "enum": [ - "Unit" - ], - "title": "S", - "type": "string" + "title": "S" }, "size": { "title": "Size", @@ -2231,11 +2063,7 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "enum": [ - "UnpackTuple" - ], - "title": "Op", - "type": "string" + "title": "Op" }, "tys": { "items": { @@ -2288,11 +2116,7 @@ "t": { "const": "V", "default": "V", - "enum": [ - "V" - ], - "title": "T", - "type": "string" + "title": "T" }, "i": { "title": "I", @@ -2314,11 +2138,7 @@ "tya": { "const": "Variable", "default": "Variable", - "enum": [ - "Variable" - ], - "title": "Tya", - "type": "string" + "title": "Tya" }, "idx": { "title": "Idx", @@ -2342,11 +2162,7 @@ "version": { "const": "v1", "default": "v1", - "enum": [ - "v1" - ], - "title": "Version", - "type": "string" + "title": "Version" }, "typ": { "anyOf": [ From 7214cbc328f0991e5babc0d9be2144d9050619b4 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Sun, 12 May 2024 19:24:47 +0100 Subject: [PATCH 25/42] Really regenerate schema (after poetry install) --- .../schema/hugr_schema_strict_v1.json | 324 +++++++++++++++--- specification/schema/hugr_schema_v1.json | 324 +++++++++++++++--- .../schema/testing_hugr_schema_strict_v1.json | 324 +++++++++++++++--- .../schema/testing_hugr_schema_v1.json | 324 +++++++++++++++--- 4 files changed, 1080 insertions(+), 216 deletions(-) diff --git a/specification/schema/hugr_schema_strict_v1.json b/specification/schema/hugr_schema_strict_v1.json index fef6770e5..bcb59e4c6 100644 --- a/specification/schema/hugr_schema_strict_v1.json +++ b/specification/schema/hugr_schema_strict_v1.json @@ -7,7 +7,11 @@ "t": { "const": "Alias", "default": "Alias", - "title": "T" + "enum": [ + "Alias" + ], + "title": "T", + "type": "string" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -49,7 +53,11 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "title": "Op" + "enum": [ + "AliasDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -92,7 +100,11 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "title": "Op" + "enum": [ + "AliasDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -120,7 +132,11 @@ "t": { "const": "Array", "default": "Array", - "title": "T" + "enum": [ + "Array" + ], + "title": "T", + "type": "string" }, "len": { "title": "Len", @@ -140,7 +156,11 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tya" + "enum": [ + "BoundedNat" + ], + "title": "Tya", + "type": "string" }, "n": { "title": "N", @@ -159,7 +179,11 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tp" + "enum": [ + "BoundedNat" + ], + "title": "Tp", + "type": "string" }, "bound": { "anyOf": [ @@ -205,7 +229,11 @@ "op": { "const": "CFG", "default": "CFG", - "title": "Op" + "enum": [ + "CFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -243,7 +271,11 @@ "op": { "const": "Call", "default": "Call", - "title": "Op" + "enum": [ + "Call" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -294,7 +326,11 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "title": "Op" + "enum": [ + "CallIndirect" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -332,7 +368,11 @@ "op": { "const": "Case", "default": "Case", - "title": "Op" + "enum": [ + "Case" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -370,7 +410,11 @@ "op": { "const": "Conditional", "default": "Conditional", - "title": "Op" + "enum": [ + "Conditional" + ], + "title": "Op", + "type": "string" }, "other_inputs": { "items": { @@ -437,7 +481,11 @@ "op": { "const": "Const", "default": "Const", - "title": "Op" + "enum": [ + "Const" + ], + "title": "Op", + "type": "string" }, "v": { "$ref": "#/$defs/Value" @@ -494,7 +542,11 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "title": "Op" + "enum": [ + "CustomOp" + ], + "title": "Op", + "type": "string" }, "extension": { "title": "Extension", @@ -554,7 +606,11 @@ "op": { "const": "DFG", "default": "DFG", - "title": "Op" + "enum": [ + "DFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -592,7 +648,11 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "title": "Op" + "enum": [ + "DataflowBlock" + ], + "title": "Op", + "type": "string" }, "inputs": { "items": { @@ -659,7 +719,11 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "title": "Op" + "enum": [ + "ExitBlock" + ], + "title": "Op", + "type": "string" }, "cfg_outputs": { "items": { @@ -683,7 +747,11 @@ "v": { "const": "Extension", "default": "Extension", - "title": "ValueTag" + "enum": [ + "Extension" + ], + "title": "ValueTag", + "type": "string" }, "extensions": { "items": { @@ -713,7 +781,11 @@ "tya": { "const": "Extensions", "default": "Extensions", - "title": "Tya" + "enum": [ + "Extensions" + ], + "title": "Tya", + "type": "string" }, "es": { "items": { @@ -735,7 +807,11 @@ "tp": { "const": "Extensions", "default": "Extensions", - "title": "Tp" + "enum": [ + "Extensions" + ], + "title": "Tp", + "type": "string" } }, "title": "ExtensionsParam", @@ -767,7 +843,11 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "title": "Op" + "enum": [ + "FuncDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -811,7 +891,11 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "title": "Op" + "enum": [ + "FuncDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -836,7 +920,11 @@ "t": { "const": "G", "default": "G", - "title": "T" + "enum": [ + "G" + ], + "title": "T", + "type": "string" }, "input": { "items": { @@ -874,7 +962,11 @@ "v": { "const": "Function", "default": "Function", - "title": "ValueTag" + "enum": [ + "Function" + ], + "title": "ValueTag", + "type": "string" }, "hugr": { "title": "Hugr" @@ -893,12 +985,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "General", "default": "General", - "title": "S" + "enum": [ + "General" + ], + "title": "S", + "type": "string" }, "rows": { "items": { @@ -943,7 +1043,11 @@ "op": { "const": "Input", "default": "Input", - "title": "Op" + "enum": [ + "Input" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -985,7 +1089,11 @@ "op": { "const": "Lift", "default": "Lift", - "title": "Op" + "enum": [ + "Lift" + ], + "title": "Op", + "type": "string" }, "type_row": { "items": { @@ -1013,7 +1121,11 @@ "tp": { "const": "List", "default": "List", - "title": "Tp" + "enum": [ + "List" + ], + "title": "Tp", + "type": "string" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1051,7 +1163,11 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "title": "Op" + "enum": [ + "LoadConstant" + ], + "title": "Op", + "type": "string" }, "datatype": { "$ref": "#/$defs/Type" @@ -1090,7 +1206,11 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "title": "Op" + "enum": [ + "LoadFunction" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1141,7 +1261,11 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "title": "Op" + "enum": [ + "MakeTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -1183,7 +1307,11 @@ "op": { "const": "Module", "default": "Module", - "title": "Op" + "enum": [ + "Module" + ], + "title": "Op", + "type": "string" } }, "required": [ @@ -1218,7 +1346,11 @@ "op": { "const": "Noop", "default": "Noop", - "title": "Op" + "enum": [ + "Noop" + ], + "title": "Op", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1353,7 +1485,11 @@ "t": { "const": "Opaque", "default": "Opaque", - "title": "T" + "enum": [ + "Opaque" + ], + "title": "T", + "type": "string" }, "extension": { "title": "Extension", @@ -1389,7 +1525,11 @@ "tya": { "const": "Opaque", "default": "Opaque", - "title": "Tya" + "enum": [ + "Opaque" + ], + "title": "Tya", + "type": "string" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1411,7 +1551,11 @@ "tp": { "const": "Opaque", "default": "Opaque", - "title": "Tp" + "enum": [ + "Opaque" + ], + "title": "Tp", + "type": "string" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1449,7 +1593,11 @@ "op": { "const": "Output", "default": "Output", - "title": "Op" + "enum": [ + "Output" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1494,7 +1642,11 @@ "t": { "const": "Q", "default": "Q", - "title": "T" + "enum": [ + "Q" + ], + "title": "T", + "type": "string" } }, "title": "Qubit", @@ -1507,7 +1659,11 @@ "t": { "const": "R", "default": "R", - "title": "T" + "enum": [ + "R" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -1530,7 +1686,11 @@ "tya": { "const": "Sequence", "default": "Sequence", - "title": "Tya" + "enum": [ + "Sequence" + ], + "title": "Tya", + "type": "string" }, "elems": { "items": { @@ -1574,7 +1734,11 @@ "v": { "const": "Sum", "default": "Sum", - "title": "ValueTag" + "enum": [ + "Sum" + ], + "title": "ValueTag", + "type": "string" }, "tag": { "title": "Tag", @@ -1625,7 +1789,11 @@ "op": { "const": "Tag", "default": "Tag", - "title": "Op" + "enum": [ + "Tag" + ], + "title": "Op", + "type": "string" }, "tag": { "title": "Tag", @@ -1676,7 +1844,11 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "title": "Op" + "enum": [ + "TailLoop" + ], + "title": "Op", + "type": "string" }, "just_inputs": { "items": { @@ -1712,7 +1884,11 @@ "tp": { "const": "Tuple", "default": "Tuple", - "title": "Tp" + "enum": [ + "Tuple" + ], + "title": "Tp", + "type": "string" }, "params": { "items": { @@ -1735,7 +1911,11 @@ "v": { "const": "Tuple", "default": "Tuple", - "title": "ValueTag" + "enum": [ + "Tuple" + ], + "title": "ValueTag", + "type": "string" }, "vs": { "items": { @@ -1892,7 +2072,11 @@ "tya": { "const": "Type", "default": "Type", - "title": "Tya" + "enum": [ + "Type" + ], + "title": "Tya", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1910,7 +2094,11 @@ "tp": { "const": "Type", "default": "Type", - "title": "Tp" + "enum": [ + "Type" + ], + "title": "Tp", + "type": "string" }, "b": { "$ref": "#/$defs/TypeBound" @@ -1929,7 +2117,11 @@ "t": { "const": "I", "default": "I", - "title": "T" + "enum": [ + "I" + ], + "title": "T", + "type": "string" } }, "title": "USize", @@ -1942,12 +2134,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "Unit", "default": "Unit", - "title": "S" + "enum": [ + "Unit" + ], + "title": "S", + "type": "string" }, "size": { "title": "Size", @@ -1986,7 +2186,11 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "title": "Op" + "enum": [ + "UnpackTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -2039,7 +2243,11 @@ "t": { "const": "V", "default": "V", - "title": "T" + "enum": [ + "V" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -2061,7 +2269,11 @@ "tya": { "const": "Variable", "default": "Variable", - "title": "Tya" + "enum": [ + "Variable" + ], + "title": "Tya", + "type": "string" }, "idx": { "title": "Idx", @@ -2084,7 +2296,11 @@ "version": { "const": "v1", "default": "v1", - "title": "Version" + "enum": [ + "v1" + ], + "title": "Version", + "type": "string" }, "nodes": { "items": { diff --git a/specification/schema/hugr_schema_v1.json b/specification/schema/hugr_schema_v1.json index e3be9cf18..188e4121f 100644 --- a/specification/schema/hugr_schema_v1.json +++ b/specification/schema/hugr_schema_v1.json @@ -7,7 +7,11 @@ "t": { "const": "Alias", "default": "Alias", - "title": "T" + "enum": [ + "Alias" + ], + "title": "T", + "type": "string" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -49,7 +53,11 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "title": "Op" + "enum": [ + "AliasDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -92,7 +100,11 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "title": "Op" + "enum": [ + "AliasDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -120,7 +132,11 @@ "t": { "const": "Array", "default": "Array", - "title": "T" + "enum": [ + "Array" + ], + "title": "T", + "type": "string" }, "len": { "title": "Len", @@ -140,7 +156,11 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tya" + "enum": [ + "BoundedNat" + ], + "title": "Tya", + "type": "string" }, "n": { "title": "N", @@ -159,7 +179,11 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tp" + "enum": [ + "BoundedNat" + ], + "title": "Tp", + "type": "string" }, "bound": { "anyOf": [ @@ -205,7 +229,11 @@ "op": { "const": "CFG", "default": "CFG", - "title": "Op" + "enum": [ + "CFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -243,7 +271,11 @@ "op": { "const": "Call", "default": "Call", - "title": "Op" + "enum": [ + "Call" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -294,7 +326,11 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "title": "Op" + "enum": [ + "CallIndirect" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -332,7 +368,11 @@ "op": { "const": "Case", "default": "Case", - "title": "Op" + "enum": [ + "Case" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -370,7 +410,11 @@ "op": { "const": "Conditional", "default": "Conditional", - "title": "Op" + "enum": [ + "Conditional" + ], + "title": "Op", + "type": "string" }, "other_inputs": { "items": { @@ -437,7 +481,11 @@ "op": { "const": "Const", "default": "Const", - "title": "Op" + "enum": [ + "Const" + ], + "title": "Op", + "type": "string" }, "v": { "$ref": "#/$defs/Value" @@ -494,7 +542,11 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "title": "Op" + "enum": [ + "CustomOp" + ], + "title": "Op", + "type": "string" }, "extension": { "title": "Extension", @@ -554,7 +606,11 @@ "op": { "const": "DFG", "default": "DFG", - "title": "Op" + "enum": [ + "DFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -592,7 +648,11 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "title": "Op" + "enum": [ + "DataflowBlock" + ], + "title": "Op", + "type": "string" }, "inputs": { "items": { @@ -659,7 +719,11 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "title": "Op" + "enum": [ + "ExitBlock" + ], + "title": "Op", + "type": "string" }, "cfg_outputs": { "items": { @@ -683,7 +747,11 @@ "v": { "const": "Extension", "default": "Extension", - "title": "ValueTag" + "enum": [ + "Extension" + ], + "title": "ValueTag", + "type": "string" }, "extensions": { "items": { @@ -713,7 +781,11 @@ "tya": { "const": "Extensions", "default": "Extensions", - "title": "Tya" + "enum": [ + "Extensions" + ], + "title": "Tya", + "type": "string" }, "es": { "items": { @@ -735,7 +807,11 @@ "tp": { "const": "Extensions", "default": "Extensions", - "title": "Tp" + "enum": [ + "Extensions" + ], + "title": "Tp", + "type": "string" } }, "title": "ExtensionsParam", @@ -767,7 +843,11 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "title": "Op" + "enum": [ + "FuncDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -811,7 +891,11 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "title": "Op" + "enum": [ + "FuncDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -836,7 +920,11 @@ "t": { "const": "G", "default": "G", - "title": "T" + "enum": [ + "G" + ], + "title": "T", + "type": "string" }, "input": { "items": { @@ -874,7 +962,11 @@ "v": { "const": "Function", "default": "Function", - "title": "ValueTag" + "enum": [ + "Function" + ], + "title": "ValueTag", + "type": "string" }, "hugr": { "title": "Hugr" @@ -893,12 +985,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "General", "default": "General", - "title": "S" + "enum": [ + "General" + ], + "title": "S", + "type": "string" }, "rows": { "items": { @@ -943,7 +1043,11 @@ "op": { "const": "Input", "default": "Input", - "title": "Op" + "enum": [ + "Input" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -985,7 +1089,11 @@ "op": { "const": "Lift", "default": "Lift", - "title": "Op" + "enum": [ + "Lift" + ], + "title": "Op", + "type": "string" }, "type_row": { "items": { @@ -1013,7 +1121,11 @@ "tp": { "const": "List", "default": "List", - "title": "Tp" + "enum": [ + "List" + ], + "title": "Tp", + "type": "string" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1051,7 +1163,11 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "title": "Op" + "enum": [ + "LoadConstant" + ], + "title": "Op", + "type": "string" }, "datatype": { "$ref": "#/$defs/Type" @@ -1090,7 +1206,11 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "title": "Op" + "enum": [ + "LoadFunction" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1141,7 +1261,11 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "title": "Op" + "enum": [ + "MakeTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -1183,7 +1307,11 @@ "op": { "const": "Module", "default": "Module", - "title": "Op" + "enum": [ + "Module" + ], + "title": "Op", + "type": "string" } }, "required": [ @@ -1218,7 +1346,11 @@ "op": { "const": "Noop", "default": "Noop", - "title": "Op" + "enum": [ + "Noop" + ], + "title": "Op", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1353,7 +1485,11 @@ "t": { "const": "Opaque", "default": "Opaque", - "title": "T" + "enum": [ + "Opaque" + ], + "title": "T", + "type": "string" }, "extension": { "title": "Extension", @@ -1389,7 +1525,11 @@ "tya": { "const": "Opaque", "default": "Opaque", - "title": "Tya" + "enum": [ + "Opaque" + ], + "title": "Tya", + "type": "string" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1411,7 +1551,11 @@ "tp": { "const": "Opaque", "default": "Opaque", - "title": "Tp" + "enum": [ + "Opaque" + ], + "title": "Tp", + "type": "string" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1449,7 +1593,11 @@ "op": { "const": "Output", "default": "Output", - "title": "Op" + "enum": [ + "Output" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1494,7 +1642,11 @@ "t": { "const": "Q", "default": "Q", - "title": "T" + "enum": [ + "Q" + ], + "title": "T", + "type": "string" } }, "title": "Qubit", @@ -1507,7 +1659,11 @@ "t": { "const": "R", "default": "R", - "title": "T" + "enum": [ + "R" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -1530,7 +1686,11 @@ "tya": { "const": "Sequence", "default": "Sequence", - "title": "Tya" + "enum": [ + "Sequence" + ], + "title": "Tya", + "type": "string" }, "elems": { "items": { @@ -1574,7 +1734,11 @@ "v": { "const": "Sum", "default": "Sum", - "title": "ValueTag" + "enum": [ + "Sum" + ], + "title": "ValueTag", + "type": "string" }, "tag": { "title": "Tag", @@ -1625,7 +1789,11 @@ "op": { "const": "Tag", "default": "Tag", - "title": "Op" + "enum": [ + "Tag" + ], + "title": "Op", + "type": "string" }, "tag": { "title": "Tag", @@ -1676,7 +1844,11 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "title": "Op" + "enum": [ + "TailLoop" + ], + "title": "Op", + "type": "string" }, "just_inputs": { "items": { @@ -1712,7 +1884,11 @@ "tp": { "const": "Tuple", "default": "Tuple", - "title": "Tp" + "enum": [ + "Tuple" + ], + "title": "Tp", + "type": "string" }, "params": { "items": { @@ -1735,7 +1911,11 @@ "v": { "const": "Tuple", "default": "Tuple", - "title": "ValueTag" + "enum": [ + "Tuple" + ], + "title": "ValueTag", + "type": "string" }, "vs": { "items": { @@ -1892,7 +2072,11 @@ "tya": { "const": "Type", "default": "Type", - "title": "Tya" + "enum": [ + "Type" + ], + "title": "Tya", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1910,7 +2094,11 @@ "tp": { "const": "Type", "default": "Type", - "title": "Tp" + "enum": [ + "Type" + ], + "title": "Tp", + "type": "string" }, "b": { "$ref": "#/$defs/TypeBound" @@ -1929,7 +2117,11 @@ "t": { "const": "I", "default": "I", - "title": "T" + "enum": [ + "I" + ], + "title": "T", + "type": "string" } }, "title": "USize", @@ -1942,12 +2134,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "Unit", "default": "Unit", - "title": "S" + "enum": [ + "Unit" + ], + "title": "S", + "type": "string" }, "size": { "title": "Size", @@ -1986,7 +2186,11 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "title": "Op" + "enum": [ + "UnpackTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -2039,7 +2243,11 @@ "t": { "const": "V", "default": "V", - "title": "T" + "enum": [ + "V" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -2061,7 +2269,11 @@ "tya": { "const": "Variable", "default": "Variable", - "title": "Tya" + "enum": [ + "Variable" + ], + "title": "Tya", + "type": "string" }, "idx": { "title": "Idx", @@ -2084,7 +2296,11 @@ "version": { "const": "v1", "default": "v1", - "title": "Version" + "enum": [ + "v1" + ], + "title": "Version", + "type": "string" }, "nodes": { "items": { diff --git a/specification/schema/testing_hugr_schema_strict_v1.json b/specification/schema/testing_hugr_schema_strict_v1.json index 297b6be95..9c272a944 100644 --- a/specification/schema/testing_hugr_schema_strict_v1.json +++ b/specification/schema/testing_hugr_schema_strict_v1.json @@ -7,7 +7,11 @@ "t": { "const": "Alias", "default": "Alias", - "title": "T" + "enum": [ + "Alias" + ], + "title": "T", + "type": "string" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -49,7 +53,11 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "title": "Op" + "enum": [ + "AliasDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -92,7 +100,11 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "title": "Op" + "enum": [ + "AliasDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -120,7 +132,11 @@ "t": { "const": "Array", "default": "Array", - "title": "T" + "enum": [ + "Array" + ], + "title": "T", + "type": "string" }, "len": { "title": "Len", @@ -140,7 +156,11 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tya" + "enum": [ + "BoundedNat" + ], + "title": "Tya", + "type": "string" }, "n": { "title": "N", @@ -159,7 +179,11 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tp" + "enum": [ + "BoundedNat" + ], + "title": "Tp", + "type": "string" }, "bound": { "anyOf": [ @@ -205,7 +229,11 @@ "op": { "const": "CFG", "default": "CFG", - "title": "Op" + "enum": [ + "CFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -243,7 +271,11 @@ "op": { "const": "Call", "default": "Call", - "title": "Op" + "enum": [ + "Call" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -294,7 +326,11 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "title": "Op" + "enum": [ + "CallIndirect" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -332,7 +368,11 @@ "op": { "const": "Case", "default": "Case", - "title": "Op" + "enum": [ + "Case" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -370,7 +410,11 @@ "op": { "const": "Conditional", "default": "Conditional", - "title": "Op" + "enum": [ + "Conditional" + ], + "title": "Op", + "type": "string" }, "other_inputs": { "items": { @@ -437,7 +481,11 @@ "op": { "const": "Const", "default": "Const", - "title": "Op" + "enum": [ + "Const" + ], + "title": "Op", + "type": "string" }, "v": { "$ref": "#/$defs/Value" @@ -494,7 +542,11 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "title": "Op" + "enum": [ + "CustomOp" + ], + "title": "Op", + "type": "string" }, "extension": { "title": "Extension", @@ -554,7 +606,11 @@ "op": { "const": "DFG", "default": "DFG", - "title": "Op" + "enum": [ + "DFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -592,7 +648,11 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "title": "Op" + "enum": [ + "DataflowBlock" + ], + "title": "Op", + "type": "string" }, "inputs": { "items": { @@ -659,7 +719,11 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "title": "Op" + "enum": [ + "ExitBlock" + ], + "title": "Op", + "type": "string" }, "cfg_outputs": { "items": { @@ -683,7 +747,11 @@ "v": { "const": "Extension", "default": "Extension", - "title": "ValueTag" + "enum": [ + "Extension" + ], + "title": "ValueTag", + "type": "string" }, "extensions": { "items": { @@ -713,7 +781,11 @@ "tya": { "const": "Extensions", "default": "Extensions", - "title": "Tya" + "enum": [ + "Extensions" + ], + "title": "Tya", + "type": "string" }, "es": { "items": { @@ -735,7 +807,11 @@ "tp": { "const": "Extensions", "default": "Extensions", - "title": "Tp" + "enum": [ + "Extensions" + ], + "title": "Tp", + "type": "string" } }, "title": "ExtensionsParam", @@ -788,7 +864,11 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "title": "Op" + "enum": [ + "FuncDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -832,7 +912,11 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "title": "Op" + "enum": [ + "FuncDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -857,7 +941,11 @@ "t": { "const": "G", "default": "G", - "title": "T" + "enum": [ + "G" + ], + "title": "T", + "type": "string" }, "input": { "items": { @@ -895,7 +983,11 @@ "v": { "const": "Function", "default": "Function", - "title": "ValueTag" + "enum": [ + "Function" + ], + "title": "ValueTag", + "type": "string" }, "hugr": { "title": "Hugr" @@ -914,12 +1006,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "General", "default": "General", - "title": "S" + "enum": [ + "General" + ], + "title": "S", + "type": "string" }, "rows": { "items": { @@ -964,7 +1064,11 @@ "op": { "const": "Input", "default": "Input", - "title": "Op" + "enum": [ + "Input" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1006,7 +1110,11 @@ "op": { "const": "Lift", "default": "Lift", - "title": "Op" + "enum": [ + "Lift" + ], + "title": "Op", + "type": "string" }, "type_row": { "items": { @@ -1034,7 +1142,11 @@ "tp": { "const": "List", "default": "List", - "title": "Tp" + "enum": [ + "List" + ], + "title": "Tp", + "type": "string" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1072,7 +1184,11 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "title": "Op" + "enum": [ + "LoadConstant" + ], + "title": "Op", + "type": "string" }, "datatype": { "$ref": "#/$defs/Type" @@ -1111,7 +1227,11 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "title": "Op" + "enum": [ + "LoadFunction" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1162,7 +1282,11 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "title": "Op" + "enum": [ + "MakeTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -1204,7 +1328,11 @@ "op": { "const": "Module", "default": "Module", - "title": "Op" + "enum": [ + "Module" + ], + "title": "Op", + "type": "string" } }, "required": [ @@ -1239,7 +1367,11 @@ "op": { "const": "Noop", "default": "Noop", - "title": "Op" + "enum": [ + "Noop" + ], + "title": "Op", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1430,7 +1562,11 @@ "t": { "const": "Opaque", "default": "Opaque", - "title": "T" + "enum": [ + "Opaque" + ], + "title": "T", + "type": "string" }, "extension": { "title": "Extension", @@ -1466,7 +1602,11 @@ "tya": { "const": "Opaque", "default": "Opaque", - "title": "Tya" + "enum": [ + "Opaque" + ], + "title": "Tya", + "type": "string" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1488,7 +1628,11 @@ "tp": { "const": "Opaque", "default": "Opaque", - "title": "Tp" + "enum": [ + "Opaque" + ], + "title": "Tp", + "type": "string" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1526,7 +1670,11 @@ "op": { "const": "Output", "default": "Output", - "title": "Op" + "enum": [ + "Output" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1571,7 +1719,11 @@ "t": { "const": "Q", "default": "Q", - "title": "T" + "enum": [ + "Q" + ], + "title": "T", + "type": "string" } }, "title": "Qubit", @@ -1584,7 +1736,11 @@ "t": { "const": "R", "default": "R", - "title": "T" + "enum": [ + "R" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -1607,7 +1763,11 @@ "tya": { "const": "Sequence", "default": "Sequence", - "title": "Tya" + "enum": [ + "Sequence" + ], + "title": "Tya", + "type": "string" }, "elems": { "items": { @@ -1651,7 +1811,11 @@ "v": { "const": "Sum", "default": "Sum", - "title": "ValueTag" + "enum": [ + "Sum" + ], + "title": "ValueTag", + "type": "string" }, "tag": { "title": "Tag", @@ -1702,7 +1866,11 @@ "op": { "const": "Tag", "default": "Tag", - "title": "Op" + "enum": [ + "Tag" + ], + "title": "Op", + "type": "string" }, "tag": { "title": "Tag", @@ -1753,7 +1921,11 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "title": "Op" + "enum": [ + "TailLoop" + ], + "title": "Op", + "type": "string" }, "just_inputs": { "items": { @@ -1789,7 +1961,11 @@ "tp": { "const": "Tuple", "default": "Tuple", - "title": "Tp" + "enum": [ + "Tuple" + ], + "title": "Tp", + "type": "string" }, "params": { "items": { @@ -1812,7 +1988,11 @@ "v": { "const": "Tuple", "default": "Tuple", - "title": "ValueTag" + "enum": [ + "Tuple" + ], + "title": "ValueTag", + "type": "string" }, "vs": { "items": { @@ -1969,7 +2149,11 @@ "tya": { "const": "Type", "default": "Type", - "title": "Tya" + "enum": [ + "Type" + ], + "title": "Tya", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1987,7 +2171,11 @@ "tp": { "const": "Type", "default": "Type", - "title": "Tp" + "enum": [ + "Type" + ], + "title": "Tp", + "type": "string" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2006,7 +2194,11 @@ "t": { "const": "I", "default": "I", - "title": "T" + "enum": [ + "I" + ], + "title": "T", + "type": "string" } }, "title": "USize", @@ -2019,12 +2211,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "Unit", "default": "Unit", - "title": "S" + "enum": [ + "Unit" + ], + "title": "S", + "type": "string" }, "size": { "title": "Size", @@ -2063,7 +2263,11 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "title": "Op" + "enum": [ + "UnpackTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -2116,7 +2320,11 @@ "t": { "const": "V", "default": "V", - "title": "T" + "enum": [ + "V" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -2138,7 +2346,11 @@ "tya": { "const": "Variable", "default": "Variable", - "title": "Tya" + "enum": [ + "Variable" + ], + "title": "Tya", + "type": "string" }, "idx": { "title": "Idx", @@ -2162,7 +2374,11 @@ "version": { "const": "v1", "default": "v1", - "title": "Version" + "enum": [ + "v1" + ], + "title": "Version", + "type": "string" }, "typ": { "anyOf": [ diff --git a/specification/schema/testing_hugr_schema_v1.json b/specification/schema/testing_hugr_schema_v1.json index 6d06445f6..01c3d6bb8 100644 --- a/specification/schema/testing_hugr_schema_v1.json +++ b/specification/schema/testing_hugr_schema_v1.json @@ -7,7 +7,11 @@ "t": { "const": "Alias", "default": "Alias", - "title": "T" + "enum": [ + "Alias" + ], + "title": "T", + "type": "string" }, "bound": { "$ref": "#/$defs/TypeBound" @@ -49,7 +53,11 @@ "op": { "const": "AliasDecl", "default": "AliasDecl", - "title": "Op" + "enum": [ + "AliasDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -92,7 +100,11 @@ "op": { "const": "AliasDefn", "default": "AliasDefn", - "title": "Op" + "enum": [ + "AliasDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -120,7 +132,11 @@ "t": { "const": "Array", "default": "Array", - "title": "T" + "enum": [ + "Array" + ], + "title": "T", + "type": "string" }, "len": { "title": "Len", @@ -140,7 +156,11 @@ "tya": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tya" + "enum": [ + "BoundedNat" + ], + "title": "Tya", + "type": "string" }, "n": { "title": "N", @@ -159,7 +179,11 @@ "tp": { "const": "BoundedNat", "default": "BoundedNat", - "title": "Tp" + "enum": [ + "BoundedNat" + ], + "title": "Tp", + "type": "string" }, "bound": { "anyOf": [ @@ -205,7 +229,11 @@ "op": { "const": "CFG", "default": "CFG", - "title": "Op" + "enum": [ + "CFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -243,7 +271,11 @@ "op": { "const": "Call", "default": "Call", - "title": "Op" + "enum": [ + "Call" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -294,7 +326,11 @@ "op": { "const": "CallIndirect", "default": "CallIndirect", - "title": "Op" + "enum": [ + "CallIndirect" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -332,7 +368,11 @@ "op": { "const": "Case", "default": "Case", - "title": "Op" + "enum": [ + "Case" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -370,7 +410,11 @@ "op": { "const": "Conditional", "default": "Conditional", - "title": "Op" + "enum": [ + "Conditional" + ], + "title": "Op", + "type": "string" }, "other_inputs": { "items": { @@ -437,7 +481,11 @@ "op": { "const": "Const", "default": "Const", - "title": "Op" + "enum": [ + "Const" + ], + "title": "Op", + "type": "string" }, "v": { "$ref": "#/$defs/Value" @@ -494,7 +542,11 @@ "op": { "const": "CustomOp", "default": "CustomOp", - "title": "Op" + "enum": [ + "CustomOp" + ], + "title": "Op", + "type": "string" }, "extension": { "title": "Extension", @@ -554,7 +606,11 @@ "op": { "const": "DFG", "default": "DFG", - "title": "Op" + "enum": [ + "DFG" + ], + "title": "Op", + "type": "string" }, "signature": { "$ref": "#/$defs/FunctionType" @@ -592,7 +648,11 @@ "op": { "const": "DataflowBlock", "default": "DataflowBlock", - "title": "Op" + "enum": [ + "DataflowBlock" + ], + "title": "Op", + "type": "string" }, "inputs": { "items": { @@ -659,7 +719,11 @@ "op": { "const": "ExitBlock", "default": "ExitBlock", - "title": "Op" + "enum": [ + "ExitBlock" + ], + "title": "Op", + "type": "string" }, "cfg_outputs": { "items": { @@ -683,7 +747,11 @@ "v": { "const": "Extension", "default": "Extension", - "title": "ValueTag" + "enum": [ + "Extension" + ], + "title": "ValueTag", + "type": "string" }, "extensions": { "items": { @@ -713,7 +781,11 @@ "tya": { "const": "Extensions", "default": "Extensions", - "title": "Tya" + "enum": [ + "Extensions" + ], + "title": "Tya", + "type": "string" }, "es": { "items": { @@ -735,7 +807,11 @@ "tp": { "const": "Extensions", "default": "Extensions", - "title": "Tp" + "enum": [ + "Extensions" + ], + "title": "Tp", + "type": "string" } }, "title": "ExtensionsParam", @@ -788,7 +864,11 @@ "op": { "const": "FuncDecl", "default": "FuncDecl", - "title": "Op" + "enum": [ + "FuncDecl" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -832,7 +912,11 @@ "op": { "const": "FuncDefn", "default": "FuncDefn", - "title": "Op" + "enum": [ + "FuncDefn" + ], + "title": "Op", + "type": "string" }, "name": { "title": "Name", @@ -857,7 +941,11 @@ "t": { "const": "G", "default": "G", - "title": "T" + "enum": [ + "G" + ], + "title": "T", + "type": "string" }, "input": { "items": { @@ -895,7 +983,11 @@ "v": { "const": "Function", "default": "Function", - "title": "ValueTag" + "enum": [ + "Function" + ], + "title": "ValueTag", + "type": "string" }, "hugr": { "title": "Hugr" @@ -914,12 +1006,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "General", "default": "General", - "title": "S" + "enum": [ + "General" + ], + "title": "S", + "type": "string" }, "rows": { "items": { @@ -964,7 +1064,11 @@ "op": { "const": "Input", "default": "Input", - "title": "Op" + "enum": [ + "Input" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1006,7 +1110,11 @@ "op": { "const": "Lift", "default": "Lift", - "title": "Op" + "enum": [ + "Lift" + ], + "title": "Op", + "type": "string" }, "type_row": { "items": { @@ -1034,7 +1142,11 @@ "tp": { "const": "List", "default": "List", - "title": "Tp" + "enum": [ + "List" + ], + "title": "Tp", + "type": "string" }, "param": { "$ref": "#/$defs/TypeParam" @@ -1072,7 +1184,11 @@ "op": { "const": "LoadConstant", "default": "LoadConstant", - "title": "Op" + "enum": [ + "LoadConstant" + ], + "title": "Op", + "type": "string" }, "datatype": { "$ref": "#/$defs/Type" @@ -1111,7 +1227,11 @@ "op": { "const": "LoadFunction", "default": "LoadFunction", - "title": "Op" + "enum": [ + "LoadFunction" + ], + "title": "Op", + "type": "string" }, "func_sig": { "$ref": "#/$defs/PolyFuncType" @@ -1162,7 +1282,11 @@ "op": { "const": "MakeTuple", "default": "MakeTuple", - "title": "Op" + "enum": [ + "MakeTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -1204,7 +1328,11 @@ "op": { "const": "Module", "default": "Module", - "title": "Op" + "enum": [ + "Module" + ], + "title": "Op", + "type": "string" } }, "required": [ @@ -1239,7 +1367,11 @@ "op": { "const": "Noop", "default": "Noop", - "title": "Op" + "enum": [ + "Noop" + ], + "title": "Op", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1430,7 +1562,11 @@ "t": { "const": "Opaque", "default": "Opaque", - "title": "T" + "enum": [ + "Opaque" + ], + "title": "T", + "type": "string" }, "extension": { "title": "Extension", @@ -1466,7 +1602,11 @@ "tya": { "const": "Opaque", "default": "Opaque", - "title": "Tya" + "enum": [ + "Opaque" + ], + "title": "Tya", + "type": "string" }, "typ": { "$ref": "#/$defs/Opaque" @@ -1488,7 +1628,11 @@ "tp": { "const": "Opaque", "default": "Opaque", - "title": "Tp" + "enum": [ + "Opaque" + ], + "title": "Tp", + "type": "string" }, "ty": { "$ref": "#/$defs/Opaque" @@ -1526,7 +1670,11 @@ "op": { "const": "Output", "default": "Output", - "title": "Op" + "enum": [ + "Output" + ], + "title": "Op", + "type": "string" }, "types": { "items": { @@ -1571,7 +1719,11 @@ "t": { "const": "Q", "default": "Q", - "title": "T" + "enum": [ + "Q" + ], + "title": "T", + "type": "string" } }, "title": "Qubit", @@ -1584,7 +1736,11 @@ "t": { "const": "R", "default": "R", - "title": "T" + "enum": [ + "R" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -1607,7 +1763,11 @@ "tya": { "const": "Sequence", "default": "Sequence", - "title": "Tya" + "enum": [ + "Sequence" + ], + "title": "Tya", + "type": "string" }, "elems": { "items": { @@ -1651,7 +1811,11 @@ "v": { "const": "Sum", "default": "Sum", - "title": "ValueTag" + "enum": [ + "Sum" + ], + "title": "ValueTag", + "type": "string" }, "tag": { "title": "Tag", @@ -1702,7 +1866,11 @@ "op": { "const": "Tag", "default": "Tag", - "title": "Op" + "enum": [ + "Tag" + ], + "title": "Op", + "type": "string" }, "tag": { "title": "Tag", @@ -1753,7 +1921,11 @@ "op": { "const": "TailLoop", "default": "TailLoop", - "title": "Op" + "enum": [ + "TailLoop" + ], + "title": "Op", + "type": "string" }, "just_inputs": { "items": { @@ -1789,7 +1961,11 @@ "tp": { "const": "Tuple", "default": "Tuple", - "title": "Tp" + "enum": [ + "Tuple" + ], + "title": "Tp", + "type": "string" }, "params": { "items": { @@ -1812,7 +1988,11 @@ "v": { "const": "Tuple", "default": "Tuple", - "title": "ValueTag" + "enum": [ + "Tuple" + ], + "title": "ValueTag", + "type": "string" }, "vs": { "items": { @@ -1969,7 +2149,11 @@ "tya": { "const": "Type", "default": "Type", - "title": "Tya" + "enum": [ + "Type" + ], + "title": "Tya", + "type": "string" }, "ty": { "$ref": "#/$defs/Type" @@ -1987,7 +2171,11 @@ "tp": { "const": "Type", "default": "Type", - "title": "Tp" + "enum": [ + "Type" + ], + "title": "Tp", + "type": "string" }, "b": { "$ref": "#/$defs/TypeBound" @@ -2006,7 +2194,11 @@ "t": { "const": "I", "default": "I", - "title": "T" + "enum": [ + "I" + ], + "title": "T", + "type": "string" } }, "title": "USize", @@ -2019,12 +2211,20 @@ "t": { "const": "Sum", "default": "Sum", - "title": "T" + "enum": [ + "Sum" + ], + "title": "T", + "type": "string" }, "s": { "const": "Unit", "default": "Unit", - "title": "S" + "enum": [ + "Unit" + ], + "title": "S", + "type": "string" }, "size": { "title": "Size", @@ -2063,7 +2263,11 @@ "op": { "const": "UnpackTuple", "default": "UnpackTuple", - "title": "Op" + "enum": [ + "UnpackTuple" + ], + "title": "Op", + "type": "string" }, "tys": { "items": { @@ -2116,7 +2320,11 @@ "t": { "const": "V", "default": "V", - "title": "T" + "enum": [ + "V" + ], + "title": "T", + "type": "string" }, "i": { "title": "I", @@ -2138,7 +2346,11 @@ "tya": { "const": "Variable", "default": "Variable", - "title": "Tya" + "enum": [ + "Variable" + ], + "title": "Tya", + "type": "string" }, "idx": { "title": "Idx", @@ -2162,7 +2374,11 @@ "version": { "const": "v1", "default": "v1", - "title": "Version" + "enum": [ + "v1" + ], + "title": "Version", + "type": "string" }, "typ": { "anyOf": [ From ce281542c6f08d6c421960951003e3a1c654ef81 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 09:18:25 +0100 Subject: [PATCH 26/42] Use Vec .into() -> TypeArg --- hugr/src/hugr/validate/test.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index d2510aca5..4cce1b9c3 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -583,17 +583,15 @@ fn extension_with_eval_parallel() -> Extension { #[test] fn instantiate_row_variables() -> Result<(), Box> { fn uint_seq(i: usize) -> TypeArg { - TypeArg::Sequence { - elems: vec![TypeArg::Type { ty: USIZE_T }; i], - } + vec![TypeArg::Type { ty: USIZE_T }; i].into() } let e = extension_with_eval_parallel(); let mut dfb = DFGBuilder::new(FunctionType::new( vec![ Type::new_function(FunctionType::new(USIZE_T, vec![USIZE_T, USIZE_T])), USIZE_T, - ], // function + argument - vec![USIZE_T; 4], // results (twice each) + ], // inputs: function + its argument + vec![USIZE_T; 4], // outputs (*2^2, three calls) ))?; let [func, int] = dfb.input_wires_arr(); let eval = e.instantiate_extension_op("eval", [uint_seq(1), uint_seq(2)], &PRELUDE_REGISTRY)?; From 0e4b23261e8754fb89357a2812857574a4fc0ac3 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 09:29:43 +0100 Subject: [PATCH 27/42] Add TypeParam::new_list --- hugr/src/hugr/validate/test.rs | 14 +++----------- hugr/src/types/type_param.rs | 12 ++++++++++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 4cce1b9c3..4ec8ae3a4 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -549,9 +549,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { fn extension_with_eval_parallel() -> Extension { fn rowparam() -> TypeParam { - TypeParam::List { - param: Box::new(TypeBound::Any.into()), - } + TypeParam::new_list(TypeBound::Any.into()) } let mut e = Extension::new(EXT_ID); @@ -627,9 +625,7 @@ fn inner_row_variables() -> Result<(), Box> { let mut fb = FunctionBuilder::new( "id", PolyFuncType::new( - [TypeParam::List { - param: Box::new(TypeParam::Type { b: TypeBound::Any }), - }], + [TypeParam::new_list(TypeBound::Any.into())], FunctionType::new(inner_ft.clone(), ft_usz), ), )?; @@ -669,11 +665,7 @@ fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box, }, /// Argument is a [TypeArg::Sequence]. A tuple of parameters. @@ -102,6 +103,13 @@ impl TypeParam { } } + /// Make a new `TypeParam::List` (an arbitrary-length homogenous) the + pub fn new_list(elem: TypeParam) -> Self { + Self::List { + param: Box::new(elem), + } + } + fn contains(&self, other: &TypeParam) -> bool { match (self, other) { (TypeParam::Type { b: b1 }, TypeParam::Type { b: b2 }) => b1.contains(*b2), From 5b39b9c5d051d7bb8fbcb59af5c4b594ad84f778 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 09:31:28 +0100 Subject: [PATCH 28/42] rowparam() -> rowp.clone() --- hugr/src/hugr/validate/test.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 4ec8ae3a4..cd4bb9e89 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -548,23 +548,21 @@ fn no_polymorphic_consts() -> Result<(), Box> { } fn extension_with_eval_parallel() -> Extension { - fn rowparam() -> TypeParam { - TypeParam::new_list(TypeBound::Any.into()) - } + let rowp = TypeParam::new_list(TypeBound::Any.into()); let mut e = Extension::new(EXT_ID); let inputs = Type::new_row_var(0, TypeBound::Any); let outputs = Type::new_row_var(1, TypeBound::Any); let evaled_fn = Type::new_function(FunctionType::new(inputs.clone(), outputs.clone())); let pf = PolyFuncType::new( - [rowparam(), rowparam()], + [rowp.clone(), rowp.clone()], FunctionType::new(vec![evaled_fn, inputs], outputs), ); e.add_op("eval".into(), "".into(), pf).unwrap(); let rv = |idx| Type::new_row_var(idx, TypeBound::Any); let pf = PolyFuncType::new( - [rowparam(), rowparam(), rowparam(), rowparam()], + [rowp.clone(), rowp.clone(), rowp.clone(), rowp.clone()], FunctionType::new( vec![ Type::new_function(FunctionType::new(rv(0), rv(2))), From 9ae2255d3ca0c80bec6bf39dbbb439863aa362bf Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 10:55:50 +0100 Subject: [PATCH 29/42] new_row_var => new_row_var_use, some cleanups using .into() --- hugr/src/extension/op_def.rs | 4 +--- hugr/src/hugr/validate/test.rs | 10 +++++----- hugr/src/types.rs | 2 +- hugr/src/types/poly_func.rs | 14 +++++--------- hugr/src/types/serialize.rs | 2 +- hugr/src/types/type_param.rs | 6 ++---- 6 files changed, 15 insertions(+), 23 deletions(-) diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 39729813c..2c7a45e8e 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -644,9 +644,7 @@ mod test { Ok(FunctionType::new_endo(vec![tv])) ); // But not with an external row variable - let arg = TypeArg::Type { - ty: Type::new_row_var(0, TypeBound::Eq), - }; + let arg: TypeArg = Type::new_row_var_use(0, TypeBound::Eq).into(); assert_eq!( def.compute_signature(&[arg.clone()], &EMPTY_REG), Err(SignatureError::TypeArgMismatch( diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index cd4bb9e89..2537eb91a 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -551,8 +551,8 @@ fn extension_with_eval_parallel() -> Extension { let rowp = TypeParam::new_list(TypeBound::Any.into()); let mut e = Extension::new(EXT_ID); - let inputs = Type::new_row_var(0, TypeBound::Any); - let outputs = Type::new_row_var(1, TypeBound::Any); + let inputs = Type::new_row_var_use(0, TypeBound::Any); + let outputs = Type::new_row_var_use(1, TypeBound::Any); let evaled_fn = Type::new_function(FunctionType::new(inputs.clone(), outputs.clone())); let pf = PolyFuncType::new( [rowp.clone(), rowp.clone()], @@ -560,7 +560,7 @@ fn extension_with_eval_parallel() -> Extension { ); e.add_op("eval".into(), "".into(), pf).unwrap(); - let rv = |idx| Type::new_row_var(idx, TypeBound::Any); + let rv = |idx| Type::new_row_var_use(idx, TypeBound::Any); let pf = PolyFuncType::new( [rowp.clone(), rowp.clone(), rowp.clone(), rowp.clone()], FunctionType::new( @@ -617,7 +617,7 @@ fn seq1ty(t: Type) -> TypeArg { #[test] fn inner_row_variables() -> Result<(), Box> { let e = extension_with_eval_parallel(); - let tv = Type::new_row_var(0, TypeBound::Any); + let tv = Type::new_row_var_use(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(tv.clone())); let ft_usz = Type::new_function(FunctionType::new_endo(vec![tv.clone(), USIZE_T])); let mut fb = FunctionBuilder::new( @@ -659,7 +659,7 @@ fn inner_row_variables() -> Result<(), Box> { #[case(true)] fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box> { let e = extension_with_eval_parallel(); - let tv = Type::new_row_var(0, TypeBound::Copyable); + let tv = Type::new_row_var_use(0, TypeBound::Copyable); let mut fb = FunctionBuilder::new( "bad_eval", PolyFuncType::new( diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 9ef5b4be4..cb69cd063 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -329,7 +329,7 @@ impl Type { /// /// [OpDef]: crate::extension::OpDef /// [FuncDefn]: crate::ops::FuncDefn - pub const fn new_row_var(idx: usize, bound: TypeBound) -> Self { + pub const fn new_row_var_use(idx: usize, bound: TypeBound) -> Self { Self(TypeEnum::RowVariable(idx, bound), bound) } diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index cf55dcbf7..fbeb1986c 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -349,7 +349,7 @@ pub(crate) mod test { [decl.clone()], FunctionType::new( vec![USIZE_T], - vec![Type::new_row_var(0, TypeBound::Copyable)], + vec![Type::new_row_var_use(0, TypeBound::Copyable)], ), &PRELUDE_REGISTRY, ) @@ -373,14 +373,10 @@ pub(crate) mod test { #[test] fn row_variables() { + let rty = Type::new_row_var_use(0, TypeBound::Any); let pf = PolyFuncType::new_validated( - [TypeParam::List { - param: Box::new(TP_ANY), - }], - FunctionType::new( - vec![USIZE_T, Type::new_row_var(0, TypeBound::Any)], - vec![Type::new_tuple(vec![Type::new_row_var(0, TypeBound::Any)])], - ), + [TypeParam::new_list(TP_ANY)], + FunctionType::new(vec![USIZE_T, rty.clone()], vec![Type::new_tuple(rty)]), &PRELUDE_REGISTRY, ) .unwrap(); @@ -412,7 +408,7 @@ pub(crate) mod test { #[test] fn row_variables_inner() { - let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_row_var( + let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_row_var_use( 0, TypeBound::Copyable, )])); diff --git a/hugr/src/types/serialize.rs b/hugr/src/types/serialize.rs index 228b18358..e4585d2f5 100644 --- a/hugr/src/types/serialize.rs +++ b/hugr/src/types/serialize.rs @@ -53,7 +53,7 @@ impl From for Type { SerSimpleType::Opaque(o) => Type::new_extension(o), SerSimpleType::Alias(a) => Type::new_alias(a), SerSimpleType::V { i, b } => Type::new_var_use(i, b), - SerSimpleType::R { i, b } => Type::new_row_var(i, b), + SerSimpleType::R { i, b } => Type::new_row_var_use(i, b), } } } diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index dcde06ef2..94dff956a 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -229,13 +229,11 @@ impl TypeArg { TypeParam::List { param: bx } if matches!(*bx, TypeParam::Type { .. }) => { // There are two reasonable schemes for representing row variables: // 1. TypeArg::Variable(idx, TypeParam::List(TypeParam::Type(typebound))) - // 2. TypeArg::Type(Type::new_row_var(idx, typebound)) + // 2. TypeArg::Type(Type::new_row_var_use(idx, typebound)) // Here we prefer the latter for canonicalization, although we cannot really // prevent both if users construct the TypeArg variants directly (doing so will break Eq) let TypeParam::Type { b } = *bx else { panic!() }; - TypeArg::Type { - ty: Type::new_row_var(idx, b), - } + Type::new_row_var_use(idx, b).into() } TypeParam::Extensions => TypeArg::Extensions { es: ExtensionSet::type_var(idx), From 412ec08aefe4048e97032d42ba7313de3fca4d56 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 11:26:28 +0100 Subject: [PATCH 30/42] squash! Add TypeParam::new_list --- hugr/src/hugr/validate/test.rs | 6 +++--- hugr/src/types/type_param.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 2537eb91a..880d464df 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -548,7 +548,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { } fn extension_with_eval_parallel() -> Extension { - let rowp = TypeParam::new_list(TypeBound::Any.into()); + let rowp = TypeParam::new_list(TypeBound::Any); let mut e = Extension::new(EXT_ID); let inputs = Type::new_row_var_use(0, TypeBound::Any); @@ -623,7 +623,7 @@ fn inner_row_variables() -> Result<(), Box> { let mut fb = FunctionBuilder::new( "id", PolyFuncType::new( - [TypeParam::new_list(TypeBound::Any.into())], + [TypeParam::new_list(TypeBound::Any)], FunctionType::new(inner_ft.clone(), ft_usz), ), )?; @@ -663,7 +663,7 @@ fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box Self { + /// Make a new `TypeParam::List` (an arbitrary-length homogenous list) + pub fn new_list(elem: impl Into) -> Self { Self::List { - param: Box::new(elem), + param: Box::new(elem.into()), } } From 34ed4c9bf10a760f29d66725b9854db4773c29cd Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 11:31:28 +0100 Subject: [PATCH 31/42] Fix apply_row_var...TODO cover this --- hugr/src/types.rs | 8 +++++--- hugr/src/types/type_param.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index cb69cd063..e763bad12 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -443,16 +443,18 @@ impl<'a> Substitution<'a> { .0 .get(idx) .expect("Undeclared type variable - call validate() ?"); + debug_assert_eq!(check_type_arg(arg, &TypeParam::new_list(bound)), Ok(())); match arg { + // Row variables are represented as 'TypeArg::Type's (see TypeArg::new_row_var_use) TypeArg::Sequence { elems } => elems .iter() .map(|ta| match ta { TypeArg::Type { ty } => ty.clone(), - _ => panic!("Not a list of types - did validate() ?"), + _ => panic!("Not a list of types - call validate() ?"), }) .collect(), - TypeArg::Type { ty } => { - debug_assert_eq!(check_type_arg(arg, &TypeParam::Type { b: bound }), Ok(())); + TypeArg::Type { ty } if matches!(ty.0, TypeEnum::RowVariable(_, _)) => { + // Standalone "Type" can be used iff its actually a Row Variable not an actual (single) Type vec![ty.clone()] } _ => panic!("Not a type or list of types - did validate() ?"), diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 32d657a34..a2814aa40 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -255,7 +255,7 @@ impl TypeArg { var_decls: &[TypeParam], ) -> Result<(), SignatureError> { match self { - // Row variables are represented as Types, even inside TypeArgs + // Row variables are represented as 'TypeArg::Type's (see TypeArg::new_row_var_use) TypeArg::Type { ty } => ty.validate_in_row(extension_registry, var_decls), TypeArg::BoundedNat { .. } => Ok(()), TypeArg::Opaque { arg: custarg } => { From 85d19695c524c48510543df8749f66d86be7517f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 12:01:50 +0100 Subject: [PATCH 32/42] check_type_arg_rv: improve comment --- hugr/src/types/type_param.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index a2814aa40..874e7c5a1 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -352,10 +352,10 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr fn check_type_arg_rv( arg: &TypeArg, param: &TypeParam, + // true to allow row-variables returning *multiple* values of the specified param + // (false => must be guaranteed to be a single value of kind `param`, so no rowvars) allow_rowvars: bool, ) -> Result<(), TypeArgError> { - // allow_row_vars only applies if we are checking against values allowed inside a list - // (where the row variable could stand for *several* elements) debug_assert!(!allow_rowvars || matches!(param, TypeParam::Type { .. })); fn rowvar_in_list(ty: &Type, list_elem: &TypeParam) -> bool { let TypeParam::Type { b } = list_elem else { From 3cf333d95dc5a35518510c77f393a94870cfb7e2 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 12:44:22 +0100 Subject: [PATCH 33/42] Remove rowvar_in_list using TypeParam::contains --- hugr/src/types/type_param.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 874e7c5a1..92daa58ab 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -357,12 +357,6 @@ fn check_type_arg_rv( allow_rowvars: bool, ) -> Result<(), TypeArgError> { debug_assert!(!allow_rowvars || matches!(param, TypeParam::Type { .. })); - fn rowvar_in_list(ty: &Type, list_elem: &TypeParam) -> bool { - let TypeParam::Type { b } = list_elem else { - return false; - }; - matches!(ty.0, TypeEnum::RowVariable(_, _)) && b.contains(ty.least_upper_bound()) - } match (arg, param) { ( TypeArg::Variable { @@ -384,7 +378,12 @@ fn check_type_arg_rv( } // Also allow a single "Type" to be used for a List *only* if the Type is a row variable // (i.e., it's not really a Type, it's multiple Types) - (TypeArg::Type { ty }, TypeParam::List { param }) if rowvar_in_list(ty, param) => Ok(()), + ( + TypeArg::Type { + ty: Type(TypeEnum::RowVariable(_, b), _), + }, + TypeParam::List { param }, + ) if param.contains(&(*b).into()) => Ok(()), (TypeArg::Sequence { elems: items }, TypeParam::Tuple { params: types }) => { if items.len() != types.len() { From 29291357f11ba6f81961a0cb3e1035d7493b1c3e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 12:50:38 +0100 Subject: [PATCH 34/42] Add Type::row_var_bound --- hugr/src/types.rs | 8 ++++++++ hugr/src/types/type_param.rs | 16 ++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hugr/src/types.rs b/hugr/src/types.rs index e763bad12..78a407e1c 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -351,6 +351,14 @@ impl Type { TypeBound::Copyable.contains(self.least_upper_bound()) } + /// If this Type is a row variable, return its bound, otherwise None + pub fn row_var_bound(&self) -> Option { + match self.0 { + TypeEnum::RowVariable(_, b) => Some(b), + _ => None, + } + } + /// Checks that this [Type] represents a single Type, not a row variable, /// that all variables used within are in the provided list of bound variables, /// and that for each [CustomType], the corresponding diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 92daa58ab..9cfba9852 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -12,7 +12,6 @@ use crate::extension::ExtensionRegistry; use crate::extension::ExtensionSet; use crate::extension::SignatureError; -use super::TypeEnum; use super::{check_typevar_decl, CustomType, Substitution, Type, TypeBound}; /// The upper non-inclusive bound of a [`TypeParam::BoundedNat`] @@ -366,7 +365,7 @@ fn check_type_arg_rv( ) if param.contains(cached_decl) => Ok(()), (TypeArg::Type { ty }, TypeParam::Type { b: bound }) if bound.contains(ty.least_upper_bound()) - && (allow_rowvars || !matches!(ty.0, TypeEnum::RowVariable(_, _))) => + && (allow_rowvars || ty.row_var_bound().is_none()) => { Ok(()) } @@ -378,12 +377,13 @@ fn check_type_arg_rv( } // Also allow a single "Type" to be used for a List *only* if the Type is a row variable // (i.e., it's not really a Type, it's multiple Types) - ( - TypeArg::Type { - ty: Type(TypeEnum::RowVariable(_, b), _), - }, - TypeParam::List { param }, - ) if param.contains(&(*b).into()) => Ok(()), + (TypeArg::Type { ty }, TypeParam::List { param }) + if ty + .row_var_bound() + .is_some_and(|b| param.contains(&b.into())) => + { + Ok(()) + } (TypeArg::Sequence { elems: items }, TypeParam::Tuple { params: types }) => { if items.len() != types.len() { From 0afdaf9621cc3b532dd0fe98efec010612bd2968 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 13:09:18 +0100 Subject: [PATCH 35/42] Remove check_type_arg_rv --- hugr/src/types/type_param.rs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 9cfba9852..efe376384 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -345,17 +345,6 @@ impl CustomTypeArg { /// Checks a [TypeArg] is as expected for a [TypeParam] pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgError> { - check_type_arg_rv(arg, param, false) -} - -fn check_type_arg_rv( - arg: &TypeArg, - param: &TypeParam, - // true to allow row-variables returning *multiple* values of the specified param - // (false => must be guaranteed to be a single value of kind `param`, so no rowvars) - allow_rowvars: bool, -) -> Result<(), TypeArgError> { - debug_assert!(!allow_rowvars || matches!(param, TypeParam::Type { .. })); match (arg, param) { ( TypeArg::Variable { @@ -364,16 +353,20 @@ fn check_type_arg_rv( _, ) if param.contains(cached_decl) => Ok(()), (TypeArg::Type { ty }, TypeParam::Type { b: bound }) - if bound.contains(ty.least_upper_bound()) - && (allow_rowvars || ty.row_var_bound().is_none()) => + if bound.contains(ty.least_upper_bound()) && ty.row_var_bound().is_none() => { Ok(()) } (TypeArg::Sequence { elems }, TypeParam::List { param }) => { - let allow_rvs = matches!(&**param, TypeParam::Type { .. }); - elems - .iter() - .try_for_each(|arg| check_type_arg_rv(arg, param, allow_rvs)) + elems.iter().try_for_each(|arg| { + // Also allow elements that are RowVars if fitting into a List of Types + if let (TypeArg::Type { ty }, TypeParam::Type { b }) = (arg, &**param) { + if ty.row_var_bound().is_some_and(|arg_b| b.contains(arg_b)) { + return Ok(()); + } + } + check_type_arg(arg, param) + }) } // Also allow a single "Type" to be used for a List *only* if the Type is a row variable // (i.e., it's not really a Type, it's multiple Types) From 5a8bf8836df3f777a2a1c169bec258b45653c508 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 14:03:07 +0100 Subject: [PATCH 36/42] Use Type .into() -> TypeArg more --- hugr/src/types/type_param.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index efe376384..c5dd3fdee 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -222,9 +222,7 @@ impl TypeArg { /// `bound` must match that with which the variable was declared. pub fn new_var_use(idx: usize, decl: TypeParam) -> Self { match decl { - TypeParam::Type { b } => TypeArg::Type { - ty: Type::new_var_use(idx, b), - }, + TypeParam::Type { b } => Type::new_var_use(idx, b).into(), TypeParam::List { param: bx } if matches!(*bx, TypeParam::Type { .. }) => { // There are two reasonable schemes for representing row variables: // 1. TypeArg::Variable(idx, TypeParam::List(TypeParam::Type(typebound))) @@ -281,11 +279,7 @@ impl TypeArg { // TODO: this case can't happen until we start substituting across Hugrs // (rather than just their types) - e.g. instantiating the *body* (not just type) // of a FuncDefn, polymorphic over a row variable, with multiple types - let tys = ty - .substitute(t) - .into_iter() - .map(|ty| TypeArg::Type { ty }) - .collect::>(); + let tys = ty.substitute(t).into_iter().map_into().collect::>(); match as TryInto<[TypeArg; 1]>>::try_into(tys) { Ok([ty]) => ty, Err(elems) => TypeArg::Sequence { elems }, From 2e535295b0682a37d2c46a709485b7dded13fe3b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 14:03:48 +0100 Subject: [PATCH 37/42] Extend comment that TypeArg::Variable's are not row-vars --- hugr/src/types/type_param.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index c5dd3fdee..91ab5ec40 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -170,8 +170,9 @@ pub enum TypeArg { #[allow(missing_docs)] es: ExtensionSet, }, - /// Variable (used in type schemes only), that is not a [TypeArg::Type] - /// or [TypeArg::Extensions] - see [TypeArg::new_var_use] + /// Variable (used in type schemes or inside polymorphic functions), + /// but not a [TypeArg::Type] (not even a row variable i.e. [TypeParam::List] of type) + /// nor [TypeArg::Extensions] - see [TypeArg::new_var_use] Variable { #[allow(missing_docs)] #[serde(flatten)] From ed09ae621b4916c6d790299465aaa9e9aefc0d4b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 16:51:34 +0100 Subject: [PATCH 38/42] type_row.rs: comment ...Variable]*s* --- hugr/src/types/type_row.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index 5facd9677..bcec336b5 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -85,7 +85,7 @@ impl TypeRow { } /// Applies a substitution to the row. Note this may change the length - /// if-and-only-if the row contains any [RowVariable] + /// if-and-only-if the row contains any [RowVariable]s. /// /// [RowVariable]: [crate::types::TypeEnum::RowVariable] pub(super) fn substitute(&self, tr: &Substitution) -> TypeRow { From 8c93c9d4326015d5719ff1fca19f87b1d2dcf912 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 17:31:07 +0100 Subject: [PATCH 39/42] Add check_type_arg tests as rstest cases --- hugr/src/types/type_param.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 91ab5ec40..ba7f6e2d1 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -439,3 +439,29 @@ pub enum TypeArgError { #[error("Invalid value of type argument")] InvalidValue(TypeArg), } + +#[cfg(test)] +mod test { + use rstest::rstest; + use crate::types::Type; + use super::{TypeArg, TypeParam}; + use crate::{extension::prelude::USIZE_T, types::TypeBound}; + + #[rstest] + #[case(USIZE_T, TypeBound::Eq, true)] + #[case(USIZE_T, TypeParam::new_list(TypeBound::Eq), false)] + #[case(vec![USIZE_T.into()], TypeBound::Any, false)] + #[case(vec![USIZE_T.into()], TypeParam::new_list(TypeBound::Eq), true)] + #[case(Type::new_row_var_use(0, TypeBound::Eq), TypeParam::new_list(TypeBound::Eq), true)] + #[case(vec![], TypeParam::new_list(TypeBound::Eq), true)] + #[case(vec![Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Eq), true)] + #[case(vec![Type::new_row_var_use(1, TypeBound::Any).into(), USIZE_T.into(), Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Any), true)] + #[case(vec![Type::new_row_var_use(1, TypeBound::Any).into(), USIZE_T.into(), Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Eq), false)] + #[case(5, TypeParam::max_nat(), true)] + #[case(vec![5.into()], TypeParam::max_nat(), false)] + #[case(vec![5.into()], TypeParam::new_list(TypeParam::max_nat()), true)] + fn check_type_arg(#[case] arg: impl Into, #[case] param: impl Into, #[case] ok: bool) { + let r = super::check_type_arg(&arg.into(), ¶m.into()); + assert!(if ok {r.is_ok()} else {r.is_err()}) + } +} \ No newline at end of file From 8811e1a5ebba7472bda21b3ca9d7590d6ea041b2 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 18:05:53 +0100 Subject: [PATCH 40/42] More tests! (giving up on rstest) --- hugr/src/types/type_param.rs | 100 +++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index ba7f6e2d1..843b1b5a1 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -442,26 +442,82 @@ pub enum TypeArgError { #[cfg(test)] mod test { - use rstest::rstest; - use crate::types::Type; - use super::{TypeArg, TypeParam}; - use crate::{extension::prelude::USIZE_T, types::TypeBound}; - - #[rstest] - #[case(USIZE_T, TypeBound::Eq, true)] - #[case(USIZE_T, TypeParam::new_list(TypeBound::Eq), false)] - #[case(vec![USIZE_T.into()], TypeBound::Any, false)] - #[case(vec![USIZE_T.into()], TypeParam::new_list(TypeBound::Eq), true)] - #[case(Type::new_row_var_use(0, TypeBound::Eq), TypeParam::new_list(TypeBound::Eq), true)] - #[case(vec![], TypeParam::new_list(TypeBound::Eq), true)] - #[case(vec![Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Eq), true)] - #[case(vec![Type::new_row_var_use(1, TypeBound::Any).into(), USIZE_T.into(), Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Any), true)] - #[case(vec![Type::new_row_var_use(1, TypeBound::Any).into(), USIZE_T.into(), Type::new_row_var_use(0, TypeBound::Eq).into()], TypeParam::new_list(TypeBound::Eq), false)] - #[case(5, TypeParam::max_nat(), true)] - #[case(vec![5.into()], TypeParam::max_nat(), false)] - #[case(vec![5.into()], TypeParam::new_list(TypeParam::max_nat()), true)] - fn check_type_arg(#[case] arg: impl Into, #[case] param: impl Into, #[case] ok: bool) { - let r = super::check_type_arg(&arg.into(), ¶m.into()); - assert!(if ok {r.is_ok()} else {r.is_err()}) + use itertools::Itertools; + + use super::{check_type_arg, TypeArg, TypeParam}; + use crate::extension::prelude::USIZE_T; + use crate::types::{type_param::TypeArgError, Type, TypeBound}; + + #[test] + fn type_arg_fits_param() { + fn check(arg: impl Into, parm: &TypeParam) -> Result<(), TypeArgError> { + check_type_arg(&arg.into(), parm) + } + fn check_seq>( + args: &[T], + parm: &TypeParam, + ) -> Result<(), TypeArgError> { + let arg = args.iter().cloned().map_into().collect_vec().into(); + check_type_arg(&arg, parm) + } + // Simple cases: a TypeArg::Type is a TypeParam::Type but singleton sequences are lists + check(USIZE_T, &TypeBound::Eq.into()).unwrap(); + let p = TypeParam::new_list(TypeBound::Eq); + check(USIZE_T, &p).unwrap_err(); + check_seq(&[USIZE_T], &TypeBound::Any.into()).unwrap_err(); + + // Into a list of type, we can fit a single row var + check(Type::new_row_var_use(0, TypeBound::Eq), &p).unwrap(); + // or a list of (types or row vars) + check(vec![], &p).unwrap(); + check_seq(&[Type::new_row_var_use(0, TypeBound::Eq)], &p).unwrap(); + check_seq( + &[ + Type::new_row_var_use(1, TypeBound::Any), + USIZE_T, + Type::new_row_var_use(0, TypeBound::Eq), + ], + &TypeParam::new_list(TypeBound::Any), + ) + .unwrap(); + // Next one fails because a list of Eq is required + check_seq( + &[ + Type::new_row_var_use(1, TypeBound::Any), + USIZE_T, + Type::new_row_var_use(0, TypeBound::Eq), + ], + &p, + ) + .unwrap_err(); + // seq of seq of types is not allowed + check(vec![USIZE_T.into(), vec![USIZE_T.into()].into()], &p).unwrap_err(); + + // Similar for nats (but no equivalent of fancy row vars) + check(5, &TypeParam::max_nat()).unwrap(); + check_seq(&[5], &TypeParam::max_nat()).unwrap_err(); + let list_of_nat = TypeParam::new_list(TypeParam::max_nat()); + check(5, &list_of_nat).unwrap_err(); + check_seq(&[5], &list_of_nat).unwrap(); + check(TypeArg::new_var_use(0, list_of_nat.clone()), &list_of_nat).unwrap(); + // But no equivalent of row vars - can't append a nat onto a list-in-a-var: + check( + vec![5.into(), TypeArg::new_var_use(0, list_of_nat.clone())], + &list_of_nat, + ) + .unwrap_err(); + + // TypeParam::Tuples require a TypeArg::Seq of the same number of elems + let usize_and_ty = TypeParam::Tuple { + params: vec![TypeParam::max_nat(), TypeBound::Eq.into()], + }; + check(vec![5.into(), USIZE_T.into()], &usize_and_ty).unwrap(); + check(vec![USIZE_T.into(), 5.into()], &usize_and_ty).unwrap_err(); // Wrong way around + let two_types = TypeParam::Tuple { + params: vec![TypeBound::Any.into(), TypeBound::Any.into()], + }; + check(TypeArg::new_var_use(0, two_types.clone()), &two_types).unwrap(); + // not a Row Var which could have any number of elems + check(TypeArg::new_var_use(0, p), &two_types).unwrap_err(); } -} \ No newline at end of file +} From d7287140dd5f5fb1309f610cfd42df818faa1e9e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 14 May 2024 18:20:26 +0100 Subject: [PATCH 41/42] Add a couple of PolyFuncType-serialization tests --- hugr/src/hugr/serialize/test.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/hugr/src/hugr/serialize/test.rs b/hugr/src/hugr/serialize/test.rs index c9ff8eae0..4f891bd86 100644 --- a/hugr/src/hugr/serialize/test.rs +++ b/hugr/src/hugr/serialize/test.rs @@ -392,13 +392,32 @@ fn polyfunctype1() -> PolyFuncType { PolyFuncType::new([TypeParam::max_nat(), TypeParam::Extensions], function_type) } +fn polyfunctype2() -> PolyFuncType { + let tv0 = Type::new_row_var_use(0, TypeBound::Any); + let tv1 = Type::new_row_var_use(1, TypeBound::Eq); + let params = [TypeBound::Any, TypeBound::Eq].map(TypeParam::new_list); + let inputs = vec![ + Type::new_function(FunctionType::new(tv0.clone(), tv1.clone())), + tv0, + ]; + let res = PolyFuncType::new(params, FunctionType::new(inputs, tv1)); + // Just check we've got the arguments the right way round + // (not that it really matters for the serialization schema we have) + res.validate_varargs(&EMPTY_REG).unwrap(); + res +} + #[rstest] #[case(FunctionType::new_endo(type_row![]).into())] #[case(polyfunctype1())] #[case(PolyFuncType::new([TypeParam::Opaque { ty: int_custom_type(TypeArg::BoundedNat { n: 1 }) }], FunctionType::new_endo(type_row![Type::new_var_use(0, TypeBound::Copyable)])))] #[case(PolyFuncType::new([TypeBound::Eq.into()], FunctionType::new_endo(type_row![Type::new_var_use(0, TypeBound::Eq)])))] -#[case(PolyFuncType::new([TypeParam::List { param: Box::new(TypeBound::Any.into()) }], FunctionType::new_endo(type_row![])))] +#[case(PolyFuncType::new([TypeParam::new_list(TypeBound::Any)], FunctionType::new_endo(type_row![])))] #[case(PolyFuncType::new([TypeParam::Tuple { params: [TypeBound::Any.into(), TypeParam::bounded_nat(2.try_into().unwrap())].into() }], FunctionType::new_endo(type_row![])))] +#[case(PolyFuncType::new( + [TypeParam::new_list(TypeBound::Any)], + FunctionType::new_endo(Type::new_tuple(Type::new_row_var_use(0, TypeBound::Any)))))] +#[case(polyfunctype2())] fn roundtrip_polyfunctype(#[case] poly_func_type: PolyFuncType) { check_testing_roundtrip(poly_func_type) } From 5ec995f2f9ec4a88f1d0985c54ec3a098c726771 Mon Sep 17 00:00:00 2001 From: Douglas Wilson Date: Thu, 16 May 2024 07:48:24 +0100 Subject: [PATCH 42/42] try adding FunctionTypeVarArgs --- hugr/src/builder/build_traits.rs | 4 +- hugr/src/builder/dataflow.rs | 2 +- hugr/src/builder/module.rs | 2 +- hugr/src/extension/op_def.rs | 2 +- hugr/src/hugr/validate/test.rs | 11 ++-- hugr/src/ops/module.rs | 3 +- hugr/src/types.rs | 13 +++-- hugr/src/types/poly_func.rs | 49 +++++++++++++++--- hugr/src/types/serialize.rs | 4 +- hugr/src/types/signature.rs | 88 ++++++++++++++++++++++++++++---- 10 files changed, 143 insertions(+), 35 deletions(-) diff --git a/hugr/src/builder/build_traits.rs b/hugr/src/builder/build_traits.rs index e3ef10de8..1ddd5a1d6 100644 --- a/hugr/src/builder/build_traits.rs +++ b/hugr/src/builder/build_traits.rs @@ -19,7 +19,7 @@ use crate::{ types::EdgeKind, }; -use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE_REGISTRY}; +use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError, PRELUDE_REGISTRY}; use crate::types::{FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; use itertools::Itertools; @@ -87,7 +87,7 @@ pub trait Container { name: impl Into, signature: PolyFuncType, ) -> Result, BuildError> { - let body = signature.body().clone(); + let body = signature.body_norowvars()?.clone(); let f_node = self.add_child_node(NodeType::new_pure(ops::FuncDefn { name: name.into(), signature, diff --git a/hugr/src/builder/dataflow.rs b/hugr/src/builder/dataflow.rs index 473e79877..a8ebad2cf 100644 --- a/hugr/src/builder/dataflow.rs +++ b/hugr/src/builder/dataflow.rs @@ -147,7 +147,7 @@ impl FunctionBuilder { /// /// Error in adding DFG child nodes. pub fn new(name: impl Into, signature: PolyFuncType) -> Result { - let body = signature.body().clone(); + let body = signature.body_norowvars()?.clone(); let op = ops::FuncDefn { signature, name: name.into(), diff --git a/hugr/src/builder/module.rs b/hugr/src/builder/module.rs index f6b4b7f20..4fada8957 100644 --- a/hugr/src/builder/module.rs +++ b/hugr/src/builder/module.rs @@ -84,7 +84,7 @@ impl + AsRef> ModuleBuilder { op_desc: "crate::ops::OpType::FuncDecl", })? .clone(); - let body = signature.body().clone(); + let body = signature.body_norowvars()?.clone(); self.hugr_mut() .replace_op( f_node, diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 2c7a45e8e..b81db42c0 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -11,7 +11,7 @@ use super::{ use crate::ops::{OpName, OpNameRef}; use crate::types::type_param::{check_type_args, TypeArg, TypeParam}; -use crate::types::{FunctionType, PolyFuncType}; +use crate::types::{FunctionType, FunctionTypeVarArgs, PolyFuncType, Substitution}; use crate::Hugr; /// Trait necessary for binary computations of OpDef signature diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 880d464df..120a23bf4 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -657,7 +657,7 @@ fn inner_row_variables() -> Result<(), Box> { #[rstest] #[case(false)] #[case(true)] -fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box> { +fn no_outer_row_variables(#[case] connect: bool) { let e = extension_with_eval_parallel(); let tv = Type::new_row_var_use(0, TypeBound::Copyable); let mut fb = FunctionBuilder::new( @@ -669,15 +669,15 @@ fn no_outer_row_variables(#[case] connect: bool) -> Result<(), Box Result<(), Box FunctionType { - self.signature.body().clone() + // ok by validation + self.signature.body_norowvars().unwrap().clone() } } diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 78a407e1c..22b645a2d 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -14,7 +14,7 @@ use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::PolyFuncType; -pub use signature::FunctionType; +pub use signature::{FunctionType, FunctionTypeVarArgs}; use smol_str::SmolStr; pub use type_param::TypeArg; pub use type_row::TypeRow; @@ -205,7 +205,7 @@ pub enum TypeEnum { Alias(AliasDecl), #[allow(missing_docs)] #[display(fmt = "Function({})", "_0")] - Function(Box), + Function(Box), // Index into TypeParams, and cache of TypeBound (checked in validation) #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] @@ -272,7 +272,7 @@ impl Type { const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; /// Initialize a new function type. - pub fn new_function(fun_ty: impl Into) -> Self { + pub fn new_function(fun_ty: impl Into) -> Self { Self::new(TypeEnum::Function(Box::new(fun_ty.into()))) } @@ -359,6 +359,11 @@ impl Type { } } + /// TODO docs + pub fn is_row_var(&self) -> bool { + matches!(self.0, TypeEnum::RowVariable(_, _)) + } + /// Checks that this [Type] represents a single Type, not a row variable, /// that all variables used within are in the provided list of bound variables, /// and that for each [CustomType], the corresponding @@ -434,7 +439,7 @@ impl Type { /// Details a replacement of type variables with a finite list of known values. /// (Variables out of the range of the list will result in a panic) -pub(crate) struct Substitution<'a>(&'a [TypeArg], &'a ExtensionRegistry); +pub(crate) struct Substitution<'a>(pub(crate) &'a [TypeArg], pub(crate) &'a ExtensionRegistry); impl<'a> Substitution<'a> { pub(crate) fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg { diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index fbeb1986c..e4eccab44 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -4,7 +4,7 @@ use crate::extension::{ExtensionRegistry, SignatureError}; use itertools::Itertools; use super::type_param::{check_type_args, TypeArg, TypeParam}; -use super::{FunctionType, Substitution}; +use super::{FunctionType, FunctionTypeVarArgs, Substitution}; /// A polymorphic type scheme, i.e. of a [FuncDecl], [FuncDefn] or [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -20,17 +20,18 @@ use super::{FunctionType, Substitution}; "params.iter().map(ToString::to_string).join(\" \")", "body" )] + pub struct PolyFuncType { /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. This /// defines the indices used by variables inside the body. params: Vec, /// Template for the function. May contain variables up to length of [Self::params] - body: FunctionType, + body: FunctionTypeVarArgs, } -impl From for PolyFuncType { - fn from(body: FunctionType) -> Self { +impl From for PolyFuncType { + fn from(body: FunctionTypeVarArgs) -> Self { Self { params: vec![], body, @@ -38,7 +39,13 @@ impl From for PolyFuncType { } } -impl TryFrom for FunctionType { +impl From for PolyFuncType { + fn from(body: FunctionType) -> Self { + Into::::into(body).into() + } +} + +impl TryFrom for FunctionTypeVarArgs { /// If the PolyFuncType is not a monomorphic FunctionType, fail with the binders type Error = Vec; @@ -51,6 +58,19 @@ impl TryFrom for FunctionType { } } +impl TryFrom for FunctionType { + /// If the PolyFuncType is not a monomorphic FunctionType, fail with the binders + type Error = PolyFuncType; + + fn try_from(value: PolyFuncType) -> Result { + if let Ok(ftva) = TryInto::::try_into(value.clone()){ + ftva.try_into().map_err(|_| value) + } else { + Err(value) + } + } +} + impl PolyFuncType { /// The type parameters, aka binders, over which this type is polymorphic pub fn params(&self) -> &[TypeParam] { @@ -58,16 +78,21 @@ impl PolyFuncType { } /// The body of the type, a function type. - pub fn body(&self) -> &FunctionType { + pub fn body(&self) -> &FunctionTypeVarArgs { &self.body } + /// The body of the type, a function type. + pub fn body_norowvars(&self) -> Result<&FunctionType,SignatureError> { + self.body.try_as_ref() + } + /// Create a new PolyFuncType given the kinds of the variables it declares /// and the underlying [FunctionType]. - pub fn new(params: impl Into>, body: FunctionType) -> Self { + pub fn new(params: impl Into>, body: impl Into) -> Self { Self { params: params.into(), - body, + body: body.into(), } } @@ -92,6 +117,14 @@ impl PolyFuncType { args: &[TypeArg], ext_reg: &ExtensionRegistry, ) -> Result { + self.instantiate_varargs(args,ext_reg).and_then(TryInto::try_into) + } + + pub(crate) fn instantiate_varargs( + &self, + args: &[TypeArg], + ext_reg: &ExtensionRegistry, + ) -> Result { // Check that args are applicable, and that we have a value for each binder, // i.e. each possible free variable within the body. check_type_args(args, &self.params)?; diff --git a/hugr/src/types/serialize.rs b/hugr/src/types/serialize.rs index e4585d2f5..093b7ac16 100644 --- a/hugr/src/types/serialize.rs +++ b/hugr/src/types/serialize.rs @@ -1,4 +1,4 @@ -use super::{FunctionType, SumType, Type, TypeArg, TypeBound, TypeEnum}; +use super::{FunctionType, FunctionTypeVarArgs, SumType, Type, TypeArg, TypeBound, TypeEnum}; use super::custom::CustomType; @@ -10,7 +10,7 @@ use crate::ops::AliasDecl; pub(super) enum SerSimpleType { Q, I, - G(Box), + G(Box), Sum(SumType), Array { inner: Box, len: u64 }, Opaque(CustomType), diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index 89b49461a..b4710cac2 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -5,7 +5,7 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; -use super::{Substitution, Type, TypeRow}; +use super::{Substitution, Type, TypeEnum, TypeRow}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -25,11 +25,27 @@ pub struct FunctionType { pub extension_reqs: ExtensionSet, } -impl FunctionType { - /// Builder method, add extension_reqs to an FunctionType - pub fn with_extension_delta(mut self, rs: impl Into) -> Self { - self.extension_reqs = self.extension_reqs.union(rs.into()); - self +#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct FunctionTypeVarArgs(FunctionType); + +impl FunctionTypeVarArgs { + pub fn any_rowvars(&self) -> bool { + self.rowvar().is_some() + } + + pub fn rowvar(&self) -> Option { + self.0.input.iter().chain(self.0.output.iter()).filter_map(|x| match x.as_type_enum() { + TypeEnum::RowVariable(i,_) => Some(*i), + _ => None + }).next() + } + + pub fn try_as_ref(&self) -> Result<&FunctionType,SignatureError> { + if let Some(idx) = self.rowvar() { + Err(SignatureError::RowTypeVarOutsideRow { idx }) + } else { + Ok(&self.0) + } } pub(super) fn validate_varargs( @@ -37,13 +53,67 @@ impl FunctionType { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - self.input.validate_var_len(extension_registry, var_decls)?; - self.output + self.0.input.validate_var_len(extension_registry, var_decls)?; + self.0.output .validate_var_len(extension_registry, var_decls)?; - self.extension_reqs.validate(var_decls) + self.0.extension_reqs.validate(var_decls) + } + + pub(crate) fn substitute(&self, tr: &Substitution) -> Self { + Self(FunctionType { + input: self.0.input.substitute(tr), + output: self.0.output.substitute(tr), + extension_reqs: self.0.extension_reqs.substitute(tr), + }) + } +} + +impl PartialEq for FunctionTypeVarArgs { + fn eq(&self, other: &FunctionType) -> bool { + &self.0 == other + } +} + +impl PartialEq for FunctionType { + fn eq(&self, other: &FunctionTypeVarArgs) -> bool { + self == &other.0 } +} + +impl Display for FunctionTypeVarArgs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl TryFrom for FunctionType { + type Error = SignatureError; + fn try_from(value: FunctionTypeVarArgs) -> Result { + if let Some(idx) = value.rowvar() { + Err(SignatureError::RowTypeVarOutsideRow { idx }) + } else { + Ok(value.0) + } + } +} + +impl From for FunctionTypeVarArgs { + fn from(value: FunctionType) -> Self { + Self(value) + } +} + + +impl FunctionType { + /// Builder method, add extension_reqs to an FunctionType + pub fn with_extension_delta(mut self, rs: impl Into) -> Self { + self.extension_reqs = self.extension_reqs.union(rs.into()); + self + } + pub(crate) fn substitute(&self, tr: &Substitution) -> Self { + // TODO assert no row vars in result FunctionType { input: self.input.substitute(tr), output: self.output.substitute(tr),