eclisp 0.2.0-beta.0

Bindings for Embeddable Common Lisp
use eclisp::{Lisp, LispClass, LispError, lisp_impl};

struct Transform {
    x: f32,
    y: f32,
}

#[derive(LispClass)]
#[lisp(name = "player", impl)]
struct Player {
    #[lisp]
    health: i32,

    #[lisp(name = "movement-speed")]
    speed: f32,

    transform: Transform,
}

#[lisp_impl]
impl Player {
    fn is_alive(&self) -> bool {
        self.health > 0
    }

    fn max_health() -> i32 {
        100
    }

    fn position_x(&self) -> f32 {
        self.transform.x
    }

    fn position_y(&self) -> f32 {
        self.transform.y
    }

    fn move_by(&mut self, dx: f32, dy: f32) {
        self.transform.x += dx * self.speed;
        self.transform.y += dy * self.speed;
    }
}

#[lisp_impl(name = "player_combat")]
impl Player {
    fn damage(&mut self, amount: i32) {
        self.health -= amount;
    }
}

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

    lisp.enter(|ctx| {
        ctx.defclass(Player::class())?;
        ctx.defimpl(player_combat::methods())?;

        let mut player = Player {
            health: 100,
            speed: 2.0,
            transform: Transform { x: 1.0, y: 2.0 },
        };

        ctx.with(&mut player, |obj| {
            let damage = ctx.int(25)?;
            ctx.call("player-damage", &[obj, &damage])?;

            let dx = ctx.float(5.0)?;
            let dy = ctx.float(10.0)?;
            ctx.call("player-move-by", &[obj, &dx, &dy])?;

            let alive = ctx.call("player-is-alive", &[obj])?;
            assert!(alive.try_as_bool()?);

            let x = ctx.call("player-position-x", &[obj])?;
            let y = ctx.call("player-position-y", &[obj])?;

            assert!((x.try_as_f64()? - 11.0).abs() < 0.001);
            assert!((y.try_as_f64()? - 22.0).abs() < 0.001);

            Ok(())
        })?;

        let maximum = ctx.eval("(player-max-health)")?;
        assert_eq!(maximum.try_as_i64()?, 100);

        assert_eq!(player.health, 75);
        assert_eq!(player.transform.x, 11.0);
        assert_eq!(player.transform.y, 22.0);

        println!("Health: {}", player.health);
        println!("Position: ({}, {})", player.transform.x, player.transform.y);
        println!("Maximum health: {}", maximum.try_as_i64()?);

        Ok::<(), LispError>(())
    })
}