use grift_eval::{
Lisp, Evaluator, ArenaIndex, ArenaResult, ToLisp, extract_arg,
};
fn native_double<const N: usize>(lisp: &Lisp<N>, args: ArenaIndex) -> ArenaResult<ArenaIndex> {
let (x, _rest): (isize, _) = extract_arg(lisp, args)?;
(x * 2).to_lisp(lisp)
}
fn native_max<const N: usize>(lisp: &Lisp<N>, args: ArenaIndex) -> ArenaResult<ArenaIndex> {
let (a, rest): (isize, _) = extract_arg(lisp, args)?;
let (b, _rest): (isize, _) = extract_arg(lisp, rest)?;
(if a > b { a } else { b }).to_lisp(lisp)
}
fn native_evenp<const N: usize>(lisp: &Lisp<N>, args: ArenaIndex) -> ArenaResult<ArenaIndex> {
let (x, _rest): (isize, _) = extract_arg(lisp, args)?;
(x % 2 == 0).to_lisp(lisp)
}
fn native_square<const N: usize>(lisp: &Lisp<N>, args: ArenaIndex) -> ArenaResult<ArenaIndex> {
let (x, _rest): (isize, _) = extract_arg(lisp, args)?;
(x * x).to_lisp(lisp)
}
fn native_clamp<const N: usize>(lisp: &Lisp<N>, args: ArenaIndex) -> ArenaResult<ArenaIndex> {
let (value, rest): (isize, _) = extract_arg(lisp, args)?;
let (min_val, rest): (isize, _) = extract_arg(lisp, rest)?;
let (max_val, _rest): (isize, _) = extract_arg(lisp, rest)?;
let clamped = if value < min_val {
min_val
} else if value > max_val {
max_val
} else {
value
};
clamped.to_lisp(lisp)
}
fn main() {
println!("=== Native Function Interop Example ===\n");
let lisp: Lisp<20000> = Lisp::new();
let mut eval = Evaluator::new(&lisp).unwrap();
eval.register_native("double", native_double).unwrap();
eval.register_native("my-max", native_max).unwrap();
eval.register_native("even?", native_evenp).unwrap();
eval.register_native("square", native_square).unwrap();
eval.register_native("clamp", native_clamp).unwrap();
println!("Registered native functions: double, my-max, even?, square, clamp\n");
let tests = [
("(double 21)", "Doubling 21"),
("(my-max 5 10)", "Max of 5 and 10"),
("(my-max 100 50)", "Max of 100 and 50"),
("(even? 4)", "Is 4 even?"),
("(even? 7)", "Is 7 even?"),
("(square 8)", "Square of 8"),
("(clamp 50 0 100)", "Clamp 50 to [0, 100]"),
("(clamp -10 0 100)", "Clamp -10 to [0, 100]"),
("(clamp 150 0 100)", "Clamp 150 to [0, 100]"),
("(+ 10 9)", "Simple addition"),
("(double 5)", "Double 5"),
("(square 3)", "Square 3"),
];
for (expr, desc) in tests {
match eval.eval_str(expr) {
Ok(result) => {
let value = lisp.get(result).unwrap();
println!("{}: {} => {:?}", desc, expr, value);
}
Err(e) => {
println!("{}: {} => ERROR: {:?}", desc, expr, e.kind);
}
}
}
println!("\n--- Using native functions in Lisp expressions ---\n");
let complex_tests = [
"(+ (double 5) (square 3))", "(if (even? 10) 'yes 'no)", "(my-max (square 5) (double 12))", "(define (double-then-square x) (square (double x)))",
"(double-then-square 3)", ];
for expr in complex_tests {
match eval.eval_str(expr) {
Ok(result) => {
let value = lisp.get(result).unwrap();
println!("{} => {:?}", expr, value);
}
Err(e) => {
println!("{} => ERROR: {:?}", expr, e.kind);
}
}
}
println!("\n=== Example Complete ===");
}