eclisp 0.1.1

Bindings for Embeddable Common Lisp
use std::{cell::Cell, rc::Rc};

use eclisp::{Lisp, LispError};

fn main() -> Result<(), LispError> {
    let lisp = Lisp::new()?;

    lisp.enter(|ctx| -> Result<(), LispError> {
        let multiplier = 10;

        ctx.defun("multiply", move |ctx, args| {
            if args.len() != 1 {
                return Err(LispError::RuntimeError(
                    "multiply expects one argument".into(),
                ));
            }

            let value = args[0].try_as_i64()?;
            ctx.int(value * multiplier)
        })?;

        let result = ctx.eval("(multiply 5)")?;
        println!("Result of (multiply 5): {:?}", result.try_as_i64());

        let counter = Rc::new(Cell::new(0));
        let captured = Rc::clone(&counter);

        ctx.defun("increment", move |ctx, args| {
            if !args.is_empty() {
                return Err(LispError::RuntimeError(
                    "increment expects no arguments".into(),
                ));
            }

            let value = captured.get() + 1;
            captured.set(value);

            ctx.int(value)
        })?;

        println!("Counter before increment: {}", counter.get());
        println!(
            "Result of (increment): {:?}",
            ctx.eval("(increment)")?.try_as_i64()
        );
        println!("Counter after increment: {}", counter.get());

        Ok(())
    })?;

    Ok(())
}