Skip to content

Commit 54b02c2

Browse files
MaxGraeydcodeIO
authored andcommitted
Fix functional Array & String methods and avoid buffer caching (AssemblyScript#415)
1 parent df3b2be commit 54b02c2

11 files changed

+928
-931
lines changed

std/assembly/array.ts

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,15 @@ export class Array<T> {
7272
}
7373

7474
every(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
75-
var buffer = this.buffer_;
76-
for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) {
77-
if (!callbackfn(LOAD<T>(buffer, index), index, this)) return false;
75+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
76+
if (!callbackfn(LOAD<T>(this.buffer_, index), index, this)) return false;
7877
}
7978
return true;
8079
}
8180

8281
findIndex(predicate: (element: T, index: i32, array: Array<T>) => bool): i32 {
83-
var buffer = this.buffer_;
84-
for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) {
85-
if (predicate(LOAD<T>(buffer, index), index, this)) return index;
82+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
83+
if (predicate(LOAD<T>(this.buffer_, index), index, this)) return index;
8684
}
8785
return -1;
8886
}
@@ -193,7 +191,7 @@ export class Array<T> {
193191

194192
concat(items: Array<T>): Array<T> {
195193
var thisLen = this.length_;
196-
var otherLen = items === null ? 0 : items.length_;
194+
var otherLen = select(0, items.length_, items === null);
197195
var outLen = thisLen + otherLen;
198196
var out = new Array<T>(outLen);
199197

@@ -250,27 +248,25 @@ export class Array<T> {
250248
}
251249

252250
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void {
253-
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
251+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
254252
callbackfn(LOAD<T>(this.buffer_, index), index, this);
255253
}
256254
}
257255

258256
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U> {
259-
var buffer = this.buffer_;
260257
var length = this.length_;
261258
var result = new Array<U>(length);
262-
var resultBuffer = result.buffer_;
259+
var buffer = result.buffer_;
263260
for (let index = 0; index < min(length, this.length_); ++index) {
264-
STORE<U>(resultBuffer, index, callbackfn(LOAD<T>(buffer, index), index, this));
261+
STORE<U>(buffer, index, callbackfn(LOAD<T>(this.buffer_, index), index, this));
265262
}
266263
return result;
267264
}
268265

269266
filter(callbackfn: (value: T, index: i32, array: Array<T>) => bool): Array<T> {
270-
var buffer = this.buffer_;
271267
var result = new Array<T>();
272-
for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) {
273-
let value = LOAD<T>(buffer, index);
268+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
269+
let value = LOAD<T>(this.buffer_, index);
274270
if (callbackfn(value, index, this)) result.push(value);
275271
}
276272
return result;
@@ -281,9 +277,8 @@ export class Array<T> {
281277
initialValue: U
282278
): U {
283279
var accum = initialValue;
284-
var buffer = this.buffer_;
285-
for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) {
286-
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
280+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
281+
accum = callbackfn(accum, LOAD<T>(this.buffer_, index), index, this);
287282
}
288283
return accum;
289284
}
@@ -293,9 +288,8 @@ export class Array<T> {
293288
initialValue: U
294289
): U {
295290
var accum = initialValue;
296-
var buffer = this.buffer_;
297-
for (let index: i32 = this.length_ - 1; index >= 0; --index) {
298-
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
291+
for (let index = this.length_ - 1; index >= 0; --index) {
292+
accum = callbackfn(accum, LOAD<T>(this.buffer_, index), index, this);
299293
}
300294
return accum;
301295
}
@@ -317,9 +311,8 @@ export class Array<T> {
317311
}
318312

319313
some(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
320-
var buffer = this.buffer_;
321-
for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) {
322-
if (callbackfn(LOAD<T>(buffer, index), index, this)) return true;
314+
for (let index = 0, length = this.length_; index < min(length, this.length_); ++index) {
315+
if (callbackfn(LOAD<T>(this.buffer_, index), index, this)) return true;
323316
}
324317
return false;
325318
}
@@ -348,20 +341,16 @@ export class Array<T> {
348341
}
349342

350343
slice(begin: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
351-
var length = this.length_;
352-
if (begin < 0) begin = max(length + begin, 0);
353-
else if (begin > length) begin = length;
354-
if (end < 0) end = length + end; // no need to clamp
355-
else if (end > length) end = length;
356-
if (end < begin) end = begin; // ^
357-
var newLength = end - begin;
358-
assert(newLength >= 0);
359-
var sliced = new Array<T>(newLength);
360-
if (newLength) {
344+
var len = this.length_;
345+
begin = begin < 0 ? max(begin + len, 0) : min(begin, len);
346+
end = end < 0 ? max(end + len, 0) : min(end, len);
347+
len = end - begin;
348+
var sliced = new Array<T>(len);
349+
if (len) {
361350
memory.copy(
362351
changetype<usize>(sliced.buffer_) + HEADER_SIZE,
363352
changetype<usize>(this.buffer_) + HEADER_SIZE + (<usize>begin << alignof<T>()),
364-
<usize>newLength << alignof<T>()
353+
<usize>len << alignof<T>()
365354
);
366355
}
367356
return sliced;
@@ -430,9 +419,8 @@ export class Array<T> {
430419
var sepLen = separator.length;
431420
var hasSeparator = sepLen != 0;
432421
if (value instanceof bool) {
433-
if (!lastIndex) {
434-
return select<string>("true", "false", LOAD<T,bool>(buffer, 0));
435-
}
422+
if (!lastIndex) return select<string>("true", "false", LOAD<T,bool>(buffer, 0));
423+
436424
let valueLen = 5; // max possible length of element len("false")
437425
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
438426
let result = allocateUnsafeString(estLen);
@@ -459,9 +447,8 @@ export class Array<T> {
459447
}
460448
return out;
461449
} else if (isInteger<T>()) {
462-
if (!lastIndex) {
463-
return changetype<string>(itoa<T>(LOAD<T>(buffer, 0)));
464-
}
450+
if (!lastIndex) return changetype<string>(itoa<T>(LOAD<T>(buffer, 0)));
451+
465452
const valueLen = (sizeof<T>() <= 4 ? 10 : 20) + <i32>isSigned<T>();
466453
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
467454
let result = allocateUnsafeString(estLen);
@@ -483,9 +470,8 @@ export class Array<T> {
483470
}
484471
return out;
485472
} else if (isFloat<T>()) {
486-
if (!lastIndex) {
487-
return changetype<string>(dtoa(LOAD<T,f64>(buffer, 0)));
488-
}
473+
if (!lastIndex) return changetype<string>(dtoa(LOAD<T,f64>(buffer, 0)));
474+
489475
const valueLen = MAX_DOUBLE_LENGTH;
490476
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
491477
let result = allocateUnsafeString(estLen);
@@ -507,9 +493,8 @@ export class Array<T> {
507493
}
508494
return out;
509495
} else if (isString<T>()) {
510-
if (!lastIndex) {
511-
return LOAD<string>(buffer, 0);
512-
}
496+
if (!lastIndex) return LOAD<string>(buffer, 0);
497+
513498
let estLen = 0;
514499
for (let i = 0, len = lastIndex + 1; i < len; ++i) {
515500
estLen += LOAD<string>(buffer, i).length;

std/assembly/string.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,9 @@ export class String {
451451
}
452452
return result;
453453
} else if (!length) {
454-
return <String[]>[changetype<String>("")];
454+
let result = new Array<String>(1);
455+
unchecked(result[0] = changetype<String>(""));
456+
return result;
455457
}
456458
var result = new Array<String>();
457459
var end = 0, start = 0, i = 0;
@@ -467,7 +469,11 @@ export class String {
467469
if (++i == limit) return result;
468470
start = end + sepLen;
469471
}
470-
if (!start) return <String[]>[this];
472+
if (!start) {
473+
let result = new Array<String>(1);
474+
unchecked(result[0] = this);
475+
return result;
476+
}
471477
var len = length - start;
472478
if (len > 0) {
473479
let out = allocateUnsafe(len);

0 commit comments

Comments
 (0)