Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: Serialise Value, PrimValue, and TypeArg with internal tags #496

Merged
merged 9 commits into from
Sep 6, 2023
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