; Benchmark scaffold fixture for local-machine array-struct-field timing
; comparisons only. Keep LOOP_COUNT and EXPECTED_CHECKSUM aligned with the
; C/Rust/Python fixtures. The runner supplies the loop count through stdin or
; argv so native compilers cannot fold the benchmark loop into a constant
; answer.

(module main)

(struct ArrayRecord
  (digits (array i32 8))
  (wides (array i64 2))
  (ratios (array f64 3))
  (flags (array bool 3))
  (words (array string 3)))

(fn loop_count () -> i32
  1000000)

(fn expected_checksum () -> i32
  3875011)

(fn parse_stdin_loop_count () -> (result i32 i32)
  (let input (result string i32) (std.io.read_stdin_result))
  (match input
    ((ok text)
      (std.string.parse_i32_result text))
    ((err code)
      (err i32 i32 code))))

(fn parse_arg_loop_count () -> (result i32 i32)
  (std.string.parse_i32_result (std.process.arg 1)))

(fn configured_stdin_loop_count () -> i32
  (let parsed_stdin (result i32 i32) (parse_stdin_loop_count))
  (if (is_ok parsed_stdin)
    (unwrap_ok parsed_stdin)
    (loop_count)))

(fn configured_loop_count () -> i32
  (let parsed_arg (result i32 i32) (parse_arg_loop_count))
  (if (is_ok parsed_arg)
    (unwrap_ok parsed_arg)
    (configured_stdin_loop_count)))

(fn make_record () -> ArrayRecord
  (ArrayRecord (digits (array i32 3 1 4 1 5 9 2 6)) (wides (array i64 40i64 41i64)) (ratios (array f64 1.5 2.5 3.5)) (flags (array bool false true true)) (words (array string "sun" "moon" "star"))))

(fn int_at ((record ArrayRecord) (i i32)) -> i32
  (index (. record digits) i))

(fn array_struct_field_loop ((limit i32)) -> i32
  (let record ArrayRecord (make_record))
  (var i i32 0)
  (var acc i32 11)
  (while (< i limit)
    (set acc (+ acc (int_at record (% i 8))))
    (set acc (if (> acc 1000000000)
      (- acc 1000000000)
      acc))
    (set i (+ i 1)))
  acc)

(fn main () -> i32
  (let result i32 (array_struct_field_loop (configured_loop_count)))
  (std.io.print_i32 result)
  (if (= result (expected_checksum))
    0
    1))

(test "array struct field loop checksum is deterministic"
  (= (array_struct_field_loop (loop_count)) (expected_checksum)))
