(module vec_bool (export empty append len at singleton append2 append3 pair triple is_empty index_or first_or last_or index_option first_option last_option index_of_option last_index_of_option contains count_of concat take starts_with without_prefix ends_with without_suffix drop reverse subvec insert_at insert_range replace_at replace_range remove_at remove_range))

(fn empty () -> (vec bool)
  (std.vec.bool.empty))

(fn append ((values (vec bool)) (value bool)) -> (vec bool)
  (std.vec.bool.append values value))

(fn len ((values (vec bool))) -> i32
  (std.vec.bool.len values))

(fn at ((values (vec bool)) (position i32)) -> bool
  (std.vec.bool.index values position))

(fn singleton ((value bool)) -> (vec bool)
  (append (empty) value))

(fn append2 ((values (vec bool)) (first bool) (second bool)) -> (vec bool)
  (append (append values first) second))

(fn append3 ((values (vec bool)) (first bool) (second bool) (third bool)) -> (vec bool)
  (append (append2 values first second) third))

(fn pair ((first bool) (second bool)) -> (vec bool)
  (append2 (empty) first second))

(fn triple ((first bool) (second bool) (third bool)) -> (vec bool)
  (append3 (empty) first second third))

(fn is_empty ((values (vec bool))) -> bool
  (= (len values) 0))

(fn index_or ((values (vec bool)) (position i32) (fallback bool)) -> bool
  (if (< position 0)
    fallback
    (if (< position (len values))
      (at values position)
      fallback)))

(fn first_or ((values (vec bool)) (fallback bool)) -> bool
  (index_or values 0 fallback))

(fn last_or ((values (vec bool)) (fallback bool)) -> bool
  (if (is_empty values)
    fallback
    (at values (- (len values) 1))))

(fn index_option ((values (vec bool)) (position i32)) -> (option bool)
  (if (< position 0)
    (none bool)
    (if (< position (len values))
      (some bool (at values position))
      (none bool))))

(fn first_option ((values (vec bool))) -> (option bool)
  (index_option values 0))

(fn last_option ((values (vec bool))) -> (option bool)
  (if (is_empty values)
    (none bool)
    (some bool (at values (- (len values) 1)))))

(fn index_of_option_loop ((values (vec bool)) (target bool) (position i32) (values_len i32)) -> (option i32)
  (if (< position values_len)
    (if (= (at values position) target)
      (some i32 position)
      (index_of_option_loop values target (+ position 1) values_len))
    (none i32)))

(fn index_of_option ((values (vec bool)) (target bool)) -> (option i32)
  (index_of_option_loop values target 0 (len values)))

(fn last_index_of_option_loop ((values (vec bool)) (target bool) (position i32) (values_len i32) (found_position (option i32))) -> (option i32)
  (if (< position values_len)
    (last_index_of_option_loop values target (+ position 1) values_len (if (= (at values position) target)
      (some i32 position)
      found_position))
    found_position))

(fn last_index_of_option ((values (vec bool)) (target bool)) -> (option i32)
  (last_index_of_option_loop values target 0 (len values) (none i32)))

(fn contains_loop ((values (vec bool)) (target bool) (position i32) (values_len i32)) -> bool
  (if (< position values_len)
    (if (= (at values position) target)
      true
      (contains_loop values target (+ position 1) values_len))
    false))

(fn contains ((values (vec bool)) (target bool)) -> bool
  (contains_loop values target 0 (len values)))

(fn count_of_loop ((values (vec bool)) (target bool) (position i32) (values_len i32) (hits i32)) -> i32
  (if (< position values_len)
    (count_of_loop values target (+ position 1) values_len (+ hits (if (= (at values position) target)
      1
      0)))
    hits))

(fn count_of ((values (vec bool)) (target bool)) -> i32
  (count_of_loop values target 0 (len values) 0))

(fn concat_loop ((result (vec bool)) (right (vec bool)) (position i32) (right_len i32)) -> (vec bool)
  (if (< position right_len)
    (concat_loop (append result (at right position)) right (+ position 1) right_len)
    result))

(fn concat ((left (vec bool)) (right (vec bool))) -> (vec bool)
  (let right_len i32 (len right))
  (concat_loop left right 0 right_len))

