staload "ralist.sats"
macdef P x y = '(,(x), ,(y))
implement{a} ralist_length (xs) = length (xs) where {
fun length {n:nat} .<n>. (xs: ralist (a, n)):<> int n = case+ xs of
| RAnil _ => 0
| RAone _ => 1
| RAevn xs => 2 * ralist_length (xs)
| RAodd (_, ys) => 2 * ralist_length (ys) + 1
}
implement{a} ralist_cons (x0, xs) = cons (x0, xs) where {
fun cons {n:nat} .<n>. (x0: a, xs: ralist (a, n)):<> ralist (a, n+1) =
case+ xs of
| RAnil _ => RAone x0
| RAone x => RAevn (RAone (P x0 x))
| RAevn xxs => RAodd (x0, xxs)
| RAodd (x, xxs) => RAevn (ralist_cons (P x0 x, xxs))
}
implement{a} ralist_head (xs) = head (xs) where {
fun head {n:pos} .<n>. (xs: ralist (a, n)):<> a = case+ xs of
| RAone x => x
| RAevn xxs => begin
let val xx = ralist_head<P a a> xxs in xx.0 end
end | RAodd (x, _) => x
}
implement{a} ralist_uncons (xs, x_r) = uncons (xs, x_r) where {
fun uncons {n:pos} .<n>.
(xs: ralist (a, n), x_r: &a? >> a):<> ralist (a, n-1) =
case+ xs of
| RAone x => (x_r := x; RAnil ())
| RAevn xxs => let
var xx_r: P a a val xxs = ralist_uncons<P a a> (xxs, xx_r)
in
case+ xxs of
| RAnil () => (x_r := xx_r.0; RAone xx_r.1)
| _ =>> (x_r := xx_r.0; RAodd (xx_r.1, xxs))
end | RAodd (x, xxs) => (x_r :=x; RAevn xxs)
}
implement{a} ralist_tail (xs) = tail (xs) where {
fun tail {n:pos} .<n>. (xs: ralist (a, n)):<> ralist (a, n-1) = case+ xs of
| RAone x => RAnil ()
| RAevn xxs => let
var xx: P a a
val xxs = ralist_uncons<P a a> (xxs, xx)
in
case+ xxs of
| RAnil () => RAone xx.1 | _ =>> RAodd (xx.1, xxs)
end | RAodd (_, xxs) => RAevn xxs
}
implement{a} ralist_lookup (xs, i) = lookup<a> (xs, i) where {
fun{a:t@ype} lookup {n,i:nat | i < n} .<n>. (xs: ralist (a, n), i: int i):<> a =
case+ xs of
| RAone x => x
| RAevn xxs => let
val x01 = lookup<P a a> (xxs, nhalf i)
in
if i nmod 2 = 0 then x01.0 else x01.1
end | RAodd (x, xxs) => begin
if i = 0 then x else let
val x01 = lookup<P a a> (xxs, nhalf (i-1))
in
if i nmod 2 = 0 then x01.1 else x01.0
end end }
implement{a} ralist_update(xs, i, x0) = let
typedef id (a:t@ype) = a -<cloref> a
fun{a:t@ype} fupdate {n,i:nat | i < n} .<n>.
(xs: ralist (a, n), i: int i, f: id a):<> ralist (a, n) =
case+ xs of
| RAone x => RAone (f(x))
| RAevn xxs => let
val i2 = i/2
in
if i = i2 + i2 then RAevn (fupdate<P a a> (xxs, i2, lam xx => P (f xx.0) (xx.1)))
else
RAevn (fupdate<P a a> (xxs, i2, lam xx => P (xx.0) (f xx.1)))
end | RAodd (x, xxs) =>
if i = 0 then RAodd (f x, xxs)
else let
val i1 = i - 1; val i2 = i1 / 2
in
if i1 = i2 + i2 then RAodd (x, fupdate<P a a> (xxs, i2, lam xx => P (f xx.0) (xx.1)))
else
RAodd (x, fupdate<P a a> (xxs, i2, lam xx => P (xx.0) (f xx.1)))
end in
fupdate<a> (xs, i, lam _ => x0)
end
fun ralist_gen {n:nat} (n: int n): ralist (int, n) = let
fun loop {i,j:nat | i+j == n}
(i: int i, xs: ralist (int, j)): ralist (int, n) =
if i > 0 then loop (i - 1, ralist_cons (i, xs)) else xs
in
loop (n, RAnil ())
end
fn{a:t@ype} ralist_foreach {n:nat}
(xs: ralist (a, n), f: a -<cloref1> void): void = let
var x: a fun loop {n:nat} {l:addr}
(pf: !a? @ l | xs: ralist (a, n), p: ptr l, f: a -<cloref1> void): void =
case+ xs of
| RAnil () => ()
| _ =>> let
val xs = ralist_uncons<a> (xs, !p); val () = f (!p)
in
loop (pf | xs, p, f)
end
in
loop (view@ x | xs, &x, f)
end
implement main () = let
val xs = ralist_gen (100)
val () = ralist_foreach (xs, lam x => (print x; print_newline ()))
val n = ralist_length<int> (xs)
val () = begin
print "n(100) = "; print n; print_newline ()
end
val x = ralist_lookup<int> (xs, 50)
val () = begin
print "x(51) = "; print x; print_newline ()
end
val xs = ralist_update<int> (xs, 50, ~51)
val x = ralist_lookup<int> (xs, 50)
val () = begin
print "x(-51) = "; print x; print_newline ()
end
in
end