norename class array{X}

  builtin

noncreation

  length: int := builtin "array_length"(self)

  apply1(i: int): X := builtin "array_get"(self, i)

  infix =(other: array{X}): bool := builtin "eq"(self, other)

  infix <>(other: array{X}): bool := builtin "ne"(self, other)

  coerce to_array_ref: array_ref{X} := array_ref(self)

  private cmp_from(other: array{X}, from: int, cmp: fun2{X,X,int}): int :=
    if from >= length then
      if from >= other.length then 0 else -1 end
    elsif from >= other.length then
      1
    else
      let
        c := cmp(self(from), other(from))
      in
        if c = 0 then cmp_from(other, from + 1, cmp) else c end
      end
    end

  cmp(other: array{X}, c: fun2{X, X, int}): int := cmp_from(other, 0, c)

end


norename class array_ref{X} inherit fun1{int, X}

    coerce val: array{X}

noncreation

    apply1(i: int): X := val(i)

end
