finx 0.1.0

A fast, lightweight embeddable scripting language
Documentation
//! Closure Demo - Demonstrates native functions with closures and captured state
//!
//! This example shows the power of the new closure-based native function system,
//! allowing native functions to capture variables from their environment.

use finx::{Finx, Value};
use std::cell::RefCell;
use std::rc::Rc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Finx Closure Demo ===\n");

    let mut engine = Finx::new();

    // Example 1: Simple closure with captured constant
    println!("1. Simple Closure with Captured Constant:");
    let multiplier = 5.0;
    engine.register_function(
        "times_five",
        Rc::new(move |args| {
            if let [Value::Number(n)] = args {
                Value::Number(n * multiplier)
            } else {
                Value::Null
            }
        }),
        1,
    );

    let result = engine.eval("times_five(7)")?;
    println!("  times_five(7) = {}", result);

    // Example 2: Closure with mutable captured state
    println!("\n2. Closure with Mutable Captured State:");
    let counter = Rc::new(RefCell::new(0));
    let counter_clone = counter.clone();

    engine.register_function(
        "next_id",
        Rc::new(move |_args| {
            let mut count = counter_clone.borrow_mut();
            *count += 1;
            Value::Number(*count as f64)
        }),
        0,
    );

    for _ in 0..5 {
        let result = engine.eval("next_id()")?;
        println!("  next_id() = {}", result);
    }

    // Example 3: Closure capturing configuration
    println!("\n3. Closure with Configuration:");
    let config = "Hello from Rust";
    engine.register_function(
        "rust_greet",
        Rc::new(move |args| {
            if let [Value::Str(name)] = args {
                Value::Str(format!("{}, {}!", config, name).into())
            } else {
                Value::Null
            }
        }),
        1,
    );

    let result = engine.eval(r#"rust_greet("World")"#)?;
    println!("  rust_greet(\"World\") = {}", result);

    // Example 4: Multiple closures sharing state
    println!("\n4. Multiple Closures Sharing State:");
    let shared_data = Rc::new(RefCell::new(vec![1.0, 2.0, 3.0]));

    // Add to list
    let data_clone = shared_data.clone();
    engine.register_function(
        "add_to_list",
        Rc::new(move |args| {
            if let [Value::Number(n)] = args {
                data_clone.borrow_mut().push(*n);
                Value::Bool(true)
            } else {
                Value::Bool(false)
            }
        }),
        1,
    );

    // Get list sum
    let data_clone2 = shared_data.clone();
    engine.register_function(
        "list_sum",
        Rc::new(move |_args| {
            let sum: f64 = data_clone2.borrow().iter().sum();
            Value::Number(sum)
        }),
        0,
    );

    // Get list length
    let data_clone3 = shared_data.clone();
    engine.register_function(
        "list_len",
        Rc::new(move |_args| Value::Number(data_clone3.borrow().len() as f64)),
        0,
    );

    println!(
        "  Initial: sum = {}, len = {}",
        engine.eval("list_sum()")?,
        engine.eval("list_len()")?
    );

    engine.eval("add_to_list(10)")?;
    engine.eval("add_to_list(20)")?;

    println!(
        "  After adding 10 and 20: sum = {}, len = {}",
        engine.eval("list_sum()")?,
        engine.eval("list_len()")?
    );

    // Example 5: Using the convenience macro with closures
    println!("\n5. Using the register_function! Macro:");
    let base_value = 100.0;
    engine.register_closure(
        "add_base",
        move |args| {
            if let [Value::Number(n)] = args {
                Value::Number(n + base_value)
            } else {
                Value::Null
            }
        },
        1,
    );

    let result = engine.eval("add_base(42)")?;
    println!("  add_base(42) = {}", result);

    println!("\n=== Closure Demo completed successfully! ===");

    Ok(())
}