module T = Sx_types
module P = Sx_parser
module R = Sx_ref
open T

let () =
  let env = T.make_env () in
  let eval src =
    let exprs = P.parse_all src in
    let result = ref Nil in
    List.iter (fun e -> result := R.eval_expr e (Env env)) exprs;
    !result
  in
  (* Test 1: basic set! in closure *)
  let r = eval "(let ((x 0)) (set! x 42) x)" in
  Printf.printf "basic set!: %s (expect 42)\n%!" (T.inspect r);

  (* Test 2: set! through lambda call *)
  let r = eval "(let ((x 0)) (let ((f (fn () (set! x 99)))) (f) x))" in
  Printf.printf "set! via lambda: %s (expect 99)\n%!" (T.inspect r);

  (* Test 3: counter pattern *)
  let r = eval "(do (define make-counter (fn () (let ((c 0)) (fn () (set! c (+ c 1)) c)))) (let ((counter (make-counter))) (counter) (counter) (counter)))" in
  Printf.printf "counter: %s (expect 3)\n%!" (T.inspect r);

  (* Test 4: set! in for-each *)
  let r = eval "(let ((total 0)) (for-each (fn (n) (set! total (+ total n))) (list 1 2 3 4 5)) total)" in
  Printf.printf "set! in for-each: %s (expect 15)\n%!" (T.inspect r);

  (* Test 5: append! in for-each *)
  ignore (T.env_bind env "append!" (NativeFn ("append!", fun args ->
    match args with
    | [List items; v] -> List (items @ [v])
    | _ -> raise (Eval_error "append!: expected list and value"))));
  let r = eval "(let ((log (list))) (for-each (fn (x) (append! log x)) (list 1 2 3)) log)" in
  Printf.printf "append! in for-each: %s (expect (1 2 3))\n%!" (T.inspect r)
