(module main)

(struct Packet
  (values (array i32 3))
  (labels (array string 2))
  (flags (array bool 2)))

(enum PacketState
  Missing
  (Live Packet)
  (Cached Packet))

(fn make_packet ((base i32) (head string)) -> Packet
  (Packet (values (array i32 base (+ base 1) (+ base 2))) (labels (array string head "tail")) (flags (array bool false true))))

(fn live ((packet Packet)) -> PacketState
  (PacketState.Live packet))

(fn cached ((packet Packet)) -> PacketState
  (PacketState.Cached packet))

(fn echo_state ((state PacketState)) -> PacketState
  state)

(fn local_state ((base i32) (head string)) -> PacketState
  (let state PacketState (PacketState.Live (make_packet base head)))
  state)

(fn call_state ((base i32) (head string)) -> PacketState
  (echo_state (cached (make_packet base head))))

(fn state_value ((state PacketState) (i i32)) -> i32
  (match state
    ((PacketState.Missing)
      0)
    ((PacketState.Live payload)
      (index (. payload values) i))
    ((PacketState.Cached payload)
      (index (. payload values) i))))

(fn state_label ((state PacketState) (i i32)) -> string
  (match state
    ((PacketState.Missing)
      "")
    ((PacketState.Live payload)
      (index (. payload labels) i))
    ((PacketState.Cached payload)
      (index (. payload labels) i))))

(fn state_flag ((state PacketState) (i i32)) -> bool
  (match state
    ((PacketState.Missing)
      false)
    ((PacketState.Live payload)
      (index (. payload flags) i))
    ((PacketState.Cached payload)
      (index (. payload flags) i))))

(test "struct payload missing arm"
  (= (state_value (PacketState.Missing) 0) 0))

(test "struct payload live constructor flow"
  (= (state_value (live (make_packet 7 "sun")) 2) 9))

(test "struct payload cached param return call flow"
  (= (state_value (call_state 7 "sun") 1) 8))

(test "struct payload string array field access"
  (= (state_label (call_state 7 "sun") 0) "sun"))

(test "struct payload bool array field access"
  (state_flag (call_state 7 "sun") 1))

(test "struct payload local return flow"
  (= (state_label (local_state 9 "orb") 1) "tail"))

(fn main () -> i32
  (state_value (call_state 7 "sun") 2))
