-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. (--DOC `i_vector' is a primitive implementation of fixed-length immutable indexed collections. Besides the `new_' methods (see the next paragraph on how they work), instances of `i_vector' can be created by Cecil vector constructor expressions, e.g., `[3, 4, 5, x*12]'. `m_vector' is a primitive implementation of fixed-length mutable indexed collections. The `new_(i|m)_vector' function constructs a new `(i|m)_vector' of a given size all of whose elements are filler. The `new_(i|m)_vector_init function' constructs a `(i|m)_vector' of a particular size and uses the elems closure to construct the initial values of the vector's elements from the indices. The `new_(i|m)_vector_init_from' function constructs a `(i|m)_vector' of the same length as some other ordered collection and applies a mapping function to translate each element of the receiver collection into the corresponding vector element; `new_(i|m)_vector_init_from' is simply the well-known map function, specialized to return a particular vector representation. In the current implementation, vectors cannot be subclassed. --) abstract object vector[`T] isa indexed[T]; extend type vector[`T] subtypes vector[`S >= T]; method as_vector(v@:vector[`T]):vector[T] { v } method length(v@:vector[`T]):int { prim rtl: "decl int len := num_elems_int v; decl OOP lenOop := box_int len; return lenOop;" } method fetch(v@:vector[`T], index:int):T { fetch(v, index, { error("index not found in vector") }) } method fetch(v@:vector[`T], index:int, if_absent:&():T):T { prim rtl: "if is_int_log index goto index_OK; fatal \"can only index into vectors with ints\"; label index_OK; decl int i := unbox_int index; decl int len := num_elems_int v; if i <_unsigned_log len goto bounds_OK; decl OOP t5 := send eval(if_absent); return t5; label bounds_OK; decl OOP t6 := v[i] OOP; return t6; " } ---------- -- i_vector is a predefined immutable vector ---------- extend i_vector[`T] isa vector[T], i_indexed[T]; extend type i_vector[`T] subtypes i_vector[`S >= T]; method new_i_vector[T](size@:int, filler:T):i_vector[T] { prim rtl: " decl int len := unbox_int size; if len >_int_log 0 goto OK; return empty_i_vector; label OK; decl OOP v := new_i_vector len; decl int i := 0; label l; v[i] OOP := filler; i := i +_int 1; if i <_int_log len goto l; return v; " } method new_i_vector(size@:int, filler:dynamic):i_vector[dynamic] { new_i_vector[dynamic](size, filler) } method new_i_vector_init[T](size@:int, cl:&(int):T):i_vector[T] { prim rtl: " decl int len := unbox_int size; if len >_int_log 0 goto OK; return empty_i_vector; label OK; decl OOP v := new_i_vector len; decl int i := 0; label l; decl OOP tagged_i := box_int i; decl OOP elem := send eval(cl, tagged_i); v[i] OOP := elem; i := i +_int 1; if i <_int_log len goto l; return v; " } method new_i_vector_init_from[T2](c@:ordered_collection[`T1], cl:&(T1):T2):i_vector[T2] { let s:stream[T1] := view_stream(c); new_i_vector_init[T2](c.length, &(i:int){ eval(cl, s.next) }) } method new_i_vector_init_from[T2](c@:indexed[`T1], cl:&(T1):T2):i_vector[T2] (** inline **) { new_i_vector_init[T2](c.length, &(i:int){ eval(cl, c!i) }) } -- specialization to avoid bounds checks on the source vector method new_i_vector_init_from[T2](c@:vector[`T1], cl:&(T1):T2):i_vector[T2] { prim rtl: " decl int len := num_elems_int c; if len >_int_log 0 goto OK; return empty_i_vector; label OK; decl OOP v := new_i_vector len; decl int i := 0; label l; decl OOP from_elem := c[i] OOP; decl OOP elem := send eval(cl, from_elem); v[i] OOP := elem; i := i +_int 1; if i <_int_log len goto l; return v; " } method as_i_vector(v@:i_vector[`T]):i_vector[T] { v } -- copying behavior is inherited from i_table (returns self) -- printing behavior method collection_name(@:i_vector[`T]):string { "i_vector" } ---------- -- m_vector is a predefined mutable vector ---------- extend m_vector[`T] isa vector[T], m_indexed[T]; -- indexing behavior method store(v@:m_vector[`T], index:int, x:T, if_absent:&():void):void { prim rtl: "if is_int_log index goto index_OK; fatal \"can only index into vectors with ints\"; label index_OK; decl int i := unbox_int index; decl int len := num_elems_int v; if i <_unsigned_log len goto bounds_OK; decl OOP t5 := send eval(if_absent); return void; label bounds_OK; v[i] OOP := x; return void; " } -- m_vector creation behavior method new_m_vector[T](size@:int):m_vector[T] { new_m_vector[T](size, cast[T](not_defined)) } method new_m_vector[T](size@:int, filler:T):m_vector[T] { prim rtl: " decl int len := unbox_int size; if len >=_int_log 0 goto OK; len := 0; label OK; decl OOP v := new_m_vector len; if len =_int_log 0 goto exit; decl int i := 0; label l; v[i] OOP := filler; i := i +_int 1; if i <_int_log len goto l; label exit; return v; " } method new_m_vector(size@:int):m_vector[dynamic] { new_m_vector[dynamic](size) } method new_m_vector(size@:int, filler:dynamic):m_vector[dynamic] { new_m_vector[dynamic](size, filler) } method new_m_vector_init[T](size@:int, cl:&(int):T):m_vector[T] { prim rtl: " decl int len := unbox_int size; if len >=_int_log 0 goto OK; len := 0; label OK; decl OOP v := new_m_vector len; if len =_int_log 0 goto exit; decl int i := 0; label l; decl OOP tagged_i := box_int i; decl OOP elem := send eval(cl, tagged_i); v[i] OOP := elem; i := i +_int 1; if i <_int_log len goto l; label exit; return v; " } method new_m_vector_init_from[T2](c@:ordered_collection[`T1], cl:&(T1):T2):m_vector[T2] { let s:stream[T1] := view_stream(c); new_m_vector_init[T2](c.length, &(i:int){ eval(cl, s.next) }) } method new_m_vector_init_from[T2](c@:indexed[`T1], cl:&(T1):T2):m_vector[T2] (** inline **) { new_m_vector_init[T2](c.length, &(i:int){ eval(cl, c!i) }) } -- specialization to avoid bounds checks on the source vector method new_m_vector_init_from[T2](c@:vector[`T1], cl:&(T1):T2):m_vector[T2] { prim rtl: " decl int len := num_elems_int c; decl OOP v := new_m_vector len; if len =_int_log 0 goto exit; decl int i := 0; label l; decl OOP from_elem := c[i] OOP; decl OOP elem := send eval(cl, from_elem); v[i] OOP := elem; i := i +_int 1; if i <_int_log len goto l; label exit; return v; " } method as_m_vector(v@:m_vector[`T]):m_vector[T] { v } -- copying behavior (-- the old version; may not be as optimized as clone() which uses memcpy method copy(v@:m_vector[`T]):m_vector[T] { new_m_vector_init_from[T](v, &(x:T){ x }) } --) method copy(v@:m_vector[`T]):m_vector[T] (** return_type(m_vector), sends(), formals_escape(f) **) { prim c_++ { #ifdef DISPATCHERS RETURN(v->asMem()->clone()->asOop()); #else BP(v->asMem()->clone()->asOop()); #endif } } -- printing behavior method collection_name(@:m_vector[`T]):string { "m_vector" }