//! AVM Runner — CLI for cross-language dataset panel.
//!
//! Reads a program name from args, executes it, and prints JSON result.
//! Used by `python/avm_dataset_panel.py`.

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let prog_name = args.get(1).map(|s| s.as_str()).unwrap_or("add_q16");

    let (prog, locals) = match prog_name {
        "add_q16" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::AddSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "div_q16" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::DivSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "mul_q16" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::MulSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "sub_q16" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::SubSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "lt_q16" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::LtQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "eq_q16_true" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::EqQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "saturation" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(2147483646)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(2)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::AddSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "control_flow" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Bool(true)),
            silversight::avm::Instr::JumpIf(4),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(0)),
            silversight::avm::Instr::Halt,
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(65536)),
            silversight::avm::Instr::Halt,
        ], 0),
        "locals" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(42 * 65536)),
            silversight::avm::Instr::Store(0),
            silversight::avm::Instr::Load(0),
            silversight::avm::Instr::Halt,
        ], 1),
        "mul_div_rt" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::MulSatQ16),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::DivSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        "bool_logic" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Bool(true)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Bool(false)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::And),
            silversight::avm::Instr::Halt,
        ], 0),
        "complex_arithmetic" => (vec![
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(5 * 65536)),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(3 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::AddSatQ16),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(2 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::MulSatQ16),
            silversight::avm::Instr::Push(silversight::avm::AvmVal::Q16_16(4 * 65536)),
            silversight::avm::Instr::Prim(silversight::avm::Prim::DivSatQ16),
            silversight::avm::Instr::Halt,
        ], 0),
        _ => {
            eprintln!("Unknown program: {prog_name}");
            std::process::exit(1);
        }
    };

    let init_state = silversight::avm::State::new(locals);
    let state = silversight::avm::run(&init_state, &prog, 1000).unwrap_or_else(|e| {
        eprintln!("Error: {:?}", e);
        std::process::exit(1);
    });
    let stack_json: Vec<String> = state.stack.iter().map(|v| {
        match v {
            silversight::avm::AvmVal::Q0_16(x) => format!("{{\"ty\":\"q0_16\",\"val\":{}}}", x),
            silversight::avm::AvmVal::Q16_16(x) => format!("{{\"ty\":\"q16_16\",\"val\":{}}}", x),
            silversight::avm::AvmVal::Bool(b) => format!("{{\"ty\":\"bool\",\"val\":{}}}", b),
        }
    }).collect();
    println!("{{\"halted\":{},\"stack\":[{}],\"stack_depth\":{}}}",
        state.halted, stack_json.join(","), state.stack.len());
}
