(***********************************************************************) (* *) (* Applied Type System *) (* *) (* Hongwei Xi *) (* *) (***********************************************************************) (* ** ATS - Unleashing the Potential of Types! ** ** Copyright (C) 2002-2010 Hongwei Xi, Boston University ** ** All rights reserved ** ** ATS is free software; you can redistribute it and/or modify it under ** the terms of the GNU General Public License as published by the Free ** Software Foundation; either version 2.1, or (at your option) any later ** version. ** ** ATS is distributed in the hope that it will be useful, but WITHOUT ANY ** WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ** for more details. ** ** You should have received a copy of the GNU General Public License ** along with ATS; see the file COPYING. If not, write to the Free ** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ** 02110-1301, USA. *) (* ****** ****** *) (* ** ** A dynamically resizable vector implementation ** ** Contributed by Hongwei Xi (hwxi AT cs DOT bu DOT edu) ** Time: Secptember, 2010 ** *) (* ****** ****** *) // // License: LGPL 3.0 (available at http://www.gnu.org/licenses/lgpl.txt) // (* ****** ****** *) #define ATS_DYNLOADFLAG 0 // there is no need for dynloading at run-time (* ****** ****** *) staload "libats/SATS/vector.sats" (* ****** ****** *) implement vector_get_cap {a} (V) = m where { prval pf = VECTOR_decode {a} (V) val m = V.m prval () = VECTOR_encode {a} (pf | V) } // end of[ vector_get_cap] implement vector_get_size {a} (V) = n where { prval pf = VECTOR_decode {a} (V) val n = V.n prval () = VECTOR_encode {a} (pf | V) } // end of[ vector_get_size] (* ****** ****** *) extern prfun vector_v_encode01 {a:viewt@ype} {n:int} {l:addr} (pf: array_v (a?, n, l)): vector_v (a, n, 0, l) // end of [vector_v_encode01] implement{a} vector_initialize {m} (V, m) = let val [l:addr] (pf_gc, pf | p) = array_ptr_alloc (m) prval pf = vector_v_encode01 {a} (pf) prval pf_gc = __cast (pf_gc) where { extern prfun __cast (pf: free_gc_v (a, m, l)): free_gc_v l } // end of [prval] val () = V.m := m val () = V.n := size1_of_int1 (0) val () = V.ptr := p val () = V.vfree := pf_gc prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_initialize] (* ****** ****** *) implement vector_clear {a} {m,n} (V) = let prval pf = VECTOR_decode {a} (V) prval pfmul = mul_istot {n,sizeof a} () prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval pf = array_v_unsplit {a?} (pfmul, pf1, pf2) prval pf = vector_v_encode01 {a} (pf) val () = V.n := (size1_of_int1)0 prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_clear] (* ****** ****** *) implement{a} vector_clear_vt {v} {m,n} (pf | V, f) = let prval () = __assert () where { extern prfun __assert (): [m>=n;n>=0] void } prval pf0 = VECTOR_decode {a} (V) // prval pfmul = mul_istot {n,sizeof a} () prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf0) // val n = V.n val p = V.ptr val () = array_ptr_clear_clo_tsz {a} {v} (pf | !p, n, f, sizeof) // prval pf = array_v_unsplit {a?} (pfmul, pf1, pf2) // prval pf = vector_v_encode01 {a} (pf) // val () = V.n := (size1_of_int1)0 prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_clear_vt] (* ****** ****** *) implement{a} vector_uninitialize {m,n} (V) = let prval pf = VECTOR_decode {a} (V) prval pfmul = mul_istot {n,sizeof a} () prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval pf = array_v_unsplit {a?} (pfmul, pf1, pf2) val () = __free (V.vfree, pf | V.ptr) where { extern fun __free {l:addr} (pf_gc: free_gc_v l, pf: array_v (a?, m, l) | p: ptr l):<> void = "ats_free_gc" // end of [__free] } // end of [val] in // nothing end // end of [vector_unintialize] implement{a} vector_uninitialize_vt {m} (V) = let prval pf = VECTOR_decode {a} (V) prval pfmul = mul_istot {0,sizeof a} () prval () = mul_elim {0,sizeof a} (pfmul) prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval () = array_v_unnil (pf1) val () = __free (V.vfree, pf2 | V.ptr) where { extern fun __free {l:addr} (pf_gc: free_gc_v l, pf: array_v (a?, m, l) | p: ptr l):<> void = "ats_free_gc" // end of [__free] } // end of [val] in // nothing end // end of [vector_unintialize_vt] (* ****** ****** *) implement{a} vector_get_elt_at {m,n} (V, i) = let prval pf = VECTOR_decode {a} (V) val p = V.ptr prval pfmul = mul_istot {n,sizeof a} () prval @(pf1, pf2) = vector_v_decode {a} (pfmul, pf) val x = array_ptr_get_elt_at (!p, i) prval () = pf := vector_v_encode {a} (pfmul, pf1, pf2) prval () = VECTOR_encode {a} (pf | V) in x end // end of [vector_get_elt_at] implement{a} vector_set_elt_at {m,n} (V, i, x) = let prval pf = VECTOR_decode {a} (V) val p = V.ptr prval pfmul = mul_istot {n,sizeof a} () prval @(pf1, pf2) = vector_v_decode {a} (pfmul, pf) val () = array_ptr_set_elt_at (!p, i, x) prval () = pf := vector_v_encode {a} (pfmul, pf1, pf2) prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_get_elt_at] (* ****** ****** *) (* // // HX: this is a bit less efficient // implement{a} vector_append {m,n} (V, x) = let prval () = __assert () where { extern prfun __assert (): [n>=0] void } val n = vector_get_size (V) in vector_insert_at (V, n, x) end // end of [vector_append] *) implement{a} vector_append (V, x) = let prval pf = VECTOR_decode {a} (V) val n = V.n prval () = __assert (n) where { extern prfun __assert {n:int} (_: size_t n): [n>=0] void } // end of [val] val (pfmul | ofs) = mul2_size1_size1 (n, sizeof) prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval (pf21, pf22) = array_v_uncons {a?} (pf2) val p = V.ptr + ofs; val () = !p := x prval pf1 = array_v_extend {a} (pfmul, pf1, pf21) prval pfmul = MULind (pfmul) prval pf = vector_v_encode {a} (pfmul, pf1, pf22) val () = V.n := n + 1 prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_append] (* ****** ****** *) implement{a} vector_prepend {m,n} (V, x) = let prval () = __assert () where { extern prfun __assert (): [n>=0] void } var x: a = x in vector_insert_at (V, 0, x) end // end of [vector_prepend] (* ****** ****** *) implement{a} vector_insert_at {m,n} {i} (V, i, x) = let prval () = __assert () where { extern prfun __assert (): [m>=n;n>=0] void } prval pf = VECTOR_decode {a} (V) // stavar l0:addr val p0 : ptr l0 = V.ptr val [ofs1:int] (pfmul1 | ofs1) = mul2_size1_size1 (i, sizeof) val n = V.n val [ofs:int] (pfmul | ofs) = mul2_size1_size1 (n, sizeof) // prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval (pf11, pf12) = array_v_split {a} {n,i} (pfmul1, pf1) prval (pf21, pf22) = array_v_uncons {a?} (pf2) prval pf3 = array_v_nil {a} {l0+ofs+sizeof a} () // prval pfmul2 = mul_distribute2 (pfmul, mul_negate (pfmul1)) // val (pfr1, pfr2 | ()) = loop (pfmul2, pf12, pf21, pf3 | p0+ofs, n-i) where { fun loop {n1,n2:nat} {l:addr} {ofs:int} .. ( pfmul: MUL (n1, sizeof a, ofs) , pf1: array_v (a, n1, l), pf2: a? @ (l+ofs), pf3: array_v (a, n2, l+ofs+sizeof a) | p1: ptr (l+ofs), n1: size_t n1 ) :<> (a? @ l, array_v (a, n1+n2, l+sizeof a) | void) = if n1 > 0 then let prval (pf11, pf12) = array_v_unextend {a} (pfmul, pf1) prval pfmul = mul_add_const {~1} (pfmul) val p2 = p1 - sizeof; val () = !p1 := !p2 prval pf3 = array_v_cons {a} (pf2, pf3) in loop (pfmul, pf11, pf12, pf3 | p2, n1-1) end else let prval () = mul_elim {0,sizeof a} (pfmul) prval () = array_v_unnil (pf1) in (pf2, pf3 | ()) end // end of [if] // end of [loop] } // end of [val] val p = p0 + ofs1; val () = !p := x prval pf12 = array_v_cons {a} (pfr1, pfr2) prval pf1 = array_v_unsplit {a} (pfmul1, pf11, pf12) prval pfmul = MULind (pfmul) prval pf = vector_v_encode {a} (pfmul, pf1, pf22) // val () = V.n := n + 1 prval () = VECTOR_encode {a} (pf | V) // in // nothing end // end of [vector_insert_at] (* ****** ****** *) implement{a} vector_remove_at {m,n} {i} (V, i, x) = let // stadef tsz = sizeof (a) // prval () = __assert () where { extern prfun __assert (): [m>=n;n>=0] void } prval pf = VECTOR_decode {a} (V) // stavar l0:addr val p0 : ptr l0 = V.ptr val [ofs1:int] (pfmul1 | ofs1) = mul2_size1_size1 (i, sizeof) prval pfmul = mul_istot {n,tsz} () prval pfmul2 = mul_distribute2 (pfmul, mul_negate (pfmul1)) prval pfmul2 = mul_add_const {~1} (pfmul2) // prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf) prval (pf11, pf12) = array_v_split {a} {n,i} (pfmul1, pf1) prval (pf121, pf122) = array_v_uncons {a} (pf12) val p = p0 + ofs1; val () = x := !p // val n = V.n val (pf11, pf12 | ()) = loop ( pfmul1, pfmul2, pf11, pf121, pf122 | p, n-i-1 ) where { fun loop {n1,n2:nat} {ofs1,ofs2:int} .. ( pfmul1: MUL (n1, tsz, ofs1) , pfmul2: MUL (n2, tsz, ofs2) , pf1: array_v (a, n1, l0) , pf21: a? @ (l0+ofs1) , pf22: array_v (a, n2, l0+ofs1+tsz) | p: ptr (l0+ofs1), n2: size_t (n2) ) :<> (array_v (a, n1+n2, l0), a? @ (l0+ofs1+ofs2) | void) = if n2 > 0 then let prval (pf221, pf222) = array_v_uncons {a} (pf22) val p1 = p+sizeof; val () = !p := !p1 prval pf1 = array_v_extend {a} (pfmul1, pf1, pf21) prval pfmul1 = mul_add_const {1} (pfmul1) prval pfmul2 = mul_add_const {~1} (pfmul2) in loop (pfmul1, pfmul2, pf1, pf221, pf222 | p1, n2-1) end else let prval () = array_v_unnil (pf22) prval () = mul_elim {0,tsz} (pfmul2) in (pf1, pf21 | ()) end // end of [if] // end of [loop] } // end of [val] // prval pf2 = array_v_cons {a?} (pf12, pf2) prval MULind (pfmul) = pfmul prval pf = vector_v_encode {a} (pfmul, pf11, pf2) // val () = V.n := n - 1 prval () = VECTOR_encode {a} (pf | V) // in // nothing end // end of [vector_remove_at] (* ****** ****** *) implement{a} vector_resize {m,n} {m1} (V, m1) = let prval pf = VECTOR_decode {a} (V) val p1 = realloc ( V.vfree, pf | V.ptr, m1, sizeof ) where { extern fun realloc {l:addr} {n <= m1} ( pf_gc: !free_gc_v l >> free_gc_v l , pf: !vector_v (a, m, n, l) >> vector_v (a, m1, n, l) | p: ptr l, m1: size_t m1, tsz: sizeof_t a ) :<> #[l:addr] ptr l = "#atslib_vector_realloc" } // end of[ val] val () = V.m := m1 val () = V.ptr := p1 prval () = VECTOR_encode {a} (pf | V) in // nothing end // end of [vector_resize] (* ****** ****** *) implement vector_foreach_fun_tsz__main {a} {v} {vt} {m,n} (pf | V, f, tsz, env) = let prval () = __assert () where { extern praxi __assert (): [m>=n;n>=0] void } // end of [prval] prval pf0 = VECTOR_decode {a} (V) prval pfmul = mul_istot {n,sizeof a} () prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf0) val p = V.ptr val () = array_ptr_foreach_fun_tsz__main (pf | !p, f, V.n, tsz, env) prval pf0 = vector_v_encode {a} (pfmul, pf1, pf2) prval () = VECTOR_encode {a} (pf0 | V) in // nothing end // end of [vector_foreach_fun_tsz__main] (* ****** ****** *) implement{a} vector_foreach_clo {v} {m,n} (pf_v | V, f) = let viewtypedef clo_t = (!v | &a) - void stavar l_f: addr val p_f: ptr l_f = &f viewdef V = @(v, clo_t @ l_f) fn app (pf: !V | x: &a, p_f: !ptr l_f):<> void = let prval (pf1, pf2) = pf; val () = !p_f (pf1 | x) in pf := (pf1, pf2) end // end of [app] prval pf = (pf_v, view@ f) val () = vector_foreach_fun_tsz__main {a} {V} {ptr l_f} (pf | V, app, sizeof, p_f) prval (pf1, pf2) = pf prval () = (pf_v := pf1; view@ f := pf2) in // empty end // end of [vector_foreach_clo] (* ****** ****** *) implement vector_iforeach_fun_tsz__main {a} {v} {vt} {m,n} (pf | V, f, tsz, env) = let prval () = __assert () where { extern praxi __assert (): [m>=n;n>=0] void } // end of [prval] prval pf0 = VECTOR_decode {a} (V) prval pfmul = mul_istot {n,sizeof a} () prval (pf1, pf2) = vector_v_decode {a} (pfmul, pf0) val p = V.ptr val () = array_ptr_iforeach_fun_tsz__main (pf | !p, f, V.n, tsz, env) prval pf0 = vector_v_encode {a} (pfmul, pf1, pf2) prval () = VECTOR_encode {a} (pf0 | V) in // nothing end // end of [vector_iforeach_fun_tsz__main] (* ****** ****** *) implement{a} vector_iforeach_clo {v} {m,n} (pf_v | A, f) = let viewtypedef clo_t = (!v | sizeLt n, &a) - void stavar l_f: addr val p_f: ptr l_f = &f viewdef V = @(v, clo_t @ l_f) fn app (pf: !V | i: sizeLt n, x: &a, p_f: !ptr l_f):<> void = let prval (pf1, pf2) = pf; val () = !p_f (pf1 | i, x) in pf := (pf1, pf2) end // end of [app] prval pf = (pf_v, view@ f) val () = vector_iforeach_fun_tsz__main {a} {V} {ptr l_f} (pf | A, app, sizeof, p_f) prval (pf1, pf2) = pf prval () = (pf_v := pf1; view@ f := pf2) in // empty end // end of [vector_iforeach_clo_tsz] (* ****** ****** *) (* end of [vector.dats] *)