use harn_parser::{Node, SNode};
use super::{Compiler, EnumCatalogSnapshot};
impl Compiler {
pub(super) fn enum_catalog_snapshot(&self) -> EnumCatalogSnapshot {
EnumCatalogSnapshot {
names: self.enum_names.clone(),
variant_owners: self.enum_variant_owners.clone(),
}
}
pub(super) fn restore_enum_catalog(&mut self, snapshot: EnumCatalogSnapshot) {
self.enum_names = snapshot.names;
self.enum_variant_owners = snapshot.variant_owners;
}
pub(super) fn register_enum_decl(&mut self, name: &str, variants: &[harn_parser::EnumVariant]) {
for owners in self.enum_variant_owners.values_mut() {
owners.retain(|owner| owner != name);
}
self.enum_variant_owners
.retain(|_, owners| !owners.is_empty());
self.enum_names.insert(name.to_string());
for variant in variants {
let owners = self
.enum_variant_owners
.entry(variant.name.clone())
.or_default();
if !owners.iter().any(|owner| owner == name) {
owners.push(name.to_string());
}
}
}
pub(super) fn collect_module_enum_catalog(&mut self, program: &[SNode]) {
for nodes in harn_parser::lexical::module_scope_node_slices(program) {
for node in nodes {
let declaration = match &node.node {
Node::AttributedDecl { inner, .. } => inner.as_ref(),
_ => node,
};
if let Node::EnumDecl { name, variants, .. } = &declaration.node {
self.register_enum_decl(name, variants);
}
}
}
for node in program {
let declaration = match &node.node {
Node::AttributedDecl { inner, .. } => inner.as_ref(),
_ => node,
};
if matches!(&declaration.node, Node::EnumDecl { .. }) {
self.predeclared_enum_declarations
.insert((declaration.span.start, declaration.span.end));
}
}
}
pub(super) fn seed_builtin_variant_owners(
owners: &mut std::collections::HashMap<String, Vec<String>>,
) {
for variant in ["Ok", "Err"] {
let entry = owners.entry(variant.to_string()).or_default();
if !entry.iter().any(|owner| owner == "Result") {
entry.push("Result".to_string());
}
}
}
pub(super) fn collect_struct_layouts(
nodes: &[SNode],
layouts: &mut std::collections::HashMap<String, Vec<String>>,
) {
for sn in nodes {
match &sn.node {
Node::StructDecl { name, fields, .. } => {
layouts.insert(
name.clone(),
fields.iter().map(|field| field.name.clone()).collect(),
);
}
Node::Pipeline { body, .. }
| Node::FnDecl { body, .. }
| Node::ToolDecl { body, .. } => Self::collect_struct_layouts(body, layouts),
Node::SkillDecl { fields, .. } => {
for (_, value) in fields {
Self::collect_struct_layouts(std::slice::from_ref(value), layouts);
}
}
Node::EvalPackDecl {
fields,
body,
summarize,
..
} => {
for (_, value) in fields {
Self::collect_struct_layouts(std::slice::from_ref(value), layouts);
}
Self::collect_struct_layouts(body, layouts);
if let Some(summary_body) = summarize {
Self::collect_struct_layouts(summary_body, layouts);
}
}
Node::Block(stmts) => Self::collect_struct_layouts(stmts, layouts),
Node::AttributedDecl { inner, .. } => {
Self::collect_struct_layouts(std::slice::from_ref(inner), layouts);
}
_ => {}
}
}
}
pub(super) fn collect_interface_methods(
nodes: &[SNode],
interfaces: &mut std::collections::HashMap<String, Vec<String>>,
) {
for sn in nodes {
match &sn.node {
Node::InterfaceDecl { name, methods, .. } => {
interfaces.insert(
name.clone(),
methods.iter().map(|method| method.name.clone()).collect(),
);
}
Node::Pipeline { body, .. }
| Node::FnDecl { body, .. }
| Node::ToolDecl { body, .. } => {
Self::collect_interface_methods(body, interfaces);
}
Node::SkillDecl { fields, .. } => {
for (_, value) in fields {
Self::collect_interface_methods(std::slice::from_ref(value), interfaces);
}
}
Node::EvalPackDecl {
fields,
body,
summarize,
..
} => {
for (_, value) in fields {
Self::collect_interface_methods(std::slice::from_ref(value), interfaces);
}
Self::collect_interface_methods(body, interfaces);
if let Some(summary_body) = summarize {
Self::collect_interface_methods(summary_body, interfaces);
}
}
Node::Block(stmts) => Self::collect_interface_methods(stmts, interfaces),
Node::AttributedDecl { inner, .. } => {
Self::collect_interface_methods(std::slice::from_ref(inner), interfaces);
}
_ => {}
}
}
}
}