//! Python tree structure generation. use std::collections::BTreeSet; use std::fmt::Write; use brk_types::TreeNode; use crate::{ ClientMetadata, LanguageSyntax, PatternField, PythonSyntax, build_child_path, generate_leaf_field, generate_tree_node_field, prepare_tree_node, }; /// Generate tree classes pub fn generate_tree_classes(output: &mut String, catalog: &TreeNode, metadata: &ClientMetadata) { writeln!(output, "# Series tree classes\n").unwrap(); let pattern_lookup = metadata.pattern_lookup(); let mut generated = BTreeSet::new(); generate_tree_class( output, "SeriesTree", "", catalog, pattern_lookup, metadata, &mut generated, ); } /// Recursively generate tree classes fn generate_tree_class( output: &mut String, name: &str, path: &str, node: &TreeNode, pattern_lookup: &std::collections::BTreeMap, String>, metadata: &ClientMetadata, generated: &mut BTreeSet, ) { let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else { return; }; // Generate child classes FIRST (post-order traversal) // This ensures children are defined before parent references them for child in &ctx.children { if child.should_inline { let child_path = build_child_path(path, child.name); generate_tree_class( output, &child.inline_type_name, &child_path, child.node, pattern_lookup, metadata, generated, ); } } // THEN generate the current class (after all children are defined) writeln!(output, "class {}:", name).unwrap(); writeln!(output, " \"\"\"Series tree node.\"\"\"").unwrap(); writeln!(output, " ").unwrap(); writeln!( output, " def __init__(self, client: BrkClient, base_path: str = ''):" ) .unwrap(); if ctx.children.is_empty() { writeln!(output, " pass").unwrap(); } let syntax = PythonSyntax; for child in &ctx.children { if child.is_leaf { if let TreeNode::Leaf(leaf) = child.node { generate_leaf_field( output, &syntax, "client", child.name, leaf, metadata, " ", ); } } else if child.should_inline { let field_name = syntax.field_name(child.name); writeln!( output, " self.{}: {} = {}(client)", field_name, child.inline_type_name, child.inline_type_name ) .unwrap(); } else { generate_tree_node_field( output, &syntax, &child.field, metadata, " ", "client", &child.base_result, ); } } writeln!(output).unwrap(); }