finx 0.1.0

A fast, lightweight embeddable scripting language
Documentation
//! Basic usage examples for Finx
//!
//! This example demonstrates the core features of Finx including:
//! - Basic arithmetic and expressions
//! - Variables and functions
//! - Native function registration
//! - Error handling

use finx::{Finx, FinxError, Value, register_function};
use std::rc::Rc;

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

    // Example 1: Basic arithmetic
    println!("1. Basic Arithmetic:");
    let mut engine = Finx::new();

    let result = engine.eval("2 + 3 * 4 - 1")?;
    println!("  2 + 3 * 4 - 1 = {}", result);

    let result = engine.eval("10 / 2 + 5")?;
    println!("  10 / 2 + 5 = {}", result);

    println!();

    // Example 2: Variables and functions
    println!("2. Variables and Functions:");

    engine.execute(
        r#"
        let pi = 3.14159;
        let radius = 5;
        
        fn circle_area(r) {
            return pi * r * r;
        }
        
        fn circle_circumference(r) {
            return 2 * pi * r;
        }
    "#,
    )?;

    let area = engine.eval("circle_area(radius)")?;
    let circumference = engine.eval("circle_circumference(radius)")?;

    println!(
        "  Circle with radius {}: area = {:.2}, circumference = {:.2}",
        engine.eval("radius")?,
        area,
        circumference
    );

    println!(); // Example 3: Native functions
    println!("3. Native Functions:");

    // Register some useful functions
    engine.register_function(
        "sqrt",
        Rc::new(|args| {
            if let [Value::Number(n)] = args {
                Value::Number(n.sqrt())
            } else {
                panic!("sqrt expects one number");
            }
        }),
        1,
    );

    register_function!(engine, "pow", 2, |base: f64, exp: f64| -> f64 {
        base.powf(exp)
    });

    register_function!(engine, "format", 2, |template: &str,

                                             value: f64|

     -> String {
        template.replace("{}", &value.to_string())
    });

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

    let result = engine.eval("pow(2, 8)")?;
    println!("  pow(2, 8) = {}", result);

    let result = engine.eval(r#"format("The answer is {}", 42)"#)?;
    println!("  format result: {}", result);

    println!();

    // Example 4: Closures and state
    println!("4. Closures and State:");

    engine.execute(
        r#"
        fn make_counter(start) {
            let count = start;
            
            fn increment() {
                count = count + 1;
                return count;
            }
            
            return increment;
        }
        
        let counter1 = make_counter(0);
        let counter2 = make_counter(100);
    "#,
    )?;

    for i in 1..=3 {
        let c1 = engine.eval("counter1()")?;
        let c2 = engine.eval("counter2()")?;
        println!("  Step {}: counter1 = {}, counter2 = {}", i, c1, c2);
    }

    println!();

    // Example 5: Control flow
    println!("5. Control Flow:");

    engine.execute(
        r#"
        fn fizzbuzz(n) {
            let i = 1;
            while i <= n {
                if i % 15 == 0 {
                    print("FizzBuzz");
                } else if i % 3 == 0 {
                    print("Fizz");
                } else if i % 5 == 0 {
                    print("Buzz");
                } else {
                    print(i);
                }
                i = i + 1;
            }
        }
    "#,
    )?;

    println!("  FizzBuzz for 1-15:");
    engine.execute("fizzbuzz(15)")?;

    let output = engine.get_output();
    println!("  Output: {}", output[output.len() - 15..].join(", "));

    println!();

    // Example 6: Error handling
    println!("6. Error Handling:");

    // This will cause a parse error
    match engine.eval("let = 42") {
        Ok(_) => println!("  Unexpected success"),
        Err(FinxError::ParseError(err)) => println!("  Parse error (expected): {}", err),
        Err(err) => println!("  Other error: {}", err),
    }

    // This will cause a runtime error
    match engine.eval("undefined_function()") {
        Ok(_) => println!("  Unexpected success"),
        Err(FinxError::RuntimeError(msg)) => println!("  Runtime error (expected): {}", msg),
        Err(err) => println!("  Other error: {}", err),
    }

    println!();
    println!("=== Examples completed successfully! ===");

    Ok(())
}