Skip to content

Commit

Permalink
feat: Change TypeParam::USize to TypeParam::BoundedNat and use in…
Browse files Browse the repository at this point in the history
… int extensions (#445)

Closes #437 

BREAKING CHANGE: `USize` type param and type arg changed to `BoundedNat`
with optional maximum. For previous behaviour use `TypeParam::max_nat()`

---------

Co-authored-by: Alec Edgington <[email protected]>
  • Loading branch information
2 people authored and lmondada committed Aug 28, 2023
1 parent 5b921f3 commit 04e387c
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 175 deletions.
6 changes: 3 additions & 3 deletions specification/hugr.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/extension/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_nat()],
"array".into(),
TypeDefBound::FromParams(vec![0]),
)
Expand Down Expand Up @@ -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::BoundedNat(size)])
.unwrap();
Type::new_extension(custom_t)
}
Expand Down
7 changes: 6 additions & 1 deletion src/ops/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::BoundedNat(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);
Expand Down
23 changes: 9 additions & 14 deletions src/std_extensions/arithmetic/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,23 @@ 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::{get_width, int_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");

fn ftoi_sig(arg_values: &[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> {
let [arg] = collect_array(arg_values);
let n: u8 = get_width(arg)?;
Ok((
type_row![FLOAT64_TYPE],
vec![Type::new_sum(vec![
int_type(n),
int_type(arg.clone()),
crate::extension::prelude::ERROR_TYPE,
])]
.into(),
Expand All @@ -37,9 +33,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(arg)?;
Ok((
vec![int_type(n)].into(),
vec![int_type(arg.clone())].into(),
type_row![FLOAT64_TYPE],
ExtensionSet::default(),
))
Expand All @@ -59,31 +54,31 @@ pub fn extension() -> Extension {
.add_op_custom_sig_simple(
"trunc_u".into(),
"float to unsigned int".to_owned(),
vec![TypeParam::USize],
vec![LOG_WIDTH_TYPE_PARAM],
ftoi_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"trunc_s".into(),
"float to signed int".to_owned(),
vec![TypeParam::USize],
vec![LOG_WIDTH_TYPE_PARAM],
ftoi_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"convert_u".into(),
"unsigned int to float".to_owned(),
vec![TypeParam::USize],
vec![LOG_WIDTH_TYPE_PARAM],
itof_sig,
)
.unwrap();
extension
.add_op_custom_sig_simple(
"convert_s".into(),
"signed int to float".to_owned(),
vec![TypeParam::USize],
vec![LOG_WIDTH_TYPE_PARAM],
itof_sig,
)
.unwrap();
Expand Down
Loading

0 comments on commit 04e387c

Please sign in to comment.