use std::sync::Arc;
use lex_ast::canonicalize_program;
use lex_bytecode::vm::Vm;
use lex_bytecode::{compile_program, Value};
use lex_syntax::parse_source;
const SRC: &str = r#"
type Response = { status :: Int, body :: Str, total :: Int }
fn handler() -> Response {
{ status: 200, body: "hello", total: 42 }
}
"#;
fn main() {
let iters: u64 = std::env::args().nth(1).and_then(|s| s.parse().ok()).unwrap_or(10_000);
let slab_direct = std::env::var_os("LEX_PROFILE_SLAB_DIRECT").is_some();
let prog = parse_source(SRC).expect("parse");
let stages = canonicalize_program(&prog);
lex_types::check_program(&stages).expect("typecheck");
let p = Arc::new(compile_program(&stages));
let handler_id = p.function_names["handler"];
let mut vm = Vm::new(&p);
vm.set_step_limit(u64::MAX);
let mut acc = 0i64;
for _ in 0..iters {
let scope = vm.enter_request_scope();
let resp = vm.invoke(handler_id, vec![]).unwrap();
debug_assert!(matches!(resp, Value::ArenaRecord { .. }),
"expected arena handle under active scope");
if slab_direct {
let status = vm.get_record_field(&resp, "status")
.and_then(|v| if let Value::Int(n) = v { Some(n) } else { None })
.unwrap_or(0);
let body_len = match vm.get_record_field(&resp, "body") {
Some(Value::Str(s)) => s.len() as i64,
_ => 0,
};
let total = vm.get_record_field(&resp, "total")
.and_then(|v| if let Value::Int(n) = v { Some(n) } else { None })
.unwrap_or(0);
acc = acc.wrapping_add(status).wrapping_add(body_len).wrapping_add(total);
} else {
let materialized = vm.materialize_arena_handles(resp);
if let Value::Record { fields, .. } = &materialized {
let status = fields.get("status")
.and_then(|v| if let Value::Int(n) = v { Some(*n) } else { None })
.unwrap_or(0);
let body_len = match fields.get("body") {
Some(Value::Str(s)) => s.len() as i64,
_ => 0,
};
let total = fields.get("total")
.and_then(|v| if let Value::Int(n) = v { Some(*n) } else { None })
.unwrap_or(0);
acc = acc.wrapping_add(status).wrapping_add(body_len).wrapping_add(total);
}
}
vm.exit_request_scope(scope);
}
eprintln!("[diag] slab_direct={slab_direct}, iters={iters}, acc={acc}");
eprintln!("[diag] arena_allocs={}, arena_fallbacks={}",
vm.arena_record_allocs, vm.arena_record_heap_fallbacks);
std::process::exit((acc & 0x7f) as i32);
}