11export class Array < T > {
22
33 private __memory : usize ;
4- private __capacity : i32 ;
5- length : i32 ;
4+ private __capacity : i32 ; // capped to [0, 0x7fffffff]
5+ private __length : i32 ; // capped to [0, __capacity]
6+
7+ private __grow ( newCapacity : i32 ) : void {
8+ assert ( newCapacity > this . __capacity ) ;
9+ var newMemory = allocate_memory ( < usize > newCapacity * sizeof < T > ( ) ) ;
10+ if ( this . __memory ) {
11+ move_memory ( newMemory , this . __memory , this . __capacity * sizeof < T > ( ) ) ;
12+ free_memory ( this . __memory ) ;
13+ }
14+ this . __memory = newMemory ;
15+ this . __capacity = newCapacity ;
16+ }
617
718 constructor ( capacity : i32 = 0 ) {
819 if ( capacity < 0 )
9- throw new RangeError ( "invalid array length" ) ;
10- this . __capacity = this . length = capacity ;
11- this . __memory = capacity > 0 ? allocate_memory ( < usize > capacity * sizeof < T > ( ) ) : 0 ;
20+ throw new RangeError ( "Invalid array length" ) ;
21+ this . __memory = capacity ? allocate_memory ( < usize > capacity * sizeof < T > ( ) ) : 0 ;
22+ this . __capacity = this . __length = capacity ;
23+ }
24+
25+ get length ( ) : i32 {
26+ return this . __length ;
27+ }
28+
29+ set length ( length : i32 ) {
30+ if ( length < 0 )
31+ throw new RangeError ( "Invalid array length" ) ;
32+ if ( length > this . __capacity )
33+ this . __grow ( max ( length , this . __capacity << 1 ) ) ;
34+ this . __length = length ;
1235 }
1336
1437 @operator ( "[]" )
1538 private __get ( index : i32 ) : T {
1639 if ( < u32 > index >= this . __capacity )
17- throw new RangeError ( "index out of range ") ;
40+ throw new Error ( "Index out of bounds ") ; // return changetype<T>(0) ?
1841 return load < T > ( this . __memory + < usize > index * sizeof < T > ( ) ) ;
1942 }
2043
2144 @operator ( "[]=" )
2245 private __set ( index : i32 , value : T ) : void {
23- if ( < u32 > index >= this . __capacity )
24- throw new RangeError ( "index out of range" ) ;
46+ if ( index < 0 )
47+ throw new Error ( "Index out of bounds" ) ;
48+ if ( index >= this . __capacity )
49+ this . __grow ( max ( index + 1 , this . __capacity << 1 ) ) ;
2550 store < T > ( this . __memory + < usize > index * sizeof < T > ( ) , value ) ;
2651 }
2752
2853 indexOf ( searchElement : T , fromIndex : i32 = 0 ) : i32 {
29- if ( < u32 > fromIndex >= this . __capacity )
30- throw new RangeError ( "fromIndex out of range" ) ;
31- for ( var index : usize = < usize > fromIndex , length : usize = min < u32 > ( this . length , this . __capacity ) ; index < length ; ++ index )
32- if ( load < T > ( this . __memory + index * sizeof < T > ( ) ) == searchElement )
33- return index ;
54+ if ( fromIndex < 0 )
55+ fromIndex = this . __length + fromIndex ;
56+ while ( < u32 > fromIndex < this . __length ) {
57+ if ( load < T > ( this . __memory + fromIndex * sizeof < T > ( ) ) == searchElement )
58+ return fromIndex ;
59+ ++ fromIndex ;
60+ }
3461 return - 1 ;
3562 }
3663
37- private __grow ( newCapacity : i32 ) : void {
38- assert ( newCapacity > this . __capacity ) ;
39- var newMemory = allocate_memory ( < usize > newCapacity * sizeof < T > ( ) ) ;
40- if ( this . __memory ) {
41- move_memory ( newMemory , this . __memory , this . __capacity * sizeof < T > ( ) ) ;
42- free_memory ( this . __memory ) ;
64+ lastIndexOf ( searchElement : T , fromIndex : i32 = 0 ) : i32 {
65+ if ( fromIndex < 0 )
66+ fromIndex = this . __length + fromIndex ;
67+ else if ( fromIndex >= this . __length )
68+ fromIndex = this . __length - 1 ;
69+ while ( fromIndex >= 0 ) {
70+ if ( load < T > ( this . __memory + fromIndex * sizeof < T > ( ) ) == searchElement )
71+ return fromIndex ;
72+ -- fromIndex ;
4373 }
44- this . __memory = newMemory ;
45- this . __capacity = newCapacity ;
74+ return - 1 ;
4675 }
4776
4877 push ( element : T ) : i32 {
49- if ( < u32 > this . length > = this . __capacity )
50- this . __grow ( max ( this . length + 1 , this . __capacity << 1 ) ) ;
51- store < T > ( this . __memory + < usize > this . length * sizeof < T > ( ) , element ) ;
52- return ++ this . length ;
78+ if ( this . __length = = this . __capacity )
79+ this . __grow ( this . __capacity ? this . __capacity << 1 : 1 ) ;
80+ store < T > ( this . __memory + this . __length * sizeof < T > ( ) , element ) ;
81+ return ++ this . __length ;
5382 }
5483
5584 pop ( ) : T {
56- if ( this . length < 1 || < u32 > this . length > this . __capacity )
57- throw new RangeError ( "index out of range" ) ;
58- -- this . length ;
59- return load < T > ( this . __memory + < usize > this . length * sizeof < T > ( ) ) ;
85+ if ( this . __length < 1 )
86+ throw new RangeError ( "Array is empty" ) ; // return changetype<T>(0) ?
87+ return load < T > ( this . __memory + -- this . __length * sizeof < T > ( ) ) ;
6088 }
6189
6290 shift ( ) : T {
63- if ( this . length < 1 || < u32 > this . length > this . __capacity )
64- throw new RangeError ( "index out of range " ) ;
91+ if ( this . __length < 1 )
92+ throw new RangeError ( "Array is empty " ) ; // return changetype<T>(0) ?
6593 var element = load < T > ( this . __memory ) ;
6694 move_memory ( this . __memory , this . __memory + sizeof < T > ( ) , ( this . __capacity - 1 ) * sizeof < T > ( ) ) ;
6795 set_memory ( this . __memory + ( this . __capacity - 1 ) * sizeof < T > ( ) , 0 , sizeof < T > ( ) ) ;
68- -- this . length ;
96+ -- this . __length ;
6997 return element ;
7098 }
7199
72100 unshift ( element : T ) : i32 {
73101 var oldCapacity = this . __capacity ;
74- if ( < u32 > this . length > = oldCapacity ) {
75- // inlined `this. __grow(max(this.length + 1, oldCapacity * 2))` (avoids moving twice)
76- var newCapacity = max ( this . length + 1 , oldCapacity * 2 ) ;
102+ if ( this . __length = = oldCapacity ) {
103+ // inlined __grow (avoids moving twice)
104+ var newCapacity : i32 = oldCapacity ? oldCapacity << 1 : 1 ;
77105 assert ( newCapacity > this . __capacity ) ;
78106 var newMemory = allocate_memory ( < usize > newCapacity * sizeof < T > ( ) ) ;
79107 if ( this . __memory ) {
@@ -85,7 +113,53 @@ export class Array<T> {
85113 } else
86114 move_memory ( this . __memory + sizeof < T > ( ) , this . __memory , oldCapacity * sizeof < T > ( ) ) ;
87115 store < T > ( this . __memory , element ) ;
88- return ++ this . length ;
116+ return ++ this . __length ;
117+ }
118+
119+ slice ( begin : i32 = 0 , end : i32 = i32 . MAX_VALUE ) : Array < T > {
120+ if ( begin < 0 ) {
121+ begin = this . __length + begin ;
122+ if ( begin < 0 )
123+ begin = 0 ;
124+ } else if ( begin > this . __length )
125+ begin = this . __length ;
126+ if ( end < 0 )
127+ end = this . __length + end ;
128+ else if ( end > this . __length )
129+ end = this . __length ;
130+ if ( end < begin )
131+ end = begin ;
132+ var capacity = end - begin ;
133+ assert ( capacity >= 0 ) ;
134+ var sliced = new Array < T > ( capacity ) ;
135+ if ( capacity )
136+ move_memory ( sliced . __memory , this . __memory + < usize > begin * sizeof < T > ( ) , < usize > capacity * sizeof < T > ( ) ) ;
137+ return sliced ;
138+ }
139+
140+ splice ( start : i32 , deleteCount : i32 = i32 . MAX_VALUE ) : void {
141+ if ( deleteCount < 1 )
142+ return ;
143+ if ( start < 0 ) {
144+ start = this . __length + start ;
145+ if ( start < 0 )
146+ start = 0 ;
147+ else if ( start >= this . __length )
148+ return ;
149+ } else if ( start >= this . __length )
150+ return ;
151+ deleteCount = min ( deleteCount , this . __length - start ) ;
152+ move_memory ( this . __memory + < usize > start * sizeof < T > ( ) , this . __memory + < usize > ( start + deleteCount ) * sizeof < T > ( ) , deleteCount * sizeof < T > ( ) ) ;
153+ this . __length -= deleteCount ;
154+ }
155+
156+ reverse ( ) : Array < T > {
157+ for ( var front : usize = 0 , back : usize = < usize > this . __length - 1 ; front < back ; ++ front , -- back ) {
158+ var temp = load < T > ( this . __memory + front * sizeof < T > ( ) ) ;
159+ store < T > ( this . __memory + front * sizeof < T > ( ) , load < T > ( this . __memory + back * sizeof < T > ( ) ) ) ;
160+ store < T > ( this . __memory + back * sizeof < T > ( ) , temp ) ;
161+ }
162+ return this ;
89163 }
90164}
91165
@@ -97,14 +171,14 @@ export class CArray<T> {
97171 @operator ( "[]" )
98172 private __get ( index : i32 ) : T {
99173 if ( index < 0 )
100- throw new RangeError ( "index out of range" ) ;
174+ throw new RangeError ( "Index out of range" ) ;
101175 return load < T > ( changetype < usize > ( this ) + < usize > index * sizeof < T > ( ) ) ;
102176 }
103177
104178 @operator ( "[]=" )
105179 private __set ( index : i32 , value : T ) : void {
106180 if ( index < 0 )
107- throw new RangeError ( "index out of range" ) ;
181+ throw new RangeError ( "Index out of range" ) ;
108182 store < T > ( changetype < usize > ( this ) + < usize > index * sizeof < T > ( ) , value ) ;
109183 }
110184}
0 commit comments