Skip to content

Commit

Permalink
fix!: Serialise Value, PrimValue, and TypeArg with internal tags (
Browse files Browse the repository at this point in the history
#496)

Adds a serde tag to the `Value`, `PrimValue`, and `TypeArg` enums.

BREAKING CHANGE: Turn all variants of the `Value`, `PrimValue`, and
`TypeArg` enums into struct variants

---------

Co-authored-by: Seyon Sivarajah <[email protected]>
  • Loading branch information
mark-koch and ss2165 authored Sep 6, 2023
1 parent 0a796a3 commit 9ee57e4
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 75 deletions.
5 changes: 4 additions & 1 deletion src/extension/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ pub 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::BoundedNat(size)])
.instantiate_concrete(vec![
TypeArg::Type { ty: typ },
TypeArg::BoundedNat { n: size },
])
.unwrap();
Type::new_extension(custom_t)
}
Expand Down
25 changes: 15 additions & 10 deletions src/extension/type_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl TypeDef {
least_upper_bound(indices.iter().map(|i| {
let ta = args.get(*i);
match ta {
Some(TypeArg::Type(s)) => s.least_upper_bound(),
Some(TypeArg::Type { ty: s }) => s.least_upper_bound(),
_ => panic!("TypeArg index does not refer to a type."),
}
}))
Expand Down Expand Up @@ -174,22 +174,24 @@ mod test {
bound: TypeDefBound::FromParams(vec![0]),
};
let typ = Type::new_extension(
def.instantiate_concrete(vec![TypeArg::Type(Type::new_function(FunctionType::new(
vec![],
vec![],
)))])
def.instantiate_concrete(vec![TypeArg::Type {
ty: Type::new_function(FunctionType::new(vec![], vec![])),
}])
.unwrap(),
);
assert_eq!(typ.least_upper_bound(), TypeBound::Copyable);
let typ2 = Type::new_extension(def.instantiate_concrete([TypeArg::Type(USIZE_T)]).unwrap());
let typ2 = Type::new_extension(
def.instantiate_concrete([TypeArg::Type { ty: USIZE_T }])
.unwrap(),
);
assert_eq!(typ2.least_upper_bound(), TypeBound::Eq);

// And some bad arguments...firstly, wrong kind of TypeArg:
assert_eq!(
def.instantiate_concrete([TypeArg::Type(QB_T)]),
def.instantiate_concrete([TypeArg::Type { ty: QB_T }]),
Err(SignatureError::TypeArgMismatch(
TypeArgError::TypeMismatch {
arg: TypeArg::Type(QB_T),
arg: TypeArg::Type { ty: QB_T },
param: TypeParam::Type(TypeBound::Copyable)
}
))
Expand All @@ -201,8 +203,11 @@ mod test {
);
// Too many arguments:
assert_eq!(
def.instantiate_concrete([TypeArg::Type(FLOAT64_TYPE), TypeArg::Type(FLOAT64_TYPE),])
.unwrap_err(),
def.instantiate_concrete([
TypeArg::Type { ty: FLOAT64_TYPE },
TypeArg::Type { ty: FLOAT64_TYPE },
])
.unwrap_err(),
SignatureError::TypeArgMismatch(TypeArgError::WrongNumberArgs(2, 1))
);
}
Expand Down
14 changes: 8 additions & 6 deletions src/hugr/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ mod test {

let valid = Type::new_extension(CustomType::new(
"MyContainer",
vec![TypeArg::Type(USIZE_T)],
vec![TypeArg::Type { ty: USIZE_T }],
"MyExt",
TypeBound::Any,
));
Expand All @@ -1363,21 +1363,21 @@ mod test {
// valid is Any, so is not allowed as an element of an outer MyContainer.
let element_outside_bound = CustomType::new(
"MyContainer",
vec![TypeArg::Type(valid.clone())],
vec![TypeArg::Type { ty: valid.clone() }],
"MyExt",
TypeBound::Any,
);
assert_eq!(
validate_to_sig_error(element_outside_bound),
SignatureError::TypeArgMismatch(TypeArgError::TypeMismatch {
param: TypeParam::Type(TypeBound::Copyable),
arg: TypeArg::Type(valid)
arg: TypeArg::Type { ty: valid }
})
);

let bad_bound = CustomType::new(
"MyContainer",
vec![TypeArg::Type(USIZE_T)],
vec![TypeArg::Type { ty: USIZE_T }],
"MyExt",
TypeBound::Copyable,
);
Expand All @@ -1392,7 +1392,9 @@ mod test {
// bad_bound claims to be Copyable, which is valid as an element for the outer MyContainer.
let nested = CustomType::new(
"MyContainer",
vec![TypeArg::Type(Type::new_extension(bad_bound))],
vec![TypeArg::Type {
ty: Type::new_extension(bad_bound),
}],
"MyExt",
TypeBound::Any,
);
Expand All @@ -1406,7 +1408,7 @@ mod test {

let too_many_type_args = CustomType::new(
"MyContainer",
vec![TypeArg::Type(USIZE_T), TypeArg::BoundedNat(3)],
vec![TypeArg::Type { ty: USIZE_T }, TypeArg::BoundedNat { n: 3 }],
"MyExt",
TypeBound::Any,
);
Expand Down
2 changes: 1 addition & 1 deletion src/ops/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ mod test {
fn test_yaml_const() {
let typ_int = CustomType::new(
"mytype",
vec![TypeArg::BoundedNat(8)],
vec![TypeArg::BoundedNat { n: 8 }],
"myrsrc",
TypeBound::Eq,
);
Expand Down
4 changes: 2 additions & 2 deletions src/ops/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ mod test {
"res".into(),
"op",
"desc".into(),
vec![TypeArg::Type(USIZE_T)],
vec![TypeArg::Type { ty: USIZE_T }],
None,
);
let op: ExternalOp = op.into();
assert_eq!(op.name(), "res.op");
assert_eq!(op.description(), "desc");
assert_eq!(op.args(), &[TypeArg::Type(USIZE_T)]);
assert_eq!(op.args(), &[TypeArg::Type { ty: USIZE_T }]);
}
}
14 changes: 8 additions & 6 deletions src/std_extensions/arithmetic/int_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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; LOG_WIDTH_BOUND as usize] = (0..LOG_WIDTH_BOUND)
.map(|i| int_type(TypeArg::BoundedNat(i as u64)))
.map(|i| int_type(TypeArg::BoundedNat { n: i as u64 }))
.collect::<Vec<_>>()
.try_into()
.unwrap();
Expand All @@ -58,7 +58,7 @@ pub const LOG_WIDTH_TYPE_PARAM: TypeParam = TypeParam::bounded_nat(unsafe {
/// is invalid.
pub(super) fn get_log_width(arg: &TypeArg) -> Result<u8, TypeArgError> {
match arg {
TypeArg::BoundedNat(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,
Expand All @@ -67,7 +67,9 @@ pub(super) fn get_log_width(arg: &TypeArg) -> Result<u8, TypeArgError> {
}

pub(super) const fn type_arg(log_width: u8) -> TypeArg {
TypeArg::BoundedNat(log_width as u64)
TypeArg::BoundedNat {
n: log_width as u64,
}
}
/// An unsigned integer
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -193,12 +195,12 @@ mod test {

#[test]
fn test_int_widths() {
let type_arg_32 = TypeArg::BoundedNat(5);
let type_arg_32 = TypeArg::BoundedNat { n: 5 };
assert_matches!(get_log_width(&type_arg_32), Ok(5));

let type_arg_128 = TypeArg::BoundedNat(7);
let type_arg_128 = TypeArg::BoundedNat { n: 7 };
assert_matches!(get_log_width(&type_arg_128), Ok(7));
let type_arg_256 = TypeArg::BoundedNat(8);
let type_arg_256 = TypeArg::BoundedNat { n: 8 };
assert_matches!(
get_log_width(&type_arg_256),
Err(TypeArgError::TypeMismatch { .. })
Expand Down
2 changes: 1 addition & 1 deletion src/std_extensions/arithmetic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod test {
for i in 0..LOG_WIDTH_BOUND {
assert_eq!(
INT_TYPES[i as usize],
int_type(TypeArg::BoundedNat(i as u64))
int_type(TypeArg::BoundedNat { n: i as u64 })
)
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/std_extensions/collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl CustomConst for ListValue {
.map_err(|_| error())?;

// constant can only hold classic type.
let [TypeArg::Type(t)] = typ.args() else {
let [TypeArg::Type { ty: t }] = typ.args() else {
return Err(error());
};

Expand Down Expand Up @@ -118,7 +118,7 @@ fn get_type(name: &str) -> &TypeDef {

fn list_types(args: &[TypeArg]) -> Result<(Type, Type), SignatureError> {
let list_custom_type = get_type(&LIST_TYPENAME).instantiate_concrete(args)?;
let [TypeArg::Type(element_type)] = args else {
let [TypeArg::Type { ty: element_type }] = args else {
panic!("should be checked by def.")
};

Expand Down Expand Up @@ -156,11 +156,11 @@ mod test {
let list_def = r.get_type(&LIST_TYPENAME).unwrap();

let list_type = list_def
.instantiate_concrete([TypeArg::Type(USIZE_T)])
.instantiate_concrete([TypeArg::Type { ty: USIZE_T }])
.unwrap();

assert!(list_def
.instantiate_concrete([TypeArg::BoundedNat(3)])
.instantiate_concrete([TypeArg::BoundedNat { n: 3 }])
.is_err());

list_def.check_custom(&list_type).unwrap();
Expand All @@ -175,12 +175,12 @@ mod test {
#[test]
fn test_list_ops() {
let pop_sig = get_op(&POP_NAME)
.compute_signature(&[TypeArg::Type(QB_T)])
.compute_signature(&[TypeArg::Type { ty: QB_T }])
.unwrap();

let list_type = Type::new_extension(CustomType::new(
LIST_TYPENAME,
vec![TypeArg::Type(QB_T)],
vec![TypeArg::Type { ty: QB_T }],
EXTENSION_NAME,
TypeBound::Any,
));
Expand All @@ -191,12 +191,12 @@ mod test {
assert_eq!(pop_sig.output(), &both_row);

let push_sig = get_op(&PUSH_NAME)
.compute_signature(&[TypeArg::Type(FLOAT64_TYPE)])
.compute_signature(&[TypeArg::Type { ty: FLOAT64_TYPE }])
.unwrap();

let list_type = Type::new_extension(CustomType::new(
LIST_TYPENAME,
vec![TypeArg::Type(FLOAT64_TYPE)],
vec![TypeArg::Type { ty: FLOAT64_TYPE }],
EXTENSION_NAME,
TypeBound::Copyable,
));
Expand Down
6 changes: 3 additions & 3 deletions src/std_extensions/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn extension() -> Extension {
|arg_values: &[TypeArg]| {
let a = arg_values.iter().exactly_one().unwrap();
let n: u64 = match a {
TypeArg::BoundedNat(n) => *n,
TypeArg::BoundedNat { n } => *n,
_ => {
return Err(TypeArgError::TypeMismatch {
arg: a.clone(),
Expand All @@ -75,7 +75,7 @@ fn extension() -> Extension {
|arg_values: &[TypeArg]| {
let a = arg_values.iter().exactly_one().unwrap();
let n: u64 = match a {
TypeArg::BoundedNat(n) => *n,
TypeArg::BoundedNat { n } => *n,
_ => {
return Err(TypeArgError::TypeMismatch {
arg: a.clone(),
Expand Down Expand Up @@ -134,7 +134,7 @@ pub(crate) mod test {
/// Generate a logic extension and "and" operation over [`crate::prelude::BOOL_T`]
pub(crate) fn and_op() -> LeafOp {
EXTENSION
.instantiate_extension_op(AND_NAME, [TypeArg::BoundedNat(2)])
.instantiate_extension_op(AND_NAME, [TypeArg::BoundedNat { n: 2 }])
.unwrap()
.into()
}
Expand Down
12 changes: 6 additions & 6 deletions src/types/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ impl PrimType {
}

match (self, val) {
(PrimType::Extension(e), PrimValue::Extension(e_val)) => {
(PrimType::Extension(e), PrimValue::Extension { c: e_val }) => {
e_val.0.check_custom_type(e)?;
Ok(())
}
(PrimType::Function(t), PrimValue::Function(v))
(PrimType::Function(t), PrimValue::Function { hugr: v })
if Some(t.as_ref()) == v.get_function_type() =>
{
// exact signature equality, in future this may need to be
Expand All @@ -68,7 +68,7 @@ impl PrimType {
}
_ => Err(ConstTypeError::ValueCheckFail(
Type::new(TypeEnum::Prim(self.clone())),
Value::Prim(val.clone()),
Value::Prim { val: val.clone() },
)),
}
}
Expand All @@ -82,8 +82,8 @@ impl Type {
/// This function will return an error if there is a type check error.
pub fn check_type(&self, val: &Value) -> Result<(), ConstTypeError> {
match (&self.0, val) {
(TypeEnum::Prim(p), Value::Prim(p_v)) => p.check_type(p_v),
(TypeEnum::Tuple(t), Value::Tuple(t_v)) => {
(TypeEnum::Prim(p), Value::Prim { val: p_v }) => p.check_type(p_v),
(TypeEnum::Tuple(t), Value::Tuple { vs: t_v }) => {
if t.len() != t_v.len() {
return Err(ConstTypeError::TupleWrongLength);
}
Expand All @@ -92,7 +92,7 @@ impl Type {
.try_for_each(|(elem, ty)| ty.check_type(elem))
.map_err(|_| ConstTypeError::ValueCheckFail(self.clone(), val.clone()))
}
(TypeEnum::Sum(sum), Value::Sum(tag, value)) => sum
(TypeEnum::Sum(sum), Value::Sum { tag, value }) => sum
.get_variant(*tag)
.ok_or(ConstTypeError::InvalidSumTag)?
.check_type(value),
Expand Down
Loading

0 comments on commit 9ee57e4

Please sign in to comment.