nested_macro/
nested_macro.rs

1/// Example: Nested Structures with Macros
2///
3/// This example demonstrates how the macro system handles complex nested structures.
4/// Compare this with `nested_parsing.rs` which manually builds ~90 lines of IR!
5///
6/// To run this example:
7/// ```bash
8/// cargo run --example nested_macro
9/// ```
10
11use simplify_baml::*;
12use simplify_baml_macros::BamlSchema;
13
14// Define complex nested types using macros - so much cleaner!
15
16#[derive(BamlSchema)]
17enum Role {
18    #[allow(dead_code)]
19    engineer,
20    #[allow(dead_code)]
21    manager,
22    #[allow(dead_code)]
23    designer,
24}
25
26#[derive(BamlSchema)]
27struct Address {
28    #[allow(dead_code)]
29    street: String,
30    #[allow(dead_code)]
31    city: String,
32    #[allow(dead_code)]
33    #[baml(rename = "zipCode")]
34    zip_code: String,
35}
36
37#[derive(BamlSchema)]
38struct Employee {
39    #[allow(dead_code)]
40    name: String,
41    #[allow(dead_code)]
42    age: i64,
43    #[allow(dead_code)]
44    role: Role,
45}
46
47#[derive(BamlSchema)]
48struct Company {
49    #[allow(dead_code)]
50    name: String,
51    #[allow(dead_code)]
52    employees: Vec<Employee>,
53    #[allow(dead_code)]
54    address: Address,
55}
56
57fn main() {
58    println!("=== Nested Structures with Macros ===\n");
59
60    // Build IR with automatic nesting resolution
61    let ir = BamlSchemaRegistry::new()
62        .register::<Role>()
63        .register::<Address>()
64        .register::<Employee>()
65        .register::<Company>()
66        .build();
67
68    println!("āœ… Generated IR with {} classes and {} enums:",
69        ir.classes.len(),
70        ir.enums.len()
71    );
72    println!();
73
74    // Show what was generated
75    for enum_def in &ir.enums {
76        println!("šŸ“‹ Enum: {}", enum_def.name);
77        println!("   Variants: {}", enum_def.values.join(", "));
78        println!();
79    }
80
81    for class in &ir.classes {
82        println!("šŸ“¦ Class: {}", class.name);
83        for field in &class.fields {
84            let optional = if field.optional { " (optional)" } else { "" };
85            println!("   - {}: {}{}",
86                field.name,
87                field.field_type.to_string(),
88                optional
89            );
90        }
91        println!();
92    }
93
94    // Test parsing with the generated IR
95    let parser = simplify_baml::parser::Parser::new(&ir);
96
97    let test_json = r#"
98    {
99        "name": "TechCorp",
100        "employees": [
101            {
102                "name": "Alice",
103                "age": 30,
104                "role": "engineer"
105            },
106            {
107                "name": "Bob",
108                "age": 35,
109                "role": "manager"
110            }
111        ],
112        "address": {
113            "street": "123 Main St",
114            "city": "San Francisco",
115            "zipCode": "94102"
116        }
117    }
118    "#;
119
120    match parser.parse(test_json, &FieldType::Class("Company".to_string())) {
121        Ok(result) => {
122            println!("āœ… Successfully parsed nested JSON!");
123            println!("{:#?}", result);
124        }
125        Err(e) => {
126            println!("āŒ Parse error: {}", e);
127        }
128    }
129
130    println!("\n=== Code Comparison ===");
131    println!("Manual IR building (nested_parsing.rs): ~90 lines");
132    println!("With macros (this file): ~40 lines of definitions");
133    println!("Reduction: ~55% less code!");
134    println!("\n✨ The macro handles:");
135    println!("  • Nested structs (Company contains Address)");
136    println!("  • Lists of structs (Vec<Employee>)");
137    println!("  • Enum fields (Role in Employee)");
138    println!("  • Field renaming (zip_code → zipCode)");
139}