Skip to content

Commit

Permalink
Enable TypeDef reporting of type tag.
Browse files Browse the repository at this point in the history
Closes #286
  • Loading branch information
ss2165 committed Jul 28, 2023
1 parent aca1dee commit 77f1c60
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/extensions/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl Type {
params: vec![],
description: self.description().to_string(),
resource: None,
tag: crate::types::TypeTag::Classic.into(),
}
}
}
Expand Down
41 changes: 41 additions & 0 deletions src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use smol_str::SmolStr;
use thiserror::Error;

use crate::types::type_param::{check_type_arg, TypeArgError};
use crate::types::TypeTag;
use crate::types::{
type_param::{TypeArg, TypeParam},
Signature, SignatureDescription, SimpleRow,
Expand Down Expand Up @@ -288,6 +289,20 @@ impl OpDef {
}
}

/// The type tag of a [`TypeDef`]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum TypeDefTag {
/// Defined by an explicit tag.
Explicit(TypeTag),
/// Derived as the tag containing all marked type parameters.
FromParams(Vec<usize>),
}

impl From<TypeTag> for TypeDefTag {
fn from(tag: TypeTag) -> Self {
Self::Explicit(tag)
}
}
/// A declaration of an opaque type.
/// Note this does not provide any way to create instances
/// - typically these are operations also provided by the Resource.
Expand All @@ -304,6 +319,32 @@ pub struct TypeDef {
pub resource: Option<ResourceId>,
/// Human readable description of the type definition.
pub description: String,
/// The definition of the type tag of this definition.
pub tag: TypeDefTag,
}

impl TypeDef {
/// The [`TypeTag`] of the definition.
pub fn tag(&self, args: &[TypeArg]) -> TypeTag {
match &self.tag {
TypeDefTag::Explicit(tag) => *tag,
TypeDefTag::FromParams(indices) => {
let args: Vec<_> = args.iter().collect();
if indices.is_empty() {
// Assume most general case
return TypeTag::Simple;
}
indices
.iter()
.map(|i| {
args.get(*i)
.and_then(|ta| ta.tag())
.expect("TypeParam index invalid or param does not have a TypeTag.")
})
.fold(TypeTag::Hashable, TypeTag::union)
}
}
}
}

/// A unique identifier for a resource.
Expand Down
2 changes: 1 addition & 1 deletion src/types/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub enum TypeTag {
impl TypeTag {
/// Returns the smallest TypeTag containing both the receiver and argument.
/// (This will be one of the receiver or the argument.)
fn union(self, other: Self) -> Self {
pub fn union(self, other: Self) -> Self {
if self == Self::Simple || other == Self::Simple {
Self::Simple
} else if self == Self::Classic || other == Self::Classic {
Expand Down
15 changes: 14 additions & 1 deletion src/types/type_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use thiserror::Error;

use crate::ops::constant::HugrIntValueStore;

use super::{ClassicType, SimpleType};
use super::{ClassicType, PrimType, SimpleType, TypeTag};

/// A parameter declared by an OpDef. Specifies a value
/// that must be provided by each operation node.
Expand Down Expand Up @@ -51,6 +51,19 @@ pub enum TypeArg {
Value(serde_yaml::Value),
}

impl TypeArg {
/// Report [`TypeArg`] if param is a type
pub fn tag(&self) -> Option<TypeTag> {
match self {
TypeArg::Type(s) => Some(s.tag()),
TypeArg::ClassicType(c) => Some(c.tag()),
// assume list is well formed - all elements of same type
TypeArg::List(t) => t.iter().next().and_then(TypeArg::tag),
_ => None,
}
}
}

/// Checks a [TypeArg] is as expected for a [TypeParam]
pub fn check_type_arg(arg: &TypeArg, param: &TypeParam) -> Result<(), TypeArgError> {
match (arg, param) {
Expand Down

0 comments on commit 77f1c60

Please sign in to comment.