diff --git a/hugr-core/src/ops/custom.rs b/hugr-core/src/ops/custom.rs index e9607e8e3..6d9a3b2b2 100644 --- a/hugr-core/src/ops/custom.rs +++ b/hugr-core/src/ops/custom.rs @@ -351,15 +351,13 @@ pub enum OpaqueOpError { #[cfg(test)] mod test { + use crate::std_extensions::arithmetic::conversions::{self, CONVERT_OPS_REGISTRY}; use crate::{ extension::{ prelude::{BOOL_T, QB_T, USIZE_T}, SignatureFunc, }, - std_extensions::arithmetic::{ - int_ops::{self, INT_OPS_REGISTRY}, - int_types::INT_TYPES, - }, + std_extensions::arithmetic::int_types::INT_TYPES, types::FuncValueType, Extension, }; @@ -387,10 +385,10 @@ mod test { #[test] fn resolve_opaque_op() { - let registry = &INT_OPS_REGISTRY; + let registry = &CONVERT_OPS_REGISTRY; let i0 = &INT_TYPES[0]; let opaque = OpaqueOp::new( - int_ops::EXTENSION_ID, + conversions::EXTENSION_ID, "itobool", "description".into(), vec![], diff --git a/hugr-core/src/std_extensions/arithmetic/conversions.rs b/hugr-core/src/std_extensions/arithmetic/conversions.rs index 06a06abed..2db324312 100644 --- a/hugr-core/src/std_extensions/arithmetic/conversions.rs +++ b/hugr-core/src/std_extensions/arithmetic/conversions.rs @@ -2,7 +2,11 @@ use strum_macros::{EnumIter, EnumString, IntoStaticStr}; +use crate::extension::prelude::{BOOL_T, STRING_TYPE, USIZE_T}; +use crate::extension::simple_op::{HasConcrete, HasDef}; use crate::ops::OpName; +use crate::std_extensions::arithmetic::int_ops::int_polytype; +use crate::std_extensions::arithmetic::int_types::int_type; use crate::{ extension::{ prelude::sum_with_error, @@ -12,12 +16,12 @@ use crate::{ }, ops::{custom::ExtensionOp, NamedOp}, type_row, - types::{FuncValueType, PolyFuncTypeRV, TypeArg, TypeRV}, + types::{TypeArg, TypeRV}, Extension, }; -use super::int_types::int_tv; -use super::{float_types::FLOAT64_TYPE, int_types::LOG_WIDTH_TYPE_PARAM}; +use super::float_types::FLOAT64_TYPE; +use super::int_types::{get_log_width, int_tv}; use lazy_static::lazy_static; mod const_fold; /// The extension identifier. @@ -34,6 +38,12 @@ pub enum ConvertOpDef { trunc_s, convert_u, convert_s, + itobool, + ifrombool, + itostring_u, + itostring_s, + itousize, + ifromusize, } impl MakeOpDef for ConvertOpDef { @@ -47,18 +57,19 @@ impl MakeOpDef for ConvertOpDef { fn signature(&self) -> SignatureFunc { use ConvertOpDef::*; - PolyFuncTypeRV::new( - vec![LOG_WIDTH_TYPE_PARAM], - match self { - trunc_s | trunc_u => FuncValueType::new( - type_row![FLOAT64_TYPE], - TypeRV::from(sum_with_error(int_tv(0))), - ), - convert_s | convert_u => { - FuncValueType::new(vec![int_tv(0)], type_row![FLOAT64_TYPE]) - } - }, - ) + match self { + trunc_s | trunc_u => int_polytype( + 1, + type_row![FLOAT64_TYPE], + TypeRV::from(sum_with_error(int_tv(0))), + ), + convert_s | convert_u => int_polytype(1, vec![int_tv(0)], type_row![FLOAT64_TYPE]), + itobool => int_polytype(0, vec![int_type(0)], vec![BOOL_T]), + ifrombool => int_polytype(0, vec![BOOL_T], vec![int_type(0)]), + itostring_u | itostring_s => int_polytype(1, vec![int_tv(0)], vec![STRING_TYPE]), + itousize => int_polytype(0, vec![int_type(6)], vec![USIZE_T]), + ifromusize => int_polytype(0, vec![USIZE_T], vec![int_type(6)]), + } .into() } @@ -69,6 +80,12 @@ impl MakeOpDef for ConvertOpDef { trunc_s => "float to signed int", convert_u => "unsigned int to float", convert_s => "signed int to float", + itobool => "convert a 1-bit integer to bool (1 is true, 0 is false)", + ifrombool => "convert from bool into a 1-bit integer (1 is true, 0 is false)", + itostring_s => "convert a signed integer to its string representation", + itostring_u => "convert an unsigned integer to its string representation", + itousize => "convert a 64b unsigned integer to its usize representation", + ifromusize => "convert a usize to a 64b unsigned integer", } .to_string() } @@ -79,19 +96,44 @@ impl MakeOpDef for ConvertOpDef { } impl ConvertOpDef { - /// Initialise a conversion op with an integer log width type argument. + /// Initialize a [ConvertOpType] from a [ConvertOpDef] which requires no + /// integer widths set. + pub fn without_log_width(self) -> ConvertOpType { + ConvertOpType { + def: self, + log_width: None, + } + } + /// Initialize a [ConvertOpType] from a [ConvertOpDef] which requires one + /// integer width set. pub fn with_log_width(self, log_width: u8) -> ConvertOpType { ConvertOpType { def: self, - log_width, + log_width: Some(log_width), } } } /// Concrete convert operation with integer log width set. #[derive(Debug, Clone, PartialEq)] pub struct ConvertOpType { + /// The kind of conversion op. def: ConvertOpDef, - log_width: u8, + /// The integer width parameter of the conversion op, if any. This is interpreted + /// differently, depending on `def`. The integer types in the inputs and + /// outputs of the op will have [int_type]s of this width. + log_width: Option, +} + +impl ConvertOpType { + /// Returns the generic [ConvertOpDef] of this [ConvertOpType]. + pub fn def(&self) -> &ConvertOpDef { + &self.def + } + + /// Returns the integer width parameters of this [ConvertOpType], if any. + pub fn log_widths(&self) -> &[u8] { + self.log_width.as_slice() + } } impl NamedOp for ConvertOpType { @@ -103,20 +145,11 @@ impl NamedOp for ConvertOpType { impl MakeExtensionOp for ConvertOpType { fn from_extension_op(ext_op: &ExtensionOp) -> Result { let def = ConvertOpDef::from_def(ext_op.def())?; - let log_width: u64 = match *ext_op.args() { - [TypeArg::BoundedNat { n }] => n, - _ => return Err(SignatureError::InvalidTypeArgs.into()), - }; - Ok(Self { - def, - log_width: u8::try_from(log_width).unwrap(), - }) + def.instantiate(ext_op.args()) } - fn type_args(&self) -> Vec { - vec![TypeArg::BoundedNat { - n: self.log_width as u64, - }] + fn type_args(&self) -> Vec { + self.log_width.iter().map(|&n| (n as u64).into()).collect() } } @@ -157,8 +190,35 @@ impl MakeRegisteredOp for ConvertOpType { } } +impl HasConcrete for ConvertOpDef { + type Concrete = ConvertOpType; + + fn instantiate(&self, type_args: &[TypeArg]) -> Result { + let log_width = match type_args { + [] => None, + [arg] => Some(get_log_width(arg).map_err(|_| SignatureError::InvalidTypeArgs)?), + _ => return Err(SignatureError::InvalidTypeArgs.into()), + }; + Ok(ConvertOpType { + def: *self, + log_width, + }) + } +} + +impl HasDef for ConvertOpType { + type Def = ConvertOpDef; +} + #[cfg(test)] mod test { + use rstest::rstest; + + use crate::extension::prelude::ConstUsize; + use crate::ops::Value; + use crate::std_extensions::arithmetic::int_types::ConstInt; + use crate::IncomingPort; + use super::*; #[test] @@ -166,8 +226,60 @@ mod test { let r = &EXTENSION; assert_eq!(r.name() as &str, "arithmetic.conversions"); assert_eq!(r.types().count(), 0); - for (name, _) in r.operations() { - assert!(name.as_str().starts_with("convert") || name.as_str().starts_with("trunc")); + } + + #[test] + fn test_conversions() { + // Initialization with an invalid number of type arguments should fail. + assert!( + ConvertOpDef::itobool + .with_log_width(1) + .to_extension_op() + .is_none(), + "type arguments invalid" + ); + + // This should work + let o = ConvertOpDef::itobool.without_log_width(); + let ext_op: ExtensionOp = o.clone().to_extension_op().unwrap(); + + assert_eq!(ConvertOpType::from_op(&ext_op).unwrap(), o); + assert_eq!( + ConvertOpDef::from_op(&ext_op).unwrap(), + ConvertOpDef::itobool + ); + } + + #[rstest] + #[case::itobool_false(ConvertOpDef::itobool.without_log_width(), &[ConstInt::new_u(0, 0).unwrap().into()], &[Value::false_val()])] + #[case::itobool_true(ConvertOpDef::itobool.without_log_width(), &[ConstInt::new_u(0, 1).unwrap().into()], &[Value::true_val()])] + #[case::ifrombool_false(ConvertOpDef::ifrombool.without_log_width(), &[Value::false_val()], &[ConstInt::new_u(0, 0).unwrap().into()])] + #[case::ifrombool_true(ConvertOpDef::ifrombool.without_log_width(), &[Value::true_val()], &[ConstInt::new_u(0, 1).unwrap().into()])] + #[case::itousize(ConvertOpDef::itousize.without_log_width(), &[ConstInt::new_u(6, 42).unwrap().into()], &[ConstUsize::new(42).into()])] + #[case::ifromusize(ConvertOpDef::ifromusize.without_log_width(), &[ConstUsize::new(42).into()], &[ConstInt::new_u(6, 42).unwrap().into()])] + fn convert_fold( + #[case] op: ConvertOpType, + #[case] inputs: &[Value], + #[case] outputs: &[Value], + ) { + use crate::ops::Value; + + let consts: Vec<(IncomingPort, Value)> = inputs + .iter() + .enumerate() + .map(|(i, v)| (i.into(), v.clone())) + .collect(); + + let res = op + .to_extension_op() + .unwrap() + .constant_fold(&consts) + .unwrap(); + + for (i, expected) in outputs.iter().enumerate() { + let res_val: &Value = &res.get(i).unwrap().1; + + assert_eq!(res_val, expected); } } } 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..bd6daf9fe 100644 --- a/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs +++ b/hugr-core/src/std_extensions/arithmetic/conversions/const_fold.rs @@ -1,3 +1,4 @@ +use crate::extension::prelude::{ConstString, ConstUsize}; use crate::ops::constant::get_single_input_value; use crate::ops::Value; use crate::std_extensions::arithmetic::int_types::INT_TYPES; @@ -25,6 +26,12 @@ pub(super) fn set_fold(op: &ConvertOpDef, def: &mut OpDef) { trunc_s => def.set_constant_folder(TruncS), convert_u => def.set_constant_folder(ConvertU), convert_s => def.set_constant_folder(ConvertS), + itobool => def.set_constant_folder(IToBool), + ifrombool => def.set_constant_folder(IFromBool), + itostring_u => def.set_constant_folder(IToStringU), + itostring_s => def.set_constant_folder(IToStringS), + itousize => def.set_constant_folder(IToUsize), + ifromusize => def.set_constant_folder(IFromUsize), } } @@ -118,3 +125,144 @@ impl ConstFold for ConvertS { Some(vec![(0.into(), ConstF64::new(f).into())]) } } + +struct IToBool; + +impl ConstFold for IToBool { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + if !type_args.is_empty() { + return None; + } + let n0: &ConstInt = get_single_input_value(consts)?; + if n0.log_width() != 0 { + None + } else { + Some(vec![(0.into(), Value::from_bool(n0.value_u() == 1))]) + } + } +} + +struct IFromBool; + +impl ConstFold for IFromBool { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + if !type_args.is_empty() { + return None; + } + let [(_, b0)] = consts else { + return None; + }; + Some(vec![( + 0.into(), + Value::extension( + ConstInt::new_u( + 0, + if b0.clone() == Value::true_val() { + 1 + } else { + 0 + }, + ) + .unwrap(), + ), + )]) + } +} + +struct IToStringU; + +impl ConstFold for IToStringU { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + let [arg] = type_args else { + return None; + }; + let logwidth: u8 = get_log_width(arg).ok()?; + let n0: &ConstInt = get_single_input_value(consts)?; + if n0.log_width() != logwidth { + None + } else { + Some(vec![( + 0.into(), + Value::extension(ConstString::new(n0.value_u().to_string())), + )]) + } + } +} + +struct IToStringS; + +impl ConstFold for IToStringS { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + let [arg] = type_args else { + return None; + }; + let logwidth: u8 = get_log_width(arg).ok()?; + let n0: &ConstInt = get_single_input_value(consts)?; + if n0.log_width() != logwidth { + None + } else { + Some(vec![( + 0.into(), + Value::extension(ConstString::new(n0.value_s().to_string())), + )]) + } + } +} + +struct IToUsize; + +impl ConstFold for IToUsize { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + if !type_args.is_empty() { + return None; + }; + let n0: &ConstInt = get_single_input_value(consts)?; + if n0.log_width() != 6 { + None + } else { + Some(vec![( + 0.into(), + Value::extension(ConstUsize::new(n0.value_u())), + )]) + } + } +} + +struct IFromUsize; + +impl ConstFold for IFromUsize { + fn fold( + &self, + type_args: &[crate::types::TypeArg], + consts: &[(IncomingPort, ops::Value)], + ) -> ConstFoldResult { + if !type_args.is_empty() { + return None; + }; + let n0: &ConstUsize = get_single_input_value(consts)?; + Some(vec![( + 0.into(), + Value::extension(ConstInt::new_u(6, n0.value()).unwrap()), + )]) + } +} diff --git a/hugr-core/src/std_extensions/arithmetic/int_ops.rs b/hugr-core/src/std_extensions/arithmetic/int_ops.rs index cae7627eb..51d3e3885 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_ops.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_ops.rs @@ -1,7 +1,7 @@ //! Basic integer operations. use super::int_types::{get_log_width, int_tv, LOG_WIDTH_TYPE_PARAM}; -use crate::extension::prelude::{sum_with_error, BOOL_T, STRING_TYPE}; +use crate::extension::prelude::{sum_with_error, BOOL_T}; use crate::extension::simple_op::{ HasConcrete, HasDef, MakeExtensionOp, MakeOpDef, MakeRegisteredOp, OpLoadError, }; @@ -10,7 +10,6 @@ use crate::extension::{ }; use crate::ops::custom::ExtensionOp; use crate::ops::{NamedOp, OpName}; -use crate::std_extensions::arithmetic::int_types::int_type; use crate::type_row; use crate::types::{FuncValueType, PolyFuncTypeRV, TypeRowRV}; use crate::utils::collect_array; @@ -57,8 +56,6 @@ pub enum IntOpDef { iwiden_s, inarrow_u, inarrow_s, - itobool, - ifrombool, ieq, ine, ilt_u, @@ -101,8 +98,6 @@ pub enum IntOpDef { irotr, iu_to_s, is_to_u, - itostring_u, - itostring_s, } impl MakeOpDef for IntOpDef { @@ -128,8 +123,6 @@ impl MakeOpDef for IntOpDef { IOValidator { f_ge_s: true }, ) .into(), - itobool => int_polytype(0, vec![int_type(0)], type_row![BOOL_T]).into(), - ifrombool => int_polytype(0, type_row![BOOL_T], vec![int_type(0)]).into(), ieq | ine | ilt_u | ilt_s | igt_u | igt_s | ile_u | ile_s | ige_u | ige_s => { int_polytype(1, vec![tv0; 2], type_row![BOOL_T]).into() } @@ -160,11 +153,6 @@ impl MakeOpDef for IntOpDef { } imod_u | imod_s => int_polytype(1, vec![tv0.clone(); 2], vec![tv0]).into(), ishl | ishr | irotl | irotr => int_polytype(1, vec![tv0.clone(); 2], vec![tv0]).into(), - itostring_u | itostring_s => PolyFuncTypeRV::new( - vec![LOG_WIDTH_TYPE_PARAM], - FuncValueType::new(vec![tv0], vec![STRING_TYPE]), - ) - .into(), } } @@ -176,8 +164,6 @@ impl MakeOpDef for IntOpDef { iwiden_s => "widen a signed integer to a wider one with the same value", inarrow_u => "narrow an unsigned integer to a narrower one with the same value if possible", inarrow_s => "narrow a signed integer to a narrower one with the same value if possible", - itobool => "convert a 1-bit integer to bool (1 is true, 0 is false)", - ifrombool => "convert from bool into a 1-bit integer (1 is true, 0 is false)", ieq => "equality test", ine => "inequality test", ilt_u => "\"less than\" as unsigned integers", @@ -228,8 +214,6 @@ impl MakeOpDef for IntOpDef { (rightmost bits replace leftmost bits)", is_to_u => "convert signed to unsigned by taking absolute value", iu_to_s => "convert unsigned to signed by taking absolute value", - itostring_s => "convert a signed integer to its string representation", - itostring_u => "convert an unsigned integer to its string representation", }.into() } @@ -237,7 +221,9 @@ impl MakeOpDef for IntOpDef { const_fold::set_fold(self, def) } } -fn int_polytype( + +/// Returns a polytype composed by a function type, and a number of integer width type parameters. +pub(in crate::std_extensions::arithmetic) fn int_polytype( n_vars: usize, input: impl Into, output: impl Into, @@ -310,6 +296,8 @@ pub struct ConcreteIntOp { /// The width parameters of the int op. These are interpreted differently, /// depending on `def`. The types of inputs and outputs of the op will have /// [int_type]s of these widths. + /// + /// [int_type]: crate::std_extensions::arithmetic::int_types::int_type pub log_widths: Vec, } @@ -375,8 +363,7 @@ mod test { use rstest::rstest; use crate::{ - ops::{dataflow::DataflowOpTrait, ExtensionOp}, - std_extensions::arithmetic::int_types::int_type, + ops::dataflow::DataflowOpTrait, std_extensions::arithmetic::int_types::int_type, types::Signature, }; @@ -386,7 +373,6 @@ mod test { fn test_int_ops_extension() { assert_eq!(EXTENSION.name() as &str, "arithmetic.int"); assert_eq!(EXTENSION.types().count(), 0); - assert_eq!(EXTENSION.operations().count(), 50); for (name, _) in EXTENSION.operations() { assert!(name.starts_with('i')); } @@ -443,22 +429,6 @@ mod test { .is_none()); } - #[test] - fn test_conversions() { - let o = IntOpDef::itobool.without_log_width(); - assert!( - IntOpDef::itobool - .with_two_log_widths(1, 2) - .to_extension_op() - .is_none(), - "type arguments invalid" - ); - let ext_op: ExtensionOp = o.clone().to_extension_op().unwrap(); - - assert_eq!(ConcreteIntOp::from_op(&ext_op).unwrap(), o); - assert_eq!(IntOpDef::from_op(&ext_op).unwrap(), IntOpDef::itobool); - } - #[rstest] #[case::iadd(IntOpDef::iadd.with_log_width(5), &[1, 2], &[3], 5)] #[case::isub(IntOpDef::isub.with_log_width(5), &[5, 2], &[3], 5)] 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..23e0e937f 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 @@ -2,7 +2,7 @@ use std::cmp::{max, min}; use crate::{ extension::{ - prelude::{sum_with_error, ConstError, ConstString}, + prelude::{sum_with_error, ConstError}, ConstFoldResult, Folder, OpDef, }, ops::{ @@ -168,47 +168,6 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { }, ), }, - IntOpDef::itobool => Folder { - folder: Box::new( - |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - if !type_args.is_empty() { - return None; - } - let n0: &ConstInt = get_single_input_value(consts)?; - if n0.log_width() != 0 { - None - } else { - Some(vec![(0.into(), Value::from_bool(n0.value_u() == 1))]) - } - }, - ), - }, - IntOpDef::ifrombool => Folder { - folder: Box::new( - |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - if !type_args.is_empty() { - return None; - } - let [(_, b0)] = consts else { - return None; - }; - Some(vec![( - 0.into(), - Value::extension( - ConstInt::new_u( - 0, - if b0.clone() == Value::true_val() { - 1 - } else { - 0 - }, - ) - .unwrap(), - ), - )]) - }, - ), - }, IntOpDef::ieq => Folder { folder: Box::new( |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { @@ -1228,43 +1187,5 @@ pub(super) fn set_fold(op: &IntOpDef, def: &mut OpDef) { }, ), }, - IntOpDef::itostring_u => Folder { - folder: Box::new( - |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg] = type_args else { - return None; - }; - let logwidth: u8 = get_log_width(arg).ok()?; - let n0: &ConstInt = get_single_input_value(consts)?; - if n0.log_width() != logwidth { - None - } else { - Some(vec![( - 0.into(), - Value::extension(ConstString::new(n0.value_u().to_string())), - )]) - } - }, - ), - }, - IntOpDef::itostring_s => Folder { - folder: Box::new( - |type_args: &[TypeArg], consts: &[(IncomingPort, Value)]| -> ConstFoldResult { - let [arg] = type_args else { - return None; - }; - let logwidth: u8 = get_log_width(arg).ok()?; - let n0: &ConstInt = get_single_input_value(consts)?; - if n0.log_width() != logwidth { - None - } else { - Some(vec![( - 0.into(), - Value::extension(ConstString::new(n0.value_s().to_string())), - )]) - } - }, - ), - }, }); } diff --git a/hugr-passes/src/const_fold/test.rs b/hugr-passes/src/const_fold/test.rs index 3fdddf24d..ce2ca667f 100644 --- a/hugr-passes/src/const_fold/test.rs +++ b/hugr-passes/src/const_fold/test.rs @@ -444,7 +444,7 @@ fn test_fold_itobool() { let mut build = DFGBuilder::new(noargfn(vec![BOOL_T])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(0, 1).unwrap())); let x1 = build - .add_dataflow_op(IntOpDef::itobool.without_log_width(), [x0]) + .add_dataflow_op(ConvertOpDef::itobool.without_log_width(), [x0]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -467,7 +467,7 @@ fn test_fold_ifrombool() { let mut build = DFGBuilder::new(noargfn(vec![INT_TYPES[0].clone()])).unwrap(); let x0 = build.add_load_const(Value::false_val()); let x1 = build - .add_dataflow_op(IntOpDef::ifrombool.without_log_width(), [x0]) + .add_dataflow_op(ConvertOpDef::ifrombool.without_log_width(), [x0]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1457,7 +1457,7 @@ fn test_fold_itostring_u() { let mut build = DFGBuilder::new(noargfn(vec![STRING_TYPE])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_u(5, 17).unwrap())); let x1 = build - .add_dataflow_op(IntOpDef::itostring_u.with_log_width(5), [x0]) + .add_dataflow_op(ConvertOpDef::itostring_u.with_log_width(5), [x0]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), @@ -1479,7 +1479,7 @@ fn test_fold_itostring_s() { let mut build = DFGBuilder::new(noargfn(vec![STRING_TYPE])).unwrap(); let x0 = build.add_load_const(Value::extension(ConstInt::new_s(5, -17).unwrap())); let x1 = build - .add_dataflow_op(IntOpDef::itostring_s.with_log_width(5), [x0]) + .add_dataflow_op(ConvertOpDef::itostring_s.with_log_width(5), [x0]) .unwrap(); let reg = ExtensionRegistry::try_new([ PRELUDE.to_owned(), 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..f8aae9eee 100644 --- a/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json +++ b/hugr-py/src/hugr/std/_json_defs/arithmetic/conversions.json @@ -96,6 +96,222 @@ }, "binary": false }, + "ifrombool": { + "extension": "arithmetic.conversions", + "name": "ifrombool", + "description": "convert from bool into a 1-bit integer (1 is true, 0 is false)", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "output": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 0 + } + ], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "ifromusize": { + "extension": "arithmetic.conversions", + "name": "ifromusize", + "description": "convert a usize to a 64b unsigned integer", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "I" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 6 + } + ], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itobool": { + "extension": "arithmetic.conversions", + "name": "itobool", + "description": "convert a 1-bit integer to bool (1 is true, 0 is false)", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 0 + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itostring_s": { + "extension": "arithmetic.conversions", + "name": "itostring_s", + "description": "convert a signed integer to its string representation", + "signature": { + "params": [ + { + "tp": "BoundedNat", + "bound": 7 + } + ], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "Variable", + "idx": 0, + "cached_decl": { + "tp": "BoundedNat", + "bound": 7 + } + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "string", + "args": [], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itostring_u": { + "extension": "arithmetic.conversions", + "name": "itostring_u", + "description": "convert an unsigned integer to its string representation", + "signature": { + "params": [ + { + "tp": "BoundedNat", + "bound": 7 + } + ], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "Variable", + "idx": 0, + "cached_decl": { + "tp": "BoundedNat", + "bound": 7 + } + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "string", + "args": [], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itousize": { + "extension": "arithmetic.conversions", + "name": "itousize", + "description": "convert a 64b unsigned integer to its usize representation", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 6 + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "I" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, "trunc_s": { "extension": "arithmetic.conversions", "name": "trunc_s", 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..56dd2a02c 100644 --- a/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json +++ b/hugr-py/src/hugr/std/_json_defs/arithmetic/int.json @@ -956,39 +956,6 @@ }, "binary": false }, - "ifrombool": { - "extension": "arithmetic.int", - "name": "ifrombool", - "description": "convert from bool into a 1-bit integer (1 is true, 0 is false)", - "signature": { - "params": [], - "body": { - "input": [ - { - "t": "Sum", - "s": "Unit", - "size": 2 - } - ], - "output": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "BoundedNat", - "n": 0 - } - ], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, "ige_s": { "extension": "arithmetic.int", "name": "ige_s", @@ -2956,127 +2923,6 @@ }, "binary": false }, - "itobool": { - "extension": "arithmetic.int", - "name": "itobool", - "description": "convert a 1-bit integer to bool (1 is true, 0 is false)", - "signature": { - "params": [], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "BoundedNat", - "n": 0 - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Sum", - "s": "Unit", - "size": 2 - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, - "itostring_s": { - "extension": "arithmetic.int", - "name": "itostring_s", - "description": "convert a signed integer to its string representation", - "signature": { - "params": [ - { - "tp": "BoundedNat", - "bound": 7 - } - ], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "Variable", - "idx": 0, - "cached_decl": { - "tp": "BoundedNat", - "bound": 7 - } - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Opaque", - "extension": "prelude", - "id": "string", - "args": [], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, - "itostring_u": { - "extension": "arithmetic.int", - "name": "itostring_u", - "description": "convert an unsigned integer to its string representation", - "signature": { - "params": [ - { - "tp": "BoundedNat", - "bound": 7 - } - ], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "Variable", - "idx": 0, - "cached_decl": { - "tp": "BoundedNat", - "bound": 7 - } - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Opaque", - "extension": "prelude", - "id": "string", - "args": [], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, "iu_to_s": { "extension": "arithmetic.int", "name": "iu_to_s", diff --git a/specification/std_extensions/arithmetic/conversions.json b/specification/std_extensions/arithmetic/conversions.json index c23cba7c6..f8aae9eee 100644 --- a/specification/std_extensions/arithmetic/conversions.json +++ b/specification/std_extensions/arithmetic/conversions.json @@ -96,6 +96,222 @@ }, "binary": false }, + "ifrombool": { + "extension": "arithmetic.conversions", + "name": "ifrombool", + "description": "convert from bool into a 1-bit integer (1 is true, 0 is false)", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "output": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 0 + } + ], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "ifromusize": { + "extension": "arithmetic.conversions", + "name": "ifromusize", + "description": "convert a usize to a 64b unsigned integer", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "I" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 6 + } + ], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itobool": { + "extension": "arithmetic.conversions", + "name": "itobool", + "description": "convert a 1-bit integer to bool (1 is true, 0 is false)", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 0 + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itostring_s": { + "extension": "arithmetic.conversions", + "name": "itostring_s", + "description": "convert a signed integer to its string representation", + "signature": { + "params": [ + { + "tp": "BoundedNat", + "bound": 7 + } + ], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "Variable", + "idx": 0, + "cached_decl": { + "tp": "BoundedNat", + "bound": 7 + } + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "string", + "args": [], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itostring_u": { + "extension": "arithmetic.conversions", + "name": "itostring_u", + "description": "convert an unsigned integer to its string representation", + "signature": { + "params": [ + { + "tp": "BoundedNat", + "bound": 7 + } + ], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "Variable", + "idx": 0, + "cached_decl": { + "tp": "BoundedNat", + "bound": 7 + } + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "string", + "args": [], + "bound": "C" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, + "itousize": { + "extension": "arithmetic.conversions", + "name": "itousize", + "description": "convert a 64b unsigned integer to its usize representation", + "signature": { + "params": [], + "body": { + "input": [ + { + "t": "Opaque", + "extension": "arithmetic.int.types", + "id": "int", + "args": [ + { + "tya": "BoundedNat", + "n": 6 + } + ], + "bound": "C" + } + ], + "output": [ + { + "t": "I" + } + ], + "extension_reqs": [] + } + }, + "binary": false + }, "trunc_s": { "extension": "arithmetic.conversions", "name": "trunc_s", diff --git a/specification/std_extensions/arithmetic/int.json b/specification/std_extensions/arithmetic/int.json index a6cc862f6..56dd2a02c 100644 --- a/specification/std_extensions/arithmetic/int.json +++ b/specification/std_extensions/arithmetic/int.json @@ -956,39 +956,6 @@ }, "binary": false }, - "ifrombool": { - "extension": "arithmetic.int", - "name": "ifrombool", - "description": "convert from bool into a 1-bit integer (1 is true, 0 is false)", - "signature": { - "params": [], - "body": { - "input": [ - { - "t": "Sum", - "s": "Unit", - "size": 2 - } - ], - "output": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "BoundedNat", - "n": 0 - } - ], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, "ige_s": { "extension": "arithmetic.int", "name": "ige_s", @@ -2956,127 +2923,6 @@ }, "binary": false }, - "itobool": { - "extension": "arithmetic.int", - "name": "itobool", - "description": "convert a 1-bit integer to bool (1 is true, 0 is false)", - "signature": { - "params": [], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "BoundedNat", - "n": 0 - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Sum", - "s": "Unit", - "size": 2 - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, - "itostring_s": { - "extension": "arithmetic.int", - "name": "itostring_s", - "description": "convert a signed integer to its string representation", - "signature": { - "params": [ - { - "tp": "BoundedNat", - "bound": 7 - } - ], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "Variable", - "idx": 0, - "cached_decl": { - "tp": "BoundedNat", - "bound": 7 - } - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Opaque", - "extension": "prelude", - "id": "string", - "args": [], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, - "itostring_u": { - "extension": "arithmetic.int", - "name": "itostring_u", - "description": "convert an unsigned integer to its string representation", - "signature": { - "params": [ - { - "tp": "BoundedNat", - "bound": 7 - } - ], - "body": { - "input": [ - { - "t": "Opaque", - "extension": "arithmetic.int.types", - "id": "int", - "args": [ - { - "tya": "Variable", - "idx": 0, - "cached_decl": { - "tp": "BoundedNat", - "bound": 7 - } - } - ], - "bound": "C" - } - ], - "output": [ - { - "t": "Opaque", - "extension": "prelude", - "id": "string", - "args": [], - "bound": "C" - } - ], - "extension_reqs": [] - } - }, - "binary": false - }, "iu_to_s": { "extension": "arithmetic.int", "name": "iu_to_s",