Skip to content

Commit 27e8410

Browse files
authored
feat: Value::some, ::none, and SumType::new_option helpers (#1828)
Some simple helpers I needed while testing, and seem reasonable to have.
1 parent 7bf85b9 commit 27e8410

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

hugr-core/src/ops/constant.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::hash::{Hash, Hasher};
99
use super::{NamedOp, OpName, OpTrait, StaticTag};
1010
use super::{OpTag, OpType};
1111
use crate::extension::ExtensionSet;
12-
use crate::types::{CustomType, EdgeKind, Signature, SumType, SumTypeError, Type};
12+
use crate::types::{CustomType, EdgeKind, Signature, SumType, SumTypeError, Type, TypeRow};
1313
use crate::{Hugr, HugrView};
1414

1515
use delegate::delegate;
@@ -450,6 +450,21 @@ impl Value {
450450
Self::unit_sum(0, 2).expect("0 < 2")
451451
}
452452

453+
/// Returns an optional with some values. This is a Sum with two variants, the
454+
/// first being empty and the second being the values.
455+
pub fn some<V: Into<Value>>(values: impl IntoIterator<Item = V>) -> Self {
456+
let values: Vec<Value> = values.into_iter().map(Into::into).collect_vec();
457+
let value_types: Vec<Type> = values.iter().map(|v| v.get_type()).collect_vec();
458+
let sum_type = SumType::new_option(value_types);
459+
Self::sum(1, values, sum_type).unwrap()
460+
}
461+
462+
/// Returns an optional with no value. This is a Sum with two variants, the
463+
/// first being empty and the second being the value.
464+
pub fn none(value_types: impl Into<TypeRow>) -> Self {
465+
Self::sum(0, [], SumType::new_option(value_types)).unwrap()
466+
}
467+
453468
/// Returns a constant `bool` value.
454469
///
455470
/// see [`Value::true_val`] and [`Value::false_val`].
@@ -753,16 +768,29 @@ pub(crate) mod test {
753768
}
754769

755770
#[fixture]
756-
fn const_array_2_bool() -> Value {
771+
fn const_array_bool() -> Value {
757772
ArrayValue::new(bool_t(), [Value::true_val(), Value::false_val()]).into()
758773
}
759774

775+
#[fixture]
776+
fn const_array_options() -> Value {
777+
let some_true = Value::some([Value::true_val()]);
778+
let none = Value::none(vec![bool_t()]);
779+
let elem_ty = SumType::new_option(vec![bool_t()]);
780+
ArrayValue::new(elem_ty.into(), [some_true, none]).into()
781+
}
782+
760783
#[rstest]
761784
#[case(Value::unit(), Type::UNIT, "const:seq:{}")]
762785
#[case(const_usize(), usize_t(), "const:custom:ConstUsize(")]
763786
#[case(serialized_float(17.4), float64_type(), "const:custom:json:Object")]
764787
#[case(const_tuple(), Type::new_tuple(vec![usize_t(), bool_t()]), "const:seq:{")]
765-
#[case(const_array_2_bool(), array_type(2, bool_t()), "const:custom:array")]
788+
#[case(const_array_bool(), array_type(2, bool_t()), "const:custom:array")]
789+
#[case(
790+
const_array_options(),
791+
array_type(2, SumType::new_option(vec![bool_t()]).into()),
792+
"const:custom:array"
793+
)]
766794
fn const_type(
767795
#[case] const_value: Value,
768796
#[case] expected_type: Type,
@@ -781,7 +809,8 @@ pub(crate) mod test {
781809
#[case(const_usize(), const_usize())]
782810
#[case(const_serialized_usize(), const_usize())]
783811
#[case(const_tuple_serialized(), const_tuple())]
784-
#[case(const_array_2_bool(), const_array_2_bool())]
812+
#[case(const_array_bool(), const_array_bool())]
813+
#[case(const_array_options(), const_array_options())]
785814
fn const_serde_roundtrip(#[case] const_value: Value, #[case] expected_value: Value) {
786815
let serialized = serde_json::to_string(&const_value).unwrap();
787816
let deserialized: Value = serde_json::from_str(&serialized).unwrap();

hugr-core/src/types.rs

+5
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ impl SumType {
226226
Self::new([types.into()])
227227
}
228228

229+
/// New option type (either an empty option, or a row of types)
230+
pub fn new_option(types: impl Into<TypeRow>) -> Self {
231+
Self::new([vec![].into(), types.into()])
232+
}
233+
229234
/// Report the tag'th variant, if it exists.
230235
pub fn get_variant(&self, tag: usize) -> Option<&TypeRowRV> {
231236
match self {

0 commit comments

Comments
 (0)