diff --git a/Cargo.lock b/Cargo.lock index 7d41cabbff..4a1134addf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1239,6 +1239,7 @@ dependencies = [ name = "hugr-core" version = "0.20.1" dependencies = [ + "base64", "cgmath", "cool_asserts", "delegate", @@ -1254,6 +1255,7 @@ dependencies = [ "itertools 0.14.0", "jsonschema", "lazy_static", + "ordered-float", "paste", "petgraph 0.8.1", "portgraph", @@ -1988,6 +1990,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" dependencies = [ "num-traits", + "rand", + "serde", ] [[package]] @@ -2388,6 +2392,7 @@ dependencies = [ "libc", "rand_chacha", "rand_core", + "serde", ] [[package]] @@ -2407,6 +2412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.16", + "serde", ] [[package]] diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml index c1e6a02b56..c8699d5aa7 100644 --- a/hugr-core/Cargo.toml +++ b/hugr-core/Cargo.toml @@ -65,6 +65,8 @@ typetag = { workspace = true } semver = { workspace = true, features = ["serde"] } zstd = { workspace = true, optional = true } relrc = { workspace = true, features = ["petgraph", "serde"] } +ordered-float = { workspace = true, features = ["serde"] } +base64.workspace = true [dev-dependencies] rstest = { workspace = true } diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs index 1ff2287caa..8bae0f1cdc 100644 --- a/hugr-core/src/export.rs +++ b/hugr-core/src/export.rs @@ -863,7 +863,10 @@ impl<'a> Context<'a> { TypeArg::Type { ty } => self.export_type(ty), TypeArg::BoundedNat { n } => self.make_term(model::Literal::Nat(*n).into()), TypeArg::String { arg } => self.make_term(model::Literal::Str(arg.into()).into()), + TypeArg::Float { value } => self.make_term(model::Literal::Float(*value).into()), + TypeArg::Bytes { value } => self.make_term(model::Literal::Bytes(value.clone()).into()), TypeArg::List { elems } => { + // For now we assume that the sequence is meant to be a list. let parts = self.bump.alloc_slice_fill_iter( elems .iter() @@ -973,6 +976,8 @@ impl<'a> Context<'a> { // This ignores the bound on the natural for now. TypeParam::BoundedNat { .. } => self.make_term_apply(model::CORE_NAT_TYPE, &[]), TypeParam::String => self.make_term_apply(model::CORE_STR_TYPE, &[]), + TypeParam::Bytes => self.make_term_apply(model::CORE_BYTES_TYPE, &[]), + TypeParam::Float => self.make_term_apply(model::CORE_FLOAT_TYPE, &[]), TypeParam::List { param } => { let item_type = self.export_type_param(param, None); self.make_term_apply(model::CORE_LIST_TYPE, &[item_type]) diff --git a/hugr-core/src/import.rs b/hugr-core/src/import.rs index 4a7d6080d0..3336439f21 100644 --- a/hugr-core/src/import.rs +++ b/hugr-core/src/import.rs @@ -1015,6 +1015,14 @@ impl<'a> Context<'a> { return Ok(TypeParam::String); } + if let Some([]) = self.match_symbol(term_id, model::CORE_BYTES_TYPE)? { + return Ok(TypeParam::Bytes); + } + + if let Some([]) = self.match_symbol(term_id, model::CORE_FLOAT_TYPE)? { + return Ok(TypeParam::Float); + } + if let Some([]) = self.match_symbol(term_id, model::CORE_NAT_TYPE)? { return Ok(TypeParam::max_nat()); } @@ -1194,11 +1202,11 @@ impl<'a> Context<'a> { Ok(TypeArg::BoundedNat { n: *value }) } - table::Term::Literal(model::Literal::Bytes(_)) => { - Err(error_unsupported!("`(bytes ..)` as `TypeArg`")) - } - table::Term::Literal(model::Literal::Float(_)) => { - Err(error_unsupported!("float literal as `TypeArg`")) + table::Term::Literal(model::Literal::Bytes(value)) => Ok(TypeArg::Bytes { + value: value.clone(), + }), + table::Term::Literal(model::Literal::Float(value)) => { + Ok(TypeArg::Float { value: *value }) } table::Term::Func { .. } => Err(error_unsupported!("function constant as `TypeArg`")), diff --git a/hugr-core/src/types/type_param.rs b/hugr-core/src/types/type_param.rs index 59af07e027..75e60e2de5 100644 --- a/hugr-core/src/types/type_param.rs +++ b/hugr-core/src/types/type_param.rs @@ -5,9 +5,11 @@ //! [`TypeDef`]: crate::extension::TypeDef use itertools::Itertools; +use ordered_float::OrderedFloat; #[cfg(test)] use proptest_derive::Arbitrary; use std::num::NonZeroU64; +use std::sync::Arc; use thiserror::Error; use super::row_var::MaybeRV; @@ -79,6 +81,10 @@ pub enum TypeParam { }, /// Argument is a [`TypeArg::String`]. String, + /// Argument is a [`TypeArg::Bytes`]. + Bytes, + /// Argument is a [`TypeArg::Float`]. + Float, /// Argument is a [`TypeArg::List`]. A list of indeterminate size containing /// parameters all of the (same) specified element type. #[display("List[{param}]")] @@ -171,6 +177,19 @@ pub enum TypeArg { /// The string value for the parameter. arg: String, }, + /// Instance of [`TypeParam::Bytes`]. Byte string. + #[display("bytes")] + Bytes { + /// The value of the bytes parameter. + #[serde(with = "base64")] + value: Arc<[u8]>, + }, + /// Instance of [`TypeParam::Float`]. 64-bit floating point number. + #[display("{}", value.into_inner())] + Float { + /// The value of the float parameter. + value: OrderedFloat, + }, /// Instance of [`TypeParam::List`] defined by a sequence of elements of the same type. #[display("[{}]", { use itertools::Itertools as _; @@ -301,12 +320,15 @@ impl TypeArg { pub(crate) fn validate(&self, var_decls: &[TypeParam]) -> Result<(), SignatureError> { match self { TypeArg::Type { ty } => ty.validate(var_decls), - TypeArg::BoundedNat { .. } | TypeArg::String { .. } => Ok(()), TypeArg::List { elems } => { // TODO: Full validation would check that the type of the elements agrees elems.iter().try_for_each(|a| a.validate(var_decls)) } TypeArg::Tuple { elems } => elems.iter().try_for_each(|a| a.validate(var_decls)), + TypeArg::BoundedNat { .. } + | TypeArg::String { .. } + | TypeArg::Float { .. } + | TypeArg::Bytes { .. } => Ok(()), TypeArg::Variable { v: TypeArgVariable { idx, cached_decl }, } => { @@ -326,7 +348,10 @@ impl TypeArg { // RowVariables are represented as TypeArg::Variable ty.substitute1(t).into() } - TypeArg::BoundedNat { .. } | TypeArg::String { .. } => self.clone(), // We do not allow variables as bounds on BoundedNat's + TypeArg::BoundedNat { .. } + | TypeArg::String { .. } + | TypeArg::Bytes { .. } + | TypeArg::Float { .. } => self.clone(), // We do not allow variables as bounds on BoundedNat's TypeArg::List { elems } => { let mut are_types = elems.iter().map(|ta| match ta { TypeArg::Type { .. } => true, @@ -369,9 +394,11 @@ impl Transformable for TypeArg { TypeArg::Type { ty } => ty.transform(tr), TypeArg::List { elems } => elems.transform(tr), TypeArg::Tuple { elems } => elems.transform(tr), - TypeArg::BoundedNat { .. } | TypeArg::String { .. } | TypeArg::Variable { .. } => { - Ok(false) - } + TypeArg::BoundedNat { .. } + | TypeArg::String { .. } + | TypeArg::Variable { .. } + | TypeArg::Float { .. } + | TypeArg::Bytes { .. } => Ok(false), } } } @@ -442,6 +469,8 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr } (TypeArg::String { .. }, TypeParam::String) => Ok(()), + (TypeArg::Bytes { .. }, TypeParam::Bytes) => Ok(()), + (TypeArg::Float { .. }, TypeParam::Float) => Ok(()), _ => Err(TypeArgError::TypeMismatch { arg: arg.clone(), param: param.clone(), @@ -489,6 +518,29 @@ pub enum TypeArgError { InvalidValue(TypeArg), } +/// Helper for to serialize and deserialize the byte string in `TypeArg::Bytes` via base64. +mod base64 { + use std::sync::Arc; + + use base64::Engine as _; + use base64::prelude::BASE64_STANDARD; + use serde::{Deserialize, Serialize}; + use serde::{Deserializer, Serializer}; + + pub fn serialize(v: &Arc<[u8]>, s: S) -> Result { + let base64 = BASE64_STANDARD.encode(v); + base64.serialize(s) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { + let base64 = String::deserialize(d)?; + BASE64_STANDARD + .decode(base64.as_bytes()) + .map(|v| v.into()) + .map_err(serde::de::Error::custom) + } +} + #[cfg(test)] mod test { use itertools::Itertools; @@ -660,6 +712,16 @@ mod test { ); } + #[test] + fn bytes_json_roundtrip() { + let bytes_arg = TypeArg::Bytes { + value: vec![0, 1, 2, 3, 255, 254, 253, 252].into(), + }; + let serialized = serde_json::to_string(&bytes_arg).unwrap(); + let deserialized: TypeArg = serde_json::from_str(&serialized).unwrap(); + assert_eq!(deserialized, bytes_arg); + } + mod proptest { use proptest::prelude::*; @@ -685,6 +747,9 @@ mod test { use prop::collection::vec; use prop::strategy::Union; let mut strat = Union::new([ + Just(Self::String).boxed(), + Just(Self::Bytes).boxed(), + Just(Self::Float).boxed(), Just(Self::String).boxed(), any::().prop_map(|b| Self::Type { b }).boxed(), any::() @@ -715,6 +780,16 @@ mod test { let mut strat = Union::new([ any::().prop_map(|n| Self::BoundedNat { n }).boxed(), any::().prop_map(|arg| Self::String { arg }).boxed(), + any::>() + .prop_map(|bytes| Self::Bytes { + value: bytes.into(), + }) + .boxed(), + any::() + .prop_map(|value| Self::Float { + value: value.into(), + }) + .boxed(), any_with::(depth) .prop_map(|ty| Self::Type { ty }) .boxed(), diff --git a/hugr-core/tests/snapshots/model__roundtrip_params.snap b/hugr-core/tests/snapshots/model__roundtrip_params.snap index 77d6d9cc77..9d7334d84a 100644 --- a/hugr-core/tests/snapshots/model__roundtrip_params.snap +++ b/hugr-core/tests/snapshots/model__roundtrip_params.snap @@ -6,13 +6,44 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-para (mod) -(import core.fn) +(import core.bytes) + +(import core.nat) + +(import core.call) (import core.type) +(import core.fn) + +(import core.str) + +(import core.float) + (define-func example.swap (param ?0 core.type) (param ?1 core.type) (core.fn [?0 ?1] [?1 ?0]) (dfg [%0 %1] [%1 %0] (signature (core.fn [?0 ?1] [?1 ?0])))) + +(declare-func + example.literals + (param ?0 core.str) + (param ?1 core.nat) + (param ?2 core.bytes) + (param ?3 core.float) + (core.fn [] [])) + +(define-func example.call_literals (core.fn [] []) + (dfg + (signature (core.fn [] [])) + ((core.call + [] + [] + (example.literals + "string" + 42 + (bytes "SGVsbG8gd29ybGQg8J+Yig==") + 6.023e23)) + (signature (core.fn [] []))))) diff --git a/hugr-model/tests/fixtures/model-params.edn b/hugr-model/tests/fixtures/model-params.edn index ba81fa6007..48fb200886 100644 --- a/hugr-model/tests/fixtures/model-params.edn +++ b/hugr-model/tests/fixtures/model-params.edn @@ -9,3 +9,18 @@ (core.fn [?a ?b] [?b ?a]) (dfg [%a %b] [%b %a] (signature (core.fn [?a ?b] [?b ?a])))) + +(declare-func example.literals + (param ?a core.str) + (param ?b core.nat) + (param ?c core.bytes) + (param ?d core.float) + (core.fn [] [])) + +(define-func example.call_literals + (core.fn [] []) + (dfg [] [] + (signature (core.fn [] [])) + ((core.call + (example.literals "string" 42 (bytes "SGVsbG8gd29ybGQg8J+Yig==") 6.023e23)) + (signature (core.fn [] []))))) diff --git a/hugr-py/src/hugr/_serialization/tys.py b/hugr-py/src/hugr/_serialization/tys.py index 05c648187a..5a500ede2e 100644 --- a/hugr-py/src/hugr/_serialization/tys.py +++ b/hugr-py/src/hugr/_serialization/tys.py @@ -1,5 +1,6 @@ from __future__ import annotations +import base64 import inspect import sys from abc import ABC, abstractmethod @@ -94,6 +95,20 @@ def deserialize(self) -> tys.StringParam: return tys.StringParam() +class BytesParam(BaseTypeParam): + tp: Literal["Bytes"] = "Bytes" + + def deserialize(self) -> tys.BytesParam: + return tys.BytesParam() + + +class FloatParam(BaseTypeParam): + tp: Literal["Float"] = "Float" + + def deserialize(self) -> tys.FloatParam: + return tys.FloatParam() + + class ListParam(BaseTypeParam): tp: Literal["List"] = "List" param: TypeParam @@ -114,7 +129,13 @@ class TypeParam(RootModel): """A type parameter.""" root: Annotated[ - TypeTypeParam | BoundedNatParam | StringParam | ListParam | TupleParam, + TypeTypeParam + | BoundedNatParam + | StringParam + | FloatParam + | BytesParam + | ListParam + | TupleParam, WrapValidator(_json_custom_error_validator), ] = Field(discriminator="tp") @@ -158,6 +179,26 @@ def deserialize(self) -> tys.StringArg: return tys.StringArg(value=self.arg) +class FloatArg(BaseTypeArg): + tya: Literal["Float"] = "Float" + value: float + + def deserialize(self) -> tys.FloatArg: + return tys.FloatArg(value=self.value) + + +class BytesArg(BaseTypeArg): + tya: Literal["Bytes"] = "Bytes" + value: str = Field( + description="Base64-encoded byte string", + json_schema_extra={"contentEncoding": "base64"}, + ) + + def deserialize(self) -> tys.BytesArg: + value = base64.b64decode(self.value) + return tys.BytesArg(value=value) + + class ListArg(BaseTypeArg): tya: Literal["List"] = "List" elems: list[TypeArg] @@ -187,7 +228,14 @@ class TypeArg(RootModel): """A type argument.""" root: Annotated[ - TypeTypeArg | BoundedNatArg | StringArg | ListArg | TupleArg | VariableArg, + TypeTypeArg + | BoundedNatArg + | StringArg + | BytesArg + | FloatArg + | ListArg + | TupleArg + | VariableArg, WrapValidator(_json_custom_error_validator), ] = Field(discriminator="tya") diff --git a/hugr-py/src/hugr/tys.py b/hugr-py/src/hugr/tys.py index 743d61530d..addf7301d7 100644 --- a/hugr-py/src/hugr/tys.py +++ b/hugr-py/src/hugr/tys.py @@ -2,6 +2,7 @@ from __future__ import annotations +import base64 from dataclasses import dataclass, field from typing import TYPE_CHECKING, Protocol, cast, runtime_checkable @@ -154,6 +155,34 @@ def to_model(self) -> model.Term: return model.Apply("core.str") +@dataclass(frozen=True) +class FloatParam(TypeParam): + """Float type parameter.""" + + def _to_serial(self) -> stys.FloatParam: + return stys.FloatParam() + + def __str__(self) -> str: + return "Float" + + def to_model(self) -> model.Term: + return model.Apply("core.float") + + +@dataclass(frozen=True) +class BytesParam(TypeParam): + """Bytes type parameter.""" + + def _to_serial(self) -> stys.BytesParam: + return stys.BytesParam() + + def __str__(self) -> str: + return "Bytes" + + def to_model(self) -> model.Term: + return model.Apply("core.bytes") + + @dataclass(frozen=True) class ListParam(TypeParam): """Type parameter which requires a list of type arguments.""" @@ -244,6 +273,39 @@ def to_model(self) -> model.Term: return model.Literal(self.value) +@dataclass(frozen=True) +class FloatArg(TypeArg): + """A floating point type argument.""" + + value: float + + def _to_serial(self) -> stys.FloatArg: + return stys.FloatArg(value=self.value) + + def __str__(self) -> str: + return f"{self.value}" + + def to_model(self) -> model.Term: + return model.Literal(self.value) + + +@dataclass(frozen=True) +class BytesArg(TypeArg): + """A bytes type argument.""" + + value: bytes + + def _to_serial(self) -> stys.BytesArg: + value = base64.b64encode(self.value).decode() + return stys.BytesArg(value=value) + + def __str__(self) -> str: + return "bytes" + + def to_model(self) -> model.Term: + return model.Literal(self.value) + + @dataclass(frozen=True) class ListArg(TypeArg): """Sequence of type arguments for a :class:`ListParam`.""" diff --git a/hugr-py/tests/test_hugr_build.py b/hugr-py/tests/test_hugr_build.py index 9452f3672a..1eba465e23 100644 --- a/hugr-py/tests/test_hugr_build.py +++ b/hugr-py/tests/test_hugr_build.py @@ -259,6 +259,39 @@ def test_poly_function(direct_call: bool) -> None: validate(mod.hugr) +def test_literals() -> None: + mod = Module() + + func = mod.declare_function( + "literals", + tys.PolyFuncType( + [ + tys.StringParam(), + tys.BoundedNatParam(), + tys.BytesParam(), + tys.FloatParam(), + ], + tys.FunctionType.endo([tys.Qubit]), + ), + ) + + caller = mod.define_function("caller", [tys.Qubit], [tys.Qubit]) + call = caller.call( + func, + caller.inputs()[0], + instantiation=tys.FunctionType.endo([tys.Qubit]), + type_args=[ + tys.StringArg("string"), + tys.BoundedNatArg(42), + tys.BytesArg(b"HUGR"), + tys.FloatArg(0.9), + ], + ) + caller.set_outputs(call) + + validate(mod.hugr) + + @pytest.mark.parametrize("direct_call", [True, False]) def test_mono_function(direct_call: bool) -> None: mod = Module() diff --git a/hugr-py/tests/test_tys.py b/hugr-py/tests/test_tys.py index 329dd12277..e6132dfbcd 100644 --- a/hugr-py/tests/test_tys.py +++ b/hugr-py/tests/test_tys.py @@ -14,8 +14,12 @@ Bool, BoundedNatArg, BoundedNatParam, + BytesArg, + BytesParam, Either, ExtType, + FloatArg, + FloatParam, FunctionType, ListArg, ListParam, @@ -90,6 +94,8 @@ def test_tys_sum_str(ty: Type, string: str, repr_str: str): (BoundedNatParam(3), "Nat(3)"), (BoundedNatParam(None), "Nat"), (StringParam(), "String"), + (FloatParam(), "Float"), + (BytesParam(), "Bytes"), ( TupleParam([TypeTypeParam(TypeBound.Any), BoundedNatParam(3)]), "(Any, Nat(3))", @@ -106,6 +112,8 @@ def test_params_str(param: TypeParam, string: str): [ (TypeTypeArg(Bool), "Type(Bool)"), (BoundedNatArg(3), "3"), + (FloatArg(3.141), "3.141"), + (BytesArg(b"0"), "bytes"), (StringArg("hello"), '"hello"'), ( ListArg([TypeTypeArg(Qubit), BoundedNatArg(3)]), diff --git a/specification/hugr.md b/specification/hugr.md index b12b128c63..ce267f748b 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -824,6 +824,9 @@ such declarations may include (bind) any number of type parameters, of kinds as TypeParam ::= Type(Any|Copyable) | BoundedUSize(u64|) -- note optional bound | Extensions + | String + | Bytes + | Float | List(TypeParam) -- homogeneous, any sized | Tuple([TypeParam]) -- heterogenous, fixed size | Opaque(Name, [TypeArg]) -- e.g. Opaque("Array", [5, Opaque("usize", [])]) @@ -841,6 +844,9 @@ TypeArgs appropriate for the function's TypeParams: ```haskell TypeArg ::= Type(Type) -- could be a variable of kind Type, or contain variable(s) | BoundedUSize(u64) + | String(String) + | Bytes([u8]) + | Float(f64) | Extensions(Extensions) -- may contain TypeArg's of kind Extensions | List([TypeArg]) | Tuple([TypeArg]) diff --git a/specification/schema/hugr_schema_live.json b/specification/schema/hugr_schema_live.json index 33f5d5c9de..54c0d8d54a 100644 --- a/specification/schema/hugr_schema_live.json +++ b/specification/schema/hugr_schema_live.json @@ -130,6 +130,41 @@ "title": "BoundedNatParam", "type": "object" }, + "BytesArg": { + "additionalProperties": true, + "properties": { + "tya": { + "const": "Bytes", + "default": "Bytes", + "title": "Tya", + "type": "string" + }, + "value": { + "contentEncoding": "base64", + "description": "Base64-encoded byte string", + "title": "Value", + "type": "string" + } + }, + "required": [ + "value" + ], + "title": "BytesArg", + "type": "object" + }, + "BytesParam": { + "additionalProperties": true, + "properties": { + "tp": { + "const": "Bytes", + "default": "Bytes", + "title": "Tp", + "type": "string" + } + }, + "title": "BytesParam", + "type": "object" + }, "CFG": { "additionalProperties": true, "description": "A dataflow node which is defined by a child CFG.", @@ -566,6 +601,39 @@ "title": "FixedHugr", "type": "object" }, + "FloatArg": { + "additionalProperties": true, + "properties": { + "tya": { + "const": "Float", + "default": "Float", + "title": "Tya", + "type": "string" + }, + "value": { + "title": "Value", + "type": "number" + } + }, + "required": [ + "value" + ], + "title": "FloatArg", + "type": "object" + }, + "FloatParam": { + "additionalProperties": true, + "properties": { + "tp": { + "const": "Float", + "default": "Float", + "title": "Tp", + "type": "string" + } + }, + "title": "FloatParam", + "type": "object" + }, "FromParamsBound": { "properties": { "b": { @@ -1604,6 +1672,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatArg", + "Bytes": "#/$defs/BytesArg", + "Float": "#/$defs/FloatArg", "List": "#/$defs/ListArg", "String": "#/$defs/StringArg", "Tuple": "#/$defs/TupleArg", @@ -1622,6 +1692,12 @@ { "$ref": "#/$defs/StringArg" }, + { + "$ref": "#/$defs/BytesArg" + }, + { + "$ref": "#/$defs/FloatArg" + }, { "$ref": "#/$defs/ListArg" }, @@ -1703,6 +1779,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatParam", + "Bytes": "#/$defs/BytesParam", + "Float": "#/$defs/FloatParam", "List": "#/$defs/ListParam", "String": "#/$defs/StringParam", "Tuple": "#/$defs/TupleParam", @@ -1720,6 +1798,12 @@ { "$ref": "#/$defs/StringParam" }, + { + "$ref": "#/$defs/FloatParam" + }, + { + "$ref": "#/$defs/BytesParam" + }, { "$ref": "#/$defs/ListParam" }, diff --git a/specification/schema/hugr_schema_strict_live.json b/specification/schema/hugr_schema_strict_live.json index 139dda53e1..84d938ead8 100644 --- a/specification/schema/hugr_schema_strict_live.json +++ b/specification/schema/hugr_schema_strict_live.json @@ -130,6 +130,41 @@ "title": "BoundedNatParam", "type": "object" }, + "BytesArg": { + "additionalProperties": false, + "properties": { + "tya": { + "const": "Bytes", + "default": "Bytes", + "title": "Tya", + "type": "string" + }, + "value": { + "contentEncoding": "base64", + "description": "Base64-encoded byte string", + "title": "Value", + "type": "string" + } + }, + "required": [ + "value" + ], + "title": "BytesArg", + "type": "object" + }, + "BytesParam": { + "additionalProperties": false, + "properties": { + "tp": { + "const": "Bytes", + "default": "Bytes", + "title": "Tp", + "type": "string" + } + }, + "title": "BytesParam", + "type": "object" + }, "CFG": { "additionalProperties": false, "description": "A dataflow node which is defined by a child CFG.", @@ -566,6 +601,39 @@ "title": "FixedHugr", "type": "object" }, + "FloatArg": { + "additionalProperties": false, + "properties": { + "tya": { + "const": "Float", + "default": "Float", + "title": "Tya", + "type": "string" + }, + "value": { + "title": "Value", + "type": "number" + } + }, + "required": [ + "value" + ], + "title": "FloatArg", + "type": "object" + }, + "FloatParam": { + "additionalProperties": false, + "properties": { + "tp": { + "const": "Float", + "default": "Float", + "title": "Tp", + "type": "string" + } + }, + "title": "FloatParam", + "type": "object" + }, "FromParamsBound": { "properties": { "b": { @@ -1604,6 +1672,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatArg", + "Bytes": "#/$defs/BytesArg", + "Float": "#/$defs/FloatArg", "List": "#/$defs/ListArg", "String": "#/$defs/StringArg", "Tuple": "#/$defs/TupleArg", @@ -1622,6 +1692,12 @@ { "$ref": "#/$defs/StringArg" }, + { + "$ref": "#/$defs/BytesArg" + }, + { + "$ref": "#/$defs/FloatArg" + }, { "$ref": "#/$defs/ListArg" }, @@ -1703,6 +1779,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatParam", + "Bytes": "#/$defs/BytesParam", + "Float": "#/$defs/FloatParam", "List": "#/$defs/ListParam", "String": "#/$defs/StringParam", "Tuple": "#/$defs/TupleParam", @@ -1720,6 +1798,12 @@ { "$ref": "#/$defs/StringParam" }, + { + "$ref": "#/$defs/FloatParam" + }, + { + "$ref": "#/$defs/BytesParam" + }, { "$ref": "#/$defs/ListParam" }, diff --git a/specification/schema/testing_hugr_schema_live.json b/specification/schema/testing_hugr_schema_live.json index c22cc0f299..f389e2574a 100644 --- a/specification/schema/testing_hugr_schema_live.json +++ b/specification/schema/testing_hugr_schema_live.json @@ -130,6 +130,41 @@ "title": "BoundedNatParam", "type": "object" }, + "BytesArg": { + "additionalProperties": true, + "properties": { + "tya": { + "const": "Bytes", + "default": "Bytes", + "title": "Tya", + "type": "string" + }, + "value": { + "contentEncoding": "base64", + "description": "Base64-encoded byte string", + "title": "Value", + "type": "string" + } + }, + "required": [ + "value" + ], + "title": "BytesArg", + "type": "object" + }, + "BytesParam": { + "additionalProperties": true, + "properties": { + "tp": { + "const": "Bytes", + "default": "Bytes", + "title": "Tp", + "type": "string" + } + }, + "title": "BytesParam", + "type": "object" + }, "CFG": { "additionalProperties": true, "description": "A dataflow node which is defined by a child CFG.", @@ -566,6 +601,39 @@ "title": "FixedHugr", "type": "object" }, + "FloatArg": { + "additionalProperties": true, + "properties": { + "tya": { + "const": "Float", + "default": "Float", + "title": "Tya", + "type": "string" + }, + "value": { + "title": "Value", + "type": "number" + } + }, + "required": [ + "value" + ], + "title": "FloatArg", + "type": "object" + }, + "FloatParam": { + "additionalProperties": true, + "properties": { + "tp": { + "const": "Float", + "default": "Float", + "title": "Tp", + "type": "string" + } + }, + "title": "FloatParam", + "type": "object" + }, "FromParamsBound": { "properties": { "b": { @@ -1682,6 +1750,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatArg", + "Bytes": "#/$defs/BytesArg", + "Float": "#/$defs/FloatArg", "List": "#/$defs/ListArg", "String": "#/$defs/StringArg", "Tuple": "#/$defs/TupleArg", @@ -1700,6 +1770,12 @@ { "$ref": "#/$defs/StringArg" }, + { + "$ref": "#/$defs/BytesArg" + }, + { + "$ref": "#/$defs/FloatArg" + }, { "$ref": "#/$defs/ListArg" }, @@ -1781,6 +1857,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatParam", + "Bytes": "#/$defs/BytesParam", + "Float": "#/$defs/FloatParam", "List": "#/$defs/ListParam", "String": "#/$defs/StringParam", "Tuple": "#/$defs/TupleParam", @@ -1798,6 +1876,12 @@ { "$ref": "#/$defs/StringParam" }, + { + "$ref": "#/$defs/FloatParam" + }, + { + "$ref": "#/$defs/BytesParam" + }, { "$ref": "#/$defs/ListParam" }, diff --git a/specification/schema/testing_hugr_schema_strict_live.json b/specification/schema/testing_hugr_schema_strict_live.json index f7415494b9..cca1222aa8 100644 --- a/specification/schema/testing_hugr_schema_strict_live.json +++ b/specification/schema/testing_hugr_schema_strict_live.json @@ -130,6 +130,41 @@ "title": "BoundedNatParam", "type": "object" }, + "BytesArg": { + "additionalProperties": false, + "properties": { + "tya": { + "const": "Bytes", + "default": "Bytes", + "title": "Tya", + "type": "string" + }, + "value": { + "contentEncoding": "base64", + "description": "Base64-encoded byte string", + "title": "Value", + "type": "string" + } + }, + "required": [ + "value" + ], + "title": "BytesArg", + "type": "object" + }, + "BytesParam": { + "additionalProperties": false, + "properties": { + "tp": { + "const": "Bytes", + "default": "Bytes", + "title": "Tp", + "type": "string" + } + }, + "title": "BytesParam", + "type": "object" + }, "CFG": { "additionalProperties": false, "description": "A dataflow node which is defined by a child CFG.", @@ -566,6 +601,39 @@ "title": "FixedHugr", "type": "object" }, + "FloatArg": { + "additionalProperties": false, + "properties": { + "tya": { + "const": "Float", + "default": "Float", + "title": "Tya", + "type": "string" + }, + "value": { + "title": "Value", + "type": "number" + } + }, + "required": [ + "value" + ], + "title": "FloatArg", + "type": "object" + }, + "FloatParam": { + "additionalProperties": false, + "properties": { + "tp": { + "const": "Float", + "default": "Float", + "title": "Tp", + "type": "string" + } + }, + "title": "FloatParam", + "type": "object" + }, "FromParamsBound": { "properties": { "b": { @@ -1682,6 +1750,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatArg", + "Bytes": "#/$defs/BytesArg", + "Float": "#/$defs/FloatArg", "List": "#/$defs/ListArg", "String": "#/$defs/StringArg", "Tuple": "#/$defs/TupleArg", @@ -1700,6 +1770,12 @@ { "$ref": "#/$defs/StringArg" }, + { + "$ref": "#/$defs/BytesArg" + }, + { + "$ref": "#/$defs/FloatArg" + }, { "$ref": "#/$defs/ListArg" }, @@ -1781,6 +1857,8 @@ "discriminator": { "mapping": { "BoundedNat": "#/$defs/BoundedNatParam", + "Bytes": "#/$defs/BytesParam", + "Float": "#/$defs/FloatParam", "List": "#/$defs/ListParam", "String": "#/$defs/StringParam", "Tuple": "#/$defs/TupleParam", @@ -1798,6 +1876,12 @@ { "$ref": "#/$defs/StringParam" }, + { + "$ref": "#/$defs/FloatParam" + }, + { + "$ref": "#/$defs/BytesParam" + }, { "$ref": "#/$defs/ListParam" }, diff --git a/uv.lock b/uv.lock index 35a6661182..54d2b3781b 100644 --- a/uv.lock +++ b/uv.lock @@ -281,7 +281,7 @@ wheels = [ [[package]] name = "hugr" -version = "0.12.1" +version = "0.12.2" source = { editable = "hugr-py" } dependencies = [ { name = "graphviz" },