From e5799c29bc48e9c13faeba079bf9a1ae27cbe2ff Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Tue, 22 Aug 2023 17:26:43 +0100 Subject: [PATCH 01/14] [RFC] define new `TypeParam::SimplePredicate` and use in int extension --- src/std_extensions/arithmetic/conversions.rs | 6 +- src/std_extensions/arithmetic/int_ops.rs | 32 +++++----- src/std_extensions/arithmetic/int_types.rs | 64 ++++++-------------- src/types/type_param.rs | 7 +++ 4 files changed, 45 insertions(+), 64 deletions(-) diff --git a/src/std_extensions/arithmetic/conversions.rs b/src/std_extensions/arithmetic/conversions.rs index 6cca97c80..736bbb3be 100644 --- a/src/std_extensions/arithmetic/conversions.rs +++ b/src/std_extensions/arithmetic/conversions.rs @@ -16,14 +16,14 @@ use crate::{ }; use super::float_types::FLOAT64_TYPE; -use super::int_types::{get_width, int_type}; +use super::int_types::{get_width_power, int_type}; /// The extension identifier. pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.conversions"); fn ftoi_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width(arg)?; + let n: u8 = get_width_power(arg); Ok(( type_row![FLOAT64_TYPE], vec![Type::new_sum(vec![ @@ -37,7 +37,7 @@ fn ftoi_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn itof_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width(arg)?; + let n: u8 = get_width_power(arg); Ok(( vec![int_type(n)].into(), type_row![FLOAT64_TYPE], diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index 9408f1bfe..76666811c 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use super::int_types::{get_width, int_type}; +use super::int_types::{get_width_power, int_type}; use crate::extension::prelude::{BOOL_T, ERROR_TYPE}; use crate::type_row; use crate::types::type_param::TypeParam; @@ -18,8 +18,8 @@ pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.int"); fn iwiden_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width(arg0)?; - let n: u8 = get_width(arg1)?; + let m: u8 = get_width_power(arg0); + let n: u8 = get_width_power(arg1); if m > n { return Err(SignatureError::InvalidTypeArgs); } @@ -32,8 +32,8 @@ fn iwiden_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet) fn inarrow_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width(arg0)?; - let n: u8 = get_width(arg1)?; + let m: u8 = get_width_power(arg0); + let n: u8 = get_width_power(arg1); if m < n { return Err(SignatureError::InvalidTypeArgs); } @@ -62,7 +62,7 @@ fn btoi_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn icmp_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width(arg)?; + let n: u8 = get_width_power(arg); Ok(( vec![int_type(n); 2].into(), type_row![BOOL_T], @@ -72,7 +72,7 @@ fn icmp_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn ibinop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width(arg)?; + let n: u8 = get_width_power(arg); Ok(( vec![int_type(n); 2].into(), vec![int_type(n)].into(), @@ -82,7 +82,7 @@ fn ibinop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet) fn iunop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width(arg)?; + let n: u8 = get_width_power(arg); Ok(( vec![int_type(n)].into(), vec![int_type(n)].into(), @@ -92,8 +92,8 @@ fn iunop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width(arg0)?; - let m: u8 = get_width(arg1)?; + let n: u8 = get_width_power(arg0); + let m: u8 = get_width_power(arg1); let intpair: TypeRow = vec![int_type(n), int_type(m)].into(); Ok(( intpair.clone(), @@ -104,8 +104,8 @@ fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet fn idiv_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width(arg0)?; - let m: u8 = get_width(arg1)?; + let n: u8 = get_width_power(arg0); + let m: u8 = get_width_power(arg1); Ok(( vec![int_type(n), int_type(m)].into(), vec![Type::new_sum(vec![int_type(n), ERROR_TYPE])].into(), @@ -115,8 +115,8 @@ fn idiv_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn imod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width(arg0)?; - let m: u8 = get_width(arg1)?; + let n: u8 = get_width_power(arg0); + let m: u8 = get_width_power(arg1); Ok(( vec![int_type(n), int_type(m)].into(), vec![Type::new_sum(vec![int_type(m), ERROR_TYPE])].into(), @@ -126,8 +126,8 @@ fn imod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn ish_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width(arg0)?; - let m: u8 = get_width(arg1)?; + let n: u8 = get_width_power(arg0); + let m: u8 = get_width_power(arg1); Ok(( vec![int_type(n), int_type(m)].into(), vec![int_type(n)].into(), diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 84ca1ccfa..95d9fde6b 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -3,9 +3,8 @@ use smol_str::SmolStr; use crate::{ - extension::SignatureError, types::{ - type_param::{TypeArg, TypeArgError, TypeParam}, + type_param::{TypeArg, TypeParam}, ConstTypeError, CustomCheckFailure, CustomType, Type, TypeBound, }, values::CustomConst, @@ -21,7 +20,7 @@ const INT_TYPE_ID: SmolStr = SmolStr::new_inline("int"); fn int_custom_type(n: u8) -> CustomType { CustomType::new( INT_TYPE_ID, - [TypeArg::USize(n as u64)], + [TypeArg::SimplePredicate(n as usize)], EXTENSION_ID, TypeBound::Copyable, ) @@ -30,37 +29,22 @@ fn int_custom_type(n: u8) -> CustomType { /// Integer type of a given bit width. /// Depending on the operation, the semantic interpretation may be unsigned integer, signed integer /// or bit string. -pub fn int_type(n: u8) -> Type { - Type::new_extension(int_custom_type(n)) +pub fn int_type(width_power: u8) -> Type { + Type::new_extension(int_custom_type(width_power)) } -fn is_valid_width(n: u8) -> bool { - (n == 1) - || (n == 2) - || (n == 4) - || (n == 8) - || (n == 16) - || (n == 32) - || (n == 64) - || (n == 128) +const fn is_valid_width(n: u8) -> bool { + (n <= (1u8 << (POWERS_OF_TWO - 1))) && ((n & (n - 1)) == 0) } +const POWERS_OF_TWO: usize = 8; + /// Get the bit width of the specified integer type, or error if the width is not supported. -pub fn get_width(arg: &TypeArg) -> Result { - let n: u8 = match arg { - TypeArg::USize(n) => *n as u8, - _ => { - return Err(TypeArgError::TypeMismatch { - arg: arg.clone(), - param: TypeParam::USize, - } - .into()); - } - }; - if !is_valid_width(n) { - return Err(TypeArgError::InvalidValue(arg.clone()).into()); +pub fn get_width_power(arg: &TypeArg) -> u8 { + match arg { + TypeArg::SimplePredicate(n) if *n < POWERS_OF_TWO => *n as u8, + _ => panic!("type check should prevent this."), } - Ok(n) } /// An unsigned integer @@ -160,7 +144,7 @@ pub fn extension() -> Extension { extension .add_type( INT_TYPE_ID, - vec![TypeParam::USize], + vec![TypeParam::SimplePredicate(POWERS_OF_TWO)], "integral value of a given bit width".to_owned(), TypeBound::Copyable.into(), ) @@ -171,7 +155,7 @@ pub fn extension() -> Extension { #[cfg(test)] mod test { - use cool_asserts::assert_matches; + use cool_asserts::{assert_matches, assert_panics}; use super::*; @@ -185,23 +169,13 @@ mod test { #[test] fn test_int_widths() { - let type_arg_32 = TypeArg::USize(32); - assert_matches!(get_width(&type_arg_32), Ok(32)); + let type_arg_32 = TypeArg::SimplePredicate(5); + assert_matches!(get_width_power(&type_arg_32), 5); - let type_arg_33 = TypeArg::USize(33); - assert_matches!( - get_width(&type_arg_33), - Err(SignatureError::TypeArgMismatch(_)) - ); + let type_arg_128 = TypeArg::SimplePredicate(7); + assert_matches!(get_width_power(&type_arg_128), 7); - let type_arg_128 = TypeArg::USize(128); - assert_matches!(get_width(&type_arg_128), Ok(128)); - - let type_arg_256 = TypeArg::USize(256); - assert_matches!( - get_width(&type_arg_256), - Err(SignatureError::TypeArgMismatch(_)) - ); + assert_panics!(get_width_power(&TypeArg::SimplePredicate(8))); } #[test] diff --git a/src/types/type_param.rs b/src/types/type_param.rs index 3d15effca..fd28e5a40 100644 --- a/src/types/type_param.rs +++ b/src/types/type_param.rs @@ -21,6 +21,9 @@ pub enum TypeParam { Type(TypeBound), /// Argument is a [TypeArg::USize]. USize, + /// Argument is a [TypeArg::SimplePredicate] which is bounded by the size + /// specified here. + SimplePredicate(usize), /// Argument is a [TypeArg::Opaque], defined by a [CustomType]. Opaque(CustomType), /// Argument is a [TypeArg::Sequence]. A list of indeterminate size containing parameters. @@ -41,6 +44,9 @@ pub enum TypeArg { Type(Type), /// Instance of [TypeParam::USize]. 64-bit unsigned integer. USize(u64), + /// Instance of [TypeParam::SimplePredicate]. A Sum over unit types with + /// specified tag. + SimplePredicate(usize), ///Instance of [TypeParam::Opaque] An opaque value, stored as serialized blob. Opaque(CustomTypeArg), /// Instance of [TypeParam::List] or [TypeParam::Tuple], defined by a @@ -99,6 +105,7 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr Ok(()) } (TypeArg::Extensions(_), TypeParam::Extensions) => Ok(()), + (TypeArg::SimplePredicate(tag), TypeParam::SimplePredicate(size)) if tag < size => Ok(()), _ => Err(TypeArgError::TypeMismatch { arg: arg.clone(), param: param.clone(), From b5d84fe859a397cbfa217f68151c66214f0e8c49 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 14:06:47 +0100 Subject: [PATCH 02/14] remove USize + SimplePredicate in favour of BoundedUSize --- src/extension/prelude.rs | 4 +- src/ops/constant.rs | 7 +- src/std_extensions/arithmetic/conversions.rs | 8 +-- src/std_extensions/arithmetic/int_ops.rs | 74 ++++++++++---------- src/std_extensions/arithmetic/int_types.rs | 16 +++-- src/std_extensions/collections.rs | 4 +- src/std_extensions/logic.rs | 8 +-- src/types/type_param.rs | 22 +++--- 8 files changed, 76 insertions(+), 67 deletions(-) diff --git a/src/extension/prelude.rs b/src/extension/prelude.rs index e4dfc92fa..4f74f4f49 100644 --- a/src/extension/prelude.rs +++ b/src/extension/prelude.rs @@ -30,7 +30,7 @@ lazy_static! { prelude .add_type( SmolStr::new_inline("array"), - vec![TypeParam::Type(TypeBound::Any), TypeParam::USize], + vec![TypeParam::Type(TypeBound::Any), TypeParam::max_usize()], "array".into(), TypeDefBound::FromParams(vec![0]), ) @@ -68,7 +68,7 @@ pub(crate) const BOOL_T: Type = Type::new_simple_predicate(2); pub fn new_array(typ: Type, size: u64) -> Type { let array_def = PRELUDE.get_type("array").unwrap(); let custom_t = array_def - .instantiate_concrete(vec![TypeArg::Type(typ), TypeArg::USize(size)]) + .instantiate_concrete(vec![TypeArg::Type(typ), TypeArg::BoundedUSize(size)]) .unwrap(); Type::new_extension(custom_t) } diff --git a/src/ops/constant.rs b/src/ops/constant.rs index ed2c0587d..ef057e9c2 100644 --- a/src/ops/constant.rs +++ b/src/ops/constant.rs @@ -199,7 +199,12 @@ mod test { #[test] fn test_yaml_const() { - let typ_int = CustomType::new("mytype", vec![TypeArg::USize(8)], "myrsrc", TypeBound::Eq); + let typ_int = CustomType::new( + "mytype", + vec![TypeArg::BoundedUSize(8)], + "myrsrc", + TypeBound::Eq, + ); let val: Value = CustomSerialized::new(typ_int.clone(), YamlValue::Number(6.into())).into(); let classic_t = Type::new_extension(typ_int.clone()); assert_matches!(classic_t.least_upper_bound(), TypeBound::Eq); diff --git a/src/std_extensions/arithmetic/conversions.rs b/src/std_extensions/arithmetic/conversions.rs index 736bbb3be..48901c7c1 100644 --- a/src/std_extensions/arithmetic/conversions.rs +++ b/src/std_extensions/arithmetic/conversions.rs @@ -59,7 +59,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "trunc_u".into(), "float to unsigned int".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ftoi_sig, ) .unwrap(); @@ -67,7 +67,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "trunc_s".into(), "float to signed int".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ftoi_sig, ) .unwrap(); @@ -75,7 +75,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "convert_u".into(), "unsigned int to float".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], itof_sig, ) .unwrap(); @@ -83,7 +83,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "convert_s".into(), "signed int to float".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], itof_sig, ) .unwrap(); diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index 76666811c..b412288ba 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -146,7 +146,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iwiden_u".into(), "widen an unsigned integer to a wider one with the same value".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], iwiden_sig, ) .unwrap(); @@ -154,7 +154,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iwiden_s".into(), "widen a signed integer to a wider one with the same value".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], iwiden_sig, ) .unwrap(); @@ -163,7 +163,7 @@ pub fn extension() -> Extension { "inarrow_u".into(), "narrow an unsigned integer to a narrower one with the same value if possible" .to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], inarrow_sig, ) .unwrap(); @@ -171,7 +171,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "inarrow_s".into(), "narrow a signed integer to a narrower one with the same value if possible".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], inarrow_sig, ) .unwrap(); @@ -195,7 +195,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ieq".into(), "equality test".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -203,7 +203,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ine".into(), "inequality test".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -211,7 +211,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ilt_u".into(), "\"less than\" as unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -219,7 +219,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ilt_s".into(), "\"less than\" as signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -227,7 +227,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "igt_u".into(), "\"greater than\" as unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -235,7 +235,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "igt_s".into(), "\"greater than\" as signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -243,7 +243,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ile_u".into(), "\"less than or equal\" as unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -251,7 +251,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ile_s".into(), "\"less than or equal\" as signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -259,7 +259,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ige_u".into(), "\"greater than or equal\" as unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -267,7 +267,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ige_s".into(), "\"greater than or equal\" as signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], icmp_sig, ) .unwrap(); @@ -275,7 +275,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imax_u".into(), "maximum of unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -283,7 +283,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imax_s".into(), "maximum of signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -291,7 +291,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imin_u".into(), "minimum of unsigned integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -299,7 +299,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imin_s".into(), "minimum of signed integers".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -307,7 +307,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iadd".into(), "addition modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -315,7 +315,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "isub".into(), "subtraction modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -323,7 +323,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ineg".into(), "negation modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], iunop_sig, ) .unwrap(); @@ -331,7 +331,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imul".into(), "multiplication modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -341,7 +341,7 @@ pub fn extension() -> Extension { "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \ q*m+r=n, 0<=r Extension { "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \ signed q and unsigned r where q*m+r=n, 0<=r Extension { .add_op_custom_sig_simple( "idiv_u".into(), "as idivmod_u but discarding the second output".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], idiv_sig, ) .unwrap(); @@ -367,7 +367,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imod_u".into(), "as idivmod_u but discarding the first output".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], idiv_sig, ) .unwrap(); @@ -375,7 +375,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "idiv_s".into(), "as idivmod_s but discarding the second output".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], imod_sig, ) .unwrap(); @@ -383,7 +383,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imod_s".into(), "as idivmod_s but discarding the first output".to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], imod_sig, ) .unwrap(); @@ -391,7 +391,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iabs".into(), "convert signed to unsigned by taking absolute value".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], iunop_sig, ) .unwrap(); @@ -399,7 +399,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iand".into(), "bitwise AND".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -407,7 +407,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ior".into(), "bitwise OR".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -415,7 +415,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ixor".into(), "bitwise XOR".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], ibinop_sig, ) .unwrap(); @@ -423,7 +423,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "inot".into(), "bitwise NOT".to_owned(), - vec![TypeParam::USize], + vec![TypeParam::max_usize()], iunop_sig, ) .unwrap(); @@ -433,7 +433,7 @@ pub fn extension() -> Extension { "shift first input left by k bits where k is unsigned interpretation of second input \ (leftmost bits dropped, rightmost bits set to zero" .to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], ish_sig, ) .unwrap(); @@ -443,7 +443,7 @@ pub fn extension() -> Extension { "shift first input right by k bits where k is unsigned interpretation of second input \ (rightmost bits dropped, leftmost bits set to zero)" .to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], ish_sig, ) .unwrap(); @@ -453,7 +453,7 @@ pub fn extension() -> Extension { "rotate first input left by k bits where k is unsigned interpretation of second input \ (leftmost bits replace rightmost bits)" .to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], ish_sig, ) .unwrap(); @@ -463,7 +463,7 @@ pub fn extension() -> Extension { "rotate first input right by k bits where k is unsigned interpretation of second input \ (rightmost bits replace leftmost bits)" .to_owned(), - vec![TypeParam::USize, TypeParam::USize], + vec![TypeParam::max_usize(), TypeParam::max_usize()], ish_sig, ) .unwrap(); diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 95d9fde6b..97666b3db 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -20,7 +20,7 @@ const INT_TYPE_ID: SmolStr = SmolStr::new_inline("int"); fn int_custom_type(n: u8) -> CustomType { CustomType::new( INT_TYPE_ID, - [TypeArg::SimplePredicate(n as usize)], + [TypeArg::BoundedUSize(n as u64)], EXTENSION_ID, TypeBound::Copyable, ) @@ -37,12 +37,14 @@ const fn is_valid_width(n: u8) -> bool { (n <= (1u8 << (POWERS_OF_TWO - 1))) && ((n & (n - 1)) == 0) } -const POWERS_OF_TWO: usize = 8; +const POWERS_OF_TWO: u64 = 8; +/// Type parameter for the log width of the integer. +pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO); /// Get the bit width of the specified integer type, or error if the width is not supported. pub fn get_width_power(arg: &TypeArg) -> u8 { match arg { - TypeArg::SimplePredicate(n) if *n < POWERS_OF_TWO => *n as u8, + TypeArg::BoundedUSize(n) if *n < POWERS_OF_TWO => *n as u8, _ => panic!("type check should prevent this."), } } @@ -144,7 +146,7 @@ pub fn extension() -> Extension { extension .add_type( INT_TYPE_ID, - vec![TypeParam::SimplePredicate(POWERS_OF_TWO)], + vec![LOG_WIDTH_TYPE_PARAM], "integral value of a given bit width".to_owned(), TypeBound::Copyable.into(), ) @@ -169,13 +171,13 @@ mod test { #[test] fn test_int_widths() { - let type_arg_32 = TypeArg::SimplePredicate(5); + let type_arg_32 = TypeArg::BoundedUSize(5); assert_matches!(get_width_power(&type_arg_32), 5); - let type_arg_128 = TypeArg::SimplePredicate(7); + let type_arg_128 = TypeArg::BoundedUSize(7); assert_matches!(get_width_power(&type_arg_128), 7); - assert_panics!(get_width_power(&TypeArg::SimplePredicate(8))); + assert_panics!(get_width_power(&TypeArg::BoundedUSize(8))); } #[test] diff --git a/src/std_extensions/collections.rs b/src/std_extensions/collections.rs index 7c1bb50ee..b31964e37 100644 --- a/src/std_extensions/collections.rs +++ b/src/std_extensions/collections.rs @@ -159,7 +159,9 @@ mod test { .instantiate_concrete([TypeArg::Type(USIZE_T)]) .unwrap(); - assert!(list_def.instantiate_concrete([TypeArg::USize(3)]).is_err()); + assert!(list_def + .instantiate_concrete([TypeArg::BoundedUSize(3)]) + .is_err()); list_def.check_custom(&list_type).unwrap(); let list_value = ListValue(vec![ConstUsize::new(3).into()]); diff --git a/src/std_extensions/logic.rs b/src/std_extensions/logic.rs index c5d45bd62..8187d186b 100644 --- a/src/std_extensions/logic.rs +++ b/src/std_extensions/logic.rs @@ -27,7 +27,7 @@ pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("logic"); /// Extension for basic logical operations. fn extension() -> Extension { - const H_INT: TypeParam = TypeParam::USize; + const H_INT: TypeParam = TypeParam::max_usize(); let mut extension = Extension::new(EXTENSION_ID); extension @@ -53,7 +53,7 @@ fn extension() -> Extension { |arg_values: &[TypeArg]| { let a = arg_values.iter().exactly_one().unwrap(); let n: u64 = match a { - TypeArg::USize(n) => *n, + TypeArg::BoundedUSize(n) => *n, _ => { return Err(TypeArgError::TypeMismatch { arg: a.clone(), @@ -79,7 +79,7 @@ fn extension() -> Extension { |arg_values: &[TypeArg]| { let a = arg_values.iter().exactly_one().unwrap(); let n: u64 = match a { - TypeArg::USize(n) => *n, + TypeArg::BoundedUSize(n) => *n, _ => { return Err(TypeArgError::TypeMismatch { arg: a.clone(), @@ -139,7 +139,7 @@ pub(crate) mod test { /// Generate a logic extension and operation over [`crate::prelude::BOOL_T`] pub(crate) fn and_op() -> LeafOp { EXTENSION - .instantiate_extension_op(AND_NAME, [TypeArg::USize(2)]) + .instantiate_extension_op(AND_NAME, [TypeArg::BoundedUSize(2)]) .unwrap() .into() } diff --git a/src/types/type_param.rs b/src/types/type_param.rs index fd28e5a40..cac0d214b 100644 --- a/src/types/type_param.rs +++ b/src/types/type_param.rs @@ -19,11 +19,8 @@ use super::TypeBound; pub enum TypeParam { /// Argument is a [TypeArg::Type]. Type(TypeBound), - /// Argument is a [TypeArg::USize]. - USize, - /// Argument is a [TypeArg::SimplePredicate] which is bounded by the size - /// specified here. - SimplePredicate(usize), + /// Argument is a [TypeArg::USize] that is less than the stated bound. + BoundedUSize(u64), /// Argument is a [TypeArg::Opaque], defined by a [CustomType]. Opaque(CustomType), /// Argument is a [TypeArg::Sequence]. A list of indeterminate size containing parameters. @@ -36,6 +33,13 @@ pub enum TypeParam { Extensions, } +impl TypeParam { + /// [`TypeParam::BoundedUSize`] with the maximum bound (`u64::MAX`) + pub const fn max_usize() -> Self { + Self::BoundedUSize(u64::MAX) + } +} + /// A statically-known argument value to an operation. #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] #[non_exhaustive] @@ -43,10 +47,7 @@ pub enum TypeArg { /// Where the (Type/Op)Def declares that an argument is a [TypeParam::Type] Type(Type), /// Instance of [TypeParam::USize]. 64-bit unsigned integer. - USize(u64), - /// Instance of [TypeParam::SimplePredicate]. A Sum over unit types with - /// specified tag. - SimplePredicate(usize), + BoundedUSize(u64), ///Instance of [TypeParam::Opaque] An opaque value, stored as serialized blob. Opaque(CustomTypeArg), /// Instance of [TypeParam::List] or [TypeParam::Tuple], defined by a @@ -98,14 +99,13 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr .try_for_each(|(arg, param)| check_type_arg(arg, param)) } } - (TypeArg::USize(_), TypeParam::USize) => Ok(()), + (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(bound)) if val < bound => Ok(()), (TypeArg::Opaque(arg), TypeParam::Opaque(param)) if param.bound() == TypeBound::Eq && &arg.typ == param => { Ok(()) } (TypeArg::Extensions(_), TypeParam::Extensions) => Ok(()), - (TypeArg::SimplePredicate(tag), TypeParam::SimplePredicate(size)) if tag < size => Ok(()), _ => Err(TypeArgError::TypeMismatch { arg: arg.clone(), param: param.clone(), From 1f9265d5936e289c353d0853302efcb2ffb7266e Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 14:16:16 +0100 Subject: [PATCH 03/14] fixup constants and tests --- src/std_extensions/arithmetic/int_types.rs | 54 +++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 97666b3db..16fd91d30 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -33,18 +33,18 @@ pub fn int_type(width_power: u8) -> Type { Type::new_extension(int_custom_type(width_power)) } -const fn is_valid_width(n: u8) -> bool { - (n <= (1u8 << (POWERS_OF_TWO - 1))) && ((n & (n - 1)) == 0) +const fn is_valid_log_width(n: u8) -> bool { + n < POWERS_OF_TWO } -const POWERS_OF_TWO: u64 = 8; +const POWERS_OF_TWO: u8 = 8; /// Type parameter for the log width of the integer. -pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO); +pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO as u64); /// Get the bit width of the specified integer type, or error if the width is not supported. pub fn get_width_power(arg: &TypeArg) -> u8 { match arg { - TypeArg::BoundedUSize(n) if *n < POWERS_OF_TWO => *n as u8, + TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => *n as u8, _ => panic!("type check should prevent this."), } } @@ -52,62 +52,64 @@ pub fn get_width_power(arg: &TypeArg) -> u8 { /// An unsigned integer #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ConstIntU { - width: u8, + log_width: u8, value: u128, } /// A signed integer #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ConstIntS { - width: u8, + log_width: u8, value: i128, } impl ConstIntU { /// Create a new [`ConstIntU`] - pub fn new(width: u8, value: u128) -> Result { - if !is_valid_width(width) { + pub fn new(log_width: u8, value: u128) -> Result { + if !is_valid_log_width(log_width) { return Err(ConstTypeError::CustomCheckFail( crate::types::CustomCheckFailure::Message("Invalid integer width.".to_owned()), )); } - if (width <= 64) && (value >= (1u128 << width)) { + if (log_width <= 6) && (value >= (1u128 << (1u8 << log_width))) { return Err(ConstTypeError::CustomCheckFail( crate::types::CustomCheckFailure::Message( "Invalid unsigned integer value.".to_owned(), ), )); } - Ok(Self { width, value }) + Ok(Self { log_width, value }) } } impl ConstIntS { /// Create a new [`ConstIntS`] - pub fn new(width: u8, value: i128) -> Result { - if !is_valid_width(width) { + pub fn new(log_width: u8, value: i128) -> Result { + if !is_valid_log_width(log_width) { return Err(ConstTypeError::CustomCheckFail( crate::types::CustomCheckFailure::Message("Invalid integer width.".to_owned()), )); } - if (width <= 64) && (value >= (1i128 << (width - 1)) || value < -(1i128 << (width - 1))) { + let width = 1u8 << log_width; + if (log_width <= 6) && (value >= (1i128 << (width - 1)) || value < -(1i128 << (width - 1))) + { return Err(ConstTypeError::CustomCheckFail( crate::types::CustomCheckFailure::Message( "Invalid signed integer value.".to_owned(), ), )); } - Ok(Self { width, value }) + Ok(Self { log_width, value }) } } #[typetag::serde] impl CustomConst for ConstIntU { fn name(&self) -> SmolStr { - format!("u{}({})", self.width, self.value).into() + format!("u{}({})", self.log_width, self.value).into() } fn check_custom_type(&self, typ: &CustomType) -> Result<(), CustomCheckFailure> { - if typ.clone() == int_custom_type(self.width) { + if typ.clone() == int_custom_type(self.log_width) { Ok(()) } else { Err(CustomCheckFailure::Message( @@ -123,10 +125,10 @@ impl CustomConst for ConstIntU { #[typetag::serde] impl CustomConst for ConstIntS { fn name(&self) -> SmolStr { - format!("i{}({})", self.width, self.value).into() + format!("i{}({})", self.log_width, self.value).into() } fn check_custom_type(&self, typ: &CustomType) -> Result<(), CustomCheckFailure> { - if typ.clone() == int_custom_type(self.width) { + if typ.clone() == int_custom_type(self.log_width) { Ok(()) } else { Err(CustomCheckFailure::Message( @@ -182,14 +184,14 @@ mod test { #[test] fn test_int_consts() { - let const_u32_7 = ConstIntU::new(32, 7); - let const_u64_7 = ConstIntU::new(64, 7); - let const_u32_8 = ConstIntU::new(32, 8); + let const_u32_7 = ConstIntU::new(5, 7); + let const_u64_7 = ConstIntU::new(6, 7); + let const_u32_8 = ConstIntU::new(5, 8); assert_ne!(const_u32_7, const_u64_7); assert_ne!(const_u32_7, const_u32_8); - assert_eq!(const_u32_7, ConstIntU::new(32, 7)); + assert_eq!(const_u32_7, ConstIntU::new(5, 7)); assert_matches!( - ConstIntU::new(8, 256), + ConstIntU::new(3, 256), Err(ConstTypeError::CustomCheckFail(_)) ); assert_matches!( @@ -197,9 +199,9 @@ mod test { Err(ConstTypeError::CustomCheckFail(_)) ); assert_matches!( - ConstIntS::new(8, 128), + ConstIntS::new(3, 128), Err(ConstTypeError::CustomCheckFail(_)) ); - assert_matches!(ConstIntS::new(8, -128), Ok(_)); + assert_matches!(ConstIntS::new(3, -128), Ok(_)); } } From 43b4432bfe366a5720b9676aab66f6b21e54f2b2 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 14:36:39 +0100 Subject: [PATCH 04/14] pass args to integer directly --- src/std_extensions/arithmetic/conversions.rs | 8 ++- src/std_extensions/arithmetic/int_ops.rs | 57 ++++++++------------ src/std_extensions/arithmetic/int_types.rs | 46 ++++++++-------- 3 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/std_extensions/arithmetic/conversions.rs b/src/std_extensions/arithmetic/conversions.rs index 48901c7c1..9224c591a 100644 --- a/src/std_extensions/arithmetic/conversions.rs +++ b/src/std_extensions/arithmetic/conversions.rs @@ -16,18 +16,17 @@ use crate::{ }; use super::float_types::FLOAT64_TYPE; -use super::int_types::{get_width_power, int_type}; +use super::int_types::int_type; /// The extension identifier. pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.conversions"); fn ftoi_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width_power(arg); Ok(( type_row![FLOAT64_TYPE], vec![Type::new_sum(vec![ - int_type(n), + int_type(arg.clone()), crate::extension::prelude::ERROR_TYPE, ])] .into(), @@ -37,9 +36,8 @@ fn ftoi_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn itof_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width_power(arg); Ok(( - vec![int_type(n)].into(), + vec![int_type(arg.clone())].into(), type_row![FLOAT64_TYPE], ExtensionSet::default(), )) diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index b412288ba..f0a667eed 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use super::int_types::{get_width_power, int_type}; +use super::int_types::{get_width_power, int_type, type_arg}; use crate::extension::prelude::{BOOL_T, ERROR_TYPE}; use crate::type_row; use crate::types::type_param::TypeParam; @@ -18,35 +18,35 @@ pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.int"); fn iwiden_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width_power(arg0); - let n: u8 = get_width_power(arg1); + let m: u8 = get_width_power(arg0)?; + let n: u8 = get_width_power(arg1)?; if m > n { return Err(SignatureError::InvalidTypeArgs); } Ok(( - vec![int_type(m)].into(), - vec![int_type(n)].into(), + vec![int_type(arg0.clone())].into(), + vec![int_type(arg1.clone())].into(), ExtensionSet::default(), )) } fn inarrow_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width_power(arg0); - let n: u8 = get_width_power(arg1); + let m: u8 = get_width_power(arg0)?; + let n: u8 = get_width_power(arg1)?; if m < n { return Err(SignatureError::InvalidTypeArgs); } Ok(( - vec![int_type(m)].into(), - vec![Type::new_sum(vec![int_type(n), ERROR_TYPE])].into(), + vec![int_type(arg0.clone())].into(), + vec![Type::new_sum(vec![int_type(arg1.clone()), ERROR_TYPE])].into(), ExtensionSet::default(), )) } fn itob_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { Ok(( - vec![int_type(1)].into(), + vec![int_type(type_arg(1))].into(), type_row![BOOL_T], ExtensionSet::default(), )) @@ -55,16 +55,15 @@ fn itob_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn btoi_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { Ok(( type_row![BOOL_T], - vec![int_type(1)].into(), + vec![int_type(type_arg(1))].into(), ExtensionSet::default(), )) } fn icmp_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width_power(arg); Ok(( - vec![int_type(n); 2].into(), + vec![int_type(arg.clone()); 2].into(), type_row![BOOL_T], ExtensionSet::default(), )) @@ -72,29 +71,25 @@ fn icmp_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn ibinop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width_power(arg); Ok(( - vec![int_type(n); 2].into(), - vec![int_type(n)].into(), + vec![int_type(arg.clone()); 2].into(), + vec![int_type(arg.clone())].into(), ExtensionSet::default(), )) } fn iunop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg] = collect_array(arg_values); - let n: u8 = get_width_power(arg); Ok(( - vec![int_type(n)].into(), - vec![int_type(n)].into(), + vec![int_type(arg.clone())].into(), + vec![int_type(arg.clone())].into(), ExtensionSet::default(), )) } fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width_power(arg0); - let m: u8 = get_width_power(arg1); - let intpair: TypeRow = vec![int_type(n), int_type(m)].into(); + let intpair: TypeRow = vec![int_type(arg1.clone()), int_type(arg0.clone())].into(); Ok(( intpair.clone(), vec![Type::new_sum(vec![Type::new_tuple(intpair), ERROR_TYPE])].into(), @@ -104,33 +99,27 @@ fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet fn idiv_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width_power(arg0); - let m: u8 = get_width_power(arg1); Ok(( - vec![int_type(n), int_type(m)].into(), - vec![Type::new_sum(vec![int_type(n), ERROR_TYPE])].into(), + vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), + vec![Type::new_sum(vec![int_type(arg1.clone()), ERROR_TYPE])].into(), ExtensionSet::default(), )) } fn imod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width_power(arg0); - let m: u8 = get_width_power(arg1); Ok(( - vec![int_type(n), int_type(m)].into(), - vec![Type::new_sum(vec![int_type(m), ERROR_TYPE])].into(), + vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), + vec![Type::new_sum(vec![int_type(arg0.clone()), ERROR_TYPE])].into(), ExtensionSet::default(), )) } fn ish_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let n: u8 = get_width_power(arg0); - let m: u8 = get_width_power(arg1); Ok(( - vec![int_type(n), int_type(m)].into(), - vec![int_type(n)].into(), + vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), + vec![int_type(arg1.clone())].into(), ExtensionSet::default(), )) } diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 16fd91d30..893f20f3e 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -4,7 +4,7 @@ use smol_str::SmolStr; use crate::{ types::{ - type_param::{TypeArg, TypeParam}, + type_param::{TypeArg, TypeArgError, TypeParam}, ConstTypeError, CustomCheckFailure, CustomType, Type, TypeBound, }, values::CustomConst, @@ -14,23 +14,18 @@ use crate::{ /// The extension identifier. pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.int.types"); -/// Identfier for the integer type. +/// Identifier for the integer type. const INT_TYPE_ID: SmolStr = SmolStr::new_inline("int"); -fn int_custom_type(n: u8) -> CustomType { - CustomType::new( - INT_TYPE_ID, - [TypeArg::BoundedUSize(n as u64)], - EXTENSION_ID, - TypeBound::Copyable, - ) +fn int_custom_type(width_arg: TypeArg) -> CustomType { + CustomType::new(INT_TYPE_ID, [width_arg], EXTENSION_ID, TypeBound::Copyable) } /// Integer type of a given bit width. /// Depending on the operation, the semantic interpretation may be unsigned integer, signed integer /// or bit string. -pub fn int_type(width_power: u8) -> Type { - Type::new_extension(int_custom_type(width_power)) +pub fn int_type(width_arg: TypeArg) -> Type { + Type::new_extension(int_custom_type(width_arg)) } const fn is_valid_log_width(n: u8) -> bool { @@ -42,13 +37,19 @@ const POWERS_OF_TWO: u8 = 8; pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO as u64); /// Get the bit width of the specified integer type, or error if the width is not supported. -pub fn get_width_power(arg: &TypeArg) -> u8 { +pub(super) fn get_width_power(arg: &TypeArg) -> Result { match arg { - TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => *n as u8, - _ => panic!("type check should prevent this."), + TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), + _ => Err(TypeArgError::TypeMismatch { + arg: arg.clone(), + param: LOG_WIDTH_TYPE_PARAM, + }), } } +pub(super) const fn type_arg(log_width: u8) -> TypeArg { + TypeArg::BoundedUSize(log_width as u64) +} /// An unsigned integer #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ConstIntU { @@ -109,7 +110,7 @@ impl CustomConst for ConstIntU { format!("u{}({})", self.log_width, self.value).into() } fn check_custom_type(&self, typ: &CustomType) -> Result<(), CustomCheckFailure> { - if typ.clone() == int_custom_type(self.log_width) { + if typ.clone() == int_custom_type(type_arg(self.log_width)) { Ok(()) } else { Err(CustomCheckFailure::Message( @@ -128,7 +129,7 @@ impl CustomConst for ConstIntS { format!("i{}({})", self.log_width, self.value).into() } fn check_custom_type(&self, typ: &CustomType) -> Result<(), CustomCheckFailure> { - if typ.clone() == int_custom_type(self.log_width) { + if typ.clone() == int_custom_type(type_arg(self.log_width)) { Ok(()) } else { Err(CustomCheckFailure::Message( @@ -159,7 +160,7 @@ pub fn extension() -> Extension { #[cfg(test)] mod test { - use cool_asserts::{assert_matches, assert_panics}; + use cool_asserts::assert_matches; use super::*; @@ -174,12 +175,15 @@ mod test { #[test] fn test_int_widths() { let type_arg_32 = TypeArg::BoundedUSize(5); - assert_matches!(get_width_power(&type_arg_32), 5); + assert_matches!(get_width_power(&type_arg_32), Ok(5)); let type_arg_128 = TypeArg::BoundedUSize(7); - assert_matches!(get_width_power(&type_arg_128), 7); - - assert_panics!(get_width_power(&TypeArg::BoundedUSize(8))); + assert_matches!(get_width_power(&type_arg_128), Ok(7)); + let type_arg_256 = TypeArg::BoundedUSize(8); + assert_matches!( + get_width_power(&type_arg_256), + Err(TypeArgError::TypeMismatch { .. }) + ); } #[test] From db5c4f47596fe2097c0921c9fbe797e17a3ec67c Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 14:40:03 +0100 Subject: [PATCH 05/14] change bound to maximum to be consistent with underlying int and fix doclinks --- src/std_extensions/arithmetic/int_types.rs | 4 ++-- src/types/type_param.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 893f20f3e..54b83316e 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -29,10 +29,10 @@ pub fn int_type(width_arg: TypeArg) -> Type { } const fn is_valid_log_width(n: u8) -> bool { - n < POWERS_OF_TWO + n <= POWERS_OF_TWO } -const POWERS_OF_TWO: u8 = 8; +const POWERS_OF_TWO: u8 = 7; /// Type parameter for the log width of the integer. pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO as u64); diff --git a/src/types/type_param.rs b/src/types/type_param.rs index cac0d214b..bc0a6d170 100644 --- a/src/types/type_param.rs +++ b/src/types/type_param.rs @@ -19,7 +19,7 @@ use super::TypeBound; pub enum TypeParam { /// Argument is a [TypeArg::Type]. Type(TypeBound), - /// Argument is a [TypeArg::USize] that is less than the stated bound. + /// Argument is a [TypeArg::BoundedUSize] that is at most the stated maximum. BoundedUSize(u64), /// Argument is a [TypeArg::Opaque], defined by a [CustomType]. Opaque(CustomType), @@ -46,7 +46,7 @@ impl TypeParam { pub enum TypeArg { /// Where the (Type/Op)Def declares that an argument is a [TypeParam::Type] Type(Type), - /// Instance of [TypeParam::USize]. 64-bit unsigned integer. + /// Instance of [TypeParam::BoundedUSize]. 64-bit unsigned integer. BoundedUSize(u64), ///Instance of [TypeParam::Opaque] An opaque value, stored as serialized blob. Opaque(CustomTypeArg), @@ -99,7 +99,7 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr .try_for_each(|(arg, param)| check_type_arg(arg, param)) } } - (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(bound)) if val < bound => Ok(()), + (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(max)) if val <= max => Ok(()), (TypeArg::Opaque(arg), TypeParam::Opaque(param)) if param.bound() == TypeBound::Eq && &arg.typ == param => { From 66f74a0044e020ca361fdf50eb9cfa9c93282b04 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:03:29 +0100 Subject: [PATCH 06/14] fix incorrect arguments Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> --- src/std_extensions/arithmetic/int_ops.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index f0a667eed..c3cf07249 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -89,7 +89,7 @@ fn iunop_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let intpair: TypeRow = vec![int_type(arg1.clone()), int_type(arg0.clone())].into(); + let intpair: TypeRow = vec![int_type(arg0.clone()), int_type(arg1.clone())].into(); Ok(( intpair.clone(), vec![Type::new_sum(vec![Type::new_tuple(intpair), ERROR_TYPE])].into(), @@ -100,8 +100,8 @@ fn idivmod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet fn idiv_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); Ok(( - vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), - vec![Type::new_sum(vec![int_type(arg1.clone()), ERROR_TYPE])].into(), + vec![int_type(arg0.clone()), int_type(arg1.clone())].into(), + vec![Type::new_sum(vec![int_type(arg0.clone()), ERROR_TYPE])].into(), ExtensionSet::default(), )) } @@ -109,8 +109,8 @@ fn idiv_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn imod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); Ok(( - vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), - vec![Type::new_sum(vec![int_type(arg0.clone()), ERROR_TYPE])].into(), + vec![int_type(arg0.clone()), int_type(arg1.clone())].into(), + vec![Type::new_sum(vec![int_type(arg1.clone()), ERROR_TYPE])].into(), ExtensionSet::default(), )) } @@ -118,8 +118,8 @@ fn imod_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn ish_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); Ok(( - vec![int_type(arg1.clone()), int_type(arg0.clone())].into(), - vec![int_type(arg1.clone())].into(), + vec![int_type(arg0.clone()), int_type(arg1.clone())].into(), + vec![int_type(arg0.clone())].into(), ExtensionSet::default(), )) } From b659bcc59e2d05b936e1c38e28f8ea289f2496e7 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:06:33 +0100 Subject: [PATCH 07/14] use `log_width` more --- src/std_extensions/arithmetic/int_ops.rs | 10 +++++----- src/std_extensions/arithmetic/int_types.rs | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index c3cf07249..dfa11e410 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use super::int_types::{get_width_power, int_type, type_arg}; +use super::int_types::{get_log_width, int_type, type_arg}; use crate::extension::prelude::{BOOL_T, ERROR_TYPE}; use crate::type_row; use crate::types::type_param::TypeParam; @@ -18,8 +18,8 @@ pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.int"); fn iwiden_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width_power(arg0)?; - let n: u8 = get_width_power(arg1)?; + let m: u8 = get_log_width(arg0)?; + let n: u8 = get_log_width(arg1)?; if m > n { return Err(SignatureError::InvalidTypeArgs); } @@ -32,8 +32,8 @@ fn iwiden_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet) fn inarrow_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { let [arg0, arg1] = collect_array(arg_values); - let m: u8 = get_width_power(arg0)?; - let n: u8 = get_width_power(arg1)?; + let m: u8 = get_log_width(arg0)?; + let n: u8 = get_log_width(arg1)?; if m < n { return Err(SignatureError::InvalidTypeArgs); } diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 54b83316e..282d756f8 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -29,15 +29,15 @@ pub fn int_type(width_arg: TypeArg) -> Type { } const fn is_valid_log_width(n: u8) -> bool { - n <= POWERS_OF_TWO + n <= MAX_LOG_WIDTH } -const POWERS_OF_TWO: u8 = 7; +const MAX_LOG_WIDTH: u8 = 7; /// Type parameter for the log width of the integer. -pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(POWERS_OF_TWO as u64); +pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(MAX_LOG_WIDTH as u64); /// Get the bit width of the specified integer type, or error if the width is not supported. -pub(super) fn get_width_power(arg: &TypeArg) -> Result { +pub(super) fn get_log_width(arg: &TypeArg) -> Result { match arg { TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), _ => Err(TypeArgError::TypeMismatch { @@ -175,13 +175,13 @@ mod test { #[test] fn test_int_widths() { let type_arg_32 = TypeArg::BoundedUSize(5); - assert_matches!(get_width_power(&type_arg_32), Ok(5)); + assert_matches!(get_log_width(&type_arg_32), Ok(5)); let type_arg_128 = TypeArg::BoundedUSize(7); - assert_matches!(get_width_power(&type_arg_128), Ok(7)); + assert_matches!(get_log_width(&type_arg_128), Ok(7)); let type_arg_256 = TypeArg::BoundedUSize(8); assert_matches!( - get_width_power(&type_arg_256), + get_log_width(&type_arg_256), Err(TypeArgError::TypeMismatch { .. }) ); } From 3033406d18634f9ae434f6c1543899f557ea8395 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:21:27 +0100 Subject: [PATCH 08/14] fix bug in unary ops --- src/std_extensions/arithmetic/int_ops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index dfa11e410..47b0a0343 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -46,7 +46,7 @@ fn inarrow_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet fn itob_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { Ok(( - vec![int_type(type_arg(1))].into(), + vec![int_type(type_arg(0))].into(), type_row![BOOL_T], ExtensionSet::default(), )) @@ -55,7 +55,7 @@ fn itob_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), fn btoi_sig(_arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> { Ok(( type_row![BOOL_T], - vec![int_type(type_arg(1))].into(), + vec![int_type(type_arg(0))].into(), ExtensionSet::default(), )) } From 007967ba82ac36ece97bbdec6b1e1bdeea58b43a Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:23:09 +0100 Subject: [PATCH 09/14] use correct type param for int ops --- src/std_extensions/arithmetic/conversions.rs | 15 ++-- src/std_extensions/arithmetic/int_ops.rs | 77 ++++++++++---------- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/std_extensions/arithmetic/conversions.rs b/src/std_extensions/arithmetic/conversions.rs index 9224c591a..c2cad2fa0 100644 --- a/src/std_extensions/arithmetic/conversions.rs +++ b/src/std_extensions/arithmetic/conversions.rs @@ -7,16 +7,13 @@ use smol_str::SmolStr; use crate::{ extension::{ExtensionSet, SignatureError}, type_row, - types::{ - type_param::{TypeArg, TypeParam}, - Type, TypeRow, - }, + types::{type_param::TypeArg, Type, TypeRow}, utils::collect_array, Extension, }; -use super::float_types::FLOAT64_TYPE; use super::int_types::int_type; +use super::{float_types::FLOAT64_TYPE, int_types::LOG_WIDTH_TYPE_PARAM}; /// The extension identifier. pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.conversions"); @@ -57,7 +54,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "trunc_u".into(), "float to unsigned int".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ftoi_sig, ) .unwrap(); @@ -65,7 +62,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "trunc_s".into(), "float to signed int".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ftoi_sig, ) .unwrap(); @@ -73,7 +70,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "convert_u".into(), "unsigned int to float".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], itof_sig, ) .unwrap(); @@ -81,7 +78,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "convert_s".into(), "signed int to float".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], itof_sig, ) .unwrap(); diff --git a/src/std_extensions/arithmetic/int_ops.rs b/src/std_extensions/arithmetic/int_ops.rs index 47b0a0343..eae8847de 100644 --- a/src/std_extensions/arithmetic/int_ops.rs +++ b/src/std_extensions/arithmetic/int_ops.rs @@ -2,10 +2,9 @@ use smol_str::SmolStr; -use super::int_types::{get_log_width, int_type, type_arg}; +use super::int_types::{get_log_width, int_type, type_arg, LOG_WIDTH_TYPE_PARAM}; use crate::extension::prelude::{BOOL_T, ERROR_TYPE}; use crate::type_row; -use crate::types::type_param::TypeParam; use crate::utils::collect_array; use crate::{ extension::{ExtensionSet, SignatureError}, @@ -135,7 +134,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iwiden_u".into(), "widen an unsigned integer to a wider one with the same value".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], iwiden_sig, ) .unwrap(); @@ -143,7 +142,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iwiden_s".into(), "widen a signed integer to a wider one with the same value".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], iwiden_sig, ) .unwrap(); @@ -152,7 +151,7 @@ pub fn extension() -> Extension { "inarrow_u".into(), "narrow an unsigned integer to a narrower one with the same value if possible" .to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], inarrow_sig, ) .unwrap(); @@ -160,7 +159,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "inarrow_s".into(), "narrow a signed integer to a narrower one with the same value if possible".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], inarrow_sig, ) .unwrap(); @@ -184,7 +183,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ieq".into(), "equality test".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -192,7 +191,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ine".into(), "inequality test".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -200,7 +199,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ilt_u".into(), "\"less than\" as unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -208,7 +207,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ilt_s".into(), "\"less than\" as signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -216,7 +215,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "igt_u".into(), "\"greater than\" as unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -224,7 +223,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "igt_s".into(), "\"greater than\" as signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -232,7 +231,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ile_u".into(), "\"less than or equal\" as unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -240,7 +239,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ile_s".into(), "\"less than or equal\" as signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -248,7 +247,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ige_u".into(), "\"greater than or equal\" as unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -256,7 +255,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ige_s".into(), "\"greater than or equal\" as signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], icmp_sig, ) .unwrap(); @@ -264,7 +263,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imax_u".into(), "maximum of unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -272,7 +271,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imax_s".into(), "maximum of signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -280,7 +279,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imin_u".into(), "minimum of unsigned integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -288,7 +287,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imin_s".into(), "minimum of signed integers".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -296,7 +295,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iadd".into(), "addition modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -304,7 +303,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "isub".into(), "subtraction modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -312,7 +311,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ineg".into(), "negation modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], iunop_sig, ) .unwrap(); @@ -320,7 +319,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imul".into(), "multiplication modulo 2^N (signed and unsigned versions are the same op)".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -330,7 +329,7 @@ pub fn extension() -> Extension { "given unsigned integers 0 <= n < 2^N, 0 <= m < 2^M, generates unsigned q, r where \ q*m+r=n, 0<=r Extension { "given signed integer -2^{N-1} <= n < 2^{N-1} and unsigned 0 <= m < 2^M, generates \ signed q and unsigned r where q*m+r=n, 0<=r Extension { .add_op_custom_sig_simple( "idiv_u".into(), "as idivmod_u but discarding the second output".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], idiv_sig, ) .unwrap(); @@ -356,7 +355,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imod_u".into(), "as idivmod_u but discarding the first output".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], idiv_sig, ) .unwrap(); @@ -364,7 +363,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "idiv_s".into(), "as idivmod_s but discarding the second output".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], imod_sig, ) .unwrap(); @@ -372,7 +371,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "imod_s".into(), "as idivmod_s but discarding the first output".to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], imod_sig, ) .unwrap(); @@ -380,7 +379,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iabs".into(), "convert signed to unsigned by taking absolute value".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], iunop_sig, ) .unwrap(); @@ -388,7 +387,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "iand".into(), "bitwise AND".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -396,7 +395,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ior".into(), "bitwise OR".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -404,7 +403,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "ixor".into(), "bitwise XOR".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], ibinop_sig, ) .unwrap(); @@ -412,7 +411,7 @@ pub fn extension() -> Extension { .add_op_custom_sig_simple( "inot".into(), "bitwise NOT".to_owned(), - vec![TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM], iunop_sig, ) .unwrap(); @@ -422,7 +421,7 @@ pub fn extension() -> Extension { "shift first input left by k bits where k is unsigned interpretation of second input \ (leftmost bits dropped, rightmost bits set to zero" .to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], ish_sig, ) .unwrap(); @@ -432,7 +431,7 @@ pub fn extension() -> Extension { "shift first input right by k bits where k is unsigned interpretation of second input \ (rightmost bits dropped, leftmost bits set to zero)" .to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], ish_sig, ) .unwrap(); @@ -442,7 +441,7 @@ pub fn extension() -> Extension { "rotate first input left by k bits where k is unsigned interpretation of second input \ (leftmost bits replace rightmost bits)" .to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], ish_sig, ) .unwrap(); @@ -452,7 +451,7 @@ pub fn extension() -> Extension { "rotate first input right by k bits where k is unsigned interpretation of second input \ (rightmost bits replace leftmost bits)" .to_owned(), - vec![TypeParam::max_usize(), TypeParam::max_usize()], + vec![LOG_WIDTH_TYPE_PARAM, LOG_WIDTH_TYPE_PARAM], ish_sig, ) .unwrap(); From e3a31825f72a1cc9470b1bc28b6d6efd5d5f4cc2 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:36:12 +0100 Subject: [PATCH 10/14] define array of valid integer types --- src/std_extensions/arithmetic/int_types.rs | 21 ++++++++++++++++----- src/std_extensions/arithmetic/mod.rs | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 282d756f8..7a9e463f1 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -10,7 +10,7 @@ use crate::{ values::CustomConst, Extension, }; - +use lazy_static::lazy_static; /// The extension identifier. pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("arithmetic.int.types"); @@ -21,22 +21,33 @@ fn int_custom_type(width_arg: TypeArg) -> CustomType { CustomType::new(INT_TYPE_ID, [width_arg], EXTENSION_ID, TypeBound::Copyable) } -/// Integer type of a given bit width. +/// Integer type of a given bit width (specified by the TypeArg). /// Depending on the operation, the semantic interpretation may be unsigned integer, signed integer /// or bit string. -pub fn int_type(width_arg: TypeArg) -> Type { +pub(super) fn int_type(width_arg: TypeArg) -> Type { Type::new_extension(int_custom_type(width_arg)) } +lazy_static! { + /// Array of valid integer types, indexed by log width of the integer. + pub static ref INT_TYPES: [Type; (MAX_LOG_WIDTH + 1) as usize] = (0..MAX_LOG_WIDTH + 1) + .map(|i| int_type(TypeArg::BoundedUSize(i as u64))) + .collect::>() + .try_into() + .unwrap(); +} + const fn is_valid_log_width(n: u8) -> bool { n <= MAX_LOG_WIDTH } -const MAX_LOG_WIDTH: u8 = 7; +/// The largest allowed log width. +pub const MAX_LOG_WIDTH: u8 = 7; /// Type parameter for the log width of the integer. pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(MAX_LOG_WIDTH as u64); -/// Get the bit width of the specified integer type, or error if the width is not supported. +/// Get the log width of the specified type argument or error if the argument +/// is invalid.. pub(super) fn get_log_width(arg: &TypeArg) -> Result { match arg { TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), diff --git a/src/std_extensions/arithmetic/mod.rs b/src/std_extensions/arithmetic/mod.rs index 1d717eed5..b0cc79d87 100644 --- a/src/std_extensions/arithmetic/mod.rs +++ b/src/std_extensions/arithmetic/mod.rs @@ -5,3 +5,23 @@ pub mod float_ops; pub mod float_types; pub mod int_ops; pub mod int_types; + +#[cfg(test)] +mod test { + use crate::{ + std_extensions::arithmetic::int_types::{int_type, INT_TYPES}, + types::type_param::TypeArg, + }; + + use super::int_types::MAX_LOG_WIDTH; + + #[test] + fn test_int_types() { + for i in 0..MAX_LOG_WIDTH + 1 { + assert_eq!( + INT_TYPES[i as usize], + int_type(TypeArg::BoundedUSize(i as u64)) + ) + } + } +} From 7b2edeadc039f869e1561727a942569b479e83da Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Wed, 23 Aug 2023 17:37:36 +0100 Subject: [PATCH 11/14] edit type params in spec --- specification/hugr.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/hugr.md b/specification/hugr.md index 0632882d5..ca9832447 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -907,17 +907,17 @@ The declaration of the `params` uses a language that is a distinct, simplified form of the [Type System](#type-system) - writing terminals that appear in the YAML in quotes, the value of each member of `params` is given by the following production: ``` -TypeParam ::= "Type"("Any"|"Copy"|"Eq") | "USize" | "Extensions" | "List"(TypeParam) | "Tuple"([TypeParam]) | Opaque +TypeParam ::= "Type"("Any"|"Copy"|"Eq") | "BoundedUSize(u64)" | "Extensions" | "List"(TypeParam) | "Tuple"([TypeParam]) | Opaque Opaque ::= string<[TypeArgs]> -TypeArgs ::= Type(Type) | USize(u64) | Extensions | List([TypeArg]) | Tuple([TypeArg]) +TypeArgs ::= Type(Type) | BoundedUSize(u64) | Extensions | List([TypeArg]) | Tuple([TypeArg]) Type ::= Name<[TypeArg]> ``` (We write `[Foo]` to indicate a list of Foo's; and omit `<>` where the contents is the empty list). -To use an OpDef as an Op, or a TypeDef as a type, the user must provide a type argument for each type param in the def: a type in the appropriate class, a constant usize, a set of extensions, a list or tuple of arguments. +To use an OpDef as an Op, or a TypeDef as a type, the user must provide a type argument for each type param in the def: a type in the appropriate class, a bounded usize, a set of extensions, a list or tuple of arguments. **Implementation note** Reading this format into Rust is made easy by `serde` and [serde\_yaml](https://github.com/dtolnay/serde-yaml) (see the From d2decaa1c0d321915c14ddf59643e7151a56ca1a Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Thu, 24 Aug 2023 09:16:04 +0100 Subject: [PATCH 12/14] fix typo Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> --- src/std_extensions/arithmetic/int_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 7a9e463f1..ce5185fc5 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -47,7 +47,7 @@ pub const MAX_LOG_WIDTH: u8 = 7; pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(MAX_LOG_WIDTH as u64); /// Get the log width of the specified type argument or error if the argument -/// is invalid.. +/// is invalid. pub(super) fn get_log_width(arg: &TypeArg) -> Result { match arg { TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), From d13a4c112165f2a65e2ed93099e3dbe9d82f25dc Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Thu, 24 Aug 2023 10:37:43 +0100 Subject: [PATCH 13/14] use NonZeroU64 to make bound non-exclusive --- src/std_extensions/arithmetic/int_types.rs | 7 ++++- src/types/type_param.rs | 34 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index ce5185fc5..8dd9e4a83 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -1,5 +1,7 @@ //! Basic integer types +use std::num::NonZeroU64; + use smol_str::SmolStr; use crate::{ @@ -43,8 +45,11 @@ const fn is_valid_log_width(n: u8) -> bool { /// The largest allowed log width. pub const MAX_LOG_WIDTH: u8 = 7; + /// Type parameter for the log width of the integer. -pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::BoundedUSize(MAX_LOG_WIDTH as u64); +// unsafe block should be ok as the value is definitely not zero. +pub const LOG_WIDTH_TYPE_PARAM: TypeParam = + TypeParam::bounded_usize(unsafe { NonZeroU64::new_unchecked(MAX_LOG_WIDTH as u64 + 1) }); /// Get the log width of the specified type argument or error if the argument /// is invalid. diff --git a/src/types/type_param.rs b/src/types/type_param.rs index bc0a6d170..87f739855 100644 --- a/src/types/type_param.rs +++ b/src/types/type_param.rs @@ -4,6 +4,8 @@ //! //! [`TypeDef`]: crate::extension::TypeDef +use std::num::NonZeroU64; + use thiserror::Error; use crate::extension::ExtensionSet; @@ -12,6 +14,20 @@ use super::CustomType; use super::Type; use super::TypeBound; +#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] +/// The upper non-inclusive bound of a [`TypeParam::BoundedUsize`] +// A None inner value implies the maximum bound: u64::MAX + 1 (all u64 values valid) +pub struct UpperBound(Option); +impl UpperBound { + fn valid_value(&self, val: u64) -> bool { + match (val, self.0) { + (0, _) | (_, None) => true, + (val, Some(inner)) if NonZeroU64::new(val).unwrap() < inner => true, + _ => false, + } + } +} + /// A parameter declared by an OpDef. Specifies a value /// that must be provided by each operation node. #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] @@ -19,8 +35,8 @@ use super::TypeBound; pub enum TypeParam { /// Argument is a [TypeArg::Type]. Type(TypeBound), - /// Argument is a [TypeArg::BoundedUSize] that is at most the stated maximum. - BoundedUSize(u64), + /// Argument is a [TypeArg::BoundedUSize] that is less than the upper bound. + BoundedUSize(UpperBound), /// Argument is a [TypeArg::Opaque], defined by a [CustomType]. Opaque(CustomType), /// Argument is a [TypeArg::Sequence]. A list of indeterminate size containing parameters. @@ -34,9 +50,14 @@ pub enum TypeParam { } impl TypeParam { - /// [`TypeParam::BoundedUSize`] with the maximum bound (`u64::MAX`) + /// [`TypeParam::BoundedUSize`] with the maximum bound (`u64::MAX` + 1) pub const fn max_usize() -> Self { - Self::BoundedUSize(u64::MAX) + Self::BoundedUSize(UpperBound(None)) + } + + /// [`TypeParam::BoundedUSize`] with the stated upper bound (non-exclusive) + pub const fn bounded_usize(upper_bound: NonZeroU64) -> Self { + Self::BoundedUSize(UpperBound(Some(upper_bound))) } } @@ -99,7 +120,10 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr .try_for_each(|(arg, param)| check_type_arg(arg, param)) } } - (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(max)) if val <= max => Ok(()), + (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(bound)) if bound.valid_value(*val) => { + Ok(()) + } + (TypeArg::Opaque(arg), TypeParam::Opaque(param)) if param.bound() == TypeBound::Eq && &arg.typ == param => { From 373a58172615efcb059272ce154b7b020429ee81 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Thu, 24 Aug 2023 10:40:03 +0100 Subject: [PATCH 14/14] rename BoundedUSize to BoundedNat --- src/extension/prelude.rs | 4 ++-- src/ops/constant.rs | 2 +- src/std_extensions/arithmetic/int_types.rs | 16 +++++++-------- src/std_extensions/arithmetic/mod.rs | 2 +- src/std_extensions/collections.rs | 2 +- src/std_extensions/logic.rs | 8 ++++---- src/types/type_param.rs | 24 +++++++++++----------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/extension/prelude.rs b/src/extension/prelude.rs index 4f74f4f49..a79497a61 100644 --- a/src/extension/prelude.rs +++ b/src/extension/prelude.rs @@ -30,7 +30,7 @@ lazy_static! { prelude .add_type( SmolStr::new_inline("array"), - vec![TypeParam::Type(TypeBound::Any), TypeParam::max_usize()], + vec![TypeParam::Type(TypeBound::Any), TypeParam::max_nat()], "array".into(), TypeDefBound::FromParams(vec![0]), ) @@ -68,7 +68,7 @@ pub(crate) const BOOL_T: Type = Type::new_simple_predicate(2); pub fn new_array(typ: Type, size: u64) -> Type { let array_def = PRELUDE.get_type("array").unwrap(); let custom_t = array_def - .instantiate_concrete(vec![TypeArg::Type(typ), TypeArg::BoundedUSize(size)]) + .instantiate_concrete(vec![TypeArg::Type(typ), TypeArg::BoundedNat(size)]) .unwrap(); Type::new_extension(custom_t) } diff --git a/src/ops/constant.rs b/src/ops/constant.rs index ef057e9c2..6f367d07b 100644 --- a/src/ops/constant.rs +++ b/src/ops/constant.rs @@ -201,7 +201,7 @@ mod test { fn test_yaml_const() { let typ_int = CustomType::new( "mytype", - vec![TypeArg::BoundedUSize(8)], + vec![TypeArg::BoundedNat(8)], "myrsrc", TypeBound::Eq, ); diff --git a/src/std_extensions/arithmetic/int_types.rs b/src/std_extensions/arithmetic/int_types.rs index 8dd9e4a83..4016c7355 100644 --- a/src/std_extensions/arithmetic/int_types.rs +++ b/src/std_extensions/arithmetic/int_types.rs @@ -33,7 +33,7 @@ pub(super) fn int_type(width_arg: TypeArg) -> Type { lazy_static! { /// Array of valid integer types, indexed by log width of the integer. pub static ref INT_TYPES: [Type; (MAX_LOG_WIDTH + 1) as usize] = (0..MAX_LOG_WIDTH + 1) - .map(|i| int_type(TypeArg::BoundedUSize(i as u64))) + .map(|i| int_type(TypeArg::BoundedNat(i as u64))) .collect::>() .try_into() .unwrap(); @@ -47,15 +47,15 @@ const fn is_valid_log_width(n: u8) -> bool { pub const MAX_LOG_WIDTH: u8 = 7; /// Type parameter for the log width of the integer. -// unsafe block should be ok as the value is definitely not zero. +// SAFETY: unsafe block should be ok as the value is definitely not zero. pub const LOG_WIDTH_TYPE_PARAM: TypeParam = - TypeParam::bounded_usize(unsafe { NonZeroU64::new_unchecked(MAX_LOG_WIDTH as u64 + 1) }); + TypeParam::bounded_nat(unsafe { NonZeroU64::new_unchecked(MAX_LOG_WIDTH as u64 + 1) }); /// Get the log width of the specified type argument or error if the argument /// is invalid. pub(super) fn get_log_width(arg: &TypeArg) -> Result { match arg { - TypeArg::BoundedUSize(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), + TypeArg::BoundedNat(n) if is_valid_log_width(*n as u8) => Ok(*n as u8), _ => Err(TypeArgError::TypeMismatch { arg: arg.clone(), param: LOG_WIDTH_TYPE_PARAM, @@ -64,7 +64,7 @@ pub(super) fn get_log_width(arg: &TypeArg) -> Result { } pub(super) const fn type_arg(log_width: u8) -> TypeArg { - TypeArg::BoundedUSize(log_width as u64) + TypeArg::BoundedNat(log_width as u64) } /// An unsigned integer #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] @@ -190,12 +190,12 @@ mod test { #[test] fn test_int_widths() { - let type_arg_32 = TypeArg::BoundedUSize(5); + let type_arg_32 = TypeArg::BoundedNat(5); assert_matches!(get_log_width(&type_arg_32), Ok(5)); - let type_arg_128 = TypeArg::BoundedUSize(7); + let type_arg_128 = TypeArg::BoundedNat(7); assert_matches!(get_log_width(&type_arg_128), Ok(7)); - let type_arg_256 = TypeArg::BoundedUSize(8); + let type_arg_256 = TypeArg::BoundedNat(8); assert_matches!( get_log_width(&type_arg_256), Err(TypeArgError::TypeMismatch { .. }) diff --git a/src/std_extensions/arithmetic/mod.rs b/src/std_extensions/arithmetic/mod.rs index b0cc79d87..76e8263aa 100644 --- a/src/std_extensions/arithmetic/mod.rs +++ b/src/std_extensions/arithmetic/mod.rs @@ -20,7 +20,7 @@ mod test { for i in 0..MAX_LOG_WIDTH + 1 { assert_eq!( INT_TYPES[i as usize], - int_type(TypeArg::BoundedUSize(i as u64)) + int_type(TypeArg::BoundedNat(i as u64)) ) } } diff --git a/src/std_extensions/collections.rs b/src/std_extensions/collections.rs index b31964e37..9718edd9e 100644 --- a/src/std_extensions/collections.rs +++ b/src/std_extensions/collections.rs @@ -160,7 +160,7 @@ mod test { .unwrap(); assert!(list_def - .instantiate_concrete([TypeArg::BoundedUSize(3)]) + .instantiate_concrete([TypeArg::BoundedNat(3)]) .is_err()); list_def.check_custom(&list_type).unwrap(); diff --git a/src/std_extensions/logic.rs b/src/std_extensions/logic.rs index 8187d186b..957985482 100644 --- a/src/std_extensions/logic.rs +++ b/src/std_extensions/logic.rs @@ -27,7 +27,7 @@ pub const EXTENSION_ID: SmolStr = SmolStr::new_inline("logic"); /// Extension for basic logical operations. fn extension() -> Extension { - const H_INT: TypeParam = TypeParam::max_usize(); + const H_INT: TypeParam = TypeParam::max_nat(); let mut extension = Extension::new(EXTENSION_ID); extension @@ -53,7 +53,7 @@ fn extension() -> Extension { |arg_values: &[TypeArg]| { let a = arg_values.iter().exactly_one().unwrap(); let n: u64 = match a { - TypeArg::BoundedUSize(n) => *n, + TypeArg::BoundedNat(n) => *n, _ => { return Err(TypeArgError::TypeMismatch { arg: a.clone(), @@ -79,7 +79,7 @@ fn extension() -> Extension { |arg_values: &[TypeArg]| { let a = arg_values.iter().exactly_one().unwrap(); let n: u64 = match a { - TypeArg::BoundedUSize(n) => *n, + TypeArg::BoundedNat(n) => *n, _ => { return Err(TypeArgError::TypeMismatch { arg: a.clone(), @@ -139,7 +139,7 @@ pub(crate) mod test { /// Generate a logic extension and operation over [`crate::prelude::BOOL_T`] pub(crate) fn and_op() -> LeafOp { EXTENSION - .instantiate_extension_op(AND_NAME, [TypeArg::BoundedUSize(2)]) + .instantiate_extension_op(AND_NAME, [TypeArg::BoundedNat(2)]) .unwrap() .into() } diff --git a/src/types/type_param.rs b/src/types/type_param.rs index 87f739855..fcf02b103 100644 --- a/src/types/type_param.rs +++ b/src/types/type_param.rs @@ -15,7 +15,7 @@ use super::Type; use super::TypeBound; #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] -/// The upper non-inclusive bound of a [`TypeParam::BoundedUsize`] +/// The upper non-inclusive bound of a [`TypeParam::BoundedNat`] // A None inner value implies the maximum bound: u64::MAX + 1 (all u64 values valid) pub struct UpperBound(Option); impl UpperBound { @@ -35,8 +35,8 @@ impl UpperBound { pub enum TypeParam { /// Argument is a [TypeArg::Type]. Type(TypeBound), - /// Argument is a [TypeArg::BoundedUSize] that is less than the upper bound. - BoundedUSize(UpperBound), + /// Argument is a [TypeArg::BoundedNat] that is less than the upper bound. + BoundedNat(UpperBound), /// Argument is a [TypeArg::Opaque], defined by a [CustomType]. Opaque(CustomType), /// Argument is a [TypeArg::Sequence]. A list of indeterminate size containing parameters. @@ -50,14 +50,14 @@ pub enum TypeParam { } impl TypeParam { - /// [`TypeParam::BoundedUSize`] with the maximum bound (`u64::MAX` + 1) - pub const fn max_usize() -> Self { - Self::BoundedUSize(UpperBound(None)) + /// [`TypeParam::BoundedNat`] with the maximum bound (`u64::MAX` + 1) + pub const fn max_nat() -> Self { + Self::BoundedNat(UpperBound(None)) } - /// [`TypeParam::BoundedUSize`] with the stated upper bound (non-exclusive) - pub const fn bounded_usize(upper_bound: NonZeroU64) -> Self { - Self::BoundedUSize(UpperBound(Some(upper_bound))) + /// [`TypeParam::BoundedNat`] with the stated upper bound (non-exclusive) + pub const fn bounded_nat(upper_bound: NonZeroU64) -> Self { + Self::BoundedNat(UpperBound(Some(upper_bound))) } } @@ -67,8 +67,8 @@ impl TypeParam { pub enum TypeArg { /// Where the (Type/Op)Def declares that an argument is a [TypeParam::Type] Type(Type), - /// Instance of [TypeParam::BoundedUSize]. 64-bit unsigned integer. - BoundedUSize(u64), + /// Instance of [TypeParam::BoundedNat]. 64-bit unsigned integer. + BoundedNat(u64), ///Instance of [TypeParam::Opaque] An opaque value, stored as serialized blob. Opaque(CustomTypeArg), /// Instance of [TypeParam::List] or [TypeParam::Tuple], defined by a @@ -120,7 +120,7 @@ pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgErr .try_for_each(|(arg, param)| check_type_arg(arg, param)) } } - (TypeArg::BoundedUSize(val), TypeParam::BoundedUSize(bound)) if bound.valid_value(*val) => { + (TypeArg::BoundedNat(val), TypeParam::BoundedNat(bound)) if bound.valid_value(*val) => { Ok(()) }