(module main)

(type Count i32)

(type Score Count)

(type Text string)

(type Counts (array Count 3))

(type CountVec (vec Count))

(type MaybeCount (option Count))

(type CountResult (result Count Count))

(struct Measurement
  (amount Count)
  (label Text))

(type Measure Measurement)

(enum Reading
  Empty
  (Value Count))

(type ReadingAlias Reading)

(fn bump ((value Count)) -> Score
  (+ value 1))

(fn make_counts ((base Count)) -> Counts
  (array Count base (+ base 1) (+ base 2)))

(fn pick_count ((values Counts)) -> Count
  (index values 1))

(fn make_measure ((amount Count)) -> Measure
  (Measurement (amount amount) (label "ok")))

(fn measure_amount ((measure Measure)) -> Count
  (. measure amount))

(fn maybe_amount ((amount Count)) -> MaybeCount
  (some Count amount))

(fn maybe_empty () -> MaybeCount
  (none Count))

(fn ok_amount ((amount Count)) -> CountResult
  (ok Count Count amount))

(fn err_amount ((code Count)) -> CountResult
  (err Count Count code))

(fn empty_counts () -> CountVec
  (std.vec.i32.empty))

(fn reading_value ((amount Count)) -> ReadingAlias
  (Reading.Value amount))

(fn reading_score ((reading ReadingAlias)) -> Count
  (match reading
    ((Reading.Empty)
      0)
    ((Reading.Value amount)
      amount)))

(fn main () -> i32
  (let values Counts (make_counts 40))
  (+ (pick_count values) (measure_amount (make_measure 1))))

(test "aliases erase through arrays and structs"
  (= (main) 42))

(test "aliases erase through option result vec and enum"
  (let maybe MaybeCount (maybe_amount 7))
  (let result CountResult (ok_amount 8))
  (and (is_some maybe) (and (is_ok result) (and (= (std.vec.i32.len (empty_counts)) 0) (= (reading_score (reading_value 9)) 9)))))
