use harn_parser::{BindingPattern, Node, SNode};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum DefKind {
Function,
Pipeline,
Tool,
Skill,
EvalPack,
Struct,
Enum,
Interface,
Type,
Variable,
Parameter,
}
impl DefKind {
pub const fn has_runtime_value(self) -> bool {
!matches!(self, Self::Type | Self::Interface | Self::Parameter)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PublicDeclaration {
pub name: String,
pub kind: DefKind,
}
pub fn public_declarations(snode: &SNode) -> Vec<PublicDeclaration> {
match &snode.node {
Node::AttributedDecl { inner, .. } => public_declarations(inner),
Node::FnDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Function),
Node::Pipeline {
name, is_pub: true, ..
} => declaration(name, DefKind::Pipeline),
Node::ToolDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Tool),
Node::SkillDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Skill),
Node::EvalPackDecl {
binding_name,
is_pub: true,
..
} => declaration(binding_name, DefKind::EvalPack),
Node::StructDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Struct),
Node::EnumDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Enum),
Node::InterfaceDecl { name, .. } => declaration(name, DefKind::Interface),
Node::TypeDecl {
name, is_pub: true, ..
} => declaration(name, DefKind::Type),
Node::LetBinding {
pattern,
is_pub: true,
..
}
| Node::ConstBinding {
pattern,
is_pub: true,
..
} => pattern_names(pattern)
.into_iter()
.map(|name| PublicDeclaration {
name,
kind: DefKind::Variable,
})
.collect(),
_ => Vec::new(),
}
}
fn declaration(name: &str, kind: DefKind) -> Vec<PublicDeclaration> {
vec![PublicDeclaration {
name: name.to_string(),
kind,
}]
}
pub(crate) fn pattern_names(pattern: &BindingPattern) -> Vec<String> {
match pattern {
BindingPattern::Identifier(name) => vec![name.clone()],
BindingPattern::Dict(fields) => fields
.iter()
.filter_map(|field| field.alias.as_ref().or(Some(&field.key)).cloned())
.collect(),
BindingPattern::List(elements) => elements
.iter()
.map(|element| element.name.clone())
.collect(),
BindingPattern::Pair(a, b) => vec![a.clone(), b.clone()],
}
}