use luna_core::frontend::error::SyntaxError;
use luna_core::frontend::macro_expander::{Macro, MacroCtx};
use luna_core::frontend::token::{Token, TokenInfo};
use luna_core::version::LuaVersion;
use luna_core::vm::Vm;
struct DoubleMacro;
impl Macro for DoubleMacro {
fn expand(
&self,
args: &[Vec<TokenInfo>],
ctx: &mut MacroCtx<'_>,
) -> Result<Vec<TokenInfo>, SyntaxError> {
if args.len() != 1 {
return Err(SyntaxError::new(
ctx.line,
format!("@double expects 1 arg, got {}", args.len()).into_bytes(),
));
}
let span = ctx.span;
let line = ctx.line;
let mk = |tok| TokenInfo { tok, span, line };
let mut out = vec![mk(Token::LParen)];
out.extend(args[0].clone());
out.extend([mk(Token::Star), mk(Token::Int(2)), mk(Token::RParen)]);
Ok(out)
}
}
fn main() {
{
let mut vm = Vm::new(LuaVersion::MacroLua);
let r = vm
.eval("@if(true, @quote{ return 42 }, @quote{ return 0 })")
.expect("eval @if");
println!("1. @if(true, 42, 0) = {:?}", r);
}
{
let mut vm = Vm::new(LuaVersion::MacroLua);
vm.eval("local @gensym = 1 local @gensym = 2 return 0")
.expect("eval @gensym");
println!("2. @gensym minted two unique locals (no collision)");
}
{
let mut vm = Vm::new(LuaVersion::MacroLua);
vm.define_macro("double", Box::new(DoubleMacro));
let r = vm.eval("return @double(21)").expect("eval @double");
println!("3. @double(21) = {:?}", r);
let r2 = vm.eval("local y = 5; return @double(y)").expect("nested");
println!("4. @double(y) where y = 5 → {:?}", r2);
}
}