From 8caa572d01aac59715480827eaf568d8488ff542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Borgna?= <121866228+aborgna-q@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:06:26 +0100 Subject: [PATCH] refactor!: Make Either::Right the "success" case (#1489) Similarly for options, which now have type `[] + [elems...]`. Adds `const_ok`/`_fail` aliases to `const_right`/`_left`. Closes #1487. Modifies the old folding tests that hard-coded the sum tags. BREAKING CHANGE: Binary sums representing fallible values now use tag `1` for the successful variant --- hugr-core/src/extension/prelude.rs | 70 +++++++-- .../arithmetic/conversions/const_fold.rs | 12 +- .../arithmetic/int_ops/const_fold.rs | 58 +++---- hugr-core/src/std_extensions/collections.rs | 6 +- .../std_extensions/collections/list_fold.rs | 10 +- hugr-passes/src/const_fold/test.rs | 117 ++++++-------- .../_json_defs/arithmetic/conversions.json | 36 ++--- .../hugr/std/_json_defs/arithmetic/int.json | 144 +++++++++--------- .../src/hugr/std/_json_defs/collections.json | 8 +- hugr-py/src/hugr/tys.py | 10 +- hugr-py/src/hugr/val.py | 10 +- hugr-py/tests/test_tys.py | 6 +- hugr-py/tests/test_val.py | 10 +- .../arithmetic/conversions.json | 36 ++--- .../std_extensions/arithmetic/int.json | 144 +++++++++--------- specification/std_extensions/collections.json | 8 +- 16 files changed, 344 insertions(+), 341 deletions(-) diff --git a/hugr-core/src/extension/prelude.rs b/hugr-core/src/extension/prelude.rs index 594a8019e..40b4caddb 100644 --- a/hugr-core/src/extension/prelude.rs +++ b/hugr-core/src/extension/prelude.rs @@ -246,24 +246,24 @@ pub const ERROR_TYPE: Type = Type::new_extension(ERROR_CUSTOM_TYPE); /// The string name of the error type. pub const ERROR_TYPE_NAME: TypeName = TypeName::new_inline("error"); -/// Return a Sum type with the first variant as the given type and the second an Error. +/// Return a Sum type with the second variant as the given type and the first an Error. pub fn sum_with_error(ty: impl Into) -> SumType { - either_type(ty, ERROR_TYPE) + either_type(ERROR_TYPE, ty) } -/// An optional type, i.e. a Sum type with the first variant as the given type and the second as an empty tuple. +/// An optional type, i.e. a Sum type with the second variant as the given type and the first as an empty tuple. #[inline] pub fn option_type(ty: impl Into) -> SumType { - either_type(ty, TypeRow::new()) + either_type(TypeRow::new(), ty) } /// An "either" type, i.e. a Sum type with a "left" and a "right" variant. /// -/// When used as a fallible value, the "left" variant represents a successful computation, -/// and the "right" variant represents a failure. +/// When used as a fallible value, the "right" variant represents a successful computation, +/// and the "left" variant represents a failure. #[inline] -pub fn either_type(ty_ok: impl Into, ty_err: impl Into) -> SumType { - SumType::new([ty_ok.into(), ty_err.into()]) +pub fn either_type(ty_left: impl Into, ty_right: impl Into) -> SumType { + SumType::new([ty_left.into(), ty_right.into()]) } /// A constant optional value with a given value. @@ -279,19 +279,19 @@ pub fn const_some(value: Value) -> Value { /// /// See [option_type]. pub fn const_some_tuple(values: impl IntoIterator) -> Value { - const_left_tuple(values, TypeRow::new()) + const_right_tuple(TypeRow::new(), values) } /// A constant optional value with no value. /// /// See [option_type]. pub fn const_none(ty: impl Into) -> Value { - const_right_tuple(ty, []) + const_left_tuple([], ty) } /// A constant Either value with a left variant. /// -/// In fallible computations, this represents a successful result. +/// In fallible computations, this represents a failure. /// /// See [either_type]. pub fn const_left(value: Value, ty_right: impl Into) -> Value { @@ -300,7 +300,7 @@ pub fn const_left(value: Value, ty_right: impl Into) -> Value { /// A constant Either value with a row of left values. /// -/// In fallible computations, this represents a successful result. +/// In fallible computations, this represents a failure. /// /// See [either_type]. pub fn const_left_tuple( @@ -319,7 +319,7 @@ pub fn const_left_tuple( /// A constant Either value with a right variant. /// -/// In fallible computations, this represents a failure. +/// In fallible computations, this represents a successful result. /// /// See [either_type]. pub fn const_right(ty_left: impl Into, value: Value) -> Value { @@ -328,7 +328,7 @@ pub fn const_right(ty_left: impl Into, value: Value) -> Value { /// A constant Either value with a row of right values. /// -/// In fallible computations, this represents a failure. +/// In fallible computations, this represents a successful result. /// /// See [either_type]. pub fn const_right_tuple( @@ -345,6 +345,40 @@ pub fn const_right_tuple( Value::sum(1, values, typ).unwrap() } +/// A constant Either value with a success variant. +/// +/// Alias for [const_right]. +pub fn const_ok(value: Value, ty_fail: impl Into) -> Value { + const_right(ty_fail, value) +} + +/// A constant Either with a row of success values. +/// +/// Alias for [const_right_tuple]. +pub fn const_ok_tuple( + values: impl IntoIterator, + ty_fail: impl Into, +) -> Value { + const_right_tuple(ty_fail, values) +} + +/// A constant Either value with a failure variant. +/// +/// Alias for [const_left]. +pub fn const_fail(value: Value, ty_ok: impl Into) -> Value { + const_left(value, ty_ok) +} + +/// A constant Either with a row of failure values. +/// +/// Alias for [const_left_tuple]. +pub fn const_fail_tuple( + values: impl IntoIterator, + ty_ok: impl Into, +) -> Value { + const_left_tuple(values, ty_ok) +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] /// Structure for holding constant usize values. pub struct ConstUsize(u64); @@ -397,6 +431,14 @@ impl ConstError { message: message.to_string(), } } + + /// Returns an "either" value with a failure variant. + /// + /// args: + /// ty_ok: The type of the success variant. + pub fn as_either(self, ty_ok: impl Into) -> Value { + const_fail(self.into(), ty_ok) + } } #[typetag::serde] diff --git a/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs b/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs index 69dd724ae..1986c7336 100644 --- a/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs +++ b/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs @@ -3,7 +3,7 @@ use crate::ops::Value; use crate::std_extensions::arithmetic::int_types::INT_TYPES; use crate::{ extension::{ - prelude::{sum_with_error, ConstError}, + prelude::{const_ok, ConstError, ERROR_TYPE}, ConstFold, ConstFoldResult, OpDef, }, ops, @@ -40,21 +40,19 @@ fn fold_trunc( }; let log_width = get_log_width(arg).ok()?; let int_type = INT_TYPES[log_width as usize].to_owned(); - let sum_type = sum_with_error(int_type.clone()); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Can't truncate non-finite float".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(int_type.clone()) }; let out_const: ops::Value = if !f.is_finite() { err_value() } else { let cv = convert(f, log_width); if let Ok(cv) = cv { - Value::sum(0, [cv], sum_type).unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + const_ok(cv, ERROR_TYPE) } else { err_value() } diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs b/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs index 76b683bd7..644397abf 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops/const_fold.rs @@ -10,7 +10,7 @@ use crate::{ Value, }, std_extensions::arithmetic::int_types::{get_log_width, ConstInt, INT_TYPES}, - types::{SumType, Type, TypeArg}, + types::{Type, TypeArg}, IncomingPort, }; @@ -132,9 +132,9 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { }; let n0val: u64 = n0.value_u(); let out_const: Value = if n0val >> (1 << logwidth1) != 0 { - mk_out_const(1, Ok(INARROW_ERROR_VALUE.clone())) + mk_out_const(0, Ok(INARROW_ERROR_VALUE.clone())) } else { - mk_out_const(0, ConstInt::new_u(logwidth1, n0val).map(Into::into)) + mk_out_const(1, ConstInt::new_u(logwidth1, n0val).map(Into::into)) }; Some(vec![(0.into(), out_const)]) }, @@ -160,9 +160,9 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let n0val: i64 = n0.value_s(); let ub = 1i64 << ((1 << logwidth1) - 1); let out_const: Value = if n0val >= ub || n0val < -ub { - mk_out_const(1, Ok(INARROW_ERROR_VALUE.clone())) + mk_out_const(0, Ok(INARROW_ERROR_VALUE.clone())) } else { - mk_out_const(0, ConstInt::new_s(logwidth1, n0val).map(Into::into)) + mk_out_const(1, ConstInt::new_s(logwidth1, n0val).map(Into::into)) }; Some(vec![(0.into(), out_const)]) }, @@ -631,14 +631,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let q_type = INT_TYPES[logwidth0 as usize].to_owned(); let r_type = q_type.clone(); let qr_type: Type = Type::new_tuple(vec![q_type, r_type]); - let sum_type: SumType = sum_with_error(qr_type); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(qr_type) }; let nval = n.value_u(); let mval = m.value_u(); @@ -694,14 +692,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { let q_type = INT_TYPES[logwidth0 as usize].to_owned(); let r_type = INT_TYPES[logwidth0 as usize].to_owned(); let qr_type: Type = Type::new_tuple(vec![q_type, r_type]); - let sum_type: SumType = sum_with_error(qr_type); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(qr_type) }; let nval = n.value_s(); let mval = m.value_u(); @@ -754,14 +750,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); - let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(int_out_type.clone()) }; let nval = n.value_u(); let mval = m.value_u(); @@ -808,14 +802,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); - let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(int_out_type.clone()) }; let nval = n.value_u(); let mval = m.value_u(); @@ -862,14 +854,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); - let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(int_out_type.clone()) }; let nval = n.value_s(); let mval = m.value_u(); @@ -918,14 +908,12 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { None } else { let int_out_type = INT_TYPES[logwidth0 as usize].to_owned(); - let sum_type = sum_with_error(int_out_type.clone()); let err_value = || { - let err_val = ConstError { + ConstError { signal: 0, message: "Division by zero".to_string(), - }; - Value::sum(1, [err_val.into()], sum_type.clone()) - .unwrap_or_else(|e| panic!("Invalid computed sum, {}", e)) + } + .as_either(int_out_type.clone()) }; let nval = n.value_s(); let mval = m.value_u(); diff --git a/hugr-core/src/std_extensions/collections.rs b/hugr-core/src/std_extensions/collections.rs index 870cd5f88..5900df4ef 100644 --- a/hugr-core/src/std_extensions/collections.rs +++ b/hugr-core/src/std_extensions/collections.rs @@ -359,7 +359,7 @@ mod test { use rstest::rstest; use crate::extension::prelude::{ - const_left_tuple, const_none, const_right_tuple, const_some_tuple, + const_fail_tuple, const_none, const_ok_tuple, const_some_tuple, }; use crate::ops::OpTrait; use crate::PortIndex; @@ -467,11 +467,11 @@ mod test { TestVal::None(tr) => const_none(tr.clone()), TestVal::Ok(l, tr) => { let elems = l.iter().map(TestVal::to_value); - const_left_tuple(elems, tr.clone()) + const_ok_tuple(elems, tr.clone()) } TestVal::Err(tr, l) => { let elems = l.iter().map(TestVal::to_value); - const_right_tuple(tr.clone(), elems) + const_fail_tuple(elems, tr.clone()) } } } diff --git a/hugr-core/src/std_extensions/collections/list_fold.rs b/hugr-core/src/std_extensions/collections/list_fold.rs index b3f6b5b0f..a7e037f6f 100644 --- a/hugr-core/src/std_extensions/collections/list_fold.rs +++ b/hugr-core/src/std_extensions/collections/list_fold.rs @@ -1,7 +1,7 @@ //! Folding definitions for list operations. use crate::extension::prelude::{ - const_left, const_left_tuple, const_none, const_right, const_some, ConstUsize, + const_fail, const_none, const_ok, const_ok_tuple, const_some, ConstUsize, }; use crate::extension::{ConstFold, ConstFoldResult, OpDef}; use crate::ops::Value; @@ -96,9 +96,9 @@ impl ConstFold for SetFold { let res_elem: Value = match list.0.get_mut(idx) { Some(old_elem) => { std::mem::swap(old_elem, &mut elem); - const_left(elem, list.1.clone()) + const_ok(elem, list.1.clone()) } - None => const_right(list.1.clone(), elem), + None => const_fail(elem, list.1.clone()), }; Some(vec![(0.into(), list.into()), (1.into(), res_elem)]) } @@ -118,9 +118,9 @@ impl ConstFold for InsertFold { let elem = elem.clone(); let res_elem: Value = if list.0.len() > idx { list.0.insert(idx, elem); - const_left_tuple([], list.1.clone()) + const_ok_tuple([], list.1.clone()) } else { - const_right(Type::UNIT, elem) + const_fail(elem, Type::UNIT) }; Some(vec![(0.into(), list.into()), (1.into(), res_elem)]) } diff --git a/hugr-passes/src/const_fold/test.rs b/hugr-passes/src/const_fold/test.rs index 3fdddf24d..e8fe43711 100644 --- a/hugr-passes/src/const_fold/test.rs +++ b/hugr-passes/src/const_fold/test.rs @@ -1,7 +1,8 @@ use crate::const_fold::constant_fold_pass; use hugr_core::builder::{DFGBuilder, Dataflow, DataflowHugr}; -use hugr_core::extension::prelude::UnpackTuple; -use hugr_core::extension::prelude::{sum_with_error, ConstError, ConstString, BOOL_T, STRING_TYPE}; +use hugr_core::extension::prelude::{ + const_ok, sum_with_error, ConstError, ConstString, UnpackTuple, BOOL_T, ERROR_TYPE, STRING_TYPE, +}; use hugr_core::extension::{ExtensionRegistry, PRELUDE}; use hugr_core::ops::Value; use hugr_core::std_extensions::arithmetic; @@ -119,7 +120,7 @@ fn test_big() { constant_fold_pass(&mut h, ®); - let expected = Value::sum(0, [i2c(2).clone()], sum_type).unwrap(); + let expected = const_ok(i2c(2).clone(), ERROR_TYPE); assert_fully_folded(&h, &expected); } @@ -403,7 +404,10 @@ fn test_fold_inarrow, E: std::fmt::Debug>( // val => the value to pass to the op // succeeds => whether to expect a int variant or an error // variant. - let sum_type = sum_with_error(INT_TYPES[to_log_width as usize].to_owned()); + + use hugr_core::extension::prelude::const_ok; + let elem_type = INT_TYPES[to_log_width as usize].to_owned(); + let sum_type = sum_with_error(elem_type.clone()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(mk_const(from_log_width, val).unwrap().into()); let x1 = build @@ -420,16 +424,15 @@ fn test_fold_inarrow, E: std::fmt::Debug>( let mut h = build.finish_hugr_with_outputs(x1.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); lazy_static! { - static ref INARROW_ERROR_VALUE: Value = ConstError { + static ref INARROW_ERROR_VALUE: ConstError = ConstError { signal: 0, message: "Integer too large to narrow".to_string(), - } - .into(); + }; } let expected = if succeeds { - Value::sum(0, [mk_const(to_log_width, val).unwrap().into()], sum_type).unwrap() + const_ok(mk_const(to_log_width, val).unwrap().into(), ERROR_TYPE) } else { - Value::sum(1, [INARROW_ERROR_VALUE.clone()], sum_type).unwrap() + INARROW_ERROR_VALUE.clone().as_either(elem_type) }; assert_fully_folded(&h, &expected); } @@ -900,7 +903,8 @@ fn test_fold_idivmod_checked_u() { // x2 := idivmod_checked_u(x0, x1) // output x2 == error let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[5].clone()].into(); - let sum_type = sum_with_error(Type::new_tuple(intpair)); + let elem_type = Type::new_tuple(intpair); + let sum_type = sum_with_error(elem_type.clone()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 20).unwrap())); let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); @@ -914,16 +918,11 @@ fn test_fold_idivmod_checked_u() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(elem_type); assert_fully_folded(&h, &expected); } @@ -962,7 +961,8 @@ fn test_fold_idivmod_checked_s() { // x2 := idivmod_checked_s(x0, x1) // output x2 == error let intpair: TypeRowRV = vec![INT_TYPES[5].clone(), INT_TYPES[5].clone()].into(); - let sum_type = sum_with_error(Type::new_tuple(intpair)); + let elem_type = Type::new_tuple(intpair); + let sum_type = sum_with_error(elem_type.clone()); let mut build = DFGBuilder::new(noargfn(vec![sum_type.clone().into()])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -20).unwrap())); let x1 = build.add_load_const(Value::extension(ConstInt::new_u(5, 0).unwrap())); @@ -976,16 +976,11 @@ fn test_fold_idivmod_checked_s() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(elem_type); assert_fully_folded(&h, &expected); } @@ -1039,16 +1034,11 @@ fn test_fold_idiv_checked_u() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(INT_TYPES[5].to_owned()); assert_fully_folded(&h, &expected); } @@ -1095,16 +1085,11 @@ fn test_fold_imod_checked_u() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(INT_TYPES[5].to_owned()); assert_fully_folded(&h, &expected); } @@ -1151,16 +1136,11 @@ fn test_fold_idiv_checked_s() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(INT_TYPES[5].to_owned()); assert_fully_folded(&h, &expected); } @@ -1207,16 +1187,11 @@ fn test_fold_imod_checked_s() { .unwrap(); let mut h = build.finish_hugr_with_outputs(x2.outputs(), ®).unwrap(); constant_fold_pass(&mut h, ®); - let expected = Value::sum( - 1, - [ConstError { - signal: 0, - message: "Division by zero".to_string(), - } - .into()], - sum_type.clone(), - ) - .unwrap(); + let expected = ConstError { + signal: 0, + message: "Division by zero".to_string(), + } + .as_either(INT_TYPES[5].to_owned()); assert_fully_folded(&h, &expected); } diff --git a/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json b/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json index c23cba7c6..9ac8a25a4 100644 --- a/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json +++ b/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json @@ -122,6 +122,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -139,15 +148,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -183,6 +183,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -200,15 +209,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } diff --git a/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json b/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json index a6cc862f6..79e8a6cda 100644 --- a/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json +++ b/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json @@ -249,6 +249,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -266,15 +275,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -335,6 +335,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -352,15 +361,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -559,6 +559,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Sum", @@ -600,15 +609,6 @@ ] ] } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -669,6 +669,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Sum", @@ -710,15 +719,6 @@ ] ] } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -1780,6 +1780,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -1797,15 +1806,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -1866,6 +1866,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -1883,15 +1892,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -2147,6 +2147,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -2164,15 +2173,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -2221,6 +2221,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -2238,15 +2247,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } diff --git a/hugr-py/src/hugr/std/_json_defs/collections.json b/hugr-py/src/hugr/std/_json_defs/collections.json index 43ba03bef..bf60f0956 100644 --- a/hugr-py/src/hugr/std/_json_defs/collections.json +++ b/hugr-py/src/hugr/std/_json_defs/collections.json @@ -61,14 +61,14 @@ "t": "Sum", "s": "General", "rows": [ + [], [ { "t": "V", "i": 0, "b": "A" } - ], - [] + ] ] } ], @@ -249,14 +249,14 @@ "t": "Sum", "s": "General", "rows": [ + [], [ { "t": "V", "i": 0, "b": "A" } - ], - [] + ] ] } ], diff --git a/hugr-py/src/hugr/tys.py b/hugr-py/src/hugr/tys.py index 2867c2e0d..fb273ece4 100644 --- a/hugr-py/src/hugr/tys.py +++ b/hugr-py/src/hugr/tys.py @@ -351,14 +351,14 @@ class Option(Sum): """Optional tuple of elements. Instances of this type correspond to :class:`Sum` with two variants. - The first variant is the tuple of elements, the second is empty. + The second variant is the tuple of elements, the first is empty. """ def __init__(self, *tys: Type): - self.variant_rows = [list(tys), []] + self.variant_rows = [[], list(tys)] def __repr__(self) -> str: - return f"Option({comma_sep_repr(self.variant_rows[0])})" + return f"Option({comma_sep_repr(self.variant_rows[1])})" @dataclass(eq=False) @@ -367,8 +367,8 @@ class Either(Sum): Instances of this type correspond to :class:`Sum` with a Left and a Right variant. - In fallible contexts, the Left variant is used to represent success, and the - Right variant is used to represent failure. + In fallible contexts, the Right variant is used to represent success, and the + Left variant is used to represent failure. """ def __init__(self, left: Iterable[Type], right: Iterable[Type]): diff --git a/hugr-py/src/hugr/val.py b/hugr-py/src/hugr/val.py index 84ff24ab4..26b84cde9 100644 --- a/hugr-py/src/hugr/val.py +++ b/hugr-py/src/hugr/val.py @@ -172,7 +172,7 @@ class Some(Sum): def __init__(self, *vals: Value): val_list = list(vals) super().__init__( - tag=0, typ=tys.Option(*(v.type_() for v in val_list)), vals=val_list + tag=1, typ=tys.Option(*(v.type_() for v in val_list)), vals=val_list ) def __repr__(self) -> str: @@ -193,10 +193,10 @@ class None_(Sum): """ def __init__(self, *types: tys.Type): - super().__init__(tag=1, typ=tys.Option(*types), vals=[]) + super().__init__(tag=0, typ=tys.Option(*types), vals=[]) def __repr__(self) -> str: - return f"None({', '.join(map(repr, self.typ.variant_rows[0]))})" + return f"None({comma_sep_str(self.typ.variant_rows[1])})" def __str__(self) -> str: return "None" @@ -206,7 +206,7 @@ def __str__(self) -> str: class Left(Sum): """Left variant of a :class:`tys.Either` type, containing a list of values. - In fallible contexts, this represents the success variant. + In fallible contexts, this represents the failure variant. Example: >>> left = Left([TRUE, FALSE], [tys.Bool]) @@ -236,7 +236,7 @@ def __str__(self) -> str: class Right(Sum): """Right variant of a :class:`tys.Either` type, containing a list of values. - In fallible contexts, this represents the failure variant. + In fallible contexts, this represents the success variant. Internally a :class:`Sum` with two variant rows. diff --git a/hugr-py/tests/test_tys.py b/hugr-py/tests/test_tys.py index 0515e17ba..cd0c2c503 100644 --- a/hugr-py/tests/test_tys.py +++ b/hugr-py/tests/test_tys.py @@ -44,9 +44,9 @@ def test_sums(): assert Tuple(Bool, Qubit) == Sum([[Bool, Qubit]]) assert Sum([[Bool, Qubit]]).as_tuple() == Sum([[Bool, Qubit]]) - assert Sum([[Bool, Qubit], []]) == Option(Bool, Qubit) - assert Sum([[Bool, Qubit], []]) == Either([Bool, Qubit], []) - assert Option(Bool, Qubit) == Either([Bool, Qubit], []) + assert Sum([[], [Bool, Qubit]]) == Option(Bool, Qubit) + assert Sum([[], [Bool, Qubit]]) == Either([], [Bool, Qubit]) + assert Option(Bool, Qubit) == Either([], [Bool, Qubit]) assert Sum([[Qubit], [Bool]]) == Either([Qubit], [Bool]) assert Tuple() == Sum([[]]) diff --git a/hugr-py/tests/test_val.py b/hugr-py/tests/test_val.py index 364b9e3df..49705b74c 100644 --- a/hugr-py/tests/test_val.py +++ b/hugr-py/tests/test_val.py @@ -10,11 +10,11 @@ def test_sums(): assert Sum(0, tys.Tuple(), []) == Tuple() assert Sum(0, tys.Tuple(tys.Bool, tys.Bool), [TRUE, FALSE]) == Tuple(TRUE, FALSE) - ty = tys.Sum([[tys.Bool, tys.Bool], []]) - assert Sum(0, ty, [TRUE, FALSE]) == Some(TRUE, FALSE) - assert Sum(0, ty, [TRUE, FALSE]) == Left([TRUE, FALSE], []) - assert Sum(1, ty, []) == None_(tys.Bool, tys.Bool) - assert Sum(1, ty, []) == Right([tys.Bool, tys.Bool], []) + ty = tys.Sum([[], [tys.Bool, tys.Bool]]) + assert Sum(1, ty, [TRUE, FALSE]) == Some(TRUE, FALSE) + assert Sum(1, ty, [TRUE, FALSE]) == Right([], [TRUE, FALSE]) + assert Sum(0, ty, []) == None_(tys.Bool, tys.Bool) + assert Sum(0, ty, []) == Left([], [tys.Bool, tys.Bool]) ty = tys.Sum([[tys.Bool], [tys.Bool]]) assert Sum(0, ty, [TRUE]) == Left([TRUE], [tys.Bool]) diff --git a/specification/std_extensions/arithmetic/conversions.json b/specification/std_extensions/arithmetic/conversions.json index c23cba7c6..9ac8a25a4 100644 --- a/specification/std_extensions/arithmetic/conversions.json +++ b/specification/std_extensions/arithmetic/conversions.json @@ -122,6 +122,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -139,15 +148,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -183,6 +183,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -200,15 +209,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } diff --git a/specification/std_extensions/arithmetic/int.json b/specification/std_extensions/arithmetic/int.json index a6cc862f6..79e8a6cda 100644 --- a/specification/std_extensions/arithmetic/int.json +++ b/specification/std_extensions/arithmetic/int.json @@ -249,6 +249,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -266,15 +275,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -335,6 +335,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -352,15 +361,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -559,6 +559,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Sum", @@ -600,15 +609,6 @@ ] ] } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -669,6 +669,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Sum", @@ -710,15 +719,6 @@ ] ] } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -1780,6 +1780,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -1797,15 +1806,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -1866,6 +1866,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -1883,15 +1892,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -2147,6 +2147,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -2164,15 +2173,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } @@ -2221,6 +2221,15 @@ "t": "Sum", "s": "General", "rows": [ + [ + { + "t": "Opaque", + "extension": "prelude", + "id": "error", + "args": [], + "bound": "C" + } + ], [ { "t": "Opaque", @@ -2238,15 +2247,6 @@ ], "bound": "C" } - ], - [ - { - "t": "Opaque", - "extension": "prelude", - "id": "error", - "args": [], - "bound": "C" - } ] ] } diff --git a/specification/std_extensions/collections.json b/specification/std_extensions/collections.json index 43ba03bef..bf60f0956 100644 --- a/specification/std_extensions/collections.json +++ b/specification/std_extensions/collections.json @@ -61,14 +61,14 @@ "t": "Sum", "s": "General", "rows": [ + [], [ { "t": "V", "i": 0, "b": "A" } - ], - [] + ] ] } ], @@ -249,14 +249,14 @@ "t": "Sum", "s": "General", "rows": [ + [], [ { "t": "V", "i": 0, "b": "A" } - ], - [] + ] ] } ],