Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions hugr-model/src/v0/ast/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,18 @@ fn try_alloc_slice<T, E>(
}
Ok(vec.into_bump_slice())
}

#[cfg(test)]
mod test {
use crate::v0::ast;
use bumpalo::Bump;
use std::str::FromStr as _;

#[test]
fn vars_in_root_scope() {
let text = "(hugr 0) (mod) (meta ?x)";
let ast = ast::Package::from_str(text).unwrap();
let bump = Bump::new();
assert!(ast.resolve(&bump).is_err());
}
}
27 changes: 14 additions & 13 deletions hugr-model/src/v0/scope/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,23 @@ impl<'a> VarTable<'a> {
/// # Errors
///
/// Returns an error if the variable is not defined in the current scope.
///
/// # Panics
///
/// Panics if there are no open scopes.
pub fn resolve(&self, name: &'a str) -> Result<VarId, UnknownVarError<'a>> {
let scope = self.scopes.last().unwrap();
let scope = self.scopes.last().ok_or(UnknownVarError::Root(name))?;
let set_index = self
.vars
.get_index_of(&(scope.node, name))
.ok_or(UnknownVarError(scope.node, name))?;
.ok_or(UnknownVarError::WithinNode(scope.node, name))?;
let var_index = (set_index - scope.var_stack) as u16;
Ok(VarId(scope.node, var_index))
}

/// Check if a variable is visible in the current scope.
///
/// # Panics
///
/// Panics if there are no open scopes.
#[must_use]
pub fn is_visible(&self, var: VarId) -> bool {
let scope = self.scopes.last().unwrap();
let Some(scope) = self.scopes.last() else {
return false;
};

scope.node == var.0 && var.1 < scope.var_count
}

Expand Down Expand Up @@ -149,5 +144,11 @@ pub struct DuplicateVarError<'a>(NodeId, &'a str);

/// Error that occurs when a variable is not defined in the current scope.
#[derive(Debug, Clone, Error)]
#[error("can not resolve variable `{1}` in node {0}")]
pub struct UnknownVarError<'a>(NodeId, &'a str);
pub enum UnknownVarError<'a> {
/// Failed to resolve a variable when in scope of a node.
#[error("can not resolve variable `{1}` in node {0}")]
WithinNode(NodeId, &'a str),
/// Failed to resolve a variable when in the root scope.
#[error("can not resolve variable `{0}` in the root scope")]
Root(&'a str),
}
Loading