(module main)

(enum Status Ready Blocked)

(enum Reading
  Missing
  (Value i32))

(struct TaggedReading
  (status Status)
  (reading Reading))

(fn make_tagged ((status Status) (reading Reading)) -> TaggedReading
  (TaggedReading (status status) (reading reading)))

(fn ready_value ((payload i32)) -> TaggedReading
  (make_tagged (Status.Ready) (Reading.Value payload)))

(fn missing_blocked () -> TaggedReading
  (make_tagged (Status.Blocked) (Reading.Missing)))

(fn echo_tagged ((tagged TaggedReading)) -> TaggedReading
  tagged)

(fn local_tagged ((payload i32)) -> TaggedReading
  (let tagged TaggedReading (ready_value payload))
  (echo_tagged tagged))

(fn status_of ((tagged TaggedReading)) -> Status
  (. tagged status))

(fn reading_of ((tagged TaggedReading)) -> Reading
  (. tagged reading))

(fn is_ready ((tagged TaggedReading)) -> bool
  (= (. tagged status) (Status.Ready)))

(fn reading_matches ((tagged TaggedReading) (reading Reading)) -> bool
  (= (. tagged reading) reading))

(fn reading_code ((tagged TaggedReading)) -> i32
  (match (. tagged reading)
    ((Reading.Missing)
      0)
    ((Reading.Value payload)
      payload)))

(test "enum struct field payloadless equality"
  (= (status_of (missing_blocked)) (Status.Blocked)))

(test "enum struct field unary payload equality"
  (reading_matches (ready_value 7) (Reading.Value 7)))

(test "enum struct field access return"
  (= (reading_of (missing_blocked)) (Reading.Missing)))

(test "enum struct field local param return call flow"
  (= (reading_code (local_tagged 9)) 9))

(test "enum struct field match missing"
  (= (reading_code (missing_blocked)) 0))

(test "enum struct field status predicate"
  (is_ready (ready_value 11)))

(fn main () -> i32
  (reading_code (local_tagged 42)))