(fn take_loop ((values (vec bool)) (position i32) (limit i32) (result (vec bool))) -> (vec bool)
  (if (< position limit)
    (take_loop values (+ position 1) limit (append result (at values position)))
    result))

(fn take ((values (vec bool)) (count i32)) -> (vec bool)
  (let values_len i32 (len values))
  (if (< count 0)
    (empty)
    (if (< count values_len)
      (take_loop values 0 count (empty))
      values)))

(fn starts_with ((values (vec bool)) (prefix (vec bool))) -> bool
  (let prefix_len i32 (len prefix))
  (if (< (len values) prefix_len)
    false
    (= (take values prefix_len) prefix)))

(fn without_prefix ((values (vec bool)) (prefix (vec bool))) -> (vec bool)
  (if (starts_with values prefix)
    (drop values (len prefix))
    values))

(fn ends_with ((values (vec bool)) (suffix (vec bool))) -> bool
  (let values_len i32 (len values))
  (let suffix_len i32 (len suffix))
  (if (< values_len suffix_len)
    false
    (= (drop values (- values_len suffix_len)) suffix)))

(fn without_suffix ((values (vec bool)) (suffix (vec bool))) -> (vec bool)
  (if (ends_with values suffix)
    (take values (- (len values) (len suffix)))
    values))

(fn drop_loop ((values (vec bool)) (position i32) (values_len i32) (result (vec bool))) -> (vec bool)
  (if (< position values_len)
    (drop_loop values (+ position 1) values_len (append result (at values position)))
    result))

(fn drop ((values (vec bool)) (count i32)) -> (vec bool)
  (let values_len i32 (len values))
  (if (< count 0)
    values
    (if (< count values_len)
      (drop_loop values count values_len (empty))
      (empty))))

(fn reverse_loop ((values (vec bool)) (position i32) (result (vec bool))) -> (vec bool)
  (if (< position 0)
    result
    (reverse_loop values (- position 1) (append result (at values position)))))

(fn reverse ((values (vec bool))) -> (vec bool)
  (reverse_loop values (- (len values) 1) (empty)))

(fn subvec ((values (vec bool)) (start i32) (end_exclusive i32)) -> (vec bool)
  (if (< start 0)
    (empty)
    (if (< start end_exclusive)
      (take (drop values start) (- end_exclusive start))
      (empty))))

(fn insert_at ((values (vec bool)) (position i32) (value bool)) -> (vec bool)
  (let values_len i32 (len values))
  (if (< position 0)
    values
    (if (< position values_len)
      (concat (append (take values position) value) (drop values position))
      (if (= position values_len)
        (append values value)
        values))))

(fn insert_range ((values (vec bool)) (position i32) (inserted (vec bool))) -> (vec bool)
  (let values_len i32 (len values))
  (if (< position 0)
    values
    (if (< position values_len)
      (concat (concat (take values position) inserted) (drop values position))
      (if (= position values_len)
        (concat values inserted)
        values))))

(fn replace_at ((values (vec bool)) (position i32) (replacement bool)) -> (vec bool)
  (if (< position 0)
    values
    (if (< position (len values))
      (concat (append (take values position) replacement) (drop values (+ position 1)))
      values)))

(fn replace_range ((values (vec bool)) (start i32) (end_exclusive i32) (replacement (vec bool))) -> (vec bool)
  (let values_len i32 (len values))
  (if (< start 0)
    values
    (if (< start values_len)
      (if (< start end_exclusive)
        (concat (concat (take values start) replacement) (drop values end_exclusive))
        values)
      values)))

(fn remove_at ((values (vec bool)) (position i32)) -> (vec bool)
  (if (< position 0)
    values
    (if (< position (len values))
      (concat (take values position) (drop values (+ position 1)))
      values)))

(fn remove_range ((values (vec bool)) (start i32) (end_exclusive i32)) -> (vec bool)
  (let values_len i32 (len values))
  (if (< start 0)
    values
    (if (< start values_len)
      (if (< start end_exclusive)
        (concat (take values start) (drop values end_exclusive))
        values)
      values)))
