Skip to content

Commit

Permalink
Comments
Browse files Browse the repository at this point in the history
  • Loading branch information
zrho committed Nov 20, 2024
1 parent a05ae29 commit 7ef9312
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
32 changes: 25 additions & 7 deletions hugr-core/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,21 @@ struct Context<'a> {
bump: &'a Bump,
/// Stores the terms that we have already seen to avoid duplicates.
term_map: FxHashMap<model::Term<'a>, model::TermId>,

/// The current scope for local variables.
///
/// This is set to the id of the smallest enclosing node that defines a polymorphic type.
/// We use this when exporting local variables in terms.
local_scope: Option<model::NodeId>,

/// Constraints to be added to the local scope.
///
/// When exporting a node that defines a polymorphic type, we use this field
/// to collect the constraints that need to be added to that polymorphic
/// type. Currently this is used to record `nonlinear` constraints on uses
/// of `TypeParam::Type` with a `TypeBound::Copyable` bound.
local_constraints: Vec<model::TermId>,

/// Mapping from extension operations to their declarations.
decl_operations: FxHashMap<(ExtensionId, OpName), model::NodeId>,
}
Expand Down Expand Up @@ -679,6 +690,12 @@ impl<'a> Context<'a> {
regions.into_bump_slice()
}

/// Exports a polymorphic function type.
///
/// The returned triple consists of:
/// - The static parameters of the polymorphic function type.
/// - The constraints of the polymorphic function type.
/// - The function type itself.
pub fn export_poly_func_type<RV: MaybeRV>(
&mut self,
t: &PolyFuncTypeBase<RV>,
Expand All @@ -699,10 +716,7 @@ impl<'a> Context<'a> {
params.push(param)
}

let constraints = self
.bump
.alloc_slice_fill_iter(self.local_constraints.drain(..));

let constraints = self.bump.alloc_slice_copy(&self.local_constraints);
let body = self.export_func_type(t.body());

(params.into_bump_slice(), constraints, body)
Expand All @@ -722,7 +736,6 @@ impl<'a> Context<'a> {
}
TypeEnum::Function(func) => self.export_func_type(func),
TypeEnum::Variable(index, _) => {
// This ignores the type bound for now
let node = self.local_scope.expect("local variable out of scope");
self.make_term(model::Term::Var(model::LocalRef::Index(node, *index as _)))
}
Expand Down Expand Up @@ -813,13 +826,18 @@ impl<'a> Context<'a> {
self.make_term(model::Term::List { items, tail: None })
}

/// Exports a `TypeParam` to a term.
///
/// The `var` argument is set when the type parameter being exported is the
/// type of a parameter to a polymorphic definition. In that case we can
/// generate a `nonlinear` constraint for the type of runtime types marked as
/// `TypeBound::Copyable`.
pub fn export_type_param(
&mut self,
t: &TypeParam,
var: Option<model::LocalRef<'static>>,
) -> model::TermId {
match t {
// This ignores the type bound for now.
TypeParam::Type { b } => {
if let (Some(var), TypeBound::Copyable) = (var, b) {
let term = self.make_term(model::Term::Var(var));
Expand All @@ -829,7 +847,7 @@ impl<'a> Context<'a> {

self.make_term(model::Term::Type)
}
// This ignores the type bound for now.
// This ignores the bound on the natural for now.
TypeParam::BoundedNat { .. } => self.make_term(model::Term::NatType),
TypeParam::String => self.make_term(model::Term::StrType),
TypeParam::List { param } => {
Expand Down
11 changes: 8 additions & 3 deletions hugr-core/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ struct Context<'a> {
/// A map from `NodeId` to the imported `Node`.
nodes: FxHashMap<model::NodeId, Node>,

/// The types of the local variables that are currently in scope.
/// The local variables that are currently in scope.
local_variables: FxIndexMap<&'a str, LocalVar>,

custom_name_cache: FxHashMap<&'a str, (ExtensionId, SmolStr)>,
Expand Down Expand Up @@ -155,7 +155,7 @@ impl<'a> Context<'a> {
.ok_or_else(|| model::ModelError::RegionNotFound(region_id).into())
}

/// Looks up a [`LocalRef`] within the current scope and returns its index and type.
/// Looks up a [`LocalRef`] within the current scope.
fn resolve_local_ref(
&self,
local_ref: &model::LocalRef,
Expand Down Expand Up @@ -915,7 +915,7 @@ impl<'a> Context<'a> {
}

for (index, param) in decl.params.iter().enumerate() {
// TODO: `PolyFuncType` should be able to distinguish between implicit and explicit parameters.
// NOTE: `PolyFuncType` only has explicit type parameters at present.
let bound = ctx.local_variables[index].bound;
imported_params.push(ctx.import_type_param(param.r#type, bound)?);
}
Expand Down Expand Up @@ -946,6 +946,8 @@ impl<'a> Context<'a> {
model::Term::FuncType { .. } => Err(error_unsupported!("`(fn ...)` as `TypeParam`")),

model::Term::ListType { item_type } => {
// At present `hugr-model` has no way to express that the item
// type of a list must be copyable. Therefore we import it as `Any`.
let param = Box::new(self.import_type_param(*item_type, TypeBound::Any)?);
Ok(TypeParam::List { param })
}
Expand Down Expand Up @@ -1303,9 +1305,12 @@ impl<'a> Names<'a> {
}
}

/// Information about a local variable.
#[derive(Debug, Clone, Copy)]
struct LocalVar {
/// The type of the variable.
r#type: model::TermId,
/// The type bound of the variable.
bound: TypeBound,
}

Expand Down

0 comments on commit 7ef9312

Please sign in to comment.