#define ATS_DYNLOADFLAG 0
abstype funarray_t (a:t@ype+ , n:int )
typedef farr (a: t@ype, n: int) = funarray_t (a, n) typedef farr (a: t@ype) = [n:nat] funarray_t (a, n)
extern fun{} funarray_nil {a:t@ype} ():<> farr (a, 0)
extern fun{} funarray_empty {a:t@ype} ():<> farr (a, 0)
extern fun{a:t@ype} funarray_length
{n:nat} (A: farr (a, n)):<> int n
extern fun{a:t@ype} funarray_get_elt_at
{n:nat} (A: farr (a, n), i: natLt n):<> a
extern fun{a:t@ype} funarray_set_elt_at
{n:nat} (A: farr (a, n), i: natLt n, x: a):<> farr (a, n)
overload [] with funarray_get_elt_at
overload [] with funarray_set_elt_at
extern fun{a:t@ype} funarray_get_elt_at_exn
{n:nat} (A: farr (a, n), i: Nat):<!exn> a
extern fun{a:t@ype} funarray_set_elt_at_exn
{n:nat} (A: farr (a, n), i: Nat, x: a):<!exn> farr (a, n)
extern fun{a:t@ype} funarray_xch_elt_at
{n:nat} (A: farr (a, n), i: natLt n, x: &a >> a):<> farr (a, n)
extern fun{a:t@ype} funarray_loadd
{n:nat} (A: farr (a, n), x: a):<> farr (a, n+1)
extern fun{a:t@ype} funarray_lorem
{n:pos} (A: farr (a, n)):<> farr (a, n-1)
extern fun{a:t@ype} funarray_lorem_get
{n:pos} (A: farr (a, n), x: &a? >> a):<> farr (a, n-1)
extern fun{a:t@ype} funarray_hiadd
{n:nat} (A: farr (a, n), n: int n, x: a):<> farr (a, n+1)
extern fun{a:t@ype} funarray_hirem
{n:pos} (A: farr (a, n), n: int n):<> farr (a, n-1)
extern fun{a:t@ype} funarray_hirem_get
{n:pos} (A: farr (a, n), n: int n, x: &a? >> a):<> farr (a, n-1)
extern fun{a:t@ype} funarray_foreach_clo {v:view} {n:nat}
(pf: !v | A: farr (a, n), n: int n, f: &(!v | a) -<clo> void):<> void
extern fun{a:t@ype} funarray_foreach_cloref {n:nat}
(A: farr (a, n), n: int n, f: a -<cloref> void):<!ref> void
extern fun{a:t@ype} funarray_iforeach_clo {v:view} {n:nat}
(pf: !v | A: farr (a, n), n: int n, f: &(!v | natLt n, a) -<clo> void):<> void
extern fun{a:t@ype} funarray_iforeach_cloref {n:nat}
(A: farr (a, n), n: int n, f: (natLt n, a) -<cloref> void):<!ref> void
datatype brauntree (a:t@ype+, int) =
| {n1,n2:nat | n2 <= n1; n1 <= n2+1}
B (a, n1+n2+1) of (a, brauntree (a, n1), brauntree (a, n2))
| E (a, 0) of ()
stadef bt = brauntree
assume funarray_t (a: t@ype, n:int) = brauntree (a, n)
implement{} funarray_nil {a} () = E ()
implement{} funarray_empty {a} () = E ()
implement{a} funarray_length (A) = size (A) where {
fun diff {nl,nr:nat | nr <= nl && nl <= nr+1} .<nr>.
(nr: int nr, t: bt (a, nl)):<> int (nl-nr) = begin case+ t of
| B (_, tl, tr) => begin
if nr > 0 then let
val nr2 = nr / 2
in
if nr > nr2 + nr2 then diff (nr2, tl) else diff (nr2-1, tr)
end else begin
1 end end | E () => 0
end
fun size {n:nat} .<n>. (t: bt (a, n)):<> int n = begin
case+ t of
| B (_, tl, tr) => begin
let val nr = size tr in 1 + nr + nr + diff (nr, tl) end
end | E () => 0
end }
implement{a} funarray_get_elt_at (A, i) = get_at (A, i) where {
fun get_at {n,i:nat | i < n} .<n>. (t: bt (a, n), i: int i):<> a =
if i > 0 then let
val i2 = i / 2
in
if i > i2 + i2 then let
val+ B (_, tl, _) = t in get_at (tl, i2)
end else let
val+ B (_, _, tr) = t in get_at (tr, i2-1)
end end else let
val+ B (x, _, _) = t in x
end }
implement{a} funarray_set_elt_at
(A, i, x0) = set_at (A, i, x0) where {
fun set_at {n,i:nat | i < n} .<n>.
(t: bt (a, n), i: int i, x0: a):<> bt (a, n) =
if i > 0 then let
val+ B (x, tl, tr) = t; val i2 = i / 2
in
if i > i2 + i2 then begin
B (x, set_at (tl, i2, x0), tr)
end else begin
B (x, tl, set_at (tr, i2-1, x0))
end end else let
val+ B (_, t1, t2) = t in B (x0, t1, t2)
end }
implement{a}
funarray_get_elt_at_exn (A, i) = get_at (A, i) where {
fun get_at {n,i:nat} .<n>. (t: bt (a, n), i: int i):<> a =
if i > 0 then let
val i2 = i / 2 in
if i > i2 + i2 then begin case+ t of
| B (_, tl, _) => get_at (tl, i2) | _ => $raise SubscriptException
end else begin case+ t of
| B (_, _, tr) => get_at (tr, i2-1) | _ => $raise SubscriptException
end end else begin case+ t of | B (x, _, _) => x | _ => $raise SubscriptException
end }
implement{a} funarray_set_elt_at_exn
(A, i, x0) = set_at (A, i, x0) where {
fun set_at {n,i:nat} .<n>.
(t: bt (a, n), i: int i, x0: a):<!exn> bt (a, n) =
if i > 0 then let
val i2 = i / 2
in
if i > i2 + i2 then begin case+ t of
| B (x, tl, tr) => let
val tl = set_at (tl, i2, x0) in B (x, tl, tr)
end | _ => $raise SubscriptException
end else begin case+ t of
| B (x, tl, tr) => let
val tr = set_at (tr, i2-1, x0) in B (x, tl, tr)
end | _ => $raise SubscriptException
end end else begin case+ t of | B (x, tl, tr) => B (x0, tl, tr) | _ => $raise SubscriptException
end }
implement{a} funarray_xch_elt_at
(A, i, x0) = xch_at (A, i, x0) where {
fun xch_at {n,i:nat | i < n} .<n>.
(t: bt (a, n), i: int i, x0: &a >> a):<> bt (a, n) =
if i > 0 then let
val+ B (x, tl, tr) = t; val i2 = i / 2
in
if i > i2 + i2 then begin
B (x, xch_at (tl, i2, x0), tr)
end else begin
B (x, tl, xch_at (tr, i2-1, x0))
end end else let
val x0_val = x0; val+ B (x, t1, t2) = t; val () = x0 := x
in
B (x0_val, t1, t2)
end }
implement{a} funarray_loadd
(t, x0) = loadd (t, x0) where {
fun loadd {n:nat} .<n>.
(t: bt (a, n), x0: a):<> bt (a, n+1) = begin
case+ t of
| B (x, tl, tr) => B (x0, loadd (tr, x), tl)
| E () => B (x0, E (), E ())
end }
implement{a} funarray_lorem (t) = lorem (t) where {
fun lorem {n:int | n > 0} .<n>.
(t: bt (a, n)):<> bt (a, n-1) = let
val+ B (_, tl, tr) = t
in
case+ tl of
| B (xl, _, _) => B (xl, tr, lorem tl) | E () => E ()
end }
implement{a} funarray_lorem_get (t, x) = let
val+ B (x0, tl, tr) = t; val () = (x := x0)
in
case+ tl of
| B (xl, _, _) => B (xl, tr, funarray_lorem<a> tl) | E () => E ()
end
implement{a} funarray_hiadd
(t, n, x0) = hiadd (t, n, x0) where {
fun hiadd {n:nat} .<n>.
(t: bt (a, n), n: int n, x0: a):<> bt (a, n+1) =
if n > 0 then let
val+ B (x, tl, tr) = t; val n2 = n / 2
in
if n > n2 + n2 then begin
B (x, hiadd (tl, n2, x0), tr)
end else begin
B (x, tl, hiadd (tr, n2-1, x0))
end
end else begin
B (x0, E (), E ())
end }
implement{a} funarray_hirem
(t, n) = hirem (t, n) where {
fun hirem {n:pos} .<n>.
(t: bt (a, n), n: int n):<> bt (a, n-1) = let
val+ B (x, tl, tr) = t; val n2 = n / 2
in
case+ tl of
| B _ => begin
if n > n2 + n2 then begin
B (x, tl, hirem (tr, n2))
end else begin
B (x, hirem (tl, n2), tr)
end end | E () => E ()
end }
implement{a} funarray_hirem_get
(t, n, x0) = hirem_get (t, n, x0) where {
fun hirem_get {n:pos} .<n>.
(t: bt (a, n), n: int n, x0: &a? >> a):<> bt (a, n-1) = let
val+ B (x, tl, tr) = t; val n2 = n / 2
in
case+ tl of
| B _ => begin
if n > n2 + n2 then begin
B (x, tl, hirem_get (tr, n2, x0))
end else begin
B (x, hirem_get (tl, n2, x0), tr)
end end | E () => (x0 := x; E ())
end
}
implement{a} funarray_foreach_clo {v} {n} (pf | A, n, f) = let
var i: natLte n
in
for* {i:nat | i <= n} .<n-i>. (i: int i) => (i := 0; i < n; i := i+1) f (pf | A[i])
end
implement{a} funarray_foreach_cloref {n} (A, n, f) = let
var i: natLte n
in
for* {i:nat | i <= n} .<n-i>. (i: int i) => (i := 0; i < n; i := i+1) f (A[i])
end
implement{a} funarray_iforeach_clo {v} {n} (pf | A, n, f) = let
var i: natLte n
in
for* {i:nat | i <= n} .<n-i>. (i: int i) => (i := 0; i < n; i := i+1) f (pf | i, A[i])
end
implement{a} funarray_iforeach_cloref {n} (A, n, f) = let
var i: natLte n
in
for* {i:nat | i <= n} .<n-i>. (i: int i) => (i := 0; i < n; i := i+1) f (i, A[i])
end